summaryrefslogtreecommitdiffstats
path: root/lib/libc
diff options
context:
space:
mode:
Diffstat (limited to 'lib/libc')
-rw-r--r--lib/libc/Makefile155
-rw-r--r--lib/libc/Versions.def33
-rw-r--r--lib/libc/amd64/Makefile.inc9
-rw-r--r--lib/libc/amd64/SYS.h73
-rw-r--r--lib/libc/amd64/Symbol.map73
-rw-r--r--lib/libc/amd64/_fpmath.h55
-rw-r--r--lib/libc/amd64/arith.h19
-rw-r--r--lib/libc/amd64/gd_qnan.h21
-rw-r--r--lib/libc/amd64/gen/Makefile.inc8
-rw-r--r--lib/libc/amd64/gen/_set_tp.c38
-rw-r--r--lib/libc/amd64/gen/_setjmp.S96
-rw-r--r--lib/libc/amd64/gen/fabs.S46
-rw-r--r--lib/libc/amd64/gen/flt_rounds.c26
-rw-r--r--lib/libc/amd64/gen/fpgetmask.c8
-rw-r--r--lib/libc/amd64/gen/fpgetprec.c8
-rw-r--r--lib/libc/amd64/gen/fpgetround.c8
-rw-r--r--lib/libc/amd64/gen/fpgetsticky.c8
-rw-r--r--lib/libc/amd64/gen/fpsetmask.c8
-rw-r--r--lib/libc/amd64/gen/fpsetprec.c8
-rw-r--r--lib/libc/amd64/gen/fpsetround.c8
-rw-r--r--lib/libc/amd64/gen/getcontextx.c101
-rw-r--r--lib/libc/amd64/gen/infinity.c14
-rw-r--r--lib/libc/amd64/gen/makecontext.c107
-rw-r--r--lib/libc/amd64/gen/rfork_thread.S104
-rw-r--r--lib/libc/amd64/gen/setjmp.S117
-rw-r--r--lib/libc/amd64/gen/signalcontext.c106
-rw-r--r--lib/libc/amd64/gen/sigsetjmp.S118
-rw-r--r--lib/libc/amd64/stdlib/Makefile.inc4
-rw-r--r--lib/libc/amd64/stdlib/div.S20
-rw-r--r--lib/libc/amd64/stdlib/ldiv.S18
-rw-r--r--lib/libc/amd64/stdlib/lldiv.S18
-rw-r--r--lib/libc/amd64/string/Makefile.inc4
-rw-r--r--lib/libc/amd64/string/bcmp.S27
-rw-r--r--lib/libc/amd64/string/bcopy.S99
-rw-r--r--lib/libc/amd64/string/bzero.S46
-rw-r--r--lib/libc/amd64/string/memcmp.S44
-rw-r--r--lib/libc/amd64/string/memcpy.S5
-rw-r--r--lib/libc/amd64/string/memmove.S5
-rw-r--r--lib/libc/amd64/string/memset.S63
-rw-r--r--lib/libc/amd64/string/stpcpy.S116
-rw-r--r--lib/libc/amd64/string/strcat.S168
-rw-r--r--lib/libc/amd64/string/strcmp.S76
-rw-r--r--lib/libc/amd64/string/strcpy.c38
-rw-r--r--lib/libc/amd64/sys/Makefile.inc15
-rw-r--r--lib/libc/amd64/sys/amd64_get_fsbase.c37
-rw-r--r--lib/libc/amd64/sys/amd64_get_gsbase.c37
-rw-r--r--lib/libc/amd64/sys/amd64_set_fsbase.c37
-rw-r--r--lib/libc/amd64/sys/amd64_set_gsbase.c37
-rw-r--r--lib/libc/amd64/sys/brk.S87
-rw-r--r--lib/libc/amd64/sys/cerror.S59
-rw-r--r--lib/libc/amd64/sys/exect.S58
-rw-r--r--lib/libc/amd64/sys/getcontext.S57
-rw-r--r--lib/libc/amd64/sys/pipe.S62
-rw-r--r--lib/libc/amd64/sys/ptrace.S62
-rw-r--r--lib/libc/amd64/sys/reboot.S59
-rw-r--r--lib/libc/amd64/sys/sbrk.S90
-rw-r--r--lib/libc/amd64/sys/setlogin.S67
-rw-r--r--lib/libc/amd64/sys/sigreturn.S48
-rw-r--r--lib/libc/amd64/sys/vfork.S61
-rw-r--r--lib/libc/arm/Makefile.inc10
-rw-r--r--lib/libc/arm/SYS.h74
-rw-r--r--lib/libc/arm/Symbol.map79
-rw-r--r--lib/libc/arm/_fpmath.h67
-rw-r--r--lib/libc/arm/arith.h21
-rw-r--r--lib/libc/arm/gd_qnan.h23
-rw-r--r--lib/libc/arm/gen/Makefile.inc6
-rw-r--r--lib/libc/arm/gen/__aeabi_read_tp.S40
-rw-r--r--lib/libc/arm/gen/_ctx_start.S9
-rw-r--r--lib/libc/arm/gen/_set_tp.c39
-rw-r--r--lib/libc/arm/gen/_setjmp.S110
-rw-r--r--lib/libc/arm/gen/alloca.S45
-rw-r--r--lib/libc/arm/gen/divsi3.S387
-rw-r--r--lib/libc/arm/gen/fabs.c46
-rw-r--r--lib/libc/arm/gen/flt_rounds.c65
-rw-r--r--lib/libc/arm/gen/getcontextx.c69
-rw-r--r--lib/libc/arm/gen/infinity.c26
-rw-r--r--lib/libc/arm/gen/makecontext.c89
-rw-r--r--lib/libc/arm/gen/setjmp.S129
-rw-r--r--lib/libc/arm/gen/signalcontext.c78
-rw-r--r--lib/libc/arm/gen/sigsetjmp.S62
-rw-r--r--lib/libc/arm/softfloat/arm-gcc.h101
-rw-r--r--lib/libc/arm/softfloat/milieu.h49
-rw-r--r--lib/libc/arm/softfloat/softfloat.h315
-rw-r--r--lib/libc/arm/string/Makefile.inc6
-rw-r--r--lib/libc/arm/string/bcopy.S6
-rw-r--r--lib/libc/arm/string/bzero.S37
-rw-r--r--lib/libc/arm/string/ffs.S82
-rw-r--r--lib/libc/arm/string/memcmp.S180
-rw-r--r--lib/libc/arm/string/memcpy.S9
-rw-r--r--lib/libc/arm/string/memcpy_arm.S332
-rw-r--r--lib/libc/arm/string/memcpy_xscale.S1783
-rw-r--r--lib/libc/arm/string/memmove.S582
-rw-r--r--lib/libc/arm/string/memset.S236
-rw-r--r--lib/libc/arm/string/strcmp.S43
-rw-r--r--lib/libc/arm/string/strlen.S78
-rw-r--r--lib/libc/arm/string/strncmp.S54
-rw-r--r--lib/libc/arm/sys/Makefile.inc11
-rw-r--r--lib/libc/arm/sys/Ovfork.S54
-rw-r--r--lib/libc/arm/sys/brk.S100
-rw-r--r--lib/libc/arm/sys/cerror.S48
-rw-r--r--lib/libc/arm/sys/fork.S49
-rw-r--r--lib/libc/arm/sys/pipe.S50
-rw-r--r--lib/libc/arm/sys/ptrace.S48
-rw-r--r--lib/libc/arm/sys/sbrk.S88
-rw-r--r--lib/libc/arm/sys/shmat.S7
-rw-r--r--lib/libc/arm/sys/sigreturn.S42
-rw-r--r--lib/libc/arm/sys/syscall.S38
-rw-r--r--lib/libc/compat-43/Makefile.inc24
-rw-r--r--lib/libc/compat-43/Symbol.map31
-rw-r--r--lib/libc/compat-43/creat.262
-rw-r--r--lib/libc/compat-43/creat.c46
-rw-r--r--lib/libc/compat-43/gethostid.380
-rw-r--r--lib/libc/compat-43/gethostid.c54
-rw-r--r--lib/libc/compat-43/getwd.c51
-rw-r--r--lib/libc/compat-43/killpg.295
-rw-r--r--lib/libc/compat-43/killpg.c51
-rw-r--r--lib/libc/compat-43/sethostid.c49
-rw-r--r--lib/libc/compat-43/setpgrp.c43
-rw-r--r--lib/libc/compat-43/setrgid.c43
-rw-r--r--lib/libc/compat-43/setruid.380
-rw-r--r--lib/libc/compat-43/setruid.c43
-rw-r--r--lib/libc/compat-43/sigcompat.c189
-rw-r--r--lib/libc/compat-43/sigpause.2242
-rw-r--r--lib/libc/compat-43/sigsetmask.2103
-rw-r--r--lib/libc/compat-43/sigvec.2342
-rw-r--r--lib/libc/db/Makefile.inc13
-rw-r--r--lib/libc/db/README34
-rw-r--r--lib/libc/db/Symbol.map36
-rw-r--r--lib/libc/db/btree/Makefile.inc8
-rw-r--r--lib/libc/db/btree/bt_close.c178
-rw-r--r--lib/libc/db/btree/bt_conv.c212
-rw-r--r--lib/libc/db/btree/bt_debug.c316
-rw-r--r--lib/libc/db/btree/bt_delete.c635
-rw-r--r--lib/libc/db/btree/bt_get.c99
-rw-r--r--lib/libc/db/btree/bt_open.c451
-rw-r--r--lib/libc/db/btree/bt_overflow.c216
-rw-r--r--lib/libc/db/btree/bt_page.c94
-rw-r--r--lib/libc/db/btree/bt_put.c314
-rw-r--r--lib/libc/db/btree/bt_search.c200
-rw-r--r--lib/libc/db/btree/bt_seq.c441
-rw-r--r--lib/libc/db/btree/bt_split.c797
-rw-r--r--lib/libc/db/btree/bt_utils.c246
-rw-r--r--lib/libc/db/btree/btree.h380
-rw-r--r--lib/libc/db/btree/extern.h67
-rw-r--r--lib/libc/db/changelog103
-rw-r--r--lib/libc/db/db/Makefile.inc6
-rw-r--r--lib/libc/db/db/db.c94
-rw-r--r--lib/libc/db/docs/hash.usenix.ps12209
-rw-r--r--lib/libc/db/docs/libtp.usenix.ps12340
-rw-r--r--lib/libc/db/hash/Makefile.inc7
-rw-r--r--lib/libc/db/hash/README69
-rw-r--r--lib/libc/db/hash/extern.h62
-rw-r--r--lib/libc/db/hash/hash.c965
-rw-r--r--lib/libc/db/hash/hash.h290
-rw-r--r--lib/libc/db/hash/hash_bigkey.c646
-rw-r--r--lib/libc/db/hash/hash_buf.c358
-rw-r--r--lib/libc/db/hash/hash_func.c190
-rw-r--r--lib/libc/db/hash/hash_log2.c52
-rw-r--r--lib/libc/db/hash/hash_page.c936
-rw-r--r--lib/libc/db/hash/ndbm.c227
-rw-r--r--lib/libc/db/hash/page.h89
-rw-r--r--lib/libc/db/man/Makefile.inc18
-rw-r--r--lib/libc/db/man/btree.3271
-rw-r--r--lib/libc/db/man/dbm.3228
-rw-r--r--lib/libc/db/man/dbopen.3546
-rw-r--r--lib/libc/db/man/hash.3196
-rw-r--r--lib/libc/db/man/mpool.3254
-rw-r--r--lib/libc/db/man/recno.3228
-rw-r--r--lib/libc/db/mpool/Makefile.inc6
-rw-r--r--lib/libc/db/mpool/README7
-rw-r--r--lib/libc/db/mpool/mpool-compat.c43
-rw-r--r--lib/libc/db/mpool/mpool.c493
-rw-r--r--lib/libc/db/mpool/mpool.libtp746
-rw-r--r--lib/libc/db/recno/Makefile.inc7
-rw-r--r--lib/libc/db/recno/extern.h51
-rw-r--r--lib/libc/db/recno/rec_close.c182
-rw-r--r--lib/libc/db/recno/rec_delete.c187
-rw-r--r--lib/libc/db/recno/rec_get.c291
-rw-r--r--lib/libc/db/recno/rec_open.c238
-rw-r--r--lib/libc/db/recno/rec_put.c275
-rw-r--r--lib/libc/db/recno/rec_search.c121
-rw-r--r--lib/libc/db/recno/rec_seq.c127
-rw-r--r--lib/libc/db/recno/rec_utils.c112
-rw-r--r--lib/libc/db/recno/recno.h36
-rw-r--r--lib/libc/db/test/Makefile24
-rw-r--r--lib/libc/db/test/README74
-rw-r--r--lib/libc/db/test/btree.tests/main.c763
-rw-r--r--lib/libc/db/test/dbtest.c738
-rw-r--r--lib/libc/db/test/hash.tests/driver2.c112
-rw-r--r--lib/libc/db/test/hash.tests/makedb.sh13
-rw-r--r--lib/libc/db/test/hash.tests/tcreat3.c103
-rw-r--r--lib/libc/db/test/hash.tests/tdel.c120
-rw-r--r--lib/libc/db/test/hash.tests/testit147
-rw-r--r--lib/libc/db/test/hash.tests/thash4.c130
-rw-r--r--lib/libc/db/test/hash.tests/tread2.c103
-rw-r--r--lib/libc/db/test/hash.tests/tseq.c86
-rw-r--r--lib/libc/db/test/hash.tests/tverify.c105
-rw-r--r--lib/libc/db/test/run.test705
-rw-r--r--lib/libc/gdtoa/Makefile.inc20
-rw-r--r--lib/libc/gdtoa/Symbol.map19
-rw-r--r--lib/libc/gdtoa/_hdtoa.c144
-rw-r--r--lib/libc/gdtoa/_hldtoa.c177
-rw-r--r--lib/libc/gdtoa/_ldtoa.c107
-rw-r--r--lib/libc/gdtoa/glue.c13
-rw-r--r--lib/libc/gdtoa/machdep_ldisQ.c52
-rw-r--r--lib/libc/gdtoa/machdep_ldisd.c49
-rw-r--r--lib/libc/gdtoa/machdep_ldisx.c53
-rw-r--r--lib/libc/gen/Makefile.inc193
-rw-r--r--lib/libc/gen/Symbol.map513
-rw-r--r--lib/libc/gen/__getosreldate.c70
-rw-r--r--lib/libc/gen/__xuname.c146
-rw-r--r--lib/libc/gen/_once_stub.c64
-rw-r--r--lib/libc/gen/_pthread_stubs.c319
-rw-r--r--lib/libc/gen/_rand48.c49
-rw-r--r--lib/libc/gen/_spinlock_stub.c83
-rw-r--r--lib/libc/gen/_thread_init.c44
-rw-r--r--lib/libc/gen/alarm.393
-rw-r--r--lib/libc/gen/alarm.c57
-rw-r--r--lib/libc/gen/arc4random.3127
-rw-r--r--lib/libc/gen/arc4random.c295
-rw-r--r--lib/libc/gen/assert.c56
-rw-r--r--lib/libc/gen/aux.c171
-rw-r--r--lib/libc/gen/basename.3113
-rw-r--r--lib/libc/gen/basename.c79
-rw-r--r--lib/libc/gen/check_utility_compat.389
-rw-r--r--lib/libc/gen/check_utility_compat.c75
-rw-r--r--lib/libc/gen/clock.376
-rw-r--r--lib/libc/gen/clock.c55
-rw-r--r--lib/libc/gen/closedir.c68
-rw-r--r--lib/libc/gen/confstr.3129
-rw-r--r--lib/libc/gen/confstr.c121
-rw-r--r--lib/libc/gen/crypt.c94
-rw-r--r--lib/libc/gen/ctermid.3108
-rw-r--r--lib/libc/gen/ctermid.c70
-rw-r--r--lib/libc/gen/daemon.3112
-rw-r--r--lib/libc/gen/daemon.c95
-rw-r--r--lib/libc/gen/devname.3115
-rw-r--r--lib/libc/gen/devname.c75
-rw-r--r--lib/libc/gen/directory.3247
-rw-r--r--lib/libc/gen/dirname.399
-rw-r--r--lib/libc/gen/dirname.c77
-rw-r--r--lib/libc/gen/disklabel.c159
-rw-r--r--lib/libc/gen/dl_iterate_phdr.3115
-rw-r--r--lib/libc/gen/dladdr.3133
-rw-r--r--lib/libc/gen/dlfcn.c235
-rw-r--r--lib/libc/gen/dlinfo.3282
-rw-r--r--lib/libc/gen/dllockinit.3127
-rw-r--r--lib/libc/gen/dlopen.3408
-rw-r--r--lib/libc/gen/drand48.c25
-rw-r--r--lib/libc/gen/elf_utils.c74
-rw-r--r--lib/libc/gen/erand48.c26
-rw-r--r--lib/libc/gen/err.3243
-rw-r--r--lib/libc/gen/err.c195
-rw-r--r--lib/libc/gen/errlst.c156
-rw-r--r--lib/libc/gen/errno.c30
-rw-r--r--lib/libc/gen/exec.3321
-rw-r--r--lib/libc/gen/exec.c284
-rw-r--r--lib/libc/gen/fdevname.c55
-rw-r--r--lib/libc/gen/feature_present.372
-rw-r--r--lib/libc/gen/feature_present.c62
-rw-r--r--lib/libc/gen/fmtcheck.3108
-rw-r--r--lib/libc/gen/fmtcheck.c325
-rw-r--r--lib/libc/gen/fmtmsg.3260
-rw-r--r--lib/libc/gen/fmtmsg.c220
-rw-r--r--lib/libc/gen/fnmatch.3151
-rw-r--r--lib/libc/gen/fnmatch.c298
-rw-r--r--lib/libc/gen/fpclassify.3133
-rw-r--r--lib/libc/gen/fpclassify.c93
-rw-r--r--lib/libc/gen/frexp.394
-rw-r--r--lib/libc/gen/frexp.c57
-rw-r--r--lib/libc/gen/fstab.c294
-rw-r--r--lib/libc/gen/ftok.383
-rw-r--r--lib/libc/gen/ftok.c46
-rw-r--r--lib/libc/gen/fts-compat.c1242
-rw-r--r--lib/libc/gen/fts-compat.h132
-rw-r--r--lib/libc/gen/fts.3813
-rw-r--r--lib/libc/gen/fts.c1171
-rw-r--r--lib/libc/gen/ftw.3216
-rw-r--r--lib/libc/gen/ftw.c92
-rw-r--r--lib/libc/gen/getbootfile.369
-rw-r--r--lib/libc/gen/getbootfile.c53
-rw-r--r--lib/libc/gen/getbsize.378
-rw-r--r--lib/libc/gen/getbsize.c106
-rw-r--r--lib/libc/gen/getcap.3568
-rw-r--r--lib/libc/gen/getcap.c1055
-rw-r--r--lib/libc/gen/getcontext.3148
-rw-r--r--lib/libc/gen/getcwd.3162
-rw-r--r--lib/libc/gen/getcwd.c230
-rw-r--r--lib/libc/gen/getdiskbyname.363
-rw-r--r--lib/libc/gen/getdomainname.3100
-rw-r--r--lib/libc/gen/getdomainname.c55
-rw-r--r--lib/libc/gen/getfsent.3185
-rw-r--r--lib/libc/gen/getgrent.3287
-rw-r--r--lib/libc/gen/getgrent.c1554
-rw-r--r--lib/libc/gen/getgrouplist.392
-rw-r--r--lib/libc/gen/getgrouplist.c52
-rw-r--r--lib/libc/gen/gethostname.3131
-rw-r--r--lib/libc/gen/gethostname.c57
-rw-r--r--lib/libc/gen/getloadavg.365
-rw-r--r--lib/libc/gen/getloadavg.c69
-rw-r--r--lib/libc/gen/getlogin.c101
-rw-r--r--lib/libc/gen/getmntinfo.3109
-rw-r--r--lib/libc/gen/getmntinfo.c68
-rw-r--r--lib/libc/gen/getnetgrent.3131
-rw-r--r--lib/libc/gen/getnetgrent.c638
-rw-r--r--lib/libc/gen/getosreldate.386
-rw-r--r--lib/libc/gen/getosreldate.c61
-rw-r--r--lib/libc/gen/getpagesize.361
-rw-r--r--lib/libc/gen/getpagesize.c75
-rw-r--r--lib/libc/gen/getpagesizes.399
-rw-r--r--lib/libc/gen/getpagesizes.c85
-rw-r--r--lib/libc/gen/getpass.393
-rw-r--r--lib/libc/gen/getpeereid.3137
-rw-r--r--lib/libc/gen/getpeereid.c54
-rw-r--r--lib/libc/gen/getprogname.394
-rw-r--r--lib/libc/gen/getprogname.c17
-rw-r--r--lib/libc/gen/getpwent.3315
-rw-r--r--lib/libc/gen/getpwent.c2009
-rw-r--r--lib/libc/gen/getttyent.3208
-rw-r--r--lib/libc/gen/getttyent.c257
-rw-r--r--lib/libc/gen/getusershell.399
-rw-r--r--lib/libc/gen/getusershell.c269
-rw-r--r--lib/libc/gen/getutxent.3478
-rw-r--r--lib/libc/gen/getutxent.c235
-rw-r--r--lib/libc/gen/getvfsbyname.3122
-rw-r--r--lib/libc/gen/getvfsbyname.c76
-rw-r--r--lib/libc/gen/glob.3471
-rw-r--r--lib/libc/gen/glob.c918
-rw-r--r--lib/libc/gen/initgroups.393
-rw-r--r--lib/libc/gen/initgroups.c68
-rw-r--r--lib/libc/gen/isatty.c48
-rw-r--r--lib/libc/gen/isgreater.3102
-rw-r--r--lib/libc/gen/isinf.c70
-rw-r--r--lib/libc/gen/isnan.c57
-rw-r--r--lib/libc/gen/jrand48.c24
-rw-r--r--lib/libc/gen/lcong48.c33
-rw-r--r--lib/libc/gen/ldexp.377
-rw-r--r--lib/libc/gen/ldexp.c123
-rw-r--r--lib/libc/gen/libc_dlopen.c61
-rw-r--r--lib/libc/gen/lockf.3266
-rw-r--r--lib/libc/gen/lockf.c79
-rw-r--r--lib/libc/gen/lrand48.c26
-rw-r--r--lib/libc/gen/makecontext.3120
-rw-r--r--lib/libc/gen/modf.381
-rw-r--r--lib/libc/gen/modf.c138
-rw-r--r--lib/libc/gen/mrand48.c26
-rw-r--r--lib/libc/gen/nftw.c117
-rw-r--r--lib/libc/gen/nice.369
-rw-r--r--lib/libc/gen/nice.c56
-rw-r--r--lib/libc/gen/nlist.377
-rw-r--r--lib/libc/gen/nlist.c411
-rw-r--r--lib/libc/gen/nrand48.c24
-rw-r--r--lib/libc/gen/opendir.c314
-rw-r--r--lib/libc/gen/pause.382
-rw-r--r--lib/libc/gen/pause.c54
-rw-r--r--lib/libc/gen/pmadvise.c16
-rw-r--r--lib/libc/gen/popen.3197
-rw-r--r--lib/libc/gen/popen.c206
-rw-r--r--lib/libc/gen/posix_spawn.3460
-rw-r--r--lib/libc/gen/posix_spawn.c475
-rw-r--r--lib/libc/gen/posix_spawn_file_actions_addopen.3182
-rw-r--r--lib/libc/gen/posix_spawn_file_actions_init.3104
-rw-r--r--lib/libc/gen/posix_spawnattr_getflags.3111
-rw-r--r--lib/libc/gen/posix_spawnattr_getpgroup.396
-rw-r--r--lib/libc/gen/posix_spawnattr_getschedparam.3100
-rw-r--r--lib/libc/gen/posix_spawnattr_getschedpolicy.398
-rw-r--r--lib/libc/gen/posix_spawnattr_getsigdefault.398
-rw-r--r--lib/libc/gen/posix_spawnattr_getsigmask.398
-rw-r--r--lib/libc/gen/posix_spawnattr_init.3123
-rw-r--r--lib/libc/gen/psignal.3109
-rw-r--r--lib/libc/gen/psignal.c63
-rw-r--r--lib/libc/gen/pututxline.c331
-rw-r--r--lib/libc/gen/pw_scan.c212
-rw-r--r--lib/libc/gen/pw_scan.h36
-rw-r--r--lib/libc/gen/pwcache.393
-rw-r--r--lib/libc/gen/pwcache.c113
-rw-r--r--lib/libc/gen/raise.373
-rw-r--r--lib/libc/gen/raise.c46
-rw-r--r--lib/libc/gen/rand48.3184
-rw-r--r--lib/libc/gen/rand48.h32
-rw-r--r--lib/libc/gen/readdir.c132
-rw-r--r--lib/libc/gen/readpassphrase.3181
-rw-r--r--lib/libc/gen/readpassphrase.c194
-rw-r--r--lib/libc/gen/rewinddir.c48
-rw-r--r--lib/libc/gen/rfork_thread.387
-rw-r--r--lib/libc/gen/scandir.3106
-rw-r--r--lib/libc/gen/scandir.c145
-rw-r--r--lib/libc/gen/seed48.c39
-rw-r--r--lib/libc/gen/seekdir.c59
-rw-r--r--lib/libc/gen/sem.c464
-rw-r--r--lib/libc/gen/sem_destroy.388
-rw-r--r--lib/libc/gen/sem_getvalue.381
-rw-r--r--lib/libc/gen/sem_init.3102
-rw-r--r--lib/libc/gen/sem_new.c445
-rw-r--r--lib/libc/gen/sem_open.3225
-rw-r--r--lib/libc/gen/sem_post.378
-rw-r--r--lib/libc/gen/sem_timedwait.3120
-rw-r--r--lib/libc/gen/sem_wait.395
-rw-r--r--lib/libc/gen/semctl.c83
-rw-r--r--lib/libc/gen/setdomainname.c51
-rw-r--r--lib/libc/gen/sethostname.c51
-rw-r--r--lib/libc/gen/setjmp.3172
-rw-r--r--lib/libc/gen/setjmperr.c53
-rw-r--r--lib/libc/gen/setmode.3114
-rw-r--r--lib/libc/gen/setmode.c446
-rw-r--r--lib/libc/gen/setproctitle.3121
-rw-r--r--lib/libc/gen/setproctitle.c176
-rw-r--r--lib/libc/gen/setprogname.c19
-rw-r--r--lib/libc/gen/siginterrupt.3119
-rw-r--r--lib/libc/gen/siginterrupt.c63
-rw-r--r--lib/libc/gen/siglist.c107
-rw-r--r--lib/libc/gen/signal.3280
-rw-r--r--lib/libc/gen/signal.c61
-rw-r--r--lib/libc/gen/sigsetops.3117
-rw-r--r--lib/libc/gen/sigsetops.c102
-rw-r--r--lib/libc/gen/sleep.383
-rw-r--r--lib/libc/gen/sleep.c67
-rw-r--r--lib/libc/gen/srand48.c30
-rw-r--r--lib/libc/gen/statvfs.3187
-rw-r--r--lib/libc/gen/statvfs.c160
-rw-r--r--lib/libc/gen/stringlist.3127
-rw-r--r--lib/libc/gen/stringlist.c122
-rw-r--r--lib/libc/gen/strtofflags.395
-rw-r--r--lib/libc/gen/strtofflags.c156
-rw-r--r--lib/libc/gen/swapcontext.c55
-rw-r--r--lib/libc/gen/sysconf.3276
-rw-r--r--lib/libc/gen/sysconf.c617
-rw-r--r--lib/libc/gen/sysctl.3874
-rw-r--r--lib/libc/gen/sysctl.c180
-rw-r--r--lib/libc/gen/sysctlbyname.c31
-rw-r--r--lib/libc/gen/sysctlnametomib.c55
-rw-r--r--lib/libc/gen/syslog.3295
-rw-r--r--lib/libc/gen/syslog.c435
-rw-r--r--lib/libc/gen/tcgetpgrp.378
-rw-r--r--lib/libc/gen/tcgetsid.372
-rw-r--r--lib/libc/gen/tcsendbreak.3153
-rw-r--r--lib/libc/gen/tcsetattr.3340
-rw-r--r--lib/libc/gen/tcsetpgrp.395
-rw-r--r--lib/libc/gen/tcsetsid.392
-rw-r--r--lib/libc/gen/telldir.c129
-rw-r--r--lib/libc/gen/telldir.h66
-rw-r--r--lib/libc/gen/termios.c265
-rw-r--r--lib/libc/gen/time.3101
-rw-r--r--lib/libc/gen/time.c52
-rw-r--r--lib/libc/gen/times.3145
-rw-r--r--lib/libc/gen/times.c67
-rw-r--r--lib/libc/gen/timezone.369
-rw-r--r--lib/libc/gen/timezone.c129
-rw-r--r--lib/libc/gen/tls.c327
-rw-r--r--lib/libc/gen/ttyname.3124
-rw-r--r--lib/libc/gen/ttyname.c110
-rw-r--r--lib/libc/gen/ttyslot.c43
-rw-r--r--lib/libc/gen/tzset.3338
-rw-r--r--lib/libc/gen/ualarm.397
-rw-r--r--lib/libc/gen/ualarm.c63
-rw-r--r--lib/libc/gen/ucontext.3111
-rw-r--r--lib/libc/gen/ulimit.398
-rw-r--r--lib/libc/gen/ulimit.c68
-rw-r--r--lib/libc/gen/uname.3117
-rw-r--r--lib/libc/gen/uname.c47
-rw-r--r--lib/libc/gen/unvis.3200
-rw-r--r--lib/libc/gen/unvis.c293
-rw-r--r--lib/libc/gen/usleep.380
-rw-r--r--lib/libc/gen/usleep.c52
-rw-r--r--lib/libc/gen/utime.392
-rw-r--r--lib/libc/gen/utime.c55
-rw-r--r--lib/libc/gen/utxdb.c179
-rw-r--r--lib/libc/gen/utxdb.h61
-rw-r--r--lib/libc/gen/valloc.375
-rw-r--r--lib/libc/gen/valloc.c48
-rw-r--r--lib/libc/gen/vis.3308
-rw-r--r--lib/libc/gen/vis.c201
-rw-r--r--lib/libc/gen/wait.c50
-rw-r--r--lib/libc/gen/wait3.c50
-rw-r--r--lib/libc/gen/waitpid.c50
-rw-r--r--lib/libc/gen/wordexp.3206
-rw-r--r--lib/libc/gen/wordexp.c354
-rw-r--r--lib/libc/gmon/Makefile.inc17
-rw-r--r--lib/libc/gmon/Symbol.map14
-rw-r--r--lib/libc/gmon/gmon.c250
-rw-r--r--lib/libc/gmon/mcount.c321
-rw-r--r--lib/libc/gmon/moncontrol.3110
-rw-r--r--lib/libc/i386/Makefile.inc6
-rw-r--r--lib/libc/i386/SYS.h59
-rw-r--r--lib/libc/i386/Symbol.map70
-rw-r--r--lib/libc/i386/_fpmath.h54
-rw-r--r--lib/libc/i386/arith.h15
-rw-r--r--lib/libc/i386/gd_qnan.h21
-rw-r--r--lib/libc/i386/gen/Makefile.inc6
-rw-r--r--lib/libc/i386/gen/_ctx_start.S54
-rw-r--r--lib/libc/i386/gen/_set_tp.c40
-rw-r--r--lib/libc/i386/gen/_setjmp.S82
-rw-r--r--lib/libc/i386/gen/fabs.S45
-rw-r--r--lib/libc/i386/gen/flt_rounds.c25
-rw-r--r--lib/libc/i386/gen/getcontextx.c133
-rw-r--r--lib/libc/i386/gen/infinity.c14
-rw-r--r--lib/libc/i386/gen/makecontext.c163
-rw-r--r--lib/libc/i386/gen/rfork_thread.S120
-rw-r--r--lib/libc/i386/gen/setjmp.S116
-rw-r--r--lib/libc/i386/gen/signalcontext.c79
-rw-r--r--lib/libc/i386/gen/sigsetjmp.S128
-rw-r--r--lib/libc/i386/stdlib/Makefile.inc4
-rw-r--r--lib/libc/i386/stdlib/div.S39
-rw-r--r--lib/libc/i386/stdlib/ldiv.S42
-rw-r--r--lib/libc/i386/string/Makefile.inc6
-rw-r--r--lib/libc/i386/string/bcmp.S66
-rw-r--r--lib/libc/i386/string/bcopy.S110
-rw-r--r--lib/libc/i386/string/bzero.S84
-rw-r--r--lib/libc/i386/string/ffs.S56
-rw-r--r--lib/libc/i386/string/memchr.S61
-rw-r--r--lib/libc/i386/string/memcmp.S78
-rw-r--r--lib/libc/i386/string/memcpy.S5
-rw-r--r--lib/libc/i386/string/memmove.S5
-rw-r--r--lib/libc/i386/string/memset.S92
-rw-r--r--lib/libc/i386/string/strcat.S103
-rw-r--r--lib/libc/i386/string/strchr.S68
-rw-r--r--lib/libc/i386/string/strcmp.S122
-rw-r--r--lib/libc/i386/string/strcpy.S92
-rw-r--r--lib/libc/i386/string/strncmp.S169
-rw-r--r--lib/libc/i386/string/strrchr.S69
-rw-r--r--lib/libc/i386/string/swab.S102
-rw-r--r--lib/libc/i386/string/wcschr.S79
-rw-r--r--lib/libc/i386/string/wcscmp.S82
-rw-r--r--lib/libc/i386/string/wcslen.S71
-rw-r--r--lib/libc/i386/string/wmemchr.S108
-rw-r--r--lib/libc/i386/sys/Makefile.inc26
-rw-r--r--lib/libc/i386/sys/Ovfork.S57
-rw-r--r--lib/libc/i386/sys/brk.S90
-rw-r--r--lib/libc/i386/sys/cerror.S66
-rw-r--r--lib/libc/i386/sys/exect.S54
-rw-r--r--lib/libc/i386/sys/getcontext.S53
-rw-r--r--lib/libc/i386/sys/i386_clr_watch.c46
-rw-r--r--lib/libc/i386/sys/i386_get_fsbase.c37
-rw-r--r--lib/libc/i386/sys/i386_get_gsbase.c37
-rw-r--r--lib/libc/i386/sys/i386_get_ioperm.287
-rw-r--r--lib/libc/i386/sys/i386_get_ioperm.c48
-rw-r--r--lib/libc/i386/sys/i386_get_ldt.2139
-rw-r--r--lib/libc/i386/sys/i386_get_ldt.c46
-rw-r--r--lib/libc/i386/sys/i386_set_fsbase.c37
-rw-r--r--lib/libc/i386/sys/i386_set_gsbase.c37
-rw-r--r--lib/libc/i386/sys/i386_set_ioperm.c42
-rw-r--r--lib/libc/i386/sys/i386_set_ldt.c46
-rw-r--r--lib/libc/i386/sys/i386_set_watch.3118
-rw-r--r--lib/libc/i386/sys/i386_set_watch.c84
-rw-r--r--lib/libc/i386/sys/i386_vm86.2141
-rw-r--r--lib/libc/i386/sys/i386_vm86.c41
-rw-r--r--lib/libc/i386/sys/pipe.S49
-rw-r--r--lib/libc/i386/sys/ptrace.S60
-rw-r--r--lib/libc/i386/sys/reboot.S45
-rw-r--r--lib/libc/i386/sys/sbrk.S93
-rw-r--r--lib/libc/i386/sys/setlogin.S57
-rw-r--r--lib/libc/i386/sys/sigreturn.S48
-rw-r--r--lib/libc/i386/sys/syscall.S55
-rw-r--r--lib/libc/ia64/Makefile.inc9
-rw-r--r--lib/libc/ia64/SYS.h63
-rw-r--r--lib/libc/ia64/Symbol.map71
-rw-r--r--lib/libc/ia64/_fpmath.h82
-rw-r--r--lib/libc/ia64/arith.h37
-rw-r--r--lib/libc/ia64/gd_qnan.h21
-rw-r--r--lib/libc/ia64/gen/Makefile.inc11
-rw-r--r--lib/libc/ia64/gen/__divdf3.S142
-rw-r--r--lib/libc/ia64/gen/__divdi3.S143
-rw-r--r--lib/libc/ia64/gen/__divsf3.S116
-rw-r--r--lib/libc/ia64/gen/__divsi3.S125
-rw-r--r--lib/libc/ia64/gen/__moddi3.S160
-rw-r--r--lib/libc/ia64/gen/__modsi3.S132
-rw-r--r--lib/libc/ia64/gen/__udivdi3.S144
-rw-r--r--lib/libc/ia64/gen/__udivsi3.S125
-rw-r--r--lib/libc/ia64/gen/__umoddi3.S156
-rw-r--r--lib/libc/ia64/gen/__umodsi3.S132
-rw-r--r--lib/libc/ia64/gen/_mcount.S75
-rw-r--r--lib/libc/ia64/gen/_set_tp.c34
-rw-r--r--lib/libc/ia64/gen/_setjmp.S310
-rw-r--r--lib/libc/ia64/gen/fabs.S33
-rw-r--r--lib/libc/ia64/gen/flt_rounds.c25
-rw-r--r--lib/libc/ia64/gen/fpgetmask.c40
-rw-r--r--lib/libc/ia64/gen/fpgetround.c39
-rw-r--r--lib/libc/ia64/gen/fpsetmask.c44
-rw-r--r--lib/libc/ia64/gen/fpsetround.c43
-rw-r--r--lib/libc/ia64/gen/getcontextx.c69
-rw-r--r--lib/libc/ia64/gen/infinity.c48
-rw-r--r--lib/libc/ia64/gen/makecontext.c123
-rw-r--r--lib/libc/ia64/gen/setjmp.S82
-rw-r--r--lib/libc/ia64/gen/signalcontext.c123
-rw-r--r--lib/libc/ia64/gen/sigsetjmp.S66
-rw-r--r--lib/libc/ia64/gen/unwind.c129
-rw-r--r--lib/libc/ia64/string/Makefile.inc3
-rw-r--r--lib/libc/ia64/string/bcopy.S95
-rw-r--r--lib/libc/ia64/string/bzero.S81
-rw-r--r--lib/libc/ia64/string/ffs.S99
-rw-r--r--lib/libc/ia64/string/memcpy.S36
-rw-r--r--lib/libc/ia64/string/memmove.S36
-rw-r--r--lib/libc/ia64/sys/Makefile.inc12
-rw-r--r--lib/libc/ia64/sys/Ovfork.S37
-rw-r--r--lib/libc/ia64/sys/brk.S57
-rw-r--r--lib/libc/ia64/sys/cerror.S46
-rw-r--r--lib/libc/ia64/sys/exect.S38
-rw-r--r--lib/libc/ia64/sys/fork.S37
-rw-r--r--lib/libc/ia64/sys/getcontext.S39
-rw-r--r--lib/libc/ia64/sys/pipe.S47
-rw-r--r--lib/libc/ia64/sys/ptrace.S41
-rw-r--r--lib/libc/ia64/sys/sbrk.S63
-rw-r--r--lib/libc/ia64/sys/setlogin.S42
-rw-r--r--lib/libc/ia64/sys/sigreturn.S41
-rw-r--r--lib/libc/ia64/sys/swapcontext.S39
-rw-r--r--lib/libc/iconv/Makefile.inc18
-rw-r--r--lib/libc/iconv/Symbol.map104
-rw-r--r--lib/libc/iconv/__iconv_get_list.395
-rw-r--r--lib/libc/iconv/_strtol.h167
-rw-r--r--lib/libc/iconv/_strtoul.h126
-rw-r--r--lib/libc/iconv/citrus_aliasname_local.h49
-rw-r--r--lib/libc/iconv/citrus_bcs.c168
-rw-r--r--lib/libc/iconv/citrus_bcs.h102
-rw-r--r--lib/libc/iconv/citrus_bcs_strtol.c57
-rw-r--r--lib/libc/iconv/citrus_bcs_strtoul.c57
-rw-r--r--lib/libc/iconv/citrus_csmapper.c383
-rw-r--r--lib/libc/iconv/citrus_csmapper.h48
-rw-r--r--lib/libc/iconv/citrus_db.c331
-rw-r--r--lib/libc/iconv/citrus_db.h70
-rw-r--r--lib/libc/iconv/citrus_db_factory.c348
-rw-r--r--lib/libc/iconv/citrus_db_factory.h57
-rw-r--r--lib/libc/iconv/citrus_db_file.h85
-rw-r--r--lib/libc/iconv/citrus_db_hash.c64
-rw-r--r--lib/libc/iconv/citrus_db_hash.h37
-rw-r--r--lib/libc/iconv/citrus_esdb.c374
-rw-r--r--lib/libc/iconv/citrus_esdb.h58
-rw-r--r--lib/libc/iconv/citrus_esdb_file.h45
-rw-r--r--lib/libc/iconv/citrus_fix_grouping.h53
-rw-r--r--lib/libc/iconv/citrus_hash.c51
-rw-r--r--lib/libc/iconv/citrus_hash.h59
-rw-r--r--lib/libc/iconv/citrus_iconv.c335
-rw-r--r--lib/libc/iconv/citrus_iconv.h64
-rw-r--r--lib/libc/iconv/citrus_iconv_local.h107
-rw-r--r--lib/libc/iconv/citrus_lock.h35
-rw-r--r--lib/libc/iconv/citrus_lookup.c362
-rw-r--r--lib/libc/iconv/citrus_lookup.h64
-rw-r--r--lib/libc/iconv/citrus_lookup_factory.c121
-rw-r--r--lib/libc/iconv/citrus_lookup_factory.h37
-rw-r--r--lib/libc/iconv/citrus_lookup_file.h35
-rw-r--r--lib/libc/iconv/citrus_mapper.c399
-rw-r--r--lib/libc/iconv/citrus_mapper.h131
-rw-r--r--lib/libc/iconv/citrus_mapper_local.h96
-rw-r--r--lib/libc/iconv/citrus_memstream.c148
-rw-r--r--lib/libc/iconv/citrus_memstream.h226
-rw-r--r--lib/libc/iconv/citrus_mmap.c97
-rw-r--r--lib/libc/iconv/citrus_mmap.h40
-rw-r--r--lib/libc/iconv/citrus_module.c315
-rw-r--r--lib/libc/iconv/citrus_module.h54
-rw-r--r--lib/libc/iconv/citrus_namespace.h241
-rw-r--r--lib/libc/iconv/citrus_none.c237
-rw-r--r--lib/libc/iconv/citrus_none.h36
-rw-r--r--lib/libc/iconv/citrus_pivot_factory.c225
-rw-r--r--lib/libc/iconv/citrus_pivot_factory.h37
-rw-r--r--lib/libc/iconv/citrus_pivot_file.h36
-rw-r--r--lib/libc/iconv/citrus_prop.c444
-rw-r--r--lib/libc/iconv/citrus_prop.h92
-rw-r--r--lib/libc/iconv/citrus_region.h113
-rw-r--r--lib/libc/iconv/citrus_stdenc.c145
-rw-r--r--lib/libc/iconv/citrus_stdenc.h124
-rw-r--r--lib/libc/iconv/citrus_stdenc_local.h161
-rw-r--r--lib/libc/iconv/citrus_stdenc_template.h211
-rw-r--r--lib/libc/iconv/citrus_types.h40
-rw-r--r--lib/libc/iconv/iconv.3305
-rw-r--r--lib/libc/iconv/iconv.c332
-rw-r--r--lib/libc/iconv/iconv_canonicalize.374
-rw-r--r--lib/libc/iconv/iconvctl.3164
-rw-r--r--lib/libc/iconv/iconvlist.393
-rw-r--r--lib/libc/include/compat.h48
-rw-r--r--lib/libc/include/fpmath.h75
-rw-r--r--lib/libc/include/isc/eventlib.h206
-rw-r--r--lib/libc/include/isc/list.h124
-rw-r--r--lib/libc/include/isc/platform.h37
-rw-r--r--lib/libc/include/libc_private.h259
-rw-r--r--lib/libc/include/namespace.h265
-rw-r--r--lib/libc/include/nscache.h197
-rw-r--r--lib/libc/include/nscachedcli.h107
-rw-r--r--lib/libc/include/nss_tls.h80
-rw-r--r--lib/libc/include/port_after.h11
-rw-r--r--lib/libc/include/port_before.h22
-rw-r--r--lib/libc/include/reentrant.h128
-rw-r--r--lib/libc/include/resolv_mt.h47
-rw-r--r--lib/libc/include/spinlock.h70
-rw-r--r--lib/libc/include/un-namespace.h255
-rw-r--r--lib/libc/inet/Makefile.inc11
-rw-r--r--lib/libc/inet/Symbol.map38
-rw-r--r--lib/libc/inet/inet_addr.c215
-rw-r--r--lib/libc/inet/inet_cidr_ntop.c263
-rw-r--r--lib/libc/inet/inet_cidr_pton.c279
-rw-r--r--lib/libc/inet/inet_lnaof.c70
-rw-r--r--lib/libc/inet/inet_makeaddr.c73
-rw-r--r--lib/libc/inet/inet_net_ntop.c288
-rw-r--r--lib/libc/inet/inet_net_pton.c416
-rw-r--r--lib/libc/inet/inet_neta.c98
-rw-r--r--lib/libc/inet/inet_netof.c69
-rw-r--r--lib/libc/inet/inet_network.c111
-rw-r--r--lib/libc/inet/inet_ntoa.c78
-rw-r--r--lib/libc/inet/inet_ntop.c203
-rw-r--r--lib/libc/inet/inet_pton.c225
-rw-r--r--lib/libc/inet/nsap_addr.c122
-rw-r--r--lib/libc/isc/Makefile.inc6
-rw-r--r--lib/libc/isc/ev_streams.c318
-rw-r--r--lib/libc/isc/ev_timers.c515
-rw-r--r--lib/libc/isc/eventlib_p.h290
-rw-r--r--lib/libc/locale/DESIGN.xlocale159
-rw-r--r--lib/libc/locale/Makefile.inc63
-rw-r--r--lib/libc/locale/Symbol.map209
-rw-r--r--lib/libc/locale/ascii.c192
-rw-r--r--lib/libc/locale/big5.551
-rw-r--r--lib/libc/locale/big5.c180
-rw-r--r--lib/libc/locale/btowc.388
-rw-r--r--lib/libc/locale/btowc.c64
-rw-r--r--lib/libc/locale/collate.c343
-rw-r--r--lib/libc/locale/collate.h81
-rw-r--r--lib/libc/locale/collcmp.c52
-rw-r--r--lib/libc/locale/ctype.3151
-rw-r--r--lib/libc/locale/ctype.c33
-rw-r--r--lib/libc/locale/ctype_l.3138
-rw-r--r--lib/libc/locale/digittoint.368
-rw-r--r--lib/libc/locale/duplocale.379
-rw-r--r--lib/libc/locale/euc.5134
-rw-r--r--lib/libc/locale/euc.c273
-rw-r--r--lib/libc/locale/fix_grouping.c86
-rw-r--r--lib/libc/locale/freelocale.361
-rw-r--r--lib/libc/locale/gb18030.578
-rw-r--r--lib/libc/locale/gb18030.c224
-rw-r--r--lib/libc/locale/gb2312.557
-rw-r--r--lib/libc/locale/gb2312.c160
-rw-r--r--lib/libc/locale/gbk.563
-rw-r--r--lib/libc/locale/gbk.c173
-rw-r--r--lib/libc/locale/isalnum.3115
-rw-r--r--lib/libc/locale/isalpha.3113
-rw-r--r--lib/libc/locale/isascii.353
-rw-r--r--lib/libc/locale/isblank.396
-rw-r--r--lib/libc/locale/iscntrl.3103
-rw-r--r--lib/libc/locale/isctype.c229
-rw-r--r--lib/libc/locale/isdigit.3113
-rw-r--r--lib/libc/locale/isgraph.3105
-rw-r--r--lib/libc/locale/isideogram.357
-rw-r--r--lib/libc/locale/islower.390
-rw-r--r--lib/libc/locale/isphonogram.357
-rw-r--r--lib/libc/locale/isprint.3103
-rw-r--r--lib/libc/locale/ispunct.395
-rw-r--r--lib/libc/locale/isrune.363
-rw-r--r--lib/libc/locale/isspace.387
-rw-r--r--lib/libc/locale/isspecial.356
-rw-r--r--lib/libc/locale/isupper.390
-rw-r--r--lib/libc/locale/iswalnum.3158
-rw-r--r--lib/libc/locale/iswctype.c210
-rw-r--r--lib/libc/locale/isxdigit.3101
-rw-r--r--lib/libc/locale/ldpart.c166
-rw-r--r--lib/libc/locale/ldpart.h39
-rw-r--r--lib/libc/locale/lmessages.c126
-rw-r--r--lib/libc/locale/lmessages.h49
-rw-r--r--lib/libc/locale/lmonetary.c225
-rw-r--r--lib/libc/locale/lmonetary.h70
-rw-r--r--lib/libc/locale/lnumeric.c127
-rw-r--r--lib/libc/locale/lnumeric.h52
-rw-r--r--lib/libc/locale/localeconv.3237
-rw-r--r--lib/libc/locale/localeconv.c117
-rw-r--r--lib/libc/locale/mblen.3106
-rw-r--r--lib/libc/locale/mblen.c61
-rw-r--r--lib/libc/locale/mblocal.h79
-rw-r--r--lib/libc/locale/mbrlen.3145
-rw-r--r--lib/libc/locale/mbrlen.c51
-rw-r--r--lib/libc/locale/mbrtowc.3139
-rw-r--r--lib/libc/locale/mbrtowc.c53
-rw-r--r--lib/libc/locale/mbsinit.367
-rw-r--r--lib/libc/locale/mbsinit.c48
-rw-r--r--lib/libc/locale/mbsnrtowcs.c102
-rw-r--r--lib/libc/locale/mbsrtowcs.3135
-rw-r--r--lib/libc/locale/mbsrtowcs.c55
-rw-r--r--lib/libc/locale/mbstowcs.387
-rw-r--r--lib/libc/locale/mbstowcs.c56
-rw-r--r--lib/libc/locale/mbtowc.3114
-rw-r--r--lib/libc/locale/mbtowc.c60
-rw-r--r--lib/libc/locale/mskanji.570
-rw-r--r--lib/libc/locale/mskanji.c165
-rw-r--r--lib/libc/locale/multibyte.3142
-rw-r--r--lib/libc/locale/newlocale.3112
-rw-r--r--lib/libc/locale/nextwctype.367
-rw-r--r--lib/libc/locale/nextwctype.c103
-rw-r--r--lib/libc/locale/nl_langinfo.390
-rw-r--r--lib/libc/locale/nl_langinfo.c193
-rw-r--r--lib/libc/locale/nomacros.c18
-rw-r--r--lib/libc/locale/none.c222
-rw-r--r--lib/libc/locale/querylocale.357
-rw-r--r--lib/libc/locale/rpmatch.366
-rw-r--r--lib/libc/locale/rpmatch.c55
-rw-r--r--lib/libc/locale/rune.c286
-rw-r--r--lib/libc/locale/runefile.h61
-rw-r--r--lib/libc/locale/runetype.c89
-rw-r--r--lib/libc/locale/setlocale.3173
-rw-r--r--lib/libc/locale/setlocale.c333
-rw-r--r--lib/libc/locale/setlocale.h40
-rw-r--r--lib/libc/locale/setrunelocale.c210
-rw-r--r--lib/libc/locale/table.c263
-rw-r--r--lib/libc/locale/toascii.369
-rw-r--r--lib/libc/locale/tolower.379
-rw-r--r--lib/libc/locale/tolower.c79
-rw-r--r--lib/libc/locale/toupper.379
-rw-r--r--lib/libc/locale/toupper.c81
-rw-r--r--lib/libc/locale/towlower.366
-rw-r--r--lib/libc/locale/towupper.366
-rw-r--r--lib/libc/locale/uselocale.360
-rw-r--r--lib/libc/locale/utf8.5102
-rw-r--r--lib/libc/locale/utf8.c434
-rw-r--r--lib/libc/locale/wcrtomb.3105
-rw-r--r--lib/libc/locale/wcrtomb.c52
-rw-r--r--lib/libc/locale/wcsftime.366
-rw-r--r--lib/libc/locale/wcsftime.c122
-rw-r--r--lib/libc/locale/wcsnrtombs.c123
-rw-r--r--lib/libc/locale/wcsrtombs.3134
-rw-r--r--lib/libc/locale/wcsrtombs.c56
-rw-r--r--lib/libc/locale/wcstod.373
-rw-r--r--lib/libc/locale/wcstod.c113
-rw-r--r--lib/libc/locale/wcstof.c83
-rw-r--r--lib/libc/locale/wcstoimax.c137
-rw-r--r--lib/libc/locale/wcstol.394
-rw-r--r--lib/libc/locale/wcstol.c130
-rw-r--r--lib/libc/locale/wcstold.c90
-rw-r--r--lib/libc/locale/wcstoll.c136
-rw-r--r--lib/libc/locale/wcstombs.390
-rw-r--r--lib/libc/locale/wcstombs.c58
-rw-r--r--lib/libc/locale/wcstoul.c128
-rw-r--r--lib/libc/locale/wcstoull.c135
-rw-r--r--lib/libc/locale/wcstoumax.c135
-rw-r--r--lib/libc/locale/wctob.c56
-rw-r--r--lib/libc/locale/wctomb.3108
-rw-r--r--lib/libc/locale/wctomb.c59
-rw-r--r--lib/libc/locale/wctrans.3122
-rw-r--r--lib/libc/locale/wctrans.c101
-rw-r--r--lib/libc/locale/wctype.3119
-rw-r--r--lib/libc/locale/wctype.c113
-rw-r--r--lib/libc/locale/wcwidth.387
-rw-r--r--lib/libc/locale/wcwidth.c61
-rw-r--r--lib/libc/locale/xlocale.3280
-rw-r--r--lib/libc/locale/xlocale.c371
-rw-r--r--lib/libc/locale/xlocale_private.h224
-rw-r--r--lib/libc/mips/Makefile.inc7
-rw-r--r--lib/libc/mips/SYS.h137
-rw-r--r--lib/libc/mips/Symbol.map77
-rw-r--r--lib/libc/mips/_fpmath.h56
-rw-r--r--lib/libc/mips/arith.h29
-rw-r--r--lib/libc/mips/gd_qnan.h48
-rw-r--r--lib/libc/mips/gdtoa/Makefile.inc4
-rw-r--r--lib/libc/mips/gdtoa/arith.h10
-rw-r--r--lib/libc/mips/gen/Makefile.inc10
-rw-r--r--lib/libc/mips/gen/_ctx_start.S41
-rw-r--r--lib/libc/mips/gen/_set_tp.c39
-rw-r--r--lib/libc/mips/gen/_setjmp.S126
-rw-r--r--lib/libc/mips/gen/fabs.S58
-rw-r--r--lib/libc/mips/gen/fabs.c46
-rw-r--r--lib/libc/mips/gen/flt_rounds.c30
-rw-r--r--lib/libc/mips/gen/getcontextx.c69
-rw-r--r--lib/libc/mips/gen/hardfloat/fpgetmask.c29
-rw-r--r--lib/libc/mips/gen/hardfloat/fpgetround.c29
-rw-r--r--lib/libc/mips/gen/hardfloat/fpgetsticky.c29
-rw-r--r--lib/libc/mips/gen/hardfloat/fpsetmask.c38
-rw-r--r--lib/libc/mips/gen/hardfloat/fpsetround.c37
-rw-r--r--lib/libc/mips/gen/hardfloat/fpsetsticky.c38
-rw-r--r--lib/libc/mips/gen/infinity.c26
-rw-r--r--lib/libc/mips/gen/ldexp.S219
-rw-r--r--lib/libc/mips/gen/longjmp.c110
-rw-r--r--lib/libc/mips/gen/makecontext.c123
-rw-r--r--lib/libc/mips/gen/setjmp.S164
-rw-r--r--lib/libc/mips/gen/signalcontext.c53
-rw-r--r--lib/libc/mips/gen/sigsetjmp.S77
-rw-r--r--lib/libc/mips/net/Makefile.inc4
-rw-r--r--lib/libc/mips/net/htonl.S58
-rw-r--r--lib/libc/mips/net/htons.S54
-rw-r--r--lib/libc/mips/net/ntohl.S58
-rw-r--r--lib/libc/mips/net/ntohs.S53
-rw-r--r--lib/libc/mips/softfloat/milieu.h48
-rw-r--r--lib/libc/mips/softfloat/mips-gcc.h91
-rw-r--r--lib/libc/mips/softfloat/softfloat.h315
-rw-r--r--lib/libc/mips/string/Makefile.inc8
-rw-r--r--lib/libc/mips/string/bcmp.S130
-rw-r--r--lib/libc/mips/string/bcopy.S297
-rw-r--r--lib/libc/mips/string/bzero.S83
-rw-r--r--lib/libc/mips/string/ffs.S59
-rw-r--r--lib/libc/mips/string/memcpy.S7
-rw-r--r--lib/libc/mips/string/memmove.S7
-rw-r--r--lib/libc/mips/string/strchr.S61
-rw-r--r--lib/libc/mips/string/strcmp.S68
-rw-r--r--lib/libc/mips/string/strlen.S55
-rw-r--r--lib/libc/mips/string/strrchr.S59
-rw-r--r--lib/libc/mips/sys/Makefile.inc13
-rw-r--r--lib/libc/mips/sys/Ovfork.S64
-rw-r--r--lib/libc/mips/sys/brk.S71
-rw-r--r--lib/libc/mips/sys/cerror.S72
-rw-r--r--lib/libc/mips/sys/exect.S51
-rw-r--r--lib/libc/mips/sys/fork.S57
-rw-r--r--lib/libc/mips/sys/pipe.S57
-rw-r--r--lib/libc/mips/sys/ptrace.S71
-rw-r--r--lib/libc/mips/sys/sbrk.S73
-rw-r--r--lib/libc/mips/sys/shmat.S7
-rw-r--r--lib/libc/mips/sys/syscall.S44
-rw-r--r--lib/libc/nameser/Makefile.inc8
-rw-r--r--lib/libc/nameser/Symbol.map31
-rw-r--r--lib/libc/nameser/ns_name.c973
-rw-r--r--lib/libc/nameser/ns_netint.c58
-rw-r--r--lib/libc/nameser/ns_parse.c211
-rw-r--r--lib/libc/nameser/ns_print.c908
-rw-r--r--lib/libc/nameser/ns_samedomain.c211
-rw-r--r--lib/libc/nameser/ns_ttl.c162
-rw-r--r--lib/libc/net/Makefile.inc129
-rw-r--r--lib/libc/net/Symbol.map168
-rw-r--r--lib/libc/net/base64.c315
-rw-r--r--lib/libc/net/byteorder.386
-rw-r--r--lib/libc/net/ether_addr.c230
-rw-r--r--lib/libc/net/ethers.3233
-rw-r--r--lib/libc/net/eui64.3223
-rw-r--r--lib/libc/net/eui64.c311
-rw-r--r--lib/libc/net/gai_strerror.392
-rw-r--r--lib/libc/net/gai_strerror.c119
-rw-r--r--lib/libc/net/getaddrinfo.3461
-rw-r--r--lib/libc/net/getaddrinfo.c2847
-rw-r--r--lib/libc/net/gethostbydns.c779
-rw-r--r--lib/libc/net/gethostbyht.c339
-rw-r--r--lib/libc/net/gethostbyname.3375
-rw-r--r--lib/libc/net/gethostbynis.c352
-rw-r--r--lib/libc/net/gethostnamadr.c734
-rw-r--r--lib/libc/net/getifaddrs.3167
-rw-r--r--lib/libc/net/getifaddrs.c343
-rw-r--r--lib/libc/net/getifmaddrs.3116
-rw-r--r--lib/libc/net/getifmaddrs.c203
-rw-r--r--lib/libc/net/getipnodebyname.3474
-rw-r--r--lib/libc/net/getnameinfo.3285
-rw-r--r--lib/libc/net/getnameinfo.c464
-rw-r--r--lib/libc/net/getnetbydns.c465
-rw-r--r--lib/libc/net/getnetbyht.c288
-rw-r--r--lib/libc/net/getnetbynis.c259
-rw-r--r--lib/libc/net/getnetent.3171
-rw-r--r--lib/libc/net/getnetnamadr.c458
-rw-r--r--lib/libc/net/getproto.c143
-rw-r--r--lib/libc/net/getprotoent.3145
-rw-r--r--lib/libc/net/getprotoent.c554
-rw-r--r--lib/libc/net/getprotoname.c151
-rw-r--r--lib/libc/net/getservent.3155
-rw-r--r--lib/libc/net/getservent.c1373
-rw-r--r--lib/libc/net/hesiod.3176
-rw-r--r--lib/libc/net/hesiod.c584
-rw-r--r--lib/libc/net/if_indextoname.3152
-rw-r--r--lib/libc/net/if_indextoname.c88
-rw-r--r--lib/libc/net/if_nameindex.c147
-rw-r--r--lib/libc/net/if_nametoindex.c102
-rw-r--r--lib/libc/net/inet.3305
-rw-r--r--lib/libc/net/inet6_opt_init.3337
-rw-r--r--lib/libc/net/inet6_option_space.354
-rw-r--r--lib/libc/net/inet6_rth_space.3225
-rw-r--r--lib/libc/net/inet6_rthdr_space.357
-rw-r--r--lib/libc/net/inet_net.3162
-rw-r--r--lib/libc/net/ip6opt.c593
-rw-r--r--lib/libc/net/linkaddr.3134
-rw-r--r--lib/libc/net/linkaddr.c156
-rw-r--r--lib/libc/net/map_v4v6.c119
-rw-r--r--lib/libc/net/name6.c1111
-rw-r--r--lib/libc/net/netdb_private.h145
-rw-r--r--lib/libc/net/nscache.c438
-rw-r--r--lib/libc/net/nscachedcli.c576
-rw-r--r--lib/libc/net/nsdispatch.3258
-rw-r--r--lib/libc/net/nsdispatch.c766
-rw-r--r--lib/libc/net/nslexer.l120
-rw-r--r--lib/libc/net/nsparser.y184
-rw-r--r--lib/libc/net/nss_backends.h43
-rw-r--r--lib/libc/net/nss_compat.c278
-rw-r--r--lib/libc/net/ntoh.c58
-rw-r--r--lib/libc/net/rcmd.3306
-rw-r--r--lib/libc/net/rcmd.c761
-rw-r--r--lib/libc/net/rcmdsh.3116
-rw-r--r--lib/libc/net/rcmdsh.c170
-rw-r--r--lib/libc/net/recv.c50
-rw-r--r--lib/libc/net/res_config.h6
-rw-r--r--lib/libc/net/resolver.3461
-rw-r--r--lib/libc/net/rthdr.c450
-rw-r--r--lib/libc/net/sctp_bindx.3114
-rw-r--r--lib/libc/net/sctp_connectx.3106
-rw-r--r--lib/libc/net/sctp_freepaddrs.368
-rw-r--r--lib/libc/net/sctp_getaddrlen.387
-rw-r--r--lib/libc/net/sctp_getassocid.374
-rw-r--r--lib/libc/net/sctp_getpaddrs.3100
-rw-r--r--lib/libc/net/sctp_opt_info.3144
-rw-r--r--lib/libc/net/sctp_recvmsg.3298
-rw-r--r--lib/libc/net/sctp_send.3354
-rw-r--r--lib/libc/net/sctp_sendmsg.3333
-rw-r--r--lib/libc/net/sctp_sys_calls.c1247
-rw-r--r--lib/libc/net/send.c50
-rw-r--r--lib/libc/net/sockatmark.3123
-rw-r--r--lib/libc/net/sockatmark.c36
-rw-r--r--lib/libc/net/sourcefilter.3240
-rw-r--r--lib/libc/net/sourcefilter.c402
-rw-r--r--lib/libc/net/vars.c45
-rw-r--r--lib/libc/nls/C.msg295
-rw-r--r--lib/libc/nls/Makefile.inc38
-rw-r--r--lib/libc/nls/Symbol.map9
-rw-r--r--lib/libc/nls/be_BY.UTF-8.msg249
-rw-r--r--lib/libc/nls/ca_ES.ISO8859-1.msg267
-rw-r--r--lib/libc/nls/catclose.364
-rw-r--r--lib/libc/nls/catgets.382
-rw-r--r--lib/libc/nls/catopen.3157
-rw-r--r--lib/libc/nls/de_DE.ISO8859-1.msg249
-rw-r--r--lib/libc/nls/el_GR.ISO8859-7.msg249
-rw-r--r--lib/libc/nls/es_ES.ISO8859-1.msg295
-rw-r--r--lib/libc/nls/fi_FI.ISO8859-1.msg233
-rw-r--r--lib/libc/nls/fr_FR.ISO8859-1.msg249
-rw-r--r--lib/libc/nls/gl_ES.ISO8859-1.msg295
-rw-r--r--lib/libc/nls/hu_HU.ISO8859-2.msg295
-rw-r--r--lib/libc/nls/it_IT.ISO8859-15.msg231
-rw-r--r--lib/libc/nls/ja_JP.UTF-8.msg295
-rw-r--r--lib/libc/nls/ja_JP.eucJP.msg295
-rw-r--r--lib/libc/nls/ko_KR.UTF-8.msg295
-rw-r--r--lib/libc/nls/ko_KR.eucKR.msg295
-rw-r--r--lib/libc/nls/mn_MN.UTF-8.msg249
-rw-r--r--lib/libc/nls/msgcat.c447
-rw-r--r--lib/libc/nls/nl_NL.ISO8859-1.msg294
-rw-r--r--lib/libc/nls/no_NO.ISO8859-1.msg231
-rw-r--r--lib/libc/nls/pl_PL.ISO8859-2.msg249
-rw-r--r--lib/libc/nls/pt_BR.ISO8859-1.msg249
-rw-r--r--lib/libc/nls/ru_RU.KOI8-R.msg266
-rw-r--r--lib/libc/nls/sk_SK.ISO8859-2.msg267
-rw-r--r--lib/libc/nls/sv_SE.ISO8859-1.msg233
-rw-r--r--lib/libc/nls/uk_UA.UTF-8.msg259
-rw-r--r--lib/libc/posix1e/Makefile.inc124
-rw-r--r--lib/libc/posix1e/Symbol.map86
-rw-r--r--lib/libc/posix1e/acl.3298
-rw-r--r--lib/libc/posix1e/acl_add_flag_np.397
-rw-r--r--lib/libc/posix1e/acl_add_perm.3129
-rw-r--r--lib/libc/posix1e/acl_branding.c169
-rw-r--r--lib/libc/posix1e/acl_calc_mask.398
-rw-r--r--lib/libc/posix1e/acl_calc_mask.c128
-rw-r--r--lib/libc/posix1e/acl_clear_flags_np.379
-rw-r--r--lib/libc/posix1e/acl_clear_perms.379
-rw-r--r--lib/libc/posix1e/acl_compat.c59
-rw-r--r--lib/libc/posix1e/acl_copy.c86
-rw-r--r--lib/libc/posix1e/acl_copy_entry.385
-rw-r--r--lib/libc/posix1e/acl_create_entry.398
-rw-r--r--lib/libc/posix1e/acl_delete.3140
-rw-r--r--lib/libc/posix1e/acl_delete.c79
-rw-r--r--lib/libc/posix1e/acl_delete_entry.3101
-rw-r--r--lib/libc/posix1e/acl_delete_entry.c162
-rw-r--r--lib/libc/posix1e/acl_delete_flag_np.384
-rw-r--r--lib/libc/posix1e/acl_delete_perm.384
-rw-r--r--lib/libc/posix1e/acl_dup.3110
-rw-r--r--lib/libc/posix1e/acl_entry.c146
-rw-r--r--lib/libc/posix1e/acl_flag.c155
-rw-r--r--lib/libc/posix1e/acl_free.389
-rw-r--r--lib/libc/posix1e/acl_free.c54
-rw-r--r--lib/libc/posix1e/acl_from_text.3130
-rw-r--r--lib/libc/posix1e/acl_from_text.c313
-rw-r--r--lib/libc/posix1e/acl_from_text_nfs4.c283
-rw-r--r--lib/libc/posix1e/acl_get.3168
-rw-r--r--lib/libc/posix1e/acl_get.c216
-rw-r--r--lib/libc/posix1e/acl_get_brand_np.386
-rw-r--r--lib/libc/posix1e/acl_get_entry.3145
-rw-r--r--lib/libc/posix1e/acl_get_entry_type_np.380
-rw-r--r--lib/libc/posix1e/acl_get_flag_np.394
-rw-r--r--lib/libc/posix1e/acl_get_flagset_np.383
-rw-r--r--lib/libc/posix1e/acl_get_perm_np.394
-rw-r--r--lib/libc/posix1e/acl_get_permset.383
-rw-r--r--lib/libc/posix1e/acl_get_qualifier.3140
-rw-r--r--lib/libc/posix1e/acl_get_tag_type.385
-rw-r--r--lib/libc/posix1e/acl_id_to_name.c100
-rw-r--r--lib/libc/posix1e/acl_init.3111
-rw-r--r--lib/libc/posix1e/acl_init.c93
-rw-r--r--lib/libc/posix1e/acl_is_trivial_np.386
-rw-r--r--lib/libc/posix1e/acl_perm.c128
-rw-r--r--lib/libc/posix1e/acl_set.3157
-rw-r--r--lib/libc/posix1e/acl_set.c253
-rw-r--r--lib/libc/posix1e/acl_set_entry_type_np.394
-rw-r--r--lib/libc/posix1e/acl_set_flagset_np.385
-rw-r--r--lib/libc/posix1e/acl_set_permset.381
-rw-r--r--lib/libc/posix1e/acl_set_qualifier.391
-rw-r--r--lib/libc/posix1e/acl_set_tag_type.3102
-rw-r--r--lib/libc/posix1e/acl_size.c43
-rw-r--r--lib/libc/posix1e/acl_strip.c225
-rw-r--r--lib/libc/posix1e/acl_strip_np.3109
-rw-r--r--lib/libc/posix1e/acl_support.c418
-rw-r--r--lib/libc/posix1e/acl_support.h66
-rw-r--r--lib/libc/posix1e/acl_support_nfs4.c260
-rw-r--r--lib/libc/posix1e/acl_to_text.3158
-rw-r--r--lib/libc/posix1e/acl_to_text.c261
-rw-r--r--lib/libc/posix1e/acl_to_text_nfs4.c264
-rw-r--r--lib/libc/posix1e/acl_valid.3170
-rw-r--r--lib/libc/posix1e/acl_valid.c124
-rw-r--r--lib/libc/posix1e/extattr.3100
-rw-r--r--lib/libc/posix1e/extattr.c77
-rw-r--r--lib/libc/posix1e/mac.3176
-rw-r--r--lib/libc/posix1e/mac.c449
-rw-r--r--lib/libc/posix1e/mac.conf.5123
-rw-r--r--lib/libc/posix1e/mac_exec.c46
-rw-r--r--lib/libc/posix1e/mac_free.399
-rw-r--r--lib/libc/posix1e/mac_get.3152
-rw-r--r--lib/libc/posix1e/mac_get.c87
-rw-r--r--lib/libc/posix1e/mac_is_present.387
-rw-r--r--lib/libc/posix1e/mac_prepare.3126
-rw-r--r--lib/libc/posix1e/mac_set.3149
-rw-r--r--lib/libc/posix1e/mac_set.c69
-rw-r--r--lib/libc/posix1e/mac_text.3117
-rw-r--r--lib/libc/posix1e/posix1e.3112
-rw-r--r--lib/libc/powerpc/Makefile.inc5
-rw-r--r--lib/libc/powerpc/SYS.h70
-rw-r--r--lib/libc/powerpc/Symbol.map58
-rw-r--r--lib/libc/powerpc/_fpmath.h49
-rw-r--r--lib/libc/powerpc/arith.h16
-rw-r--r--lib/libc/powerpc/gd_qnan.h21
-rw-r--r--lib/libc/powerpc/gen/Makefile.inc9
-rw-r--r--lib/libc/powerpc/gen/_ctx_start.S45
-rw-r--r--lib/libc/powerpc/gen/_set_tp.c35
-rw-r--r--lib/libc/powerpc/gen/_setjmp.S72
-rw-r--r--lib/libc/powerpc/gen/fabs.S37
-rw-r--r--lib/libc/powerpc/gen/flt_rounds.c56
-rw-r--r--lib/libc/powerpc/gen/fpgetmask.c48
-rw-r--r--lib/libc/powerpc/gen/fpgetround.c48
-rw-r--r--lib/libc/powerpc/gen/fpgetsticky.c54
-rw-r--r--lib/libc/powerpc/gen/fpsetmask.c52
-rw-r--r--lib/libc/powerpc/gen/fpsetround.c52
-rw-r--r--lib/libc/powerpc/gen/getcontextx.c69
-rw-r--r--lib/libc/powerpc/gen/infinity.c17
-rw-r--r--lib/libc/powerpc/gen/makecontext.c120
-rw-r--r--lib/libc/powerpc/gen/setjmp.S90
-rw-r--r--lib/libc/powerpc/gen/signalcontext.c103
-rw-r--r--lib/libc/powerpc/gen/sigsetjmp.S98
-rw-r--r--lib/libc/powerpc/gen/syncicache.c103
-rw-r--r--lib/libc/powerpc/softfloat/milieu.h49
-rw-r--r--lib/libc/powerpc/softfloat/powerpc-gcc.h92
-rw-r--r--lib/libc/powerpc/softfloat/softfloat.h307
-rw-r--r--lib/libc/powerpc/sys/Makefile.inc11
-rw-r--r--lib/libc/powerpc/sys/brk.S75
-rw-r--r--lib/libc/powerpc/sys/cerror.S57
-rw-r--r--lib/libc/powerpc/sys/exect.S41
-rw-r--r--lib/libc/powerpc/sys/pipe.S45
-rw-r--r--lib/libc/powerpc/sys/ptrace.S60
-rw-r--r--lib/libc/powerpc/sys/sbrk.S72
-rw-r--r--lib/libc/powerpc/sys/setlogin.S51
-rw-r--r--lib/libc/powerpc64/Makefile.inc5
-rw-r--r--lib/libc/powerpc64/SYS.h94
-rw-r--r--lib/libc/powerpc64/Symbol.map58
-rw-r--r--lib/libc/powerpc64/_fpmath.h49
-rw-r--r--lib/libc/powerpc64/arith.h16
-rw-r--r--lib/libc/powerpc64/gd_qnan.h21
-rw-r--r--lib/libc/powerpc64/gen/Makefile.inc9
-rw-r--r--lib/libc/powerpc64/gen/_ctx_start.S50
-rw-r--r--lib/libc/powerpc64/gen/_set_tp.c35
-rw-r--r--lib/libc/powerpc64/gen/_setjmp.S117
-rw-r--r--lib/libc/powerpc64/gen/fabs.S37
-rw-r--r--lib/libc/powerpc64/gen/flt_rounds.c56
-rw-r--r--lib/libc/powerpc64/gen/fpgetmask.c55
-rw-r--r--lib/libc/powerpc64/gen/fpgetround.c55
-rw-r--r--lib/libc/powerpc64/gen/fpgetsticky.c61
-rw-r--r--lib/libc/powerpc64/gen/fpsetmask.c59
-rw-r--r--lib/libc/powerpc64/gen/fpsetround.c59
-rw-r--r--lib/libc/powerpc64/gen/getcontextx.c69
-rw-r--r--lib/libc/powerpc64/gen/infinity.c17
-rw-r--r--lib/libc/powerpc64/gen/makecontext.c118
-rw-r--r--lib/libc/powerpc64/gen/setjmp.S136
-rw-r--r--lib/libc/powerpc64/gen/signalcontext.c103
-rw-r--r--lib/libc/powerpc64/gen/sigsetjmp.S145
-rw-r--r--lib/libc/powerpc64/gen/syncicache.c103
-rw-r--r--lib/libc/powerpc64/softfloat/milieu.h49
-rw-r--r--lib/libc/powerpc64/softfloat/powerpc-gcc.h92
-rw-r--r--lib/libc/powerpc64/softfloat/softfloat.h307
-rw-r--r--lib/libc/powerpc64/sys/Makefile.inc11
-rw-r--r--lib/libc/powerpc64/sys/brk.S73
-rw-r--r--lib/libc/powerpc64/sys/cerror.S60
-rw-r--r--lib/libc/powerpc64/sys/exect.S49
-rw-r--r--lib/libc/powerpc64/sys/pipe.S53
-rw-r--r--lib/libc/powerpc64/sys/ptrace.S67
-rw-r--r--lib/libc/powerpc64/sys/sbrk.S68
-rw-r--r--lib/libc/powerpc64/sys/setlogin.S41
-rw-r--r--lib/libc/quad/Makefile.inc21
-rw-r--r--lib/libc/quad/Symbol.map38
-rw-r--r--lib/libc/quad/TESTS/Makefile11
-rw-r--r--lib/libc/quad/TESTS/divrem.c76
-rw-r--r--lib/libc/quad/TESTS/mul.c72
-rw-r--r--lib/libc/quad/adddi3.c58
-rw-r--r--lib/libc/quad/anddi3.c56
-rw-r--r--lib/libc/quad/ashldi3.c64
-rw-r--r--lib/libc/quad/ashrdi3.c73
-rw-r--r--lib/libc/quad/cmpdi2.c57
-rw-r--r--lib/libc/quad/divdi3.c63
-rw-r--r--lib/libc/quad/fixdfdi.c60
-rw-r--r--lib/libc/quad/fixsfdi.c61
-rw-r--r--lib/libc/quad/fixunsdfdi.c94
-rw-r--r--lib/libc/quad/fixunssfdi.c98
-rw-r--r--lib/libc/quad/floatdidf.c72
-rw-r--r--lib/libc/quad/floatdisf.c74
-rw-r--r--lib/libc/quad/floatunsdidf.c57
-rw-r--r--lib/libc/quad/iordi3.c56
-rw-r--r--lib/libc/quad/lshldi3.c64
-rw-r--r--lib/libc/quad/lshrdi3.c63
-rw-r--r--lib/libc/quad/moddi3.c65
-rw-r--r--lib/libc/quad/muldi3.c244
-rw-r--r--lib/libc/quad/negdi2.c55
-rw-r--r--lib/libc/quad/notdi2.c56
-rw-r--r--lib/libc/quad/qdivrem.c277
-rw-r--r--lib/libc/quad/quad.h103
-rw-r--r--lib/libc/quad/subdi3.c57
-rw-r--r--lib/libc/quad/ucmpdi2.c56
-rw-r--r--lib/libc/quad/udivdi3.c51
-rw-r--r--lib/libc/quad/umoddi3.c53
-rw-r--r--lib/libc/quad/xordi3.c56
-rw-r--r--lib/libc/regex/COPYRIGHT56
-rw-r--r--lib/libc/regex/Makefile.inc17
-rw-r--r--lib/libc/regex/Symbol.map10
-rw-r--r--lib/libc/regex/WHATSNEW94
-rw-r--r--lib/libc/regex/cname.h138
-rw-r--r--lib/libc/regex/engine.c1191
-rw-r--r--lib/libc/regex/grot/Makefile98
-rw-r--r--lib/libc/regex/grot/debug.c212
-rw-r--r--lib/libc/regex/grot/main.c513
-rwxr-xr-xlib/libc/regex/grot/mkh77
-rw-r--r--lib/libc/regex/grot/split.c319
-rw-r--r--lib/libc/regex/grot/tests477
-rw-r--r--lib/libc/regex/re_format.7483
-rw-r--r--lib/libc/regex/regcomp.c1784
-rw-r--r--lib/libc/regex/regerror.c174
-rw-r--r--lib/libc/regex/regex.3727
-rw-r--r--lib/libc/regex/regex2.h192
-rw-r--r--lib/libc/regex/regexec.c233
-rw-r--r--lib/libc/regex/regfree.c89
-rw-r--r--lib/libc/regex/utils.h54
-rw-r--r--lib/libc/resolv/Makefile.inc10
-rw-r--r--lib/libc/resolv/Symbol.map107
-rw-r--r--lib/libc/resolv/h_errno.c46
-rw-r--r--lib/libc/resolv/herror.c126
-rw-r--r--lib/libc/resolv/mtctxres.c141
-rw-r--r--lib/libc/resolv/res_comp.c277
-rw-r--r--lib/libc/resolv/res_data.c320
-rw-r--r--lib/libc/resolv/res_debug.c1229
-rw-r--r--lib/libc/resolv/res_debug.h35
-rw-r--r--lib/libc/resolv/res_findzonecut.c727
-rw-r--r--lib/libc/resolv/res_init.c872
-rw-r--r--lib/libc/resolv/res_mkquery.c303
-rw-r--r--lib/libc/resolv/res_mkupdate.c1196
-rw-r--r--lib/libc/resolv/res_private.h22
-rw-r--r--lib/libc/resolv/res_query.c489
-rw-r--r--lib/libc/resolv/res_send.c1179
-rw-r--r--lib/libc/resolv/res_state.c87
-rw-r--r--lib/libc/resolv/res_update.c222
-rw-r--r--lib/libc/rpc/DISCLAIMER31
-rw-r--r--lib/libc/rpc/LICENSE335
-rw-r--r--lib/libc/rpc/Makefile.inc179
-rw-r--r--lib/libc/rpc/README176
-rw-r--r--lib/libc/rpc/Symbol.map247
-rw-r--r--lib/libc/rpc/auth_des.c498
-rw-r--r--lib/libc/rpc/auth_none.c176
-rw-r--r--lib/libc/rpc/auth_time.c507
-rw-r--r--lib/libc/rpc/auth_unix.c381
-rw-r--r--lib/libc/rpc/authdes_prot.c94
-rw-r--r--lib/libc/rpc/authunix_prot.c79
-rw-r--r--lib/libc/rpc/bindresvport.3103
-rw-r--r--lib/libc/rpc/bindresvport.c161
-rw-r--r--lib/libc/rpc/clnt_bcast.c673
-rw-r--r--lib/libc/rpc/clnt_dg.c859
-rw-r--r--lib/libc/rpc/clnt_generic.c466
-rw-r--r--lib/libc/rpc/clnt_perror.c333
-rw-r--r--lib/libc/rpc/clnt_raw.c315
-rw-r--r--lib/libc/rpc/clnt_simple.c206
-rw-r--r--lib/libc/rpc/clnt_vc.c871
-rw-r--r--lib/libc/rpc/crypt_client.c101
-rw-r--r--lib/libc/rpc/des_crypt.3130
-rw-r--r--lib/libc/rpc/des_crypt.c154
-rw-r--r--lib/libc/rpc/des_soft.c71
-rw-r--r--lib/libc/rpc/getnetconfig.3222
-rw-r--r--lib/libc/rpc/getnetconfig.c742
-rw-r--r--lib/libc/rpc/getnetpath.3170
-rw-r--r--lib/libc/rpc/getnetpath.c276
-rw-r--r--lib/libc/rpc/getpublickey.c179
-rw-r--r--lib/libc/rpc/getrpcent.3109
-rw-r--r--lib/libc/rpc/getrpcent.c1048
-rw-r--r--lib/libc/rpc/getrpcport.336
-rw-r--r--lib/libc/rpc/getrpcport.c78
-rw-r--r--lib/libc/rpc/key_call.c480
-rw-r--r--lib/libc/rpc/key_prot_xdr.c178
-rw-r--r--lib/libc/rpc/mt_misc.c117
-rw-r--r--lib/libc/rpc/mt_misc.h65
-rw-r--r--lib/libc/rpc/netconfig.5132
-rw-r--r--lib/libc/rpc/netname.c150
-rw-r--r--lib/libc/rpc/netnamer.c331
-rw-r--r--lib/libc/rpc/pmap_clnt.c120
-rw-r--r--lib/libc/rpc/pmap_getmaps.c100
-rw-r--r--lib/libc/rpc/pmap_getport.c104
-rw-r--r--lib/libc/rpc/pmap_prot.c69
-rw-r--r--lib/libc/rpc/pmap_prot2.c143
-rw-r--r--lib/libc/rpc/pmap_rmt.c176
-rw-r--r--lib/libc/rpc/publickey.353
-rw-r--r--lib/libc/rpc/publickey.542
-rw-r--r--lib/libc/rpc/rpc.3517
-rw-r--r--lib/libc/rpc/rpc.559
-rw-r--r--lib/libc/rpc/rpc_callmsg.c207
-rw-r--r--lib/libc/rpc/rpc_clnt_auth.396
-rw-r--r--lib/libc/rpc/rpc_clnt_calls.3316
-rw-r--r--lib/libc/rpc/rpc_clnt_create.3514
-rw-r--r--lib/libc/rpc/rpc_com.h95
-rw-r--r--lib/libc/rpc/rpc_commondata.c48
-rw-r--r--lib/libc/rpc/rpc_dtablesize.c67
-rw-r--r--lib/libc/rpc/rpc_generic.c845
-rw-r--r--lib/libc/rpc/rpc_prot.c372
-rw-r--r--lib/libc/rpc/rpc_secure.3287
-rw-r--r--lib/libc/rpc/rpc_soc.31721
-rw-r--r--lib/libc/rpc/rpc_soc.c582
-rw-r--r--lib/libc/rpc/rpc_svc_calls.3267
-rw-r--r--lib/libc/rpc/rpc_svc_create.3337
-rw-r--r--lib/libc/rpc/rpc_svc_err.397
-rw-r--r--lib/libc/rpc/rpc_svc_reg.3183
-rw-r--r--lib/libc/rpc/rpc_xdr.3101
-rw-r--r--lib/libc/rpc/rpcb_clnt.c1363
-rw-r--r--lib/libc/rpc/rpcb_prot.c332
-rw-r--r--lib/libc/rpc/rpcb_st_xdr.c275
-rw-r--r--lib/libc/rpc/rpcbind.3194
-rw-r--r--lib/libc/rpc/rpcdname.c82
-rw-r--r--lib/libc/rpc/rpcsec_gss_stub.c48
-rw-r--r--lib/libc/rpc/rtime.350
-rw-r--r--lib/libc/rpc/rtime.c160
-rw-r--r--lib/libc/rpc/svc.c789
-rw-r--r--lib/libc/rpc/svc_auth.c234
-rw-r--r--lib/libc/rpc/svc_auth_des.c538
-rw-r--r--lib/libc/rpc/svc_auth_unix.c156
-rw-r--r--lib/libc/rpc/svc_dg.c739
-rw-r--r--lib/libc/rpc/svc_generic.c311
-rw-r--r--lib/libc/rpc/svc_raw.c274
-rw-r--r--lib/libc/rpc/svc_run.c98
-rw-r--r--lib/libc/rpc/svc_simple.c313
-rw-r--r--lib/libc/rpc/svc_vc.c811
-rw-r--r--lib/libc/softfloat/Makefile.inc30
-rw-r--r--lib/libc/softfloat/README.NetBSD9
-rw-r--r--lib/libc/softfloat/README.txt40
-rw-r--r--lib/libc/softfloat/Symbol.map41
-rw-r--r--lib/libc/softfloat/bits32/softfloat-macros649
-rw-r--r--lib/libc/softfloat/bits32/softfloat.c2347
-rw-r--r--lib/libc/softfloat/bits64/softfloat-macros746
-rw-r--r--lib/libc/softfloat/bits64/softfloat.c5599
-rw-r--r--lib/libc/softfloat/eqdf2.c22
-rw-r--r--lib/libc/softfloat/eqsf2.c22
-rw-r--r--lib/libc/softfloat/eqtf2.c24
-rw-r--r--lib/libc/softfloat/fpgetmask.c53
-rw-r--r--lib/libc/softfloat/fpgetround.c53
-rw-r--r--lib/libc/softfloat/fpgetsticky.c53
-rw-r--r--lib/libc/softfloat/fpsetmask.c56
-rw-r--r--lib/libc/softfloat/fpsetround.c56
-rw-r--r--lib/libc/softfloat/fpsetsticky.c56
-rw-r--r--lib/libc/softfloat/gedf2.c22
-rw-r--r--lib/libc/softfloat/gesf2.c22
-rw-r--r--lib/libc/softfloat/getf2.c26
-rw-r--r--lib/libc/softfloat/gexf2.c25
-rw-r--r--lib/libc/softfloat/gtdf2.c22
-rw-r--r--lib/libc/softfloat/gtsf2.c22
-rw-r--r--lib/libc/softfloat/gttf2.c26
-rw-r--r--lib/libc/softfloat/gtxf2.c25
-rw-r--r--lib/libc/softfloat/ledf2.c22
-rw-r--r--lib/libc/softfloat/lesf2.c22
-rw-r--r--lib/libc/softfloat/letf2.c26
-rw-r--r--lib/libc/softfloat/ltdf2.c22
-rw-r--r--lib/libc/softfloat/ltsf2.c22
-rw-r--r--lib/libc/softfloat/lttf2.c26
-rw-r--r--lib/libc/softfloat/nedf2.c22
-rw-r--r--lib/libc/softfloat/negdf2.c22
-rw-r--r--lib/libc/softfloat/negsf2.c22
-rw-r--r--lib/libc/softfloat/negtf2.c27
-rw-r--r--lib/libc/softfloat/negxf2.c25
-rw-r--r--lib/libc/softfloat/nesf2.c22
-rw-r--r--lib/libc/softfloat/netf2.c26
-rw-r--r--lib/libc/softfloat/nexf2.c25
-rw-r--r--lib/libc/softfloat/softfloat-for-gcc.h169
-rw-r--r--lib/libc/softfloat/softfloat-history.txt53
-rw-r--r--lib/libc/softfloat/softfloat-source.txt384
-rw-r--r--lib/libc/softfloat/softfloat-specialize521
-rw-r--r--lib/libc/softfloat/softfloat.txt373
-rw-r--r--lib/libc/softfloat/templates/milieu.h49
-rw-r--r--lib/libc/softfloat/templates/softfloat-specialize465
-rw-r--r--lib/libc/softfloat/templates/softfloat.h291
-rw-r--r--lib/libc/softfloat/timesoftfloat.c2639
-rw-r--r--lib/libc/softfloat/timesoftfloat.txt150
-rw-r--r--lib/libc/softfloat/unorddf2.c26
-rw-r--r--lib/libc/softfloat/unordsf2.c26
-rw-r--r--lib/libc/sparc64/Makefile.inc11
-rw-r--r--lib/libc/sparc64/SYS.h85
-rw-r--r--lib/libc/sparc64/Symbol.map98
-rw-r--r--lib/libc/sparc64/_fpmath.h57
-rw-r--r--lib/libc/sparc64/arith.h19
-rw-r--r--lib/libc/sparc64/fpu/Makefile.inc8
-rw-r--r--lib/libc/sparc64/fpu/fpu.c461
-rw-r--r--lib/libc/sparc64/fpu/fpu_add.c214
-rw-r--r--lib/libc/sparc64/fpu/fpu_arith.h87
-rw-r--r--lib/libc/sparc64/fpu/fpu_compare.c177
-rw-r--r--lib/libc/sparc64/fpu/fpu_div.c270
-rw-r--r--lib/libc/sparc64/fpu/fpu_emu.h177
-rw-r--r--lib/libc/sparc64/fpu/fpu_explode.c324
-rw-r--r--lib/libc/sparc64/fpu/fpu_extern.h85
-rw-r--r--lib/libc/sparc64/fpu/fpu_implode.c542
-rw-r--r--lib/libc/sparc64/fpu/fpu_mul.c224
-rw-r--r--lib/libc/sparc64/fpu/fpu_qp.c163
-rw-r--r--lib/libc/sparc64/fpu/fpu_reg.S194
-rw-r--r--lib/libc/sparc64/fpu/fpu_reg.h88
-rw-r--r--lib/libc/sparc64/fpu/fpu_sqrt.c397
-rw-r--r--lib/libc/sparc64/fpu/fpu_subr.c221
-rw-r--r--lib/libc/sparc64/gd_qnan.h21
-rw-r--r--lib/libc/sparc64/gen/Makefile.inc6
-rw-r--r--lib/libc/sparc64/gen/_ctx_start.S36
-rw-r--r--lib/libc/sparc64/gen/_set_tp.c34
-rw-r--r--lib/libc/sparc64/gen/_setjmp.S79
-rw-r--r--lib/libc/sparc64/gen/assym.s18
-rw-r--r--lib/libc/sparc64/gen/fabs.S35
-rw-r--r--lib/libc/sparc64/gen/fixunsdfsi.S93
-rw-r--r--lib/libc/sparc64/gen/flt_rounds.c26
-rw-r--r--lib/libc/sparc64/gen/fpgetmask.c22
-rw-r--r--lib/libc/sparc64/gen/fpgetround.c21
-rw-r--r--lib/libc/sparc64/gen/fpgetsticky.c21
-rw-r--r--lib/libc/sparc64/gen/fpsetmask.c28
-rw-r--r--lib/libc/sparc64/gen/fpsetround.c30
-rw-r--r--lib/libc/sparc64/gen/getcontextx.c69
-rw-r--r--lib/libc/sparc64/gen/infinity.c17
-rw-r--r--lib/libc/sparc64/gen/makecontext.c89
-rw-r--r--lib/libc/sparc64/gen/setjmp.S88
-rw-r--r--lib/libc/sparc64/gen/signalcontext.c77
-rw-r--r--lib/libc/sparc64/gen/sigsetjmp.S56
-rw-r--r--lib/libc/sparc64/string/Makefile.inc1
-rw-r--r--lib/libc/sparc64/sys/Makefile.inc23
-rw-r--r--lib/libc/sparc64/sys/__sparc_sigtramp_setup.c46
-rw-r--r--lib/libc/sparc64/sys/__sparc_utrap.c141
-rw-r--r--lib/libc/sparc64/sys/__sparc_utrap_align.c117
-rw-r--r--lib/libc/sparc64/sys/__sparc_utrap_emul.c155
-rw-r--r--lib/libc/sparc64/sys/__sparc_utrap_fp_disabled.S36
-rw-r--r--lib/libc/sparc64/sys/__sparc_utrap_gen.S107
-rw-r--r--lib/libc/sparc64/sys/__sparc_utrap_install.c49
-rw-r--r--lib/libc/sparc64/sys/__sparc_utrap_private.h66
-rw-r--r--lib/libc/sparc64/sys/__sparc_utrap_setup.c58
-rw-r--r--lib/libc/sparc64/sys/assym.s39
-rw-r--r--lib/libc/sparc64/sys/brk.S65
-rw-r--r--lib/libc/sparc64/sys/cerror.S59
-rw-r--r--lib/libc/sparc64/sys/exect.S51
-rw-r--r--lib/libc/sparc64/sys/pipe.S57
-rw-r--r--lib/libc/sparc64/sys/ptrace.S57
-rw-r--r--lib/libc/sparc64/sys/sbrk.S71
-rw-r--r--lib/libc/sparc64/sys/setlogin.S55
-rw-r--r--lib/libc/sparc64/sys/sigaction.S49
-rw-r--r--lib/libc/sparc64/sys/sigcode.S40
-rw-r--r--lib/libc/stdio/Makefile.inc76
-rw-r--r--lib/libc/stdio/Symbol.map198
-rw-r--r--lib/libc/stdio/_flock_stub.c136
-rw-r--r--lib/libc/stdio/asprintf.c67
-rw-r--r--lib/libc/stdio/clrerr.c61
-rw-r--r--lib/libc/stdio/dprintf.c46
-rw-r--r--lib/libc/stdio/fclose.3111
-rw-r--r--lib/libc/stdio/fclose.c85
-rw-r--r--lib/libc/stdio/fcloseall.c39
-rw-r--r--lib/libc/stdio/fdopen.c98
-rw-r--r--lib/libc/stdio/feof.c63
-rw-r--r--lib/libc/stdio/ferror.3131
-rw-r--r--lib/libc/stdio/ferror.c63
-rw-r--r--lib/libc/stdio/fflush.3111
-rw-r--r--lib/libc/stdio/fflush.c141
-rw-r--r--lib/libc/stdio/fgetc.c56
-rw-r--r--lib/libc/stdio/fgetln.3125
-rw-r--r--lib/libc/stdio/fgetln.c164
-rw-r--r--lib/libc/stdio/fgetpos.c51
-rw-r--r--lib/libc/stdio/fgets.3158
-rw-r--r--lib/libc/stdio/fgets.c112
-rw-r--r--lib/libc/stdio/fgetwc.c109
-rw-r--r--lib/libc/stdio/fgetwln.3116
-rw-r--r--lib/libc/stdio/fgetwln.c79
-rw-r--r--lib/libc/stdio/fgetws.3121
-rw-r--r--lib/libc/stdio/fgetws.c112
-rw-r--r--lib/libc/stdio/fileno.c64
-rw-r--r--lib/libc/stdio/findfp.c215
-rw-r--r--lib/libc/stdio/flags.c109
-rw-r--r--lib/libc/stdio/floatio.h54
-rw-r--r--lib/libc/stdio/flockfile.3104
-rw-r--r--lib/libc/stdio/fopen.3275
-rw-r--r--lib/libc/stdio/fopen.c99
-rw-r--r--lib/libc/stdio/fprintf.c70
-rw-r--r--lib/libc/stdio/fpurge.c70
-rw-r--r--lib/libc/stdio/fputc.c57
-rw-r--r--lib/libc/stdio/fputs.3104
-rw-r--r--lib/libc/stdio/fputs.c68
-rw-r--r--lib/libc/stdio/fputwc.c98
-rw-r--r--lib/libc/stdio/fputws.388
-rw-r--r--lib/libc/stdio/fputws.c86
-rw-r--r--lib/libc/stdio/fread.3105
-rw-r--r--lib/libc/stdio/fread.c115
-rw-r--r--lib/libc/stdio/freopen.c237
-rw-r--r--lib/libc/stdio/fscanf.c78
-rw-r--r--lib/libc/stdio/fseek.3269
-rw-r--r--lib/libc/stdio/fseek.c311
-rw-r--r--lib/libc/stdio/fsetpos.c51
-rw-r--r--lib/libc/stdio/ftell.c139
-rw-r--r--lib/libc/stdio/funopen.3176
-rw-r--r--lib/libc/stdio/funopen.c76
-rw-r--r--lib/libc/stdio/fvwrite.c207
-rw-r--r--lib/libc/stdio/fvwrite.h49
-rw-r--r--lib/libc/stdio/fwalk.c67
-rw-r--r--lib/libc/stdio/fwide.397
-rw-r--r--lib/libc/stdio/fwide.c51
-rw-r--r--lib/libc/stdio/fwprintf.c63
-rw-r--r--lib/libc/stdio/fwrite.c99
-rw-r--r--lib/libc/stdio/fwscanf.c63
-rw-r--r--lib/libc/stdio/getc.3169
-rw-r--r--lib/libc/stdio/getc.c65
-rw-r--r--lib/libc/stdio/getchar.c68
-rw-r--r--lib/libc/stdio/getdelim.c160
-rw-r--r--lib/libc/stdio/getline.3165
-rw-r--r--lib/libc/stdio/getline.c39
-rw-r--r--lib/libc/stdio/gets.c77
-rw-r--r--lib/libc/stdio/getw.c48
-rw-r--r--lib/libc/stdio/getwc.3114
-rw-r--r--lib/libc/stdio/getwc.c60
-rw-r--r--lib/libc/stdio/getwchar.c57
-rw-r--r--lib/libc/stdio/glue.h45
-rw-r--r--lib/libc/stdio/local.h133
-rw-r--r--lib/libc/stdio/makebuf.c120
-rw-r--r--lib/libc/stdio/mktemp.3238
-rw-r--r--lib/libc/stdio/mktemp.c201
-rw-r--r--lib/libc/stdio/perror.c76
-rw-r--r--lib/libc/stdio/printf-pos.c752
-rw-r--r--lib/libc/stdio/printf.3920
-rw-r--r--lib/libc/stdio/printf.c69
-rw-r--r--lib/libc/stdio/printfcommon.h307
-rw-r--r--lib/libc/stdio/printflocal.h94
-rw-r--r--lib/libc/stdio/putc.3165
-rw-r--r--lib/libc/stdio/putc.c67
-rw-r--r--lib/libc/stdio/putchar.c71
-rw-r--r--lib/libc/stdio/puts.c71
-rw-r--r--lib/libc/stdio/putw.c62
-rw-r--r--lib/libc/stdio/putwc.3103
-rw-r--r--lib/libc/stdio/putwc.c59
-rw-r--r--lib/libc/stdio/putwchar.c58
-rw-r--r--lib/libc/stdio/refill.c146
-rw-r--r--lib/libc/stdio/remove.383
-rw-r--r--lib/libc/stdio/remove.c55
-rw-r--r--lib/libc/stdio/rewind.c61
-rw-r--r--lib/libc/stdio/rget.c55
-rw-r--r--lib/libc/stdio/scanf.3513
-rw-r--r--lib/libc/stdio/scanf.c78
-rw-r--r--lib/libc/stdio/setbuf.3209
-rw-r--r--lib/libc/stdio/setbuf.c46
-rw-r--r--lib/libc/stdio/setbuffer.c60
-rw-r--r--lib/libc/stdio/setvbuf.c161
-rw-r--r--lib/libc/stdio/snprintf.c105
-rw-r--r--lib/libc/stdio/sprintf.c73
-rw-r--r--lib/libc/stdio/sscanf.c72
-rw-r--r--lib/libc/stdio/stdio.3333
-rw-r--r--lib/libc/stdio/stdio.c187
-rw-r--r--lib/libc/stdio/swprintf.c64
-rw-r--r--lib/libc/stdio/swscanf.c64
-rw-r--r--lib/libc/stdio/tempnam.c90
-rw-r--r--lib/libc/stdio/tmpfile.c92
-rw-r--r--lib/libc/stdio/tmpnam.3248
-rw-r--r--lib/libc/stdio/tmpnam.c61
-rw-r--r--lib/libc/stdio/ungetc.398
-rw-r--r--lib/libc/stdio/ungetc.c168
-rw-r--r--lib/libc/stdio/ungetwc.395
-rw-r--r--lib/libc/stdio/ungetwc.c90
-rw-r--r--lib/libc/stdio/vasprintf.c74
-rw-r--r--lib/libc/stdio/vdprintf.c70
-rw-r--r--lib/libc/stdio/vfprintf.c1037
-rw-r--r--lib/libc/stdio/vfscanf.c1174
-rw-r--r--lib/libc/stdio/vfwprintf.c1101
-rw-r--r--lib/libc/stdio/vfwscanf.c983
-rw-r--r--lib/libc/stdio/vprintf.c56
-rw-r--r--lib/libc/stdio/vscanf.c71
-rw-r--r--lib/libc/stdio/vsnprintf.c88
-rw-r--r--lib/libc/stdio/vsprintf.c68
-rw-r--r--lib/libc/stdio/vsscanf.c78
-rw-r--r--lib/libc/stdio/vswprintf.c114
-rw-r--r--lib/libc/stdio/vswscanf.c104
-rw-r--r--lib/libc/stdio/vwprintf.c49
-rw-r--r--lib/libc/stdio/vwscanf.c49
-rw-r--r--lib/libc/stdio/wbuf.c91
-rw-r--r--lib/libc/stdio/wprintf.3618
-rw-r--r--lib/libc/stdio/wprintf.c63
-rw-r--r--lib/libc/stdio/wscanf.3479
-rw-r--r--lib/libc/stdio/wscanf.c63
-rw-r--r--lib/libc/stdio/wsetup.c93
-rw-r--r--lib/libc/stdio/xprintf.c690
-rw-r--r--lib/libc/stdio/xprintf_errno.c65
-rw-r--r--lib/libc/stdio/xprintf_float.c425
-rw-r--r--lib/libc/stdio/xprintf_hexdump.c97
-rw-r--r--lib/libc/stdio/xprintf_int.c471
-rw-r--r--lib/libc/stdio/xprintf_quote.c98
-rw-r--r--lib/libc/stdio/xprintf_str.c187
-rw-r--r--lib/libc/stdio/xprintf_time.c122
-rw-r--r--lib/libc/stdio/xprintf_vis.c78
-rw-r--r--lib/libc/stdlib/Makefile.inc48
-rw-r--r--lib/libc/stdlib/Symbol.map110
-rw-r--r--lib/libc/stdlib/_Exit.c22
-rw-r--r--lib/libc/stdlib/a64l.3187
-rw-r--r--lib/libc/stdlib/a64l.c46
-rw-r--r--lib/libc/stdlib/abort.379
-rw-r--r--lib/libc/stdlib/abort.c79
-rw-r--r--lib/libc/stdlib/abs.375
-rw-r--r--lib/libc/stdlib/abs.c43
-rw-r--r--lib/libc/stdlib/alloca.388
-rw-r--r--lib/libc/stdlib/at_quick_exit.361
-rw-r--r--lib/libc/stdlib/atexit.389
-rw-r--r--lib/libc/stdlib/atexit.c205
-rw-r--r--lib/libc/stdlib/atexit.h36
-rw-r--r--lib/libc/stdlib/atof.395
-rw-r--r--lib/libc/stdlib/atof.c57
-rw-r--r--lib/libc/stdlib/atoi.387
-rw-r--r--lib/libc/stdlib/atoi.c57
-rw-r--r--lib/libc/stdlib/atol.3135
-rw-r--r--lib/libc/stdlib/atol.c57
-rw-r--r--lib/libc/stdlib/atoll.c54
-rw-r--r--lib/libc/stdlib/bsearch.389
-rw-r--r--lib/libc/stdlib/bsearch.c79
-rw-r--r--lib/libc/stdlib/div.368
-rw-r--r--lib/libc/stdlib/div.c77
-rw-r--r--lib/libc/stdlib/exit.3132
-rw-r--r--lib/libc/stdlib/exit.c71
-rw-r--r--lib/libc/stdlib/getenv.3229
-rw-r--r--lib/libc/stdlib/getenv.c686
-rw-r--r--lib/libc/stdlib/getopt.3306
-rw-r--r--lib/libc/stdlib/getopt.c135
-rw-r--r--lib/libc/stdlib/getopt_long.3507
-rw-r--r--lib/libc/stdlib/getopt_long.c625
-rw-r--r--lib/libc/stdlib/getsubopt.3147
-rw-r--r--lib/libc/stdlib/getsubopt.c97
-rw-r--r--lib/libc/stdlib/hcreate.3258
-rw-r--r--lib/libc/stdlib/hcreate.c185
-rw-r--r--lib/libc/stdlib/heapsort.c181
-rw-r--r--lib/libc/stdlib/imaxabs.362
-rw-r--r--lib/libc/stdlib/imaxabs.c36
-rw-r--r--lib/libc/stdlib/imaxdiv.373
-rw-r--r--lib/libc/stdlib/imaxdiv.c45
-rw-r--r--lib/libc/stdlib/insque.361
-rw-r--r--lib/libc/stdlib/insque.c47
-rw-r--r--lib/libc/stdlib/jemalloc/Makefile.inc46
-rw-r--r--lib/libc/stdlib/jemalloc/Symbol.map35
-rw-r--r--lib/libc/stdlib/l64a.c52
-rw-r--r--lib/libc/stdlib/labs.367
-rw-r--r--lib/libc/stdlib/labs.c43
-rw-r--r--lib/libc/stdlib/ldiv.371
-rw-r--r--lib/libc/stdlib/ldiv.c56
-rw-r--r--lib/libc/stdlib/llabs.362
-rw-r--r--lib/libc/stdlib/llabs.c36
-rw-r--r--lib/libc/stdlib/lldiv.373
-rw-r--r--lib/libc/stdlib/lldiv.c45
-rw-r--r--lib/libc/stdlib/lsearch.3105
-rw-r--r--lib/libc/stdlib/lsearch.c64
-rw-r--r--lib/libc/stdlib/memory.377
-rw-r--r--lib/libc/stdlib/merge.c351
-rw-r--r--lib/libc/stdlib/ptsname.3160
-rw-r--r--lib/libc/stdlib/ptsname.c93
-rw-r--r--lib/libc/stdlib/qsort.3286
-rw-r--r--lib/libc/stdlib/qsort.c195
-rw-r--r--lib/libc/stdlib/qsort_r.c8
-rw-r--r--lib/libc/stdlib/quick_exit.357
-rw-r--r--lib/libc/stdlib/quick_exit.c80
-rw-r--r--lib/libc/stdlib/radixsort.3160
-rw-r--r--lib/libc/stdlib/radixsort.c327
-rw-r--r--lib/libc/stdlib/rand.3126
-rw-r--r--lib/libc/stdlib/rand.c168
-rw-r--r--lib/libc/stdlib/random.3196
-rw-r--r--lib/libc/stdlib/random.c502
-rw-r--r--lib/libc/stdlib/reallocf.382
-rw-r--r--lib/libc/stdlib/reallocf.c48
-rw-r--r--lib/libc/stdlib/realpath.3135
-rw-r--r--lib/libc/stdlib/realpath.c235
-rw-r--r--lib/libc/stdlib/remque.c30
-rw-r--r--lib/libc/stdlib/strfmon.3167
-rw-r--r--lib/libc/stdlib/strfmon.c643
-rw-r--r--lib/libc/stdlib/strtod.3198
-rw-r--r--lib/libc/stdlib/strtoimax.c153
-rw-r--r--lib/libc/stdlib/strtol.3222
-rw-r--r--lib/libc/stdlib/strtol.c158
-rw-r--r--lib/libc/stdlib/strtoll.c153
-rw-r--r--lib/libc/stdlib/strtonum.3155
-rw-r--r--lib/libc/stdlib/strtonum.c68
-rw-r--r--lib/libc/stdlib/strtoq.c48
-rw-r--r--lib/libc/stdlib/strtoul.3224
-rw-r--r--lib/libc/stdlib/strtoul.c130
-rw-r--r--lib/libc/stdlib/strtoull.c131
-rw-r--r--lib/libc/stdlib/strtoumax.c131
-rw-r--r--lib/libc/stdlib/strtouq.c48
-rw-r--r--lib/libc/stdlib/system.399
-rw-r--r--lib/libc/stdlib/system.c97
-rw-r--r--lib/libc/stdlib/tdelete.c71
-rw-r--r--lib/libc/stdlib/tfind.c48
-rw-r--r--lib/libc/stdlib/tsearch.3132
-rw-r--r--lib/libc/stdlib/tsearch.c58
-rw-r--r--lib/libc/stdlib/twalk.c58
-rw-r--r--lib/libc/stdtime/Makefile.inc21
-rw-r--r--lib/libc/stdtime/Symbol.map35
-rw-r--r--lib/libc/stdtime/strftime.3278
-rw-r--r--lib/libc/stdtime/strftime.c648
-rw-r--r--lib/libc/stdtime/strptime.3173
-rw-r--r--lib/libc/stdtime/strptime.c614
-rw-r--r--lib/libc/stdtime/time32.c100
-rw-r--r--lib/libc/stdtime/timelocal.c154
-rw-r--r--lib/libc/stdtime/timelocal.h61
-rw-r--r--lib/libc/string/Makefile.inc86
-rw-r--r--lib/libc/string/Symbol.map104
-rw-r--r--lib/libc/string/bcmp.377
-rw-r--r--lib/libc/string/bcmp.c55
-rw-r--r--lib/libc/string/bcopy.377
-rw-r--r--lib/libc/string/bcopy.c137
-rw-r--r--lib/libc/string/bstring.3108
-rw-r--r--lib/libc/string/bzero.374
-rw-r--r--lib/libc/string/bzero.c5
-rw-r--r--lib/libc/string/ffs.3111
-rw-r--r--lib/libc/string/ffs.c51
-rw-r--r--lib/libc/string/ffsl.c48
-rw-r--r--lib/libc/string/ffsll.c48
-rw-r--r--lib/libc/string/fls.c48
-rw-r--r--lib/libc/string/flsl.c48
-rw-r--r--lib/libc/string/flsll.c48
-rw-r--r--lib/libc/string/index.3115
-rw-r--r--lib/libc/string/memccpy.374
-rw-r--r--lib/libc/string/memccpy.c52
-rw-r--r--lib/libc/string/memchr.3106
-rw-r--r--lib/libc/string/memchr.c53
-rw-r--r--lib/libc/string/memcmp.384
-rw-r--r--lib/libc/string/memcmp.c56
-rw-r--r--lib/libc/string/memcpy.388
-rw-r--r--lib/libc/string/memcpy.c5
-rw-r--r--lib/libc/string/memmem.386
-rw-r--r--lib/libc/string/memmem.c65
-rw-r--r--lib/libc/string/memmove.375
-rw-r--r--lib/libc/string/memmove.c5
-rw-r--r--lib/libc/string/memrchr.c40
-rw-r--r--lib/libc/string/memset.372
-rw-r--r--lib/libc/string/memset.c128
-rw-r--r--lib/libc/string/stpcpy.c46
-rw-r--r--lib/libc/string/stpncpy.c45
-rw-r--r--lib/libc/string/strcasecmp.3101
-rw-r--r--lib/libc/string/strcasecmp.c87
-rw-r--r--lib/libc/string/strcasestr.c72
-rw-r--r--lib/libc/string/strcat.3157
-rw-r--r--lib/libc/string/strcat.c46
-rw-r--r--lib/libc/string/strchr.396
-rw-r--r--lib/libc/string/strchr.c54
-rw-r--r--lib/libc/string/strcmp.3101
-rw-r--r--lib/libc/string/strcmp.c51
-rw-r--r--lib/libc/string/strcoll.375
-rw-r--r--lib/libc/string/strcoll.c102
-rw-r--r--lib/libc/string/strcpy.3216
-rw-r--r--lib/libc/string/strcpy.c45
-rw-r--r--lib/libc/string/strcspn.388
-rw-r--r--lib/libc/string/strcspn.c72
-rw-r--r--lib/libc/string/strdup.384
-rw-r--r--lib/libc/string/strdup.c51
-rw-r--r--lib/libc/string/strerror.3190
-rw-r--r--lib/libc/string/strerror.c126
-rw-r--r--lib/libc/string/string.3157
-rw-r--r--lib/libc/string/strlcat.c58
-rw-r--r--lib/libc/string/strlcpy.3205
-rw-r--r--lib/libc/string/strlcpy.c54
-rw-r--r--lib/libc/string/strlen.392
-rw-r--r--lib/libc/string/strlen.c130
-rw-r--r--lib/libc/string/strmode.3142
-rw-r--r--lib/libc/string/strmode.c148
-rw-r--r--lib/libc/string/strncat.c62
-rw-r--r--lib/libc/string/strncmp.c52
-rw-r--r--lib/libc/string/strncpy.c62
-rw-r--r--lib/libc/string/strndup.c51
-rw-r--r--lib/libc/string/strnlen.c42
-rw-r--r--lib/libc/string/strnstr.c65
-rw-r--r--lib/libc/string/strpbrk.377
-rw-r--r--lib/libc/string/strpbrk.c53
-rw-r--r--lib/libc/string/strrchr.c55
-rw-r--r--lib/libc/string/strsep.3135
-rw-r--r--lib/libc/string/strsep.c75
-rw-r--r--lib/libc/string/strsignal.c152
-rw-r--r--lib/libc/string/strspn.384
-rw-r--r--lib/libc/string/strspn.c71
-rw-r--r--lib/libc/string/strstr.3145
-rw-r--r--lib/libc/string/strstr.c61
-rw-r--r--lib/libc/string/strtok.3172
-rw-r--r--lib/libc/string/strtok.c136
-rw-r--r--lib/libc/string/strxfrm.396
-rw-r--r--lib/libc/string/strxfrm.c89
-rw-r--r--lib/libc/string/swab.367
-rw-r--r--lib/libc/string/swab.c61
-rw-r--r--lib/libc/string/wcpcpy.c46
-rw-r--r--lib/libc/string/wcpncpy.c45
-rw-r--r--lib/libc/string/wcscasecmp.c45
-rw-r--r--lib/libc/string/wcscat.c51
-rw-r--r--lib/libc/string/wcschr.c41
-rw-r--r--lib/libc/string/wcscmp.c56
-rw-r--r--lib/libc/string/wcscoll.3108
-rw-r--r--lib/libc/string/wcscoll.c112
-rw-r--r--lib/libc/string/wcscpy.c49
-rw-r--r--lib/libc/string/wcscspn.c58
-rw-r--r--lib/libc/string/wcsdup.c43
-rw-r--r--lib/libc/string/wcslcat.c74
-rw-r--r--lib/libc/string/wcslcpy.c70
-rw-r--r--lib/libc/string/wcslen.c49
-rw-r--r--lib/libc/string/wcsncasecmp.c49
-rw-r--r--lib/libc/string/wcsncat.c57
-rw-r--r--lib/libc/string/wcsncmp.c57
-rw-r--r--lib/libc/string/wcsncpy.c64
-rw-r--r--lib/libc/string/wcsnlen.c42
-rw-r--r--lib/libc/string/wcspbrk.c58
-rw-r--r--lib/libc/string/wcsrchr.c47
-rw-r--r--lib/libc/string/wcsspn.c60
-rw-r--r--lib/libc/string/wcsstr.c63
-rw-r--r--lib/libc/string/wcstok.3133
-rw-r--r--lib/libc/string/wcstok.c86
-rw-r--r--lib/libc/string/wcswidth.362
-rw-r--r--lib/libc/string/wcswidth.c69
-rw-r--r--lib/libc/string/wcsxfrm.3122
-rw-r--r--lib/libc/string/wcsxfrm.c129
-rw-r--r--lib/libc/string/wmemchr.3174
-rw-r--r--lib/libc/string/wmemchr.c52
-rw-r--r--lib/libc/string/wmemcmp.c53
-rw-r--r--lib/libc/string/wmemcpy.c44
-rw-r--r--lib/libc/string/wmemmove.c44
-rw-r--r--lib/libc/string/wmemset.c51
-rw-r--r--lib/libc/sys/Makefile.inc36
-rw-r--r--lib/libc/sys/Symbol.map25
-rw-r--r--lib/libc/sys/cap_enter.2102
-rw-r--r--lib/libc/sys/cap_new.2475
-rw-r--r--lib/libc/sys/chflags.229
-rw-r--r--lib/libc/sys/chmod.24
-rw-r--r--lib/libc/sys/chroot.220
-rw-r--r--lib/libc/sys/close.26
-rw-r--r--lib/libc/sys/cpuset.28
-rw-r--r--lib/libc/sys/cpuset_getaffinity.23
-rw-r--r--lib/libc/sys/dup.225
-rw-r--r--lib/libc/sys/fcntl.236
-rw-r--r--lib/libc/sys/ffclock.2177
-rw-r--r--lib/libc/sys/flock.24
-rw-r--r--lib/libc/sys/getdirentries.28
-rw-r--r--lib/libc/sys/getfh.26
-rw-r--r--lib/libc/sys/getgroups.212
-rw-r--r--lib/libc/sys/getloginclass.297
-rw-r--r--lib/libc/sys/getpriority.22
-rw-r--r--lib/libc/sys/getsockopt.237
-rw-r--r--lib/libc/sys/intro.22
-rw-r--r--lib/libc/sys/jail.210
-rw-r--r--lib/libc/sys/kill.28
-rw-r--r--lib/libc/sys/kldstat.210
-rw-r--r--lib/libc/sys/kqueue.215
-rw-r--r--lib/libc/sys/kse.22
-rw-r--r--lib/libc/sys/ktrace.244
-rw-r--r--lib/libc/sys/madvise.23
-rw-r--r--lib/libc/sys/mknod.24
-rw-r--r--lib/libc/sys/mmap.210
-rw-r--r--lib/libc/sys/mq_setattr.24
-rw-r--r--lib/libc/sys/msync.27
-rw-r--r--lib/libc/sys/nfssvc.24
-rw-r--r--lib/libc/sys/open.221
-rw-r--r--lib/libc/sys/pathconf.26
-rw-r--r--lib/libc/sys/pdfork.2183
-rw-r--r--lib/libc/sys/posix_fadvise.2138
-rw-r--r--lib/libc/sys/posix_fallocate.2145
-rw-r--r--lib/libc/sys/ptrace.258
-rw-r--r--lib/libc/sys/quotactl.24
-rw-r--r--lib/libc/sys/read.24
-rw-r--r--lib/libc/sys/rfork.234
-rw-r--r--lib/libc/sys/rtprio.298
-rw-r--r--lib/libc/sys/sctp_generic_sendmsg.24
-rw-r--r--lib/libc/sys/sctp_peeloff.23
-rw-r--r--lib/libc/sys/select.22
-rw-r--r--lib/libc/sys/sendfile.22
-rw-r--r--lib/libc/sys/setfib.227
-rw-r--r--lib/libc/sys/setuid.22
-rw-r--r--lib/libc/sys/shm_open.21
-rw-r--r--lib/libc/sys/shmat.21
-rw-r--r--lib/libc/sys/shmctl.21
-rw-r--r--lib/libc/sys/shmget.220
-rw-r--r--lib/libc/sys/sigqueue.23
-rw-r--r--lib/libc/sys/sigwait.210
-rw-r--r--lib/libc/sys/sigwaitinfo.212
-rw-r--r--lib/libc/sys/stat.210
-rw-r--r--lib/libc/sys/timer_create.22
-rw-r--r--lib/libc/sys/wait.213
-rw-r--r--lib/libc/sys/write.24
-rw-r--r--lib/libc/uuid/Makefile.inc24
-rw-r--r--lib/libc/uuid/Symbol.map21
-rw-r--r--lib/libc/uuid/uuid.3136
-rw-r--r--lib/libc/uuid/uuid_compare.c76
-rw-r--r--lib/libc/uuid/uuid_create.c45
-rw-r--r--lib/libc/uuid/uuid_create_nil.c46
-rw-r--r--lib/libc/uuid/uuid_equal.c55
-rw-r--r--lib/libc/uuid/uuid_from_string.c92
-rw-r--r--lib/libc/uuid/uuid_hash.c49
-rw-r--r--lib/libc/uuid/uuid_is_nil.c54
-rw-r--r--lib/libc/uuid/uuid_stream.c113
-rw-r--r--lib/libc/uuid/uuid_to_string.c67
-rw-r--r--lib/libc/xdr/Makefile.inc52
-rw-r--r--lib/libc/xdr/Symbol.map56
-rw-r--r--lib/libc/xdr/xdr.3847
-rw-r--r--lib/libc/xdr/xdr.c967
-rw-r--r--lib/libc/xdr/xdr_array.c163
-rw-r--r--lib/libc/xdr/xdr_float.c309
-rw-r--r--lib/libc/xdr/xdr_mem.c260
-rw-r--r--lib/libc/xdr/xdr_rec.c795
-rw-r--r--lib/libc/xdr/xdr_reference.c143
-rw-r--r--lib/libc/xdr/xdr_sizeof.c168
-rw-r--r--lib/libc/xdr/xdr_stdio.c196
-rw-r--r--lib/libc/yp/Makefile.inc19
-rw-r--r--lib/libc/yp/Symbol.map25
-rw-r--r--lib/libc/yp/xdryp.c125
-rw-r--r--lib/libc/yp/yplib.c1220
1895 files changed, 313713 insertions, 218 deletions
diff --git a/lib/libc/Makefile b/lib/libc/Makefile
new file mode 100644
index 0000000..2222384
--- /dev/null
+++ b/lib/libc/Makefile
@@ -0,0 +1,155 @@
+# @(#)Makefile 8.2 (Berkeley) 2/3/94
+# $FreeBSD$
+
+SHLIBDIR?= /lib
+
+.include <bsd.own.mk>
+
+# Pick the current architecture directory for libc. In general, this is
+# named MACHINE_CPUARCH, but some ABIs are different enough to require
+# their own libc, so allow a directory named MACHINE_ARCH to override this.
+
+.if exists(${.CURDIR}/${MACHINE_ARCH})
+LIBC_ARCH=${MACHINE_ARCH}
+.else
+LIBC_ARCH=${MACHINE_CPUARCH}
+.endif
+
+# All library objects contain FreeBSD revision strings by default; they may be
+# excluded as a space-saving measure. To produce a library that does
+# not contain these strings, add -DSTRIP_FBSDID (see <sys/cdefs.h>) to CFLAGS
+# below. Note: there are no IDs for syscall stubs whose sources are generated.
+# To include legacy CSRG sccsid strings, add -DLIBC_SCCS and -DSYSLIBC_SCCS
+# to CFLAGS below. -DSYSLIBC_SCCS affects just the system call stubs.
+LIB=c
+SHLIB_MAJOR= 7
+WARNS?= 2
+CFLAGS+=-I${.CURDIR}/include -I${.CURDIR}/../../include
+CFLAGS+=-I${.CURDIR}/${LIBC_ARCH}
+CFLAGS+=-DNLS
+CLEANFILES+=tags
+INSTALL_PIC_ARCHIVE=
+PRECIOUSLIB=
+
+.ifndef NO_THREAD_STACK_UNWIND
+CANCELPOINTS_CFLAGS=-fexceptions
+CFLAGS+=${CANCELPOINTS_CFLAGS}
+.endif
+
+#
+# Only link with static libgcc.a (no libgcc_eh.a).
+#
+DPADD+= ${LIBGCC}
+LDFLAGS+= -nodefaultlibs
+LDADD+= -lgcc -lssp_nonshared
+
+# Define (empty) variables so that make doesn't give substitution
+# errors if the included makefiles don't change these:
+MDSRCS=
+MISRCS=
+MDASM=
+MIASM=
+NOASM=
+
+.include "${.CURDIR}/${LIBC_ARCH}/Makefile.inc"
+.include "${.CURDIR}/db/Makefile.inc"
+.include "${.CURDIR}/compat-43/Makefile.inc"
+.include "${.CURDIR}/gdtoa/Makefile.inc"
+.include "${.CURDIR}/gen/Makefile.inc"
+.include "${.CURDIR}/gmon/Makefile.inc"
+.if ${MK_ICONV} != "no"
+.include "${.CURDIR}/iconv/Makefile.inc"
+.endif
+.include "${.CURDIR}/inet/Makefile.inc"
+.include "${.CURDIR}/isc/Makefile.inc"
+.include "${.CURDIR}/locale/Makefile.inc"
+.include "${.CURDIR}/nameser/Makefile.inc"
+.include "${.CURDIR}/net/Makefile.inc"
+.include "${.CURDIR}/nls/Makefile.inc"
+.include "${.CURDIR}/posix1e/Makefile.inc"
+.if ${LIBC_ARCH} != "amd64" && \
+ ${LIBC_ARCH} != "ia64" && \
+ ${LIBC_ARCH} != "powerpc64" && \
+ ${LIBC_ARCH} != "sparc64" && \
+ ${MACHINE_ARCH:Mmipsn32*} == "" && \
+ ${MACHINE_ARCH:Mmips64*} == ""
+.include "${.CURDIR}/quad/Makefile.inc"
+.endif
+.include "${.CURDIR}/regex/Makefile.inc"
+.include "${.CURDIR}/resolv/Makefile.inc"
+.include "${.CURDIR}/stdio/Makefile.inc"
+.include "${.CURDIR}/stdlib/Makefile.inc"
+.include "${.CURDIR}/stdlib/jemalloc/Makefile.inc"
+.include "${.CURDIR}/stdtime/Makefile.inc"
+.include "${.CURDIR}/string/Makefile.inc"
+.include "${.CURDIR}/sys/Makefile.inc"
+.include "${.CURDIR}/rpc/Makefile.inc"
+.include "${.CURDIR}/uuid/Makefile.inc"
+.include "${.CURDIR}/xdr/Makefile.inc"
+.if ${LIBC_ARCH} == "arm" || ${LIBC_ARCH} == "mips"
+.include "${.CURDIR}/softfloat/Makefile.inc"
+.endif
+.if ${MK_NIS} != "no"
+CFLAGS+= -DYP
+.include "${.CURDIR}/yp/Makefile.inc"
+.endif
+.if ${MK_HESIOD} != "no"
+CFLAGS+= -DHESIOD
+.endif
+.if ${MK_FP_LIBC} == "no"
+CFLAGS+= -DNO_FLOATING_POINT
+.endif
+.if ${MK_NS_CACHING} != "no"
+CFLAGS+= -DNS_CACHING
+.endif
+.if defined(_FREEFALL_CONFIG)
+CFLAGS+=-D_FREEFALL_CONFIG
+.endif
+
+VERSION_DEF=${.CURDIR}/Versions.def
+SYMBOL_MAPS=${SYM_MAPS}
+CFLAGS+= -DSYMBOL_VERSIONING
+
+# If there are no machine dependent sources, append all the
+# machine-independent sources:
+.if empty(MDSRCS)
+SRCS+= ${MISRCS}
+.else
+# Append machine-dependent sources, then append machine-independent sources
+# for which there is no machine-dependent variant.
+SRCS+= ${MDSRCS}
+.for _src in ${MISRCS}
+.if ${MDSRCS:R:M${_src:R}} == ""
+SRCS+= ${_src}
+.endif
+.endfor
+.endif
+
+KQSRCS= adddi3.c anddi3.c ashldi3.c ashrdi3.c cmpdi2.c divdi3.c iordi3.c \
+ lshldi3.c lshrdi3.c moddi3.c muldi3.c negdi2.c notdi2.c qdivrem.c \
+ subdi3.c ucmpdi2.c udivdi3.c umoddi3.c xordi3.c
+KSRCS= bcmp.c ffs.c ffsl.c fls.c flsl.c mcount.c strcat.c strchr.c \
+ strcmp.c strcpy.c strlen.c strncpy.c strrchr.c
+
+libkern: libkern.gen libkern.${LIBC_ARCH}
+
+libkern.gen: ${KQSRCS} ${KSRCS}
+ cp -p ${.CURDIR}/quad/quad.h ${.ALLSRC} ${DESTDIR}/sys/libkern
+
+libkern.${LIBC_ARCH}:: ${KMSRCS}
+.if defined(KMSRCS) && !empty(KMSRCS)
+ cp -p ${.ALLSRC} ${DESTDIR}/sys/libkern/${LIBC_ARCH}
+.endif
+
+.include <bsd.lib.mk>
+
+# Disable warnings in contributed sources.
+CWARNFLAGS:= ${.IMPSRC:Ngdtoa_*.c:C/^.+$/${CWARNFLAGS}/:C/^$/-w/}
+# XXX For now, we don't allow libc to be compiled with
+# -fstack-protector-all because it breaks rtld. We may want to make a librtld
+# in the future to circumvent this.
+SSP_CFLAGS:= ${SSP_CFLAGS:S/^-fstack-protector-all$/-fstack-protector/}
+# Disable stack protection for SSP symbols.
+SSP_CFLAGS:= ${.IMPSRC:N*/stack_protector.c:C/^.+$/${SSP_CFLAGS}/}
+# Generate stack unwinding tables for cancellation points
+CANCELPOINTS_CFLAGS:= ${.IMPSRC:Mcancelpoints_*:C/^.+$/${CANCELPOINTS_CFLAGS}/:C/^$//}
diff --git a/lib/libc/Versions.def b/lib/libc/Versions.def
new file mode 100644
index 0000000..bbd59a4
--- /dev/null
+++ b/lib/libc/Versions.def
@@ -0,0 +1,33 @@
+# $FreeBSD$
+
+#
+# Note: Whenever bumping the FBSD version, always make
+# FBSDprivate_1.0 depend on the new FBSD version.
+# This will keep it at the end of the dependency chain.
+#
+
+# This is our first version; it depends on no other.
+# This version was first added to 7.0-current.
+FBSD_1.0 {
+};
+
+# This version was first added to 8.0-current.
+FBSD_1.1 {
+} FBSD_1.0;
+
+# This version was first added to 9.0-current.
+FBSD_1.2 {
+} FBSD_1.1;
+
+# This version was first added to 10.0-current.
+FBSD_1.3 {
+} FBSD_1.2;
+
+# This is our private namespace. Any global interfaces that are
+# strictly for use only by other FreeBSD applications and libraries
+# are listed here. We use a separate namespace so we can write
+# simple ABI-checking tools.
+#
+# Please do NOT increment the version of this namespace.
+FBSDprivate_1.0 {
+} FBSD_1.3;
diff --git a/lib/libc/amd64/Makefile.inc b/lib/libc/amd64/Makefile.inc
new file mode 100644
index 0000000..e4c0900
--- /dev/null
+++ b/lib/libc/amd64/Makefile.inc
@@ -0,0 +1,9 @@
+# $FreeBSD$
+#
+# Machine dependent definitions for the amd64 architecture.
+#
+
+# Long double is 80 bits
+GDTOASRCS+=strtorx.c
+MDSRCS+=machdep_ldisx.c
+SYM_MAPS+=${.CURDIR}/amd64/Symbol.map
diff --git a/lib/libc/amd64/SYS.h b/lib/libc/amd64/SYS.h
new file mode 100644
index 0000000..61d7ab4
--- /dev/null
+++ b/lib/libc/amd64/SYS.h
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)SYS.h 5.5 (Berkeley) 5/7/91
+ * $FreeBSD$
+ */
+
+#include <sys/syscall.h>
+#include <machine/asm.h>
+
+#ifdef PIC
+#define RSYSCALL(x) ENTRY(__CONCAT(__sys_,x)); \
+ .weak CNAME(x); \
+ .set CNAME(x),CNAME(__CONCAT(__sys_,x)); \
+ .weak CNAME(__CONCAT(_,x)); \
+ .set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \
+ mov __CONCAT($SYS_,x),%rax; KERNCALL; jb 2f; ret; \
+ 2: movq PIC_GOT(HIDENAME(cerror)),%rcx; jmp *%rcx; \
+ END(__CONCAT(__sys_,x))
+
+#define PSEUDO(x) ENTRY(__CONCAT(__sys_,x)); \
+ .weak CNAME(__CONCAT(_,x)); \
+ .set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \
+ mov __CONCAT($SYS_,x),%rax; KERNCALL; jb 2f; ret ; \
+ 2: movq PIC_GOT(HIDENAME(cerror)),%rcx; jmp *%rcx; \
+ END(__CONCAT(__sys_,x))
+#else
+#define RSYSCALL(x) ENTRY(__CONCAT(__sys_,x)); \
+ .weak CNAME(x); \
+ .set CNAME(x),CNAME(__CONCAT(__sys_,x)); \
+ .weak CNAME(__CONCAT(_,x)); \
+ .set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \
+ mov __CONCAT($SYS_,x),%rax; KERNCALL; jb 2f; ret; \
+ 2: jmp HIDENAME(cerror); \
+ END(__CONCAT(__sys_,x))
+
+#define PSEUDO(x) ENTRY(__CONCAT(__sys_,x)); \
+ .weak CNAME(__CONCAT(_,x)); \
+ .set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \
+ mov __CONCAT($SYS_,x),%rax; KERNCALL; jb 2f; ret; \
+ 2: jmp HIDENAME(cerror); \
+ END(__CONCAT(__sys_,x))
+#endif
+
+#define KERNCALL movq %rcx, %r10; syscall
diff --git a/lib/libc/amd64/Symbol.map b/lib/libc/amd64/Symbol.map
new file mode 100644
index 0000000..9997cc2
--- /dev/null
+++ b/lib/libc/amd64/Symbol.map
@@ -0,0 +1,73 @@
+/*
+ * $FreeBSD$
+ */
+
+/*
+ * This only needs to contain symbols that are not listed in
+ * symbol maps from other parts of libc (i.e., not found in
+ * stdlib/Symbol.map, string/Symbol.map, sys/Symbol.map, ...).
+ */
+FBSD_1.0 {
+ /* PSEUDO syscalls */
+ _exit;
+
+ .mcount;
+ _setjmp;
+ _longjmp;
+ fabs;
+ __flt_rounds;
+ fpgetmask;
+ fpgetprec;
+ fpgetround;
+ fpgetsticky;
+ fpsetmask;
+ fpsetprec;
+ fpsetround;
+ __infinity;
+ __nan;
+ makecontext;
+ rfork_thread;
+ setjmp;
+ longjmp;
+ sigsetjmp;
+ siglongjmp;
+ htonl;
+ htons;
+ ntohl;
+ ntohs;
+ amd64_get_fsbase;
+ amd64_get_gsbase;
+ amd64_set_fsbase;
+ amd64_set_gsbase;
+ brk;
+ exect;
+ sbrk;
+ vfork;
+};
+
+/*
+ *
+ * FreeBSD private ABI
+ *
+ */
+FBSDprivate_1.0 {
+ /* PSEUDO syscalls */
+ __sys_getlogin;
+ _getlogin;
+ __sys_exit;
+
+ _set_tp;
+ ___longjmp;
+ __makecontext;
+ __longjmp;
+ __signalcontext;
+ signalcontext;
+ __siglongjmp;
+ .curbrk;
+ .minbrk;
+ _brk;
+ .cerror;
+ _end;
+ __sys_vfork;
+ _vfork;
+};
diff --git a/lib/libc/amd64/_fpmath.h b/lib/libc/amd64/_fpmath.h
new file mode 100644
index 0000000..c2a7384
--- /dev/null
+++ b/lib/libc/amd64/_fpmath.h
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+union IEEEl2bits {
+ long double e;
+ struct {
+ unsigned int manl :32;
+ unsigned int manh :32;
+ unsigned int exp :15;
+ unsigned int sign :1;
+ unsigned int junkl :16;
+ unsigned int junkh :32;
+ } bits;
+ struct {
+ unsigned long man :64;
+ unsigned int expsign :16;
+ unsigned long junk :48;
+ } xbits;
+};
+
+#define LDBL_NBIT 0x80000000
+#define mask_nbit_l(u) ((u).bits.manh &= ~LDBL_NBIT)
+
+#define LDBL_MANH_SIZE 32
+#define LDBL_MANL_SIZE 32
+
+#define LDBL_TO_ARRAY32(u, a) do { \
+ (a)[0] = (uint32_t)(u).bits.manl; \
+ (a)[1] = (uint32_t)(u).bits.manh; \
+} while (0)
diff --git a/lib/libc/amd64/arith.h b/lib/libc/amd64/arith.h
new file mode 100644
index 0000000..ecb1a33
--- /dev/null
+++ b/lib/libc/amd64/arith.h
@@ -0,0 +1,19 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * NOTE: The definitions in this file must be correct or strtod(3) and
+ * floating point formats in printf(3) will break! The file can be
+ * generated by running contrib/gdtoa/arithchk.c on the target
+ * architecture. See contrib/gdtoa/gdtoaimp.h for details.
+ */
+
+#define IEEE_8087
+#define Arith_Kind_ASL 1
+#define Long int
+#define Intcast (int)(long)
+#define Double_Align
+#define X64_bit_pointers
diff --git a/lib/libc/amd64/gd_qnan.h b/lib/libc/amd64/gd_qnan.h
new file mode 100644
index 0000000..3992386
--- /dev/null
+++ b/lib/libc/amd64/gd_qnan.h
@@ -0,0 +1,21 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * This file can be generated by compiling and running contrib/gdtoa/qnan.c
+ * on the target architecture after arith.h has been generated.
+ *
+ * $FreeBSD$
+ */
+
+#define f_QNAN 0x7fc00000
+#define d_QNAN0 0x0
+#define d_QNAN1 0x7ff80000
+#define ld_QNAN0 0x0
+#define ld_QNAN1 0xc0000000
+#define ld_QNAN2 0x7fff
+#define ld_QNAN3 0x0
+#define ldus_QNAN0 0x0
+#define ldus_QNAN1 0x0
+#define ldus_QNAN2 0x0
+#define ldus_QNAN3 0xc000
+#define ldus_QNAN4 0x7fff
diff --git a/lib/libc/amd64/gen/Makefile.inc b/lib/libc/amd64/gen/Makefile.inc
new file mode 100644
index 0000000..fb4f7f4
--- /dev/null
+++ b/lib/libc/amd64/gen/Makefile.inc
@@ -0,0 +1,8 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+SRCS+= _setjmp.S _set_tp.c rfork_thread.S setjmp.S sigsetjmp.S \
+ fabs.S getcontextx.c \
+ infinity.c ldexp.c makecontext.c signalcontext.c \
+ flt_rounds.c fpgetmask.c fpsetmask.c fpgetprec.c fpsetprec.c \
+ fpgetround.c fpsetround.c fpgetsticky.c
diff --git a/lib/libc/amd64/gen/_set_tp.c b/lib/libc/amd64/gen/_set_tp.c
new file mode 100644
index 0000000..02e5e14
--- /dev/null
+++ b/lib/libc/amd64/gen/_set_tp.c
@@ -0,0 +1,38 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <string.h>
+#include <stdint.h>
+#include <machine/sysarch.h>
+
+void
+_set_tp(void *tp)
+{
+
+ amd64_set_fsbase(tp);
+}
diff --git a/lib/libc/amd64/gen/_setjmp.S b/lib/libc/amd64/gen/_setjmp.S
new file mode 100644
index 0000000..9035632
--- /dev/null
+++ b/lib/libc/amd64/gen/_setjmp.S
@@ -0,0 +1,96 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ .asciz "@(#)_setjmp.s 5.1 (Berkeley) 4/23/90"
+#endif /* LIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * C library -- _setjmp, _longjmp
+ *
+ * _longjmp(a,v)
+ * will generate a "return(v)" from the last call to
+ * _setjmp(a)
+ * by restoring registers from the environment 'a'.
+ * The previous signal state is NOT restored.
+ */
+
+ENTRY(_setjmp)
+ movq %rdi,%rax
+ movq 0(%rsp),%rdx /* retval */
+ movq %rdx, 0(%rax) /* 0; retval */
+ movq %rbx, 8(%rax) /* 1; rbx */
+ movq %rsp,16(%rax) /* 2; rsp */
+ movq %rbp,24(%rax) /* 3; rbp */
+ movq %r12,32(%rax) /* 4; r12 */
+ movq %r13,40(%rax) /* 5; r13 */
+ movq %r14,48(%rax) /* 6; r14 */
+ movq %r15,56(%rax) /* 7; r15 */
+ fnstcw 64(%rax) /* 8; fpu cw */
+ stmxcsr 68(%rax) /* and mxcsr */
+ xorq %rax,%rax
+ ret
+END(_setjmp)
+
+ .weak CNAME(_longjmp)
+ .set CNAME(_longjmp),CNAME(___longjmp)
+ENTRY(___longjmp)
+ movq %rdi,%rdx
+ /* Restore the mxcsr, but leave exception flags intact. */
+ stmxcsr -4(%rsp)
+ movl 68(%rdx),%eax
+ andl $0xffffffc0,%eax
+ movl -4(%rsp),%edi
+ andl $0x3f,%edi
+ xorl %eax,%edi
+ movl %edi,-4(%rsp)
+ ldmxcsr -4(%rsp)
+ movq %rsi,%rax /* retval */
+ movq 0(%rdx),%rcx
+ movq 8(%rdx),%rbx
+ movq 16(%rdx),%rsp
+ movq 24(%rdx),%rbp
+ movq 32(%rdx),%r12
+ movq 40(%rdx),%r13
+ movq 48(%rdx),%r14
+ movq 56(%rdx),%r15
+ fldcw 64(%rdx)
+ testq %rax,%rax
+ jnz 1f
+ incq %rax
+1: movq %rcx,0(%rsp)
+ ret
+END(___longjmp)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/gen/fabs.S b/lib/libc/amd64/gen/fabs.S
new file mode 100644
index 0000000..2ace0f9
--- /dev/null
+++ b/lib/libc/amd64/gen/fabs.S
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2004 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Return floating point absolute value of a double.
+ */
+
+ .text
+ENTRY(fabs)
+ movsd %xmm0, %xmm1
+ movsd signbit(%rip), %xmm0
+ andnpd %xmm1, %xmm0
+ ret
+END(fabs)
+
+ .data
+signbit:
+ .quad 0x8000000000000000
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/gen/flt_rounds.c b/lib/libc/amd64/gen/flt_rounds.c
new file mode 100644
index 0000000..c0ce81f
--- /dev/null
+++ b/lib/libc/amd64/gen/flt_rounds.c
@@ -0,0 +1,26 @@
+/*
+ * Written by J.T. Conklin, Apr 10, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <float.h>
+
+static const int map[] = {
+ 1, /* round to nearest */
+ 3, /* round to zero */
+ 2, /* round to negative infinity */
+ 0 /* round to positive infinity */
+};
+
+int
+__flt_rounds(void)
+{
+ int x;
+
+ /* Assume that the x87 and the SSE unit agree on the rounding mode. */
+ __asm("fnstcw %0" : "=m" (x));
+ return (map[(x >> 10) & 0x03]);
+}
diff --git a/lib/libc/amd64/gen/fpgetmask.c b/lib/libc/amd64/gen/fpgetmask.c
new file mode 100644
index 0000000..03bb274
--- /dev/null
+++ b/lib/libc/amd64/gen/fpgetmask.c
@@ -0,0 +1,8 @@
+/* $FreeBSD$ */
+#define __IEEEFP_NOINLINES__ 1
+#include <ieeefp.h>
+
+fp_except_t fpgetmask(void)
+{
+ return __fpgetmask();
+}
diff --git a/lib/libc/amd64/gen/fpgetprec.c b/lib/libc/amd64/gen/fpgetprec.c
new file mode 100644
index 0000000..22d2148
--- /dev/null
+++ b/lib/libc/amd64/gen/fpgetprec.c
@@ -0,0 +1,8 @@
+/* $FreeBSD$ */
+#define __IEEEFP_NOINLINES__ 1
+#include <ieeefp.h>
+
+fp_prec_t fpgetprec(void)
+{
+ return __fpgetprec();
+}
diff --git a/lib/libc/amd64/gen/fpgetround.c b/lib/libc/amd64/gen/fpgetround.c
new file mode 100644
index 0000000..9c066b1
--- /dev/null
+++ b/lib/libc/amd64/gen/fpgetround.c
@@ -0,0 +1,8 @@
+/* $FreeBSD$ */
+#define __IEEEFP_NOINLINES__ 1
+#include <ieeefp.h>
+
+fp_rnd_t fpgetround(void)
+{
+ return __fpgetround();
+}
diff --git a/lib/libc/amd64/gen/fpgetsticky.c b/lib/libc/amd64/gen/fpgetsticky.c
new file mode 100644
index 0000000..c3acb91
--- /dev/null
+++ b/lib/libc/amd64/gen/fpgetsticky.c
@@ -0,0 +1,8 @@
+/* $FreeBSD$ */
+#define __IEEEFP_NOINLINES__ 1
+#include <ieeefp.h>
+
+fp_except_t fpgetsticky(void)
+{
+ return __fpgetsticky();
+}
diff --git a/lib/libc/amd64/gen/fpsetmask.c b/lib/libc/amd64/gen/fpsetmask.c
new file mode 100644
index 0000000..996e167
--- /dev/null
+++ b/lib/libc/amd64/gen/fpsetmask.c
@@ -0,0 +1,8 @@
+/* $FreeBSD$ */
+#define __IEEEFP_NOINLINES__ 1
+#include <ieeefp.h>
+
+fp_except_t fpsetmask(fp_except_t m)
+{
+ return (__fpsetmask(m));
+}
diff --git a/lib/libc/amd64/gen/fpsetprec.c b/lib/libc/amd64/gen/fpsetprec.c
new file mode 100644
index 0000000..5898de7
--- /dev/null
+++ b/lib/libc/amd64/gen/fpsetprec.c
@@ -0,0 +1,8 @@
+/* $FreeBSD$ */
+#define __IEEEFP_NOINLINES__ 1
+#include <ieeefp.h>
+
+fp_prec_t fpsetprec(fp_prec_t m)
+{
+ return (__fpsetprec(m));
+}
diff --git a/lib/libc/amd64/gen/fpsetround.c b/lib/libc/amd64/gen/fpsetround.c
new file mode 100644
index 0000000..6f13367
--- /dev/null
+++ b/lib/libc/amd64/gen/fpsetround.c
@@ -0,0 +1,8 @@
+/* $FreeBSD$ */
+#define __IEEEFP_NOINLINES__ 1
+#include <ieeefp.h>
+
+fp_rnd_t fpsetround(fp_rnd_t m)
+{
+ return (__fpsetround(m));
+}
diff --git a/lib/libc/amd64/gen/getcontextx.c b/lib/libc/amd64/gen/getcontextx.c
new file mode 100644
index 0000000..7412560
--- /dev/null
+++ b/lib/libc/amd64/gen/getcontextx.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2011 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <machine/cpufunc.h>
+#include <machine/fpu.h>
+#include <machine/specialreg.h>
+#include <machine/sysarch.h>
+
+static int xstate_sz = -1;
+
+int
+__getcontextx_size(void)
+{
+ u_int p[4];
+
+ if (xstate_sz == -1) {
+ do_cpuid(1, p);
+ if ((p[2] & CPUID2_OSXSAVE) != 0) {
+ cpuid_count(0xd, 0x0, p);
+ xstate_sz = p[1] - sizeof(struct savefpu);
+ } else
+ xstate_sz = 0;
+ }
+
+ return (sizeof(ucontext_t) + xstate_sz);
+}
+
+int
+__fillcontextx(char *ctx)
+{
+ struct amd64_get_xfpustate xfpu;
+ ucontext_t *ucp;
+
+ ucp = (ucontext_t *)ctx;
+ if (getcontext(ucp) == -1)
+ return (-1);
+ if (xstate_sz != 0) {
+ xfpu.addr = (char *)(ucp + 1);
+ xfpu.len = xstate_sz;
+ if (sysarch(AMD64_GET_XFPUSTATE, &xfpu) == -1)
+ return (-1);
+ ucp->uc_mcontext.mc_xfpustate = (__register_t)xfpu.addr;
+ ucp->uc_mcontext.mc_xfpustate_len = xstate_sz;
+ ucp->uc_mcontext.mc_flags |= _MC_HASFPXSTATE;
+ } else {
+ ucp->uc_mcontext.mc_xfpustate = 0;
+ ucp->uc_mcontext.mc_xfpustate_len = 0;
+ }
+ return (0);
+}
+
+__weak_reference(__getcontextx, getcontextx);
+
+ucontext_t *
+__getcontextx(void)
+{
+ char *ctx;
+ int error;
+
+ ctx = malloc(__getcontextx_size());
+ if (ctx == NULL)
+ return (NULL);
+ if (__fillcontextx(ctx) == -1) {
+ error = errno;
+ free(ctx);
+ errno = error;
+ return (NULL);
+ }
+ return ((ucontext_t *)ctx);
+}
diff --git a/lib/libc/amd64/gen/infinity.c b/lib/libc/amd64/gen/infinity.c
new file mode 100644
index 0000000..464b402
--- /dev/null
+++ b/lib/libc/amd64/gen/infinity.c
@@ -0,0 +1,14 @@
+/*
+ * infinity.c
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <math.h>
+
+/* bytes for +Infinity on a 387 */
+const union __infinity_un __infinity = { { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } };
+
+/* bytes for NaN */
+const union __nan_un __nan = { { 0, 0, 0xc0, 0xff } };
diff --git a/lib/libc/amd64/gen/makecontext.c b/lib/libc/amd64/gen/makecontext.c
new file mode 100644
index 0000000..15f10b5
--- /dev/null
+++ b/lib/libc/amd64/gen/makecontext.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+typedef void (*func_t)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
+ uint64_t);
+
+/* Prototypes */
+static void makectx_wrapper(ucontext_t *ucp, func_t func, uint64_t *args);
+
+__weak_reference(__makecontext, makecontext);
+
+void
+__makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...)
+{
+ uint64_t *args;
+ uint64_t *sp;
+ va_list ap;
+ int i;
+
+ /* A valid context is required. */
+ if ((ucp == NULL) || (ucp->uc_mcontext.mc_len != sizeof(mcontext_t)))
+ return;
+ else if ((argc < 0) || (argc > 6) || (ucp->uc_stack.ss_sp == NULL) ||
+ (ucp->uc_stack.ss_size < MINSIGSTKSZ)) {
+ /*
+ * This should really return -1 with errno set to ENOMEM
+ * or something, but the spec says that makecontext is
+ * a void function. At least make sure that the context
+ * isn't valid so it can't be used without an error.
+ */
+ ucp->uc_mcontext.mc_len = 0;
+ return;
+ }
+
+ /* Align the stack to 16 bytes. */
+ sp = (uint64_t *)(ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
+ sp = (uint64_t *)((uint64_t)sp & ~15UL);
+
+ /* Allocate space for a maximum of 6 arguments on the stack. */
+ args = sp - 6;
+
+ /*
+ * Account for arguments on stack and do the funky C entry alignment.
+ * This means that we need an 8-byte-odd alignment since the ABI expects
+ * the return address to be pushed, thus breaking the 16 byte alignment.
+ */
+ sp -= 7;
+
+ /* Add the arguments: */
+ va_start(ap, argc);
+ for (i = 0; i < argc; i++)
+ args[i] = va_arg(ap, uint64_t);
+ va_end(ap);
+ for (i = argc; i < 6; i++)
+ args[i] = 0;
+
+ ucp->uc_mcontext.mc_rdi = (register_t)ucp;
+ ucp->uc_mcontext.mc_rsi = (register_t)start;
+ ucp->uc_mcontext.mc_rdx = (register_t)args;
+ ucp->uc_mcontext.mc_rbp = 0;
+ ucp->uc_mcontext.mc_rbx = (register_t)sp;
+ ucp->uc_mcontext.mc_rsp = (register_t)sp;
+ ucp->uc_mcontext.mc_rip = (register_t)makectx_wrapper;
+}
+
+static void
+makectx_wrapper(ucontext_t *ucp, func_t func, uint64_t *args)
+{
+ (*func)(args[0], args[1], args[2], args[3], args[4], args[5]);
+ if (ucp->uc_link == NULL)
+ exit(0);
+ setcontext((const ucontext_t *)ucp->uc_link);
+ /* should never get here */
+ abort();
+ /* NOTREACHED */
+}
diff --git a/lib/libc/amd64/gen/rfork_thread.S b/lib/libc/amd64/gen/rfork_thread.S
new file mode 100644
index 0000000..9720e08
--- /dev/null
+++ b/lib/libc/amd64/gen/rfork_thread.S
@@ -0,0 +1,104 @@
+/*-
+ * Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org>
+ * Copyright (c) 2003 Alan L. Cox <alc@cs.rice.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * With thanks to John Dyson for the original version of this.
+ */
+
+#include <SYS.h>
+
+/*
+ * %edi %rsi %rdx %rcx
+ * rfork_thread(flags, stack_addr, start_fnc, start_arg);
+ *
+ * flags: Flags to rfork system call. See rfork(2).
+ * stack_addr: Top of stack for thread.
+ * start_fnc: Address of thread function to call in child.
+ * start_arg: Argument to pass to the thread function in child.
+ */
+
+ENTRY(rfork_thread)
+ pushq %rbx
+ pushq %r12
+ movq %rdx, %rbx
+ movq %rcx, %r12
+
+ /*
+ * Prepare and execute the thread creation syscall
+ */
+ movq $SYS_rfork, %rax
+ KERNCALL
+ jb 2f
+
+ /*
+ * Check to see if we are in the parent or child
+ */
+ cmpl $0, %edx
+ jnz 1f
+ popq %r12
+ popq %rbx
+ ret
+
+ /*
+ * If we are in the child (new thread), then
+ * set-up the call to the internal subroutine. If it
+ * returns, then call __exit.
+ */
+1:
+ movq %rsi, %rsp
+ movq %r12, %rdi
+ call *%rbx
+ movl %eax, %edi
+
+ /*
+ * Exit system call
+ */
+#ifdef SYS_exit
+ movq $SYS_exit, %rax
+#else
+ movq $SYS_sys_exit, %rax
+#endif
+ KERNCALL
+
+ /*
+ * Branch here if the thread creation fails:
+ */
+2:
+ popq %r12
+ popq %rbx
+#ifdef PIC
+ movq PIC_GOT(HIDENAME(cerror)), %rdx
+ jmp *%rdx
+#else
+ jmp HIDENAME(cerror)
+#endif
+END(rfork_thread)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/gen/setjmp.S b/lib/libc/amd64/gen/setjmp.S
new file mode 100644
index 0000000..47772be
--- /dev/null
+++ b/lib/libc/amd64/gen/setjmp.S
@@ -0,0 +1,117 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ .asciz "@(#)setjmp.s 5.1 (Berkeley) 4/23/90"
+#endif /* LIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * C library -- _setjmp, _longjmp
+ *
+ * longjmp(a,v)
+ * will generate a "return(v)" from the last call to
+ * setjmp(a)
+ * by restoring registers from the environment 'a'.
+ * The previous signal state is restored.
+ */
+
+#include "SYS.h"
+
+ENTRY(setjmp)
+ pushq %rdi
+ movq %rdi,%rcx
+ movq $1,%rdi /* SIG_BLOCK */
+ movq $0,%rsi /* (sigset_t*)set */
+ leaq 72(%rcx),%rdx /* 9,10; (sigset_t*)oset */
+ /* stack is 16-byte aligned */
+ call PIC_PLT(CNAME(_sigprocmask))
+ popq %rdi
+ movq %rdi,%rcx
+ movq 0(%rsp),%rdx /* retval */
+ movq %rdx, 0(%rcx) /* 0; retval */
+ movq %rbx, 8(%rcx) /* 1; rbx */
+ movq %rsp,16(%rcx) /* 2; rsp */
+ movq %rbp,24(%rcx) /* 3; rbp */
+ movq %r12,32(%rcx) /* 4; r12 */
+ movq %r13,40(%rcx) /* 5; r13 */
+ movq %r14,48(%rcx) /* 6; r14 */
+ movq %r15,56(%rcx) /* 7; r15 */
+ fnstcw 64(%rcx) /* 8; fpu cw */
+ stmxcsr 68(%rcx) /* and mxcsr */
+ xorq %rax,%rax
+ ret
+END(setjmp)
+
+ .weak CNAME(longjmp)
+ .set CNAME(longjmp),CNAME(__longjmp)
+ENTRY(__longjmp)
+ pushq %rdi
+ pushq %rsi
+ movq %rdi,%rdx
+ movq $3,%rdi /* SIG_SETMASK */
+ leaq 72(%rdx),%rsi /* (sigset_t*)set */
+ movq $0,%rdx /* (sigset_t*)oset */
+ subq $0x8,%rsp /* make the stack 16-byte aligned */
+ call PIC_PLT(CNAME(_sigprocmask))
+ addq $0x8,%rsp
+ popq %rsi
+ popq %rdi /* jmpbuf */
+ movq %rdi,%rdx
+ /* Restore the mxcsr, but leave exception flags intact. */
+ stmxcsr -4(%rsp)
+ movl 68(%rdx),%eax
+ andl $0xffffffc0,%eax
+ movl -4(%rsp),%edi
+ andl $0x3f,%edi
+ xorl %eax,%edi
+ movl %edi,-4(%rsp)
+ ldmxcsr -4(%rsp)
+ movq %rsi,%rax /* retval */
+ movq 0(%rdx),%rcx
+ movq 8(%rdx),%rbx
+ movq 16(%rdx),%rsp
+ movq 24(%rdx),%rbp
+ movq 32(%rdx),%r12
+ movq 40(%rdx),%r13
+ movq 48(%rdx),%r14
+ movq 56(%rdx),%r15
+ fldcw 64(%rdx)
+ testq %rax,%rax
+ jnz 1f
+ incq %rax
+1: movq %rcx,0(%rsp)
+ ret
+END(__longjmp)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/gen/signalcontext.c b/lib/libc/amd64/gen/signalcontext.c
new file mode 100644
index 0000000..1a2621a
--- /dev/null
+++ b/lib/libc/amd64/gen/signalcontext.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <strings.h>
+
+typedef void (*handler_t)(uint64_t, uint64_t, uint64_t);
+
+/* Prototypes */
+static void sigctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args);
+
+__weak_reference(__signalcontext, signalcontext);
+
+int
+__signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func)
+{
+ uint64_t *args;
+ siginfo_t *sig_si;
+ ucontext_t *sig_uc;
+ uint64_t sp;
+
+ /* Bail out if we don't have a valid ucontext pointer. */
+ if (ucp == NULL)
+ abort();
+
+ /*
+ * Build a signal frame and copy the arguments of signal handler
+ * 'func' onto the stack and do the funky stack alignment.
+ * This means that we need an 8-byte-odd alignment since the ABI expects
+ * the return address to be pushed, thus breaking the 16 byte alignment.
+ */
+ sp = (ucp->uc_mcontext.mc_rsp - 128 - sizeof(ucontext_t)) & ~15UL;
+ sig_uc = (ucontext_t *)sp;
+ bcopy(ucp, sig_uc, sizeof(*sig_uc));
+ sp = (sp - sizeof(siginfo_t)) & ~15UL;
+ sig_si = (siginfo_t *)sp;
+ bzero(sig_si, sizeof(*sig_si));
+ sig_si->si_signo = sig;
+ sp -= 3 * sizeof(uint64_t);
+ args = (uint64_t *)sp;
+ args[0] = sig;
+ args[1] = (intptr_t)sig_si;
+ args[2] = (intptr_t)sig_uc;
+ sp -= 16;
+
+ /*
+ * Setup the ucontext of the signal handler.
+ */
+ bzero(&ucp->uc_mcontext, sizeof(ucp->uc_mcontext));
+ ucp->uc_mcontext.mc_fpformat = _MC_FPFMT_NODEV;
+ ucp->uc_mcontext.mc_ownedfp = _MC_FPOWNED_NONE;
+ ucp->uc_link = sig_uc;
+ sigdelset(&ucp->uc_sigmask, sig);
+
+ ucp->uc_mcontext.mc_len = sizeof(mcontext_t);
+ ucp->uc_mcontext.mc_rdi = (register_t)ucp;
+ ucp->uc_mcontext.mc_rsi = (register_t)func;
+ ucp->uc_mcontext.mc_rdx = (register_t)args;
+ ucp->uc_mcontext.mc_rbp = (register_t)sp;
+ ucp->uc_mcontext.mc_rbx = (register_t)sp;
+ ucp->uc_mcontext.mc_rsp = (register_t)sp;
+ ucp->uc_mcontext.mc_rip = (register_t)sigctx_wrapper;
+ return (0);
+}
+
+static void
+sigctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args)
+{
+
+ (*func)(args[0], args[1], args[2]);
+ if (ucp->uc_link == NULL)
+ exit(0);
+ setcontext((const ucontext_t *)ucp->uc_link);
+ /* should never get here */
+ abort();
+ /* NOTREACHED */
+}
diff --git a/lib/libc/amd64/gen/sigsetjmp.S b/lib/libc/amd64/gen/sigsetjmp.S
new file mode 100644
index 0000000..ef90bc6
--- /dev/null
+++ b/lib/libc/amd64/gen/sigsetjmp.S
@@ -0,0 +1,118 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)setjmp.s 5.1 (Berkeley) 4/23/90"
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ .text
+ .asciz "$Id: sigsetjmp.S,v 1.1 1993/12/05 13:01:05 ats Exp $"
+#endif /* LIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+/*-
+ * TODO:
+ * Rename sigsetjmp to __sigsetjmp and siglongjmp to __siglongjmp,
+ * remove the other *jmp functions and define everything in terms
+ * of the renamed functions. This requires compiler support for
+ * the renamed functions (introduced in gcc-2.5.3; previous versions
+ * only supported *jmp with 0 or 1 leading underscores).
+ *
+ * Restore _all_ the registers and the signal mask atomically. Can
+ * use sigreturn() if sigreturn() works.
+ */
+
+ENTRY(sigsetjmp)
+ movl %esi,88(%rdi) /* 11; savemask */
+ testl %esi,%esi
+ jz 2f
+ pushq %rdi
+ movq %rdi,%rcx
+ movq $1,%rdi /* SIG_BLOCK */
+ movq $0,%rsi /* (sigset_t*)set */
+ leaq 72(%rcx),%rdx /* 9,10 (sigset_t*)oset */
+ /* stack is 16-byte aligned */
+ call PIC_PLT(CNAME(_sigprocmask))
+ popq %rdi
+2: movq %rdi,%rcx
+ movq 0(%rsp),%rdx /* retval */
+ movq %rdx, 0(%rcx) /* 0; retval */
+ movq %rbx, 8(%rcx) /* 1; rbx */
+ movq %rsp,16(%rcx) /* 2; rsp */
+ movq %rbp,24(%rcx) /* 3; rbp */
+ movq %r12,32(%rcx) /* 4; r12 */
+ movq %r13,40(%rcx) /* 5; r13 */
+ movq %r14,48(%rcx) /* 6; r14 */
+ movq %r15,56(%rcx) /* 7; r15 */
+ fnstcw 64(%rcx) /* 8; fpu cw */
+ xorq %rax,%rax
+ ret
+END(sigsetjmp)
+
+ .weak CNAME(siglongjmp)
+ .set CNAME(siglongjmp),CNAME(__siglongjmp)
+ENTRY(__siglongjmp)
+ cmpl $0,88(%rdi)
+ jz 2f
+ movq %rdi,%rdx
+ pushq %rdi
+ pushq %rsi
+ movq $3,%rdi /* SIG_SETMASK */
+ leaq 72(%rdx),%rsi /* (sigset_t*)set */
+ movq $0,%rdx /* (sigset_t*)oset */
+ subq $0x8,%rsp /* make the stack 16-byte aligned */
+ call PIC_PLT(CNAME(_sigprocmask))
+ addq $0x8,%rsp
+ popq %rsi
+ popq %rdi /* jmpbuf */
+2: movq %rdi,%rdx
+ movq %rsi,%rax /* retval */
+ movq 0(%rdx),%rcx
+ movq 8(%rdx),%rbx
+ movq 16(%rdx),%rsp
+ movq 24(%rdx),%rbp
+ movq 32(%rdx),%r12
+ movq 40(%rdx),%r13
+ movq 48(%rdx),%r14
+ movq 56(%rdx),%r15
+ fninit
+ fldcw 64(%rdx)
+ testq %rax,%rax
+ jnz 1f
+ incq %rax
+1: movq %rcx,0(%rsp)
+ ret
+END(__siglongjmp)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/stdlib/Makefile.inc b/lib/libc/amd64/stdlib/Makefile.inc
new file mode 100644
index 0000000..5b7e675
--- /dev/null
+++ b/lib/libc/amd64/stdlib/Makefile.inc
@@ -0,0 +1,4 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+MDSRCS+=div.S ldiv.S lldiv.S
diff --git a/lib/libc/amd64/stdlib/div.S b/lib/libc/amd64/stdlib/div.S
new file mode 100644
index 0000000..366010c
--- /dev/null
+++ b/lib/libc/amd64/stdlib/div.S
@@ -0,0 +1,20 @@
+/* $NetBSD: div.S,v 1.1 2001/06/19 00:25:04 fvdl Exp $ */
+
+/*-
+ * Written by Frank van der Linden (fvdl@wasabisystems.com)
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(div)
+ movl %edi,%eax
+ cltd
+ idivl %esi
+ salq $32,%rdx
+ orq %rdx,%rax
+ ret
+END(div)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/stdlib/ldiv.S b/lib/libc/amd64/stdlib/ldiv.S
new file mode 100644
index 0000000..f11472c
--- /dev/null
+++ b/lib/libc/amd64/stdlib/ldiv.S
@@ -0,0 +1,18 @@
+/* $NetBSD: ldiv.S,v 1.1 2001/06/19 00:25:04 fvdl Exp $ */
+
+/*-
+ * Written by gcc 3.0.
+ * Copy/pasted by Frank van der Linden (fvdl@wasabisystems.com)
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(ldiv)
+ movq %rdi,%rax
+ cqto
+ idivq %rsi
+ ret
+END(ldiv)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/stdlib/lldiv.S b/lib/libc/amd64/stdlib/lldiv.S
new file mode 100644
index 0000000..4dab0fd
--- /dev/null
+++ b/lib/libc/amd64/stdlib/lldiv.S
@@ -0,0 +1,18 @@
+/* $NetBSD: ldiv.S,v 1.1 2001/06/19 00:25:04 fvdl Exp $ */
+
+/*-
+ * Written by gcc 3.0.
+ * Copy/pasted by Frank van der Linden (fvdl@wasabisystems.com)
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(lldiv)
+ movq %rdi,%rax
+ cqto
+ idivq %rsi
+ ret
+END(lldiv)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/string/Makefile.inc b/lib/libc/amd64/string/Makefile.inc
new file mode 100644
index 0000000..46571ab
--- /dev/null
+++ b/lib/libc/amd64/string/Makefile.inc
@@ -0,0 +1,4 @@
+# $FreeBSD$
+
+MDSRCS+= bcmp.S bcopy.S bzero.S memcmp.S memcpy.S memmove.S memset.S \
+ strcat.S strcmp.S stpcpy.S strcpy.c
diff --git a/lib/libc/amd64/string/bcmp.S b/lib/libc/amd64/string/bcmp.S
new file mode 100644
index 0000000..d01b76b
--- /dev/null
+++ b/lib/libc/amd64/string/bcmp.S
@@ -0,0 +1,27 @@
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if 0
+ RCSID("$NetBSD: bcmp.S,v 1.1 2001/06/19 00:25:04 fvdl Exp $")
+#endif
+
+ENTRY(bcmp)
+ cld /* set compare direction forward */
+
+ movq %rdx,%rcx /* compare by words */
+ shrq $3,%rcx
+ repe
+ cmpsq
+ jne L1
+
+ movq %rdx,%rcx /* compare remainder by bytes */
+ andq $7,%rcx
+ repe
+ cmpsb
+L1:
+ setne %al
+ movsbl %al,%eax
+ ret
+END(bcmp)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/string/bcopy.S b/lib/libc/amd64/string/bcopy.S
new file mode 100644
index 0000000..cc38f47
--- /dev/null
+++ b/lib/libc/amd64/string/bcopy.S
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from locore.s.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if 0
+ RCSID("$NetBSD: bcopy.S,v 1.2 2003/08/07 16:42:36 agc Exp $")
+#endif
+
+ /*
+ * (ov)bcopy (src,dst,cnt)
+ * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
+ */
+
+#ifdef MEMCOPY
+ENTRY(memcpy)
+#else
+#ifdef MEMMOVE
+ENTRY(memmove)
+#else
+ENTRY(bcopy)
+#endif
+#endif
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ movq %rdi,%rax /* return dst */
+#else
+ xchgq %rdi,%rsi
+#endif
+ movq %rdx,%rcx
+ movq %rdi,%r8
+ subq %rsi,%r8
+ cmpq %rcx,%r8 /* overlapping? */
+ jb 1f
+ cld /* nope, copy forwards. */
+ shrq $3,%rcx /* copy by words */
+ rep
+ movsq
+ movq %rdx,%rcx
+ andq $7,%rcx /* any bytes left? */
+ rep
+ movsb
+ ret
+1:
+ addq %rcx,%rdi /* copy backwards. */
+ addq %rcx,%rsi
+ std
+ andq $7,%rcx /* any fractional bytes? */
+ decq %rdi
+ decq %rsi
+ rep
+ movsb
+ movq %rdx,%rcx /* copy remainder by words */
+ shrq $3,%rcx
+ subq $7,%rsi
+ subq $7,%rdi
+ rep
+ movsq
+ cld
+ ret
+#ifdef MEMCOPY
+END(memcpy)
+#else
+#ifdef MEMMOVE
+END(memmove)
+#else
+END(bcopy)
+#endif
+#endif
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/string/bzero.S b/lib/libc/amd64/string/bzero.S
new file mode 100644
index 0000000..cf46a2a
--- /dev/null
+++ b/lib/libc/amd64/string/bzero.S
@@ -0,0 +1,46 @@
+/*
+ * Written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if 0
+ RCSID("$NetBSD: bzero.S,v 1.2 2003/07/26 19:24:38 salo Exp $")
+#endif
+
+ENTRY(bzero)
+ cld /* set fill direction forward */
+ xorq %rax,%rax /* set fill data to 0 */
+
+ /*
+ * if the string is too short, it's really not worth the overhead
+ * of aligning to word boundries, etc. So we jump to a plain
+ * unaligned set.
+ */
+ cmpq $16,%rsi
+ jb L1
+
+ movq %rdi,%rcx /* compute misalignment */
+ negq %rcx
+ andq $7,%rcx
+ subq %rcx,%rsi
+ rep /* zero until word aligned */
+ stosb
+
+ movq %rsi,%rcx /* zero by words */
+ shrq $3,%rcx
+ andq $7,%rsi
+ rep
+ stosq
+
+L1: movq %rsi,%rcx /* zero remainder by bytes */
+ rep
+ stosb
+
+ ret
+END(bzero)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/string/memcmp.S b/lib/libc/amd64/string/memcmp.S
new file mode 100644
index 0000000..66d64a0
--- /dev/null
+++ b/lib/libc/amd64/string/memcmp.S
@@ -0,0 +1,44 @@
+/*
+ * Written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if 0
+ RCSID("$NetBSD: memcmp.S,v 1.2 2003/07/26 19:24:39 salo Exp $")
+#endif
+
+ENTRY(memcmp)
+ cld /* set compare direction forward */
+ movq %rdx,%rcx /* compare by longs */
+ shrq $3,%rcx
+ repe
+ cmpsq
+ jne L5 /* do we match so far? */
+
+ movq %rdx,%rcx /* compare remainder by bytes */
+ andq $7,%rcx
+ repe
+ cmpsb
+ jne L6 /* do we match? */
+
+ xorl %eax,%eax /* we match, return zero */
+ ret
+
+L5: movl $8,%ecx /* We know that one of the next */
+ subq %rcx,%rdi /* eight pairs of bytes do not */
+ subq %rcx,%rsi /* match. */
+ repe
+ cmpsb
+L6: xorl %eax,%eax /* Perform unsigned comparison */
+ movb -1(%rdi),%al
+ xorl %edx,%edx
+ movb -1(%rsi),%dl
+ subl %edx,%eax
+ ret
+END(memcmp)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/string/memcpy.S b/lib/libc/amd64/string/memcpy.S
new file mode 100644
index 0000000..bd1e842
--- /dev/null
+++ b/lib/libc/amd64/string/memcpy.S
@@ -0,0 +1,5 @@
+/* $NetBSD: memcpy.S,v 1.1 2001/06/19 00:25:05 fvdl Exp $ */
+/* $FreeBSD$ */
+
+#define MEMCOPY
+#include "bcopy.S"
diff --git a/lib/libc/amd64/string/memmove.S b/lib/libc/amd64/string/memmove.S
new file mode 100644
index 0000000..85beb26
--- /dev/null
+++ b/lib/libc/amd64/string/memmove.S
@@ -0,0 +1,5 @@
+/* $NetBSD: memmove.S,v 1.1 2001/06/19 00:25:05 fvdl Exp $ */
+/* $FreeBSD$ */
+
+#define MEMMOVE
+#include "bcopy.S"
diff --git a/lib/libc/amd64/string/memset.S b/lib/libc/amd64/string/memset.S
new file mode 100644
index 0000000..84d1562
--- /dev/null
+++ b/lib/libc/amd64/string/memset.S
@@ -0,0 +1,63 @@
+/*
+ * Written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ * Adapted for NetBSD/x86_64 by Frank van der Linden <fvdl@wasabisystems.com>
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if 0
+ RCSID("$NetBSD: memset.S,v 1.3 2004/02/26 20:50:06 drochner Exp $")
+#endif
+
+ENTRY(memset)
+ movq %rsi,%rax
+ andq $0xff,%rax
+ movq %rdx,%rcx
+ movq %rdi,%r11
+
+ cld /* set fill direction forward */
+
+ /*
+ * if the string is too short, it's really not worth the overhead
+ * of aligning to word boundries, etc. So we jump to a plain
+ * unaligned set.
+ */
+ cmpq $0x0f,%rcx
+ jle L1
+
+ movb %al,%ah /* copy char to all bytes in word */
+ movl %eax,%edx
+ sall $16,%eax
+ orl %edx,%eax
+
+ movl %eax,%edx
+ salq $32,%rax
+ orq %rdx,%rax
+
+ movq %rdi,%rdx /* compute misalignment */
+ negq %rdx
+ andq $7,%rdx
+ movq %rcx,%r8
+ subq %rdx,%r8
+
+ movq %rdx,%rcx /* set until word aligned */
+ rep
+ stosb
+
+ movq %r8,%rcx
+ shrq $3,%rcx /* set by words */
+ rep
+ stosq
+
+ movq %r8,%rcx /* set remainder by bytes */
+ andq $7,%rcx
+L1: rep
+ stosb
+ movq %r11,%rax
+
+ ret
+END(memset)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/string/stpcpy.S b/lib/libc/amd64/string/stpcpy.S
new file mode 100644
index 0000000..52ac69c
--- /dev/null
+++ b/lib/libc/amd64/string/stpcpy.S
@@ -0,0 +1,116 @@
+/*
+ * Adapted by Guillaume Morin <guillaume@morinfr.org> from strcpy.S
+ * written by J.T. Conklin <jtc@acorntoolworks.com>
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * This stpcpy implementation copies a byte at a time until the
+ * source pointer is aligned to a word boundary, it then copies by
+ * words until it finds a word containing a zero byte, and finally
+ * copies by bytes until the end of the string is reached.
+ *
+ * While this may result in unaligned stores if the source and
+ * destination pointers are unaligned with respect to each other,
+ * it is still faster than either byte copies or the overhead of
+ * an implementation suitable for machines with strict alignment
+ * requirements.
+ */
+
+ .globl stpcpy,__stpcpy
+ENTRY(stpcpy)
+__stpcpy:
+ movabsq $0x0101010101010101,%r8
+ movabsq $0x8080808080808080,%r9
+
+ /*
+ * Align source to a word boundary.
+ * Consider unrolling loop?
+ */
+.Lalign:
+ testb $7,%sil
+ je .Lword_aligned
+ movb (%rsi),%dl
+ incq %rsi
+ movb %dl,(%rdi)
+ incq %rdi
+ testb %dl,%dl
+ jne .Lalign
+ movq %rdi,%rax
+ dec %rax
+ ret
+
+ .p2align 4
+.Lloop:
+ movq %rdx,(%rdi)
+ addq $8,%rdi
+.Lword_aligned:
+ movq (%rsi),%rdx
+ movq %rdx,%rcx
+ addq $8,%rsi
+ subq %r8,%rcx
+ testq %r9,%rcx
+ je .Lloop
+
+ /*
+ * In rare cases, the above loop may exit prematurely. We must
+ * return to the loop if none of the bytes in the word equal 0.
+ */
+
+ movb %dl,(%rdi)
+ testb %dl,%dl /* 1st byte == 0? */
+ je .Ldone
+ incq %rdi
+
+ shrq $8,%rdx
+ movb %dl,(%rdi)
+ testb %dl,%dl /* 2nd byte == 0? */
+ je .Ldone
+ incq %rdi
+
+ shrq $8,%rdx
+ movb %dl,(%rdi)
+ testb %dl,%dl /* 3rd byte == 0? */
+ je .Ldone
+ incq %rdi
+
+ shrq $8,%rdx
+ movb %dl,(%rdi)
+ testb %dl,%dl /* 4th byte == 0? */
+ je .Ldone
+ incq %rdi
+
+ shrq $8,%rdx
+ movb %dl,(%rdi)
+ testb %dl,%dl /* 5th byte == 0? */
+ je .Ldone
+ incq %rdi
+
+ shrq $8,%rdx
+ movb %dl,(%rdi)
+ testb %dl,%dl /* 6th byte == 0? */
+ je .Ldone
+ incq %rdi
+
+ shrq $8,%rdx
+ movb %dl,(%rdi)
+ testb %dl,%dl /* 7th byte == 0? */
+ je .Ldone
+ incq %rdi
+
+ shrq $8,%rdx
+ movb %dl,(%rdi)
+ incq %rdi
+ testb %dl,%dl /* 8th byte == 0? */
+ jne .Lword_aligned
+ decq %rdi
+
+.Ldone:
+ movq %rdi,%rax
+ ret
+END(stpcpy)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/string/strcat.S b/lib/libc/amd64/string/strcat.S
new file mode 100644
index 0000000..7b5a1dd
--- /dev/null
+++ b/lib/libc/amd64/string/strcat.S
@@ -0,0 +1,168 @@
+/*
+ * Written by J.T. Conklin <jtc@acorntoolworks.com>
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if 0
+ RCSID("$NetBSD: strcat.S,v 1.4 2004/07/26 18:51:21 drochner Exp $")
+#endif
+
+ENTRY(strcat)
+ movq %rdi,%rax
+ movabsq $0x0101010101010101,%r8
+ movabsq $0x8080808080808080,%r9
+
+ /*
+ * Align destination to word boundary.
+ * Consider unrolling loop?
+ */
+.Lscan:
+.Lscan_align:
+ testb $7,%dil
+ je .Lscan_aligned
+ cmpb $0,(%rdi)
+ je .Lcopy
+ incq %rdi
+ jmp .Lscan_align
+
+ .align 4
+.Lscan_aligned:
+.Lscan_loop:
+ movq (%rdi),%rdx
+ addq $8,%rdi
+ subq %r8,%rdx
+ testq %r9,%rdx
+ je .Lscan_loop
+
+ /*
+ * In rare cases, the above loop may exit prematurely. We must
+ * return to the loop if none of the bytes in the word equal 0.
+ */
+
+ cmpb $0,-8(%rdi) /* 1st byte == 0? */
+ jne 1f
+ subq $8,%rdi
+ jmp .Lcopy
+
+1: cmpb $0,-7(%rdi) /* 2nd byte == 0? */
+ jne 1f
+ subq $7,%rdi
+ jmp .Lcopy
+
+1: cmpb $0,-6(%rdi) /* 3rd byte == 0? */
+ jne 1f
+ subq $6,%rdi
+ jmp .Lcopy
+
+1: cmpb $0,-5(%rdi) /* 4th byte == 0? */
+ jne 1f
+ subq $5,%rdi
+ jmp .Lcopy
+
+1: cmpb $0,-4(%rdi) /* 5th byte == 0? */
+ jne 1f
+ subq $4,%rdi
+ jmp .Lcopy
+
+1: cmpb $0,-3(%rdi) /* 6th byte == 0? */
+ jne 1f
+ subq $3,%rdi
+ jmp .Lcopy
+
+1: cmpb $0,-2(%rdi) /* 7th byte == 0? */
+ jne 1f
+ subq $2,%rdi
+ jmp .Lcopy
+
+1: cmpb $0,-1(%rdi) /* 8th byte == 0? */
+ jne .Lscan_loop
+ subq $1,%rdi
+
+ /*
+ * Align source to a word boundary.
+ * Consider unrolling loop?
+ */
+.Lcopy:
+.Lcopy_align:
+ testb $7,%sil
+ je .Lcopy_aligned
+ movb (%rsi),%dl
+ incq %rsi
+ movb %dl,(%rdi)
+ incq %rdi
+ testb %dl,%dl
+ jne .Lcopy_align
+ ret
+
+ .align 4
+.Lcopy_loop:
+ movq %rdx,(%rdi)
+ addq $8,%rdi
+.Lcopy_aligned:
+ movq (%rsi),%rdx
+ movq %rdx,%rcx
+ addq $8,%rsi
+ subq %r8,%rcx
+ testq %r9,%rcx
+ je .Lcopy_loop
+
+ /*
+ * In rare cases, the above loop may exit prematurely. We must
+ * return to the loop if none of the bytes in the word equal 0.
+ */
+
+ movb %dl,(%rdi)
+ incq %rdi
+ testb %dl,%dl /* 1st byte == 0? */
+ je .Ldone
+
+ shrq $8,%rdx
+ movb %dl,(%rdi)
+ incq %rdi
+ testb %dl,%dl /* 2nd byte == 0? */
+ je .Ldone
+
+ shrq $8,%rdx
+ movb %dl,(%rdi)
+ incq %rdi
+ testb %dl,%dl /* 3rd byte == 0? */
+ je .Ldone
+
+ shrq $8,%rdx
+ movb %dl,(%rdi)
+ incq %rdi
+ testb %dl,%dl /* 4th byte == 0? */
+ je .Ldone
+
+ shrq $8,%rdx
+ movb %dl,(%rdi)
+ incq %rdi
+ testb %dl,%dl /* 5th byte == 0? */
+ je .Ldone
+
+ shrq $8,%rdx
+ movb %dl,(%rdi)
+ incq %rdi
+ testb %dl,%dl /* 6th byte == 0? */
+ je .Ldone
+
+ shrq $8,%rdx
+ movb %dl,(%rdi)
+ incq %rdi
+ testb %dl,%dl /* 7th byte == 0? */
+ je .Ldone
+
+ shrq $8,%rdx
+ movb %dl,(%rdi)
+ incq %rdi
+ testb %dl,%dl /* 8th byte == 0? */
+ jne .Lcopy_aligned
+
+.Ldone:
+ ret
+END(strcat)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/string/strcmp.S b/lib/libc/amd64/string/strcmp.S
new file mode 100644
index 0000000..07009c1
--- /dev/null
+++ b/lib/libc/amd64/string/strcmp.S
@@ -0,0 +1,76 @@
+/*
+ * Written by J.T. Conklin <jtc@acorntoolworks.com>
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if 0
+ RCSID("$NetBSD: strcmp.S,v 1.3 2004/07/19 20:04:41 drochner Exp $")
+#endif
+
+ENTRY(strcmp)
+ /*
+ * Align s1 to word boundary.
+ * Consider unrolling loop?
+ */
+.Ls1align:
+ testb $7,%dil
+ je .Ls1aligned
+ movb (%rdi),%al
+ incq %rdi
+ movb (%rsi),%dl
+ incq %rsi
+ testb %al,%al
+ je .Ldone
+ cmpb %al,%dl
+ je .Ls1align
+ jmp .Ldone
+
+ /*
+ * Check whether s2 is aligned to a word boundry. If it is, we
+ * can compare by words. Otherwise we have to compare by bytes.
+ */
+.Ls1aligned:
+ testb $7,%sil
+ jne .Lbyte_loop
+
+ movabsq $0x0101010101010101,%r8
+ subq $8,%rdi
+ movabsq $0x8080808080808080,%r9
+ subq $8,%rsi
+
+ .align 4
+.Lword_loop:
+ movq 8(%rdi),%rax
+ addq $8,%rdi
+ movq 8(%rsi),%rdx
+ addq $8,%rsi
+ cmpq %rax,%rdx
+ jne .Lbyte_loop
+ subq %r8,%rdx
+ notq %rax
+ andq %rax,%rdx
+ testq %r9,%rdx
+ je .Lword_loop
+
+ .align 4
+.Lbyte_loop:
+ movb (%rdi),%al
+ incq %rdi
+ movb (%rsi),%dl
+ incq %rsi
+ testb %al,%al
+ je .Ldone
+ cmpb %al,%dl
+ je .Lbyte_loop
+
+.Ldone:
+ movzbq %al,%rax
+ movzbq %dl,%rdx
+ subq %rdx,%rax
+ ret
+END(strcmp)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/string/strcpy.c b/lib/libc/amd64/string/strcpy.c
new file mode 100644
index 0000000..11a24eb
--- /dev/null
+++ b/lib/libc/amd64/string/strcpy.c
@@ -0,0 +1,38 @@
+/*
+ * Copyright 2011 George V. Neville-Neil. All rights reserved.
+ *
+ * The compilation of software known as FreeBSD is distributed under the
+ * following terms:
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+char *__stpcpy(char * __restrict, const char * __restrict);
+
+char *
+strcpy(char * __restrict to, const char * __restrict from)
+{
+ __stpcpy(to, from);
+ return(to);
+}
diff --git a/lib/libc/amd64/sys/Makefile.inc b/lib/libc/amd64/sys/Makefile.inc
new file mode 100644
index 0000000..c7b17e0
--- /dev/null
+++ b/lib/libc/amd64/sys/Makefile.inc
@@ -0,0 +1,15 @@
+# from: Makefile.inc,v 1.1 1993/09/03 19:04:23 jtc Exp
+# $FreeBSD$
+
+SRCS+= amd64_get_fsbase.c amd64_get_gsbase.c amd64_set_fsbase.c amd64_set_gsbase.c
+
+MDASM= vfork.S brk.S cerror.S exect.S getcontext.S pipe.S ptrace.S \
+ reboot.S sbrk.S setlogin.S sigreturn.S
+
+# Don't generate default code for these syscalls:
+NOASM= break.o exit.o getlogin.o openbsd_poll.o sstk.o vfork.o yield.o
+
+PSEUDO= _getlogin.o _exit.o
+.if !defined(WITHOUT_SYSCALL_COMPAT)
+PSEUDO+= _pread.o _pwrite.o _lseek.o _mmap.o _ftruncate.o _truncate.o
+.endif
diff --git a/lib/libc/amd64/sys/amd64_get_fsbase.c b/lib/libc/amd64/sys/amd64_get_fsbase.c
new file mode 100644
index 0000000..ff5eb8f
--- /dev/null
+++ b/lib/libc/amd64/sys/amd64_get_fsbase.c
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2003 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/sysarch.h>
+
+int
+amd64_get_fsbase(void **addr)
+{
+
+ return (sysarch(AMD64_GET_FSBASE, addr));
+}
diff --git a/lib/libc/amd64/sys/amd64_get_gsbase.c b/lib/libc/amd64/sys/amd64_get_gsbase.c
new file mode 100644
index 0000000..ddbf977
--- /dev/null
+++ b/lib/libc/amd64/sys/amd64_get_gsbase.c
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2003 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/sysarch.h>
+
+int
+amd64_get_gsbase(void **addr)
+{
+
+ return (sysarch(AMD64_GET_GSBASE, addr));
+}
diff --git a/lib/libc/amd64/sys/amd64_set_fsbase.c b/lib/libc/amd64/sys/amd64_set_fsbase.c
new file mode 100644
index 0000000..e091485
--- /dev/null
+++ b/lib/libc/amd64/sys/amd64_set_fsbase.c
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2003 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/sysarch.h>
+
+int
+amd64_set_fsbase(void *addr)
+{
+
+ return (sysarch(AMD64_SET_FSBASE, &addr));
+}
diff --git a/lib/libc/amd64/sys/amd64_set_gsbase.c b/lib/libc/amd64/sys/amd64_set_gsbase.c
new file mode 100644
index 0000000..f896328
--- /dev/null
+++ b/lib/libc/amd64/sys/amd64_set_gsbase.c
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2003 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/sysarch.h>
+
+int
+amd64_set_gsbase(void *addr)
+{
+
+ return (sysarch(AMD64_SET_GSBASE, &addr));
+}
diff --git a/lib/libc/amd64/sys/brk.S b/lib/libc/amd64/sys/brk.S
new file mode 100644
index 0000000..2319417
--- /dev/null
+++ b/lib/libc/amd64/sys/brk.S
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)brk.s 5.2 (Berkeley) 12/17/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl HIDENAME(curbrk)
+ .globl HIDENAME(minbrk)
+ENTRY(_brk)
+ pushq %rdi
+ jmp ok
+END(_brk)
+
+ENTRY(brk)
+ pushq %rdi
+ movq %rdi,%rax
+#ifdef PIC
+ movq PIC_GOT(HIDENAME(minbrk)),%rdx
+ cmpq %rax,(%rdx)
+#else
+ cmpq %rax,HIDENAME(minbrk)(%rip)
+#endif
+ jbe ok
+#ifdef PIC
+ movq (%rdx),%rdi
+#else
+ movq HIDENAME(minbrk)(%rip),%rdi
+#endif
+ok:
+ movq $SYS_break,%rax
+ KERNCALL
+ jb err
+ movq 0(%rsp),%rax
+#ifdef PIC
+ movq PIC_GOT(HIDENAME(curbrk)),%rdx
+ movq %rax,(%rdx)
+#else
+ movq %rax,HIDENAME(curbrk)(%rip)
+#endif
+ movq $0,%rax
+ popq %rdi
+ ret
+err:
+ addq $8, %rsp
+#ifdef PIC
+ movq PIC_GOT(HIDENAME(cerror)),%rdx
+ jmp *%rdx
+#else
+ jmp HIDENAME(cerror)
+#endif
+END(brk)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/cerror.S b/lib/libc/amd64/sys/cerror.S
new file mode 100644
index 0000000..d01cf4a
--- /dev/null
+++ b/lib/libc/amd64/sys/cerror.S
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)cerror.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl HIDENAME(cerror)
+
+ /*
+ * The __error() function is thread aware. For non-threaded
+ * programs and the initial threaded in threaded programs,
+ * it returns a pointer to the global errno variable.
+ */
+ .globl CNAME(__error)
+ .type CNAME(__error),@function
+HIDENAME(cerror):
+ pushq %rax
+ call PIC_PLT(CNAME(__error))
+ popq %rcx
+ movl %ecx,(%rax)
+ movq $-1,%rax
+ movq $-1,%rdx
+ ret
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/exect.S b/lib/libc/amd64/sys/exect.S
new file mode 100644
index 0000000..81dc8e5
--- /dev/null
+++ b/lib/libc/amd64/sys/exect.S
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)exect.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+#include <machine/psl.h>
+
+ENTRY(exect)
+ movq $SYS_execve,%rax
+ pushfq
+ popq %r8
+ orq $PSL_T,%r8
+ pushq %r8
+ popfq
+ KERNCALL
+#ifdef PIC
+ movq PIC_GOT(HIDENAME(cerror)),%rdx
+ jmp *%rdx
+#else
+ jmp HIDENAME(cerror)
+#endif
+END(exect)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/getcontext.S b/lib/libc/amd64/sys/getcontext.S
new file mode 100644
index 0000000..ea29adb
--- /dev/null
+++ b/lib/libc/amd64/sys/getcontext.S
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2003 Peter Wemm <peter@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include <SYS.h>
+
+/*
+ * This has to be magic to handle the multiple returns.
+ * Otherwise, the setcontext() syscall will return here and we'll
+ * pop off the return address and go to the *setcontext* call.
+ */
+ .weak _getcontext
+ .set _getcontext,__sys_getcontext
+ .weak getcontext
+ .set getcontext,__sys_getcontext
+ENTRY(__sys_getcontext)
+ movq (%rsp),%rsi /* save getcontext return address */
+ mov $SYS_getcontext,%rax
+ KERNCALL
+ jb 1f
+ addq $8,%rsp /* remove stale (setcontext) return address */
+ jmp *%rsi /* restore return address */
+1:
+#ifdef PIC
+ movq PIC_GOT(HIDENAME(cerror)),%rdx
+ jmp *%rdx
+#else
+ jmp HIDENAME(cerror)
+#endif
+END(__sys_getcontext)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/pipe.S b/lib/libc/amd64/sys/pipe.S
new file mode 100644
index 0000000..59c1ac1c
--- /dev/null
+++ b/lib/libc/amd64/sys/pipe.S
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)pipe.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .weak _pipe
+ .set _pipe,__sys_pipe
+ .weak pipe
+ .set pipe,__sys_pipe
+ENTRY(__sys_pipe)
+ mov $SYS_pipe,%rax
+ KERNCALL
+ jb 1f
+ movl %eax,(%rdi) /* %rdi is preserved by syscall */
+ movl %edx,4(%rdi)
+ movq $0,%rax
+ ret
+1:
+#ifdef PIC
+ movq PIC_GOT(HIDENAME(cerror)),%rdx
+ jmp *%rdx
+#else
+ jmp HIDENAME(cerror)
+#endif
+END(__sys_pipe)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/ptrace.S b/lib/libc/amd64/sys/ptrace.S
new file mode 100644
index 0000000..6235390
--- /dev/null
+++ b/lib/libc/amd64/sys/ptrace.S
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)ptrace.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ENTRY(ptrace)
+ xorl %eax,%eax
+#ifdef PIC
+ movq PIC_GOT(CNAME(errno)),%r8
+ movl %eax,(%r8)
+#else
+ movl %eax,CNAME(errno)(%rip)
+#endif
+ mov $SYS_ptrace,%eax
+ KERNCALL
+ jb err
+ ret
+err:
+#ifdef PIC
+ movq PIC_GOT(HIDENAME(cerror)),%rdx
+ jmp *%rdx
+#else
+ jmp HIDENAME(cerror)
+#endif
+END(ptrace)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/reboot.S b/lib/libc/amd64/sys/reboot.S
new file mode 100644
index 0000000..e79ca79
--- /dev/null
+++ b/lib/libc/amd64/sys/reboot.S
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)reboot.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .weak _reboot
+ .set _reboot,__sys_reboot
+ .weak reboot
+ .set reboot,__sys_reboot
+ENTRY(__sys_reboot)
+ mov $SYS_reboot,%rax
+ KERNCALL
+ jb 1f
+ iretq
+1:
+#ifdef PIC
+ movq PIC_GOT(HIDENAME(cerror)),%rdx
+ jmp *%rdx
+#else
+ jmp HIDENAME(cerror)
+#endif
+END(__sys_reboot)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/sbrk.S b/lib/libc/amd64/sys/sbrk.S
new file mode 100644
index 0000000..3e4d8aa
--- /dev/null
+++ b/lib/libc/amd64/sys/sbrk.S
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)sbrk.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl CNAME(_end)
+ .globl HIDENAME(minbrk)
+ .globl HIDENAME(curbrk)
+
+ .data
+HIDENAME(minbrk): .quad CNAME(_end)
+HIDENAME(curbrk): .quad CNAME(_end)
+ .text
+
+ENTRY(sbrk)
+ pushq %rdi
+ movq %rdi,%rcx
+#ifdef PIC
+ movq PIC_GOT(HIDENAME(curbrk)),%rdx
+ movq (%rdx),%rax
+#else
+ movq HIDENAME(curbrk)(%rip),%rax
+#endif
+ testq %rcx,%rcx
+ jz back
+ addq %rax,%rdi
+ mov $SYS_break,%eax
+ KERNCALL
+ jb err
+#ifdef PIC
+ movq PIC_GOT(HIDENAME(curbrk)),%rdx
+ movq (%rdx),%rax
+#else
+ movq HIDENAME(curbrk)(%rip),%rax
+#endif
+ movq 0(%rsp), %rcx
+#ifdef PIC
+ addq %rcx,(%rdx)
+#else
+ addq %rcx,HIDENAME(curbrk)(%rip)
+#endif
+back:
+ addq $8, %rsp
+ ret
+err:
+ addq $8, %rsp
+#ifdef PIC
+ movq PIC_GOT(HIDENAME(cerror)),%rdx
+ jmp *%rdx
+#else
+ jmp HIDENAME(cerror)
+#endif
+END(sbrk)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/setlogin.S b/lib/libc/amd64/sys/setlogin.S
new file mode 100644
index 0000000..23692b9
--- /dev/null
+++ b/lib/libc/amd64/sys/setlogin.S
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ .asciz "@(#)setlogin.s 5.2 (Berkeley) 4/12/91"
+#endif /* LIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+.globl CNAME(_logname_valid) /* in _getlogin() */
+
+ .weak _setlogin
+ .set _setlogin,__sys_setlogin
+ .weak setlogin
+ .set setlogin,__sys_setlogin
+ENTRY(__sys_setlogin)
+ mov $SYS_setlogin,%rax
+ KERNCALL
+ jb 1f
+#ifdef PIC
+ movq PIC_GOT(CNAME(_logname_valid)),%rdx
+ movl $0,(%rdx)
+#else
+ movl $0,CNAME(_logname_valid)(%rip)
+#endif
+ ret /* setlogin(name) */
+1:
+#ifdef PIC
+ movq PIC_GOT(HIDENAME(cerror)),%rdx
+ jmp *%rdx
+#else
+ jmp HIDENAME(cerror)
+#endif
+END(__sys_setlogin)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/sigreturn.S b/lib/libc/amd64/sys/sigreturn.S
new file mode 100644
index 0000000..f91816e
--- /dev/null
+++ b/lib/libc/amd64/sys/sigreturn.S
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)sigreturn.s 5.2 (Berkeley) 12/17/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+/*
+ * NOTE: If the profiling ENTRY() code ever changes any registers, they
+ * must be saved. On FreeBSD, this is not the case.
+ */
+
+RSYSCALL(sigreturn)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/amd64/sys/vfork.S b/lib/libc/amd64/sys/vfork.S
new file mode 100644
index 0000000..555c3ca
--- /dev/null
+++ b/lib/libc/amd64/sys/vfork.S
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)Ovfork.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .weak _vfork
+ .set _vfork,__sys_vfork
+ .weak vfork
+ .set vfork,__sys_vfork
+ENTRY(__sys_vfork)
+ popq %rsi /* fetch return address (%rsi preserved) */
+ mov $SYS_vfork,%rax
+ KERNCALL
+ jb 1f
+ jmp *%rsi
+1:
+ pushq %rsi
+#ifdef PIC
+ movq PIC_GOT(HIDENAME(cerror)),%rdx
+ jmp *%rdx
+#else
+ jmp HIDENAME(cerror)
+#endif
+END(__sys_vfork)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/arm/Makefile.inc b/lib/libc/arm/Makefile.inc
new file mode 100644
index 0000000..4c72e56
--- /dev/null
+++ b/lib/libc/arm/Makefile.inc
@@ -0,0 +1,10 @@
+# $FreeBSD$
+#
+# Machine dependent definitions for the arm architecture.
+#
+
+SOFTFLOAT_BITS=32
+
+# Long double is just double precision.
+MDSRCS+=machdep_ldisd.c
+SYM_MAPS+=${.CURDIR}/arm/Symbol.map
diff --git a/lib/libc/arm/SYS.h b/lib/libc/arm/SYS.h
new file mode 100644
index 0000000..584c151
--- /dev/null
+++ b/lib/libc/arm/SYS.h
@@ -0,0 +1,74 @@
+/* $NetBSD: SYS.h,v 1.8 2003/08/07 16:42:02 agc Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)SYS.h 5.5 (Berkeley) 5/7/91
+ * $FreeBSD$
+ */
+
+#include <machine/asm.h>
+#include <sys/syscall.h>
+#include <machine/swi.h>
+
+#define SYSTRAP(x) swi 0 | SYS_ ## x
+
+#define CERROR _C_LABEL(cerror)
+#define CURBRK _C_LABEL(curbrk)
+
+#define _SYSCALL_NOERROR(x) \
+ ENTRY(__CONCAT(__sys_, x)); \
+ .weak _C_LABEL(x); \
+ .set _C_LABEL(x), _C_LABEL(__CONCAT(__sys_,x)); \
+ .weak _C_LABEL(__CONCAT(_,x)); \
+ .set _C_LABEL(__CONCAT(_,x)),_C_LABEL(__CONCAT(__sys_,x)); \
+ SYSTRAP(x)
+
+#define _SYSCALL(x) \
+ _SYSCALL_NOERROR(x); \
+ bcs PIC_SYM(CERROR, PLT)
+
+#define SYSCALL(x) \
+ _SYSCALL(x)
+
+#define PSEUDO(x) \
+ ENTRY(__CONCAT(__sys_, x)); \
+ .weak _C_LABEL(__CONCAT(_,x)); \
+ .set _C_LABEL(__CONCAT(_,x)),_C_LABEL(__CONCAT(__sys_,x)); \
+ SYSTRAP(x); \
+ bcs PIC_SYM(CERROR, PLT); \
+ RET
+
+#define RSYSCALL(x) \
+ _SYSCALL(x); \
+ RET
+
+ .globl CERROR
diff --git a/lib/libc/arm/Symbol.map b/lib/libc/arm/Symbol.map
new file mode 100644
index 0000000..dc46013
--- /dev/null
+++ b/lib/libc/arm/Symbol.map
@@ -0,0 +1,79 @@
+/*
+ * $FreeBSD$
+ */
+
+/*
+ * This only needs to contain symbols that are not listed in
+ * symbol maps from other parts of libc (i.e., not found in
+ * stdlib/Symbol.map, string/Symbol.map, sys/Symbol.map, ...).
+ */
+FBSD_1.0 {
+ /* PSEUDO syscalls */
+ _exit;
+
+ __mcount;
+ _setjmp;
+ _longjmp;
+ alloca;
+ fabs;
+ __infinity;
+ __nan;
+ makecontext;
+ setjmp;
+ longjmp;
+ sigsetjmp;
+ siglongjmp;
+ htonl;
+ htons;
+ ntohl;
+ ntohs;
+ vfork;
+ brk;
+ cerror; /* XXX - Should this be .cerror (see sys/cerror.S)? */
+ sbrk;
+};
+
+FBSDprivate_1.0 {
+ /* PSEUDO syscalls */
+ __sys_getlogin;
+ _getlogin;
+ __sys_exit;
+
+ _set_tp;
+ __aeabi_read_tp;
+ ___longjmp;
+ __umodsi3;
+ __modsi3;
+ __udivsi3;
+ __divsi3;
+ __makecontext;
+ __longjmp;
+ signalcontext;
+ _signalcontext;
+ __siglongjmp;
+ __sys_vfork;
+ _vfork;
+ _brk;
+ _end;
+ curbrk;
+ minbrk;
+ _sbrk;
+
+ /* softfloat */
+ __addsf3;
+ __adddf3;
+ __subsf3;
+ __subdf3;
+ __mulsf3;
+ __muldf3;
+ __divsf3;
+ __divdf3;
+ __floatsisf;
+ __floatsidf;
+ __fixsfsi;
+ __fixdfsi;
+ __fixunssfsi;
+ __fixunsdfsi;
+ __extendsfdf2;
+ __truncdfsf2;
+};
diff --git a/lib/libc/arm/_fpmath.h b/lib/libc/arm/_fpmath.h
new file mode 100644
index 0000000..4c18945
--- /dev/null
+++ b/lib/libc/arm/_fpmath.h
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#if defined(__VFP_FP__)
+#define _IEEE_WORD_ORDER _BYTE_ORDER
+#else
+#define _IEEE_WORD_ORDER _BIG_ENDIAN
+#endif
+
+union IEEEl2bits {
+ long double e;
+ struct {
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+#if _IEEE_WORD_ORDER == _LITTLE_ENDIAN
+ unsigned int manl :32;
+#endif
+ unsigned int manh :20;
+ unsigned int exp :11;
+ unsigned int sign :1;
+#if _IEEE_WORD_ORDER == _BIG_ENDIAN
+ unsigned int manl :32;
+#endif
+#else /* _BYTE_ORDER == _LITTLE_ENDIAN */
+ unsigned int sign :1;
+ unsigned int exp :11;
+ unsigned int manh :20;
+ unsigned int manl :32;
+#endif
+ } bits;
+};
+
+#define LDBL_NBIT 0
+#define LDBL_IMPLICIT_NBIT
+#define mask_nbit_l(u) ((void)0)
+
+#define LDBL_MANH_SIZE 20
+#define LDBL_MANL_SIZE 32
+
+#define LDBL_TO_ARRAY32(u, a) do { \
+ (a)[0] = (uint32_t)(u).bits.manl; \
+ (a)[1] = (uint32_t)(u).bits.manh; \
+} while(0)
diff --git a/lib/libc/arm/arith.h b/lib/libc/arm/arith.h
new file mode 100644
index 0000000..be78d86
--- /dev/null
+++ b/lib/libc/arm/arith.h
@@ -0,0 +1,21 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * NOTE: The definitions in this file must be correct or strtod(3) and
+ * floating point formats in printf(3) will break! The file can be
+ * generated by running contrib/gdtoa/arithchk.c on the target
+ * architecture. See contrib/gdtoa/gdtoaimp.h for details.
+ */
+
+#if !defined(__ARMEB__) && defined(__VFP_FP__)
+#define IEEE_8087
+#define Arith_Kind_ASL 1
+#define Sudden_Underflow
+#else
+#define IEEE_MC68k
+#define Arith_Kind_ASL 2
+#endif
diff --git a/lib/libc/arm/gd_qnan.h b/lib/libc/arm/gd_qnan.h
new file mode 100644
index 0000000..8fa9edd
--- /dev/null
+++ b/lib/libc/arm/gd_qnan.h
@@ -0,0 +1,23 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * This file can be generated by compiling and running contrib/gdtoa/qnan.c
+ * on the target architecture after arith.h has been generated.
+ *
+ * XXX I don't have ARM hardware, so I just guessed. --das
+ *
+ * $FreeBSD$
+ */
+
+#define f_QNAN 0x7fc00000
+#define d_QNAN0 0x0
+#define d_QNAN1 0x7ff80000
+#define ld_QNAN0 0x0
+#define ld_QNAN1 0xc0000000
+#define ld_QNAN2 0x7fff
+#define ld_QNAN3 0x0
+#define ldus_QNAN0 0x0
+#define ldus_QNAN1 0x0
+#define ldus_QNAN2 0x0
+#define ldus_QNAN3 0xc000
+#define ldus_QNAN4 0x7fff
diff --git a/lib/libc/arm/gen/Makefile.inc b/lib/libc/arm/gen/Makefile.inc
new file mode 100644
index 0000000..a78cbb9
--- /dev/null
+++ b/lib/libc/arm/gen/Makefile.inc
@@ -0,0 +1,6 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+SRCS+= _ctx_start.S _setjmp.S _set_tp.c alloca.S fabs.c \
+ getcontextx.c infinity.c ldexp.c makecontext.c \
+ __aeabi_read_tp.S setjmp.S signalcontext.c sigsetjmp.S divsi3.S flt_rounds.c
diff --git a/lib/libc/arm/gen/__aeabi_read_tp.S b/lib/libc/arm/gen/__aeabi_read_tp.S
new file mode 100644
index 0000000..228acff
--- /dev/null
+++ b/lib/libc/arm/gen/__aeabi_read_tp.S
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2012 Oleksandr Tymoshenko
+ * Copyright (c) 2012 Andrew Turner
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/sysarch.h>
+
+ENTRY(__aeabi_read_tp)
+ ldr r0, .Larm_tp_address
+ ldr r0, [r0]
+ RET
+
+.Larm_tp_address:
+ .word ARM_TP_ADDRESS
+
diff --git a/lib/libc/arm/gen/_ctx_start.S b/lib/libc/arm/gen/_ctx_start.S
new file mode 100644
index 0000000..fbde357
--- /dev/null
+++ b/lib/libc/arm/gen/_ctx_start.S
@@ -0,0 +1,9 @@
+#include <machine/asm.h>
+
+.ident "$FreeBSD$"
+ENTRY(_ctx_start)
+ mov lr, pc
+ mov pc, r4
+ mov r0, r5
+ bl _C_LABEL(ctx_done)
+ bl _C_LABEL(abort)
diff --git a/lib/libc/arm/gen/_set_tp.c b/lib/libc/arm/gen/_set_tp.c
new file mode 100644
index 0000000..44bbdd8
--- /dev/null
+++ b/lib/libc/arm/gen/_set_tp.c
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <string.h>
+#include <sys/types.h>
+
+#include <machine/sysarch.h>
+
+void
+_set_tp(void *tp)
+{
+
+ *((struct tcb **)ARM_TP_ADDRESS) = tp;
+}
diff --git a/lib/libc/arm/gen/_setjmp.S b/lib/libc/arm/gen/_setjmp.S
new file mode 100644
index 0000000..6594afb
--- /dev/null
+++ b/lib/libc/arm/gen/_setjmp.S
@@ -0,0 +1,110 @@
+/* $NetBSD: _setjmp.S,v 1.5 2003/04/05 23:08:51 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1997 Mark Brinicombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * C library -- _setjmp, _longjmp
+ *
+ * _longjmp(a,v)
+ * will generate a "return(v)" from the last call to
+ * _setjmp(a)
+ * by restoring registers from the stack.
+ * The previous signal state is NOT restored.
+ *
+ * Note: r0 is the return value
+ * r1-r3 are scratch registers in functions
+ */
+
+ENTRY(_setjmp)
+ ldr r1, .L_setjmp_magic
+ str r1, [r0], #4
+#ifdef __SOFTFP__
+ add r0, r0, #52
+#else
+ /* Store fp registers */
+ sfm f4, 4, [r0], #48
+ /* Store fpsr */
+ rfs r1
+ str r1, [r0], #0x0004
+#endif /* __SOFTFP__ */
+ /* Store integer registers */
+ stmia r0, {r4-r14}
+
+ mov r0, #0x00000000
+ RET
+
+.L_setjmp_magic:
+ .word _JB_MAGIC__SETJMP
+
+WEAK_ALIAS(___longjmp, _longjmp)
+ENTRY(_longjmp)
+ ldr r2, .L_setjmp_magic
+ ldr r3, [r0], #4
+ teq r2, r3
+ bne botch
+
+#ifdef __SOFTFP__
+ add r0, r0, #52
+#else
+ /* Restore fp registers */
+ lfm f4, 4, [r0], #48
+ /* Restore fpsr */
+ ldr r4, [r0], #0x0004
+ wfs r4
+#endif /* __SOFTFP__ */
+ /* Restore integer registers */
+ ldmia r0, {r4-r14}
+
+ /* Validate sp and r14 */
+ teq sp, #0
+ teqne r14, #0
+ beq botch
+
+ /* Set return value */
+ mov r0, r1
+ teq r0, #0x00000000
+ moveq r0, #0x00000001
+ RET
+
+ /* validation failed, die die die. */
+botch:
+#if !defined(_STANDALONE)
+ bl PIC_SYM(_C_LABEL(longjmperror), PLT)
+ bl PIC_SYM(_C_LABEL(abort), PLT)
+ b . - 8 /* Cannot get here */
+#else
+ b .
+#endif
diff --git a/lib/libc/arm/gen/alloca.S b/lib/libc/arm/gen/alloca.S
new file mode 100644
index 0000000..9569d86
--- /dev/null
+++ b/lib/libc/arm/gen/alloca.S
@@ -0,0 +1,45 @@
+/* $NetBSD: alloca.S,v 1.3 2003/04/05 23:08:51 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1995 Mark Brinicombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* like alloc, but automatic automatic free in return */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(alloca)
+ add r0, r0, #0x00000007 /* round up to next 8 byte alignment */
+ bic r0, r0, #0x00000007
+ sub sp, sp, r0 /* Adjust the stack pointer */
+ mov r0, sp /* r0 = base of new space */
+ RET
diff --git a/lib/libc/arm/gen/divsi3.S b/lib/libc/arm/gen/divsi3.S
new file mode 100644
index 0000000..104a958
--- /dev/null
+++ b/lib/libc/arm/gen/divsi3.S
@@ -0,0 +1,387 @@
+/* $NetBSD: divsi3.S,v 1.4 2003/04/05 23:27:15 bjh21 Exp $ */
+
+/*
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * stack is aligned as there's a possibility of branching to L_overflow
+ * which makes a C call
+ */
+
+ENTRY(__umodsi3)
+ stmfd sp!, {lr}
+ sub sp, sp, #4 /* align stack */
+ bl .L_udivide
+ add sp, sp, #4 /* unalign stack */
+ mov r0, r1
+ ldmfd sp!, {pc}
+
+ENTRY(__modsi3)
+ stmfd sp!, {lr}
+ sub sp, sp, #4 /* align stack */
+ bl .L_divide
+ add sp, sp, #4 /* unalign stack */
+ mov r0, r1
+ ldmfd sp!, {pc}
+
+.L_overflow:
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+ mov r0, #8 /* SIGFPE */
+ bl PIC_SYM(_C_LABEL(raise), PLT) /* raise it */
+ mov r0, #0
+#else
+ /* XXX should cause a fatal error */
+ mvn r0, #0
+#endif
+ RET
+
+ENTRY(__udivsi3)
+.L_udivide: /* r0 = r0 / r1; r1 = r0 % r1 */
+ eor r0, r1, r0
+ eor r1, r0, r1
+ eor r0, r1, r0
+ /* r0 = r1 / r0; r1 = r1 % r0 */
+ cmp r0, #1
+ bcc .L_overflow
+ beq .L_divide_l0
+ mov ip, #0
+ movs r1, r1
+ bpl .L_divide_l1
+ orr ip, ip, #0x20000000 /* ip bit 0x20000000 = -ve r1 */
+ movs r1, r1, lsr #1
+ orrcs ip, ip, #0x10000000 /* ip bit 0x10000000 = bit 0 of r1 */
+ b .L_divide_l1
+
+.L_divide_l0: /* r0 == 1 */
+ mov r0, r1
+ mov r1, #0
+ RET
+
+ENTRY(__divsi3)
+.L_divide: /* r0 = r0 / r1; r1 = r0 % r1 */
+ eor r0, r1, r0
+ eor r1, r0, r1
+ eor r0, r1, r0
+ /* r0 = r1 / r0; r1 = r1 % r0 */
+ cmp r0, #1
+ bcc .L_overflow
+ beq .L_divide_l0
+ ands ip, r0, #0x80000000
+ rsbmi r0, r0, #0
+ ands r2, r1, #0x80000000
+ eor ip, ip, r2
+ rsbmi r1, r1, #0
+ orr ip, r2, ip, lsr #1 /* ip bit 0x40000000 = -ve division */
+ /* ip bit 0x80000000 = -ve remainder */
+
+.L_divide_l1:
+ mov r2, #1
+ mov r3, #0
+
+ /*
+ * If the highest bit of the dividend is set, we have to be
+ * careful when shifting the divisor. Test this.
+ */
+ movs r1,r1
+ bpl .L_old_code
+
+ /*
+ * At this point, the highest bit of r1 is known to be set.
+ * We abuse this below in the tst instructions.
+ */
+ tst r1, r0 /*, lsl #0 */
+ bmi .L_divide_b1
+ tst r1, r0, lsl #1
+ bmi .L_divide_b2
+ tst r1, r0, lsl #2
+ bmi .L_divide_b3
+ tst r1, r0, lsl #3
+ bmi .L_divide_b4
+ tst r1, r0, lsl #4
+ bmi .L_divide_b5
+ tst r1, r0, lsl #5
+ bmi .L_divide_b6
+ tst r1, r0, lsl #6
+ bmi .L_divide_b7
+ tst r1, r0, lsl #7
+ bmi .L_divide_b8
+ tst r1, r0, lsl #8
+ bmi .L_divide_b9
+ tst r1, r0, lsl #9
+ bmi .L_divide_b10
+ tst r1, r0, lsl #10
+ bmi .L_divide_b11
+ tst r1, r0, lsl #11
+ bmi .L_divide_b12
+ tst r1, r0, lsl #12
+ bmi .L_divide_b13
+ tst r1, r0, lsl #13
+ bmi .L_divide_b14
+ tst r1, r0, lsl #14
+ bmi .L_divide_b15
+ tst r1, r0, lsl #15
+ bmi .L_divide_b16
+ tst r1, r0, lsl #16
+ bmi .L_divide_b17
+ tst r1, r0, lsl #17
+ bmi .L_divide_b18
+ tst r1, r0, lsl #18
+ bmi .L_divide_b19
+ tst r1, r0, lsl #19
+ bmi .L_divide_b20
+ tst r1, r0, lsl #20
+ bmi .L_divide_b21
+ tst r1, r0, lsl #21
+ bmi .L_divide_b22
+ tst r1, r0, lsl #22
+ bmi .L_divide_b23
+ tst r1, r0, lsl #23
+ bmi .L_divide_b24
+ tst r1, r0, lsl #24
+ bmi .L_divide_b25
+ tst r1, r0, lsl #25
+ bmi .L_divide_b26
+ tst r1, r0, lsl #26
+ bmi .L_divide_b27
+ tst r1, r0, lsl #27
+ bmi .L_divide_b28
+ tst r1, r0, lsl #28
+ bmi .L_divide_b29
+ tst r1, r0, lsl #29
+ bmi .L_divide_b30
+ tst r1, r0, lsl #30
+ bmi .L_divide_b31
+/*
+ * instead of:
+ * tst r1, r0, lsl #31
+ * bmi .L_divide_b32
+ */
+ b .L_divide_b32
+
+.L_old_code:
+ cmp r1, r0
+ bcc .L_divide_b0
+ cmp r1, r0, lsl #1
+ bcc .L_divide_b1
+ cmp r1, r0, lsl #2
+ bcc .L_divide_b2
+ cmp r1, r0, lsl #3
+ bcc .L_divide_b3
+ cmp r1, r0, lsl #4
+ bcc .L_divide_b4
+ cmp r1, r0, lsl #5
+ bcc .L_divide_b5
+ cmp r1, r0, lsl #6
+ bcc .L_divide_b6
+ cmp r1, r0, lsl #7
+ bcc .L_divide_b7
+ cmp r1, r0, lsl #8
+ bcc .L_divide_b8
+ cmp r1, r0, lsl #9
+ bcc .L_divide_b9
+ cmp r1, r0, lsl #10
+ bcc .L_divide_b10
+ cmp r1, r0, lsl #11
+ bcc .L_divide_b11
+ cmp r1, r0, lsl #12
+ bcc .L_divide_b12
+ cmp r1, r0, lsl #13
+ bcc .L_divide_b13
+ cmp r1, r0, lsl #14
+ bcc .L_divide_b14
+ cmp r1, r0, lsl #15
+ bcc .L_divide_b15
+ cmp r1, r0, lsl #16
+ bcc .L_divide_b16
+ cmp r1, r0, lsl #17
+ bcc .L_divide_b17
+ cmp r1, r0, lsl #18
+ bcc .L_divide_b18
+ cmp r1, r0, lsl #19
+ bcc .L_divide_b19
+ cmp r1, r0, lsl #20
+ bcc .L_divide_b20
+ cmp r1, r0, lsl #21
+ bcc .L_divide_b21
+ cmp r1, r0, lsl #22
+ bcc .L_divide_b22
+ cmp r1, r0, lsl #23
+ bcc .L_divide_b23
+ cmp r1, r0, lsl #24
+ bcc .L_divide_b24
+ cmp r1, r0, lsl #25
+ bcc .L_divide_b25
+ cmp r1, r0, lsl #26
+ bcc .L_divide_b26
+ cmp r1, r0, lsl #27
+ bcc .L_divide_b27
+ cmp r1, r0, lsl #28
+ bcc .L_divide_b28
+ cmp r1, r0, lsl #29
+ bcc .L_divide_b29
+ cmp r1, r0, lsl #30
+ bcc .L_divide_b30
+.L_divide_b32:
+ cmp r1, r0, lsl #31
+ subhs r1, r1,r0, lsl #31
+ addhs r3, r3,r2, lsl #31
+.L_divide_b31:
+ cmp r1, r0, lsl #30
+ subhs r1, r1,r0, lsl #30
+ addhs r3, r3,r2, lsl #30
+.L_divide_b30:
+ cmp r1, r0, lsl #29
+ subhs r1, r1,r0, lsl #29
+ addhs r3, r3,r2, lsl #29
+.L_divide_b29:
+ cmp r1, r0, lsl #28
+ subhs r1, r1,r0, lsl #28
+ addhs r3, r3,r2, lsl #28
+.L_divide_b28:
+ cmp r1, r0, lsl #27
+ subhs r1, r1,r0, lsl #27
+ addhs r3, r3,r2, lsl #27
+.L_divide_b27:
+ cmp r1, r0, lsl #26
+ subhs r1, r1,r0, lsl #26
+ addhs r3, r3,r2, lsl #26
+.L_divide_b26:
+ cmp r1, r0, lsl #25
+ subhs r1, r1,r0, lsl #25
+ addhs r3, r3,r2, lsl #25
+.L_divide_b25:
+ cmp r1, r0, lsl #24
+ subhs r1, r1,r0, lsl #24
+ addhs r3, r3,r2, lsl #24
+.L_divide_b24:
+ cmp r1, r0, lsl #23
+ subhs r1, r1,r0, lsl #23
+ addhs r3, r3,r2, lsl #23
+.L_divide_b23:
+ cmp r1, r0, lsl #22
+ subhs r1, r1,r0, lsl #22
+ addhs r3, r3,r2, lsl #22
+.L_divide_b22:
+ cmp r1, r0, lsl #21
+ subhs r1, r1,r0, lsl #21
+ addhs r3, r3,r2, lsl #21
+.L_divide_b21:
+ cmp r1, r0, lsl #20
+ subhs r1, r1,r0, lsl #20
+ addhs r3, r3,r2, lsl #20
+.L_divide_b20:
+ cmp r1, r0, lsl #19
+ subhs r1, r1,r0, lsl #19
+ addhs r3, r3,r2, lsl #19
+.L_divide_b19:
+ cmp r1, r0, lsl #18
+ subhs r1, r1,r0, lsl #18
+ addhs r3, r3,r2, lsl #18
+.L_divide_b18:
+ cmp r1, r0, lsl #17
+ subhs r1, r1,r0, lsl #17
+ addhs r3, r3,r2, lsl #17
+.L_divide_b17:
+ cmp r1, r0, lsl #16
+ subhs r1, r1,r0, lsl #16
+ addhs r3, r3,r2, lsl #16
+.L_divide_b16:
+ cmp r1, r0, lsl #15
+ subhs r1, r1,r0, lsl #15
+ addhs r3, r3,r2, lsl #15
+.L_divide_b15:
+ cmp r1, r0, lsl #14
+ subhs r1, r1,r0, lsl #14
+ addhs r3, r3,r2, lsl #14
+.L_divide_b14:
+ cmp r1, r0, lsl #13
+ subhs r1, r1,r0, lsl #13
+ addhs r3, r3,r2, lsl #13
+.L_divide_b13:
+ cmp r1, r0, lsl #12
+ subhs r1, r1,r0, lsl #12
+ addhs r3, r3,r2, lsl #12
+.L_divide_b12:
+ cmp r1, r0, lsl #11
+ subhs r1, r1,r0, lsl #11
+ addhs r3, r3,r2, lsl #11
+.L_divide_b11:
+ cmp r1, r0, lsl #10
+ subhs r1, r1,r0, lsl #10
+ addhs r3, r3,r2, lsl #10
+.L_divide_b10:
+ cmp r1, r0, lsl #9
+ subhs r1, r1,r0, lsl #9
+ addhs r3, r3,r2, lsl #9
+.L_divide_b9:
+ cmp r1, r0, lsl #8
+ subhs r1, r1,r0, lsl #8
+ addhs r3, r3,r2, lsl #8
+.L_divide_b8:
+ cmp r1, r0, lsl #7
+ subhs r1, r1,r0, lsl #7
+ addhs r3, r3,r2, lsl #7
+.L_divide_b7:
+ cmp r1, r0, lsl #6
+ subhs r1, r1,r0, lsl #6
+ addhs r3, r3,r2, lsl #6
+.L_divide_b6:
+ cmp r1, r0, lsl #5
+ subhs r1, r1,r0, lsl #5
+ addhs r3, r3,r2, lsl #5
+.L_divide_b5:
+ cmp r1, r0, lsl #4
+ subhs r1, r1,r0, lsl #4
+ addhs r3, r3,r2, lsl #4
+.L_divide_b4:
+ cmp r1, r0, lsl #3
+ subhs r1, r1,r0, lsl #3
+ addhs r3, r3,r2, lsl #3
+.L_divide_b3:
+ cmp r1, r0, lsl #2
+ subhs r1, r1,r0, lsl #2
+ addhs r3, r3,r2, lsl #2
+.L_divide_b2:
+ cmp r1, r0, lsl #1
+ subhs r1, r1,r0, lsl #1
+ addhs r3, r3,r2, lsl #1
+.L_divide_b1:
+ cmp r1, r0
+ subhs r1, r1, r0
+ addhs r3, r3, r2
+.L_divide_b0:
+
+ tst ip, #0x20000000
+ bne .L_udivide_l1
+ mov r0, r3
+ cmp ip, #0
+ rsbmi r1, r1, #0
+ movs ip, ip, lsl #1
+ bicmi r0, r0, #0x80000000 /* Fix incase we divided 0x80000000 */
+ rsbmi r0, r0, #0
+ RET
+
+.L_udivide_l1:
+ tst ip, #0x10000000
+ mov r1, r1, lsl #1
+ orrne r1, r1, #1
+ mov r3, r3, lsl #1
+ cmp r1, r0
+ subhs r1, r1, r0
+ addhs r3, r3, r2
+ mov r0, r3
+ RET
diff --git a/lib/libc/arm/gen/fabs.c b/lib/libc/arm/gen/fabs.c
new file mode 100644
index 0000000..8bb1502
--- /dev/null
+++ b/lib/libc/arm/gen/fabs.c
@@ -0,0 +1,46 @@
+/* $NetBSD: fabs.c,v 1.2 2002/05/26 11:48:01 wiz Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * fabs(x) returns the absolute value of x.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+double
+fabs(double x)
+{
+ if (x < 0)
+ x = -x;
+ return(x);
+}
diff --git a/lib/libc/arm/gen/flt_rounds.c b/lib/libc/arm/gen/flt_rounds.c
new file mode 100644
index 0000000..81ab08b
--- /dev/null
+++ b/lib/libc/arm/gen/flt_rounds.c
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2012 Ian Lepore <freebsd@damnhippie.dyndns.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <fenv.h>
+#include <float.h>
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+int
+__flt_rounds(void)
+{
+
+#ifndef ARM_HARD_FLOAT
+ /*
+ * Translate our rounding modes to the unnamed
+ * manifest constants required by C99 et. al.
+ */
+ switch (__softfloat_float_rounding_mode) {
+ case FE_TOWARDZERO:
+ return (0);
+ case FE_TONEAREST:
+ return (1);
+ case FE_UPWARD:
+ return (2);
+ case FE_DOWNWARD:
+ return (3);
+ }
+ return (-1);
+#else /* ARM_HARD_FLOAT */
+ /*
+ * Apparently, the rounding mode is specified as part of the
+ * instruction format on ARM, so the dynamic rounding mode is
+ * indeterminate. Some FPUs may differ.
+ */
+ return (-1);
+#endif /* ARM_HARD_FLOAT */
+}
diff --git a/lib/libc/arm/gen/getcontextx.c b/lib/libc/arm/gen/getcontextx.c
new file mode 100644
index 0000000..307978a
--- /dev/null
+++ b/lib/libc/arm/gen/getcontextx.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int
+__getcontextx_size(void)
+{
+
+ return (sizeof(ucontext_t));
+}
+
+int
+__fillcontextx(char *ctx)
+{
+ ucontext_t *ucp;
+
+ ucp = (ucontext_t *)ctx;
+ return (getcontext(ucp));
+}
+
+__weak_reference(__getcontextx, getcontextx);
+
+ucontext_t *
+__getcontextx(void)
+{
+ char *ctx;
+ int error;
+
+ ctx = malloc(__getcontextx_size());
+ if (ctx == NULL)
+ return (NULL);
+ if (__fillcontextx(ctx) == -1) {
+ error = errno;
+ free(ctx);
+ errno = error;
+ return (NULL);
+ }
+ return ((ucontext_t *)ctx);
+}
diff --git a/lib/libc/arm/gen/infinity.c b/lib/libc/arm/gen/infinity.c
new file mode 100644
index 0000000..60faf42
--- /dev/null
+++ b/lib/libc/arm/gen/infinity.c
@@ -0,0 +1,26 @@
+/*
+ * infinity.c
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <math.h>
+
+/* bytes for +Infinity on a 387 */
+const union __infinity_un __infinity = {
+#if BYTE_ORDER == BIG_ENDIAN
+ { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }
+#else
+ { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }
+#endif
+};
+
+/* bytes for NaN */
+const union __nan_un __nan = {
+#if BYTE_ORDER == BIG_ENDIAN
+ {0xff, 0xc0, 0, 0}
+#else
+ { 0, 0, 0xc0, 0xff }
+#endif
+};
diff --git a/lib/libc/arm/gen/makecontext.c b/lib/libc/arm/gen/makecontext.c
new file mode 100644
index 0000000..4b0f92d
--- /dev/null
+++ b/lib/libc/arm/gen/makecontext.c
@@ -0,0 +1,89 @@
+/* $NetBSD: makecontext.c,v 1.2 2003/01/18 11:06:24 thorpej Exp $ */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <stddef.h>
+#include <inttypes.h>
+#include <ucontext.h>
+
+#include <stdarg.h>
+
+extern void _ctx_start(void);
+
+void
+ctx_done(ucontext_t *ucp)
+{
+
+ if (ucp->uc_link == NULL)
+ exit(0);
+ else {
+ setcontext((const ucontext_t *)ucp->uc_link);
+ abort();
+ }
+}
+
+__weak_reference(__makecontext, makecontext);
+
+void
+__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
+{
+ __greg_t *gr = ucp->uc_mcontext.__gregs;
+ int i;
+ unsigned int *sp;
+ va_list ap;
+
+ /* Compute and align stack pointer. */
+ sp = (unsigned int *)
+ (((uintptr_t)ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size -
+ sizeof(double)) & ~7);
+ /* Allocate necessary stack space for arguments exceeding r0-3. */
+ if (argc > 4)
+ sp -= argc - 4;
+ gr[_REG_SP] = (__greg_t)sp;
+ /* Wipe out frame pointer. */
+ gr[_REG_FP] = 0;
+ /* Arrange for return via the trampoline code. */
+ gr[_REG_PC] = (__greg_t)_ctx_start;
+ gr[_REG_R4] = (__greg_t)func;
+ gr[_REG_R5] = (__greg_t)ucp;
+
+ va_start(ap, argc);
+ /* Pass up to four arguments in r0-3. */
+ for (i = 0; i < argc && i < 4; i++)
+ gr[_REG_R0 + i] = va_arg(ap, int);
+ /* Pass any additional arguments on the stack. */
+ for (argc -= i; argc > 0; argc--)
+ *sp++ = va_arg(ap, int);
+ va_end(ap);
+}
diff --git a/lib/libc/arm/gen/setjmp.S b/lib/libc/arm/gen/setjmp.S
new file mode 100644
index 0000000..e5f581f
--- /dev/null
+++ b/lib/libc/arm/gen/setjmp.S
@@ -0,0 +1,129 @@
+/* $NetBSD: setjmp.S,v 1.5 2003/04/05 23:08:51 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 1997 Mark Brinicombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+/*
+ * C library -- setjmp, longjmp
+ *
+ * longjmp(a,v)
+ * will generate a "return(v)" from the last call to
+ * setjmp(a)
+ * by restoring registers from the stack.
+ * The previous signal state is restored.
+ */
+
+ENTRY(setjmp)
+ /* Block all signals and retrieve the old signal mask */
+ stmfd sp!, {r0, r14}
+ add r2, r0, #(25 * 4) /* oset */
+ mov r0, #0x00000001 /* SIG_BLOCK */
+ mov r1, #0 /* set */
+
+ bl PIC_SYM(_C_LABEL(sigprocmask), PLT)
+
+ ldmfd sp!, {r0, r14}
+
+ ldr r1, .Lsetjmp_magic
+ str r1, [r0], #4
+
+#ifdef __SOFTFP__
+ add r0, r0, #52
+#else
+ /* Store fp registers */
+ sfm f4, 4, [r0], #48
+ /* Store fpsr */
+ rfs r1
+ str r1, [r0], #0x0004
+#endif /* __SOFTFP__ */
+ /* Store integer registers */
+ stmia r0, {r4-r14}
+ mov r0, #0x00000000
+ RET
+
+.Lsetjmp_magic:
+ .word _JB_MAGIC_SETJMP
+
+
+.weak _C_LABEL(longjmp)
+.set _C_LABEL(longjmp), _C_LABEL(__longjmp)
+ENTRY(__longjmp)
+ ldr r2, .Lsetjmp_magic
+ ldr r3, [r0]
+ teq r2, r3
+ bne botch
+
+
+ /* Set signal mask */
+ stmfd sp!, {r0, r1, r14}
+ sub sp, sp, #4 /* align the stack */
+
+ add r1, r0, #(25 * 4) /* Signal mask */
+ mov r0, #3 /* SIG_SETMASK */
+ mov r2, #0
+ bl PIC_SYM(_C_LABEL(sigprocmask), PLT)
+
+ add sp, sp, #4 /* unalign the stack */
+ ldmfd sp!, {r0, r1, r14}
+
+ add r0, r0, #4
+#ifdef __SOFTFP__
+ add r0, r0, #52
+#else
+ /* Restore fp registers */
+ lfm f4, 4, [r0], #48
+ /* Restore FPSR */
+ ldr r4, [r0], #0x0004
+ wfs r4
+#endif /* __SOFTFP__ */
+ /* Restore integer registers */
+ ldmia r0, {r4-r14}
+
+ /* Validate sp and r14 */
+ teq sp, #0
+ teqne r14, #0
+ beq botch
+
+ /* Set return value */
+
+ mov r0, r1
+ teq r0, #0x00000000
+ moveq r0, #0x00000001
+ RET
+
+ /* validation failed, die die die. */
+botch:
+ bl PIC_SYM(_C_LABEL(longjmperror), PLT)
+ bl PIC_SYM(_C_LABEL(abort), PLT)
+ b . - 8 /* Cannot get here */
diff --git a/lib/libc/arm/gen/signalcontext.c b/lib/libc/arm/gen/signalcontext.c
new file mode 100644
index 0000000..bb9a54d
--- /dev/null
+++ b/lib/libc/arm/gen/signalcontext.c
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 2004 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/signal.h>
+#include <sys/ucontext.h>
+
+#include <machine/frame.h>
+#include <machine/sigframe.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <strings.h>
+#include <signal.h>
+
+__weak_reference(__signalcontext, signalcontext);
+
+extern void _ctx_start(void);
+
+int
+__signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func)
+{
+ struct sigframe *sfp;
+ __greg_t *gr = ucp->uc_mcontext.__gregs;
+ unsigned int *sp;
+
+ sp = (unsigned int *)gr[_REG_SP];
+
+ sfp = (struct sigframe *)sp - 1;
+
+ bzero(sfp, sizeof(*sfp));
+ bcopy(ucp, &sfp->sf_uc, sizeof(*ucp));
+ sfp->sf_si.si_signo = sig;
+
+ gr[_REG_SP] = (__greg_t)sfp;
+ /* Wipe out frame pointer. */
+ gr[_REG_FP] = 0;
+ /* Arrange for return via the trampoline code. */
+ gr[_REG_PC] = (__greg_t)_ctx_start;
+ gr[_REG_R4] = (__greg_t)func;
+ gr[_REG_R5] = (__greg_t)ucp;
+ gr[_REG_R0] = (__greg_t)sig;
+ gr[_REG_R1] = (__greg_t)&sfp->sf_si;
+ gr[_REG_R2] = (__greg_t)&sfp->sf_uc;
+
+ ucp->uc_link = &sfp->sf_uc;
+ sigdelset(&ucp->uc_sigmask, sig);
+
+ return (0);
+}
diff --git a/lib/libc/arm/gen/sigsetjmp.S b/lib/libc/arm/gen/sigsetjmp.S
new file mode 100644
index 0000000..09ec256
--- /dev/null
+++ b/lib/libc/arm/gen/sigsetjmp.S
@@ -0,0 +1,62 @@
+/* $NetBSD: sigsetjmp.S,v 1.3 2002/08/17 19:54:30 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1997 Mark Brinicombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * C library -- sigsetjmp, siglongjmp
+ *
+ * longjmp(a,v)
+ * will generate a "return(v)" from the last call to
+ * setjmp(a, m)
+ * by restoring registers from the stack.
+ * The previous signal state is restored.
+ */
+
+ENTRY(sigsetjmp)
+ teq r1, #0
+ beq PIC_SYM(_C_LABEL(_setjmp), PLT)
+ b PIC_SYM(_C_LABEL(setjmp), PLT)
+
+.L_setjmp_magic:
+ .word _JB_MAGIC__SETJMP
+WEAK_ALIAS(__siglongjmp, siglongjmp)
+
+ENTRY(siglongjmp)
+ ldr r2, .L_setjmp_magic
+ ldr r3, [r0]
+ teq r2, r3
+ beq PIC_SYM(_C_LABEL(_longjmp), PLT)
+ b PIC_SYM(_C_LABEL(longjmp), PLT)
diff --git a/lib/libc/arm/softfloat/arm-gcc.h b/lib/libc/arm/softfloat/arm-gcc.h
new file mode 100644
index 0000000..1204108
--- /dev/null
+++ b/lib/libc/arm/softfloat/arm-gcc.h
@@ -0,0 +1,101 @@
+/* $NetBSD: arm-gcc.h,v 1.2 2001/02/21 18:09:25 bjh21 Exp $ */
+/* $FreeBSD$ */
+
+/*
+-------------------------------------------------------------------------------
+One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined.
+-------------------------------------------------------------------------------
+*/
+#ifdef __ARMEB__
+#define BIGENDIAN
+#else
+#define LITTLEENDIAN
+#endif
+
+/*
+-------------------------------------------------------------------------------
+The macro `BITS64' can be defined to indicate that 64-bit integer types are
+supported by the compiler.
+-------------------------------------------------------------------------------
+*/
+#define BITS64
+
+/*
+-------------------------------------------------------------------------------
+Each of the following `typedef's defines the most convenient type that holds
+integers of at least as many bits as specified. For example, `uint8' should
+be the most convenient type that can hold unsigned integers of as many as
+8 bits. The `flag' type must be able to hold either a 0 or 1. For most
+implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
+to the same as `int'.
+-------------------------------------------------------------------------------
+*/
+typedef int flag;
+typedef int uint8;
+typedef int int8;
+typedef int uint16;
+typedef int int16;
+typedef unsigned int uint32;
+typedef signed int int32;
+#ifdef BITS64
+typedef unsigned long long int uint64;
+typedef signed long long int int64;
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Each of the following `typedef's defines a type that holds integers
+of _exactly_ the number of bits specified. For instance, for most
+implementation of C, `bits16' and `sbits16' should be `typedef'ed to
+`unsigned short int' and `signed short int' (or `short int'), respectively.
+-------------------------------------------------------------------------------
+*/
+typedef unsigned char bits8;
+typedef signed char sbits8;
+typedef unsigned short int bits16;
+typedef signed short int sbits16;
+typedef unsigned int bits32;
+typedef signed int sbits32;
+#ifdef BITS64
+typedef unsigned long long int bits64;
+typedef signed long long int sbits64;
+#endif
+
+#ifdef BITS64
+/*
+-------------------------------------------------------------------------------
+The `LIT64' macro takes as its argument a textual integer literal and
+if necessary ``marks'' the literal as having a 64-bit integer type.
+For example, the GNU C Compiler (`gcc') requires that 64-bit literals be
+appended with the letters `LL' standing for `long long', which is `gcc's
+name for the 64-bit integer type. Some compilers may allow `LIT64' to be
+defined as the identity macro: `#define LIT64( a ) a'.
+-------------------------------------------------------------------------------
+*/
+#define LIT64( a ) a##LL
+#endif
+
+/*
+-------------------------------------------------------------------------------
+The macro `INLINE' can be used before functions that should be inlined. If
+a compiler does not support explicit inlining, this macro should be defined
+to be `static'.
+-------------------------------------------------------------------------------
+*/
+#define INLINE static __inline
+
+/*
+-------------------------------------------------------------------------------
+The ARM FPA is odd in that it stores doubles high-order word first, no matter
+what the endianness of the CPU. VFP is sane.
+-------------------------------------------------------------------------------
+*/
+#if defined(SOFTFLOAT_FOR_GCC)
+#if defined(__VFP_FP__) || defined(__ARMEB__)
+#define FLOAT64_DEMANGLE(a) (a)
+#define FLOAT64_MANGLE(a) (a)
+#else
+#define FLOAT64_DEMANGLE(a) (((a) << 32) | ((a) >> 32))
+#define FLOAT64_MANGLE(a) FLOAT64_DEMANGLE(a)
+#endif
+#endif
diff --git a/lib/libc/arm/softfloat/milieu.h b/lib/libc/arm/softfloat/milieu.h
new file mode 100644
index 0000000..54775c7
--- /dev/null
+++ b/lib/libc/arm/softfloat/milieu.h
@@ -0,0 +1,49 @@
+/* $NetBSD: milieu.h,v 1.1 2000/12/29 20:13:54 bjh21 Exp $ */
+/* $FreeBSD$ */
+
+/*
+===============================================================================
+
+This C header file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+Include common integer types and flags.
+-------------------------------------------------------------------------------
+*/
+#include "arm-gcc.h"
+
+/*
+-------------------------------------------------------------------------------
+Symbolic Boolean literals.
+-------------------------------------------------------------------------------
+*/
+enum {
+ FALSE = 0,
+ TRUE = 1
+};
diff --git a/lib/libc/arm/softfloat/softfloat.h b/lib/libc/arm/softfloat/softfloat.h
new file mode 100644
index 0000000..6aef499
--- /dev/null
+++ b/lib/libc/arm/softfloat/softfloat.h
@@ -0,0 +1,315 @@
+/* $NetBSD: softfloat.h,v 1.6 2002/05/12 13:12:46 bjh21 Exp $ */
+/* $FreeBSD$ */
+
+/* This is a derivative work. */
+
+/*
+===============================================================================
+
+This C header file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+The macro `FLOATX80' must be defined to enable the extended double-precision
+floating-point format `floatx80'. If this macro is not defined, the
+`floatx80' type will not be defined, and none of the functions that either
+input or output the `floatx80' type will be defined. The same applies to
+the `FLOAT128' macro and the quadruple-precision format `float128'.
+-------------------------------------------------------------------------------
+*/
+/* #define FLOATX80 */
+/* #define FLOAT128 */
+
+#include <fenv.h>
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point types.
+-------------------------------------------------------------------------------
+*/
+typedef unsigned int float32;
+typedef unsigned long long float64;
+#ifdef FLOATX80
+typedef struct {
+ unsigned short high;
+ unsigned long long low;
+} floatx80;
+#endif
+#ifdef FLOAT128
+typedef struct {
+ unsigned long long high, low;
+} float128;
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point underflow tininess-detection mode.
+-------------------------------------------------------------------------------
+*/
+#ifndef SOFTFLOAT_FOR_GCC
+extern int float_detect_tininess;
+#endif
+enum {
+ float_tininess_after_rounding = 0,
+ float_tininess_before_rounding = 1
+};
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point rounding mode.
+-------------------------------------------------------------------------------
+*/
+extern int float_rounding_mode;
+enum {
+ float_round_nearest_even = FE_TONEAREST,
+ float_round_to_zero = FE_TOWARDZERO,
+ float_round_down = FE_DOWNWARD,
+ float_round_up = FE_UPWARD
+};
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point exception flags.
+-------------------------------------------------------------------------------
+*/
+extern int float_exception_flags;
+extern int float_exception_mask;
+enum {
+ float_flag_inexact = FE_INEXACT,
+ float_flag_underflow = FE_UNDERFLOW,
+ float_flag_overflow = FE_OVERFLOW,
+ float_flag_divbyzero = FE_DIVBYZERO,
+ float_flag_invalid = FE_INVALID
+};
+
+/*
+-------------------------------------------------------------------------------
+Routine to raise any or all of the software IEC/IEEE floating-point
+exception flags.
+-------------------------------------------------------------------------------
+*/
+void float_raise( int );
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE integer-to-floating-point conversion routines.
+-------------------------------------------------------------------------------
+*/
+float32 int32_to_float32( int );
+float64 int32_to_float64( int );
+#ifdef FLOATX80
+floatx80 int32_to_floatx80( int );
+#endif
+#ifdef FLOAT128
+float128 int32_to_float128( int );
+#endif
+#ifndef SOFTFLOAT_FOR_GCC /* __floatdi?f is in libgcc2.c */
+float32 int64_to_float32( long long );
+float64 int64_to_float64( long long );
+#ifdef FLOATX80
+floatx80 int64_to_floatx80( long long );
+#endif
+#ifdef FLOAT128
+float128 int64_to_float128( long long );
+#endif
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE single-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float32_to_int32( float32 );
+int float32_to_int32_round_to_zero( float32 );
+#if defined(SOFTFLOAT_FOR_GCC) && defined(SOFTFLOAT_NEED_FIXUNS)
+unsigned int float32_to_uint32_round_to_zero( float32 );
+#endif
+#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */
+long long float32_to_int64( float32 );
+long long float32_to_int64_round_to_zero( float32 );
+#endif
+float64 float32_to_float64( float32 );
+#ifdef FLOATX80
+floatx80 float32_to_floatx80( float32 );
+#endif
+#ifdef FLOAT128
+float128 float32_to_float128( float32 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE single-precision operations.
+-------------------------------------------------------------------------------
+*/
+float32 float32_round_to_int( float32 );
+float32 float32_add( float32, float32 );
+float32 float32_sub( float32, float32 );
+float32 float32_mul( float32, float32 );
+float32 float32_div( float32, float32 );
+float32 float32_rem( float32, float32 );
+float32 float32_sqrt( float32 );
+int float32_eq( float32, float32 );
+int float32_le( float32, float32 );
+int float32_lt( float32, float32 );
+int float32_eq_signaling( float32, float32 );
+int float32_le_quiet( float32, float32 );
+int float32_lt_quiet( float32, float32 );
+#ifndef SOFTFLOAT_FOR_GCC
+int float32_is_signaling_nan( float32 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE double-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float64_to_int32( float64 );
+int float64_to_int32_round_to_zero( float64 );
+#if defined(SOFTFLOAT_FOR_GCC) && defined(SOFTFLOAT_NEED_FIXUNS)
+unsigned int float64_to_uint32_round_to_zero( float64 );
+#endif
+#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */
+long long float64_to_int64( float64 );
+long long float64_to_int64_round_to_zero( float64 );
+#endif
+float32 float64_to_float32( float64 );
+#ifdef FLOATX80
+floatx80 float64_to_floatx80( float64 );
+#endif
+#ifdef FLOAT128
+float128 float64_to_float128( float64 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE double-precision operations.
+-------------------------------------------------------------------------------
+*/
+float64 float64_round_to_int( float64 );
+float64 float64_add( float64, float64 );
+float64 float64_sub( float64, float64 );
+float64 float64_mul( float64, float64 );
+float64 float64_div( float64, float64 );
+float64 float64_rem( float64, float64 );
+float64 float64_sqrt( float64 );
+int float64_eq( float64, float64 );
+int float64_le( float64, float64 );
+int float64_lt( float64, float64 );
+int float64_eq_signaling( float64, float64 );
+int float64_le_quiet( float64, float64 );
+int float64_lt_quiet( float64, float64 );
+#ifndef SOFTFLOAT_FOR_GCC
+int float64_is_signaling_nan( float64 );
+#endif
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int floatx80_to_int32( floatx80 );
+int floatx80_to_int32_round_to_zero( floatx80 );
+long long floatx80_to_int64( floatx80 );
+long long floatx80_to_int64_round_to_zero( floatx80 );
+float32 floatx80_to_float32( floatx80 );
+float64 floatx80_to_float64( floatx80 );
+#ifdef FLOAT128
+float128 floatx80_to_float128( floatx80 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision rounding precision. Valid
+values are 32, 64, and 80.
+-------------------------------------------------------------------------------
+*/
+extern int floatx80_rounding_precision;
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision operations.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_round_to_int( floatx80 );
+floatx80 floatx80_add( floatx80, floatx80 );
+floatx80 floatx80_sub( floatx80, floatx80 );
+floatx80 floatx80_mul( floatx80, floatx80 );
+floatx80 floatx80_div( floatx80, floatx80 );
+floatx80 floatx80_rem( floatx80, floatx80 );
+floatx80 floatx80_sqrt( floatx80 );
+int floatx80_eq( floatx80, floatx80 );
+int floatx80_le( floatx80, floatx80 );
+int floatx80_lt( floatx80, floatx80 );
+int floatx80_eq_signaling( floatx80, floatx80 );
+int floatx80_le_quiet( floatx80, floatx80 );
+int floatx80_lt_quiet( floatx80, floatx80 );
+int floatx80_is_signaling_nan( floatx80 );
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE quadruple-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float128_to_int32( float128 );
+int float128_to_int32_round_to_zero( float128 );
+long long float128_to_int64( float128 );
+long long float128_to_int64_round_to_zero( float128 );
+float32 float128_to_float32( float128 );
+float64 float128_to_float64( float128 );
+#ifdef FLOATX80
+floatx80 float128_to_floatx80( float128 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE quadruple-precision operations.
+-------------------------------------------------------------------------------
+*/
+float128 float128_round_to_int( float128 );
+float128 float128_add( float128, float128 );
+float128 float128_sub( float128, float128 );
+float128 float128_mul( float128, float128 );
+float128 float128_div( float128, float128 );
+float128 float128_rem( float128, float128 );
+float128 float128_sqrt( float128 );
+int float128_eq( float128, float128 );
+int float128_le( float128, float128 );
+int float128_lt( float128, float128 );
+int float128_eq_signaling( float128, float128 );
+int float128_le_quiet( float128, float128 );
+int float128_lt_quiet( float128, float128 );
+int float128_is_signaling_nan( float128 );
+
+#endif
+
diff --git a/lib/libc/arm/string/Makefile.inc b/lib/libc/arm/string/Makefile.inc
new file mode 100644
index 0000000..0ba43e6
--- /dev/null
+++ b/lib/libc/arm/string/Makefile.inc
@@ -0,0 +1,6 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+MDSRCS+=bcmp.c bcopy.S bzero.S ffs.S memchr.c memcmp.S memcpy.S \
+ memmove.S memset.S strcat.c strchr.c strcmp.S strcpy.c strlen.S \
+ strncmp.S strrchr.c swab.c wcschr.c wcscmp.c wcslen.c wmemchr.c
diff --git a/lib/libc/arm/string/bcopy.S b/lib/libc/arm/string/bcopy.S
new file mode 100644
index 0000000..f2583fc
--- /dev/null
+++ b/lib/libc/arm/string/bcopy.S
@@ -0,0 +1,6 @@
+/* $NetBSD: bcopy.S,v 1.3 2003/10/14 07:51:45 scw Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#define _BCOPY
+#include "memmove.S"
diff --git a/lib/libc/arm/string/bzero.S b/lib/libc/arm/string/bzero.S
new file mode 100644
index 0000000..b31358d
--- /dev/null
+++ b/lib/libc/arm/string/bzero.S
@@ -0,0 +1,37 @@
+/* $NetBSD: bzero.S,v 1.3 2003/10/14 07:51:45 scw Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD$");
+
+#define _BZERO
+#include "memset.S"
diff --git a/lib/libc/arm/string/ffs.S b/lib/libc/arm/string/ffs.S
new file mode 100644
index 0000000..af4e118
--- /dev/null
+++ b/lib/libc/arm/string/ffs.S
@@ -0,0 +1,82 @@
+/* $NetBSD: ffs.S,v 1.5 2003/04/05 23:08:52 bjh21 Exp $ */
+/*
+ * Copyright (c) 2001 Christopher Gilbert
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD$");
+
+/*
+ * ffs - find first set bit, this algorithm isolates the first set
+ * bit, then multiplies the number by 0x0450fbaf which leaves the top
+ * 6 bits as an index into the table. This algorithm should be a win
+ * over the checking each bit in turn as per the C compiled version.
+ *
+ * under ARMv5 there's an instruction called CLZ (count leading Zero's) that
+ * could be used
+ *
+ * This is the ffs algorithm devised by d.seal and posted to comp.sys.arm on
+ * 16 Feb 1994.
+ */
+
+ENTRY(ffs)
+ /* Standard trick to isolate bottom bit in r0 or 0 if r0 = 0 on entry */
+ rsb r1, r0, #0
+ ands r0, r0, r1
+#ifndef _ARM_ARCH_5
+ /*
+ * now r0 has at most one set bit, call this X
+ * if X = 0, all further instructions are skipped
+ */
+ adrne r2, .L_ffs_table
+ orrne r0, r0, r0, lsl #4 /* r0 = X * 0x11 */
+ orrne r0, r0, r0, lsl #6 /* r0 = X * 0x451 */
+ rsbne r0, r0, r0, lsl #16 /* r0 = X * 0x0450fbaf */
+
+ /* now lookup in table indexed on top 6 bits of r0 */
+ ldrneb r0, [ r2, r0, lsr #26 ]
+
+ RET
+.text;
+.type .L_ffs_table, _ASM_TYPE_OBJECT;
+.L_ffs_table:
+/* 0 1 2 3 4 5 6 7 */
+ .byte 0, 1, 2, 13, 3, 7, 0, 14 /* 0- 7 */
+ .byte 4, 0, 8, 0, 0, 0, 0, 15 /* 8-15 */
+ .byte 11, 5, 0, 0, 9, 0, 0, 26 /* 16-23 */
+ .byte 0, 0, 0, 0, 0, 22, 28, 16 /* 24-31 */
+ .byte 32, 12, 6, 0, 0, 0, 0, 0 /* 32-39 */
+ .byte 10, 0, 0, 25, 0, 0, 21, 27 /* 40-47 */
+ .byte 31, 0, 0, 0, 0, 24, 0, 20 /* 48-55 */
+ .byte 30, 0, 23, 19, 29, 18, 17, 0 /* 56-63 */
+#else
+ clzne r0, r0
+ rsbne r0, r0, #32
+ RET
+#endif
diff --git a/lib/libc/arm/string/memcmp.S b/lib/libc/arm/string/memcmp.S
new file mode 100644
index 0000000..a81c960
--- /dev/null
+++ b/lib/libc/arm/string/memcmp.S
@@ -0,0 +1,180 @@
+/* $NetBSD: memcmp.S,v 1.3 2003/10/14 07:51:45 scw Exp $ */
+
+/*
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 2002 ARM Ltd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD$");
+
+ENTRY(memcmp)
+ mov ip, r0
+#if defined(_KERNEL) && !defined(_STANDALONE)
+ cmp r2, #0x06
+ beq .Lmemcmp_6bytes
+#endif
+ mov r0, #0x00
+
+ /* Are both addresses aligned the same way? */
+ cmp r2, #0x00
+ eornes r3, ip, r1
+ RETeq /* len == 0, or same addresses! */
+ tst r3, #0x03
+ subne r2, r2, #0x01
+ bne .Lmemcmp_bytewise2 /* Badly aligned. Do it the slow way */
+
+ /* Word-align the addresses, if necessary */
+ sub r3, r1, #0x05
+ ands r3, r3, #0x03
+ add r3, r3, r3, lsl #1
+ addne pc, pc, r3, lsl #3
+ nop
+
+ /* Compare up to 3 bytes */
+ ldrb r0, [ip], #0x01
+ ldrb r3, [r1], #0x01
+ subs r0, r0, r3
+ RETne
+ subs r2, r2, #0x01
+ RETeq
+
+ /* Compare up to 2 bytes */
+ ldrb r0, [ip], #0x01
+ ldrb r3, [r1], #0x01
+ subs r0, r0, r3
+ RETne
+ subs r2, r2, #0x01
+ RETeq
+
+ /* Compare 1 byte */
+ ldrb r0, [ip], #0x01
+ ldrb r3, [r1], #0x01
+ subs r0, r0, r3
+ RETne
+ subs r2, r2, #0x01
+ RETeq
+
+ /* Compare 4 bytes at a time, if possible */
+ subs r2, r2, #0x04
+ bcc .Lmemcmp_bytewise
+.Lmemcmp_word_aligned:
+ ldr r0, [ip], #0x04
+ ldr r3, [r1], #0x04
+ subs r2, r2, #0x04
+ cmpcs r0, r3
+ beq .Lmemcmp_word_aligned
+ sub r0, r0, r3
+
+ /* Correct for extra subtraction, and check if done */
+ adds r2, r2, #0x04
+ cmpeq r0, #0x00 /* If done, did all bytes match? */
+ RETeq /* Yup. Just return */
+
+ /* Re-do the final word byte-wise */
+ sub ip, ip, #0x04
+ sub r1, r1, #0x04
+
+.Lmemcmp_bytewise:
+ add r2, r2, #0x03
+.Lmemcmp_bytewise2:
+ ldrb r0, [ip], #0x01
+ ldrb r3, [r1], #0x01
+ subs r2, r2, #0x01
+ cmpcs r0, r3
+ beq .Lmemcmp_bytewise2
+ sub r0, r0, r3
+ RET
+
+#if defined(_KERNEL) && !defined(_STANDALONE)
+ /*
+ * 6 byte compares are very common, thanks to the network stack.
+ * This code is hand-scheduled to reduce the number of stalls for
+ * load results. Everything else being equal, this will be ~32%
+ * faster than a byte-wise memcmp.
+ */
+ .align 5
+.Lmemcmp_6bytes:
+ ldrb r3, [r1, #0x00] /* r3 = b2#0 */
+ ldrb r0, [ip, #0x00] /* r0 = b1#0 */
+ ldrb r2, [r1, #0x01] /* r2 = b2#1 */
+ subs r0, r0, r3 /* r0 = b1#0 - b2#0 */
+ ldreqb r3, [ip, #0x01] /* r3 = b1#1 */
+ RETne /* Return if mismatch on #0 */
+ subs r0, r3, r2 /* r0 = b1#1 - b2#1 */
+ ldreqb r3, [r1, #0x02] /* r3 = b2#2 */
+ ldreqb r0, [ip, #0x02] /* r0 = b1#2 */
+ RETne /* Return if mismatch on #1 */
+ ldrb r2, [r1, #0x03] /* r2 = b2#3 */
+ subs r0, r0, r3 /* r0 = b1#2 - b2#2 */
+ ldreqb r3, [ip, #0x03] /* r3 = b1#3 */
+ RETne /* Return if mismatch on #2 */
+ subs r0, r3, r2 /* r0 = b1#3 - b2#3 */
+ ldreqb r3, [r1, #0x04] /* r3 = b2#4 */
+ ldreqb r0, [ip, #0x04] /* r0 = b1#4 */
+ RETne /* Return if mismatch on #3 */
+ ldrb r2, [r1, #0x05] /* r2 = b2#5 */
+ subs r0, r0, r3 /* r0 = b1#4 - b2#4 */
+ ldreqb r3, [ip, #0x05] /* r3 = b1#5 */
+ RETne /* Return if mismatch on #4 */
+ sub r0, r3, r2 /* r0 = b1#5 - b2#5 */
+ RET
+#endif
diff --git a/lib/libc/arm/string/memcpy.S b/lib/libc/arm/string/memcpy.S
new file mode 100644
index 0000000..3628652
--- /dev/null
+++ b/lib/libc/arm/string/memcpy.S
@@ -0,0 +1,9 @@
+/* $NetBSD: memcpy.S,v 1.4 2003/10/14 07:51:45 scw Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#if !defined(_ARM_ARCH_5E) || defined(_STANDALONE)
+#include "memcpy_arm.S"
+#else
+#include "memcpy_xscale.S"
+#endif
diff --git a/lib/libc/arm/string/memcpy_arm.S b/lib/libc/arm/string/memcpy_arm.S
new file mode 100644
index 0000000..b84a32e
--- /dev/null
+++ b/lib/libc/arm/string/memcpy_arm.S
@@ -0,0 +1,332 @@
+/* $NetBSD: memcpy_arm.S,v 1.1 2003/10/14 07:51:45 scw Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+/*
+ * This is one fun bit of code ...
+ * Some easy listening music is suggested while trying to understand this
+ * code e.g. Iron Maiden
+ *
+ * For anyone attempting to understand it :
+ *
+ * The core code is implemented here with simple stubs for memcpy().
+ *
+ * All local labels are prefixed with Lmemcpy_
+ * Following the prefix a label starting f is used in the forward copy code
+ * while a label using b is used in the backwards copy code
+ * The source and destination addresses determine whether a forward or
+ * backward copy is performed.
+ * Separate bits of code are used to deal with the following situations
+ * for both the forward and backwards copy.
+ * unaligned source address
+ * unaligned destination address
+ * Separate copy routines are used to produce an optimised result for each
+ * of these cases.
+ * The copy code will use LDM/STM instructions to copy up to 32 bytes at
+ * a time where possible.
+ *
+ * Note: r12 (aka ip) can be trashed during the function along with
+ * r0-r3 although r0-r2 have defined uses i.e. src, dest, len through out.
+ * Additional registers are preserved prior to use i.e. r4, r5 & lr
+ *
+ * Apologies for the state of the comments ;-)
+ */
+/* LINTSTUB: Func: void *memcpy(void *dst, const void *src, size_t len) */
+ENTRY(memcpy)
+ /* save leaf functions having to store this away */
+ stmdb sp!, {r0, lr} /* memcpy() returns dest addr */
+
+ subs r2, r2, #4
+ blt .Lmemcpy_l4 /* less than 4 bytes */
+ ands r12, r0, #3
+ bne .Lmemcpy_destul /* oh unaligned destination addr */
+ ands r12, r1, #3
+ bne .Lmemcpy_srcul /* oh unaligned source addr */
+
+.Lmemcpy_t8:
+ /* We have aligned source and destination */
+ subs r2, r2, #8
+ blt .Lmemcpy_l12 /* less than 12 bytes (4 from above) */
+ subs r2, r2, #0x14
+ blt .Lmemcpy_l32 /* less than 32 bytes (12 from above) */
+ stmdb sp!, {r4} /* borrow r4 */
+
+ /* blat 32 bytes at a time */
+ /* XXX for really big copies perhaps we should use more registers */
+.Lmemcpy_loop32:
+ ldmia r1!, {r3, r4, r12, lr}
+ stmia r0!, {r3, r4, r12, lr}
+ ldmia r1!, {r3, r4, r12, lr}
+ stmia r0!, {r3, r4, r12, lr}
+ subs r2, r2, #0x20
+ bge .Lmemcpy_loop32
+
+ cmn r2, #0x10
+ ldmgeia r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
+ stmgeia r0!, {r3, r4, r12, lr}
+ subge r2, r2, #0x10
+ ldmia sp!, {r4} /* return r4 */
+
+.Lmemcpy_l32:
+ adds r2, r2, #0x14
+
+ /* blat 12 bytes at a time */
+.Lmemcpy_loop12:
+ ldmgeia r1!, {r3, r12, lr}
+ stmgeia r0!, {r3, r12, lr}
+ subges r2, r2, #0x0c
+ bge .Lmemcpy_loop12
+
+.Lmemcpy_l12:
+ adds r2, r2, #8
+ blt .Lmemcpy_l4
+
+ subs r2, r2, #4
+ ldrlt r3, [r1], #4
+ strlt r3, [r0], #4
+ ldmgeia r1!, {r3, r12}
+ stmgeia r0!, {r3, r12}
+ subge r2, r2, #4
+
+.Lmemcpy_l4:
+ /* less than 4 bytes to go */
+ adds r2, r2, #4
+#ifdef __APCS_26_
+ ldmeqia sp!, {r0, pc}^ /* done */
+#else
+ ldmeqia sp!, {r0, pc} /* done */
+#endif
+ /* copy the crud byte at a time */
+ cmp r2, #2
+ ldrb r3, [r1], #1
+ strb r3, [r0], #1
+ ldrgeb r3, [r1], #1
+ strgeb r3, [r0], #1
+ ldrgtb r3, [r1], #1
+ strgtb r3, [r0], #1
+ ldmia sp!, {r0, pc}
+
+ /* erg - unaligned destination */
+.Lmemcpy_destul:
+ rsb r12, r12, #4
+ cmp r12, #2
+
+ /* align destination with byte copies */
+ ldrb r3, [r1], #1
+ strb r3, [r0], #1
+ ldrgeb r3, [r1], #1
+ strgeb r3, [r0], #1
+ ldrgtb r3, [r1], #1
+ strgtb r3, [r0], #1
+ subs r2, r2, r12
+ blt .Lmemcpy_l4 /* less the 4 bytes */
+
+ ands r12, r1, #3
+ beq .Lmemcpy_t8 /* we have an aligned source */
+
+ /* erg - unaligned source */
+ /* This is where it gets nasty ... */
+.Lmemcpy_srcul:
+ bic r1, r1, #3
+ ldr lr, [r1], #4
+ cmp r12, #2
+ bgt .Lmemcpy_srcul3
+ beq .Lmemcpy_srcul2
+ cmp r2, #0x0c
+ blt .Lmemcpy_srcul1loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+.Lmemcpy_srcul1loop16:
+#ifdef __ARMEB__
+ mov r3, lr, lsl #8
+#else
+ mov r3, lr, lsr #8
+#endif
+ ldmia r1!, {r4, r5, r12, lr}
+#ifdef __ARMEB__
+ orr r3, r3, r4, lsr #24
+ mov r4, r4, lsl #8
+ orr r4, r4, r5, lsr #24
+ mov r5, r5, lsl #8
+ orr r5, r5, r12, lsr #24
+ mov r12, r12, lsl #8
+ orr r12, r12, lr, lsr #24
+#else
+ orr r3, r3, r4, lsl #24
+ mov r4, r4, lsr #8
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r12, lsl #24
+ mov r12, r12, lsr #8
+ orr r12, r12, lr, lsl #24
+#endif
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge .Lmemcpy_srcul1loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt .Lmemcpy_srcul1l4
+
+.Lmemcpy_srcul1loop4:
+#ifdef __ARMEB__
+ mov r12, lr, lsl #8
+#else
+ mov r12, lr, lsr #8
+#endif
+ ldr lr, [r1], #4
+#ifdef __ARMEB__
+ orr r12, r12, lr, lsr #24
+#else
+ orr r12, r12, lr, lsl #24
+#endif
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge .Lmemcpy_srcul1loop4
+
+.Lmemcpy_srcul1l4:
+ sub r1, r1, #3
+ b .Lmemcpy_l4
+
+.Lmemcpy_srcul2:
+ cmp r2, #0x0c
+ blt .Lmemcpy_srcul2loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+.Lmemcpy_srcul2loop16:
+#ifdef __ARMEB__
+ mov r3, lr, lsl #16
+#else
+ mov r3, lr, lsr #16
+#endif
+ ldmia r1!, {r4, r5, r12, lr}
+#ifdef __ARMEB__
+ orr r3, r3, r4, lsr #16
+ mov r4, r4, lsl #16
+ orr r4, r4, r5, lsr #16
+ mov r5, r5, lsl #16
+ orr r5, r5, r12, lsr #16
+ mov r12, r12, lsl #16
+ orr r12, r12, lr, lsr #16
+#else
+ orr r3, r3, r4, lsl #16
+ mov r4, r4, lsr #16
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r12, lsl #16
+ mov r12, r12, lsr #16
+ orr r12, r12, lr, lsl #16
+#endif
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge .Lmemcpy_srcul2loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt .Lmemcpy_srcul2l4
+
+.Lmemcpy_srcul2loop4:
+#ifdef __ARMEB__
+ mov r12, lr, lsl #16
+#else
+ mov r12, lr, lsr #16
+#endif
+ ldr lr, [r1], #4
+#ifdef __ARMEB__
+ orr r12, r12, lr, lsr #16
+#else
+ orr r12, r12, lr, lsl #16
+#endif
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge .Lmemcpy_srcul2loop4
+
+.Lmemcpy_srcul2l4:
+ sub r1, r1, #2
+ b .Lmemcpy_l4
+
+.Lmemcpy_srcul3:
+ cmp r2, #0x0c
+ blt .Lmemcpy_srcul3loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+.Lmemcpy_srcul3loop16:
+#ifdef __ARMEB__
+ mov r3, lr, lsl #24
+#else
+ mov r3, lr, lsr #24
+#endif
+ ldmia r1!, {r4, r5, r12, lr}
+#ifdef __ARMEB__
+ orr r3, r3, r4, lsr #8
+ mov r4, r4, lsl #24
+ orr r4, r4, r5, lsr #8
+ mov r5, r5, lsl #24
+ orr r5, r5, r12, lsr #8
+ mov r12, r12, lsl #24
+ orr r12, r12, lr, lsr #8
+#else
+ orr r3, r3, r4, lsl #8
+ mov r4, r4, lsr #24
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r12, lsl #8
+ mov r12, r12, lsr #24
+ orr r12, r12, lr, lsl #8
+#endif
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge .Lmemcpy_srcul3loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt .Lmemcpy_srcul3l4
+
+.Lmemcpy_srcul3loop4:
+#ifdef __ARMEB__
+ mov r12, lr, lsl #24
+#else
+ mov r12, lr, lsr #24
+#endif
+ ldr lr, [r1], #4
+#ifdef __ARMEB__
+ orr r12, r12, lr, lsr #8
+#else
+ orr r12, r12, lr, lsl #8
+#endif
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge .Lmemcpy_srcul3loop4
+
+.Lmemcpy_srcul3l4:
+ sub r1, r1, #1
+ b .Lmemcpy_l4
diff --git a/lib/libc/arm/string/memcpy_xscale.S b/lib/libc/arm/string/memcpy_xscale.S
new file mode 100644
index 0000000..02cca5e
--- /dev/null
+++ b/lib/libc/arm/string/memcpy_xscale.S
@@ -0,0 +1,1783 @@
+/* $NetBSD: memcpy_xscale.S,v 1.1 2003/10/14 07:51:45 scw Exp $ */
+
+/*
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/* LINTSTUB: Func: void *memcpy(void *dst, const void *src, size_t len) */
+ENTRY(memcpy)
+ pld [r1]
+ cmp r2, #0x0c
+ ble .Lmemcpy_short /* <= 12 bytes */
+ mov r3, r0 /* We must not clobber r0 */
+
+ /* Word-align the destination buffer */
+ ands ip, r3, #0x03 /* Already word aligned? */
+ beq .Lmemcpy_wordaligned /* Yup */
+ cmp ip, #0x02
+ ldrb ip, [r1], #0x01
+ sub r2, r2, #0x01
+ strb ip, [r3], #0x01
+ ldrleb ip, [r1], #0x01
+ suble r2, r2, #0x01
+ strleb ip, [r3], #0x01
+ ldrltb ip, [r1], #0x01
+ sublt r2, r2, #0x01
+ strltb ip, [r3], #0x01
+
+ /* Destination buffer is now word aligned */
+.Lmemcpy_wordaligned:
+ ands ip, r1, #0x03 /* Is src also word-aligned? */
+ bne .Lmemcpy_bad_align /* Nope. Things just got bad */
+
+ /* Quad-align the destination buffer */
+ tst r3, #0x07 /* Already quad aligned? */
+ ldrne ip, [r1], #0x04
+ stmfd sp!, {r4-r9} /* Free up some registers */
+ subne r2, r2, #0x04
+ strne ip, [r3], #0x04
+
+ /* Destination buffer quad aligned, source is at least word aligned */
+ subs r2, r2, #0x80
+ blt .Lmemcpy_w_lessthan128
+
+ /* Copy 128 bytes at a time */
+.Lmemcpy_w_loop128:
+ ldr r4, [r1], #0x04 /* LD:00-03 */
+ ldr r5, [r1], #0x04 /* LD:04-07 */
+ pld [r1, #0x18] /* Prefetch 0x20 */
+ ldr r6, [r1], #0x04 /* LD:08-0b */
+ ldr r7, [r1], #0x04 /* LD:0c-0f */
+ ldr r8, [r1], #0x04 /* LD:10-13 */
+ ldr r9, [r1], #0x04 /* LD:14-17 */
+ strd r4, [r3], #0x08 /* ST:00-07 */
+ ldr r4, [r1], #0x04 /* LD:18-1b */
+ ldr r5, [r1], #0x04 /* LD:1c-1f */
+ strd r6, [r3], #0x08 /* ST:08-0f */
+ ldr r6, [r1], #0x04 /* LD:20-23 */
+ ldr r7, [r1], #0x04 /* LD:24-27 */
+ pld [r1, #0x18] /* Prefetch 0x40 */
+ strd r8, [r3], #0x08 /* ST:10-17 */
+ ldr r8, [r1], #0x04 /* LD:28-2b */
+ ldr r9, [r1], #0x04 /* LD:2c-2f */
+ strd r4, [r3], #0x08 /* ST:18-1f */
+ ldr r4, [r1], #0x04 /* LD:30-33 */
+ ldr r5, [r1], #0x04 /* LD:34-37 */
+ strd r6, [r3], #0x08 /* ST:20-27 */
+ ldr r6, [r1], #0x04 /* LD:38-3b */
+ ldr r7, [r1], #0x04 /* LD:3c-3f */
+ strd r8, [r3], #0x08 /* ST:28-2f */
+ ldr r8, [r1], #0x04 /* LD:40-43 */
+ ldr r9, [r1], #0x04 /* LD:44-47 */
+ pld [r1, #0x18] /* Prefetch 0x60 */
+ strd r4, [r3], #0x08 /* ST:30-37 */
+ ldr r4, [r1], #0x04 /* LD:48-4b */
+ ldr r5, [r1], #0x04 /* LD:4c-4f */
+ strd r6, [r3], #0x08 /* ST:38-3f */
+ ldr r6, [r1], #0x04 /* LD:50-53 */
+ ldr r7, [r1], #0x04 /* LD:54-57 */
+ strd r8, [r3], #0x08 /* ST:40-47 */
+ ldr r8, [r1], #0x04 /* LD:58-5b */
+ ldr r9, [r1], #0x04 /* LD:5c-5f */
+ strd r4, [r3], #0x08 /* ST:48-4f */
+ ldr r4, [r1], #0x04 /* LD:60-63 */
+ ldr r5, [r1], #0x04 /* LD:64-67 */
+ pld [r1, #0x18] /* Prefetch 0x80 */
+ strd r6, [r3], #0x08 /* ST:50-57 */
+ ldr r6, [r1], #0x04 /* LD:68-6b */
+ ldr r7, [r1], #0x04 /* LD:6c-6f */
+ strd r8, [r3], #0x08 /* ST:58-5f */
+ ldr r8, [r1], #0x04 /* LD:70-73 */
+ ldr r9, [r1], #0x04 /* LD:74-77 */
+ strd r4, [r3], #0x08 /* ST:60-67 */
+ ldr r4, [r1], #0x04 /* LD:78-7b */
+ ldr r5, [r1], #0x04 /* LD:7c-7f */
+ strd r6, [r3], #0x08 /* ST:68-6f */
+ strd r8, [r3], #0x08 /* ST:70-77 */
+ subs r2, r2, #0x80
+ strd r4, [r3], #0x08 /* ST:78-7f */
+ bge .Lmemcpy_w_loop128
+
+.Lmemcpy_w_lessthan128:
+ adds r2, r2, #0x80 /* Adjust for extra sub */
+ ldmeqfd sp!, {r4-r9}
+ bxeq lr /* Return now if done */
+ subs r2, r2, #0x20
+ blt .Lmemcpy_w_lessthan32
+
+ /* Copy 32 bytes at a time */
+.Lmemcpy_w_loop32:
+ ldr r4, [r1], #0x04
+ ldr r5, [r1], #0x04
+ pld [r1, #0x18]
+ ldr r6, [r1], #0x04
+ ldr r7, [r1], #0x04
+ ldr r8, [r1], #0x04
+ ldr r9, [r1], #0x04
+ strd r4, [r3], #0x08
+ ldr r4, [r1], #0x04
+ ldr r5, [r1], #0x04
+ strd r6, [r3], #0x08
+ strd r8, [r3], #0x08
+ subs r2, r2, #0x20
+ strd r4, [r3], #0x08
+ bge .Lmemcpy_w_loop32
+
+.Lmemcpy_w_lessthan32:
+ adds r2, r2, #0x20 /* Adjust for extra sub */
+ ldmeqfd sp!, {r4-r9}
+ bxeq lr /* Return now if done */
+
+ and r4, r2, #0x18
+ rsbs r4, r4, #0x18
+ addne pc, pc, r4, lsl #1
+ nop
+
+ /* At least 24 bytes remaining */
+ ldr r4, [r1], #0x04
+ ldr r5, [r1], #0x04
+ sub r2, r2, #0x08
+ strd r4, [r3], #0x08
+
+ /* At least 16 bytes remaining */
+ ldr r4, [r1], #0x04
+ ldr r5, [r1], #0x04
+ sub r2, r2, #0x08
+ strd r4, [r3], #0x08
+
+ /* At least 8 bytes remaining */
+ ldr r4, [r1], #0x04
+ ldr r5, [r1], #0x04
+ subs r2, r2, #0x08
+ strd r4, [r3], #0x08
+
+ /* Less than 8 bytes remaining */
+ ldmfd sp!, {r4-r9}
+ bxeq lr /* Return now if done */
+ subs r2, r2, #0x04
+ ldrge ip, [r1], #0x04
+ strge ip, [r3], #0x04
+ bxeq lr /* Return now if done */
+ addlt r2, r2, #0x04
+ ldrb ip, [r1], #0x01
+ cmp r2, #0x02
+ ldrgeb r2, [r1], #0x01
+ strb ip, [r3], #0x01
+ ldrgtb ip, [r1]
+ strgeb r2, [r3], #0x01
+ strgtb ip, [r3]
+ bx lr
+
+
+/*
+ * At this point, it has not been possible to word align both buffers.
+ * The destination buffer is word aligned, but the source buffer is not.
+ */
+.Lmemcpy_bad_align:
+ stmfd sp!, {r4-r7}
+ bic r1, r1, #0x03
+ cmp ip, #2
+ ldr ip, [r1], #0x04
+ bgt .Lmemcpy_bad3
+ beq .Lmemcpy_bad2
+ b .Lmemcpy_bad1
+
+.Lmemcpy_bad1_loop16:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #8
+#else
+ mov r4, ip, lsr #8
+#endif
+ ldr r5, [r1], #0x04
+ pld [r1, #0x018]
+ ldr r6, [r1], #0x04
+ ldr r7, [r1], #0x04
+ ldr ip, [r1], #0x04
+#ifdef __ARMEB__
+ orr r4, r4, r5, lsr #24
+ mov r5, r5, lsl #8
+ orr r5, r5, r6, lsr #24
+ mov r6, r6, lsl #8
+ orr r6, r6, r7, lsr #24
+ mov r7, r7, lsl #8
+ orr r7, r7, ip, lsr #24
+#else
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r6, lsl #24
+ mov r6, r6, lsr #8
+ orr r6, r6, r7, lsl #24
+ mov r7, r7, lsr #8
+ orr r7, r7, ip, lsl #24
+#endif
+ str r4, [r3], #0x04
+ str r5, [r3], #0x04
+ str r6, [r3], #0x04
+ str r7, [r3], #0x04
+.Lmemcpy_bad1:
+ subs r2, r2, #0x10
+ bge .Lmemcpy_bad1_loop16
+
+ adds r2, r2, #0x10
+ ldmeqfd sp!, {r4-r7}
+ bxeq lr /* Return now if done */
+ subs r2, r2, #0x04
+ sublt r1, r1, #0x03
+ blt .Lmemcpy_bad_done
+
+.Lmemcpy_bad1_loop4:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #8
+#else
+ mov r4, ip, lsr #8
+#endif
+ ldr ip, [r1], #0x04
+ subs r2, r2, #0x04
+#ifdef __ARMEB__
+ orr r4, r4, ip, lsr #24
+#else
+ orr r4, r4, ip, lsl #24
+#endif
+ str r4, [r3], #0x04
+ bge .Lmemcpy_bad1_loop4
+ sub r1, r1, #0x03
+ b .Lmemcpy_bad_done
+
+.Lmemcpy_bad2_loop16:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #16
+#else
+ mov r4, ip, lsr #16
+#endif
+ ldr r5, [r1], #0x04
+ pld [r1, #0x018]
+ ldr r6, [r1], #0x04
+ ldr r7, [r1], #0x04
+ ldr ip, [r1], #0x04
+#ifdef __ARMEB__
+ orr r4, r4, r5, lsr #16
+ mov r5, r5, lsl #16
+ orr r5, r5, r6, lsr #16
+ mov r6, r6, lsl #16
+ orr r6, r6, r7, lsr #16
+ mov r7, r7, lsl #16
+ orr r7, r7, ip, lsr #16
+#else
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r6, lsl #16
+ mov r6, r6, lsr #16
+ orr r6, r6, r7, lsl #16
+ mov r7, r7, lsr #16
+ orr r7, r7, ip, lsl #16
+#endif
+ str r4, [r3], #0x04
+ str r5, [r3], #0x04
+ str r6, [r3], #0x04
+ str r7, [r3], #0x04
+.Lmemcpy_bad2:
+ subs r2, r2, #0x10
+ bge .Lmemcpy_bad2_loop16
+
+ adds r2, r2, #0x10
+ ldmeqfd sp!, {r4-r7}
+ bxeq lr /* Return now if done */
+ subs r2, r2, #0x04
+ sublt r1, r1, #0x02
+ blt .Lmemcpy_bad_done
+
+.Lmemcpy_bad2_loop4:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #16
+#else
+ mov r4, ip, lsr #16
+#endif
+ ldr ip, [r1], #0x04
+ subs r2, r2, #0x04
+#ifdef __ARMEB__
+ orr r4, r4, ip, lsr #16
+#else
+ orr r4, r4, ip, lsl #16
+#endif
+ str r4, [r3], #0x04
+ bge .Lmemcpy_bad2_loop4
+ sub r1, r1, #0x02
+ b .Lmemcpy_bad_done
+
+.Lmemcpy_bad3_loop16:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #24
+#else
+ mov r4, ip, lsr #24
+#endif
+ ldr r5, [r1], #0x04
+ pld [r1, #0x018]
+ ldr r6, [r1], #0x04
+ ldr r7, [r1], #0x04
+ ldr ip, [r1], #0x04
+#ifdef __ARMEB__
+ orr r4, r4, r5, lsr #8
+ mov r5, r5, lsl #24
+ orr r5, r5, r6, lsr #8
+ mov r6, r6, lsl #24
+ orr r6, r6, r7, lsr #8
+ mov r7, r7, lsl #24
+ orr r7, r7, ip, lsr #8
+#else
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r6, lsl #8
+ mov r6, r6, lsr #24
+ orr r6, r6, r7, lsl #8
+ mov r7, r7, lsr #24
+ orr r7, r7, ip, lsl #8
+#endif
+ str r4, [r3], #0x04
+ str r5, [r3], #0x04
+ str r6, [r3], #0x04
+ str r7, [r3], #0x04
+.Lmemcpy_bad3:
+ subs r2, r2, #0x10
+ bge .Lmemcpy_bad3_loop16
+
+ adds r2, r2, #0x10
+ ldmeqfd sp!, {r4-r7}
+ bxeq lr /* Return now if done */
+ subs r2, r2, #0x04
+ sublt r1, r1, #0x01
+ blt .Lmemcpy_bad_done
+
+.Lmemcpy_bad3_loop4:
+#ifdef __ARMEB__
+ mov r4, ip, lsl #24
+#else
+ mov r4, ip, lsr #24
+#endif
+ ldr ip, [r1], #0x04
+ subs r2, r2, #0x04
+#ifdef __ARMEB__
+ orr r4, r4, ip, lsr #8
+#else
+ orr r4, r4, ip, lsl #8
+#endif
+ str r4, [r3], #0x04
+ bge .Lmemcpy_bad3_loop4
+ sub r1, r1, #0x01
+
+.Lmemcpy_bad_done:
+ ldmfd sp!, {r4-r7}
+ adds r2, r2, #0x04
+ bxeq lr
+ ldrb ip, [r1], #0x01
+ cmp r2, #0x02
+ ldrgeb r2, [r1], #0x01
+ strb ip, [r3], #0x01
+ ldrgtb ip, [r1]
+ strgeb r2, [r3], #0x01
+ strgtb ip, [r3]
+ bx lr
+
+
+/*
+ * Handle short copies (less than 16 bytes), possibly misaligned.
+ * Some of these are *very* common, thanks to the network stack,
+ * and so are handled specially.
+ */
+.Lmemcpy_short:
+#ifndef _STANDALONE
+ add pc, pc, r2, lsl #2
+ nop
+ bx lr /* 0x00 */
+ b .Lmemcpy_bytewise /* 0x01 */
+ b .Lmemcpy_bytewise /* 0x02 */
+ b .Lmemcpy_bytewise /* 0x03 */
+ b .Lmemcpy_4 /* 0x04 */
+ b .Lmemcpy_bytewise /* 0x05 */
+ b .Lmemcpy_6 /* 0x06 */
+ b .Lmemcpy_bytewise /* 0x07 */
+ b .Lmemcpy_8 /* 0x08 */
+ b .Lmemcpy_bytewise /* 0x09 */
+ b .Lmemcpy_bytewise /* 0x0a */
+ b .Lmemcpy_bytewise /* 0x0b */
+ b .Lmemcpy_c /* 0x0c */
+#endif
+.Lmemcpy_bytewise:
+ mov r3, r0 /* We must not clobber r0 */
+ ldrb ip, [r1], #0x01
+1: subs r2, r2, #0x01
+ strb ip, [r3], #0x01
+ ldrneb ip, [r1], #0x01
+ bne 1b
+ bx lr
+
+#ifndef _STANDALONE
+/******************************************************************************
+ * Special case for 4 byte copies
+ */
+#define LMEMCPY_4_LOG2 6 /* 64 bytes */
+#define LMEMCPY_4_PAD .align LMEMCPY_4_LOG2
+ LMEMCPY_4_PAD
+.Lmemcpy_4:
+ and r2, r1, #0x03
+ orr r2, r2, r0, lsl #2
+ ands r2, r2, #0x0f
+ sub r3, pc, #0x14
+ addne pc, r3, r2, lsl #LMEMCPY_4_LOG2
+
+/*
+ * 0000: dst is 32-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1]
+ str r2, [r0]
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 0001: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldr r3, [r1, #-1] /* BE:r3 = x012 LE:r3 = 210x */
+ ldr r2, [r1, #3] /* BE:r2 = 3xxx LE:r2 = xxx3 */
+#ifdef __ARMEB__
+ mov r3, r3, lsl #8 /* r3 = 012. */
+ orr r3, r3, r2, lsr #24 /* r3 = 0123 */
+#else
+ mov r3, r3, lsr #8 /* r3 = .210 */
+ orr r3, r3, r2, lsl #24 /* r3 = 3210 */
+#endif
+ str r3, [r0]
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 0010: dst is 32-bit aligned, src is 16-bit aligned
+ */
+#ifdef __ARMEB__
+ ldrh r3, [r1]
+ ldrh r2, [r1, #0x02]
+#else
+ ldrh r3, [r1, #0x02]
+ ldrh r2, [r1]
+#endif
+ orr r3, r2, r3, lsl #16
+ str r3, [r0]
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 0011: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldr r3, [r1, #-3] /* BE:r3 = xxx0 LE:r3 = 0xxx */
+ ldr r2, [r1, #1] /* BE:r2 = 123x LE:r2 = x321 */
+#ifdef __ARMEB__
+ mov r3, r3, lsl #24 /* r3 = 0... */
+ orr r3, r3, r2, lsr #8 /* r3 = 0123 */
+#else
+ mov r3, r3, lsr #24 /* r3 = ...0 */
+ orr r3, r3, r2, lsl #8 /* r3 = 3210 */
+#endif
+ str r3, [r0]
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 0100: dst is 8-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1]
+#ifdef __ARMEB__
+ strb r2, [r0, #0x03]
+ mov r3, r2, lsr #8
+ mov r1, r2, lsr #24
+ strb r1, [r0]
+#else
+ strb r2, [r0]
+ mov r3, r2, lsr #8
+ mov r1, r2, lsr #24
+ strb r1, [r0, #0x03]
+#endif
+ strh r3, [r0, #0x01]
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 0101: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldrb r1, [r1, #0x03]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ strb r1, [r0, #0x03]
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 0110: dst is 8-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldrh r3, [r1, #0x02] /* LE:r3 = ..23 LE:r3 = ..32 */
+#ifdef __ARMEB__
+ mov r1, r2, lsr #8 /* r1 = ...0 */
+ strb r1, [r0]
+ mov r2, r2, lsl #8 /* r2 = .01. */
+ orr r2, r2, r3, lsr #8 /* r2 = .012 */
+#else
+ strb r2, [r0]
+ mov r2, r2, lsr #8 /* r2 = ...1 */
+ orr r2, r2, r3, lsl #8 /* r2 = .321 */
+ mov r3, r3, lsr #8 /* r3 = ...3 */
+#endif
+ strh r2, [r0, #0x01]
+ strb r3, [r0, #0x03]
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 0111: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldrb r1, [r1, #0x03]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ strb r1, [r0, #0x03]
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 1000: dst is 16-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1]
+#ifdef __ARMEB__
+ strh r2, [r0, #0x02]
+ mov r3, r2, lsr #16
+ strh r3, [r0]
+#else
+ strh r2, [r0]
+ mov r3, r2, lsr #16
+ strh r3, [r0, #0x02]
+#endif
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 1001: dst is 16-bit aligned, src is 8-bit aligned
+ */
+ ldr r2, [r1, #-1] /* BE:r2 = x012 LE:r2 = 210x */
+ ldr r3, [r1, #3] /* BE:r3 = 3xxx LE:r3 = xxx3 */
+ mov r1, r2, lsr #8 /* BE:r1 = .x01 LE:r1 = .210 */
+ strh r1, [r0]
+#ifdef __ARMEB__
+ mov r2, r2, lsl #8 /* r2 = 012. */
+ orr r2, r2, r3, lsr #24 /* r2 = 0123 */
+#else
+ mov r2, r2, lsr #24 /* r2 = ...2 */
+ orr r2, r2, r3, lsl #8 /* r2 = xx32 */
+#endif
+ strh r2, [r0, #0x02]
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 1010: dst is 16-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1]
+ ldrh r3, [r1, #0x02]
+ strh r2, [r0]
+ strh r3, [r0, #0x02]
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 1011: dst is 16-bit aligned, src is 8-bit aligned
+ */
+ ldr r3, [r1, #1] /* BE:r3 = 123x LE:r3 = x321 */
+ ldr r2, [r1, #-3] /* BE:r2 = xxx0 LE:r2 = 0xxx */
+ mov r1, r3, lsr #8 /* BE:r1 = .123 LE:r1 = .x32 */
+ strh r1, [r0, #0x02]
+#ifdef __ARMEB__
+ mov r3, r3, lsr #24 /* r3 = ...1 */
+ orr r3, r3, r2, lsl #8 /* r3 = xx01 */
+#else
+ mov r3, r3, lsl #8 /* r3 = 321. */
+ orr r3, r3, r2, lsr #24 /* r3 = 3210 */
+#endif
+ strh r3, [r0]
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 1100: dst is 8-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */
+#ifdef __ARMEB__
+ strb r2, [r0, #0x03]
+ mov r3, r2, lsr #8
+ mov r1, r2, lsr #24
+ strh r3, [r0, #0x01]
+ strb r1, [r0]
+#else
+ strb r2, [r0]
+ mov r3, r2, lsr #8
+ mov r1, r2, lsr #24
+ strh r3, [r0, #0x01]
+ strb r1, [r0, #0x03]
+#endif
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 1101: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldrb r1, [r1, #0x03]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ strb r1, [r0, #0x03]
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 1110: dst is 8-bit aligned, src is 16-bit aligned
+ */
+#ifdef __ARMEB__
+ ldrh r3, [r1, #0x02] /* BE:r3 = ..23 LE:r3 = ..32 */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ strb r3, [r0, #0x03]
+ mov r3, r3, lsr #8 /* r3 = ...2 */
+ orr r3, r3, r2, lsl #8 /* r3 = ..12 */
+ strh r3, [r0, #0x01]
+ mov r2, r2, lsr #8 /* r2 = ...0 */
+ strb r2, [r0]
+#else
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldrh r3, [r1, #0x02] /* BE:r3 = ..23 LE:r3 = ..32 */
+ strb r2, [r0]
+ mov r2, r2, lsr #8 /* r2 = ...1 */
+ orr r2, r2, r3, lsl #8 /* r2 = .321 */
+ strh r2, [r0, #0x01]
+ mov r3, r3, lsr #8 /* r3 = ...3 */
+ strb r3, [r0, #0x03]
+#endif
+ bx lr
+ LMEMCPY_4_PAD
+
+/*
+ * 1111: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldrb r1, [r1, #0x03]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ strb r1, [r0, #0x03]
+ bx lr
+ LMEMCPY_4_PAD
+
+
+/******************************************************************************
+ * Special case for 6 byte copies
+ */
+#define LMEMCPY_6_LOG2 6 /* 64 bytes */
+#define LMEMCPY_6_PAD .align LMEMCPY_6_LOG2
+ LMEMCPY_6_PAD
+.Lmemcpy_6:
+ and r2, r1, #0x03
+ orr r2, r2, r0, lsl #2
+ ands r2, r2, #0x0f
+ sub r3, pc, #0x14
+ addne pc, r3, r2, lsl #LMEMCPY_6_LOG2
+
+/*
+ * 0000: dst is 32-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1]
+ ldrh r3, [r1, #0x04]
+ str r2, [r0]
+ strh r3, [r0, #0x04]
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 0001: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldr r2, [r1, #-1] /* BE:r2 = x012 LE:r2 = 210x */
+ ldr r3, [r1, #0x03] /* BE:r3 = 345x LE:r3 = x543 */
+#ifdef __ARMEB__
+ mov r2, r2, lsl #8 /* r2 = 012. */
+ orr r2, r2, r3, lsr #24 /* r2 = 0123 */
+#else
+ mov r2, r2, lsr #8 /* r2 = .210 */
+ orr r2, r2, r3, lsl #24 /* r2 = 3210 */
+#endif
+ mov r3, r3, lsr #8 /* BE:r3 = .345 LE:r3 = .x54 */
+ str r2, [r0]
+ strh r3, [r0, #0x04]
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 0010: dst is 32-bit aligned, src is 16-bit aligned
+ */
+ ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+#ifdef __ARMEB__
+ mov r1, r3, lsr #16 /* r1 = ..23 */
+ orr r1, r1, r2, lsl #16 /* r1 = 0123 */
+ str r1, [r0]
+ strh r3, [r0, #0x04]
+#else
+ mov r1, r3, lsr #16 /* r1 = ..54 */
+ orr r2, r2, r3, lsl #16 /* r2 = 3210 */
+ str r2, [r0]
+ strh r1, [r0, #0x04]
+#endif
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 0011: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldr r2, [r1, #-3] /* BE:r2 = xxx0 LE:r2 = 0xxx */
+ ldr r3, [r1, #1] /* BE:r3 = 1234 LE:r3 = 4321 */
+ ldr r1, [r1, #5] /* BE:r1 = 5xxx LE:r3 = xxx5 */
+#ifdef __ARMEB__
+ mov r2, r2, lsl #24 /* r2 = 0... */
+ orr r2, r2, r3, lsr #8 /* r2 = 0123 */
+ mov r3, r3, lsl #8 /* r3 = 234. */
+ orr r1, r3, r1, lsr #24 /* r1 = 2345 */
+#else
+ mov r2, r2, lsr #24 /* r2 = ...0 */
+ orr r2, r2, r3, lsl #8 /* r2 = 3210 */
+ mov r1, r1, lsl #8 /* r1 = xx5. */
+ orr r1, r1, r3, lsr #24 /* r1 = xx54 */
+#endif
+ str r2, [r0]
+ strh r1, [r0, #0x04]
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 0100: dst is 8-bit aligned, src is 32-bit aligned
+ */
+ ldr r3, [r1] /* BE:r3 = 0123 LE:r3 = 3210 */
+ ldrh r2, [r1, #0x04] /* BE:r2 = ..45 LE:r2 = ..54 */
+ mov r1, r3, lsr #8 /* BE:r1 = .012 LE:r1 = .321 */
+ strh r1, [r0, #0x01]
+#ifdef __ARMEB__
+ mov r1, r3, lsr #24 /* r1 = ...0 */
+ strb r1, [r0]
+ mov r3, r3, lsl #8 /* r3 = 123. */
+ orr r3, r3, r2, lsr #8 /* r3 = 1234 */
+#else
+ strb r3, [r0]
+ mov r3, r3, lsr #24 /* r3 = ...3 */
+ orr r3, r3, r2, lsl #8 /* r3 = .543 */
+ mov r2, r2, lsr #8 /* r2 = ...5 */
+#endif
+ strh r3, [r0, #0x03]
+ strb r2, [r0, #0x05]
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 0101: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldrh ip, [r1, #0x03]
+ ldrb r1, [r1, #0x05]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ strh ip, [r0, #0x03]
+ strb r1, [r0, #0x05]
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 0110: dst is 8-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldr r1, [r1, #0x02] /* BE:r1 = 2345 LE:r1 = 5432 */
+#ifdef __ARMEB__
+ mov r3, r2, lsr #8 /* r3 = ...0 */
+ strb r3, [r0]
+ strb r1, [r0, #0x05]
+ mov r3, r1, lsr #8 /* r3 = .234 */
+ strh r3, [r0, #0x03]
+ mov r3, r2, lsl #8 /* r3 = .01. */
+ orr r3, r3, r1, lsr #24 /* r3 = .012 */
+ strh r3, [r0, #0x01]
+#else
+ strb r2, [r0]
+ mov r3, r1, lsr #24
+ strb r3, [r0, #0x05]
+ mov r3, r1, lsr #8 /* r3 = .543 */
+ strh r3, [r0, #0x03]
+ mov r3, r2, lsr #8 /* r3 = ...1 */
+ orr r3, r3, r1, lsl #8 /* r3 = 4321 */
+ strh r3, [r0, #0x01]
+#endif
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 0111: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldrh ip, [r1, #0x03]
+ ldrb r1, [r1, #0x05]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ strh ip, [r0, #0x03]
+ strb r1, [r0, #0x05]
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 1000: dst is 16-bit aligned, src is 32-bit aligned
+ */
+#ifdef __ARMEB__
+ ldr r2, [r1] /* r2 = 0123 */
+ ldrh r3, [r1, #0x04] /* r3 = ..45 */
+ mov r1, r2, lsr #16 /* r1 = ..01 */
+ orr r3, r3, r2, lsl#16 /* r3 = 2345 */
+ strh r1, [r0]
+ str r3, [r0, #0x02]
+#else
+ ldrh r2, [r1, #0x04] /* r2 = ..54 */
+ ldr r3, [r1] /* r3 = 3210 */
+ mov r2, r2, lsl #16 /* r2 = 54.. */
+ orr r2, r2, r3, lsr #16 /* r2 = 5432 */
+ strh r3, [r0]
+ str r2, [r0, #0x02]
+#endif
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 1001: dst is 16-bit aligned, src is 8-bit aligned
+ */
+ ldr r3, [r1, #-1] /* BE:r3 = x012 LE:r3 = 210x */
+ ldr r2, [r1, #3] /* BE:r2 = 345x LE:r2 = x543 */
+ mov r1, r3, lsr #8 /* BE:r1 = .x01 LE:r1 = .210 */
+#ifdef __ARMEB__
+ mov r2, r2, lsr #8 /* r2 = .345 */
+ orr r2, r2, r3, lsl #24 /* r2 = 2345 */
+#else
+ mov r2, r2, lsl #8 /* r2 = 543. */
+ orr r2, r2, r3, lsr #24 /* r2 = 5432 */
+#endif
+ strh r1, [r0]
+ str r2, [r0, #0x02]
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 1010: dst is 16-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1]
+ ldr r3, [r1, #0x02]
+ strh r2, [r0]
+ str r3, [r0, #0x02]
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 1011: dst is 16-bit aligned, src is 8-bit aligned
+ */
+ ldrb r3, [r1] /* r3 = ...0 */
+ ldr r2, [r1, #0x01] /* BE:r2 = 1234 LE:r2 = 4321 */
+ ldrb r1, [r1, #0x05] /* r1 = ...5 */
+#ifdef __ARMEB__
+ mov r3, r3, lsl #8 /* r3 = ..0. */
+ orr r3, r3, r2, lsr #24 /* r3 = ..01 */
+ orr r1, r1, r2, lsl #8 /* r1 = 2345 */
+#else
+ orr r3, r3, r2, lsl #8 /* r3 = 3210 */
+ mov r1, r1, lsl #24 /* r1 = 5... */
+ orr r1, r1, r2, lsr #8 /* r1 = 5432 */
+#endif
+ strh r3, [r0]
+ str r1, [r0, #0x02]
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 1100: dst is 8-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */
+ ldrh r1, [r1, #0x04] /* BE:r1 = ..45 LE:r1 = ..54 */
+#ifdef __ARMEB__
+ mov r3, r2, lsr #24 /* r3 = ...0 */
+ strb r3, [r0]
+ mov r2, r2, lsl #8 /* r2 = 123. */
+ orr r2, r2, r1, lsr #8 /* r2 = 1234 */
+#else
+ strb r2, [r0]
+ mov r2, r2, lsr #8 /* r2 = .321 */
+ orr r2, r2, r1, lsl #24 /* r2 = 4321 */
+ mov r1, r1, lsr #8 /* r1 = ...5 */
+#endif
+ str r2, [r0, #0x01]
+ strb r1, [r0, #0x05]
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 1101: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldrh ip, [r1, #0x03]
+ ldrb r1, [r1, #0x05]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ strh ip, [r0, #0x03]
+ strb r1, [r0, #0x05]
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 1110: dst is 8-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldr r1, [r1, #0x02] /* BE:r1 = 2345 LE:r1 = 5432 */
+#ifdef __ARMEB__
+ mov r3, r2, lsr #8 /* r3 = ...0 */
+ strb r3, [r0]
+ mov r2, r2, lsl #24 /* r2 = 1... */
+ orr r2, r2, r1, lsr #8 /* r2 = 1234 */
+#else
+ strb r2, [r0]
+ mov r2, r2, lsr #8 /* r2 = ...1 */
+ orr r2, r2, r1, lsl #8 /* r2 = 4321 */
+ mov r1, r1, lsr #24 /* r1 = ...5 */
+#endif
+ str r2, [r0, #0x01]
+ strb r1, [r0, #0x05]
+ bx lr
+ LMEMCPY_6_PAD
+
+/*
+ * 1111: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldr r3, [r1, #0x01]
+ ldrb r1, [r1, #0x05]
+ strb r2, [r0]
+ str r3, [r0, #0x01]
+ strb r1, [r0, #0x05]
+ bx lr
+ LMEMCPY_6_PAD
+
+
+/******************************************************************************
+ * Special case for 8 byte copies
+ */
+#define LMEMCPY_8_LOG2 6 /* 64 bytes */
+#define LMEMCPY_8_PAD .align LMEMCPY_8_LOG2
+ LMEMCPY_8_PAD
+.Lmemcpy_8:
+ and r2, r1, #0x03
+ orr r2, r2, r0, lsl #2
+ ands r2, r2, #0x0f
+ sub r3, pc, #0x14
+ addne pc, r3, r2, lsl #LMEMCPY_8_LOG2
+
+/*
+ * 0000: dst is 32-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1]
+ ldr r3, [r1, #0x04]
+ str r2, [r0]
+ str r3, [r0, #0x04]
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 0001: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldr r3, [r1, #-1] /* BE:r3 = x012 LE:r3 = 210x */
+ ldr r2, [r1, #0x03] /* BE:r2 = 3456 LE:r2 = 6543 */
+ ldrb r1, [r1, #0x07] /* r1 = ...7 */
+#ifdef __ARMEB__
+ mov r3, r3, lsl #8 /* r3 = 012. */
+ orr r3, r3, r2, lsr #24 /* r3 = 0123 */
+ orr r2, r1, r2, lsl #8 /* r2 = 4567 */
+#else
+ mov r3, r3, lsr #8 /* r3 = .210 */
+ orr r3, r3, r2, lsl #24 /* r3 = 3210 */
+ mov r1, r1, lsl #24 /* r1 = 7... */
+ orr r2, r1, r2, lsr #8 /* r2 = 7654 */
+#endif
+ str r3, [r0]
+ str r2, [r0, #0x04]
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 0010: dst is 32-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */
+ ldrh r1, [r1, #0x06] /* BE:r1 = ..67 LE:r1 = ..76 */
+#ifdef __ARMEB__
+ mov r2, r2, lsl #16 /* r2 = 01.. */
+ orr r2, r2, r3, lsr #16 /* r2 = 0123 */
+ orr r3, r1, r3, lsl #16 /* r3 = 4567 */
+#else
+ orr r2, r2, r3, lsl #16 /* r2 = 3210 */
+ mov r3, r3, lsr #16 /* r3 = ..54 */
+ orr r3, r3, r1, lsl #16 /* r3 = 7654 */
+#endif
+ str r2, [r0]
+ str r3, [r0, #0x04]
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 0011: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldrb r3, [r1] /* r3 = ...0 */
+ ldr r2, [r1, #0x01] /* BE:r2 = 1234 LE:r2 = 4321 */
+ ldr r1, [r1, #0x05] /* BE:r1 = 567x LE:r1 = x765 */
+#ifdef __ARMEB__
+ mov r3, r3, lsl #24 /* r3 = 0... */
+ orr r3, r3, r2, lsr #8 /* r3 = 0123 */
+ mov r2, r2, lsl #24 /* r2 = 4... */
+ orr r2, r2, r1, lsr #8 /* r2 = 4567 */
+#else
+ orr r3, r3, r2, lsl #8 /* r3 = 3210 */
+ mov r2, r2, lsr #24 /* r2 = ...4 */
+ orr r2, r2, r1, lsl #8 /* r2 = 7654 */
+#endif
+ str r3, [r0]
+ str r2, [r0, #0x04]
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 0100: dst is 8-bit aligned, src is 32-bit aligned
+ */
+ ldr r3, [r1] /* BE:r3 = 0123 LE:r3 = 3210 */
+ ldr r2, [r1, #0x04] /* BE:r2 = 4567 LE:r2 = 7654 */
+#ifdef __ARMEB__
+ mov r1, r3, lsr #24 /* r1 = ...0 */
+ strb r1, [r0]
+ mov r1, r3, lsr #8 /* r1 = .012 */
+ strb r2, [r0, #0x07]
+ mov r3, r3, lsl #24 /* r3 = 3... */
+ orr r3, r3, r2, lsr #8 /* r3 = 3456 */
+#else
+ strb r3, [r0]
+ mov r1, r2, lsr #24 /* r1 = ...7 */
+ strb r1, [r0, #0x07]
+ mov r1, r3, lsr #8 /* r1 = .321 */
+ mov r3, r3, lsr #24 /* r3 = ...3 */
+ orr r3, r3, r2, lsl #8 /* r3 = 6543 */
+#endif
+ strh r1, [r0, #0x01]
+ str r3, [r0, #0x03]
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 0101: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldr ip, [r1, #0x03]
+ ldrb r1, [r1, #0x07]
+ strb r2, [r0]
+ strh r3, [r0, #0x01]
+ str ip, [r0, #0x03]
+ strb r1, [r0, #0x07]
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 0110: dst is 8-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */
+ ldrh r1, [r1, #0x06] /* BE:r1 = ..67 LE:r1 = ..76 */
+#ifdef __ARMEB__
+ mov ip, r2, lsr #8 /* ip = ...0 */
+ strb ip, [r0]
+ mov ip, r2, lsl #8 /* ip = .01. */
+ orr ip, ip, r3, lsr #24 /* ip = .012 */
+ strb r1, [r0, #0x07]
+ mov r3, r3, lsl #8 /* r3 = 345. */
+ orr r3, r3, r1, lsr #8 /* r3 = 3456 */
+#else
+ strb r2, [r0] /* 0 */
+ mov ip, r1, lsr #8 /* ip = ...7 */
+ strb ip, [r0, #0x07] /* 7 */
+ mov ip, r2, lsr #8 /* ip = ...1 */
+ orr ip, ip, r3, lsl #8 /* ip = 4321 */
+ mov r3, r3, lsr #8 /* r3 = .543 */
+ orr r3, r3, r1, lsl #24 /* r3 = 6543 */
+#endif
+ strh ip, [r0, #0x01]
+ str r3, [r0, #0x03]
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 0111: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r3, [r1] /* r3 = ...0 */
+ ldr ip, [r1, #0x01] /* BE:ip = 1234 LE:ip = 4321 */
+ ldrh r2, [r1, #0x05] /* BE:r2 = ..56 LE:r2 = ..65 */
+ ldrb r1, [r1, #0x07] /* r1 = ...7 */
+ strb r3, [r0]
+ mov r3, ip, lsr #16 /* BE:r3 = ..12 LE:r3 = ..43 */
+#ifdef __ARMEB__
+ strh r3, [r0, #0x01]
+ orr r2, r2, ip, lsl #16 /* r2 = 3456 */
+#else
+ strh ip, [r0, #0x01]
+ orr r2, r3, r2, lsl #16 /* r2 = 6543 */
+#endif
+ str r2, [r0, #0x03]
+ strb r1, [r0, #0x07]
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 1000: dst is 16-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */
+ ldr r3, [r1, #0x04] /* BE:r3 = 4567 LE:r3 = 7654 */
+ mov r1, r2, lsr #16 /* BE:r1 = ..01 LE:r1 = ..32 */
+#ifdef __ARMEB__
+ strh r1, [r0]
+ mov r1, r3, lsr #16 /* r1 = ..45 */
+ orr r2, r1 ,r2, lsl #16 /* r2 = 2345 */
+#else
+ strh r2, [r0]
+ orr r2, r1, r3, lsl #16 /* r2 = 5432 */
+ mov r3, r3, lsr #16 /* r3 = ..76 */
+#endif
+ str r2, [r0, #0x02]
+ strh r3, [r0, #0x06]
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 1001: dst is 16-bit aligned, src is 8-bit aligned
+ */
+ ldr r2, [r1, #-1] /* BE:r2 = x012 LE:r2 = 210x */
+ ldr r3, [r1, #0x03] /* BE:r3 = 3456 LE:r3 = 6543 */
+ ldrb ip, [r1, #0x07] /* ip = ...7 */
+ mov r1, r2, lsr #8 /* BE:r1 = .x01 LE:r1 = .210 */
+ strh r1, [r0]
+#ifdef __ARMEB__
+ mov r1, r2, lsl #24 /* r1 = 2... */
+ orr r1, r1, r3, lsr #8 /* r1 = 2345 */
+ orr r3, ip, r3, lsl #8 /* r3 = 4567 */
+#else
+ mov r1, r2, lsr #24 /* r1 = ...2 */
+ orr r1, r1, r3, lsl #8 /* r1 = 5432 */
+ mov r3, r3, lsr #24 /* r3 = ...6 */
+ orr r3, r3, ip, lsl #8 /* r3 = ..76 */
+#endif
+ str r1, [r0, #0x02]
+ strh r3, [r0, #0x06]
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 1010: dst is 16-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1]
+ ldr ip, [r1, #0x02]
+ ldrh r3, [r1, #0x06]
+ strh r2, [r0]
+ str ip, [r0, #0x02]
+ strh r3, [r0, #0x06]
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 1011: dst is 16-bit aligned, src is 8-bit aligned
+ */
+ ldr r3, [r1, #0x05] /* BE:r3 = 567x LE:r3 = x765 */
+ ldr r2, [r1, #0x01] /* BE:r2 = 1234 LE:r2 = 4321 */
+ ldrb ip, [r1] /* ip = ...0 */
+ mov r1, r3, lsr #8 /* BE:r1 = .567 LE:r1 = .x76 */
+ strh r1, [r0, #0x06]
+#ifdef __ARMEB__
+ mov r3, r3, lsr #24 /* r3 = ...5 */
+ orr r3, r3, r2, lsl #8 /* r3 = 2345 */
+ mov r2, r2, lsr #24 /* r2 = ...1 */
+ orr r2, r2, ip, lsl #8 /* r2 = ..01 */
+#else
+ mov r3, r3, lsl #24 /* r3 = 5... */
+ orr r3, r3, r2, lsr #8 /* r3 = 5432 */
+ orr r2, ip, r2, lsl #8 /* r2 = 3210 */
+#endif
+ str r3, [r0, #0x02]
+ strh r2, [r0]
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 1100: dst is 8-bit aligned, src is 32-bit aligned
+ */
+ ldr r3, [r1, #0x04] /* BE:r3 = 4567 LE:r3 = 7654 */
+ ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */
+ mov r1, r3, lsr #8 /* BE:r1 = .456 LE:r1 = .765 */
+ strh r1, [r0, #0x05]
+#ifdef __ARMEB__
+ strb r3, [r0, #0x07]
+ mov r1, r2, lsr #24 /* r1 = ...0 */
+ strb r1, [r0]
+ mov r2, r2, lsl #8 /* r2 = 123. */
+ orr r2, r2, r3, lsr #24 /* r2 = 1234 */
+ str r2, [r0, #0x01]
+#else
+ strb r2, [r0]
+ mov r1, r3, lsr #24 /* r1 = ...7 */
+ strb r1, [r0, #0x07]
+ mov r2, r2, lsr #8 /* r2 = .321 */
+ orr r2, r2, r3, lsl #24 /* r2 = 4321 */
+ str r2, [r0, #0x01]
+#endif
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 1101: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r3, [r1] /* r3 = ...0 */
+ ldrh r2, [r1, #0x01] /* BE:r2 = ..12 LE:r2 = ..21 */
+ ldr ip, [r1, #0x03] /* BE:ip = 3456 LE:ip = 6543 */
+ ldrb r1, [r1, #0x07] /* r1 = ...7 */
+ strb r3, [r0]
+ mov r3, ip, lsr #16 /* BE:r3 = ..34 LE:r3 = ..65 */
+#ifdef __ARMEB__
+ strh ip, [r0, #0x05]
+ orr r2, r3, r2, lsl #16 /* r2 = 1234 */
+#else
+ strh r3, [r0, #0x05]
+ orr r2, r2, ip, lsl #16 /* r2 = 4321 */
+#endif
+ str r2, [r0, #0x01]
+ strb r1, [r0, #0x07]
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 1110: dst is 8-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */
+ ldrh r1, [r1, #0x06] /* BE:r1 = ..67 LE:r1 = ..76 */
+#ifdef __ARMEB__
+ mov ip, r2, lsr #8 /* ip = ...0 */
+ strb ip, [r0]
+ mov ip, r2, lsl #24 /* ip = 1... */
+ orr ip, ip, r3, lsr #8 /* ip = 1234 */
+ strb r1, [r0, #0x07]
+ mov r1, r1, lsr #8 /* r1 = ...6 */
+ orr r1, r1, r3, lsl #8 /* r1 = 3456 */
+#else
+ strb r2, [r0]
+ mov ip, r2, lsr #8 /* ip = ...1 */
+ orr ip, ip, r3, lsl #8 /* ip = 4321 */
+ mov r2, r1, lsr #8 /* r2 = ...7 */
+ strb r2, [r0, #0x07]
+ mov r1, r1, lsl #8 /* r1 = .76. */
+ orr r1, r1, r3, lsr #24 /* r1 = .765 */
+#endif
+ str ip, [r0, #0x01]
+ strh r1, [r0, #0x05]
+ bx lr
+ LMEMCPY_8_PAD
+
+/*
+ * 1111: dst is 8-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1]
+ ldr ip, [r1, #0x01]
+ ldrh r3, [r1, #0x05]
+ ldrb r1, [r1, #0x07]
+ strb r2, [r0]
+ str ip, [r0, #0x01]
+ strh r3, [r0, #0x05]
+ strb r1, [r0, #0x07]
+ bx lr
+ LMEMCPY_8_PAD
+
+/******************************************************************************
+ * Special case for 12 byte copies
+ */
+#define LMEMCPY_C_LOG2 7 /* 128 bytes */
+#define LMEMCPY_C_PAD .align LMEMCPY_C_LOG2
+ LMEMCPY_C_PAD
+.Lmemcpy_c:
+ and r2, r1, #0x03
+ orr r2, r2, r0, lsl #2
+ ands r2, r2, #0x0f
+ sub r3, pc, #0x14
+ addne pc, r3, r2, lsl #LMEMCPY_C_LOG2
+
+/*
+ * 0000: dst is 32-bit aligned, src is 32-bit aligned
+ */
+ ldr r2, [r1]
+ ldr r3, [r1, #0x04]
+ ldr r1, [r1, #0x08]
+ str r2, [r0]
+ str r3, [r0, #0x04]
+ str r1, [r0, #0x08]
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 0001: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1, #0xb] /* r2 = ...B */
+ ldr ip, [r1, #0x07] /* BE:ip = 789A LE:ip = A987 */
+ ldr r3, [r1, #0x03] /* BE:r3 = 3456 LE:r3 = 6543 */
+ ldr r1, [r1, #-1] /* BE:r1 = x012 LE:r1 = 210x */
+#ifdef __ARMEB__
+ orr r2, r2, ip, lsl #8 /* r2 = 89AB */
+ str r2, [r0, #0x08]
+ mov r2, ip, lsr #24 /* r2 = ...7 */
+ orr r2, r2, r3, lsl #8 /* r2 = 4567 */
+ mov r1, r1, lsl #8 /* r1 = 012. */
+ orr r1, r1, r3, lsr #24 /* r1 = 0123 */
+#else
+ mov r2, r2, lsl #24 /* r2 = B... */
+ orr r2, r2, ip, lsr #8 /* r2 = BA98 */
+ str r2, [r0, #0x08]
+ mov r2, ip, lsl #24 /* r2 = 7... */
+ orr r2, r2, r3, lsr #8 /* r2 = 7654 */
+ mov r1, r1, lsr #8 /* r1 = .210 */
+ orr r1, r1, r3, lsl #24 /* r1 = 3210 */
+#endif
+ str r2, [r0, #0x04]
+ str r1, [r0]
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 0010: dst is 32-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */
+ ldr ip, [r1, #0x06] /* BE:ip = 6789 LE:ip = 9876 */
+ ldrh r1, [r1, #0x0a] /* BE:r1 = ..AB LE:r1 = ..BA */
+#ifdef __ARMEB__
+ mov r2, r2, lsl #16 /* r2 = 01.. */
+ orr r2, r2, r3, lsr #16 /* r2 = 0123 */
+ str r2, [r0]
+ mov r3, r3, lsl #16 /* r3 = 45.. */
+ orr r3, r3, ip, lsr #16 /* r3 = 4567 */
+ orr r1, r1, ip, lsl #16 /* r1 = 89AB */
+#else
+ orr r2, r2, r3, lsl #16 /* r2 = 3210 */
+ str r2, [r0]
+ mov r3, r3, lsr #16 /* r3 = ..54 */
+ orr r3, r3, ip, lsl #16 /* r3 = 7654 */
+ mov r1, r1, lsl #16 /* r1 = BA.. */
+ orr r1, r1, ip, lsr #16 /* r1 = BA98 */
+#endif
+ str r3, [r0, #0x04]
+ str r1, [r0, #0x08]
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 0011: dst is 32-bit aligned, src is 8-bit aligned
+ */
+ ldrb r2, [r1] /* r2 = ...0 */
+ ldr r3, [r1, #0x01] /* BE:r3 = 1234 LE:r3 = 4321 */
+ ldr ip, [r1, #0x05] /* BE:ip = 5678 LE:ip = 8765 */
+ ldr r1, [r1, #0x09] /* BE:r1 = 9ABx LE:r1 = xBA9 */
+#ifdef __ARMEB__
+ mov r2, r2, lsl #24 /* r2 = 0... */
+ orr r2, r2, r3, lsr #8 /* r2 = 0123 */
+ str r2, [r0]
+ mov r3, r3, lsl #24 /* r3 = 4... */
+ orr r3, r3, ip, lsr #8 /* r3 = 4567 */
+ mov r1, r1, lsr #8 /* r1 = .9AB */
+ orr r1, r1, ip, lsl #24 /* r1 = 89AB */
+#else
+ orr r2, r2, r3, lsl #8 /* r2 = 3210 */
+ str r2, [r0]
+ mov r3, r3, lsr #24 /* r3 = ...4 */
+ orr r3, r3, ip, lsl #8 /* r3 = 7654 */
+ mov r1, r1, lsl #8 /* r1 = BA9. */
+ orr r1, r1, ip, lsr #24 /* r1 = BA98 */
+#endif
+ str r3, [r0, #0x04]
+ str r1, [r0, #0x08]
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 0100: dst is 8-bit aligned (byte 1), src is 32-bit aligned
+ */
+ ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */
+ ldr r3, [r1, #0x04] /* BE:r3 = 4567 LE:r3 = 7654 */
+ ldr ip, [r1, #0x08] /* BE:ip = 89AB LE:ip = BA98 */
+ mov r1, r2, lsr #8 /* BE:r1 = .012 LE:r1 = .321 */
+ strh r1, [r0, #0x01]
+#ifdef __ARMEB__
+ mov r1, r2, lsr #24 /* r1 = ...0 */
+ strb r1, [r0]
+ mov r1, r2, lsl #24 /* r1 = 3... */
+ orr r2, r1, r3, lsr #8 /* r1 = 3456 */
+ mov r1, r3, lsl #24 /* r1 = 7... */
+ orr r1, r1, ip, lsr #8 /* r1 = 789A */
+#else
+ strb r2, [r0]
+ mov r1, r2, lsr #24 /* r1 = ...3 */
+ orr r2, r1, r3, lsl #8 /* r1 = 6543 */
+ mov r1, r3, lsr #24 /* r1 = ...7 */
+ orr r1, r1, ip, lsl #8 /* r1 = A987 */
+ mov ip, ip, lsr #24 /* ip = ...B */
+#endif
+ str r2, [r0, #0x03]
+ str r1, [r0, #0x07]
+ strb ip, [r0, #0x0b]
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 0101: dst is 8-bit aligned (byte 1), src is 8-bit aligned (byte 1)
+ */
+ ldrb r2, [r1]
+ ldrh r3, [r1, #0x01]
+ ldr ip, [r1, #0x03]
+ strb r2, [r0]
+ ldr r2, [r1, #0x07]
+ ldrb r1, [r1, #0x0b]
+ strh r3, [r0, #0x01]
+ str ip, [r0, #0x03]
+ str r2, [r0, #0x07]
+ strb r1, [r0, #0x0b]
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 0110: dst is 8-bit aligned (byte 1), src is 16-bit aligned
+ */
+ ldrh r2, [r1] /* BE:r2 = ..01 LE:r2 = ..10 */
+ ldr r3, [r1, #0x02] /* BE:r3 = 2345 LE:r3 = 5432 */
+ ldr ip, [r1, #0x06] /* BE:ip = 6789 LE:ip = 9876 */
+ ldrh r1, [r1, #0x0a] /* BE:r1 = ..AB LE:r1 = ..BA */
+#ifdef __ARMEB__
+ mov r2, r2, ror #8 /* r2 = 1..0 */
+ strb r2, [r0]
+ mov r2, r2, lsr #16 /* r2 = ..1. */
+ orr r2, r2, r3, lsr #24 /* r2 = ..12 */
+ strh r2, [r0, #0x01]
+ mov r2, r3, lsl #8 /* r2 = 345. */
+ orr r3, r2, ip, lsr #24 /* r3 = 3456 */
+ mov r2, ip, lsl #8 /* r2 = 789. */
+ orr r2, r2, r1, lsr #8 /* r2 = 789A */
+#else
+ strb r2, [r0]
+ mov r2, r2, lsr #8 /* r2 = ...1 */
+ orr r2, r2, r3, lsl #8 /* r2 = 4321 */
+ strh r2, [r0, #0x01]
+ mov r2, r3, lsr #8 /* r2 = .543 */
+ orr r3, r2, ip, lsl #24 /* r3 = 6543 */
+ mov r2, ip, lsr #8 /* r2 = .987 */
+ orr r2, r2, r1, lsl #24 /* r2 = A987 */
+ mov r1, r1, lsr #8 /* r1 = ...B */
+#endif
+ str r3, [r0, #0x03]
+ str r2, [r0, #0x07]
+ strb r1, [r0, #0x0b]
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 0111: dst is 8-bit aligned (byte 1), src is 8-bit aligned (byte 3)
+ */
+ ldrb r2, [r1]
+ ldr r3, [r1, #0x01] /* BE:r3 = 1234 LE:r3 = 4321 */
+ ldr ip, [r1, #0x05] /* BE:ip = 5678 LE:ip = 8765 */
+ ldr r1, [r1, #0x09] /* BE:r1 = 9ABx LE:r1 = xBA9 */
+ strb r2, [r0]
+#ifdef __ARMEB__
+ mov r2, r3, lsr #16 /* r2 = ..12 */
+ strh r2, [r0, #0x01]
+ mov r3, r3, lsl #16 /* r3 = 34.. */
+ orr r3, r3, ip, lsr #16 /* r3 = 3456 */
+ mov ip, ip, lsl #16 /* ip = 78.. */
+ orr ip, ip, r1, lsr #16 /* ip = 789A */
+ mov r1, r1, lsr #8 /* r1 = .9AB */
+#else
+ strh r3, [r0, #0x01]
+ mov r3, r3, lsr #16 /* r3 = ..43 */
+ orr r3, r3, ip, lsl #16 /* r3 = 6543 */
+ mov ip, ip, lsr #16 /* ip = ..87 */
+ orr ip, ip, r1, lsl #16 /* ip = A987 */
+ mov r1, r1, lsr #16 /* r1 = ..xB */
+#endif
+ str r3, [r0, #0x03]
+ str ip, [r0, #0x07]
+ strb r1, [r0, #0x0b]
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 1000: dst is 16-bit aligned, src is 32-bit aligned
+ */
+ ldr ip, [r1] /* BE:ip = 0123 LE:ip = 3210 */
+ ldr r3, [r1, #0x04] /* BE:r3 = 4567 LE:r3 = 7654 */
+ ldr r2, [r1, #0x08] /* BE:r2 = 89AB LE:r2 = BA98 */
+ mov r1, ip, lsr #16 /* BE:r1 = ..01 LE:r1 = ..32 */
+#ifdef __ARMEB__
+ strh r1, [r0]
+ mov r1, ip, lsl #16 /* r1 = 23.. */
+ orr r1, r1, r3, lsr #16 /* r1 = 2345 */
+ mov r3, r3, lsl #16 /* r3 = 67.. */
+ orr r3, r3, r2, lsr #16 /* r3 = 6789 */
+#else
+ strh ip, [r0]
+ orr r1, r1, r3, lsl #16 /* r1 = 5432 */
+ mov r3, r3, lsr #16 /* r3 = ..76 */
+ orr r3, r3, r2, lsl #16 /* r3 = 9876 */
+ mov r2, r2, lsr #16 /* r2 = ..BA */
+#endif
+ str r1, [r0, #0x02]
+ str r3, [r0, #0x06]
+ strh r2, [r0, #0x0a]
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 1001: dst is 16-bit aligned, src is 8-bit aligned (byte 1)
+ */
+ ldr r2, [r1, #-1] /* BE:r2 = x012 LE:r2 = 210x */
+ ldr r3, [r1, #0x03] /* BE:r3 = 3456 LE:r3 = 6543 */
+ mov ip, r2, lsr #8 /* BE:ip = .x01 LE:ip = .210 */
+ strh ip, [r0]
+ ldr ip, [r1, #0x07] /* BE:ip = 789A LE:ip = A987 */
+ ldrb r1, [r1, #0x0b] /* r1 = ...B */
+#ifdef __ARMEB__
+ mov r2, r2, lsl #24 /* r2 = 2... */
+ orr r2, r2, r3, lsr #8 /* r2 = 2345 */
+ mov r3, r3, lsl #24 /* r3 = 6... */
+ orr r3, r3, ip, lsr #8 /* r3 = 6789 */
+ orr r1, r1, ip, lsl #8 /* r1 = 89AB */
+#else
+ mov r2, r2, lsr #24 /* r2 = ...2 */
+ orr r2, r2, r3, lsl #8 /* r2 = 5432 */
+ mov r3, r3, lsr #24 /* r3 = ...6 */
+ orr r3, r3, ip, lsl #8 /* r3 = 9876 */
+ mov r1, r1, lsl #8 /* r1 = ..B. */
+ orr r1, r1, ip, lsr #24 /* r1 = ..BA */
+#endif
+ str r2, [r0, #0x02]
+ str r3, [r0, #0x06]
+ strh r1, [r0, #0x0a]
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 1010: dst is 16-bit aligned, src is 16-bit aligned
+ */
+ ldrh r2, [r1]
+ ldr r3, [r1, #0x02]
+ ldr ip, [r1, #0x06]
+ ldrh r1, [r1, #0x0a]
+ strh r2, [r0]
+ str r3, [r0, #0x02]
+ str ip, [r0, #0x06]
+ strh r1, [r0, #0x0a]
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 1011: dst is 16-bit aligned, src is 8-bit aligned (byte 3)
+ */
+ ldr r2, [r1, #0x09] /* BE:r2 = 9ABx LE:r2 = xBA9 */
+ ldr r3, [r1, #0x05] /* BE:r3 = 5678 LE:r3 = 8765 */
+ mov ip, r2, lsr #8 /* BE:ip = .9AB LE:ip = .xBA */
+ strh ip, [r0, #0x0a]
+ ldr ip, [r1, #0x01] /* BE:ip = 1234 LE:ip = 4321 */
+ ldrb r1, [r1] /* r1 = ...0 */
+#ifdef __ARMEB__
+ mov r2, r2, lsr #24 /* r2 = ...9 */
+ orr r2, r2, r3, lsl #8 /* r2 = 6789 */
+ mov r3, r3, lsr #24 /* r3 = ...5 */
+ orr r3, r3, ip, lsl #8 /* r3 = 2345 */
+ mov r1, r1, lsl #8 /* r1 = ..0. */
+ orr r1, r1, ip, lsr #24 /* r1 = ..01 */
+#else
+ mov r2, r2, lsl #24 /* r2 = 9... */
+ orr r2, r2, r3, lsr #8 /* r2 = 9876 */
+ mov r3, r3, lsl #24 /* r3 = 5... */
+ orr r3, r3, ip, lsr #8 /* r3 = 5432 */
+ orr r1, r1, ip, lsl #8 /* r1 = 3210 */
+#endif
+ str r2, [r0, #0x06]
+ str r3, [r0, #0x02]
+ strh r1, [r0]
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 1100: dst is 8-bit aligned (byte 3), src is 32-bit aligned
+ */
+ ldr r2, [r1] /* BE:r2 = 0123 LE:r2 = 3210 */
+ ldr ip, [r1, #0x04] /* BE:ip = 4567 LE:ip = 7654 */
+ ldr r1, [r1, #0x08] /* BE:r1 = 89AB LE:r1 = BA98 */
+#ifdef __ARMEB__
+ mov r3, r2, lsr #24 /* r3 = ...0 */
+ strb r3, [r0]
+ mov r2, r2, lsl #8 /* r2 = 123. */
+ orr r2, r2, ip, lsr #24 /* r2 = 1234 */
+ str r2, [r0, #0x01]
+ mov r2, ip, lsl #8 /* r2 = 567. */
+ orr r2, r2, r1, lsr #24 /* r2 = 5678 */
+ str r2, [r0, #0x05]
+ mov r2, r1, lsr #8 /* r2 = ..9A */
+ strh r2, [r0, #0x09]
+ strb r1, [r0, #0x0b]
+#else
+ strb r2, [r0]
+ mov r3, r2, lsr #8 /* r3 = .321 */
+ orr r3, r3, ip, lsl #24 /* r3 = 4321 */
+ str r3, [r0, #0x01]
+ mov r3, ip, lsr #8 /* r3 = .765 */
+ orr r3, r3, r1, lsl #24 /* r3 = 8765 */
+ str r3, [r0, #0x05]
+ mov r1, r1, lsr #8 /* r1 = .BA9 */
+ strh r1, [r0, #0x09]
+ mov r1, r1, lsr #16 /* r1 = ...B */
+ strb r1, [r0, #0x0b]
+#endif
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 1101: dst is 8-bit aligned (byte 3), src is 8-bit aligned (byte 1)
+ */
+ ldrb r2, [r1, #0x0b] /* r2 = ...B */
+ ldr r3, [r1, #0x07] /* BE:r3 = 789A LE:r3 = A987 */
+ ldr ip, [r1, #0x03] /* BE:ip = 3456 LE:ip = 6543 */
+ ldr r1, [r1, #-1] /* BE:r1 = x012 LE:r1 = 210x */
+ strb r2, [r0, #0x0b]
+#ifdef __ARMEB__
+ strh r3, [r0, #0x09]
+ mov r3, r3, lsr #16 /* r3 = ..78 */
+ orr r3, r3, ip, lsl #16 /* r3 = 5678 */
+ mov ip, ip, lsr #16 /* ip = ..34 */
+ orr ip, ip, r1, lsl #16 /* ip = 1234 */
+ mov r1, r1, lsr #16 /* r1 = ..x0 */
+#else
+ mov r2, r3, lsr #16 /* r2 = ..A9 */
+ strh r2, [r0, #0x09]
+ mov r3, r3, lsl #16 /* r3 = 87.. */
+ orr r3, r3, ip, lsr #16 /* r3 = 8765 */
+ mov ip, ip, lsl #16 /* ip = 43.. */
+ orr ip, ip, r1, lsr #16 /* ip = 4321 */
+ mov r1, r1, lsr #8 /* r1 = .210 */
+#endif
+ str r3, [r0, #0x05]
+ str ip, [r0, #0x01]
+ strb r1, [r0]
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 1110: dst is 8-bit aligned (byte 3), src is 16-bit aligned
+ */
+#ifdef __ARMEB__
+ ldrh r2, [r1, #0x0a] /* r2 = ..AB */
+ ldr ip, [r1, #0x06] /* ip = 6789 */
+ ldr r3, [r1, #0x02] /* r3 = 2345 */
+ ldrh r1, [r1] /* r1 = ..01 */
+ strb r2, [r0, #0x0b]
+ mov r2, r2, lsr #8 /* r2 = ...A */
+ orr r2, r2, ip, lsl #8 /* r2 = 789A */
+ mov ip, ip, lsr #8 /* ip = .678 */
+ orr ip, ip, r3, lsl #24 /* ip = 5678 */
+ mov r3, r3, lsr #8 /* r3 = .234 */
+ orr r3, r3, r1, lsl #24 /* r3 = 1234 */
+ mov r1, r1, lsr #8 /* r1 = ...0 */
+ strb r1, [r0]
+ str r3, [r0, #0x01]
+ str ip, [r0, #0x05]
+ strh r2, [r0, #0x09]
+#else
+ ldrh r2, [r1] /* r2 = ..10 */
+ ldr r3, [r1, #0x02] /* r3 = 5432 */
+ ldr ip, [r1, #0x06] /* ip = 9876 */
+ ldrh r1, [r1, #0x0a] /* r1 = ..BA */
+ strb r2, [r0]
+ mov r2, r2, lsr #8 /* r2 = ...1 */
+ orr r2, r2, r3, lsl #8 /* r2 = 4321 */
+ mov r3, r3, lsr #24 /* r3 = ...5 */
+ orr r3, r3, ip, lsl #8 /* r3 = 8765 */
+ mov ip, ip, lsr #24 /* ip = ...9 */
+ orr ip, ip, r1, lsl #8 /* ip = .BA9 */
+ mov r1, r1, lsr #8 /* r1 = ...B */
+ str r2, [r0, #0x01]
+ str r3, [r0, #0x05]
+ strh ip, [r0, #0x09]
+ strb r1, [r0, #0x0b]
+#endif
+ bx lr
+ LMEMCPY_C_PAD
+
+/*
+ * 1111: dst is 8-bit aligned (byte 3), src is 8-bit aligned (byte 3)
+ */
+ ldrb r2, [r1]
+ ldr r3, [r1, #0x01]
+ ldr ip, [r1, #0x05]
+ strb r2, [r0]
+ ldrh r2, [r1, #0x09]
+ ldrb r1, [r1, #0x0b]
+ str r3, [r0, #0x01]
+ str ip, [r0, #0x05]
+ strh r2, [r0, #0x09]
+ strb r1, [r0, #0x0b]
+ bx lr
+#endif /* !_STANDALONE */
diff --git a/lib/libc/arm/string/memmove.S b/lib/libc/arm/string/memmove.S
new file mode 100644
index 0000000..8b8baaf
--- /dev/null
+++ b/lib/libc/arm/string/memmove.S
@@ -0,0 +1,582 @@
+/* $NetBSD: memmove.S,v 1.4 2003/10/14 07:51:45 scw Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#ifndef _BCOPY
+/* LINTSTUB: Func: void *memmove(void *, const void *, size_t) */
+ENTRY(memmove)
+#else
+/* bcopy = memcpy/memmove with arguments reversed. */
+/* LINTSTUB: Func: void bcopy(void *, void *, size_t) */
+ENTRY(bcopy)
+ /* switch the source and destination registers */
+ eor r0, r1, r0
+ eor r1, r0, r1
+ eor r0, r1, r0
+#endif
+ /* Do the buffers overlap? */
+ cmp r0, r1
+ RETeq /* Bail now if src/dst are the same */
+ subcc r3, r0, r1 /* if (dst > src) r3 = dst - src */
+ subcs r3, r1, r0 /* if (src > dsr) r3 = src - dst */
+ cmp r3, r2 /* if (r3 < len) we have an overlap */
+ bcc PIC_SYM(_C_LABEL(memcpy), PLT)
+
+ /* Determine copy direction */
+ cmp r1, r0
+ bcc .Lmemmove_backwards
+
+ moveq r0, #0 /* Quick abort for len=0 */
+ RETeq
+
+ stmdb sp!, {r0, lr} /* memmove() returns dest addr */
+ subs r2, r2, #4
+ blt .Lmemmove_fl4 /* less than 4 bytes */
+ ands r12, r0, #3
+ bne .Lmemmove_fdestul /* oh unaligned destination addr */
+ ands r12, r1, #3
+ bne .Lmemmove_fsrcul /* oh unaligned source addr */
+
+.Lmemmove_ft8:
+ /* We have aligned source and destination */
+ subs r2, r2, #8
+ blt .Lmemmove_fl12 /* less than 12 bytes (4 from above) */
+ subs r2, r2, #0x14
+ blt .Lmemmove_fl32 /* less than 32 bytes (12 from above) */
+ stmdb sp!, {r4} /* borrow r4 */
+
+ /* blat 32 bytes at a time */
+ /* XXX for really big copies perhaps we should use more registers */
+.Lmemmove_floop32:
+ ldmia r1!, {r3, r4, r12, lr}
+ stmia r0!, {r3, r4, r12, lr}
+ ldmia r1!, {r3, r4, r12, lr}
+ stmia r0!, {r3, r4, r12, lr}
+ subs r2, r2, #0x20
+ bge .Lmemmove_floop32
+
+ cmn r2, #0x10
+ ldmgeia r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
+ stmgeia r0!, {r3, r4, r12, lr}
+ subge r2, r2, #0x10
+ ldmia sp!, {r4} /* return r4 */
+
+.Lmemmove_fl32:
+ adds r2, r2, #0x14
+
+ /* blat 12 bytes at a time */
+.Lmemmove_floop12:
+ ldmgeia r1!, {r3, r12, lr}
+ stmgeia r0!, {r3, r12, lr}
+ subges r2, r2, #0x0c
+ bge .Lmemmove_floop12
+
+.Lmemmove_fl12:
+ adds r2, r2, #8
+ blt .Lmemmove_fl4
+
+ subs r2, r2, #4
+ ldrlt r3, [r1], #4
+ strlt r3, [r0], #4
+ ldmgeia r1!, {r3, r12}
+ stmgeia r0!, {r3, r12}
+ subge r2, r2, #4
+
+.Lmemmove_fl4:
+ /* less than 4 bytes to go */
+ adds r2, r2, #4
+ ldmeqia sp!, {r0, pc} /* done */
+
+ /* copy the crud byte at a time */
+ cmp r2, #2
+ ldrb r3, [r1], #1
+ strb r3, [r0], #1
+ ldrgeb r3, [r1], #1
+ strgeb r3, [r0], #1
+ ldrgtb r3, [r1], #1
+ strgtb r3, [r0], #1
+ ldmia sp!, {r0, pc}
+
+ /* erg - unaligned destination */
+.Lmemmove_fdestul:
+ rsb r12, r12, #4
+ cmp r12, #2
+
+ /* align destination with byte copies */
+ ldrb r3, [r1], #1
+ strb r3, [r0], #1
+ ldrgeb r3, [r1], #1
+ strgeb r3, [r0], #1
+ ldrgtb r3, [r1], #1
+ strgtb r3, [r0], #1
+ subs r2, r2, r12
+ blt .Lmemmove_fl4 /* less the 4 bytes */
+
+ ands r12, r1, #3
+ beq .Lmemmove_ft8 /* we have an aligned source */
+
+ /* erg - unaligned source */
+ /* This is where it gets nasty ... */
+.Lmemmove_fsrcul:
+ bic r1, r1, #3
+ ldr lr, [r1], #4
+ cmp r12, #2
+ bgt .Lmemmove_fsrcul3
+ beq .Lmemmove_fsrcul2
+ cmp r2, #0x0c
+ blt .Lmemmove_fsrcul1loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+.Lmemmove_fsrcul1loop16:
+#ifdef __ARMEB__
+ mov r3, lr, lsl #8
+#else
+ mov r3, lr, lsr #8
+#endif
+ ldmia r1!, {r4, r5, r12, lr}
+#ifdef __ARMEB__
+ orr r3, r3, r4, lsr #24
+ mov r4, r4, lsl #8
+ orr r4, r4, r5, lsr #24
+ mov r5, r5, lsl #8
+ orr r5, r5, r12, lsr #24
+ mov r12, r12, lsl #8
+ orr r12, r12, lr, lsr #24
+#else
+ orr r3, r3, r4, lsl #24
+ mov r4, r4, lsr #8
+ orr r4, r4, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r12, lsl #24
+ mov r12, r12, lsr #8
+ orr r12, r12, lr, lsl #24
+#endif
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge .Lmemmove_fsrcul1loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt .Lmemmove_fsrcul1l4
+
+.Lmemmove_fsrcul1loop4:
+#ifdef __ARMEB__
+ mov r12, lr, lsl #8
+#else
+ mov r12, lr, lsr #8
+#endif
+ ldr lr, [r1], #4
+#ifdef __ARMEB__
+ orr r12, r12, lr, lsr #24
+#else
+ orr r12, r12, lr, lsl #24
+#endif
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge .Lmemmove_fsrcul1loop4
+
+.Lmemmove_fsrcul1l4:
+ sub r1, r1, #3
+ b .Lmemmove_fl4
+
+.Lmemmove_fsrcul2:
+ cmp r2, #0x0c
+ blt .Lmemmove_fsrcul2loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+.Lmemmove_fsrcul2loop16:
+#ifdef __ARMEB__
+ mov r3, lr, lsl #16
+#else
+ mov r3, lr, lsr #16
+#endif
+ ldmia r1!, {r4, r5, r12, lr}
+#ifdef __ARMEB__
+ orr r3, r3, r4, lsr #16
+ mov r4, r4, lsl #16
+ orr r4, r4, r5, lsr #16
+ mov r5, r5, lsl #16
+ orr r5, r5, r12, lsr #16
+ mov r12, r12, lsl #16
+ orr r12, r12, lr, lsr #16
+#else
+ orr r3, r3, r4, lsl #16
+ mov r4, r4, lsr #16
+ orr r4, r4, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r12, lsl #16
+ mov r12, r12, lsr #16
+ orr r12, r12, lr, lsl #16
+#endif
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge .Lmemmove_fsrcul2loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt .Lmemmove_fsrcul2l4
+
+.Lmemmove_fsrcul2loop4:
+#ifdef __ARMEB__
+ mov r12, lr, lsl #16
+#else
+ mov r12, lr, lsr #16
+#endif
+ ldr lr, [r1], #4
+#ifdef __ARMEB__
+ orr r12, r12, lr, lsr #16
+#else
+ orr r12, r12, lr, lsl #16
+#endif
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge .Lmemmove_fsrcul2loop4
+
+.Lmemmove_fsrcul2l4:
+ sub r1, r1, #2
+ b .Lmemmove_fl4
+
+.Lmemmove_fsrcul3:
+ cmp r2, #0x0c
+ blt .Lmemmove_fsrcul3loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5}
+
+.Lmemmove_fsrcul3loop16:
+#ifdef __ARMEB__
+ mov r3, lr, lsl #24
+#else
+ mov r3, lr, lsr #24
+#endif
+ ldmia r1!, {r4, r5, r12, lr}
+#ifdef __ARMEB__
+ orr r3, r3, r4, lsr #8
+ mov r4, r4, lsl #24
+ orr r4, r4, r5, lsr #8
+ mov r5, r5, lsl #24
+ orr r5, r5, r12, lsr #8
+ mov r12, r12, lsl #24
+ orr r12, r12, lr, lsr #8
+#else
+ orr r3, r3, r4, lsl #8
+ mov r4, r4, lsr #24
+ orr r4, r4, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r12, lsl #8
+ mov r12, r12, lsr #24
+ orr r12, r12, lr, lsl #8
+#endif
+ stmia r0!, {r3-r5, r12}
+ subs r2, r2, #0x10
+ bge .Lmemmove_fsrcul3loop16
+ ldmia sp!, {r4, r5}
+ adds r2, r2, #0x0c
+ blt .Lmemmove_fsrcul3l4
+
+.Lmemmove_fsrcul3loop4:
+#ifdef __ARMEB__
+ mov r12, lr, lsl #24
+#else
+ mov r12, lr, lsr #24
+#endif
+ ldr lr, [r1], #4
+#ifdef __ARMEB__
+ orr r12, r12, lr, lsr #8
+#else
+ orr r12, r12, lr, lsl #8
+#endif
+ str r12, [r0], #4
+ subs r2, r2, #4
+ bge .Lmemmove_fsrcul3loop4
+
+.Lmemmove_fsrcul3l4:
+ sub r1, r1, #1
+ b .Lmemmove_fl4
+
+.Lmemmove_backwards:
+ add r1, r1, r2
+ add r0, r0, r2
+ subs r2, r2, #4
+ blt .Lmemmove_bl4 /* less than 4 bytes */
+ ands r12, r0, #3
+ bne .Lmemmove_bdestul /* oh unaligned destination addr */
+ ands r12, r1, #3
+ bne .Lmemmove_bsrcul /* oh unaligned source addr */
+
+.Lmemmove_bt8:
+ /* We have aligned source and destination */
+ subs r2, r2, #8
+ blt .Lmemmove_bl12 /* less than 12 bytes (4 from above) */
+ stmdb sp!, {r4, lr}
+ subs r2, r2, #0x14 /* less than 32 bytes (12 from above) */
+ blt .Lmemmove_bl32
+
+ /* blat 32 bytes at a time */
+ /* XXX for really big copies perhaps we should use more registers */
+.Lmemmove_bloop32:
+ ldmdb r1!, {r3, r4, r12, lr}
+ stmdb r0!, {r3, r4, r12, lr}
+ ldmdb r1!, {r3, r4, r12, lr}
+ stmdb r0!, {r3, r4, r12, lr}
+ subs r2, r2, #0x20
+ bge .Lmemmove_bloop32
+
+.Lmemmove_bl32:
+ cmn r2, #0x10
+ ldmgedb r1!, {r3, r4, r12, lr} /* blat a remaining 16 bytes */
+ stmgedb r0!, {r3, r4, r12, lr}
+ subge r2, r2, #0x10
+ adds r2, r2, #0x14
+ ldmgedb r1!, {r3, r12, lr} /* blat a remaining 12 bytes */
+ stmgedb r0!, {r3, r12, lr}
+ subge r2, r2, #0x0c
+ ldmia sp!, {r4, lr}
+
+.Lmemmove_bl12:
+ adds r2, r2, #8
+ blt .Lmemmove_bl4
+ subs r2, r2, #4
+ ldrlt r3, [r1, #-4]!
+ strlt r3, [r0, #-4]!
+ ldmgedb r1!, {r3, r12}
+ stmgedb r0!, {r3, r12}
+ subge r2, r2, #4
+
+.Lmemmove_bl4:
+ /* less than 4 bytes to go */
+ adds r2, r2, #4
+ RETeq /* done */
+
+ /* copy the crud byte at a time */
+ cmp r2, #2
+ ldrb r3, [r1, #-1]!
+ strb r3, [r0, #-1]!
+ ldrgeb r3, [r1, #-1]!
+ strgeb r3, [r0, #-1]!
+ ldrgtb r3, [r1, #-1]!
+ strgtb r3, [r0, #-1]!
+ RET
+
+ /* erg - unaligned destination */
+.Lmemmove_bdestul:
+ cmp r12, #2
+
+ /* align destination with byte copies */
+ ldrb r3, [r1, #-1]!
+ strb r3, [r0, #-1]!
+ ldrgeb r3, [r1, #-1]!
+ strgeb r3, [r0, #-1]!
+ ldrgtb r3, [r1, #-1]!
+ strgtb r3, [r0, #-1]!
+ subs r2, r2, r12
+ blt .Lmemmove_bl4 /* less than 4 bytes to go */
+ ands r12, r1, #3
+ beq .Lmemmove_bt8 /* we have an aligned source */
+
+ /* erg - unaligned source */
+ /* This is where it gets nasty ... */
+.Lmemmove_bsrcul:
+ bic r1, r1, #3
+ ldr r3, [r1, #0]
+ cmp r12, #2
+ blt .Lmemmove_bsrcul1
+ beq .Lmemmove_bsrcul2
+ cmp r2, #0x0c
+ blt .Lmemmove_bsrcul3loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5, lr}
+
+.Lmemmove_bsrcul3loop16:
+#ifdef __ARMEB__
+ mov lr, r3, lsr #8
+#else
+ mov lr, r3, lsl #8
+#endif
+ ldmdb r1!, {r3-r5, r12}
+#ifdef __ARMEB__
+ orr lr, lr, r12, lsl #24
+ mov r12, r12, lsr #8
+ orr r12, r12, r5, lsl #24
+ mov r5, r5, lsr #8
+ orr r5, r5, r4, lsl #24
+ mov r4, r4, lsr #8
+ orr r4, r4, r3, lsl #24
+#else
+ orr lr, lr, r12, lsr #24
+ mov r12, r12, lsl #8
+ orr r12, r12, r5, lsr #24
+ mov r5, r5, lsl #8
+ orr r5, r5, r4, lsr #24
+ mov r4, r4, lsl #8
+ orr r4, r4, r3, lsr #24
+#endif
+ stmdb r0!, {r4, r5, r12, lr}
+ subs r2, r2, #0x10
+ bge .Lmemmove_bsrcul3loop16
+ ldmia sp!, {r4, r5, lr}
+ adds r2, r2, #0x0c
+ blt .Lmemmove_bsrcul3l4
+
+.Lmemmove_bsrcul3loop4:
+#ifdef __ARMEB__
+ mov r12, r3, lsr #8
+#else
+ mov r12, r3, lsl #8
+#endif
+ ldr r3, [r1, #-4]!
+#ifdef __ARMEB__
+ orr r12, r12, r3, lsl #24
+#else
+ orr r12, r12, r3, lsr #24
+#endif
+ str r12, [r0, #-4]!
+ subs r2, r2, #4
+ bge .Lmemmove_bsrcul3loop4
+
+.Lmemmove_bsrcul3l4:
+ add r1, r1, #3
+ b .Lmemmove_bl4
+
+.Lmemmove_bsrcul2:
+ cmp r2, #0x0c
+ blt .Lmemmove_bsrcul2loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5, lr}
+
+.Lmemmove_bsrcul2loop16:
+#ifdef __ARMEB__
+ mov lr, r3, lsr #16
+#else
+ mov lr, r3, lsl #16
+#endif
+ ldmdb r1!, {r3-r5, r12}
+#ifdef __ARMEB__
+ orr lr, lr, r12, lsl #16
+ mov r12, r12, lsr #16
+ orr r12, r12, r5, lsl #16
+ mov r5, r5, lsr #16
+ orr r5, r5, r4, lsl #16
+ mov r4, r4, lsr #16
+ orr r4, r4, r3, lsl #16
+#else
+ orr lr, lr, r12, lsr #16
+ mov r12, r12, lsl #16
+ orr r12, r12, r5, lsr #16
+ mov r5, r5, lsl #16
+ orr r5, r5, r4, lsr #16
+ mov r4, r4, lsl #16
+ orr r4, r4, r3, lsr #16
+#endif
+ stmdb r0!, {r4, r5, r12, lr}
+ subs r2, r2, #0x10
+ bge .Lmemmove_bsrcul2loop16
+ ldmia sp!, {r4, r5, lr}
+ adds r2, r2, #0x0c
+ blt .Lmemmove_bsrcul2l4
+
+.Lmemmove_bsrcul2loop4:
+#ifdef __ARMEB__
+ mov r12, r3, lsr #16
+#else
+ mov r12, r3, lsl #16
+#endif
+ ldr r3, [r1, #-4]!
+#ifdef __ARMEB__
+ orr r12, r12, r3, lsl #16
+#else
+ orr r12, r12, r3, lsr #16
+#endif
+ str r12, [r0, #-4]!
+ subs r2, r2, #4
+ bge .Lmemmove_bsrcul2loop4
+
+.Lmemmove_bsrcul2l4:
+ add r1, r1, #2
+ b .Lmemmove_bl4
+
+.Lmemmove_bsrcul1:
+ cmp r2, #0x0c
+ blt .Lmemmove_bsrcul1loop4
+ sub r2, r2, #0x0c
+ stmdb sp!, {r4, r5, lr}
+
+.Lmemmove_bsrcul1loop32:
+#ifdef __ARMEB__
+ mov lr, r3, lsr #24
+#else
+ mov lr, r3, lsl #24
+#endif
+ ldmdb r1!, {r3-r5, r12}
+#ifdef __ARMEB__
+ orr lr, lr, r12, lsl #8
+ mov r12, r12, lsr #24
+ orr r12, r12, r5, lsl #8
+ mov r5, r5, lsr #24
+ orr r5, r5, r4, lsl #8
+ mov r4, r4, lsr #24
+ orr r4, r4, r3, lsl #8
+#else
+ orr lr, lr, r12, lsr #8
+ mov r12, r12, lsl #24
+ orr r12, r12, r5, lsr #8
+ mov r5, r5, lsl #24
+ orr r5, r5, r4, lsr #8
+ mov r4, r4, lsl #24
+ orr r4, r4, r3, lsr #8
+#endif
+ stmdb r0!, {r4, r5, r12, lr}
+ subs r2, r2, #0x10
+ bge .Lmemmove_bsrcul1loop32
+ ldmia sp!, {r4, r5, lr}
+ adds r2, r2, #0x0c
+ blt .Lmemmove_bsrcul1l4
+
+.Lmemmove_bsrcul1loop4:
+#ifdef __ARMEB__
+ mov r12, r3, lsr #24
+#else
+ mov r12, r3, lsl #24
+#endif
+ ldr r3, [r1, #-4]!
+#ifdef __ARMEB__
+ orr r12, r12, r3, lsl #8
+#else
+ orr r12, r12, r3, lsr #8
+#endif
+ str r12, [r0, #-4]!
+ subs r2, r2, #4
+ bge .Lmemmove_bsrcul1loop4
+
+.Lmemmove_bsrcul1l4:
+ add r1, r1, #1
+ b .Lmemmove_bl4
diff --git a/lib/libc/arm/string/memset.S b/lib/libc/arm/string/memset.S
new file mode 100644
index 0000000..5387aab
--- /dev/null
+++ b/lib/libc/arm/string/memset.S
@@ -0,0 +1,236 @@
+/* $NetBSD: memset.S,v 1.4 2003/10/14 07:51:45 scw Exp $ */
+
+/*
+ * Copyright 2003 Wasabi Systems, Inc.
+ * All rights reserved.
+ *
+ * Written by Steve C. Woodford for Wasabi Systems, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the NetBSD Project by
+ * Wasabi Systems, Inc.
+ * 4. The name of Wasabi Systems, Inc. may not be used to endorse
+ * or promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY WASABI SYSTEMS, INC. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL WASABI SYSTEMS, INC
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*
+ * Copyright (c) 1995 Mark Brinicombe.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe.
+ * 4. The name of the company nor the name of the author may be used to
+ * endorse or promote products derived from this software without specific
+ * prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * memset: Sets a block of memory to the specified value
+ *
+ * On entry:
+ * r0 - dest address
+ * r1 - byte to write
+ * r2 - number of bytes to write
+ *
+ * On exit:
+ * r0 - dest address
+ */
+#ifdef _BZERO
+/* LINTSTUB: Func: void bzero(void *, size_t) */
+ENTRY(bzero)
+ mov r3, #0x00
+#else
+/* LINTSTUB: Func: void *memset(void *, int, size_t) */
+ENTRY(memset)
+ and r3, r1, #0xff /* We deal with bytes */
+ mov r1, r2
+#endif
+ cmp r1, #0x04 /* Do we have less than 4 bytes */
+ mov ip, r0
+ blt .Lmemset_lessthanfour
+
+ /* Ok first we will word align the address */
+ ands r2, ip, #0x03 /* Get the bottom two bits */
+ bne .Lmemset_wordunaligned /* The address is not word aligned */
+
+ /* We are now word aligned */
+.Lmemset_wordaligned:
+#ifndef _BZERO
+ orr r3, r3, r3, lsl #8 /* Extend value to 16-bits */
+#endif
+#ifdef _ARM_ARCH_5E
+ tst ip, #0x04 /* Quad-align for armv5e */
+#else
+ cmp r1, #0x10
+#endif
+#ifndef _BZERO
+ orr r3, r3, r3, lsl #16 /* Extend value to 32-bits */
+#endif
+#ifdef _ARM_ARCH_5E
+ subne r1, r1, #0x04 /* Quad-align if necessary */
+ strne r3, [ip], #0x04
+ cmp r1, #0x10
+#endif
+ blt .Lmemset_loop4 /* If less than 16 then use words */
+ mov r2, r3 /* Duplicate data */
+ cmp r1, #0x80 /* If < 128 then skip the big loop */
+ blt .Lmemset_loop32
+
+ /* Do 128 bytes at a time */
+.Lmemset_loop128:
+ subs r1, r1, #0x80
+#ifdef _ARM_ARCH_5E
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+#else
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+#endif
+ bgt .Lmemset_loop128
+ RETeq /* Zero length so just exit */
+
+ add r1, r1, #0x80 /* Adjust for extra sub */
+
+ /* Do 32 bytes at a time */
+.Lmemset_loop32:
+ subs r1, r1, #0x20
+#ifdef _ARM_ARCH_5E
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+#else
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+#endif
+ bgt .Lmemset_loop32
+ RETeq /* Zero length so just exit */
+
+ adds r1, r1, #0x10 /* Partially adjust for extra sub */
+
+ /* Deal with 16 bytes or more */
+#ifdef _ARM_ARCH_5E
+ strged r2, [ip], #0x08
+ strged r2, [ip], #0x08
+#else
+ stmgeia ip!, {r2-r3}
+ stmgeia ip!, {r2-r3}
+#endif
+ RETeq /* Zero length so just exit */
+
+ addlt r1, r1, #0x10 /* Possibly adjust for extra sub */
+
+ /* We have at least 4 bytes so copy as words */
+.Lmemset_loop4:
+ subs r1, r1, #0x04
+ strge r3, [ip], #0x04
+ bgt .Lmemset_loop4
+ RETeq /* Zero length so just exit */
+
+#ifdef _ARM_ARCH_5E
+ /* Compensate for 64-bit alignment check */
+ adds r1, r1, #0x04
+ RETeq
+ cmp r1, #2
+#else
+ cmp r1, #-2
+#endif
+
+ strb r3, [ip], #0x01 /* Set 1 byte */
+ strgeb r3, [ip], #0x01 /* Set another byte */
+ strgtb r3, [ip] /* and a third */
+ RET /* Exit */
+
+.Lmemset_wordunaligned:
+ rsb r2, r2, #0x004
+ strb r3, [ip], #0x01 /* Set 1 byte */
+ cmp r2, #0x02
+ strgeb r3, [ip], #0x01 /* Set another byte */
+ sub r1, r1, r2
+ strgtb r3, [ip], #0x01 /* and a third */
+ cmp r1, #0x04 /* More than 4 bytes left? */
+ bge .Lmemset_wordaligned /* Yup */
+
+.Lmemset_lessthanfour:
+ cmp r1, #0x00
+ RETeq /* Zero length so exit */
+ strb r3, [ip], #0x01 /* Set 1 byte */
+ cmp r1, #0x02
+ strgeb r3, [ip], #0x01 /* Set another byte */
+ strgtb r3, [ip] /* and a third */
+ RET /* Exit */
diff --git a/lib/libc/arm/string/strcmp.S b/lib/libc/arm/string/strcmp.S
new file mode 100644
index 0000000..e5cba7d
--- /dev/null
+++ b/lib/libc/arm/string/strcmp.S
@@ -0,0 +1,43 @@
+/* $NetBSD: strcmp.S,v 1.3 2003/04/05 23:08:52 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 2002 ARM Ltd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD$");
+
+ENTRY(strcmp)
+1:
+ ldrb r2, [r0], #1
+ ldrb r3, [r1], #1
+ cmp r2, #1
+ cmpcs r2, r3
+ beq 1b
+ sub r0, r2, r3
+ RET
diff --git a/lib/libc/arm/string/strlen.S b/lib/libc/arm/string/strlen.S
new file mode 100644
index 0000000..378257d
--- /dev/null
+++ b/lib/libc/arm/string/strlen.S
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 2005 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(strlen)
+ mov r1, #0
+ /* Check that the pointer is aligned on 32 bits. */
+ ands r3, r0, #3
+ beq .Loop
+ sub r0, r0, r3
+ ldr r2, [r0]
+ add r0, r0, #4
+ cmp r3, #2
+ blt .Ldo_3
+ bgt .Ldo_1
+ /* So that the N bit is set. */
+ cmp r3, #0
+ b .Ldo_2
+
+.Loop:
+ ldr r2, [r0]
+ add r0, r0, #4
+#ifndef __ARMEB__
+ ands r3, r2, #0x000000ff
+#else
+ ands r3, r2, #0xff000000
+#endif
+ addne r1, r1, #1
+.Ldo_3:
+#ifndef __ARMEB__
+ andnes r3, r2, #0x0000ff00
+#else
+ andnes r3, r2, #0x00ff0000
+#endif
+ addne r1, r1, #1
+.Ldo_2:
+#ifndef __ARMEB__
+ andnes r3, r2, #0x00ff0000
+#else
+ andnes r3, r2, #0x0000ff00
+#endif
+ addne r1, r1, #1
+.Ldo_1:
+#ifndef __ARMEB__
+ andnes r3, r2, #0xff000000
+#else
+ andnes r3, r2, #0x000000ff
+#endif
+ addne r1, r1, #1
+ bne .Loop
+.Lexit:
+ mov r0, r1
+ RET
diff --git a/lib/libc/arm/string/strncmp.S b/lib/libc/arm/string/strncmp.S
new file mode 100644
index 0000000..fce0159
--- /dev/null
+++ b/lib/libc/arm/string/strncmp.S
@@ -0,0 +1,54 @@
+/* $NetBSD: strncmp.S,v 1.2 2003/04/05 23:08:52 bjh21 Exp $ */
+
+/*
+ * Copyright (c) 2002 ARM Ltd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD$");
+
+ENTRY(strncmp)
+/* if (len == 0) return 0 */
+ cmp r2, #0
+ moveq r0, #0
+ moveq pc, lr
+
+/* ip == last src address to compare */
+ adds ip, r0, r2
+/* Use last possible address on overflow. */
+ movcs ip, #0
+ sub ip, ip, #1
+1:
+ ldrb r2, [r0], #1
+ ldrb r3, [r1], #1
+ cmp ip, r0
+ cmpcs r2, #1
+ cmpcs r2, r3
+ beq 1b
+ sub r0, r2, r3
+ RET
diff --git a/lib/libc/arm/sys/Makefile.inc b/lib/libc/arm/sys/Makefile.inc
new file mode 100644
index 0000000..1a58eae
--- /dev/null
+++ b/lib/libc/arm/sys/Makefile.inc
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+MDASM= Ovfork.S brk.S cerror.S pipe.S ptrace.S sbrk.S shmat.S sigreturn.S syscall.S
+
+# Don't generate default code for these syscalls:
+NOASM= break.o exit.o getlogin.o openbsd_poll.o sstk.o vfork.o yield.o
+
+PSEUDO= _exit.o _getlogin.o
+.if !defined(WITHOUT_SYSCALL_COMPAT)
+PSEUDO+= _pread.o _pwrite.o _lseek.o _mmap.o _ftruncate.o _truncate.o
+.endif
diff --git a/lib/libc/arm/sys/Ovfork.S b/lib/libc/arm/sys/Ovfork.S
new file mode 100644
index 0000000..286347e
--- /dev/null
+++ b/lib/libc/arm/sys/Ovfork.S
@@ -0,0 +1,54 @@
+/* $NetBSD: Ovfork.S,v 1.6 2003/08/07 16:42:03 agc Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)Ovfork.s 5.1 (Berkeley) 4/23/90
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+/*
+ * pid = vfork();
+ *
+ * On return from the SWI:
+ * r1 == 0 in parent process, r1 == 1 in child process.
+ * r0 == pid of child in parent, r0 == pid of parent in child.
+ */
+ .text
+ .align 0
+
+ENTRY(vfork)
+ mov r2, r14
+ SYSTRAP(vfork)
+ bcs PIC_SYM(CERROR, PLT)
+ sub r1, r1, #1 /* r1 == 0xffffffff if parent, 0 if child */
+ and r0, r0, r1 /* r0 == 0 if child, else unchanged */
+ mov r15, r2
diff --git a/lib/libc/arm/sys/brk.S b/lib/libc/arm/sys/brk.S
new file mode 100644
index 0000000..5fdf90c
--- /dev/null
+++ b/lib/libc/arm/sys/brk.S
@@ -0,0 +1,100 @@
+/* $NetBSD: brk.S,v 1.6 2003/08/07 16:42:04 agc Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)brk.s 5.2 (Berkeley) 12/17/90
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+ .globl _C_LABEL(_end)
+ .globl CURBRK
+
+#ifdef WEAK_ALIAS
+WEAK_ALIAS(brk, _brk)
+#endif
+
+ .data
+ .align 0
+ .globl _C_LABEL(minbrk)
+ .type _C_LABEL(minbrk),#object
+_C_LABEL(minbrk):
+ .word _C_LABEL(_end)
+
+/*
+ * Change the data segment size
+ */
+ENTRY(_brk)
+#ifdef PIC
+ /* Setup the GOT */
+ ldr r3, .Lgot
+ add r3, pc, r3
+.L1:
+ ldr r1, .Lminbrk
+ ldr r1, [r3, r1]
+#else
+ ldr r1, .Lminbrk
+#endif
+ /* Get the minimum allowable brk address */
+ ldr r1, [r1]
+
+ /*
+ * Valid the address specified and set to the minimum
+ * if the address is below minbrk.
+ */
+ cmp r0, r1
+ movlt r0, r1
+ mov r2, r0
+ SYSTRAP(break)
+ bcs PIC_SYM(CERROR, PLT)
+
+#ifdef PIC
+ ldr r1, .Lcurbrk
+ ldr r1, [r3, r1]
+#else
+ ldr r1, .Lcurbrk
+#endif
+ /* Store the new address in curbrk */
+ str r2, [r1]
+
+ /* Return 0 for success */
+ mov r0, #0x00000000
+ RET
+
+ .align 2
+#ifdef PIC
+.Lgot:
+ .word _GLOBAL_OFFSET_TABLE_ - (.L1+4)
+#endif
+.Lminbrk:
+ .word PIC_SYM(_C_LABEL(minbrk), GOT)
+.Lcurbrk:
+ .word PIC_SYM(CURBRK, GOT)
diff --git a/lib/libc/arm/sys/cerror.S b/lib/libc/arm/sys/cerror.S
new file mode 100644
index 0000000..e807285
--- /dev/null
+++ b/lib/libc/arm/sys/cerror.S
@@ -0,0 +1,48 @@
+/* $NetBSD: cerror.S,v 1.5 2003/08/07 16:42:04 agc Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)cerror.s 5.1 (Berkeley) 4/23/90
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+.globl _C_LABEL(__error)
+.type _C_LABEL(__error),%function
+
+ASENTRY(CERROR)
+ stmfd sp!, {r4, lr}
+ mov r4, r0
+ bl PIC_SYM(_C_LABEL(__error), PLT)
+ str r4, [r0]
+ mvn r0, #0x00000000
+ mvn r1, #0x00000000
+ ldmfd sp!, {r4, pc}
diff --git a/lib/libc/arm/sys/fork.S b/lib/libc/arm/sys/fork.S
new file mode 100644
index 0000000..a5ae1f0
--- /dev/null
+++ b/lib/libc/arm/sys/fork.S
@@ -0,0 +1,49 @@
+/* $NetBSD: fork.S,v 1.5 2003/08/07 16:42:04 agc Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)fork.s 5.1 (Berkeley) 4/23/90
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+/*
+ * pid = fork();
+ *
+ * On return from the SWI:
+ * r1 == 0 in parent process, r1 == 1 in child process.
+ * r0 == pid of child in parent, r0 == pid of parent in child.
+ */
+
+_SYSCALL(fork)
+ sub r1, r1, #1 /* r1 == 0xffffffff if parent, 0 if child */
+ and r0, r0, r1 /* r0 == 0 if child, else unchanged */
+ RET
diff --git a/lib/libc/arm/sys/pipe.S b/lib/libc/arm/sys/pipe.S
new file mode 100644
index 0000000..83518fc2
--- /dev/null
+++ b/lib/libc/arm/sys/pipe.S
@@ -0,0 +1,50 @@
+/* $NetBSD: pipe.S,v 1.5 2003/08/07 16:42:04 agc Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)pipe.s 5.1 (Berkeley) 4/23/90
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+#ifdef WEAK_ALIAS
+WEAK_ALIAS(pipe, _pipe)
+WEAK_ALIAS(__sys_pipe, _pipe)
+#endif
+
+ENTRY(_pipe)
+ mov r2, r0
+ SYSTRAP(pipe)
+ bcs PIC_SYM(CERROR, PLT)
+ str r0, [r2, #0x0000]
+ str r1, [r2, #0x0004]
+ mov r0, #0x00000000
+ RET
diff --git a/lib/libc/arm/sys/ptrace.S b/lib/libc/arm/sys/ptrace.S
new file mode 100644
index 0000000..3cc13f3
--- /dev/null
+++ b/lib/libc/arm/sys/ptrace.S
@@ -0,0 +1,48 @@
+/* $NetBSD: ptrace.S,v 1.7 2003/08/07 16:42:04 agc Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)ptrace.s 5.1 (Berkeley) 4/23/90
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+ENTRY(ptrace)
+ stmfd sp!, {r0-r3, lr}
+ sub sp, sp, #4 /* align stack */
+ bl PIC_SYM(_C_LABEL(__error), PLT)
+ add sp, sp, #4 /* unalign stack */
+ mov r1, #0x00000000
+ str r1, [r0]
+ ldmfd sp!, {r0-r3, lr}
+ SYSTRAP(ptrace)
+ bcs PIC_SYM(CERROR, PLT)
+ RET
diff --git a/lib/libc/arm/sys/sbrk.S b/lib/libc/arm/sys/sbrk.S
new file mode 100644
index 0000000..d76e85a
--- /dev/null
+++ b/lib/libc/arm/sys/sbrk.S
@@ -0,0 +1,88 @@
+/* $NetBSD: sbrk.S,v 1.7 2003/08/07 16:42:05 agc Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)sbrk.s 5.1 (Berkeley) 4/23/90
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+ .globl _C_LABEL(_end)
+
+#ifdef WEAK_ALIAS
+WEAK_ALIAS(sbrk, _sbrk)
+#endif
+
+ .data
+ .align 0
+ .globl CURBRK
+ .type CURBRK,#object
+CURBRK:
+ .word _C_LABEL(_end)
+
+/*
+ * Change the data segment size
+ */
+ENTRY(_sbrk)
+#ifdef PIC
+ /* Setup the GOT */
+ ldr r3, .Lgot
+ add r3, pc, r3
+.L1:
+ ldr r2, .Lcurbrk
+ ldr r2, [r3, r2]
+#else
+ ldr r2, .Lcurbrk
+#endif
+ /* Get the current brk address */
+ ldr r1, [r2]
+
+ /* Calculate new value */
+ mov r3, r0
+ add r0, r0, r1
+ SYSTRAP(break)
+ bcs PIC_SYM(CERROR, PLT)
+
+ /* Store new curbrk value */
+ ldr r0, [r2]
+ add r1, r0, r3
+ str r1, [r2]
+
+ /* Return old curbrk value */
+ RET
+
+ .align 0
+#ifdef PIC
+.Lgot:
+ .word _GLOBAL_OFFSET_TABLE_ - (.L1+4)
+#endif
+.Lcurbrk:
+ .word PIC_SYM(CURBRK, GOT)
diff --git a/lib/libc/arm/sys/shmat.S b/lib/libc/arm/sys/shmat.S
new file mode 100644
index 0000000..3fc3d02
--- /dev/null
+++ b/lib/libc/arm/sys/shmat.S
@@ -0,0 +1,7 @@
+/* $NetBSD: shmat.S,v 1.1 2000/12/29 20:14:04 bjh21 Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+RSYSCALL(shmat)
diff --git a/lib/libc/arm/sys/sigreturn.S b/lib/libc/arm/sys/sigreturn.S
new file mode 100644
index 0000000..1e0f245
--- /dev/null
+++ b/lib/libc/arm/sys/sigreturn.S
@@ -0,0 +1,42 @@
+/* $NetBSD: __sigreturn14.S,v 1.3 2003/08/07 16:42:03 agc Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)sigreturn.s 5.2 (Berkeley) 12/17/90"
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+/*
+ * We must preserve the state of the registers as the user has set them up.
+ */
+
+RSYSCALL(sigreturn)
diff --git a/lib/libc/arm/sys/syscall.S b/lib/libc/arm/sys/syscall.S
new file mode 100644
index 0000000..73e6b83
--- /dev/null
+++ b/lib/libc/arm/sys/syscall.S
@@ -0,0 +1,38 @@
+/* $NetBSD: syscall.S,v 1.4 2003/08/07 16:42:05 agc Exp $ */
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)syscall.s 5.1 (Berkeley) 4/23/90
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+RSYSCALL(syscall)
diff --git a/lib/libc/compat-43/Makefile.inc b/lib/libc/compat-43/Makefile.inc
new file mode 100644
index 0000000..867a9d9
--- /dev/null
+++ b/lib/libc/compat-43/Makefile.inc
@@ -0,0 +1,24 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/2/93
+# $FreeBSD$
+
+# compat-43 sources
+.PATH: ${.CURDIR}/${LIBC_ARCH}/compat-43 ${.CURDIR}/compat-43
+
+SRCS+= creat.c gethostid.c getwd.c killpg.c sethostid.c setpgrp.c \
+ setrgid.c setruid.c sigcompat.c
+
+SYM_MAPS+=${.CURDIR}/compat-43/Symbol.map
+
+MAN+= creat.2 killpg.2 sigpause.2 sigsetmask.2 sigvec.2
+MAN+= gethostid.3 setruid.3
+
+MLINKS+=gethostid.3 sethostid.3
+MLINKS+=sigpause.2 sighold.2
+MLINKS+=sigpause.2 sigignore.2
+MLINKS+=sigpause.2 sigrelse.2
+MLINKS+=sigpause.2 sigset.2
+MLINKS+=sigpause.2 xsi_sigpause.2
+MLINKS+=setruid.3 setrgid.3
+
+MLINKS+=sigsetmask.2 sigblock.2
+MLINKS+=sigsetmask.2 sigmask.2
diff --git a/lib/libc/compat-43/Symbol.map b/lib/libc/compat-43/Symbol.map
new file mode 100644
index 0000000..bd49f99
--- /dev/null
+++ b/lib/libc/compat-43/Symbol.map
@@ -0,0 +1,31 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ creat;
+ gethostid;
+ getwd;
+ killpg;
+ sethostid;
+ setpgrp;
+ setrgid;
+ setruid;
+ sigblock;
+ sigpause;
+ sigsetmask;
+ sigvec;
+};
+
+FBSD_1.2 {
+ sighold;
+ sigignore;
+ sigrelse;
+ sigset;
+ xsi_sigpause;
+};
+
+FBSDprivate_1.0 {
+ __creat;
+ _creat;
+};
diff --git a/lib/libc/compat-43/creat.2 b/lib/libc/compat-43/creat.2
new file mode 100644
index 0000000..3b1d03b
--- /dev/null
+++ b/lib/libc/compat-43/creat.2
@@ -0,0 +1,62 @@
+.\" Copyright (c) 1989, 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)creat.2 8.1 (Berkeley) 6/2/93
+.\" $FreeBSD$
+.\"
+.Dd June 2, 1993
+.Dt CREAT 2
+.Os
+.Sh NAME
+.Nm creat
+.Nd create a new file
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In fcntl.h
+.Ft int
+.Fn creat "const char *path" "mode_t mode"
+.Sh DESCRIPTION
+.Bf -symbolic
+This interface is made obsolete by:
+.Ef
+.Xr open 2 .
+.Pp
+The
+.Fn creat
+function
+is the same as:
+.Bd -literal -offset indent
+open(path, O_CREAT | O_TRUNC | O_WRONLY, mode);
+.Ed
+.Sh SEE ALSO
+.Xr open 2
+.Sh HISTORY
+The
+.Fn creat
+function appeared in
+.At v6 .
diff --git a/lib/libc/compat-43/creat.c b/lib/libc/compat-43/creat.c
new file mode 100644
index 0000000..fc3be06
--- /dev/null
+++ b/lib/libc/compat-43/creat.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)creat.c 8.1 (Berkeley) 6/2/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <fcntl.h>
+#include "un-namespace.h"
+
+int
+__creat(const char *path, mode_t mode)
+{
+ return(_open(path, O_WRONLY|O_CREAT|O_TRUNC, mode));
+}
+__weak_reference(__creat, creat);
+__weak_reference(__creat, _creat);
diff --git a/lib/libc/compat-43/gethostid.3 b/lib/libc/compat-43/gethostid.3
new file mode 100644
index 0000000..faaee56
--- /dev/null
+++ b/lib/libc/compat-43/gethostid.3
@@ -0,0 +1,80 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)gethostid.3 8.1 (Berkeley) 6/2/93
+.\" $FreeBSD$
+.\"
+.Dd June 2, 1993
+.Dt GETHOSTID 3
+.Os
+.Sh NAME
+.Nm gethostid ,
+.Nm sethostid
+.Nd get/set unique identifier of current host
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft long
+.Fn gethostid void
+.Ft void
+.Fn sethostid "long hostid"
+.Sh DESCRIPTION
+The
+.Fn sethostid
+function
+establishes a 32-bit identifier for the
+current processor that is intended to be unique among all
+UNIX systems in existence.
+This is normally a DARPA Internet
+address for the local machine.
+This call is allowed only to the
+super-user and is normally performed at boot time.
+.Pp
+The
+.Fn gethostid
+function
+returns the 32-bit identifier for the current processor.
+.Pp
+This function has been deprecated.
+The hostid should be set or retrieved by use of
+.Xr sysctl 3 .
+.Sh SEE ALSO
+.Xr gethostname 3 ,
+.Xr sysctl 3 ,
+.Xr sysctl 8
+.Sh HISTORY
+The
+.Fn gethostid
+and
+.Fn sethostid
+syscalls appeared in
+.Bx 4.2
+and were dropped in
+.Bx 4.4 .
+.Sh BUGS
+32 bits for the identifier is too small.
diff --git a/lib/libc/compat-43/gethostid.c b/lib/libc/compat-43/gethostid.c
new file mode 100644
index 0000000..6c33850
--- /dev/null
+++ b/lib/libc/compat-43/gethostid.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostid.c 8.1 (Berkeley) 6/2/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <unistd.h>
+
+long
+gethostid(void)
+{
+ int mib[2];
+ size_t size;
+ long value;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_HOSTID;
+ size = sizeof value;
+ if (sysctl(mib, 2, &value, &size, NULL, 0) == -1)
+ return (-1);
+ return (value);
+}
diff --git a/lib/libc/compat-43/getwd.c b/lib/libc/compat-43/getwd.c
new file mode 100644
index 0000000..98fceaf
--- /dev/null
+++ b/lib/libc/compat-43/getwd.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getwd.c 8.1 (Berkeley) 6/2/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+char *
+getwd(char *buf)
+{
+ char *p;
+
+ if ( (p = getcwd(buf, MAXPATHLEN)) )
+ return(p);
+ (void)strerror_r(errno, buf, MAXPATHLEN);
+ return((char *)NULL);
+}
diff --git a/lib/libc/compat-43/killpg.2 b/lib/libc/compat-43/killpg.2
new file mode 100644
index 0000000..b23b773
--- /dev/null
+++ b/lib/libc/compat-43/killpg.2
@@ -0,0 +1,95 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)killpg.2 8.1 (Berkeley) 6/2/93
+.\" $FreeBSD$
+.\"
+.Dd March 15, 2012
+.Dt KILLPG 2
+.Os
+.Sh NAME
+.Nm killpg
+.Nd send signal to a process group
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In signal.h
+.Ft int
+.Fn killpg "pid_t pgrp" "int sig"
+.Sh DESCRIPTION
+The
+.Fn killpg
+function
+sends the signal
+.Fa sig
+to the process group
+.Fa pgrp .
+See
+.Xr sigaction 2
+for a list of signals.
+If
+.Fa pgrp
+is 0,
+.Fn killpg
+sends the signal to the sending process's process group.
+.Pp
+The sending process and members of the process group must
+have the same effective user ID, or
+the sender must be the super-user.
+As a single special case the continue signal SIGCONT may be sent
+to any process with the same session ID as the caller.
+.Sh RETURN VALUES
+.Rv -std killpg
+.Sh ERRORS
+The
+.Fn killpg
+function
+will fail and no signal will be sent if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa sig
+argument
+is not a valid signal number.
+.It Bq Er ESRCH
+No process can be found in the process group specified by
+.Fa pgrp .
+.It Bq Er EPERM
+The sending process is not the super-user and one or more
+of the target processes has an effective user ID different from that
+of the sending process.
+.El
+.Sh SEE ALSO
+.Xr getpgrp 2 ,
+.Xr kill 2 ,
+.Xr sigaction 2
+.Sh HISTORY
+The
+.Fn killpg
+function appeared in
+.Bx 4.0 .
diff --git a/lib/libc/compat-43/killpg.c b/lib/libc/compat-43/killpg.c
new file mode 100644
index 0000000..a8e36ae
--- /dev/null
+++ b/lib/libc/compat-43/killpg.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)killpg.c 8.1 (Berkeley) 6/2/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <signal.h>
+#include <errno.h>
+
+/*
+ * Backwards-compatible killpg().
+ */
+int
+killpg(pid_t pgid, int sig)
+{
+ if (pgid == 1) {
+ errno = ESRCH;
+ return (-1);
+ }
+ return (kill(-pgid, sig));
+}
diff --git a/lib/libc/compat-43/sethostid.c b/lib/libc/compat-43/sethostid.c
new file mode 100644
index 0000000..95c8333
--- /dev/null
+++ b/lib/libc/compat-43/sethostid.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)sethostid.c 8.1 (Berkeley) 6/2/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <unistd.h>
+
+void
+sethostid(long hostid)
+{
+ int mib[2];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_HOSTID;
+ sysctl(mib, 2, NULL, NULL, &hostid, sizeof hostid);
+}
diff --git a/lib/libc/compat-43/setpgrp.c b/lib/libc/compat-43/setpgrp.c
new file mode 100644
index 0000000..39713d2
--- /dev/null
+++ b/lib/libc/compat-43/setpgrp.c
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setpgrp.c 8.1 (Berkeley) 6/2/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <unistd.h>
+
+int
+setpgrp(pid_t pid, pid_t pgid)
+{
+ return(setpgid(pid, pgid));
+}
diff --git a/lib/libc/compat-43/setrgid.c b/lib/libc/compat-43/setrgid.c
new file mode 100644
index 0000000..f006c76
--- /dev/null
+++ b/lib/libc/compat-43/setrgid.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setrgid.c 8.1 (Berkeley) 6/2/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <unistd.h>
+
+int
+setrgid(gid_t rgid)
+{
+
+ return (setregid(rgid, -1));
+}
diff --git a/lib/libc/compat-43/setruid.3 b/lib/libc/compat-43/setruid.3
new file mode 100644
index 0000000..22584cf
--- /dev/null
+++ b/lib/libc/compat-43/setruid.3
@@ -0,0 +1,80 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)setruid.3 8.1 (Berkeley) 6/2/93
+.\" $FreeBSD$
+.\"
+.Dd June 2, 1993
+.Dt SETRUID 3
+.Os
+.Sh NAME
+.Nm setruid ,
+.Nm setrgid
+.Nd set user and group ID
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn setruid "uid_t ruid"
+.Ft int
+.Fn setrgid "gid_t rgid"
+.Sh DESCRIPTION
+The
+.Fn setruid
+function
+.Pq Fn setrgid
+sets the real user ID (group ID) of the
+current process.
+.Sh RETURN VALUES
+.Rv -std
+.Sh COMPATIBILITY
+The use of these calls is not portable.
+Their use is discouraged; they will be removed in the future.
+.Sh ERRORS
+The functions fail if:
+.Bl -tag -width Er
+.It Bq Er EPERM
+The user is not the super user and the ID
+specified is not the real or effective ID.
+.El
+.Sh SEE ALSO
+.Xr getgid 2 ,
+.Xr getuid 2 ,
+.Xr setegid 2 ,
+.Xr seteuid 2 ,
+.Xr setgid 2 ,
+.Xr setuid 2
+.Sh HISTORY
+The
+.Fn setruid
+and
+.Fn setrgid
+syscalls appeared in
+.Bx 4.2
+and were dropped in
+.Bx 4.4 .
diff --git a/lib/libc/compat-43/setruid.c b/lib/libc/compat-43/setruid.c
new file mode 100644
index 0000000..33c9db1
--- /dev/null
+++ b/lib/libc/compat-43/setruid.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setruid.c 8.1 (Berkeley) 6/2/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <unistd.h>
+
+int
+setruid(uid_t ruid)
+{
+
+ return (setreuid(ruid, -1));
+}
diff --git a/lib/libc/compat-43/sigcompat.c b/lib/libc/compat-43/sigcompat.c
new file mode 100644
index 0000000..199846f
--- /dev/null
+++ b/lib/libc/compat-43/sigcompat.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)sigcompat.c 8.1 (Berkeley) 6/2/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <errno.h>
+#include <signal.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+int
+sigvec(signo, sv, osv)
+ int signo;
+ struct sigvec *sv, *osv;
+{
+ struct sigaction sa, osa;
+ struct sigaction *sap, *osap;
+ int ret;
+
+ if (sv != NULL) {
+ sa.sa_handler = sv->sv_handler;
+ sa.sa_flags = sv->sv_flags ^ SV_INTERRUPT;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_mask.__bits[0] = sv->sv_mask;
+ sap = &sa;
+ } else
+ sap = NULL;
+ osap = osv != NULL ? &osa : NULL;
+ ret = _sigaction(signo, sap, osap);
+ if (ret == 0 && osv != NULL) {
+ osv->sv_handler = osa.sa_handler;
+ osv->sv_flags = osa.sa_flags ^ SV_INTERRUPT;
+ osv->sv_mask = osa.sa_mask.__bits[0];
+ }
+ return (ret);
+}
+
+int
+sigsetmask(mask)
+ int mask;
+{
+ sigset_t set, oset;
+ int n;
+
+ sigemptyset(&set);
+ set.__bits[0] = mask;
+ n = _sigprocmask(SIG_SETMASK, &set, &oset);
+ if (n)
+ return (n);
+ return (oset.__bits[0]);
+}
+
+int
+sigblock(mask)
+ int mask;
+{
+ sigset_t set, oset;
+ int n;
+
+ sigemptyset(&set);
+ set.__bits[0] = mask;
+ n = _sigprocmask(SIG_BLOCK, &set, &oset);
+ if (n)
+ return (n);
+ return (oset.__bits[0]);
+}
+
+int
+sigpause(int mask)
+{
+ sigset_t set;
+
+ sigemptyset(&set);
+ set.__bits[0] = mask;
+ return (_sigsuspend(&set));
+}
+
+int
+xsi_sigpause(int sig)
+{
+ sigset_t set;
+
+ if (_sigprocmask(SIG_BLOCK, NULL, &set) == -1)
+ return (-1);
+ if (sigdelset(&set, sig) == -1)
+ return (-1);
+ return (_sigsuspend(&set));
+}
+
+int
+sighold(int sig)
+{
+ sigset_t set;
+
+ sigemptyset(&set);
+ if (sigaddset(&set, sig) == -1)
+ return (-1);
+ return (_sigprocmask(SIG_BLOCK, &set, NULL));
+}
+
+int
+sigignore(int sig)
+{
+ struct sigaction sa;
+
+ bzero(&sa, sizeof(sa));
+ sa.sa_handler = SIG_IGN;
+ return (_sigaction(sig, &sa, NULL));
+}
+
+int
+sigrelse(int sig)
+{
+ sigset_t set;
+
+ sigemptyset(&set);
+ if (sigaddset(&set, sig) == -1)
+ return (-1);
+ return (_sigprocmask(SIG_UNBLOCK, &set, NULL));
+}
+
+void
+(*sigset(int sig, void (*disp)(int)))(int)
+{
+ sigset_t set, pset;
+ struct sigaction sa, psa;
+
+ sigemptyset(&set);
+ if (sigaddset(&set, sig) == -1)
+ return (SIG_ERR);
+ if (_sigprocmask(SIG_BLOCK, NULL, &pset) == -1)
+ return (SIG_ERR);
+ if ((__sighandler_t *)disp == SIG_HOLD) {
+ if (_sigprocmask(SIG_BLOCK, &set, &pset) == -1)
+ return (SIG_ERR);
+ if (sigismember(&pset, sig))
+ return (SIG_HOLD);
+ else {
+ if (_sigaction(sig, NULL, &psa) == -1)
+ return (SIG_ERR);
+ return (psa.sa_handler);
+ }
+ } else {
+ if (_sigprocmask(SIG_UNBLOCK, &set, &pset) == -1)
+ return (SIG_ERR);
+ }
+
+ bzero(&sa, sizeof(sa));
+ sa.sa_handler = disp;
+ if (_sigaction(sig, &sa, &psa) == -1)
+ return (SIG_ERR);
+ if (sigismember(&pset, sig))
+ return (SIG_HOLD);
+ else
+ return (psa.sa_handler);
+}
diff --git a/lib/libc/compat-43/sigpause.2 b/lib/libc/compat-43/sigpause.2
new file mode 100644
index 0000000..1187b52
--- /dev/null
+++ b/lib/libc/compat-43/sigpause.2
@@ -0,0 +1,242 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)sigpause.2 8.1 (Berkeley) 6/2/93
+.\" $FreeBSD$
+.\"
+.\" Part of the content of the man page was derived from
+.\" The Open Group Base Specifications Issue 7
+.\" IEEE Std 1003.1-2008
+.\"
+.Dd June 2, 1993
+.Dt SIGPAUSE 2
+.Os
+.Sh NAME
+.Nm sighold ,
+.Nm sigignore ,
+.Nm sigpause ,
+.Nm sigrelse ,
+.Nm sigset
+.Nd legacy interface for signal management
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In signal.h
+.Ft int
+.Fn sighold "int sig"
+.Ft int
+.Fn sigignore "int sig"
+.Ft int
+.Fn xsi_sigpause "int sigmask"
+.Ft int
+.Fn sigrelse "int sig"
+.Ft void (*)(int)
+.Fn sigset "int" "void (*disp)(int)"
+.Ft int
+.Fn sigpause "int sigmask"
+.Sh DESCRIPTION
+.Sy This interface is made obsolete by
+.Xr sigsuspend 2
+.Sy and
+.Xr sigaction 2
+.Pp
+The
+.Fn sigset
+function modifies signal dispositions.
+The
+.Fa sig
+argument specifies the signal, which may be any signal except
+.Dv SIGKILL
+and
+.Dv SIGSTOP .
+The
+.Fa disp
+argument specifies the signal's disposition,
+which may be
+.Dv SIG_DFL ,
+.Dv SIG_IGN ,
+or the address of a signal handler.
+If
+.Fn sigset
+is used, and
+.Fa disp
+is the address of a signal handler, the
+system adds
+.Fa sig
+to the signal mask of the calling process before executing the signal
+handler; when the signal handler returns, the system restores the
+signal mask of the calling process to its state prior to the delivery
+of the signal.
+In addition, if
+.Fn sigset
+is used, and
+.Fa disp
+is equal to
+.Dv SIG_HOLD ,
+.Fa sig
+is added to the signal
+mask of the calling process and
+.Fa sig 's
+disposition remains unchanged.
+If
+.Fn sigset
+is used, and
+.Fa disp
+is not equal to
+.Dv SIG_HOLD ,
+.Fa sig
+is removed from the signal mask of the calling process.
+.Pp
+The
+.Fn sighold
+function adds
+.Fa sig
+to the signal mask of the calling process.
+.Pp
+The
+.Fn sigrelse
+function removes
+.Fa sig
+from the signal mask of the calling process.
+.Pp
+The
+.Fn sigignore
+function sets the disposition of
+.Fa sig
+to
+.Dv SIG_IGN .
+.Pp
+The
+.Fn xsi_sigpause
+function removes
+.Fa sig
+from the signal mask of the calling process and suspend the calling process
+until a signal is received.
+The
+.Fn xsi_sigpause
+function restores the signal mask of the process to its original state before
+returning.
+.Pp
+The
+.Fn sigpause
+function
+assigns
+.Fa sigmask
+to the set of masked signals
+and then waits for a signal to arrive;
+on return the set of masked signals is restored.
+The
+.Fa sigmask
+argument
+is usually 0 to indicate that no
+signals are to be blocked.
+.Sh RETURN VALUES
+The
+.Fn sigpause
+and
+.Fn xsi_sigpause
+functions
+always terminate by being interrupted, returning -1 with
+.Va errno
+set to
+.Er EINTR .
+.Pp
+Upon successful completion,
+.Fn sigset
+returns
+.Dv SIG_HOLD
+if the signal had been blocked and the signal's previous disposition if
+it had not been blocked.
+Otherwise,
+.Dv SIG_ERR is returned and
+.Va errno
+set to indicate the error.
+.Pp
+For all other functions, upon successful completion, 0 is returned.
+Otherwise, -1 is returned and
+.Va errno
+is set to indicate the error:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa sig
+argument
+is not a valid signal number.
+.It Bq Er EINVAL
+For
+.Fn sigset
+and
+.Fn sigignore
+functions, an attempt was made to catch or ignore
+.Dv SIGKILL
+or
+.Dv SIGSTOP .
+.El
+.Sh SEE ALSO
+.Xr kill 2 ,
+.Xr sigaction 2 ,
+.Xr sigblock 2 ,
+.Xr sigprocmask 2 ,
+.Xr sigsuspend 2 ,
+.Xr sigvec 2
+.Sh STANDARDS
+The
+.Fn sigpause
+function is implemented for compatibility with historic
+.Bx 4.3
+applications.
+An incompatible interface by the same name, which used a single signal number
+rather than a mask, was present in
+.At V ,
+and was copied from there into the
+.Sy X/Open System Interfaces
+.Pq Tn XSI
+option of
+.St -p1003.1-2001 .
+.Fx
+implements it under the name
+.Fn xsi_sigpause .
+The
+.Fn sighold ,
+.Fn sigignore ,
+.Fn sigrelse
+and
+.Fn sigset
+functions are implemented for compatibility with
+.Sy System V
+and
+.Sy XSI
+interfaces.
+.Sh HISTORY
+The
+.Fn sigpause
+function appeared in
+.Bx 4.2
+and has been deprecated.
+All other functions appeared in
+.Fx 8.1
+and were deprecated before being implemented.
diff --git a/lib/libc/compat-43/sigsetmask.2 b/lib/libc/compat-43/sigsetmask.2
new file mode 100644
index 0000000..8894a1e
--- /dev/null
+++ b/lib/libc/compat-43/sigsetmask.2
@@ -0,0 +1,103 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)sigsetmask.2 8.1 (Berkeley) 6/2/93
+.\" $FreeBSD$
+.\"
+.Dd June 2, 1993
+.Dt SIGSETMASK 2
+.Os
+.Sh NAME
+.Nm sigsetmask ,
+.Nm sigblock
+.Nd manipulate current signal mask
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In signal.h
+.Ft int
+.Fn sigsetmask "int mask"
+.Ft int
+.Fn sigblock "int mask"
+.Ft int
+.Fn sigmask "int signum"
+.Sh DESCRIPTION
+.Bf -symbolic
+This interface is made obsolete by:
+.Ef
+.Xr sigprocmask 2 .
+.Pp
+The
+.Fn sigsetmask
+function
+sets the current signal mask to the specified
+.Fa mask .
+Signals are blocked from delivery if the corresponding bit in
+.Fa mask
+is a 1.
+The
+.Fn sigblock
+function
+adds the signals in the specified
+.Fa mask
+to the current signal mask,
+rather than overwriting it as
+.Fn sigsetmask
+does.
+The macro
+.Fn sigmask
+is provided to construct the mask for a given
+.Fa signum .
+.Pp
+The system
+quietly disallows
+.Dv SIGKILL
+or
+.Dv SIGSTOP
+to be blocked.
+.Sh RETURN VALUES
+The
+.Fn sigblock
+and
+.Fn sigsetmask
+functions
+return the previous set of masked signals.
+.Sh SEE ALSO
+.Xr kill 2 ,
+.Xr sigaction 2 ,
+.Xr sigprocmask 2 ,
+.Xr sigsuspend 2 ,
+.Xr sigvec 2 ,
+.Xr sigsetops 3
+.Sh HISTORY
+The
+.Fn sigsetmask
+and
+.Fn sigblock
+functions first appeared in
+.Bx 4.2
+and have been deprecated.
diff --git a/lib/libc/compat-43/sigvec.2 b/lib/libc/compat-43/sigvec.2
new file mode 100644
index 0000000..d15c023
--- /dev/null
+++ b/lib/libc/compat-43/sigvec.2
@@ -0,0 +1,342 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)sigvec.2 8.2 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd April 19, 1994
+.Dt SIGVEC 2
+.Os
+.Sh NAME
+.Nm sigvec
+.Nd software signal facilities
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In signal.h
+.Bd -literal
+struct sigvec {
+ void (*sv_handler)();
+ int sv_mask;
+ int sv_flags;
+};
+.Ed
+.Ft int
+.Fn sigvec "int sig" "struct sigvec *vec" "struct sigvec *ovec"
+.Sh DESCRIPTION
+.Bf -symbolic
+This interface is made obsolete by
+.Xr sigaction 2 .
+.Ef
+.Pp
+The system defines a set of signals that may be delivered to a process.
+Signal delivery resembles the occurrence of a hardware interrupt:
+the signal is blocked from further occurrence, the current process
+context is saved, and a new one is built.
+A process may specify a
+.Em handler
+to which a signal is delivered, or specify that a signal is to be
+.Em blocked
+or
+.Em ignored .
+A process may also specify that a default action is to be taken
+by the system when a signal occurs.
+Normally, signal handlers execute on the current stack
+of the process.
+This may be changed, on a per-handler basis,
+so that signals are taken on a special
+.Em "signal stack" .
+.Pp
+All signals have the same
+.Em priority .
+Signal routines execute with the signal that caused their
+invocation
+.Em blocked ,
+but other signals may yet occur.
+A global
+.Em "signal mask"
+defines the set of signals currently blocked from delivery
+to a process.
+The signal mask for a process is initialized
+from that of its parent (normally 0).
+It
+may be changed with a
+.Xr sigblock 2
+or
+.Xr sigsetmask 2
+call, or when a signal is delivered to the process.
+.Pp
+When a signal
+condition arises for a process, the signal is added to a set of
+signals pending for the process.
+If the signal is not currently
+.Em blocked
+by the process then it is delivered to the process.
+When a signal
+is delivered, the current state of the process is saved,
+a new signal mask is calculated (as described below),
+and the signal handler is invoked.
+The call to the handler
+is arranged so that if the signal handling routine returns
+normally the process will resume execution in the context
+from before the signal's delivery.
+If the process wishes to resume in a different context, then it
+must arrange to restore the previous context itself.
+.Pp
+When a signal is delivered to a process a new signal mask is
+installed for the duration of the process' signal handler
+(or until a
+.Xr sigblock 2
+or
+.Xr sigsetmask 2
+call is made).
+This mask is formed by taking the current signal mask,
+adding the signal to be delivered, and
+.Em or Ns 'ing
+in the signal mask associated with the handler to be invoked.
+.Pp
+The
+.Fn sigvec
+function
+assigns a handler for a specific signal.
+If
+.Fa vec
+is non-zero, it
+specifies a handler routine and mask
+to be used when delivering the specified signal.
+Further, if the
+.Dv SV_ONSTACK
+bit is set in
+.Fa sv_flags ,
+the system will deliver the signal to the process on a
+.Em "signal stack" ,
+specified with
+.Xr sigaltstack 2 .
+If
+.Fa ovec
+is non-zero, the previous handling information for the signal
+is returned to the user.
+.Pp
+The following is a list of all signals
+with names as in the include file
+.In signal.h :
+.Bl -column SIGVTALARMXX "create core imagexxx"
+.It Sy "NAME Default Action Description"
+.It Dv SIGHUP No " terminate process" " terminal line hangup"
+.It Dv SIGINT No " terminate process" " interrupt program"
+.It Dv SIGQUIT No " create core image" " quit program"
+.It Dv SIGILL No " create core image" " illegal instruction"
+.It Dv SIGTRAP No " create core image" " trace trap"
+.It Dv SIGABRT No " create core image" Ta Xr abort 3
+call (formerly
+.Dv SIGIOT )
+.It Dv SIGEMT No " create core image" " emulate instruction executed"
+.It Dv SIGFPE No " create core image" " floating-point exception"
+.It Dv SIGKILL No " terminate process" " kill program"
+.It Dv SIGBUS No " create core image" " bus error"
+.It Dv SIGSEGV No " create core image" " segmentation violation"
+.It Dv SIGSYS No " create core image" " non-existent system call invoked"
+.It Dv SIGPIPE No " terminate process" " write on a pipe with no reader"
+.It Dv SIGALRM No " terminate process" " real-time timer expired"
+.It Dv SIGTERM No " terminate process" " software termination signal"
+.It Dv SIGURG No " discard signal" " urgent condition present on socket"
+.It Dv SIGSTOP No " stop process" " stop (cannot be caught or ignored)"
+.It Dv SIGTSTP No " stop process" " stop signal generated from keyboard"
+.It Dv SIGCONT No " discard signal" " continue after stop"
+.It Dv SIGCHLD No " discard signal" " child status has changed"
+.It Dv SIGTTIN No " stop process" " background read attempted from control terminal"
+.It Dv SIGTTOU No " stop process" " background write attempted to control terminal"
+.It Dv SIGIO No " discard signal" Tn " I/O"
+is possible on a descriptor (see
+.Xr fcntl 2 )
+.It Dv SIGXCPU No " terminate process" " cpu time limit exceeded (see"
+.Xr setrlimit 2 )
+.It Dv SIGXFSZ No " terminate process" " file size limit exceeded (see"
+.Xr setrlimit 2 )
+.It Dv SIGVTALRM No " terminate process" " virtual time alarm (see"
+.Xr setitimer 2 )
+.It Dv SIGPROF No " terminate process" " profiling timer alarm (see"
+.Xr setitimer 2 )
+.It Dv SIGWINCH No " discard signal" " Window size change"
+.It Dv SIGINFO No " discard signal" " status request from keyboard"
+.It Dv SIGUSR1 No " terminate process" " User defined signal 1"
+.It Dv SIGUSR2 No " terminate process" " User defined signal 2"
+.El
+.Pp
+Once a signal handler is installed, it remains installed
+until another
+.Fn sigvec
+call is made, or an
+.Xr execve 2
+is performed.
+A signal-specific default action may be reset by
+setting
+.Fa sv_handler
+to
+.Dv SIG_DFL .
+The defaults are process termination, possibly with core dump;
+no action; stopping the process; or continuing the process.
+See the above signal list for each signal's default action.
+If
+.Fa sv_handler
+is
+.Dv SIG_IGN
+current and pending instances
+of the signal are ignored and discarded.
+.Pp
+If a signal is caught during the system calls listed below,
+the call is normally restarted.
+The call can be forced to terminate prematurely with an
+.Er EINTR
+error return by setting the
+.Dv SV_INTERRUPT
+bit in
+.Fa sv_flags .
+The affected system calls include
+.Xr read 2 ,
+.Xr write 2 ,
+.Xr sendto 2 ,
+.Xr recvfrom 2 ,
+.Xr sendmsg 2
+and
+.Xr recvmsg 2
+on a communications channel or a slow device (such as a terminal,
+but not a regular file)
+and during a
+.Xr wait 2
+or
+.Xr ioctl 2 .
+However, calls that have already committed are not restarted,
+but instead return a partial success (for example, a short read count).
+.Pp
+After a
+.Xr fork 2
+or
+.Xr vfork 2
+all signals, the signal mask, the signal stack,
+and the restart/interrupt flags are inherited by the child.
+.Pp
+The
+.Xr execve 2
+system call reinstates the default
+action for all signals which were caught and
+resets all signals to be caught on the user stack.
+Ignored signals remain ignored;
+the signal mask remains the same;
+signals that interrupt system calls continue to do so.
+.Sh NOTES
+The mask specified in
+.Fa vec
+is not allowed to block
+.Dv SIGKILL
+or
+.Dv SIGSTOP .
+This is done silently by the system.
+.Pp
+The
+.Dv SV_INTERRUPT
+flag is not available in
+.Bx 4.2 ,
+hence it should not be used if backward compatibility is needed.
+.Sh RETURN VALUES
+.Rv -std sigvec
+.Sh EXAMPLES
+On the
+.Tn VAX\-11
+The handler routine can be declared:
+.Bd -literal -offset indent
+void handler(sig, code, scp)
+int sig, code;
+struct sigcontext *scp;
+.Ed
+.Pp
+Here
+.Fa sig
+is the signal number, into which the hardware faults and traps are
+mapped as defined below.
+The
+.Fa code
+argument
+is either a constant
+as given below or, for compatibility mode faults, the code provided by
+the hardware (Compatibility mode faults are distinguished from the
+other
+.Dv SIGILL
+traps by having
+.Dv PSL_CM
+set in the psl).
+The
+.Fa scp
+argument
+is a pointer to the
+.Fa sigcontext
+structure (defined in
+.In signal.h ) ,
+used to restore the context from before the signal.
+.Sh ERRORS
+The
+.Fn sigvec
+function
+will fail and no new signal handler will be installed if one
+of the following occurs:
+.Bl -tag -width Er
+.It Bq Er EFAULT
+Either
+.Fa vec
+or
+.Fa ovec
+points to memory that is not a valid part of the process
+address space.
+.It Bq Er EINVAL
+The
+.Fa sig
+argument
+is not a valid signal number.
+.It Bq Er EINVAL
+An attempt is made to ignore or supply a handler for
+.Dv SIGKILL
+or
+.Dv SIGSTOP .
+.El
+.Sh SEE ALSO
+.Xr kill 1 ,
+.Xr kill 2 ,
+.Xr ptrace 2 ,
+.Xr sigaction 2 ,
+.Xr sigaltstack 2 ,
+.Xr sigblock 2 ,
+.Xr sigpause 2 ,
+.Xr sigprocmask 2 ,
+.Xr sigsetmask 2 ,
+.Xr sigsuspend 2 ,
+.Xr setjmp 3 ,
+.Xr siginterrupt 3 ,
+.Xr signal 3 ,
+.Xr sigsetops 3 ,
+.Xr tty 4
+.Sh BUGS
+This manual page is still confusing.
diff --git a/lib/libc/db/Makefile.inc b/lib/libc/db/Makefile.inc
new file mode 100644
index 0000000..bbfb7e7
--- /dev/null
+++ b/lib/libc/db/Makefile.inc
@@ -0,0 +1,13 @@
+# from @(#)Makefile.inc 8.2 (Berkeley) 2/21/94
+# $FreeBSD$
+#
+CFLAGS+=-D__DBINTERFACE_PRIVATE
+
+.include "${.CURDIR}/db/btree/Makefile.inc"
+.include "${.CURDIR}/db/db/Makefile.inc"
+.include "${.CURDIR}/db/hash/Makefile.inc"
+.include "${.CURDIR}/db/man/Makefile.inc"
+.include "${.CURDIR}/db/mpool/Makefile.inc"
+.include "${.CURDIR}/db/recno/Makefile.inc"
+
+SYM_MAPS+=${.CURDIR}/db/Symbol.map
diff --git a/lib/libc/db/README b/lib/libc/db/README
new file mode 100644
index 0000000..1f9ae72
--- /dev/null
+++ b/lib/libc/db/README
@@ -0,0 +1,34 @@
+# @(#)README 8.27 (Berkeley) 9/1/94
+# $FreeBSD$
+
+This is version 1.85 of the Berkeley DB code.
+
+For information on compiling and installing this software, see the file
+PORT/README.
+
+Newer versions of this software will periodically be made available by
+anonymous ftp from ftp.cs.berkeley.edu. An archive in compressed format
+is in ucb/4bsd/db.tar.Z, or in gzip format in ucb/4bsd/db.tar.gz. If
+you'd like to receive announcements of future releases of this software,
+send email to the contact address below.
+
+Email questions may be addressed to Keith Bostic at bostic@cs.berkeley.edu.
+
+============================================
+Distribution contents:
+
+Makefile.inc Ignore this, it's the 4.4BSD subsystem Makefile.
+PORT The per OS/architecture directories to use to build
+ libdb.a, if you're not running 4.4BSD. See the file
+ PORT/README for more information.
+README This file.
+btree The B+tree routines.
+changelog List of changes, per version.
+db The dbopen(3) interface routine.
+docs Various USENIX papers, and the formatted manual pages.
+hash The extended linear hashing routines.
+man The unformatted manual pages.
+mpool The memory pool routines.
+recno The fixed/variable length record routines.
+test Test package.
+
diff --git a/lib/libc/db/Symbol.map b/lib/libc/db/Symbol.map
new file mode 100644
index 0000000..225fd40
--- /dev/null
+++ b/lib/libc/db/Symbol.map
@@ -0,0 +1,36 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ dbopen;
+ dbm_open;
+ dbm_close;
+ dbm_fetch;
+ dbm_firstkey;
+ dbm_nextkey;
+ dbm_delete;
+ dbm_store;
+ dbm_error;
+ dbm_clearerr;
+ dbm_dirfno;
+ mpool_open;
+ mpool_filter;
+ mpool_get;
+ mpool_put;
+ mpool_close;
+ mpool_sync;
+ mpool_stat;
+};
+
+FBSD_1.1 {
+ mpool_new;
+ mpool_delete;
+};
+
+FBSDprivate_1.0 {
+ __bt_open;
+ __dbpanic;
+ __hash_open;
+ __rec_open;
+};
diff --git a/lib/libc/db/btree/Makefile.inc b/lib/libc/db/btree/Makefile.inc
new file mode 100644
index 0000000..76c2238
--- /dev/null
+++ b/lib/libc/db/btree/Makefile.inc
@@ -0,0 +1,8 @@
+# from @(#)Makefile.inc 8.2 (Berkeley) 7/14/94
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/db/btree
+
+SRCS+= bt_close.c bt_conv.c bt_debug.c bt_delete.c bt_get.c bt_open.c \
+ bt_overflow.c bt_page.c bt_put.c bt_search.c bt_seq.c bt_split.c \
+ bt_utils.c
diff --git a/lib/libc/db/btree/bt_close.c b/lib/libc/db/btree/bt_close.c
new file mode 100644
index 0000000..1f85992
--- /dev/null
+++ b/lib/libc/db/btree/bt_close.c
@@ -0,0 +1,178 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_close.c 8.7 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+#include "btree.h"
+
+static int bt_meta(BTREE *);
+
+/*
+ * BT_CLOSE -- Close a btree.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__bt_close(DB *dbp)
+{
+ BTREE *t;
+ int fd;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* Sync the tree. */
+ if (__bt_sync(dbp, 0) == RET_ERROR)
+ return (RET_ERROR);
+
+ /* Close the memory pool. */
+ if (mpool_close(t->bt_mp) == RET_ERROR)
+ return (RET_ERROR);
+
+ /* Free random memory. */
+ if (t->bt_cursor.key.data != NULL) {
+ free(t->bt_cursor.key.data);
+ t->bt_cursor.key.size = 0;
+ t->bt_cursor.key.data = NULL;
+ }
+ if (t->bt_rkey.data) {
+ free(t->bt_rkey.data);
+ t->bt_rkey.size = 0;
+ t->bt_rkey.data = NULL;
+ }
+ if (t->bt_rdata.data) {
+ free(t->bt_rdata.data);
+ t->bt_rdata.size = 0;
+ t->bt_rdata.data = NULL;
+ }
+
+ fd = t->bt_fd;
+ free(t);
+ free(dbp);
+ return (_close(fd) ? RET_ERROR : RET_SUCCESS);
+}
+
+/*
+ * BT_SYNC -- sync the btree to disk.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_sync(const DB *dbp, u_int flags)
+{
+ BTREE *t;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* Sync doesn't currently take any flags. */
+ if (flags != 0) {
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ if (F_ISSET(t, B_INMEM | B_RDONLY) || !F_ISSET(t, B_MODIFIED))
+ return (RET_SUCCESS);
+
+ if (F_ISSET(t, B_METADIRTY) && bt_meta(t) == RET_ERROR)
+ return (RET_ERROR);
+
+ if ((status = mpool_sync(t->bt_mp)) == RET_SUCCESS)
+ F_CLR(t, B_MODIFIED);
+
+ return (status);
+}
+
+/*
+ * BT_META -- write the tree meta data to disk.
+ *
+ * Parameters:
+ * t: tree
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_meta(BTREE *t)
+{
+ BTMETA m;
+ void *p;
+
+ if ((p = mpool_get(t->bt_mp, P_META, 0)) == NULL)
+ return (RET_ERROR);
+
+ /* Fill in metadata. */
+ m.magic = BTREEMAGIC;
+ m.version = BTREEVERSION;
+ m.psize = t->bt_psize;
+ m.free = t->bt_free;
+ m.nrecs = t->bt_nrecs;
+ m.flags = F_ISSET(t, SAVEMETA);
+
+ memmove(p, &m, sizeof(BTMETA));
+ mpool_put(t->bt_mp, p, MPOOL_DIRTY);
+ return (RET_SUCCESS);
+}
diff --git a/lib/libc/db/btree/bt_conv.c b/lib/libc/db/btree/bt_conv.c
new file mode 100644
index 0000000..ba4a38b
--- /dev/null
+++ b/lib/libc/db/btree/bt_conv.c
@@ -0,0 +1,212 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_conv.c 8.5 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+static void mswap(PAGE *);
+
+/*
+ * __BT_BPGIN, __BT_BPGOUT --
+ * Convert host-specific number layout to/from the host-independent
+ * format stored on disk.
+ *
+ * Parameters:
+ * t: tree
+ * pg: page number
+ * h: page to convert
+ */
+void
+__bt_pgin(void *t, pgno_t pg, void *pp)
+{
+ PAGE *h;
+ indx_t i, top;
+ u_char flags;
+ char *p;
+
+ if (!F_ISSET(((BTREE *)t), B_NEEDSWAP))
+ return;
+ if (pg == P_META) {
+ mswap(pp);
+ return;
+ }
+
+ h = pp;
+ M_32_SWAP(h->pgno);
+ M_32_SWAP(h->prevpg);
+ M_32_SWAP(h->nextpg);
+ M_32_SWAP(h->flags);
+ M_16_SWAP(h->lower);
+ M_16_SWAP(h->upper);
+
+ top = NEXTINDEX(h);
+ if ((h->flags & P_TYPE) == P_BINTERNAL)
+ for (i = 0; i < top; i++) {
+ M_16_SWAP(h->linp[i]);
+ p = (char *)GETBINTERNAL(h, i);
+ P_32_SWAP(p);
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ if (*(u_char *)p & P_BIGKEY) {
+ p += sizeof(u_char);
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ P_32_SWAP(p);
+ }
+ }
+ else if ((h->flags & P_TYPE) == P_BLEAF)
+ for (i = 0; i < top; i++) {
+ M_16_SWAP(h->linp[i]);
+ p = (char *)GETBLEAF(h, i);
+ P_32_SWAP(p);
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p);
+ p += sizeof(u_int32_t);
+ flags = *(u_char *)p;
+ if (flags & (P_BIGKEY | P_BIGDATA)) {
+ p += sizeof(u_char);
+ if (flags & P_BIGKEY) {
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ P_32_SWAP(p);
+ }
+ if (flags & P_BIGDATA) {
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ P_32_SWAP(p);
+ }
+ }
+ }
+}
+
+void
+__bt_pgout(void *t, pgno_t pg, void *pp)
+{
+ PAGE *h;
+ indx_t i, top;
+ u_char flags;
+ char *p;
+
+ if (!F_ISSET(((BTREE *)t), B_NEEDSWAP))
+ return;
+ if (pg == P_META) {
+ mswap(pp);
+ return;
+ }
+
+ h = pp;
+ top = NEXTINDEX(h);
+ if ((h->flags & P_TYPE) == P_BINTERNAL)
+ for (i = 0; i < top; i++) {
+ p = (char *)GETBINTERNAL(h, i);
+ P_32_SWAP(p);
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ if (*(u_char *)p & P_BIGKEY) {
+ p += sizeof(u_char);
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ P_32_SWAP(p);
+ }
+ M_16_SWAP(h->linp[i]);
+ }
+ else if ((h->flags & P_TYPE) == P_BLEAF)
+ for (i = 0; i < top; i++) {
+ p = (char *)GETBLEAF(h, i);
+ P_32_SWAP(p);
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p);
+ p += sizeof(u_int32_t);
+ flags = *(u_char *)p;
+ if (flags & (P_BIGKEY | P_BIGDATA)) {
+ p += sizeof(u_char);
+ if (flags & P_BIGKEY) {
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ P_32_SWAP(p);
+ }
+ if (flags & P_BIGDATA) {
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p);
+ p += sizeof(pgno_t);
+ P_32_SWAP(p);
+ }
+ }
+ M_16_SWAP(h->linp[i]);
+ }
+
+ M_32_SWAP(h->pgno);
+ M_32_SWAP(h->prevpg);
+ M_32_SWAP(h->nextpg);
+ M_32_SWAP(h->flags);
+ M_16_SWAP(h->lower);
+ M_16_SWAP(h->upper);
+}
+
+/*
+ * MSWAP -- Actually swap the bytes on the meta page.
+ *
+ * Parameters:
+ * p: page to convert
+ */
+static void
+mswap(PAGE *pg)
+{
+ char *p;
+
+ p = (char *)pg;
+ P_32_SWAP(p); /* magic */
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p); /* version */
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p); /* psize */
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p); /* free */
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p); /* nrecs */
+ p += sizeof(u_int32_t);
+ P_32_SWAP(p); /* flags */
+ p += sizeof(u_int32_t);
+}
diff --git a/lib/libc/db/btree/bt_debug.c b/lib/libc/db/btree/bt_debug.c
new file mode 100644
index 0000000..dc8b83d
--- /dev/null
+++ b/lib/libc/db/btree/bt_debug.c
@@ -0,0 +1,316 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_debug.c 8.5 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+#ifdef DEBUG
+/*
+ * BT_DUMP -- Dump the tree
+ *
+ * Parameters:
+ * dbp: pointer to the DB
+ */
+void
+__bt_dump(DB *dbp)
+{
+ BTREE *t;
+ PAGE *h;
+ pgno_t i;
+ char *sep;
+
+ t = dbp->internal;
+ (void)fprintf(stderr, "%s: pgsz %u",
+ F_ISSET(t, B_INMEM) ? "memory" : "disk", t->bt_psize);
+ if (F_ISSET(t, R_RECNO))
+ (void)fprintf(stderr, " keys %u", t->bt_nrecs);
+#undef X
+#define X(flag, name) \
+ if (F_ISSET(t, flag)) { \
+ (void)fprintf(stderr, "%s%s", sep, name); \
+ sep = ", "; \
+ }
+ if (t->flags != 0) {
+ sep = " flags (";
+ X(R_FIXLEN, "FIXLEN");
+ X(B_INMEM, "INMEM");
+ X(B_NODUPS, "NODUPS");
+ X(B_RDONLY, "RDONLY");
+ X(R_RECNO, "RECNO");
+ X(B_METADIRTY,"METADIRTY");
+ (void)fprintf(stderr, ")\n");
+ }
+#undef X
+
+ for (i = P_ROOT;
+ (h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i)
+ __bt_dpage(h);
+}
+
+/*
+ * BT_DMPAGE -- Dump the meta page
+ *
+ * Parameters:
+ * h: pointer to the PAGE
+ */
+void
+__bt_dmpage(PAGE *h)
+{
+ BTMETA *m;
+ char *sep;
+
+ m = (BTMETA *)h;
+ (void)fprintf(stderr, "magic %x\n", m->magic);
+ (void)fprintf(stderr, "version %u\n", m->version);
+ (void)fprintf(stderr, "psize %u\n", m->psize);
+ (void)fprintf(stderr, "free %u\n", m->free);
+ (void)fprintf(stderr, "nrecs %u\n", m->nrecs);
+ (void)fprintf(stderr, "flags %u", m->flags);
+#undef X
+#define X(flag, name) \
+ if (m->flags & flag) { \
+ (void)fprintf(stderr, "%s%s", sep, name); \
+ sep = ", "; \
+ }
+ if (m->flags) {
+ sep = " (";
+ X(B_NODUPS, "NODUPS");
+ X(R_RECNO, "RECNO");
+ (void)fprintf(stderr, ")");
+ }
+}
+
+/*
+ * BT_DNPAGE -- Dump the page
+ *
+ * Parameters:
+ * n: page number to dump.
+ */
+void
+__bt_dnpage(DB *dbp, pgno_t pgno)
+{
+ BTREE *t;
+ PAGE *h;
+
+ t = dbp->internal;
+ if ((h = mpool_get(t->bt_mp, pgno, MPOOL_IGNOREPIN)) != NULL)
+ __bt_dpage(h);
+}
+
+/*
+ * BT_DPAGE -- Dump the page
+ *
+ * Parameters:
+ * h: pointer to the PAGE
+ */
+void
+__bt_dpage(PAGE *h)
+{
+ BINTERNAL *bi;
+ BLEAF *bl;
+ RINTERNAL *ri;
+ RLEAF *rl;
+ indx_t cur, top;
+ char *sep;
+
+ (void)fprintf(stderr, " page %u: (", h->pgno);
+#undef X
+#define X(flag, name) \
+ if (h->flags & flag) { \
+ (void)fprintf(stderr, "%s%s", sep, name); \
+ sep = ", "; \
+ }
+ sep = "";
+ X(P_BINTERNAL, "BINTERNAL") /* types */
+ X(P_BLEAF, "BLEAF")
+ X(P_RINTERNAL, "RINTERNAL") /* types */
+ X(P_RLEAF, "RLEAF")
+ X(P_OVERFLOW, "OVERFLOW")
+ X(P_PRESERVE, "PRESERVE");
+ (void)fprintf(stderr, ")\n");
+#undef X
+
+ (void)fprintf(stderr, "\tprev %2u next %2u", h->prevpg, h->nextpg);
+ if (h->flags & P_OVERFLOW)
+ return;
+
+ top = NEXTINDEX(h);
+ (void)fprintf(stderr, " lower %3d upper %3d nextind %d\n",
+ h->lower, h->upper, top);
+ for (cur = 0; cur < top; cur++) {
+ (void)fprintf(stderr, "\t[%03d] %4d ", cur, h->linp[cur]);
+ switch (h->flags & P_TYPE) {
+ case P_BINTERNAL:
+ bi = GETBINTERNAL(h, cur);
+ (void)fprintf(stderr,
+ "size %03d pgno %03d", bi->ksize, bi->pgno);
+ if (bi->flags & P_BIGKEY)
+ (void)fprintf(stderr, " (indirect)");
+ else if (bi->ksize)
+ (void)fprintf(stderr,
+ " {%.*s}", (int)bi->ksize, bi->bytes);
+ break;
+ case P_RINTERNAL:
+ ri = GETRINTERNAL(h, cur);
+ (void)fprintf(stderr, "entries %03d pgno %03d",
+ ri->nrecs, ri->pgno);
+ break;
+ case P_BLEAF:
+ bl = GETBLEAF(h, cur);
+ if (bl->flags & P_BIGKEY)
+ (void)fprintf(stderr,
+ "big key page %u size %u/",
+ *(pgno_t *)bl->bytes,
+ *(u_int32_t *)(bl->bytes + sizeof(pgno_t)));
+ else if (bl->ksize)
+ (void)fprintf(stderr, "%.*s/",
+ bl->ksize, bl->bytes);
+ if (bl->flags & P_BIGDATA)
+ (void)fprintf(stderr,
+ "big data page %u size %u",
+ *(pgno_t *)(bl->bytes + bl->ksize),
+ *(u_int32_t *)(bl->bytes + bl->ksize +
+ sizeof(pgno_t)));
+ else if (bl->dsize)
+ (void)fprintf(stderr, "%.*s",
+ (int)bl->dsize, bl->bytes + bl->ksize);
+ break;
+ case P_RLEAF:
+ rl = GETRLEAF(h, cur);
+ if (rl->flags & P_BIGDATA)
+ (void)fprintf(stderr,
+ "big data page %u size %u",
+ *(pgno_t *)rl->bytes,
+ *(u_int32_t *)(rl->bytes + sizeof(pgno_t)));
+ else if (rl->dsize)
+ (void)fprintf(stderr,
+ "%.*s", (int)rl->dsize, rl->bytes);
+ break;
+ }
+ (void)fprintf(stderr, "\n");
+ }
+}
+#endif
+
+#ifdef STATISTICS
+/*
+ * BT_STAT -- Gather/print the tree statistics
+ *
+ * Parameters:
+ * dbp: pointer to the DB
+ */
+void
+__bt_stat(DB *dbp)
+{
+ extern u_long bt_cache_hit, bt_cache_miss, bt_pfxsaved, bt_rootsplit;
+ extern u_long bt_sortsplit, bt_split;
+ BTREE *t;
+ PAGE *h;
+ pgno_t i, pcont, pinternal, pleaf;
+ u_long ifree, lfree, nkeys;
+ int levels;
+
+ t = dbp->internal;
+ pcont = pinternal = pleaf = 0;
+ nkeys = ifree = lfree = 0;
+ for (i = P_ROOT;
+ (h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN)) != NULL; ++i)
+ switch (h->flags & P_TYPE) {
+ case P_BINTERNAL:
+ case P_RINTERNAL:
+ ++pinternal;
+ ifree += h->upper - h->lower;
+ break;
+ case P_BLEAF:
+ case P_RLEAF:
+ ++pleaf;
+ lfree += h->upper - h->lower;
+ nkeys += NEXTINDEX(h);
+ break;
+ case P_OVERFLOW:
+ ++pcont;
+ break;
+ }
+
+ /* Count the levels of the tree. */
+ for (i = P_ROOT, levels = 0 ;; ++levels) {
+ h = mpool_get(t->bt_mp, i, MPOOL_IGNOREPIN);
+ if (h->flags & (P_BLEAF|P_RLEAF)) {
+ if (levels == 0)
+ levels = 1;
+ break;
+ }
+ i = F_ISSET(t, R_RECNO) ?
+ GETRINTERNAL(h, 0)->pgno :
+ GETBINTERNAL(h, 0)->pgno;
+ }
+
+ (void)fprintf(stderr, "%d level%s with %lu keys",
+ levels, levels == 1 ? "" : "s", nkeys);
+ if (F_ISSET(t, R_RECNO))
+ (void)fprintf(stderr, " (%u header count)", t->bt_nrecs);
+ (void)fprintf(stderr,
+ "\n%u pages (leaf %u, internal %u, overflow %u)\n",
+ pinternal + pleaf + pcont, pleaf, pinternal, pcont);
+ (void)fprintf(stderr, "%lu cache hits, %lu cache misses\n",
+ bt_cache_hit, bt_cache_miss);
+ (void)fprintf(stderr, "%lu splits (%lu root splits, %lu sort splits)\n",
+ bt_split, bt_rootsplit, bt_sortsplit);
+ pleaf *= t->bt_psize - BTDATAOFF;
+ if (pleaf)
+ (void)fprintf(stderr,
+ "%.0f%% leaf fill (%lu bytes used, %lu bytes free)\n",
+ ((double)(pleaf - lfree) / pleaf) * 100,
+ pleaf - lfree, lfree);
+ pinternal *= t->bt_psize - BTDATAOFF;
+ if (pinternal)
+ (void)fprintf(stderr,
+ "%.0f%% internal fill (%lu bytes used, %lu bytes free\n",
+ ((double)(pinternal - ifree) / pinternal) * 100,
+ pinternal - ifree, ifree);
+ if (bt_pfxsaved)
+ (void)fprintf(stderr, "prefix checking removed %lu bytes.\n",
+ bt_pfxsaved);
+}
+#endif
diff --git a/lib/libc/db/btree/bt_delete.c b/lib/libc/db/btree/bt_delete.c
new file mode 100644
index 0000000..aa191b6
--- /dev/null
+++ b/lib/libc/db/btree/bt_delete.c
@@ -0,0 +1,635 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_delete.c 8.13 (Berkeley) 7/28/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int __bt_bdelete(BTREE *, const DBT *);
+static int __bt_curdel(BTREE *, const DBT *, PAGE *, u_int);
+static int __bt_pdelete(BTREE *, PAGE *);
+static int __bt_relink(BTREE *, PAGE *);
+static int __bt_stkacq(BTREE *, PAGE **, CURSOR *);
+
+/*
+ * __bt_delete
+ * Delete the item(s) referenced by a key.
+ *
+ * Return RET_SPECIAL if the key is not found.
+ */
+int
+__bt_delete(const DB *dbp, const DBT *key, u_int flags)
+{
+ BTREE *t;
+ CURSOR *c;
+ PAGE *h;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* Check for change to a read-only tree. */
+ if (F_ISSET(t, B_RDONLY)) {
+ errno = EPERM;
+ return (RET_ERROR);
+ }
+
+ switch (flags) {
+ case 0:
+ status = __bt_bdelete(t, key);
+ break;
+ case R_CURSOR:
+ /*
+ * If flags is R_CURSOR, delete the cursor. Must already
+ * have started a scan and not have already deleted it.
+ */
+ c = &t->bt_cursor;
+ if (F_ISSET(c, CURS_INIT)) {
+ if (F_ISSET(c, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
+ return (RET_SPECIAL);
+ if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
+ return (RET_ERROR);
+
+ /*
+ * If the page is about to be emptied, we'll need to
+ * delete it, which means we have to acquire a stack.
+ */
+ if (NEXTINDEX(h) == 1)
+ if (__bt_stkacq(t, &h, &t->bt_cursor))
+ return (RET_ERROR);
+
+ status = __bt_dleaf(t, NULL, h, c->pg.index);
+
+ if (NEXTINDEX(h) == 0 && status == RET_SUCCESS) {
+ if (__bt_pdelete(t, h))
+ return (RET_ERROR);
+ } else
+ mpool_put(t->bt_mp,
+ h, status == RET_SUCCESS ? MPOOL_DIRTY : 0);
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+ if (status == RET_SUCCESS)
+ F_SET(t, B_MODIFIED);
+ return (status);
+}
+
+/*
+ * __bt_stkacq --
+ * Acquire a stack so we can delete a cursor entry.
+ *
+ * Parameters:
+ * t: tree
+ * hp: pointer to current, pinned PAGE pointer
+ * c: pointer to the cursor
+ *
+ * Returns:
+ * 0 on success, 1 on failure
+ */
+static int
+__bt_stkacq(BTREE *t, PAGE **hp, CURSOR *c)
+{
+ BINTERNAL *bi;
+ EPG *e;
+ EPGNO *parent;
+ PAGE *h;
+ indx_t idx;
+ pgno_t pgno;
+ recno_t nextpg, prevpg;
+ int exact, level;
+
+ /*
+ * Find the first occurrence of the key in the tree. Toss the
+ * currently locked page so we don't hit an already-locked page.
+ */
+ h = *hp;
+ mpool_put(t->bt_mp, h, 0);
+ if ((e = __bt_search(t, &c->key, &exact)) == NULL)
+ return (1);
+ h = e->page;
+
+ /* See if we got it in one shot. */
+ if (h->pgno == c->pg.pgno)
+ goto ret;
+
+ /*
+ * Move right, looking for the page. At each move we have to move
+ * up the stack until we don't have to move to the next page. If
+ * we have to change pages at an internal level, we have to fix the
+ * stack back up.
+ */
+ while (h->pgno != c->pg.pgno) {
+ if ((nextpg = h->nextpg) == P_INVALID)
+ break;
+ mpool_put(t->bt_mp, h, 0);
+
+ /* Move up the stack. */
+ for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
+ /* Get the parent page. */
+ if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+ return (1);
+
+ /* Move to the next index. */
+ if (parent->index != NEXTINDEX(h) - 1) {
+ idx = parent->index + 1;
+ BT_PUSH(t, h->pgno, idx);
+ break;
+ }
+ mpool_put(t->bt_mp, h, 0);
+ }
+
+ /* Restore the stack. */
+ while (level--) {
+ /* Push the next level down onto the stack. */
+ bi = GETBINTERNAL(h, idx);
+ pgno = bi->pgno;
+ BT_PUSH(t, pgno, 0);
+
+ /* Lose the currently pinned page. */
+ mpool_put(t->bt_mp, h, 0);
+
+ /* Get the next level down. */
+ if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
+ return (1);
+ idx = 0;
+ }
+ mpool_put(t->bt_mp, h, 0);
+ if ((h = mpool_get(t->bt_mp, nextpg, 0)) == NULL)
+ return (1);
+ }
+
+ if (h->pgno == c->pg.pgno)
+ goto ret;
+
+ /* Reacquire the original stack. */
+ mpool_put(t->bt_mp, h, 0);
+ if ((e = __bt_search(t, &c->key, &exact)) == NULL)
+ return (1);
+ h = e->page;
+
+ /*
+ * Move left, looking for the page. At each move we have to move
+ * up the stack until we don't have to change pages to move to the
+ * next page. If we have to change pages at an internal level, we
+ * have to fix the stack back up.
+ */
+ while (h->pgno != c->pg.pgno) {
+ if ((prevpg = h->prevpg) == P_INVALID)
+ break;
+ mpool_put(t->bt_mp, h, 0);
+
+ /* Move up the stack. */
+ for (level = 0; (parent = BT_POP(t)) != NULL; ++level) {
+ /* Get the parent page. */
+ if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+ return (1);
+
+ /* Move to the next index. */
+ if (parent->index != 0) {
+ idx = parent->index - 1;
+ BT_PUSH(t, h->pgno, idx);
+ break;
+ }
+ mpool_put(t->bt_mp, h, 0);
+ }
+
+ /* Restore the stack. */
+ while (level--) {
+ /* Push the next level down onto the stack. */
+ bi = GETBINTERNAL(h, idx);
+ pgno = bi->pgno;
+
+ /* Lose the currently pinned page. */
+ mpool_put(t->bt_mp, h, 0);
+
+ /* Get the next level down. */
+ if ((h = mpool_get(t->bt_mp, pgno, 0)) == NULL)
+ return (1);
+
+ idx = NEXTINDEX(h) - 1;
+ BT_PUSH(t, pgno, idx);
+ }
+ mpool_put(t->bt_mp, h, 0);
+ if ((h = mpool_get(t->bt_mp, prevpg, 0)) == NULL)
+ return (1);
+ }
+
+
+ret: mpool_put(t->bt_mp, h, 0);
+ return ((*hp = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL);
+}
+
+/*
+ * __bt_bdelete --
+ * Delete all key/data pairs matching the specified key.
+ *
+ * Parameters:
+ * t: tree
+ * key: key to delete
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+static int
+__bt_bdelete(BTREE *t, const DBT *key)
+{
+ EPG *e;
+ PAGE *h;
+ int deleted, exact, redo;
+
+ deleted = 0;
+
+ /* Find any matching record; __bt_search pins the page. */
+loop: if ((e = __bt_search(t, key, &exact)) == NULL)
+ return (deleted ? RET_SUCCESS : RET_ERROR);
+ if (!exact) {
+ mpool_put(t->bt_mp, e->page, 0);
+ return (deleted ? RET_SUCCESS : RET_SPECIAL);
+ }
+
+ /*
+ * Delete forward, then delete backward, from the found key. If
+ * there are duplicates and we reach either side of the page, do
+ * the key search again, so that we get them all.
+ */
+ redo = 0;
+ h = e->page;
+ do {
+ if (__bt_dleaf(t, key, h, e->index)) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_ERROR);
+ }
+ if (F_ISSET(t, B_NODUPS)) {
+ if (NEXTINDEX(h) == 0) {
+ if (__bt_pdelete(t, h))
+ return (RET_ERROR);
+ } else
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ return (RET_SUCCESS);
+ }
+ deleted = 1;
+ } while (e->index < NEXTINDEX(h) && __bt_cmp(t, key, e) == 0);
+
+ /* Check for right-hand edge of the page. */
+ if (e->index == NEXTINDEX(h))
+ redo = 1;
+
+ /* Delete from the key to the beginning of the page. */
+ while (e->index-- > 0) {
+ if (__bt_cmp(t, key, e) != 0)
+ break;
+ if (__bt_dleaf(t, key, h, e->index) == RET_ERROR) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_ERROR);
+ }
+ if (e->index == 0)
+ redo = 1;
+ }
+
+ /* Check for an empty page. */
+ if (NEXTINDEX(h) == 0) {
+ if (__bt_pdelete(t, h))
+ return (RET_ERROR);
+ goto loop;
+ }
+
+ /* Put the page. */
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+ if (redo)
+ goto loop;
+ return (RET_SUCCESS);
+}
+
+/*
+ * __bt_pdelete --
+ * Delete a single page from the tree.
+ *
+ * Parameters:
+ * t: tree
+ * h: leaf page
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ *
+ * Side-effects:
+ * mpool_put's the page
+ */
+static int
+__bt_pdelete(BTREE *t, PAGE *h)
+{
+ BINTERNAL *bi;
+ PAGE *pg;
+ EPGNO *parent;
+ indx_t cnt, idx, *ip, offset;
+ u_int32_t nksize;
+ char *from;
+
+ /*
+ * Walk the parent page stack -- a LIFO stack of the pages that were
+ * traversed when we searched for the page where the delete occurred.
+ * Each stack entry is a page number and a page index offset. The
+ * offset is for the page traversed on the search. We've just deleted
+ * a page, so we have to delete the key from the parent page.
+ *
+ * If the delete from the parent page makes it empty, this process may
+ * continue all the way up the tree. We stop if we reach the root page
+ * (which is never deleted, it's just not worth the effort) or if the
+ * delete does not empty the page.
+ */
+ while ((parent = BT_POP(t)) != NULL) {
+ /* Get the parent page. */
+ if ((pg = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+ return (RET_ERROR);
+
+ idx = parent->index;
+ bi = GETBINTERNAL(pg, idx);
+
+ /* Free any overflow pages. */
+ if (bi->flags & P_BIGKEY &&
+ __ovfl_delete(t, bi->bytes) == RET_ERROR) {
+ mpool_put(t->bt_mp, pg, 0);
+ return (RET_ERROR);
+ }
+
+ /*
+ * Free the parent if it has only the one key and it's not the
+ * root page. If it's the rootpage, turn it back into an empty
+ * leaf page.
+ */
+ if (NEXTINDEX(pg) == 1) {
+ if (pg->pgno == P_ROOT) {
+ pg->lower = BTDATAOFF;
+ pg->upper = t->bt_psize;
+ pg->flags = P_BLEAF;
+ } else {
+ if (__bt_relink(t, pg) || __bt_free(t, pg))
+ return (RET_ERROR);
+ continue;
+ }
+ } else {
+ /* Pack remaining key items at the end of the page. */
+ nksize = NBINTERNAL(bi->ksize);
+ from = (char *)pg + pg->upper;
+ memmove(from + nksize, from, (char *)bi - from);
+ pg->upper += nksize;
+
+ /* Adjust indices' offsets, shift the indices down. */
+ offset = pg->linp[idx];
+ for (cnt = idx, ip = &pg->linp[0]; cnt--; ++ip)
+ if (ip[0] < offset)
+ ip[0] += nksize;
+ for (cnt = NEXTINDEX(pg) - idx; --cnt; ++ip)
+ ip[0] = ip[1] < offset ? ip[1] + nksize : ip[1];
+ pg->lower -= sizeof(indx_t);
+ }
+
+ mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+ break;
+ }
+
+ /* Free the leaf page, as long as it wasn't the root. */
+ if (h->pgno == P_ROOT) {
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ return (RET_SUCCESS);
+ }
+ return (__bt_relink(t, h) || __bt_free(t, h));
+}
+
+/*
+ * __bt_dleaf --
+ * Delete a single record from a leaf page.
+ *
+ * Parameters:
+ * t: tree
+ * key: referenced key
+ * h: page
+ * idx: index on page to delete
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_dleaf(BTREE *t, const DBT *key, PAGE *h, u_int idx)
+{
+ BLEAF *bl;
+ indx_t cnt, *ip, offset;
+ u_int32_t nbytes;
+ void *to;
+ char *from;
+
+ /* If this record is referenced by the cursor, delete the cursor. */
+ if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+ !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+ t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index == idx &&
+ __bt_curdel(t, key, h, idx))
+ return (RET_ERROR);
+
+ /* If the entry uses overflow pages, make them available for reuse. */
+ to = bl = GETBLEAF(h, idx);
+ if (bl->flags & P_BIGKEY && __ovfl_delete(t, bl->bytes) == RET_ERROR)
+ return (RET_ERROR);
+ if (bl->flags & P_BIGDATA &&
+ __ovfl_delete(t, bl->bytes + bl->ksize) == RET_ERROR)
+ return (RET_ERROR);
+
+ /* Pack the remaining key/data items at the end of the page. */
+ nbytes = NBLEAF(bl);
+ from = (char *)h + h->upper;
+ memmove(from + nbytes, from, (char *)to - from);
+ h->upper += nbytes;
+
+ /* Adjust the indices' offsets, shift the indices down. */
+ offset = h->linp[idx];
+ for (cnt = idx, ip = &h->linp[0]; cnt--; ++ip)
+ if (ip[0] < offset)
+ ip[0] += nbytes;
+ for (cnt = NEXTINDEX(h) - idx; --cnt; ++ip)
+ ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
+ h->lower -= sizeof(indx_t);
+
+ /* If the cursor is on this page, adjust it as necessary. */
+ if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+ !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+ t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index > idx)
+ --t->bt_cursor.pg.index;
+
+ return (RET_SUCCESS);
+}
+
+/*
+ * __bt_curdel --
+ * Delete the cursor.
+ *
+ * Parameters:
+ * t: tree
+ * key: referenced key (or NULL)
+ * h: page
+ * idx: index on page to delete
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+static int
+__bt_curdel(BTREE *t, const DBT *key, PAGE *h, u_int idx)
+{
+ CURSOR *c;
+ EPG e;
+ PAGE *pg;
+ int curcopy, status;
+
+ /*
+ * If there are duplicates, move forward or backward to one.
+ * Otherwise, copy the key into the cursor area.
+ */
+ c = &t->bt_cursor;
+ F_CLR(c, CURS_AFTER | CURS_BEFORE | CURS_ACQUIRE);
+
+ curcopy = 0;
+ if (!F_ISSET(t, B_NODUPS)) {
+ /*
+ * We're going to have to do comparisons. If we weren't
+ * provided a copy of the key, i.e. the user is deleting
+ * the current cursor position, get one.
+ */
+ if (key == NULL) {
+ e.page = h;
+ e.index = idx;
+ if ((status = __bt_ret(t, &e,
+ &c->key, &c->key, NULL, NULL, 1)) != RET_SUCCESS)
+ return (status);
+ curcopy = 1;
+ key = &c->key;
+ }
+ /* Check previous key, if not at the beginning of the page. */
+ if (idx > 0) {
+ e.page = h;
+ e.index = idx - 1;
+ if (__bt_cmp(t, key, &e) == 0) {
+ F_SET(c, CURS_BEFORE);
+ goto dup2;
+ }
+ }
+ /* Check next key, if not at the end of the page. */
+ if (idx < NEXTINDEX(h) - 1) {
+ e.page = h;
+ e.index = idx + 1;
+ if (__bt_cmp(t, key, &e) == 0) {
+ F_SET(c, CURS_AFTER);
+ goto dup2;
+ }
+ }
+ /* Check previous key if at the beginning of the page. */
+ if (idx == 0 && h->prevpg != P_INVALID) {
+ if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+ return (RET_ERROR);
+ e.page = pg;
+ e.index = NEXTINDEX(pg) - 1;
+ if (__bt_cmp(t, key, &e) == 0) {
+ F_SET(c, CURS_BEFORE);
+ goto dup1;
+ }
+ mpool_put(t->bt_mp, pg, 0);
+ }
+ /* Check next key if at the end of the page. */
+ if (idx == NEXTINDEX(h) - 1 && h->nextpg != P_INVALID) {
+ if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+ return (RET_ERROR);
+ e.page = pg;
+ e.index = 0;
+ if (__bt_cmp(t, key, &e) == 0) {
+ F_SET(c, CURS_AFTER);
+dup1: mpool_put(t->bt_mp, pg, 0);
+dup2: c->pg.pgno = e.page->pgno;
+ c->pg.index = e.index;
+ return (RET_SUCCESS);
+ }
+ mpool_put(t->bt_mp, pg, 0);
+ }
+ }
+ e.page = h;
+ e.index = idx;
+ if (curcopy || (status =
+ __bt_ret(t, &e, &c->key, &c->key, NULL, NULL, 1)) == RET_SUCCESS) {
+ F_SET(c, CURS_ACQUIRE);
+ return (RET_SUCCESS);
+ }
+ return (status);
+}
+
+/*
+ * __bt_relink --
+ * Link around a deleted page.
+ *
+ * Parameters:
+ * t: tree
+ * h: page to be deleted
+ */
+static int
+__bt_relink(BTREE *t, PAGE *h)
+{
+ PAGE *pg;
+
+ if (h->nextpg != P_INVALID) {
+ if ((pg = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+ return (RET_ERROR);
+ pg->prevpg = h->prevpg;
+ mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+ }
+ if (h->prevpg != P_INVALID) {
+ if ((pg = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+ return (RET_ERROR);
+ pg->nextpg = h->nextpg;
+ mpool_put(t->bt_mp, pg, MPOOL_DIRTY);
+ }
+ return (0);
+}
diff --git a/lib/libc/db/btree/bt_get.c b/lib/libc/db/btree/bt_get.c
new file mode 100644
index 0000000..77fae30
--- /dev/null
+++ b/lib/libc/db/btree/bt_get.c
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_get.c 8.6 (Berkeley) 7/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * __BT_GET -- Get a record from the btree.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ * key: key to find
+ * data: data to return
+ * flag: currently unused
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__bt_get(const DB *dbp, const DBT *key, DBT *data, u_int flags)
+{
+ BTREE *t;
+ EPG *e;
+ int exact, status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* Get currently doesn't take any flags. */
+ if (flags) {
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ if ((e = __bt_search(t, key, &exact)) == NULL)
+ return (RET_ERROR);
+ if (!exact) {
+ mpool_put(t->bt_mp, e->page, 0);
+ return (RET_SPECIAL);
+ }
+
+ status = __bt_ret(t, e, NULL, NULL, data, &t->bt_rdata, 0);
+
+ /*
+ * If the user is doing concurrent access, we copied the
+ * key/data, toss the page.
+ */
+ if (F_ISSET(t, B_DB_LOCK))
+ mpool_put(t->bt_mp, e->page, 0);
+ else
+ t->bt_pinned = e->page;
+ return (status);
+}
diff --git a/lib/libc/db/btree/bt_open.c b/lib/libc/db/btree/bt_open.c
new file mode 100644
index 0000000..47f3646
--- /dev/null
+++ b/lib/libc/db/btree/bt_open.c
@@ -0,0 +1,451 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_open.c 8.10 (Berkeley) 8/17/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Implementation of btree access method for 4.4BSD.
+ *
+ * The design here was originally based on that of the btree access method
+ * used in the Postgres database system at UC Berkeley. This implementation
+ * is wholly independent of the Postgres code.
+ */
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+#include "btree.h"
+
+#ifdef DEBUG
+#undef MINPSIZE
+#define MINPSIZE 128
+#endif
+
+static int byteorder(void);
+static int nroot(BTREE *);
+static int tmp(void);
+
+/*
+ * __BT_OPEN -- Open a btree.
+ *
+ * Creates and fills a DB struct, and calls the routine that actually
+ * opens the btree.
+ *
+ * Parameters:
+ * fname: filename (NULL for in-memory trees)
+ * flags: open flag bits
+ * mode: open permission bits
+ * b: BTREEINFO pointer
+ *
+ * Returns:
+ * NULL on failure, pointer to DB on success.
+ *
+ */
+DB *
+__bt_open(const char *fname, int flags, int mode, const BTREEINFO *openinfo, int dflags)
+{
+ struct stat sb;
+ BTMETA m;
+ BTREE *t;
+ BTREEINFO b;
+ DB *dbp;
+ pgno_t ncache;
+ ssize_t nr;
+ int machine_lorder, saved_errno;
+
+ t = NULL;
+
+ /*
+ * Intention is to make sure all of the user's selections are okay
+ * here and then use them without checking. Can't be complete, since
+ * we don't know the right page size, lorder or flags until the backing
+ * file is opened. Also, the file's page size can cause the cachesize
+ * to change.
+ */
+ machine_lorder = byteorder();
+ if (openinfo) {
+ b = *openinfo;
+
+ /* Flags: R_DUP. */
+ if (b.flags & ~(R_DUP))
+ goto einval;
+
+ /*
+ * Page size must be indx_t aligned and >= MINPSIZE. Default
+ * page size is set farther on, based on the underlying file
+ * transfer size.
+ */
+ if (b.psize &&
+ (b.psize < MINPSIZE || b.psize > MAX_PAGE_OFFSET + 1 ||
+ b.psize & (sizeof(indx_t) - 1) ))
+ goto einval;
+
+ /* Minimum number of keys per page; absolute minimum is 2. */
+ if (b.minkeypage) {
+ if (b.minkeypage < 2)
+ goto einval;
+ } else
+ b.minkeypage = DEFMINKEYPAGE;
+
+ /* If no comparison, use default comparison and prefix. */
+ if (b.compare == NULL) {
+ b.compare = __bt_defcmp;
+ if (b.prefix == NULL)
+ b.prefix = __bt_defpfx;
+ }
+
+ if (b.lorder == 0)
+ b.lorder = machine_lorder;
+ } else {
+ b.compare = __bt_defcmp;
+ b.cachesize = 0;
+ b.flags = 0;
+ b.lorder = machine_lorder;
+ b.minkeypage = DEFMINKEYPAGE;
+ b.prefix = __bt_defpfx;
+ b.psize = 0;
+ }
+
+ /* Check for the ubiquitous PDP-11. */
+ if (b.lorder != BIG_ENDIAN && b.lorder != LITTLE_ENDIAN)
+ goto einval;
+
+ /* Allocate and initialize DB and BTREE structures. */
+ if ((t = (BTREE *)calloc(1, sizeof(BTREE))) == NULL)
+ goto err;
+ t->bt_fd = -1; /* Don't close unopened fd on error. */
+ t->bt_lorder = b.lorder;
+ t->bt_order = NOT;
+ t->bt_cmp = b.compare;
+ t->bt_pfx = b.prefix;
+ t->bt_rfd = -1;
+
+ if ((t->bt_dbp = dbp = (DB *)calloc(1, sizeof(DB))) == NULL)
+ goto err;
+ if (t->bt_lorder != machine_lorder)
+ F_SET(t, B_NEEDSWAP);
+
+ dbp->type = DB_BTREE;
+ dbp->internal = t;
+ dbp->close = __bt_close;
+ dbp->del = __bt_delete;
+ dbp->fd = __bt_fd;
+ dbp->get = __bt_get;
+ dbp->put = __bt_put;
+ dbp->seq = __bt_seq;
+ dbp->sync = __bt_sync;
+
+ /*
+ * If no file name was supplied, this is an in-memory btree and we
+ * open a backing temporary file. Otherwise, it's a disk-based tree.
+ */
+ if (fname) {
+ switch (flags & O_ACCMODE) {
+ case O_RDONLY:
+ F_SET(t, B_RDONLY);
+ break;
+ case O_RDWR:
+ break;
+ case O_WRONLY:
+ default:
+ goto einval;
+ }
+
+ if ((t->bt_fd = _open(fname, flags, mode)) < 0)
+ goto err;
+
+ } else {
+ if ((flags & O_ACCMODE) != O_RDWR)
+ goto einval;
+ if ((t->bt_fd = tmp()) == -1)
+ goto err;
+ F_SET(t, B_INMEM);
+ }
+
+ if (_fcntl(t->bt_fd, F_SETFD, 1) == -1)
+ goto err;
+
+ if (_fstat(t->bt_fd, &sb))
+ goto err;
+ if (sb.st_size) {
+ if ((nr = _read(t->bt_fd, &m, sizeof(BTMETA))) < 0)
+ goto err;
+ if (nr != sizeof(BTMETA))
+ goto eftype;
+
+ /*
+ * Read in the meta-data. This can change the notion of what
+ * the lorder, page size and flags are, and, when the page size
+ * changes, the cachesize value can change too. If the user
+ * specified the wrong byte order for an existing database, we
+ * don't bother to return an error, we just clear the NEEDSWAP
+ * bit.
+ */
+ if (m.magic == BTREEMAGIC)
+ F_CLR(t, B_NEEDSWAP);
+ else {
+ F_SET(t, B_NEEDSWAP);
+ M_32_SWAP(m.magic);
+ M_32_SWAP(m.version);
+ M_32_SWAP(m.psize);
+ M_32_SWAP(m.free);
+ M_32_SWAP(m.nrecs);
+ M_32_SWAP(m.flags);
+ }
+ if (m.magic != BTREEMAGIC || m.version != BTREEVERSION)
+ goto eftype;
+ if (m.psize < MINPSIZE || m.psize > MAX_PAGE_OFFSET + 1 ||
+ m.psize & (sizeof(indx_t) - 1) )
+ goto eftype;
+ if (m.flags & ~SAVEMETA)
+ goto eftype;
+ b.psize = m.psize;
+ F_SET(t, m.flags);
+ t->bt_free = m.free;
+ t->bt_nrecs = m.nrecs;
+ } else {
+ /*
+ * Set the page size to the best value for I/O to this file.
+ * Don't overflow the page offset type.
+ */
+ if (b.psize == 0) {
+ b.psize = sb.st_blksize;
+ if (b.psize < MINPSIZE)
+ b.psize = MINPSIZE;
+ if (b.psize > MAX_PAGE_OFFSET + 1)
+ b.psize = MAX_PAGE_OFFSET + 1;
+ }
+
+ /* Set flag if duplicates permitted. */
+ if (!(b.flags & R_DUP))
+ F_SET(t, B_NODUPS);
+
+ t->bt_free = P_INVALID;
+ t->bt_nrecs = 0;
+ F_SET(t, B_METADIRTY);
+ }
+
+ t->bt_psize = b.psize;
+
+ /* Set the cache size; must be a multiple of the page size. */
+ if (b.cachesize && b.cachesize & (b.psize - 1) )
+ b.cachesize += (~b.cachesize & (b.psize - 1) ) + 1;
+ if (b.cachesize < b.psize * MINCACHE)
+ b.cachesize = b.psize * MINCACHE;
+
+ /* Calculate number of pages to cache. */
+ ncache = (b.cachesize + t->bt_psize - 1) / t->bt_psize;
+
+ /*
+ * The btree data structure requires that at least two keys can fit on
+ * a page, but other than that there's no fixed requirement. The user
+ * specified a minimum number per page, and we translated that into the
+ * number of bytes a key/data pair can use before being placed on an
+ * overflow page. This calculation includes the page header, the size
+ * of the index referencing the leaf item and the size of the leaf item
+ * structure. Also, don't let the user specify a minkeypage such that
+ * a key/data pair won't fit even if both key and data are on overflow
+ * pages.
+ */
+ t->bt_ovflsize = (t->bt_psize - BTDATAOFF) / b.minkeypage -
+ (sizeof(indx_t) + NBLEAFDBT(0, 0));
+ if (t->bt_ovflsize < NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t))
+ t->bt_ovflsize =
+ NBLEAFDBT(NOVFLSIZE, NOVFLSIZE) + sizeof(indx_t);
+
+ /* Initialize the buffer pool. */
+ if ((t->bt_mp =
+ mpool_open(NULL, t->bt_fd, t->bt_psize, ncache)) == NULL)
+ goto err;
+ if (!F_ISSET(t, B_INMEM))
+ mpool_filter(t->bt_mp, __bt_pgin, __bt_pgout, t);
+
+ /* Create a root page if new tree. */
+ if (nroot(t) == RET_ERROR)
+ goto err;
+
+ /* Global flags. */
+ if (dflags & DB_LOCK)
+ F_SET(t, B_DB_LOCK);
+ if (dflags & DB_SHMEM)
+ F_SET(t, B_DB_SHMEM);
+ if (dflags & DB_TXN)
+ F_SET(t, B_DB_TXN);
+
+ return (dbp);
+
+einval: errno = EINVAL;
+ goto err;
+
+eftype: errno = EFTYPE;
+ goto err;
+
+err: saved_errno = errno;
+ if (t) {
+ if (t->bt_dbp)
+ free(t->bt_dbp);
+ if (t->bt_fd != -1)
+ (void)_close(t->bt_fd);
+ free(t);
+ }
+ errno = saved_errno;
+ return (NULL);
+}
+
+/*
+ * NROOT -- Create the root of a new tree.
+ *
+ * Parameters:
+ * t: tree
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+static int
+nroot(BTREE *t)
+{
+ PAGE *meta, *root;
+ pgno_t npg;
+
+ if ((root = mpool_get(t->bt_mp, 1, 0)) != NULL) {
+ if (root->lower == 0 &&
+ root->pgno == 0 &&
+ root->linp[0] == 0) {
+ mpool_delete(t->bt_mp, root);
+ errno = EINVAL;
+ } else {
+ mpool_put(t->bt_mp, root, 0);
+ return (RET_SUCCESS);
+ }
+ }
+ if (errno != EINVAL) /* It's OK to not exist. */
+ return (RET_ERROR);
+ errno = 0;
+
+ if ((meta = mpool_new(t->bt_mp, &npg, MPOOL_PAGE_NEXT)) == NULL)
+ return (RET_ERROR);
+
+ if ((root = mpool_new(t->bt_mp, &npg, MPOOL_PAGE_NEXT)) == NULL)
+ return (RET_ERROR);
+
+ if (npg != P_ROOT)
+ return (RET_ERROR);
+ root->pgno = npg;
+ root->prevpg = root->nextpg = P_INVALID;
+ root->lower = BTDATAOFF;
+ root->upper = t->bt_psize;
+ root->flags = P_BLEAF;
+ memset(meta, 0, t->bt_psize);
+ mpool_put(t->bt_mp, meta, MPOOL_DIRTY);
+ mpool_put(t->bt_mp, root, MPOOL_DIRTY);
+ return (RET_SUCCESS);
+}
+
+static int
+tmp(void)
+{
+ sigset_t set, oset;
+ int fd, len;
+ char *envtmp = NULL;
+ char path[MAXPATHLEN];
+
+ if (issetugid() == 0)
+ envtmp = getenv("TMPDIR");
+ len = snprintf(path,
+ sizeof(path), "%s/bt.XXXXXXXXXX", envtmp ? envtmp : "/tmp");
+ if (len < 0 || len >= (int)sizeof(path)) {
+ errno = ENAMETOOLONG;
+ return(-1);
+ }
+
+ (void)sigfillset(&set);
+ (void)_sigprocmask(SIG_BLOCK, &set, &oset);
+ if ((fd = mkstemp(path)) != -1)
+ (void)unlink(path);
+ (void)_sigprocmask(SIG_SETMASK, &oset, NULL);
+ return(fd);
+}
+
+static int
+byteorder(void)
+{
+ u_int32_t x;
+ u_char *p;
+
+ x = 0x01020304;
+ p = (u_char *)&x;
+ switch (*p) {
+ case 1:
+ return (BIG_ENDIAN);
+ case 4:
+ return (LITTLE_ENDIAN);
+ default:
+ return (0);
+ }
+}
+
+int
+__bt_fd(const DB *dbp)
+{
+ BTREE *t;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* In-memory database can't have a file descriptor. */
+ if (F_ISSET(t, B_INMEM)) {
+ errno = ENOENT;
+ return (-1);
+ }
+ return (t->bt_fd);
+}
diff --git a/lib/libc/db/btree/bt_overflow.c b/lib/libc/db/btree/bt_overflow.c
new file mode 100644
index 0000000..266d599
--- /dev/null
+++ b/lib/libc/db/btree/bt_overflow.c
@@ -0,0 +1,216 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_overflow.c 8.5 (Berkeley) 7/16/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * Big key/data code.
+ *
+ * Big key and data entries are stored on linked lists of pages. The initial
+ * reference is byte string stored with the key or data and is the page number
+ * and size. The actual record is stored in a chain of pages linked by the
+ * nextpg field of the PAGE header.
+ *
+ * The first page of the chain has a special property. If the record is used
+ * by an internal page, it cannot be deleted and the P_PRESERVE bit will be set
+ * in the header.
+ *
+ * XXX
+ * A single DBT is written to each chain, so a lot of space on the last page
+ * is wasted. This is a fairly major bug for some data sets.
+ */
+
+/*
+ * __OVFL_GET -- Get an overflow key/data item.
+ *
+ * Parameters:
+ * t: tree
+ * p: pointer to { pgno_t, u_int32_t }
+ * buf: storage address
+ * bufsz: storage size
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_get(BTREE *t, void *p, size_t *ssz, void **buf, size_t *bufsz)
+{
+ PAGE *h;
+ pgno_t pg;
+ size_t nb, plen;
+ u_int32_t sz;
+
+ memmove(&pg, p, sizeof(pgno_t));
+ memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t));
+ *ssz = sz;
+
+#ifdef DEBUG
+ if (pg == P_INVALID || sz == 0)
+ abort();
+#endif
+ /* Make the buffer bigger as necessary. */
+ if (*bufsz < sz) {
+ *buf = reallocf(*buf, sz);
+ if (*buf == NULL)
+ return (RET_ERROR);
+ *bufsz = sz;
+ }
+
+ /*
+ * Step through the linked list of pages, copying the data on each one
+ * into the buffer. Never copy more than the data's length.
+ */
+ plen = t->bt_psize - BTDATAOFF;
+ for (p = *buf;; p = (char *)p + nb, pg = h->nextpg) {
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+
+ nb = MIN(sz, plen);
+ memmove(p, (char *)h + BTDATAOFF, nb);
+ mpool_put(t->bt_mp, h, 0);
+
+ if ((sz -= nb) == 0)
+ break;
+ }
+ return (RET_SUCCESS);
+}
+
+/*
+ * __OVFL_PUT -- Store an overflow key/data item.
+ *
+ * Parameters:
+ * t: tree
+ * data: DBT to store
+ * pgno: storage page number
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_put(BTREE *t, const DBT *dbt, pgno_t *pg)
+{
+ PAGE *h, *last;
+ void *p;
+ pgno_t npg;
+ size_t nb, plen;
+ u_int32_t sz;
+
+ /*
+ * Allocate pages and copy the key/data record into them. Store the
+ * number of the first page in the chain.
+ */
+ plen = t->bt_psize - BTDATAOFF;
+ for (last = NULL, p = dbt->data, sz = dbt->size;;
+ p = (char *)p + plen, last = h) {
+ if ((h = __bt_new(t, &npg)) == NULL)
+ return (RET_ERROR);
+
+ h->pgno = npg;
+ h->nextpg = h->prevpg = P_INVALID;
+ h->flags = P_OVERFLOW;
+ h->lower = h->upper = 0;
+
+ nb = MIN(sz, plen);
+ memmove((char *)h + BTDATAOFF, p, nb);
+
+ if (last) {
+ last->nextpg = h->pgno;
+ mpool_put(t->bt_mp, last, MPOOL_DIRTY);
+ } else
+ *pg = h->pgno;
+
+ if ((sz -= nb) == 0) {
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ break;
+ }
+ }
+ return (RET_SUCCESS);
+}
+
+/*
+ * __OVFL_DELETE -- Delete an overflow chain.
+ *
+ * Parameters:
+ * t: tree
+ * p: pointer to { pgno_t, u_int32_t }
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__ovfl_delete(BTREE *t, void *p)
+{
+ PAGE *h;
+ pgno_t pg;
+ size_t plen;
+ u_int32_t sz;
+
+ memmove(&pg, p, sizeof(pgno_t));
+ memmove(&sz, (char *)p + sizeof(pgno_t), sizeof(u_int32_t));
+
+#ifdef DEBUG
+ if (pg == P_INVALID || sz == 0)
+ abort();
+#endif
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+
+ /* Don't delete chains used by internal pages. */
+ if (h->flags & P_PRESERVE) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_SUCCESS);
+ }
+
+ /* Step through the chain, calling the free routine for each page. */
+ for (plen = t->bt_psize - BTDATAOFF;; sz -= plen) {
+ pg = h->nextpg;
+ __bt_free(t, h);
+ if (sz <= plen)
+ break;
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+ }
+ return (RET_SUCCESS);
+}
diff --git a/lib/libc/db/btree/bt_page.c b/lib/libc/db/btree/bt_page.c
new file mode 100644
index 0000000..ab5e359
--- /dev/null
+++ b/lib/libc/db/btree/bt_page.c
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_page.c 8.3 (Berkeley) 7/14/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * __bt_free --
+ * Put a page on the freelist.
+ *
+ * Parameters:
+ * t: tree
+ * h: page to free
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ *
+ * Side-effect:
+ * mpool_put's the page.
+ */
+int
+__bt_free(BTREE *t, PAGE *h)
+{
+ /* Insert the page at the head of the free list. */
+ h->prevpg = P_INVALID;
+ h->nextpg = t->bt_free;
+ t->bt_free = h->pgno;
+ F_SET(t, B_METADIRTY);
+
+ /* Make sure the page gets written back. */
+ return (mpool_put(t->bt_mp, h, MPOOL_DIRTY));
+}
+
+/*
+ * __bt_new --
+ * Get a new page, preferably from the freelist.
+ *
+ * Parameters:
+ * t: tree
+ * npg: storage for page number.
+ *
+ * Returns:
+ * Pointer to a page, NULL on error.
+ */
+PAGE *
+__bt_new(BTREE *t, pgno_t *npg)
+{
+ PAGE *h;
+
+ if (t->bt_free != P_INVALID &&
+ (h = mpool_get(t->bt_mp, t->bt_free, 0)) != NULL) {
+ *npg = t->bt_free;
+ t->bt_free = h->nextpg;
+ F_SET(t, B_METADIRTY);
+ return (h);
+ }
+ return (mpool_new(t->bt_mp, npg, MPOOL_PAGE_NEXT));
+}
diff --git a/lib/libc/db/btree/bt_put.c b/lib/libc/db/btree/bt_put.c
new file mode 100644
index 0000000..e4016c0
--- /dev/null
+++ b/lib/libc/db/btree/bt_put.c
@@ -0,0 +1,314 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_put.c 8.8 (Berkeley) 7/26/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+static EPG *bt_fast(BTREE *, const DBT *, const DBT *, int *);
+
+/*
+ * __BT_PUT -- Add a btree item to the tree.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ * key: key
+ * data: data
+ * flag: R_NOOVERWRITE
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is already in the
+ * tree and R_NOOVERWRITE specified.
+ */
+int
+__bt_put(const DB *dbp, DBT *key, const DBT *data, u_int flags)
+{
+ BTREE *t;
+ DBT tkey, tdata;
+ EPG *e;
+ PAGE *h;
+ indx_t idx, nxtindex;
+ pgno_t pg;
+ u_int32_t nbytes, tmp;
+ int dflags, exact, status;
+ char *dest, db[NOVFLSIZE], kb[NOVFLSIZE];
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* Check for change to a read-only tree. */
+ if (F_ISSET(t, B_RDONLY)) {
+ errno = EPERM;
+ return (RET_ERROR);
+ }
+
+ switch (flags) {
+ case 0:
+ case R_NOOVERWRITE:
+ break;
+ case R_CURSOR:
+ /*
+ * If flags is R_CURSOR, put the cursor. Must already
+ * have started a scan and not have already deleted it.
+ */
+ if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+ !F_ISSET(&t->bt_cursor,
+ CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE))
+ break;
+ /* FALLTHROUGH */
+ default:
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ /*
+ * If the key/data pair won't fit on a page, store it on overflow
+ * pages. Only put the key on the overflow page if the pair are
+ * still too big after moving the data to an overflow page.
+ *
+ * XXX
+ * If the insert fails later on, the overflow pages aren't recovered.
+ */
+ dflags = 0;
+ if (key->size + data->size > t->bt_ovflsize) {
+ if (key->size > t->bt_ovflsize) {
+storekey: if (__ovfl_put(t, key, &pg) == RET_ERROR)
+ return (RET_ERROR);
+ tkey.data = kb;
+ tkey.size = NOVFLSIZE;
+ memmove(kb, &pg, sizeof(pgno_t));
+ tmp = key->size;
+ memmove(kb + sizeof(pgno_t),
+ &tmp, sizeof(u_int32_t));
+ dflags |= P_BIGKEY;
+ key = &tkey;
+ }
+ if (key->size + data->size > t->bt_ovflsize) {
+ if (__ovfl_put(t, data, &pg) == RET_ERROR)
+ return (RET_ERROR);
+ tdata.data = db;
+ tdata.size = NOVFLSIZE;
+ memmove(db, &pg, sizeof(pgno_t));
+ tmp = data->size;
+ memmove(db + sizeof(pgno_t),
+ &tmp, sizeof(u_int32_t));
+ dflags |= P_BIGDATA;
+ data = &tdata;
+ }
+ if (key->size + data->size > t->bt_ovflsize)
+ goto storekey;
+ }
+
+ /* Replace the cursor. */
+ if (flags == R_CURSOR) {
+ if ((h = mpool_get(t->bt_mp, t->bt_cursor.pg.pgno, 0)) == NULL)
+ return (RET_ERROR);
+ idx = t->bt_cursor.pg.index;
+ goto delete;
+ }
+
+ /*
+ * Find the key to delete, or, the location at which to insert.
+ * Bt_fast and __bt_search both pin the returned page.
+ */
+ if (t->bt_order == NOT || (e = bt_fast(t, key, data, &exact)) == NULL)
+ if ((e = __bt_search(t, key, &exact)) == NULL)
+ return (RET_ERROR);
+ h = e->page;
+ idx = e->index;
+
+ /*
+ * Add the key/data pair to the tree. If an identical key is already
+ * in the tree, and R_NOOVERWRITE is set, an error is returned. If
+ * R_NOOVERWRITE is not set, the key is either added (if duplicates are
+ * permitted) or an error is returned.
+ */
+ switch (flags) {
+ case R_NOOVERWRITE:
+ if (!exact)
+ break;
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_SPECIAL);
+ default:
+ if (!exact || !F_ISSET(t, B_NODUPS))
+ break;
+ /*
+ * !!!
+ * Note, the delete may empty the page, so we need to put a
+ * new entry into the page immediately.
+ */
+delete: if (__bt_dleaf(t, key, h, idx) == RET_ERROR) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_ERROR);
+ }
+ break;
+ }
+
+ /*
+ * If not enough room, or the user has put a ceiling on the number of
+ * keys permitted in the page, split the page. The split code will
+ * insert the key and data and unpin the current page. If inserting
+ * into the offset array, shift the pointers up.
+ */
+ nbytes = NBLEAFDBT(key->size, data->size);
+ if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t)) {
+ if ((status = __bt_split(t, h, key,
+ data, dflags, nbytes, idx)) != RET_SUCCESS)
+ return (status);
+ goto success;
+ }
+
+ if (idx < (nxtindex = NEXTINDEX(h)))
+ memmove(h->linp + idx + 1, h->linp + idx,
+ (nxtindex - idx) * sizeof(indx_t));
+ h->lower += sizeof(indx_t);
+
+ h->linp[idx] = h->upper -= nbytes;
+ dest = (char *)h + h->upper;
+ WR_BLEAF(dest, key, data, dflags);
+
+ /* If the cursor is on this page, adjust it as necessary. */
+ if (F_ISSET(&t->bt_cursor, CURS_INIT) &&
+ !F_ISSET(&t->bt_cursor, CURS_ACQUIRE) &&
+ t->bt_cursor.pg.pgno == h->pgno && t->bt_cursor.pg.index >= idx)
+ ++t->bt_cursor.pg.index;
+
+ if (t->bt_order == NOT) {
+ if (h->nextpg == P_INVALID) {
+ if (idx == NEXTINDEX(h) - 1) {
+ t->bt_order = FORWARD;
+ t->bt_last.index = idx;
+ t->bt_last.pgno = h->pgno;
+ }
+ } else if (h->prevpg == P_INVALID) {
+ if (idx == 0) {
+ t->bt_order = BACK;
+ t->bt_last.index = 0;
+ t->bt_last.pgno = h->pgno;
+ }
+ }
+ }
+
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+success:
+ if (flags == R_SETCURSOR)
+ __bt_setcur(t, e->page->pgno, e->index);
+
+ F_SET(t, B_MODIFIED);
+ return (RET_SUCCESS);
+}
+
+#ifdef STATISTICS
+u_long bt_cache_hit, bt_cache_miss;
+#endif
+
+/*
+ * BT_FAST -- Do a quick check for sorted data.
+ *
+ * Parameters:
+ * t: tree
+ * key: key to insert
+ *
+ * Returns:
+ * EPG for new record or NULL if not found.
+ */
+static EPG *
+bt_fast(BTREE *t, const DBT *key, const DBT *data, int *exactp)
+{
+ PAGE *h;
+ u_int32_t nbytes;
+ int cmp;
+
+ if ((h = mpool_get(t->bt_mp, t->bt_last.pgno, 0)) == NULL) {
+ t->bt_order = NOT;
+ return (NULL);
+ }
+ t->bt_cur.page = h;
+ t->bt_cur.index = t->bt_last.index;
+
+ /*
+ * If won't fit in this page or have too many keys in this page,
+ * have to search to get split stack.
+ */
+ nbytes = NBLEAFDBT(key->size, data->size);
+ if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t))
+ goto miss;
+
+ if (t->bt_order == FORWARD) {
+ if (t->bt_cur.page->nextpg != P_INVALID)
+ goto miss;
+ if (t->bt_cur.index != NEXTINDEX(h) - 1)
+ goto miss;
+ if ((cmp = __bt_cmp(t, key, &t->bt_cur)) < 0)
+ goto miss;
+ t->bt_last.index = cmp ? ++t->bt_cur.index : t->bt_cur.index;
+ } else {
+ if (t->bt_cur.page->prevpg != P_INVALID)
+ goto miss;
+ if (t->bt_cur.index != 0)
+ goto miss;
+ if ((cmp = __bt_cmp(t, key, &t->bt_cur)) > 0)
+ goto miss;
+ t->bt_last.index = 0;
+ }
+ *exactp = cmp == 0;
+#ifdef STATISTICS
+ ++bt_cache_hit;
+#endif
+ return (&t->bt_cur);
+
+miss:
+#ifdef STATISTICS
+ ++bt_cache_miss;
+#endif
+ t->bt_order = NOT;
+ mpool_put(t->bt_mp, h, 0);
+ return (NULL);
+}
diff --git a/lib/libc/db/btree/bt_search.c b/lib/libc/db/btree/bt_search.c
new file mode 100644
index 0000000..15ef1fa
--- /dev/null
+++ b/lib/libc/db/btree/bt_search.c
@@ -0,0 +1,200 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_search.c 8.8 (Berkeley) 7/31/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <stdio.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int __bt_snext(BTREE *, PAGE *, const DBT *, int *);
+static int __bt_sprev(BTREE *, PAGE *, const DBT *, int *);
+
+/*
+ * __bt_search --
+ * Search a btree for a key.
+ *
+ * Parameters:
+ * t: tree to search
+ * key: key to find
+ * exactp: pointer to exact match flag
+ *
+ * Returns:
+ * The EPG for matching record, if any, or the EPG for the location
+ * of the key, if it were inserted into the tree, is entered into
+ * the bt_cur field of the tree. A pointer to the field is returned.
+ */
+EPG *
+__bt_search(BTREE *t, const DBT *key, int *exactp)
+{
+ PAGE *h;
+ indx_t base, idx, lim;
+ pgno_t pg;
+ int cmp;
+
+ BT_CLR(t);
+ for (pg = P_ROOT;;) {
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (NULL);
+
+ /* Do a binary search on the current page. */
+ t->bt_cur.page = h;
+ for (base = 0, lim = NEXTINDEX(h); lim; lim >>= 1) {
+ t->bt_cur.index = idx = base + (lim >> 1);
+ if ((cmp = __bt_cmp(t, key, &t->bt_cur)) == 0) {
+ if (h->flags & P_BLEAF) {
+ *exactp = 1;
+ return (&t->bt_cur);
+ }
+ goto next;
+ }
+ if (cmp > 0) {
+ base = idx + 1;
+ --lim;
+ }
+ }
+
+ /*
+ * If it's a leaf page, we're almost done. If no duplicates
+ * are allowed, or we have an exact match, we're done. Else,
+ * it's possible that there were matching keys on this page,
+ * which later deleted, and we're on a page with no matches
+ * while there are matches on other pages. If at the start or
+ * end of a page, check the adjacent page.
+ */
+ if (h->flags & P_BLEAF) {
+ if (!F_ISSET(t, B_NODUPS)) {
+ if (base == 0 &&
+ h->prevpg != P_INVALID &&
+ __bt_sprev(t, h, key, exactp))
+ return (&t->bt_cur);
+ if (base == NEXTINDEX(h) &&
+ h->nextpg != P_INVALID &&
+ __bt_snext(t, h, key, exactp))
+ return (&t->bt_cur);
+ }
+ *exactp = 0;
+ t->bt_cur.index = base;
+ return (&t->bt_cur);
+ }
+
+ /*
+ * No match found. Base is the smallest index greater than
+ * key and may be zero or a last + 1 index. If it's non-zero,
+ * decrement by one, and record the internal page which should
+ * be a parent page for the key. If a split later occurs, the
+ * inserted page will be to the right of the saved page.
+ */
+ idx = base ? base - 1 : base;
+
+next: BT_PUSH(t, h->pgno, idx);
+ pg = GETBINTERNAL(h, idx)->pgno;
+ mpool_put(t->bt_mp, h, 0);
+ }
+}
+
+/*
+ * __bt_snext --
+ * Check for an exact match after the key.
+ *
+ * Parameters:
+ * t: tree
+ * h: current page
+ * key: key
+ * exactp: pointer to exact match flag
+ *
+ * Returns:
+ * If an exact match found.
+ */
+static int
+__bt_snext(BTREE *t, PAGE *h, const DBT *key, int *exactp)
+{
+ EPG e;
+
+ /*
+ * Get the next page. The key is either an exact
+ * match, or not as good as the one we already have.
+ */
+ if ((e.page = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL)
+ return (0);
+ e.index = 0;
+ if (__bt_cmp(t, key, &e) == 0) {
+ mpool_put(t->bt_mp, h, 0);
+ t->bt_cur = e;
+ *exactp = 1;
+ return (1);
+ }
+ mpool_put(t->bt_mp, e.page, 0);
+ return (0);
+}
+
+/*
+ * __bt_sprev --
+ * Check for an exact match before the key.
+ *
+ * Parameters:
+ * t: tree
+ * h: current page
+ * key: key
+ * exactp: pointer to exact match flag
+ *
+ * Returns:
+ * If an exact match found.
+ */
+static int
+__bt_sprev(BTREE *t, PAGE *h, const DBT *key, int *exactp)
+{
+ EPG e;
+
+ /*
+ * Get the previous page. The key is either an exact
+ * match, or not as good as the one we already have.
+ */
+ if ((e.page = mpool_get(t->bt_mp, h->prevpg, 0)) == NULL)
+ return (0);
+ e.index = NEXTINDEX(e.page) - 1;
+ if (__bt_cmp(t, key, &e) == 0) {
+ mpool_put(t->bt_mp, h, 0);
+ t->bt_cur = e;
+ *exactp = 1;
+ return (1);
+ }
+ mpool_put(t->bt_mp, e.page, 0);
+ return (0);
+}
diff --git a/lib/libc/db/btree/bt_seq.c b/lib/libc/db/btree/bt_seq.c
new file mode 100644
index 0000000..1928951
--- /dev/null
+++ b/lib/libc/db/btree/bt_seq.c
@@ -0,0 +1,441 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_seq.c 8.7 (Berkeley) 7/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int __bt_first(BTREE *, const DBT *, EPG *, int *);
+static int __bt_seqadv(BTREE *, EPG *, int);
+static int __bt_seqset(BTREE *, EPG *, DBT *, int);
+
+/*
+ * Sequential scan support.
+ *
+ * The tree can be scanned sequentially, starting from either end of the
+ * tree or from any specific key. A scan request before any scanning is
+ * done is initialized as starting from the least node.
+ */
+
+/*
+ * __bt_seq --
+ * Btree sequential scan interface.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ * key: key for positioning and return value
+ * data: data return value
+ * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+int
+__bt_seq(const DB *dbp, DBT *key, DBT *data, u_int flags)
+{
+ BTREE *t;
+ EPG e;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /*
+ * If scan unitialized as yet, or starting at a specific record, set
+ * the scan to a specific key. Both __bt_seqset and __bt_seqadv pin
+ * the page the cursor references if they're successful.
+ */
+ switch (flags) {
+ case R_NEXT:
+ case R_PREV:
+ if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+ status = __bt_seqadv(t, &e, flags);
+ break;
+ }
+ /* FALLTHROUGH */
+ case R_FIRST:
+ case R_LAST:
+ case R_CURSOR:
+ status = __bt_seqset(t, &e, key, flags);
+ break;
+ default:
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ if (status == RET_SUCCESS) {
+ __bt_setcur(t, e.page->pgno, e.index);
+
+ status =
+ __bt_ret(t, &e, key, &t->bt_rkey, data, &t->bt_rdata, 0);
+
+ /*
+ * If the user is doing concurrent access, we copied the
+ * key/data, toss the page.
+ */
+ if (F_ISSET(t, B_DB_LOCK))
+ mpool_put(t->bt_mp, e.page, 0);
+ else
+ t->bt_pinned = e.page;
+ }
+ return (status);
+}
+
+/*
+ * __bt_seqset --
+ * Set the sequential scan to a specific key.
+ *
+ * Parameters:
+ * t: tree
+ * ep: storage for returned key
+ * key: key for initial scan position
+ * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV
+ *
+ * Side effects:
+ * Pins the page the cursor references.
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+static int
+__bt_seqset(BTREE *t, EPG *ep, DBT *key, int flags)
+{
+ PAGE *h;
+ pgno_t pg;
+ int exact;
+
+ /*
+ * Find the first, last or specific key in the tree and point the
+ * cursor at it. The cursor may not be moved until a new key has
+ * been found.
+ */
+ switch (flags) {
+ case R_CURSOR: /* Keyed scan. */
+ /*
+ * Find the first instance of the key or the smallest key
+ * which is greater than or equal to the specified key.
+ */
+ if (key->data == NULL || key->size == 0) {
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+ return (__bt_first(t, key, ep, &exact));
+ case R_FIRST: /* First record. */
+ case R_NEXT:
+ /* Walk down the left-hand side of the tree. */
+ for (pg = P_ROOT;;) {
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+
+ /* Check for an empty tree. */
+ if (NEXTINDEX(h) == 0) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_SPECIAL);
+ }
+
+ if (h->flags & (P_BLEAF | P_RLEAF))
+ break;
+ pg = GETBINTERNAL(h, 0)->pgno;
+ mpool_put(t->bt_mp, h, 0);
+ }
+ ep->page = h;
+ ep->index = 0;
+ break;
+ case R_LAST: /* Last record. */
+ case R_PREV:
+ /* Walk down the right-hand side of the tree. */
+ for (pg = P_ROOT;;) {
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+
+ /* Check for an empty tree. */
+ if (NEXTINDEX(h) == 0) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_SPECIAL);
+ }
+
+ if (h->flags & (P_BLEAF | P_RLEAF))
+ break;
+ pg = GETBINTERNAL(h, NEXTINDEX(h) - 1)->pgno;
+ mpool_put(t->bt_mp, h, 0);
+ }
+
+ ep->page = h;
+ ep->index = NEXTINDEX(h) - 1;
+ break;
+ }
+ return (RET_SUCCESS);
+}
+
+/*
+ * __bt_seqadvance --
+ * Advance the sequential scan.
+ *
+ * Parameters:
+ * t: tree
+ * flags: R_NEXT, R_PREV
+ *
+ * Side effects:
+ * Pins the page the new key/data record is on.
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+static int
+__bt_seqadv(BTREE *t, EPG *ep, int flags)
+{
+ CURSOR *c;
+ PAGE *h;
+ indx_t idx;
+ pgno_t pg;
+ int exact;
+
+ /*
+ * There are a couple of states that we can be in. The cursor has
+ * been initialized by the time we get here, but that's all we know.
+ */
+ c = &t->bt_cursor;
+
+ /*
+ * The cursor was deleted where there weren't any duplicate records,
+ * so the key was saved. Find out where that key would go in the
+ * current tree. It doesn't matter if the returned key is an exact
+ * match or not -- if it's an exact match, the record was added after
+ * the delete so we can just return it. If not, as long as there's
+ * a record there, return it.
+ */
+ if (F_ISSET(c, CURS_ACQUIRE))
+ return (__bt_first(t, &c->key, ep, &exact));
+
+ /* Get the page referenced by the cursor. */
+ if ((h = mpool_get(t->bt_mp, c->pg.pgno, 0)) == NULL)
+ return (RET_ERROR);
+
+ /*
+ * Find the next/previous record in the tree and point the cursor at
+ * it. The cursor may not be moved until a new key has been found.
+ */
+ switch (flags) {
+ case R_NEXT: /* Next record. */
+ /*
+ * The cursor was deleted in duplicate records, and moved
+ * forward to a record that has yet to be returned. Clear
+ * that flag, and return the record.
+ */
+ if (F_ISSET(c, CURS_AFTER))
+ goto usecurrent;
+ idx = c->pg.index;
+ if (++idx == NEXTINDEX(h)) {
+ pg = h->nextpg;
+ mpool_put(t->bt_mp, h, 0);
+ if (pg == P_INVALID)
+ return (RET_SPECIAL);
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+ idx = 0;
+ }
+ break;
+ case R_PREV: /* Previous record. */
+ /*
+ * The cursor was deleted in duplicate records, and moved
+ * backward to a record that has yet to be returned. Clear
+ * that flag, and return the record.
+ */
+ if (F_ISSET(c, CURS_BEFORE)) {
+usecurrent: F_CLR(c, CURS_AFTER | CURS_BEFORE);
+ ep->page = h;
+ ep->index = c->pg.index;
+ return (RET_SUCCESS);
+ }
+ idx = c->pg.index;
+ if (idx == 0) {
+ pg = h->prevpg;
+ mpool_put(t->bt_mp, h, 0);
+ if (pg == P_INVALID)
+ return (RET_SPECIAL);
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+ idx = NEXTINDEX(h) - 1;
+ } else
+ --idx;
+ break;
+ }
+
+ ep->page = h;
+ ep->index = idx;
+ return (RET_SUCCESS);
+}
+
+/*
+ * __bt_first --
+ * Find the first entry.
+ *
+ * Parameters:
+ * t: the tree
+ * key: the key
+ * erval: return EPG
+ * exactp: pointer to exact match flag
+ *
+ * Returns:
+ * The first entry in the tree greater than or equal to key,
+ * or RET_SPECIAL if no such key exists.
+ */
+static int
+__bt_first(BTREE *t, const DBT *key, EPG *erval, int *exactp)
+{
+ PAGE *h;
+ EPG *ep, save;
+ pgno_t pg;
+
+ /*
+ * Find any matching record; __bt_search pins the page.
+ *
+ * If it's an exact match and duplicates are possible, walk backwards
+ * in the tree until we find the first one. Otherwise, make sure it's
+ * a valid key (__bt_search may return an index just past the end of a
+ * page) and return it.
+ */
+ if ((ep = __bt_search(t, key, exactp)) == NULL)
+ return (0);
+ if (*exactp) {
+ if (F_ISSET(t, B_NODUPS)) {
+ *erval = *ep;
+ return (RET_SUCCESS);
+ }
+
+ /*
+ * Walk backwards, as long as the entry matches and there are
+ * keys left in the tree. Save a copy of each match in case
+ * we go too far.
+ */
+ save = *ep;
+ h = ep->page;
+ do {
+ if (save.page->pgno != ep->page->pgno) {
+ mpool_put(t->bt_mp, save.page, 0);
+ save = *ep;
+ } else
+ save.index = ep->index;
+
+ /*
+ * Don't unpin the page the last (or original) match
+ * was on, but make sure it's unpinned if an error
+ * occurs.
+ */
+ if (ep->index == 0) {
+ if (h->prevpg == P_INVALID)
+ break;
+ if (h->pgno != save.page->pgno)
+ mpool_put(t->bt_mp, h, 0);
+ if ((h = mpool_get(t->bt_mp,
+ h->prevpg, 0)) == NULL) {
+ if (h->pgno == save.page->pgno)
+ mpool_put(t->bt_mp,
+ save.page, 0);
+ return (RET_ERROR);
+ }
+ ep->page = h;
+ ep->index = NEXTINDEX(h);
+ }
+ --ep->index;
+ } while (__bt_cmp(t, key, ep) == 0);
+
+ /*
+ * Reach here with the last page that was looked at pinned,
+ * which may or may not be the same as the last (or original)
+ * match page. If it's not useful, release it.
+ */
+ if (h->pgno != save.page->pgno)
+ mpool_put(t->bt_mp, h, 0);
+
+ *erval = save;
+ return (RET_SUCCESS);
+ }
+
+ /* If at the end of a page, find the next entry. */
+ if (ep->index == NEXTINDEX(ep->page)) {
+ h = ep->page;
+ pg = h->nextpg;
+ mpool_put(t->bt_mp, h, 0);
+ if (pg == P_INVALID)
+ return (RET_SPECIAL);
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+ ep->index = 0;
+ ep->page = h;
+ }
+ *erval = *ep;
+ return (RET_SUCCESS);
+}
+
+/*
+ * __bt_setcur --
+ * Set the cursor to an entry in the tree.
+ *
+ * Parameters:
+ * t: the tree
+ * pgno: page number
+ * idx: page index
+ */
+void
+__bt_setcur(BTREE *t, pgno_t pgno, u_int idx)
+{
+ /* Lose any already deleted key. */
+ if (t->bt_cursor.key.data != NULL) {
+ free(t->bt_cursor.key.data);
+ t->bt_cursor.key.size = 0;
+ t->bt_cursor.key.data = NULL;
+ }
+ F_CLR(&t->bt_cursor, CURS_ACQUIRE | CURS_AFTER | CURS_BEFORE);
+
+ /* Update the cursor. */
+ t->bt_cursor.pg.pgno = pgno;
+ t->bt_cursor.pg.index = idx;
+ F_SET(&t->bt_cursor, CURS_INIT);
+}
diff --git a/lib/libc/db/btree/bt_split.c b/lib/libc/db/btree/bt_split.c
new file mode 100644
index 0000000..f0db406
--- /dev/null
+++ b/lib/libc/db/btree/bt_split.c
@@ -0,0 +1,797 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_split.c 8.10 (Berkeley) 1/9/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+static int bt_broot(BTREE *, PAGE *, PAGE *, PAGE *);
+static PAGE *bt_page(BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
+static int bt_preserve(BTREE *, pgno_t);
+static PAGE *bt_psplit(BTREE *, PAGE *, PAGE *, PAGE *, indx_t *, size_t);
+static PAGE *bt_root(BTREE *, PAGE *, PAGE **, PAGE **, indx_t *, size_t);
+static int bt_rroot(BTREE *, PAGE *, PAGE *, PAGE *);
+static recno_t rec_total(PAGE *);
+
+#ifdef STATISTICS
+u_long bt_rootsplit, bt_split, bt_sortsplit, bt_pfxsaved;
+#endif
+
+/*
+ * __BT_SPLIT -- Split the tree.
+ *
+ * Parameters:
+ * t: tree
+ * sp: page to split
+ * key: key to insert
+ * data: data to insert
+ * flags: BIGKEY/BIGDATA flags
+ * ilen: insert length
+ * skip: index to leave open
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__bt_split(BTREE *t, PAGE *sp, const DBT *key, const DBT *data, int flags,
+ size_t ilen, u_int32_t argskip)
+{
+ BINTERNAL *bi;
+ BLEAF *bl, *tbl;
+ DBT a, b;
+ EPGNO *parent;
+ PAGE *h, *l, *r, *lchild, *rchild;
+ indx_t nxtindex;
+ u_int16_t skip;
+ u_int32_t n, nbytes, nksize;
+ int parentsplit;
+ char *dest;
+
+ /*
+ * Split the page into two pages, l and r. The split routines return
+ * a pointer to the page into which the key should be inserted and with
+ * skip set to the offset which should be used. Additionally, l and r
+ * are pinned.
+ */
+ skip = argskip;
+ h = sp->pgno == P_ROOT ?
+ bt_root(t, sp, &l, &r, &skip, ilen) :
+ bt_page(t, sp, &l, &r, &skip, ilen);
+ if (h == NULL)
+ return (RET_ERROR);
+
+ /*
+ * Insert the new key/data pair into the leaf page. (Key inserts
+ * always cause a leaf page to split first.)
+ */
+ h->linp[skip] = h->upper -= ilen;
+ dest = (char *)h + h->upper;
+ if (F_ISSET(t, R_RECNO))
+ WR_RLEAF(dest, data, flags)
+ else
+ WR_BLEAF(dest, key, data, flags)
+
+ /* If the root page was split, make it look right. */
+ if (sp->pgno == P_ROOT &&
+ (F_ISSET(t, R_RECNO) ?
+ bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
+ goto err2;
+
+ /*
+ * Now we walk the parent page stack -- a LIFO stack of the pages that
+ * were traversed when we searched for the page that split. Each stack
+ * entry is a page number and a page index offset. The offset is for
+ * the page traversed on the search. We've just split a page, so we
+ * have to insert a new key into the parent page.
+ *
+ * If the insert into the parent page causes it to split, may have to
+ * continue splitting all the way up the tree. We stop if the root
+ * splits or the page inserted into didn't have to split to hold the
+ * new key. Some algorithms replace the key for the old page as well
+ * as the new page. We don't, as there's no reason to believe that the
+ * first key on the old page is any better than the key we have, and,
+ * in the case of a key being placed at index 0 causing the split, the
+ * key is unavailable.
+ *
+ * There are a maximum of 5 pages pinned at any time. We keep the left
+ * and right pages pinned while working on the parent. The 5 are the
+ * two children, left parent and right parent (when the parent splits)
+ * and the root page or the overflow key page when calling bt_preserve.
+ * This code must make sure that all pins are released other than the
+ * root page or overflow page which is unlocked elsewhere.
+ */
+ while ((parent = BT_POP(t)) != NULL) {
+ lchild = l;
+ rchild = r;
+
+ /* Get the parent page. */
+ if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+ goto err2;
+
+ /*
+ * The new key goes ONE AFTER the index, because the split
+ * was to the right.
+ */
+ skip = parent->index + 1;
+
+ /*
+ * Calculate the space needed on the parent page.
+ *
+ * Prefix trees: space hack when inserting into BINTERNAL
+ * pages. Retain only what's needed to distinguish between
+ * the new entry and the LAST entry on the page to its left.
+ * If the keys compare equal, retain the entire key. Note,
+ * we don't touch overflow keys, and the entire key must be
+ * retained for the next-to-left most key on the leftmost
+ * page of each level, or the search will fail. Applicable
+ * ONLY to internal pages that have leaf pages as children.
+ * Further reduction of the key between pairs of internal
+ * pages loses too much information.
+ */
+ switch (rchild->flags & P_TYPE) {
+ case P_BINTERNAL:
+ bi = GETBINTERNAL(rchild, 0);
+ nbytes = NBINTERNAL(bi->ksize);
+ break;
+ case P_BLEAF:
+ bl = GETBLEAF(rchild, 0);
+ nbytes = NBINTERNAL(bl->ksize);
+ if (t->bt_pfx && !(bl->flags & P_BIGKEY) &&
+ (h->prevpg != P_INVALID || skip > 1)) {
+ tbl = GETBLEAF(lchild, NEXTINDEX(lchild) - 1);
+ a.size = tbl->ksize;
+ a.data = tbl->bytes;
+ b.size = bl->ksize;
+ b.data = bl->bytes;
+ nksize = t->bt_pfx(&a, &b);
+ n = NBINTERNAL(nksize);
+ if (n < nbytes) {
+#ifdef STATISTICS
+ bt_pfxsaved += nbytes - n;
+#endif
+ nbytes = n;
+ } else
+ nksize = 0;
+ } else
+ nksize = 0;
+ break;
+ case P_RINTERNAL:
+ case P_RLEAF:
+ nbytes = NRINTERNAL;
+ break;
+ default:
+ abort();
+ }
+
+ /* Split the parent page if necessary or shift the indices. */
+ if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t)) {
+ sp = h;
+ h = h->pgno == P_ROOT ?
+ bt_root(t, h, &l, &r, &skip, nbytes) :
+ bt_page(t, h, &l, &r, &skip, nbytes);
+ if (h == NULL)
+ goto err1;
+ parentsplit = 1;
+ } else {
+ if (skip < (nxtindex = NEXTINDEX(h)))
+ memmove(h->linp + skip + 1, h->linp + skip,
+ (nxtindex - skip) * sizeof(indx_t));
+ h->lower += sizeof(indx_t);
+ parentsplit = 0;
+ }
+
+ /* Insert the key into the parent page. */
+ switch (rchild->flags & P_TYPE) {
+ case P_BINTERNAL:
+ h->linp[skip] = h->upper -= nbytes;
+ dest = (char *)h + h->linp[skip];
+ memmove(dest, bi, nbytes);
+ ((BINTERNAL *)dest)->pgno = rchild->pgno;
+ break;
+ case P_BLEAF:
+ h->linp[skip] = h->upper -= nbytes;
+ dest = (char *)h + h->linp[skip];
+ WR_BINTERNAL(dest, nksize ? nksize : bl->ksize,
+ rchild->pgno, bl->flags & P_BIGKEY);
+ memmove(dest, bl->bytes, nksize ? nksize : bl->ksize);
+ if (bl->flags & P_BIGKEY &&
+ bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR)
+ goto err1;
+ break;
+ case P_RINTERNAL:
+ /*
+ * Update the left page count. If split
+ * added at index 0, fix the correct page.
+ */
+ if (skip > 0)
+ dest = (char *)h + h->linp[skip - 1];
+ else
+ dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
+ ((RINTERNAL *)dest)->nrecs = rec_total(lchild);
+ ((RINTERNAL *)dest)->pgno = lchild->pgno;
+
+ /* Update the right page count. */
+ h->linp[skip] = h->upper -= nbytes;
+ dest = (char *)h + h->linp[skip];
+ ((RINTERNAL *)dest)->nrecs = rec_total(rchild);
+ ((RINTERNAL *)dest)->pgno = rchild->pgno;
+ break;
+ case P_RLEAF:
+ /*
+ * Update the left page count. If split
+ * added at index 0, fix the correct page.
+ */
+ if (skip > 0)
+ dest = (char *)h + h->linp[skip - 1];
+ else
+ dest = (char *)l + l->linp[NEXTINDEX(l) - 1];
+ ((RINTERNAL *)dest)->nrecs = NEXTINDEX(lchild);
+ ((RINTERNAL *)dest)->pgno = lchild->pgno;
+
+ /* Update the right page count. */
+ h->linp[skip] = h->upper -= nbytes;
+ dest = (char *)h + h->linp[skip];
+ ((RINTERNAL *)dest)->nrecs = NEXTINDEX(rchild);
+ ((RINTERNAL *)dest)->pgno = rchild->pgno;
+ break;
+ default:
+ abort();
+ }
+
+ /* Unpin the held pages. */
+ if (!parentsplit) {
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ break;
+ }
+
+ /* If the root page was split, make it look right. */
+ if (sp->pgno == P_ROOT &&
+ (F_ISSET(t, R_RECNO) ?
+ bt_rroot(t, sp, l, r) : bt_broot(t, sp, l, r)) == RET_ERROR)
+ goto err1;
+
+ mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
+ mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
+ }
+
+ /* Unpin the held pages. */
+ mpool_put(t->bt_mp, l, MPOOL_DIRTY);
+ mpool_put(t->bt_mp, r, MPOOL_DIRTY);
+
+ /* Clear any pages left on the stack. */
+ return (RET_SUCCESS);
+
+ /*
+ * If something fails in the above loop we were already walking back
+ * up the tree and the tree is now inconsistent. Nothing much we can
+ * do about it but release any memory we're holding.
+ */
+err1: mpool_put(t->bt_mp, lchild, MPOOL_DIRTY);
+ mpool_put(t->bt_mp, rchild, MPOOL_DIRTY);
+
+err2: mpool_put(t->bt_mp, l, 0);
+ mpool_put(t->bt_mp, r, 0);
+ __dbpanic(t->bt_dbp);
+ return (RET_ERROR);
+}
+
+/*
+ * BT_PAGE -- Split a non-root page of a btree.
+ *
+ * Parameters:
+ * t: tree
+ * h: root page
+ * lp: pointer to left page pointer
+ * rp: pointer to right page pointer
+ * skip: pointer to index to leave open
+ * ilen: insert length
+ *
+ * Returns:
+ * Pointer to page in which to insert or NULL on error.
+ */
+static PAGE *
+bt_page(BTREE *t, PAGE *h, PAGE **lp, PAGE **rp, indx_t *skip, size_t ilen)
+{
+ PAGE *l, *r, *tp;
+ pgno_t npg;
+
+#ifdef STATISTICS
+ ++bt_split;
+#endif
+ /* Put the new right page for the split into place. */
+ if ((r = __bt_new(t, &npg)) == NULL)
+ return (NULL);
+ r->pgno = npg;
+ r->lower = BTDATAOFF;
+ r->upper = t->bt_psize;
+ r->nextpg = h->nextpg;
+ r->prevpg = h->pgno;
+ r->flags = h->flags & P_TYPE;
+
+ /*
+ * If we're splitting the last page on a level because we're appending
+ * a key to it (skip is NEXTINDEX()), it's likely that the data is
+ * sorted. Adding an empty page on the side of the level is less work
+ * and can push the fill factor much higher than normal. If we're
+ * wrong it's no big deal, we'll just do the split the right way next
+ * time. It may look like it's equally easy to do a similar hack for
+ * reverse sorted data, that is, split the tree left, but it's not.
+ * Don't even try.
+ */
+ if (h->nextpg == P_INVALID && *skip == NEXTINDEX(h)) {
+#ifdef STATISTICS
+ ++bt_sortsplit;
+#endif
+ h->nextpg = r->pgno;
+ r->lower = BTDATAOFF + sizeof(indx_t);
+ *skip = 0;
+ *lp = h;
+ *rp = r;
+ return (r);
+ }
+
+ /* Put the new left page for the split into place. */
+ if ((l = (PAGE *)calloc(1, t->bt_psize)) == NULL) {
+ mpool_put(t->bt_mp, r, 0);
+ return (NULL);
+ }
+ l->pgno = h->pgno;
+ l->nextpg = r->pgno;
+ l->prevpg = h->prevpg;
+ l->lower = BTDATAOFF;
+ l->upper = t->bt_psize;
+ l->flags = h->flags & P_TYPE;
+
+ /* Fix up the previous pointer of the page after the split page. */
+ if (h->nextpg != P_INVALID) {
+ if ((tp = mpool_get(t->bt_mp, h->nextpg, 0)) == NULL) {
+ free(l);
+ /* XXX mpool_free(t->bt_mp, r->pgno); */
+ return (NULL);
+ }
+ tp->prevpg = r->pgno;
+ mpool_put(t->bt_mp, tp, MPOOL_DIRTY);
+ }
+
+ /*
+ * Split right. The key/data pairs aren't sorted in the btree page so
+ * it's simpler to copy the data from the split page onto two new pages
+ * instead of copying half the data to the right page and compacting
+ * the left page in place. Since the left page can't change, we have
+ * to swap the original and the allocated left page after the split.
+ */
+ tp = bt_psplit(t, h, l, r, skip, ilen);
+
+ /* Move the new left page onto the old left page. */
+ memmove(h, l, t->bt_psize);
+ if (tp == l)
+ tp = h;
+ free(l);
+
+ *lp = h;
+ *rp = r;
+ return (tp);
+}
+
+/*
+ * BT_ROOT -- Split the root page of a btree.
+ *
+ * Parameters:
+ * t: tree
+ * h: root page
+ * lp: pointer to left page pointer
+ * rp: pointer to right page pointer
+ * skip: pointer to index to leave open
+ * ilen: insert length
+ *
+ * Returns:
+ * Pointer to page in which to insert or NULL on error.
+ */
+static PAGE *
+bt_root(BTREE *t, PAGE *h, PAGE **lp, PAGE **rp, indx_t *skip, size_t ilen)
+{
+ PAGE *l, *r, *tp;
+ pgno_t lnpg, rnpg;
+
+#ifdef STATISTICS
+ ++bt_split;
+ ++bt_rootsplit;
+#endif
+ /* Put the new left and right pages for the split into place. */
+ if ((l = __bt_new(t, &lnpg)) == NULL ||
+ (r = __bt_new(t, &rnpg)) == NULL)
+ return (NULL);
+ l->pgno = lnpg;
+ r->pgno = rnpg;
+ l->nextpg = r->pgno;
+ r->prevpg = l->pgno;
+ l->prevpg = r->nextpg = P_INVALID;
+ l->lower = r->lower = BTDATAOFF;
+ l->upper = r->upper = t->bt_psize;
+ l->flags = r->flags = h->flags & P_TYPE;
+
+ /* Split the root page. */
+ tp = bt_psplit(t, h, l, r, skip, ilen);
+
+ *lp = l;
+ *rp = r;
+ return (tp);
+}
+
+/*
+ * BT_RROOT -- Fix up the recno root page after it has been split.
+ *
+ * Parameters:
+ * t: tree
+ * h: root page
+ * l: left page
+ * r: right page
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_rroot(BTREE *t, PAGE *h, PAGE *l, PAGE *r)
+{
+ char *dest;
+
+ /* Insert the left and right keys, set the header information. */
+ h->linp[0] = h->upper = t->bt_psize - NRINTERNAL;
+ dest = (char *)h + h->upper;
+ WR_RINTERNAL(dest,
+ l->flags & P_RLEAF ? NEXTINDEX(l) : rec_total(l), l->pgno);
+
+ __PAST_END(h->linp, 1) = h->upper -= NRINTERNAL;
+ dest = (char *)h + h->upper;
+ WR_RINTERNAL(dest,
+ r->flags & P_RLEAF ? NEXTINDEX(r) : rec_total(r), r->pgno);
+
+ h->lower = BTDATAOFF + 2 * sizeof(indx_t);
+
+ /* Unpin the root page, set to recno internal page. */
+ h->flags &= ~P_TYPE;
+ h->flags |= P_RINTERNAL;
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+ return (RET_SUCCESS);
+}
+
+/*
+ * BT_BROOT -- Fix up the btree root page after it has been split.
+ *
+ * Parameters:
+ * t: tree
+ * h: root page
+ * l: left page
+ * r: right page
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+static int
+bt_broot(BTREE *t, PAGE *h, PAGE *l, PAGE *r)
+{
+ BINTERNAL *bi;
+ BLEAF *bl;
+ u_int32_t nbytes;
+ char *dest;
+
+ /*
+ * If the root page was a leaf page, change it into an internal page.
+ * We copy the key we split on (but not the key's data, in the case of
+ * a leaf page) to the new root page.
+ *
+ * The btree comparison code guarantees that the left-most key on any
+ * level of the tree is never used, so it doesn't need to be filled in.
+ */
+ nbytes = NBINTERNAL(0);
+ h->linp[0] = h->upper = t->bt_psize - nbytes;
+ dest = (char *)h + h->upper;
+ WR_BINTERNAL(dest, 0, l->pgno, 0);
+
+ switch (h->flags & P_TYPE) {
+ case P_BLEAF:
+ bl = GETBLEAF(r, 0);
+ nbytes = NBINTERNAL(bl->ksize);
+ __PAST_END(h->linp, 1) = h->upper -= nbytes;
+ dest = (char *)h + h->upper;
+ WR_BINTERNAL(dest, bl->ksize, r->pgno, 0);
+ memmove(dest, bl->bytes, bl->ksize);
+
+ /*
+ * If the key is on an overflow page, mark the overflow chain
+ * so it isn't deleted when the leaf copy of the key is deleted.
+ */
+ if (bl->flags & P_BIGKEY &&
+ bt_preserve(t, *(pgno_t *)bl->bytes) == RET_ERROR)
+ return (RET_ERROR);
+ break;
+ case P_BINTERNAL:
+ bi = GETBINTERNAL(r, 0);
+ nbytes = NBINTERNAL(bi->ksize);
+ __PAST_END(h->linp, 1) = h->upper -= nbytes;
+ dest = (char *)h + h->upper;
+ memmove(dest, bi, nbytes);
+ ((BINTERNAL *)dest)->pgno = r->pgno;
+ break;
+ default:
+ abort();
+ }
+
+ /* There are two keys on the page. */
+ h->lower = BTDATAOFF + 2 * sizeof(indx_t);
+
+ /* Unpin the root page, set to btree internal page. */
+ h->flags &= ~P_TYPE;
+ h->flags |= P_BINTERNAL;
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+ return (RET_SUCCESS);
+}
+
+/*
+ * BT_PSPLIT -- Do the real work of splitting the page.
+ *
+ * Parameters:
+ * t: tree
+ * h: page to be split
+ * l: page to put lower half of data
+ * r: page to put upper half of data
+ * pskip: pointer to index to leave open
+ * ilen: insert length
+ *
+ * Returns:
+ * Pointer to page in which to insert.
+ */
+static PAGE *
+bt_psplit(BTREE *t, PAGE *h, PAGE *l, PAGE *r, indx_t *pskip, size_t ilen)
+{
+ BINTERNAL *bi;
+ BLEAF *bl;
+ CURSOR *c;
+ RLEAF *rl;
+ PAGE *rval;
+ void *src;
+ indx_t full, half, nxt, off, skip, top, used;
+ u_int32_t nbytes;
+ int bigkeycnt, isbigkey;
+
+ /*
+ * Split the data to the left and right pages. Leave the skip index
+ * open. Additionally, make some effort not to split on an overflow
+ * key. This makes internal page processing faster and can save
+ * space as overflow keys used by internal pages are never deleted.
+ */
+ bigkeycnt = 0;
+ skip = *pskip;
+ full = t->bt_psize - BTDATAOFF;
+ half = full / 2;
+ used = 0;
+ for (nxt = off = 0, top = NEXTINDEX(h); nxt < top; ++off) {
+ if (skip == off) {
+ nbytes = ilen;
+ isbigkey = 0; /* XXX: not really known. */
+ } else
+ switch (h->flags & P_TYPE) {
+ case P_BINTERNAL:
+ src = bi = GETBINTERNAL(h, nxt);
+ nbytes = NBINTERNAL(bi->ksize);
+ isbigkey = bi->flags & P_BIGKEY;
+ break;
+ case P_BLEAF:
+ src = bl = GETBLEAF(h, nxt);
+ nbytes = NBLEAF(bl);
+ isbigkey = bl->flags & P_BIGKEY;
+ break;
+ case P_RINTERNAL:
+ src = GETRINTERNAL(h, nxt);
+ nbytes = NRINTERNAL;
+ isbigkey = 0;
+ break;
+ case P_RLEAF:
+ src = rl = GETRLEAF(h, nxt);
+ nbytes = NRLEAF(rl);
+ isbigkey = 0;
+ break;
+ default:
+ abort();
+ }
+
+ /*
+ * If the key/data pairs are substantial fractions of the max
+ * possible size for the page, it's possible to get situations
+ * where we decide to try and copy too much onto the left page.
+ * Make sure that doesn't happen.
+ */
+ if ((skip <= off && used + nbytes + sizeof(indx_t) >= full) ||
+ nxt == top - 1) {
+ --off;
+ break;
+ }
+
+ /* Copy the key/data pair, if not the skipped index. */
+ if (skip != off) {
+ ++nxt;
+
+ l->linp[off] = l->upper -= nbytes;
+ memmove((char *)l + l->upper, src, nbytes);
+ }
+
+ used += nbytes + sizeof(indx_t);
+ if (used >= half) {
+ if (!isbigkey || bigkeycnt == 3)
+ break;
+ else
+ ++bigkeycnt;
+ }
+ }
+
+ /*
+ * Off is the last offset that's valid for the left page.
+ * Nxt is the first offset to be placed on the right page.
+ */
+ l->lower += (off + 1) * sizeof(indx_t);
+
+ /*
+ * If splitting the page that the cursor was on, the cursor has to be
+ * adjusted to point to the same record as before the split. If the
+ * cursor is at or past the skipped slot, the cursor is incremented by
+ * one. If the cursor is on the right page, it is decremented by the
+ * number of records split to the left page.
+ */
+ c = &t->bt_cursor;
+ if (F_ISSET(c, CURS_INIT) && c->pg.pgno == h->pgno) {
+ if (c->pg.index >= skip)
+ ++c->pg.index;
+ if (c->pg.index < nxt) /* Left page. */
+ c->pg.pgno = l->pgno;
+ else { /* Right page. */
+ c->pg.pgno = r->pgno;
+ c->pg.index -= nxt;
+ }
+ }
+
+ /*
+ * If the skipped index was on the left page, just return that page.
+ * Otherwise, adjust the skip index to reflect the new position on
+ * the right page.
+ */
+ if (skip <= off) {
+ skip = MAX_PAGE_OFFSET;
+ rval = l;
+ } else {
+ rval = r;
+ *pskip -= nxt;
+ }
+
+ for (off = 0; nxt < top; ++off) {
+ if (skip == nxt) {
+ ++off;
+ skip = MAX_PAGE_OFFSET;
+ }
+ switch (h->flags & P_TYPE) {
+ case P_BINTERNAL:
+ src = bi = GETBINTERNAL(h, nxt);
+ nbytes = NBINTERNAL(bi->ksize);
+ break;
+ case P_BLEAF:
+ src = bl = GETBLEAF(h, nxt);
+ nbytes = NBLEAF(bl);
+ break;
+ case P_RINTERNAL:
+ src = GETRINTERNAL(h, nxt);
+ nbytes = NRINTERNAL;
+ break;
+ case P_RLEAF:
+ src = rl = GETRLEAF(h, nxt);
+ nbytes = NRLEAF(rl);
+ break;
+ default:
+ abort();
+ }
+ ++nxt;
+ r->linp[off] = r->upper -= nbytes;
+ memmove((char *)r + r->upper, src, nbytes);
+ }
+ r->lower += off * sizeof(indx_t);
+
+ /* If the key is being appended to the page, adjust the index. */
+ if (skip == top)
+ r->lower += sizeof(indx_t);
+
+ return (rval);
+}
+
+/*
+ * BT_PRESERVE -- Mark a chain of pages as used by an internal node.
+ *
+ * Chains of indirect blocks pointed to by leaf nodes get reclaimed when the
+ * record that references them gets deleted. Chains pointed to by internal
+ * pages never get deleted. This routine marks a chain as pointed to by an
+ * internal page.
+ *
+ * Parameters:
+ * t: tree
+ * pg: page number of first page in the chain.
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+static int
+bt_preserve(BTREE *t, pgno_t pg)
+{
+ PAGE *h;
+
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ return (RET_ERROR);
+ h->flags |= P_PRESERVE;
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ return (RET_SUCCESS);
+}
+
+/*
+ * REC_TOTAL -- Return the number of recno entries below a page.
+ *
+ * Parameters:
+ * h: page
+ *
+ * Returns:
+ * The number of recno entries below a page.
+ *
+ * XXX
+ * These values could be set by the bt_psplit routine. The problem is that the
+ * entry has to be popped off of the stack etc. or the values have to be passed
+ * all the way back to bt_split/bt_rroot and it's not very clean.
+ */
+static recno_t
+rec_total(PAGE *h)
+{
+ recno_t recs;
+ indx_t nxt, top;
+
+ for (recs = 0, nxt = 0, top = NEXTINDEX(h); nxt < top; ++nxt)
+ recs += GETRINTERNAL(h, nxt)->nrecs;
+ return (recs);
+}
diff --git a/lib/libc/db/btree/bt_utils.c b/lib/libc/db/btree/bt_utils.c
new file mode 100644
index 0000000..92b76ba
--- /dev/null
+++ b/lib/libc/db/btree/bt_utils.c
@@ -0,0 +1,246 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bt_utils.c 8.8 (Berkeley) 7/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "btree.h"
+
+/*
+ * __bt_ret --
+ * Build return key/data pair.
+ *
+ * Parameters:
+ * t: tree
+ * e: key/data pair to be returned
+ * key: user's key structure (NULL if not to be filled in)
+ * rkey: memory area to hold key
+ * data: user's data structure (NULL if not to be filled in)
+ * rdata: memory area to hold data
+ * copy: always copy the key/data item
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+int
+__bt_ret(BTREE *t, EPG *e, DBT *key, DBT *rkey, DBT *data, DBT *rdata, int copy)
+{
+ BLEAF *bl;
+ void *p;
+
+ bl = GETBLEAF(e->page, e->index);
+
+ /*
+ * We must copy big keys/data to make them contigous. Otherwise,
+ * leave the page pinned and don't copy unless the user specified
+ * concurrent access.
+ */
+ if (key == NULL)
+ goto dataonly;
+
+ if (bl->flags & P_BIGKEY) {
+ if (__ovfl_get(t, bl->bytes,
+ &key->size, &rkey->data, &rkey->size))
+ return (RET_ERROR);
+ key->data = rkey->data;
+ } else if (copy || F_ISSET(t, B_DB_LOCK)) {
+ if (bl->ksize > rkey->size) {
+ p = realloc(rkey->data, bl->ksize);
+ if (p == NULL)
+ return (RET_ERROR);
+ rkey->data = p;
+ rkey->size = bl->ksize;
+ }
+ memmove(rkey->data, bl->bytes, bl->ksize);
+ key->size = bl->ksize;
+ key->data = rkey->data;
+ } else {
+ key->size = bl->ksize;
+ key->data = bl->bytes;
+ }
+
+dataonly:
+ if (data == NULL)
+ return (RET_SUCCESS);
+
+ if (bl->flags & P_BIGDATA) {
+ if (__ovfl_get(t, bl->bytes + bl->ksize,
+ &data->size, &rdata->data, &rdata->size))
+ return (RET_ERROR);
+ data->data = rdata->data;
+ } else if (copy || F_ISSET(t, B_DB_LOCK)) {
+ /* Use +1 in case the first record retrieved is 0 length. */
+ if (bl->dsize + 1 > rdata->size) {
+ p = realloc(rdata->data, bl->dsize + 1);
+ if (p == NULL)
+ return (RET_ERROR);
+ rdata->data = p;
+ rdata->size = bl->dsize + 1;
+ }
+ memmove(rdata->data, bl->bytes + bl->ksize, bl->dsize);
+ data->size = bl->dsize;
+ data->data = rdata->data;
+ } else {
+ data->size = bl->dsize;
+ data->data = bl->bytes + bl->ksize;
+ }
+
+ return (RET_SUCCESS);
+}
+
+/*
+ * __BT_CMP -- Compare a key to a given record.
+ *
+ * Parameters:
+ * t: tree
+ * k1: DBT pointer of first arg to comparison
+ * e: pointer to EPG for comparison
+ *
+ * Returns:
+ * < 0 if k1 is < record
+ * = 0 if k1 is = record
+ * > 0 if k1 is > record
+ */
+int
+__bt_cmp(BTREE *t, const DBT *k1, EPG *e)
+{
+ BINTERNAL *bi;
+ BLEAF *bl;
+ DBT k2;
+ PAGE *h;
+ void *bigkey;
+
+ /*
+ * The left-most key on internal pages, at any level of the tree, is
+ * guaranteed by the following code to be less than any user key.
+ * This saves us from having to update the leftmost key on an internal
+ * page when the user inserts a new key in the tree smaller than
+ * anything we've yet seen.
+ */
+ h = e->page;
+ if (e->index == 0 && h->prevpg == P_INVALID && !(h->flags & P_BLEAF))
+ return (1);
+
+ bigkey = NULL;
+ if (h->flags & P_BLEAF) {
+ bl = GETBLEAF(h, e->index);
+ if (bl->flags & P_BIGKEY)
+ bigkey = bl->bytes;
+ else {
+ k2.data = bl->bytes;
+ k2.size = bl->ksize;
+ }
+ } else {
+ bi = GETBINTERNAL(h, e->index);
+ if (bi->flags & P_BIGKEY)
+ bigkey = bi->bytes;
+ else {
+ k2.data = bi->bytes;
+ k2.size = bi->ksize;
+ }
+ }
+
+ if (bigkey) {
+ if (__ovfl_get(t, bigkey,
+ &k2.size, &t->bt_rdata.data, &t->bt_rdata.size))
+ return (RET_ERROR);
+ k2.data = t->bt_rdata.data;
+ }
+ return ((*t->bt_cmp)(k1, &k2));
+}
+
+/*
+ * __BT_DEFCMP -- Default comparison routine.
+ *
+ * Parameters:
+ * a: DBT #1
+ * b: DBT #2
+ *
+ * Returns:
+ * < 0 if a is < b
+ * = 0 if a is = b
+ * > 0 if a is > b
+ */
+int
+__bt_defcmp(const DBT *a, const DBT *b)
+{
+ size_t len;
+ u_char *p1, *p2;
+
+ /*
+ * XXX
+ * If a size_t doesn't fit in an int, this routine can lose.
+ * What we need is an integral type which is guaranteed to be
+ * larger than a size_t, and there is no such thing.
+ */
+ len = MIN(a->size, b->size);
+ for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2)
+ if (*p1 != *p2)
+ return ((int)*p1 - (int)*p2);
+ return ((int)a->size - (int)b->size);
+}
+
+/*
+ * __BT_DEFPFX -- Default prefix routine.
+ *
+ * Parameters:
+ * a: DBT #1
+ * b: DBT #2
+ *
+ * Returns:
+ * Number of bytes needed to distinguish b from a.
+ */
+size_t
+__bt_defpfx(const DBT *a, const DBT *b)
+{
+ u_char *p1, *p2;
+ size_t cnt, len;
+
+ cnt = 1;
+ len = MIN(a->size, b->size);
+ for (p1 = a->data, p2 = b->data; len--; ++p1, ++p2, ++cnt)
+ if (*p1 != *p2)
+ return (cnt);
+
+ /* a->size must be <= b->size, or they wouldn't be in this order. */
+ return (a->size < b->size ? a->size + 1 : a->size);
+}
diff --git a/lib/libc/db/btree/btree.h b/lib/libc/db/btree/btree.h
new file mode 100644
index 0000000..a1766dc
--- /dev/null
+++ b/lib/libc/db/btree/btree.h
@@ -0,0 +1,380 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)btree.h 8.11 (Berkeley) 8/17/94
+ * $FreeBSD$
+ */
+
+/* Macros to set/clear/test flags. */
+#define F_SET(p, f) (p)->flags |= (f)
+#define F_CLR(p, f) (p)->flags &= ~(f)
+#define F_ISSET(p, f) ((p)->flags & (f))
+
+#include <mpool.h>
+
+#define DEFMINKEYPAGE (2) /* Minimum keys per page */
+#define MINCACHE (5) /* Minimum cached pages */
+#define MINPSIZE (512) /* Minimum page size */
+
+/*
+ * Page 0 of a btree file contains a copy of the meta-data. This page is also
+ * used as an out-of-band page, i.e. page pointers that point to nowhere point
+ * to page 0. Page 1 is the root of the btree.
+ */
+#define P_INVALID 0 /* Invalid tree page number. */
+#define P_META 0 /* Tree metadata page number. */
+#define P_ROOT 1 /* Tree root page number. */
+
+/*
+ * There are five page layouts in the btree: btree internal pages (BINTERNAL),
+ * btree leaf pages (BLEAF), recno internal pages (RINTERNAL), recno leaf pages
+ * (RLEAF) and overflow pages. All five page types have a page header (PAGE).
+ * This implementation requires that values within structures NOT be padded.
+ * (ANSI C permits random padding.) If your compiler pads randomly you'll have
+ * to do some work to get this package to run.
+ */
+typedef struct _page {
+ pgno_t pgno; /* this page's page number */
+ pgno_t prevpg; /* left sibling */
+ pgno_t nextpg; /* right sibling */
+
+#define P_BINTERNAL 0x01 /* btree internal page */
+#define P_BLEAF 0x02 /* leaf page */
+#define P_OVERFLOW 0x04 /* overflow page */
+#define P_RINTERNAL 0x08 /* recno internal page */
+#define P_RLEAF 0x10 /* leaf page */
+#define P_TYPE 0x1f /* type mask */
+#define P_PRESERVE 0x20 /* never delete this chain of pages */
+ u_int32_t flags;
+
+ indx_t lower; /* lower bound of free space on page */
+ indx_t upper; /* upper bound of free space on page */
+ indx_t linp[1]; /* indx_t-aligned VAR. LENGTH DATA */
+} PAGE;
+
+/* First and next index. */
+#define BTDATAOFF \
+ (sizeof(pgno_t) + sizeof(pgno_t) + sizeof(pgno_t) + \
+ sizeof(u_int32_t) + sizeof(indx_t) + sizeof(indx_t))
+#define NEXTINDEX(p) (((p)->lower - BTDATAOFF) / sizeof(indx_t))
+
+/*
+ * For pages other than overflow pages, there is an array of offsets into the
+ * rest of the page immediately following the page header. Each offset is to
+ * an item which is unique to the type of page. The h_lower offset is just
+ * past the last filled-in index. The h_upper offset is the first item on the
+ * page. Offsets are from the beginning of the page.
+ *
+ * If an item is too big to store on a single page, a flag is set and the item
+ * is a { page, size } pair such that the page is the first page of an overflow
+ * chain with size bytes of item. Overflow pages are simply bytes without any
+ * external structure.
+ *
+ * The page number and size fields in the items are pgno_t-aligned so they can
+ * be manipulated without copying. (This presumes that 32 bit items can be
+ * manipulated on this system.)
+ */
+#define LALIGN(n) (((n) + sizeof(pgno_t) - 1) & ~(sizeof(pgno_t) - 1))
+#define NOVFLSIZE (sizeof(pgno_t) + sizeof(u_int32_t))
+
+/*
+ * For the btree internal pages, the item is a key. BINTERNALs are {key, pgno}
+ * pairs, such that the key compares less than or equal to all of the records
+ * on that page. For a tree without duplicate keys, an internal page with two
+ * consecutive keys, a and b, will have all records greater than or equal to a
+ * and less than b stored on the page associated with a. Duplicate keys are
+ * somewhat special and can cause duplicate internal and leaf page records and
+ * some minor modifications of the above rule.
+ */
+typedef struct _binternal {
+ u_int32_t ksize; /* key size */
+ pgno_t pgno; /* page number stored on */
+#define P_BIGDATA 0x01 /* overflow data */
+#define P_BIGKEY 0x02 /* overflow key */
+ u_char flags;
+ char bytes[1]; /* data */
+} BINTERNAL;
+
+/* Get the page's BINTERNAL structure at index indx. */
+#define GETBINTERNAL(pg, indx) \
+ ((BINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NBINTERNAL(len) \
+ LALIGN(sizeof(u_int32_t) + sizeof(pgno_t) + sizeof(u_char) + (len))
+
+/* Copy a BINTERNAL entry to the page. */
+#define WR_BINTERNAL(p, size, pgno, flags) { \
+ *(u_int32_t *)p = size; \
+ p += sizeof(u_int32_t); \
+ *(pgno_t *)p = pgno; \
+ p += sizeof(pgno_t); \
+ *(u_char *)p = flags; \
+ p += sizeof(u_char); \
+}
+
+/*
+ * For the recno internal pages, the item is a page number with the number of
+ * keys found on that page and below.
+ */
+typedef struct _rinternal {
+ recno_t nrecs; /* number of records */
+ pgno_t pgno; /* page number stored below */
+} RINTERNAL;
+
+/* Get the page's RINTERNAL structure at index indx. */
+#define GETRINTERNAL(pg, indx) \
+ ((RINTERNAL *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NRINTERNAL \
+ LALIGN(sizeof(recno_t) + sizeof(pgno_t))
+
+/* Copy a RINTERAL entry to the page. */
+#define WR_RINTERNAL(p, nrecs, pgno) { \
+ *(recno_t *)p = nrecs; \
+ p += sizeof(recno_t); \
+ *(pgno_t *)p = pgno; \
+}
+
+/* For the btree leaf pages, the item is a key and data pair. */
+typedef struct _bleaf {
+ u_int32_t ksize; /* size of key */
+ u_int32_t dsize; /* size of data */
+ u_char flags; /* P_BIGDATA, P_BIGKEY */
+ char bytes[1]; /* data */
+} BLEAF;
+
+/* Get the page's BLEAF structure at index indx. */
+#define GETBLEAF(pg, indx) \
+ ((BLEAF *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NBLEAF(p) NBLEAFDBT((p)->ksize, (p)->dsize)
+
+/* Get the number of bytes in the user's key/data pair. */
+#define NBLEAFDBT(ksize, dsize) \
+ LALIGN(sizeof(u_int32_t) + sizeof(u_int32_t) + sizeof(u_char) + \
+ (ksize) + (dsize))
+
+/* Copy a BLEAF entry to the page. */
+#define WR_BLEAF(p, key, data, flags) { \
+ *(u_int32_t *)p = key->size; \
+ p += sizeof(u_int32_t); \
+ *(u_int32_t *)p = data->size; \
+ p += sizeof(u_int32_t); \
+ *(u_char *)p = flags; \
+ p += sizeof(u_char); \
+ memmove(p, key->data, key->size); \
+ p += key->size; \
+ memmove(p, data->data, data->size); \
+}
+
+/* For the recno leaf pages, the item is a data entry. */
+typedef struct _rleaf {
+ u_int32_t dsize; /* size of data */
+ u_char flags; /* P_BIGDATA */
+ char bytes[1];
+} RLEAF;
+
+/* Get the page's RLEAF structure at index indx. */
+#define GETRLEAF(pg, indx) \
+ ((RLEAF *)((char *)(pg) + (pg)->linp[indx]))
+
+/* Get the number of bytes in the entry. */
+#define NRLEAF(p) NRLEAFDBT((p)->dsize)
+
+/* Get the number of bytes from the user's data. */
+#define NRLEAFDBT(dsize) \
+ LALIGN(sizeof(u_int32_t) + sizeof(u_char) + (dsize))
+
+/* Copy a RLEAF entry to the page. */
+#define WR_RLEAF(p, data, flags) { \
+ *(u_int32_t *)p = data->size; \
+ p += sizeof(u_int32_t); \
+ *(u_char *)p = flags; \
+ p += sizeof(u_char); \
+ memmove(p, data->data, data->size); \
+}
+
+/*
+ * A record in the tree is either a pointer to a page and an index in the page
+ * or a page number and an index. These structures are used as a cursor, stack
+ * entry and search returns as well as to pass records to other routines.
+ *
+ * One comment about searches. Internal page searches must find the largest
+ * record less than key in the tree so that descents work. Leaf page searches
+ * must find the smallest record greater than key so that the returned index
+ * is the record's correct position for insertion.
+ */
+typedef struct _epgno {
+ pgno_t pgno; /* the page number */
+ indx_t index; /* the index on the page */
+} EPGNO;
+
+typedef struct _epg {
+ PAGE *page; /* the (pinned) page */
+ indx_t index; /* the index on the page */
+} EPG;
+
+/*
+ * About cursors. The cursor (and the page that contained the key/data pair
+ * that it referenced) can be deleted, which makes things a bit tricky. If
+ * there are no duplicates of the cursor key in the tree (i.e. B_NODUPS is set
+ * or there simply aren't any duplicates of the key) we copy the key that it
+ * referenced when it's deleted, and reacquire a new cursor key if the cursor
+ * is used again. If there are duplicates keys, we move to the next/previous
+ * key, and set a flag so that we know what happened. NOTE: if duplicate (to
+ * the cursor) keys are added to the tree during this process, it is undefined
+ * if they will be returned or not in a cursor scan.
+ *
+ * The flags determine the possible states of the cursor:
+ *
+ * CURS_INIT The cursor references *something*.
+ * CURS_ACQUIRE The cursor was deleted, and a key has been saved so that
+ * we can reacquire the right position in the tree.
+ * CURS_AFTER, CURS_BEFORE
+ * The cursor was deleted, and now references a key/data pair
+ * that has not yet been returned, either before or after the
+ * deleted key/data pair.
+ * XXX
+ * This structure is broken out so that we can eventually offer multiple
+ * cursors as part of the DB interface.
+ */
+typedef struct _cursor {
+ EPGNO pg; /* B: Saved tree reference. */
+ DBT key; /* B: Saved key, or key.data == NULL. */
+ recno_t rcursor; /* R: recno cursor (1-based) */
+
+#define CURS_ACQUIRE 0x01 /* B: Cursor needs to be reacquired. */
+#define CURS_AFTER 0x02 /* B: Unreturned cursor after key. */
+#define CURS_BEFORE 0x04 /* B: Unreturned cursor before key. */
+#define CURS_INIT 0x08 /* RB: Cursor initialized. */
+ u_int8_t flags;
+} CURSOR;
+
+/*
+ * The metadata of the tree. The nrecs field is used only by the RECNO code.
+ * This is because the btree doesn't really need it and it requires that every
+ * put or delete call modify the metadata.
+ */
+typedef struct _btmeta {
+ u_int32_t magic; /* magic number */
+ u_int32_t version; /* version */
+ u_int32_t psize; /* page size */
+ u_int32_t free; /* page number of first free page */
+ u_int32_t nrecs; /* R: number of records */
+
+#define SAVEMETA (B_NODUPS | R_RECNO)
+ u_int32_t flags; /* bt_flags & SAVEMETA */
+} BTMETA;
+
+/* The in-memory btree/recno data structure. */
+typedef struct _btree {
+ MPOOL *bt_mp; /* memory pool cookie */
+
+ DB *bt_dbp; /* pointer to enclosing DB */
+
+ EPG bt_cur; /* current (pinned) page */
+ PAGE *bt_pinned; /* page pinned across calls */
+
+ CURSOR bt_cursor; /* cursor */
+
+#define BT_PUSH(t, p, i) { \
+ t->bt_sp->pgno = p; \
+ t->bt_sp->index = i; \
+ ++t->bt_sp; \
+}
+#define BT_POP(t) (t->bt_sp == t->bt_stack ? NULL : --t->bt_sp)
+#define BT_CLR(t) (t->bt_sp = t->bt_stack)
+ EPGNO bt_stack[50]; /* stack of parent pages */
+ EPGNO *bt_sp; /* current stack pointer */
+
+ DBT bt_rkey; /* returned key */
+ DBT bt_rdata; /* returned data */
+
+ int bt_fd; /* tree file descriptor */
+
+ pgno_t bt_free; /* next free page */
+ u_int32_t bt_psize; /* page size */
+ indx_t bt_ovflsize; /* cut-off for key/data overflow */
+ int bt_lorder; /* byte order */
+ /* sorted order */
+ enum { NOT, BACK, FORWARD } bt_order;
+ EPGNO bt_last; /* last insert */
+
+ /* B: key comparison function */
+ int (*bt_cmp)(const DBT *, const DBT *);
+ /* B: prefix comparison function */
+ size_t (*bt_pfx)(const DBT *, const DBT *);
+ /* R: recno input function */
+ int (*bt_irec)(struct _btree *, recno_t);
+
+ FILE *bt_rfp; /* R: record FILE pointer */
+ int bt_rfd; /* R: record file descriptor */
+
+ caddr_t bt_cmap; /* R: current point in mapped space */
+ caddr_t bt_smap; /* R: start of mapped space */
+ caddr_t bt_emap; /* R: end of mapped space */
+ size_t bt_msize; /* R: size of mapped region. */
+
+ recno_t bt_nrecs; /* R: number of records */
+ size_t bt_reclen; /* R: fixed record length */
+ u_char bt_bval; /* R: delimiting byte/pad character */
+
+/*
+ * NB:
+ * B_NODUPS and R_RECNO are stored on disk, and may not be changed.
+ */
+#define B_INMEM 0x00001 /* in-memory tree */
+#define B_METADIRTY 0x00002 /* need to write metadata */
+#define B_MODIFIED 0x00004 /* tree modified */
+#define B_NEEDSWAP 0x00008 /* if byte order requires swapping */
+#define B_RDONLY 0x00010 /* read-only tree */
+
+#define B_NODUPS 0x00020 /* no duplicate keys permitted */
+#define R_RECNO 0x00080 /* record oriented tree */
+
+#define R_CLOSEFP 0x00040 /* opened a file pointer */
+#define R_EOF 0x00100 /* end of input file reached. */
+#define R_FIXLEN 0x00200 /* fixed length records */
+#define R_MEMMAPPED 0x00400 /* memory mapped file. */
+#define R_INMEM 0x00800 /* in-memory file */
+#define R_MODIFIED 0x01000 /* modified file */
+#define R_RDONLY 0x02000 /* read-only file */
+
+#define B_DB_LOCK 0x04000 /* DB_LOCK specified. */
+#define B_DB_SHMEM 0x08000 /* DB_SHMEM specified. */
+#define B_DB_TXN 0x10000 /* DB_TXN specified. */
+ u_int32_t flags;
+} BTREE;
+
+#include "extern.h"
diff --git a/lib/libc/db/btree/extern.h b/lib/libc/db/btree/extern.h
new file mode 100644
index 0000000..0abd594
--- /dev/null
+++ b/lib/libc/db/btree/extern.h
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)extern.h 8.10 (Berkeley) 7/20/94
+ * $FreeBSD$
+ */
+
+int __bt_close(DB *);
+int __bt_cmp(BTREE *, const DBT *, EPG *);
+int __bt_crsrdel(BTREE *, EPGNO *);
+int __bt_defcmp(const DBT *, const DBT *);
+size_t __bt_defpfx(const DBT *, const DBT *);
+int __bt_delete(const DB *, const DBT *, u_int);
+int __bt_dleaf(BTREE *, const DBT *, PAGE *, u_int);
+int __bt_fd(const DB *);
+int __bt_free(BTREE *, PAGE *);
+int __bt_get(const DB *, const DBT *, DBT *, u_int);
+PAGE *__bt_new(BTREE *, pgno_t *);
+void __bt_pgin(void *, pgno_t, void *);
+void __bt_pgout(void *, pgno_t, void *);
+int __bt_push(BTREE *, pgno_t, int);
+int __bt_put(const DB *dbp, DBT *, const DBT *, u_int);
+int __bt_ret(BTREE *, EPG *, DBT *, DBT *, DBT *, DBT *, int);
+EPG *__bt_search(BTREE *, const DBT *, int *);
+int __bt_seq(const DB *, DBT *, DBT *, u_int);
+void __bt_setcur(BTREE *, pgno_t, u_int);
+int __bt_split(BTREE *, PAGE *,
+ const DBT *, const DBT *, int, size_t, u_int32_t);
+int __bt_sync(const DB *, u_int);
+
+int __ovfl_delete(BTREE *, void *);
+int __ovfl_get(BTREE *, void *, size_t *, void **, size_t *);
+int __ovfl_put(BTREE *, const DBT *, pgno_t *);
+
+#ifdef DEBUG
+void __bt_dnpage(DB *, pgno_t);
+void __bt_dpage(PAGE *);
+void __bt_dump(DB *);
+#endif
+#ifdef STATISTICS
+void __bt_stat(DB *);
+#endif
diff --git a/lib/libc/db/changelog b/lib/libc/db/changelog
new file mode 100644
index 0000000..1540ca8
--- /dev/null
+++ b/lib/libc/db/changelog
@@ -0,0 +1,103 @@
+1.84 -> 1.85
+ recno: #ifdef out use of mmap, it's not portable enough.
+
+1.83 -> 1.84 Thu Aug 18 15:46:07 EDT 1994
+ recno: Rework fixed-length records so that closing and reopening
+ the file now works. Pad short records on input. Never do
+ signed comparison in recno input reading functions.
+
+1.82 -> 1.83 Tue Jul 26 15:33:44 EDT 1994
+ btree: Rework cursor deletion code yet again; bugs with
+ deleting empty pages that only contained the cursor
+ record.
+
+1.81 -> 1.82 Sat Jul 16 11:01:50 EDT 1994
+ btree: Fix bugs introduced by new cursor/deletion code.
+ Replace return kbuf/dbuf with real DBT's.
+
+1.80 -> 1.81
+ btree: Fix bugs introduced by new cursor/deletion code.
+ all: Add #defines for Purify.
+
+1.79 -> 1.80 Wed Jul 13 22:41:54 EDT 1994
+ btree Change deletion to coalesce empty pages. This is a major
+ change, cursors and duplicate pages all had to be reworked.
+ Return to a fixed stack.
+ recno: Affected by cursor changes. New cursor structures should
+ permit multiple cursors in the future.
+
+1.78 -> 1.79 Mon Jun 20 17:36:47 EDT 1994
+ all: Minor cleanups of 1.78 for porting reasons; only
+ major change was inlining check of NULL pointer
+ so that __fix_realloc goes away.
+
+1.77 -> 1.78 Thu Jun 16 19:06:43 EDT 1994
+ all: Move "standard" size typedef's into db.h.
+
+1.76 -> 1.77 Thu Jun 16 16:48:38 EDT 1994
+ hash: Delete __init_ routine, has special meaning to OSF 2.0.
+
+1.74 -> 1.76
+ all: Finish up the port to the Alpha.
+
+1.73 -> 1.74
+ recno: Don't put the record if rec_search fails, in rec_rdelete.
+ Create fixed-length intermediate records past "end" of DB
+ correctly.
+ Realloc bug when reading in fixed records.
+ all: First cut at port to Alpha (64-bit architecture) using
+ 4.4BSD basic integral types typedef's.
+ Cast allocation pointers to shut up old compilers.
+ Rework PORT directory into OS/machine directories.
+
+1.72 -> 1.73
+ btree: If enough duplicate records were inserted and then deleted
+ that internal pages had references to empty pages of the
+ duplicate keys, the search function ended up on the wrong
+ page.
+
+1.7 -> 1.72 12 Oct 1993
+ hash: Support NET/2 hash formats.
+
+1.7 -> 1.71 16 Sep 1993
+ btree/recno:
+ Fix bug in internal search routines that caused
+ return of invalid pointers.
+
+1.6 -> 1.7 07 Sep 1993
+ hash: Fixed big key overflow bugs.
+ test: Portability hacks, rewrite test script, Makefile.
+ btree/recno:
+ Stop copying non-overflow key/data pairs.
+ PORT: Break PORT directory up into per architecture/OS
+ subdirectories.
+
+1.5 -> 1.6 06 Jun 1993
+ hash: In PAIRFITS, the first comparison should look at (P)[2].
+ The hash_realloc function was walking off the end of memory.
+ The overflow page number was wrong when bumping splitpoint.
+
+1.4 -> 1.5 23 May 1993
+ hash: Set hash default fill factor dynamically.
+ recno: Fixed bug in sorted page splits.
+ Add page size parameter support.
+ Allow recno to specify the name of the underlying btree;
+ used for vi recovery.
+ btree/recno:
+ Support 64K pages.
+ btree/hash/recno:
+ Provide access to an underlying file descriptor.
+ Change sync routines to take a flag argument, recno
+ uses this to sync out the underlying btree.
+
+1.3 -> 1.4 10 May 1993
+ recno: Delete the R_CURSORLOG flag from the recno interface.
+ Zero-length record fix for non-mmap reads.
+ Try and make SIZE_T_MAX test in open portable.
+
+1.2 -> 1.3 01 May 1993
+ btree: Ignore user byte-order setting when reading already
+ existing database. Fixes to byte-order conversions.
+
+1.1 -> 1.2 15 Apr 1993
+ No bug fixes, only compatibility hacks.
diff --git a/lib/libc/db/db/Makefile.inc b/lib/libc/db/db/Makefile.inc
new file mode 100644
index 0000000..2bbac4e
--- /dev/null
+++ b/lib/libc/db/db/Makefile.inc
@@ -0,0 +1,6 @@
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/db/db
+
+SRCS+= db.c
diff --git a/lib/libc/db/db/db.c b/lib/libc/db/db/db.c
new file mode 100644
index 0000000..3cfd0a9
--- /dev/null
+++ b/lib/libc/db/db/db.c
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)db.c 8.4 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stddef.h>
+#include <stdio.h>
+
+#include <db.h>
+
+static int __dberr(void);
+
+DB *
+dbopen(const char *fname, int flags, int mode, DBTYPE type, const void *openinfo)
+{
+
+#define DB_FLAGS (DB_LOCK | DB_SHMEM | DB_TXN)
+#define USE_OPEN_FLAGS \
+ (O_CREAT | O_EXCL | O_EXLOCK | O_NOFOLLOW | O_NONBLOCK | \
+ O_RDONLY | O_RDWR | O_SHLOCK | O_SYNC | O_TRUNC)
+
+ if ((flags & ~(USE_OPEN_FLAGS | DB_FLAGS)) == 0)
+ switch (type) {
+ case DB_BTREE:
+ return (__bt_open(fname, flags & USE_OPEN_FLAGS,
+ mode, openinfo, flags & DB_FLAGS));
+ case DB_HASH:
+ return (__hash_open(fname, flags & USE_OPEN_FLAGS,
+ mode, openinfo, flags & DB_FLAGS));
+ case DB_RECNO:
+ return (__rec_open(fname, flags & USE_OPEN_FLAGS,
+ mode, openinfo, flags & DB_FLAGS));
+ }
+ errno = EINVAL;
+ return (NULL);
+}
+
+static int
+__dberr(void)
+{
+ return (RET_ERROR);
+}
+
+/*
+ * __DBPANIC -- Stop.
+ *
+ * Parameters:
+ * dbp: pointer to the DB structure.
+ */
+void
+__dbpanic(DB *dbp)
+{
+ /* The only thing that can succeed is a close. */
+ dbp->del = (int (*)(const struct __db *, const DBT*, u_int))__dberr;
+ dbp->fd = (int (*)(const struct __db *))__dberr;
+ dbp->get = (int (*)(const struct __db *, const DBT*, DBT *, u_int))__dberr;
+ dbp->put = (int (*)(const struct __db *, DBT *, const DBT *, u_int))__dberr;
+ dbp->seq = (int (*)(const struct __db *, DBT *, DBT *, u_int))__dberr;
+ dbp->sync = (int (*)(const struct __db *, u_int))__dberr;
+}
diff --git a/lib/libc/db/docs/hash.usenix.ps b/lib/libc/db/docs/hash.usenix.ps
new file mode 100644
index 0000000..3a0cf44
--- /dev/null
+++ b/lib/libc/db/docs/hash.usenix.ps
@@ -0,0 +1,12209 @@
+%!PS-Adobe-1.0
+%%Creator: utopia:margo (& Seltzer,608-13E,8072,)
+%%Title: stdin (ditroff)
+%%CreationDate: Tue Dec 11 15:06:45 1990
+%%EndComments
+% @(#)psdit.pro 1.3 4/15/88
+% lib/psdit.pro -- prolog for psdit (ditroff) files
+% Copyright (c) 1984, 1985 Adobe Systems Incorporated. All Rights Reserved.
+% last edit: shore Sat Nov 23 20:28:03 1985
+% RCSID: $FreeBSD$
+
+% Changed by Edward Wang (edward@ucbarpa.berkeley.edu) to handle graphics,
+% 17 Feb, 87.
+
+/$DITroff 140 dict def $DITroff begin
+/fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def
+/xi{0 72 11 mul translate 72 resolution div dup neg scale 0 0 moveto
+ /fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def F
+ /pagesave save def}def
+/PB{save /psv exch def currentpoint translate
+ resolution 72 div dup neg scale 0 0 moveto}def
+/PE{psv restore}def
+/arctoobig 90 def /arctoosmall .05 def
+/m1 matrix def /m2 matrix def /m3 matrix def /oldmat matrix def
+/tan{dup sin exch cos div}def
+/point{resolution 72 div mul}def
+/dround {transform round exch round exch itransform}def
+/xT{/devname exch def}def
+/xr{/mh exch def /my exch def /resolution exch def}def
+/xp{}def
+/xs{docsave restore end}def
+/xt{}def
+/xf{/fontname exch def /slotno exch def fontnames slotno get fontname eq not
+ {fonts slotno fontname findfont put fontnames slotno fontname put}if}def
+/xH{/fontheight exch def F}def
+/xS{/fontslant exch def F}def
+/s{/fontsize exch def /fontheight fontsize def F}def
+/f{/fontnum exch def F}def
+/F{fontheight 0 le{/fontheight fontsize def}if
+ fonts fontnum get fontsize point 0 0 fontheight point neg 0 0 m1 astore
+ fontslant 0 ne{1 0 fontslant tan 1 0 0 m2 astore m3 concatmatrix}if
+ makefont setfont .04 fontsize point mul 0 dround pop setlinewidth}def
+/X{exch currentpoint exch pop moveto show}def
+/N{3 1 roll moveto show}def
+/Y{exch currentpoint pop exch moveto show}def
+/S{show}def
+/ditpush{}def/ditpop{}def
+/AX{3 -1 roll currentpoint exch pop moveto 0 exch ashow}def
+/AN{4 2 roll moveto 0 exch ashow}def
+/AY{3 -1 roll currentpoint pop exch moveto 0 exch ashow}def
+/AS{0 exch ashow}def
+/MX{currentpoint exch pop moveto}def
+/MY{currentpoint pop exch moveto}def
+/MXY{moveto}def
+/cb{pop}def % action on unknown char -- nothing for now
+/n{}def/w{}def
+/p{pop showpage pagesave restore /pagesave save def}def
+/Dt{/Dlinewidth exch def}def 1 Dt
+/Ds{/Ddash exch def}def -1 Ds
+/Di{/Dstipple exch def}def 1 Di
+/Dsetlinewidth{2 Dlinewidth mul setlinewidth}def
+/Dsetdash{Ddash 4 eq{[8 12]}{Ddash 16 eq{[32 36]}
+ {Ddash 20 eq{[32 12 8 12]}{[]}ifelse}ifelse}ifelse 0 setdash}def
+/Dstroke{gsave Dsetlinewidth Dsetdash 1 setlinecap stroke grestore
+ currentpoint newpath moveto}def
+/Dl{rlineto Dstroke}def
+/arcellipse{/diamv exch def /diamh exch def oldmat currentmatrix pop
+ currentpoint translate 1 diamv diamh div scale /rad diamh 2 div def
+ currentpoint exch rad add exch rad -180 180 arc oldmat setmatrix}def
+/Dc{dup arcellipse Dstroke}def
+/De{arcellipse Dstroke}def
+/Da{/endv exch def /endh exch def /centerv exch def /centerh exch def
+ /cradius centerv centerv mul centerh centerh mul add sqrt def
+ /eradius endv endv mul endh endh mul add sqrt def
+ /endang endv endh atan def
+ /startang centerv neg centerh neg atan def
+ /sweep startang endang sub dup 0 lt{360 add}if def
+ sweep arctoobig gt
+ {/midang startang sweep 2 div sub def /midrad cradius eradius add 2 div def
+ /midh midang cos midrad mul def /midv midang sin midrad mul def
+ midh neg midv neg endh endv centerh centerv midh midv Da
+ Da}
+ {sweep arctoosmall ge
+ {/controldelt 1 sweep 2 div cos sub 3 sweep 2 div sin mul div 4 mul def
+ centerv neg controldelt mul centerh controldelt mul
+ endv neg controldelt mul centerh add endh add
+ endh controldelt mul centerv add endv add
+ centerh endh add centerv endv add rcurveto Dstroke}
+ {centerh endh add centerv endv add rlineto Dstroke}
+ ifelse}
+ ifelse}def
+/Dpatterns[
+[%cf[widthbits]
+[8<0000000000000010>]
+[8<0411040040114000>]
+[8<0204081020408001>]
+[8<0000103810000000>]
+[8<6699996666999966>]
+[8<0000800100001008>]
+[8<81c36666c3810000>]
+[8<0f0e0c0800000000>]
+[8<0000000000000010>]
+[8<0411040040114000>]
+[8<0204081020408001>]
+[8<0000001038100000>]
+[8<6699996666999966>]
+[8<0000800100001008>]
+[8<81c36666c3810000>]
+[8<0f0e0c0800000000>]
+[8<0042660000246600>]
+[8<0000990000990000>]
+[8<0804020180402010>]
+[8<2418814242811824>]
+[8<6699996666999966>]
+[8<8000000008000000>]
+[8<00001c3e363e1c00>]
+[8<0000000000000000>]
+[32<00000040000000c00000004000000040000000e0000000000000000000000000>]
+[32<00000000000060000000900000002000000040000000f0000000000000000000>]
+[32<000000000000000000e0000000100000006000000010000000e0000000000000>]
+[32<00000000000000002000000060000000a0000000f00000002000000000000000>]
+[32<0000000e0000000000000000000000000000000f000000080000000e00000001>]
+[32<0000090000000600000000000000000000000000000007000000080000000e00>]
+[32<00010000000200000004000000040000000000000000000000000000000f0000>]
+[32<0900000006000000090000000600000000000000000000000000000006000000>]]
+[%ug
+[8<0000020000000000>]
+[8<0000020000002000>]
+[8<0004020000002000>]
+[8<0004020000402000>]
+[8<0004060000402000>]
+[8<0004060000406000>]
+[8<0006060000406000>]
+[8<0006060000606000>]
+[8<00060e0000606000>]
+[8<00060e000060e000>]
+[8<00070e000060e000>]
+[8<00070e000070e000>]
+[8<00070e020070e000>]
+[8<00070e020070e020>]
+[8<04070e020070e020>]
+[8<04070e024070e020>]
+[8<04070e064070e020>]
+[8<04070e064070e060>]
+[8<06070e064070e060>]
+[8<06070e066070e060>]
+[8<06070f066070e060>]
+[8<06070f066070f060>]
+[8<060f0f066070f060>]
+[8<060f0f0660f0f060>]
+[8<060f0f0760f0f060>]
+[8<060f0f0760f0f070>]
+[8<0e0f0f0760f0f070>]
+[8<0e0f0f07e0f0f070>]
+[8<0e0f0f0fe0f0f070>]
+[8<0e0f0f0fe0f0f0f0>]
+[8<0f0f0f0fe0f0f0f0>]
+[8<0f0f0f0ff0f0f0f0>]
+[8<1f0f0f0ff0f0f0f0>]
+[8<1f0f0f0ff1f0f0f0>]
+[8<1f0f0f8ff1f0f0f0>]
+[8<1f0f0f8ff1f0f0f8>]
+[8<9f0f0f8ff1f0f0f8>]
+[8<9f0f0f8ff9f0f0f8>]
+[8<9f0f0f9ff9f0f0f8>]
+[8<9f0f0f9ff9f0f0f9>]
+[8<9f8f0f9ff9f0f0f9>]
+[8<9f8f0f9ff9f8f0f9>]
+[8<9f8f1f9ff9f8f0f9>]
+[8<9f8f1f9ff9f8f1f9>]
+[8<bf8f1f9ff9f8f1f9>]
+[8<bf8f1f9ffbf8f1f9>]
+[8<bf8f1fdffbf8f1f9>]
+[8<bf8f1fdffbf8f1fd>]
+[8<ff8f1fdffbf8f1fd>]
+[8<ff8f1fdffff8f1fd>]
+[8<ff8f1ffffff8f1fd>]
+[8<ff8f1ffffff8f1ff>]
+[8<ff9f1ffffff8f1ff>]
+[8<ff9f1ffffff9f1ff>]
+[8<ff9f9ffffff9f1ff>]
+[8<ff9f9ffffff9f9ff>]
+[8<ffbf9ffffff9f9ff>]
+[8<ffbf9ffffffbf9ff>]
+[8<ffbfdffffffbf9ff>]
+[8<ffbfdffffffbfdff>]
+[8<ffffdffffffbfdff>]
+[8<ffffdffffffffdff>]
+[8<fffffffffffffdff>]
+[8<ffffffffffffffff>]]
+[%mg
+[8<8000000000000000>]
+[8<0822080080228000>]
+[8<0204081020408001>]
+[8<40e0400000000000>]
+[8<66999966>]
+[8<8001000010080000>]
+[8<81c36666c3810000>]
+[8<f0e0c08000000000>]
+[16<07c00f801f003e007c00f800f001e003c007800f001f003e007c00f801f003e0>]
+[16<1f000f8007c003e001f000f8007c003e001f800fc007e003f001f8007c003e00>]
+[8<c3c300000000c3c3>]
+[16<0040008001000200040008001000200040008000000100020004000800100020>]
+[16<0040002000100008000400020001800040002000100008000400020001000080>]
+[16<1fc03fe07df0f8f8f07de03fc01f800fc01fe03ff07df8f87df03fe01fc00f80>]
+[8<80>]
+[8<8040201000000000>]
+[8<84cc000048cc0000>]
+[8<9900009900000000>]
+[8<08040201804020100800020180002010>]
+[8<2418814242811824>]
+[8<66999966>]
+[8<8000000008000000>]
+[8<70f8d8f870000000>]
+[8<0814224180402010>]
+[8<aa00440a11a04400>]
+[8<018245aa45820100>]
+[8<221c224180808041>]
+[8<88000000>]
+[8<0855800080550800>]
+[8<2844004482440044>]
+[8<0810204080412214>]
+[8<00>]]]def
+/Dfill{
+ transform /maxy exch def /maxx exch def
+ transform /miny exch def /minx exch def
+ minx maxx gt{/minx maxx /maxx minx def def}if
+ miny maxy gt{/miny maxy /maxy miny def def}if
+ Dpatterns Dstipple 1 sub get exch 1 sub get
+ aload pop /stip exch def /stipw exch def /stiph 128 def
+ /imatrix[stipw 0 0 stiph 0 0]def
+ /tmatrix[stipw 0 0 stiph 0 0]def
+ /minx minx cvi stiph idiv stiph mul def
+ /miny miny cvi stipw idiv stipw mul def
+ gsave eoclip 0 setgray
+ miny stiph maxy{
+ tmatrix exch 5 exch put
+ minx stipw maxx{
+ tmatrix exch 4 exch put tmatrix setmatrix
+ stipw stiph true imatrix {stip} imagemask
+ }for
+ }for
+ grestore
+}def
+/Dp{Dfill Dstroke}def
+/DP{Dfill currentpoint newpath moveto}def
+end
+
+/ditstart{$DITroff begin
+ /nfonts 60 def % NFONTS makedev/ditroff dependent!
+ /fonts[nfonts{0}repeat]def
+ /fontnames[nfonts{()}repeat]def
+/docsave save def
+}def
+
+% character outcalls
+/oc{
+ /pswid exch def /cc exch def /name exch def
+ /ditwid pswid fontsize mul resolution mul 72000 div def
+ /ditsiz fontsize resolution mul 72 div def
+ ocprocs name known{ocprocs name get exec}{name cb}ifelse
+}def
+/fractm [.65 0 0 .6 0 0] def
+/fraction{
+ /fden exch def /fnum exch def gsave /cf currentfont def
+ cf fractm makefont setfont 0 .3 dm 2 copy neg rmoveto
+ fnum show rmoveto currentfont cf setfont(\244)show setfont fden show
+ grestore ditwid 0 rmoveto
+}def
+/oce{grestore ditwid 0 rmoveto}def
+/dm{ditsiz mul}def
+/ocprocs 50 dict def ocprocs begin
+(14){(1)(4)fraction}def
+(12){(1)(2)fraction}def
+(34){(3)(4)fraction}def
+(13){(1)(3)fraction}def
+(23){(2)(3)fraction}def
+(18){(1)(8)fraction}def
+(38){(3)(8)fraction}def
+(58){(5)(8)fraction}def
+(78){(7)(8)fraction}def
+(sr){gsave 0 .06 dm rmoveto(\326)show oce}def
+(is){gsave 0 .15 dm rmoveto(\362)show oce}def
+(->){gsave 0 .02 dm rmoveto(\256)show oce}def
+(<-){gsave 0 .02 dm rmoveto(\254)show oce}def
+(==){gsave 0 .05 dm rmoveto(\272)show oce}def
+(uc){gsave currentpoint 400 .009 dm mul add translate
+ 8 -8 scale ucseal oce}def
+end
+
+% an attempt at a PostScript FONT to implement ditroff special chars
+% this will enable us to
+% cache the little buggers
+% generate faster, more compact PS out of psdit
+% confuse everyone (including myself)!
+50 dict dup begin
+/FontType 3 def
+/FontName /DIThacks def
+/FontMatrix [.001 0 0 .001 0 0] def
+/FontBBox [-260 -260 900 900] def% a lie but ...
+/Encoding 256 array def
+0 1 255{Encoding exch /.notdef put}for
+Encoding
+ dup 8#040/space put %space
+ dup 8#110/rc put %right ceil
+ dup 8#111/lt put %left top curl
+ dup 8#112/bv put %bold vert
+ dup 8#113/lk put %left mid curl
+ dup 8#114/lb put %left bot curl
+ dup 8#115/rt put %right top curl
+ dup 8#116/rk put %right mid curl
+ dup 8#117/rb put %right bot curl
+ dup 8#120/rf put %right floor
+ dup 8#121/lf put %left floor
+ dup 8#122/lc put %left ceil
+ dup 8#140/sq put %square
+ dup 8#141/bx put %box
+ dup 8#142/ci put %circle
+ dup 8#143/br put %box rule
+ dup 8#144/rn put %root extender
+ dup 8#145/vr put %vertical rule
+ dup 8#146/ob put %outline bullet
+ dup 8#147/bu put %bullet
+ dup 8#150/ru put %rule
+ dup 8#151/ul put %underline
+ pop
+/DITfd 100 dict def
+/BuildChar{0 begin
+ /cc exch def /fd exch def
+ /charname fd /Encoding get cc get def
+ /charwid fd /Metrics get charname get def
+ /charproc fd /CharProcs get charname get def
+ charwid 0 fd /FontBBox get aload pop setcachedevice
+ 2 setlinejoin 40 setlinewidth
+ newpath 0 0 moveto gsave charproc grestore
+ end}def
+/BuildChar load 0 DITfd put
+/CharProcs 50 dict def
+CharProcs begin
+/space{}def
+/.notdef{}def
+/ru{500 0 rls}def
+/rn{0 840 moveto 500 0 rls}def
+/vr{0 800 moveto 0 -770 rls}def
+/bv{0 800 moveto 0 -1000 rls}def
+/br{0 840 moveto 0 -1000 rls}def
+/ul{0 -140 moveto 500 0 rls}def
+/ob{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath stroke}def
+/bu{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath fill}def
+/sq{80 0 rmoveto currentpoint dround newpath moveto
+ 640 0 rlineto 0 640 rlineto -640 0 rlineto closepath stroke}def
+/bx{80 0 rmoveto currentpoint dround newpath moveto
+ 640 0 rlineto 0 640 rlineto -640 0 rlineto closepath fill}def
+/ci{500 360 rmoveto currentpoint newpath 333 0 360 arc
+ 50 setlinewidth stroke}def
+
+/lt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 add exch s4 a4p stroke}def
+/lb{0 800 moveto 0 -550 rlineto currx -200 2cx s4 add exch s4 a4p stroke}def
+/rt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 sub exch s4 a4p stroke}def
+/rb{0 800 moveto 0 -500 rlineto currx -200 2cx s4 sub exch s4 a4p stroke}def
+/lk{0 800 moveto 0 300 -300 300 s4 arcto pop pop 1000 sub
+ 0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
+/rk{0 800 moveto 0 300 s2 300 s4 arcto pop pop 1000 sub
+ 0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
+/lf{0 800 moveto 0 -1000 rlineto s4 0 rls}def
+/rf{0 800 moveto 0 -1000 rlineto s4 neg 0 rls}def
+/lc{0 -200 moveto 0 1000 rlineto s4 0 rls}def
+/rc{0 -200 moveto 0 1000 rlineto s4 neg 0 rls}def
+end
+
+/Metrics 50 dict def Metrics begin
+/.notdef 0 def
+/space 500 def
+/ru 500 def
+/br 0 def
+/lt 416 def
+/lb 416 def
+/rt 416 def
+/rb 416 def
+/lk 416 def
+/rk 416 def
+/rc 416 def
+/lc 416 def
+/rf 416 def
+/lf 416 def
+/bv 416 def
+/ob 350 def
+/bu 350 def
+/ci 750 def
+/bx 750 def
+/sq 750 def
+/rn 500 def
+/ul 500 def
+/vr 0 def
+end
+
+DITfd begin
+/s2 500 def /s4 250 def /s3 333 def
+/a4p{arcto pop pop pop pop}def
+/2cx{2 copy exch}def
+/rls{rlineto stroke}def
+/currx{currentpoint pop}def
+/dround{transform round exch round exch itransform} def
+end
+end
+/DIThacks exch definefont pop
+ditstart
+(psc)xT
+576 1 1 xr
+1(Times-Roman)xf 1 f
+2(Times-Italic)xf 2 f
+3(Times-Bold)xf 3 f
+4(Times-BoldItalic)xf 4 f
+5(Helvetica)xf 5 f
+6(Helvetica-Bold)xf 6 f
+7(Courier)xf 7 f
+8(Courier-Bold)xf 8 f
+9(Symbol)xf 9 f
+10(DIThacks)xf 10 f
+10 s
+1 f
+xi
+%%EndProlog
+
+%%Page: 1 1
+10 s 10 xH 0 xS 1 f
+3 f
+22 s
+1249 626(A)N
+1420(N)X
+1547(ew)X
+1796(H)X
+1933(ashing)X
+2467(P)X
+2574(ackage)X
+3136(for)X
+3405(U)X
+3532(N)X
+3659(IX)X
+2 f
+20 s
+3855 562(1)N
+1 f
+12 s
+1607 779(Margo)N
+1887(Seltzer)X
+9 f
+2179(-)X
+1 f
+2256(University)X
+2686(of)X
+2790(California,)X
+3229(Berkeley)X
+2015 875(Ozan)N
+2242(Yigit)X
+9 f
+2464(-)X
+1 f
+2541(York)X
+2762(University)X
+3 f
+2331 1086(ABSTRACT)N
+1 f
+10 s
+1152 1222(UNIX)N
+1385(support)X
+1657(of)X
+1756(disk)X
+1921(oriented)X
+2216(hashing)X
+2497(was)X
+2654(originally)X
+2997(provided)X
+3314(by)X
+2 f
+3426(dbm)X
+1 f
+3595([ATT79])X
+3916(and)X
+1152 1310(subsequently)N
+1595(improved)X
+1927(upon)X
+2112(in)X
+2 f
+2199(ndbm)X
+1 f
+2402([BSD86].)X
+2735(In)X
+2826(AT&T)X
+3068(System)X
+3327(V,)X
+3429(in-memory)X
+3809(hashed)X
+1152 1398(storage)N
+1420(and)X
+1572(access)X
+1814(support)X
+2090(was)X
+2251(added)X
+2479(in)X
+2577(the)X
+2 f
+2711(hsearch)X
+1 f
+3000(library)X
+3249(routines)X
+3542([ATT85].)X
+3907(The)X
+1152 1486(result)N
+1367(is)X
+1457(a)X
+1530(system)X
+1789(with)X
+1968(two)X
+2125(incompatible)X
+2580(hashing)X
+2865(schemes,)X
+3193(each)X
+3377(with)X
+3555(its)X
+3666(own)X
+3840(set)X
+3965(of)X
+1152 1574(shortcomings.)N
+1152 1688(This)N
+1316(paper)X
+1517(presents)X
+1802(the)X
+1922(design)X
+2152(and)X
+2289(performance)X
+2717(characteristics)X
+3198(of)X
+3286(a)X
+3343(new)X
+3498(hashing)X
+3768(package)X
+1152 1776(providing)N
+1483(a)X
+1539(superset)X
+1822(of)X
+1909(the)X
+2027(functionality)X
+2456(provided)X
+2761(by)X
+2 f
+2861(dbm)X
+1 f
+3019(and)X
+2 f
+3155(hsearch)X
+1 f
+3409(.)X
+3469(The)X
+3614(new)X
+3768(package)X
+1152 1864(uses)N
+1322(linear)X
+1537(hashing)X
+1818(to)X
+1912(provide)X
+2189(ef\256cient)X
+2484(support)X
+2755(of)X
+2853(both)X
+3026(memory)X
+3324(based)X
+3538(and)X
+3685(disk)X
+3849(based)X
+1152 1952(hash)N
+1319(tables)X
+1526(with)X
+1688(performance)X
+2115(superior)X
+2398(to)X
+2480(both)X
+2 f
+2642(dbm)X
+1 f
+2800(and)X
+2 f
+2936(hsearch)X
+1 f
+3210(under)X
+3413(most)X
+3588(conditions.)X
+3 f
+1380 2128(Introduction)N
+1 f
+892 2260(Current)N
+1196(UNIX)X
+1456(systems)X
+1768(offer)X
+1984(two)X
+2163(forms)X
+2409(of)X
+720 2348(hashed)N
+973(data)X
+1137(access.)X
+2 f
+1413(Dbm)X
+1 f
+1599(and)X
+1745(its)X
+1850(derivatives)X
+2231(provide)X
+720 2436(keyed)N
+939(access)X
+1171(to)X
+1259(disk)X
+1418(resident)X
+1698(data)X
+1858(while)X
+2 f
+2062(hsearch)X
+1 f
+2342(pro-)X
+720 2524(vides)N
+929(access)X
+1175(for)X
+1309(memory)X
+1616(resident)X
+1910(data.)X
+2124(These)X
+2356(two)X
+720 2612(access)N
+979(methods)X
+1302(are)X
+1453(incompatible)X
+1923(in)X
+2037(that)X
+2209(memory)X
+720 2700(resident)N
+1011(hash)X
+1195(tables)X
+1419(may)X
+1593(not)X
+1731(be)X
+1843(stored)X
+2075(on)X
+2191(disk)X
+2360(and)X
+720 2788(disk)N
+884(resident)X
+1169(tables)X
+1387(cannot)X
+1632(be)X
+1739(read)X
+1909(into)X
+2063(memory)X
+2360(and)X
+720 2876(accessed)N
+1022(using)X
+1215(the)X
+1333(in-memory)X
+1709(routines.)X
+2 f
+892 2990(Dbm)N
+1 f
+1091(has)X
+1241(several)X
+1512(shortcomings.)X
+2026(Since)X
+2247(data)X
+2423(is)X
+720 3078(assumed)N
+1032(to)X
+1130(be)X
+1242(disk)X
+1411(resident,)X
+1721(each)X
+1905(access)X
+2146(requires)X
+2440(a)X
+720 3166(system)N
+963(call,)X
+1120(and)X
+1257(almost)X
+1491(certainly,)X
+1813(a)X
+1869(disk)X
+2022(operation.)X
+2365(For)X
+720 3254(extremely)N
+1072(large)X
+1264(databases,)X
+1623(where)X
+1851(caching)X
+2131(is)X
+2214(unlikely)X
+720 3342(to)N
+810(be)X
+914(effective,)X
+1244(this)X
+1386(is)X
+1466(acceptable,)X
+1853(however,)X
+2177(when)X
+2378(the)X
+720 3430(database)N
+1022(is)X
+1100(small)X
+1298(\(i.e.)X
+1447(the)X
+1569(password)X
+1896(\256le\),)X
+2069(performance)X
+720 3518(improvements)N
+1204(can)X
+1342(be)X
+1443(obtained)X
+1744(through)X
+2018(caching)X
+2293(pages)X
+720 3606(of)N
+818(the)X
+947(database)X
+1255(in)X
+1348(memory.)X
+1685(In)X
+1782(addition,)X
+2 f
+2094(dbm)X
+1 f
+2262(cannot)X
+720 3694(store)N
+902(data)X
+1062(items)X
+1261(whose)X
+1492(total)X
+1660(key)X
+1802(and)X
+1943(data)X
+2102(size)X
+2252(exceed)X
+720 3782(the)N
+850(page)X
+1034(size)X
+1191(of)X
+1290(the)X
+1420(hash)X
+1599(table.)X
+1827(Similarly,)X
+2176(if)X
+2257(two)X
+2409(or)X
+720 3870(more)N
+907(keys)X
+1076(produce)X
+1357(the)X
+1477(same)X
+1664(hash)X
+1833(value)X
+2029(and)X
+2166(their)X
+2334(total)X
+720 3958(size)N
+876(exceeds)X
+1162(the)X
+1291(page)X
+1474(size,)X
+1650(the)X
+1779(table)X
+1966(cannot)X
+2210(store)X
+2396(all)X
+720 4046(the)N
+838(colliding)X
+1142(keys.)X
+892 4160(The)N
+1050(in-memory)X
+2 f
+1439(hsearch)X
+1 f
+1725(routines)X
+2015(have)X
+2199(different)X
+720 4248(shortcomings.)N
+1219(First,)X
+1413(the)X
+1539(notion)X
+1771(of)X
+1865(a)X
+1928(single)X
+2146(hash)X
+2320(table)X
+720 4336(is)N
+807(embedded)X
+1171(in)X
+1266(the)X
+1397(interface,)X
+1732(preventing)X
+2108(an)X
+2217(applica-)X
+720 4424(tion)N
+902(from)X
+1116(accessing)X
+1482(multiple)X
+1806(tables)X
+2050(concurrently.)X
+720 4512(Secondly,)N
+1063(the)X
+1186(routine)X
+1438(to)X
+1525(create)X
+1743(a)X
+1804(hash)X
+1976(table)X
+2157(requires)X
+2440(a)X
+720 4600(parameter)N
+1066(which)X
+1286(declares)X
+1573(the)X
+1694(size)X
+1842(of)X
+1932(the)X
+2053(hash)X
+2223(table.)X
+2422(If)X
+720 4688(this)N
+856(size)X
+1001(is)X
+1074(set)X
+1183(too)X
+1305(low,)X
+1465(performance)X
+1892(degradation)X
+2291(or)X
+2378(the)X
+720 4776(inability)N
+1008(to)X
+1092(add)X
+1230(items)X
+1425(to)X
+1509(the)X
+1628(table)X
+1805(may)X
+1964(result.)X
+2223(In)X
+2311(addi-)X
+720 4864(tion,)N
+2 f
+910(hsearch)X
+1 f
+1210(requires)X
+1515(that)X
+1681(the)X
+1825(application)X
+2226(allocate)X
+720 4952(memory)N
+1037(for)X
+1181(the)X
+1329(key)X
+1495(and)X
+1661(data)X
+1845(items.)X
+2108(Lastly,)X
+2378(the)X
+2 f
+720 5040(hsearch)N
+1 f
+1013(routines)X
+1310(provide)X
+1594(no)X
+1713(interface)X
+2034(to)X
+2135(store)X
+2329(hash)X
+720 5128(tables)N
+927(on)X
+1027(disk.)X
+16 s
+720 5593 MXY
+864 0 Dl
+2 f
+8 s
+760 5648(1)N
+1 f
+9 s
+5673(UNIX)Y
+990(is)X
+1056(a)X
+1106(registered)X
+1408(trademark)X
+1718(of)X
+1796(AT&T.)X
+10 s
+2878 2128(The)N
+3032(goal)X
+3199(of)X
+3295(our)X
+3431(work)X
+3625(was)X
+3779(to)X
+3870(design)X
+4108(and)X
+4253(imple-)X
+2706 2216(ment)N
+2900(a)X
+2970(new)X
+3138(package)X
+3436(that)X
+3590(provides)X
+3899(a)X
+3968(superset)X
+4264(of)X
+4364(the)X
+2706 2304(functionality)N
+3144(of)X
+3240(both)X
+2 f
+3411(dbm)X
+1 f
+3578(and)X
+2 f
+3723(hsearch)X
+1 f
+3977(.)X
+4045(The)X
+4198(package)X
+2706 2392(had)N
+2871(to)X
+2982(overcome)X
+3348(the)X
+3495(interface)X
+3826(shortcomings)X
+4306(cited)X
+2706 2480(above)N
+2930(and)X
+3078(its)X
+3185(implementation)X
+3719(had)X
+3867(to)X
+3961(provide)X
+4238(perfor-)X
+2706 2568(mance)N
+2942(equal)X
+3142(or)X
+3235(superior)X
+3524(to)X
+3612(that)X
+3758(of)X
+3851(the)X
+3975(existing)X
+4253(imple-)X
+2706 2656(mentations.)N
+3152(In)X
+3274(order)X
+3498(to)X
+3614(provide)X
+3913(a)X
+4003(compact)X
+4329(disk)X
+2706 2744(representation,)N
+3224(graceful)X
+3531(table)X
+3729(growth,)X
+4018(and)X
+4176(expected)X
+2706 2832(constant)N
+3033(time)X
+3234(performance,)X
+3720(we)X
+3873(selected)X
+4191(Litwin's)X
+2706 2920(linear)N
+2923(hashing)X
+3206(algorithm)X
+3551([LAR88,)X
+3872(LIT80].)X
+4178(We)X
+4324(then)X
+2706 3008(enhanced)N
+3037(the)X
+3161(algorithm)X
+3498(to)X
+3586(handle)X
+3826(page)X
+4004(over\257ows)X
+4346(and)X
+2706 3096(large)N
+2900(key)X
+3049(handling)X
+3362(with)X
+3537(a)X
+3606(single)X
+3830(mechanism,)X
+4248(named)X
+2706 3184(buddy-in-waiting.)N
+3 f
+2975 3338(Existing)N
+3274(UNIX)X
+3499(Hashing)X
+3802(Techniques)X
+1 f
+2878 3470(Over)N
+3076(the)X
+3210(last)X
+3357(decade,)X
+3637(several)X
+3901(dynamic)X
+4213(hashing)X
+2706 3558(schemes)N
+3000(have)X
+3174(been)X
+3348(developed)X
+3700(for)X
+3816(the)X
+3936(UNIX)X
+4159(timeshar-)X
+2706 3646(ing)N
+2856(system,)X
+3146(starting)X
+3433(with)X
+3622(the)X
+3767(inclusion)X
+4107(of)X
+2 f
+4221(dbm)X
+1 f
+4359(,)X
+4426(a)X
+2706 3734(minimal)N
+3008(database)X
+3321(library)X
+3571(written)X
+3834(by)X
+3950(Ken)X
+4120(Thompson)X
+2706 3822([THOM90],)N
+3141(in)X
+3248(the)X
+3391(Seventh)X
+3694(Edition)X
+3974(UNIX)X
+4220(system.)X
+2706 3910(Since)N
+2916(then,)X
+3106(an)X
+3214(extended)X
+3536(version)X
+3804(of)X
+3903(the)X
+4032(same)X
+4228(library,)X
+2 f
+2706 3998(ndbm)N
+1 f
+2884(,)X
+2933(and)X
+3078(a)X
+3142(public-domain)X
+3637(clone)X
+3839(of)X
+3934(the)X
+4060(latter,)X
+2 f
+4273(sdbm)X
+1 f
+4442(,)X
+2706 4086(have)N
+2902(been)X
+3098(developed.)X
+3491(Another)X
+3797 0.1645(interface-compatible)AX
+2706 4174(library)N
+2 f
+2950(gdbm)X
+1 f
+3128(,)X
+3178(was)X
+3333(recently)X
+3622(made)X
+3826(available)X
+4145(as)X
+4241(part)X
+4395(of)X
+2706 4262(the)N
+2829(Free)X
+2997(Software)X
+3312(Foundation's)X
+3759(\(FSF\))X
+3970(software)X
+4271(distri-)X
+2706 4350(bution.)N
+2878 4464(All)N
+3017(of)X
+3121(these)X
+3323(implementations)X
+3893(are)X
+4029(based)X
+4248(on)X
+4364(the)X
+2706 4552(idea)N
+2871(of)X
+2969(revealing)X
+3299(just)X
+3445(enough)X
+3711(bits)X
+3856(of)X
+3953(a)X
+4019(hash)X
+4196(value)X
+4400(to)X
+2706 4640(locate)N
+2920(a)X
+2978(page)X
+3151(in)X
+3234(a)X
+3291(single)X
+3503(access.)X
+3770(While)X
+2 f
+3987(dbm/ndbm)X
+1 f
+4346(and)X
+2 f
+2706 4728(sdbm)N
+1 f
+2908(map)X
+3079(the)X
+3210(hash)X
+3390(value)X
+3597(directly)X
+3874(to)X
+3968(a)X
+4036(disk)X
+4201(address,)X
+2 f
+2706 4816(gdbm)N
+1 f
+2921(uses)X
+3096(the)X
+3231(hash)X
+3414(value)X
+3624(to)X
+3722(index)X
+3936(into)X
+4096(a)X
+2 f
+4168(directory)X
+1 f
+2706 4904([ENB88])N
+3020(containing)X
+3378(disk)X
+3531(addresses.)X
+2878 5018(The)N
+2 f
+3033(hsearch)X
+1 f
+3317(routines)X
+3605(in)X
+3697(System)X
+3962(V)X
+4049(are)X
+4177(designed)X
+2706 5106(to)N
+2804(provide)X
+3085(memory-resident)X
+3669(hash)X
+3852(tables.)X
+4115(Since)X
+4328(data)X
+2706 5194(access)N
+2948(does)X
+3131(not)X
+3269(require)X
+3533(disk)X
+3702(access,)X
+3964(simple)X
+4213(hashing)X
+2706 5282(schemes)N
+3010(which)X
+3238(may)X
+3408(require)X
+3667(multiple)X
+3964(probes)X
+4209(into)X
+4364(the)X
+2706 5370(table)N
+2889(are)X
+3015(used.)X
+3209(A)X
+3294(more)X
+3486(interesting)X
+3851(version)X
+4114(of)X
+2 f
+4208(hsearch)X
+1 f
+2706 5458(is)N
+2784(a)X
+2845(public)X
+3070(domain)X
+3335(library,)X
+2 f
+3594(dynahash)X
+1 f
+3901(,)X
+3945(that)X
+4089(implements)X
+2706 5546(Larson's)N
+3036(in-memory)X
+3440(adaptation)X
+3822([LAR88])X
+4164(of)X
+4279(linear)X
+2706 5634(hashing)N
+2975([LIT80].)X
+3 f
+720 5960(USENIX)N
+9 f
+1042(-)X
+3 f
+1106(Winter)X
+1371('91)X
+9 f
+1498(-)X
+3 f
+1562(Dallas,)X
+1815(TX)X
+1 f
+4424(1)X
+
+2 p
+%%Page: 2 2
+10 s 10 xH 0 xS 1 f
+3 f
+432 258(A)N
+510(New)X
+682(Hashing)X
+985(Package)X
+1290(for)X
+1413(UNIX)X
+3663(Seltzer)X
+3920(&)X
+4007(Yigit)X
+2 f
+1074 538(dbm)N
+1 f
+1232(and)X
+2 f
+1368(ndbm)X
+1 f
+604 670(The)N
+2 f
+760(dbm)X
+1 f
+928(and)X
+2 f
+1074(ndbm)X
+1 f
+1282(library)X
+1526(implementations)X
+2089(are)X
+432 758(based)N
+667(on)X
+799(the)X
+949(same)X
+1166(algorithm)X
+1529(by)X
+1661(Ken)X
+1846(Thompson)X
+432 846([THOM90,)N
+824(TOR88,)X
+1113(WAL84],)X
+1452(but)X
+1582(differ)X
+1789(in)X
+1879(their)X
+2054(pro-)X
+432 934(grammatic)N
+801(interfaces.)X
+1160(The)X
+1311(latter)X
+1502(is)X
+1581(a)X
+1643(modi\256ed)X
+1952(version)X
+432 1022(of)N
+533(the)X
+665(former)X
+918(which)X
+1148(adds)X
+1328(support)X
+1601(for)X
+1728(multiple)X
+2027(data-)X
+432 1110(bases)N
+634(to)X
+724(be)X
+828(open)X
+1011(concurrently.)X
+1484(The)X
+1636(discussion)X
+1996(of)X
+2090(the)X
+432 1198(algorithm)N
+774(that)X
+925(follows)X
+1196(is)X
+1280(applicable)X
+1640(to)X
+1732(both)X
+2 f
+1904(dbm)X
+1 f
+2072(and)X
+2 f
+432 1286(ndbm)N
+1 f
+610(.)X
+604 1400(The)N
+760(basic)X
+956(structure)X
+1268(of)X
+2 f
+1366(dbm)X
+1 f
+1535(calls)X
+1712(for)X
+1836(\256xed-sized)X
+432 1488(disk)N
+612(blocks)X
+868(\(buckets\))X
+1214(and)X
+1377(an)X
+2 f
+1499(access)X
+1 f
+1755(function)X
+2068(that)X
+432 1576(maps)N
+623(a)X
+681(key)X
+819(to)X
+902(a)X
+959(bucket.)X
+1234(The)X
+1380(interface)X
+1683(routines)X
+1962(use)X
+2090(the)X
+2 f
+432 1664(access)N
+1 f
+673(function)X
+970(to)X
+1062(obtain)X
+1292(the)X
+1420(appropriate)X
+1816(bucket)X
+2060(in)X
+2152(a)X
+432 1752(single)N
+643(disk)X
+796(access.)X
+604 1866(Within)N
+869(the)X
+2 f
+1010(access)X
+1 f
+1263(function,)X
+1593(a)X
+1672(bit-randomizing)X
+432 1954(hash)N
+610(function)X
+2 f
+8 s
+877 1929(2)N
+1 f
+10 s
+940 1954(is)N
+1024(used)X
+1202(to)X
+1294(convert)X
+1565(a)X
+1631(key)X
+1777(into)X
+1931(a)X
+1997(32-bit)X
+432 2042(hash)N
+605(value.)X
+825(Out)X
+971(of)X
+1064(these)X
+1254(32)X
+1359(bits,)X
+1519(only)X
+1686(as)X
+1778(many)X
+1981(bits)X
+2121(as)X
+432 2130(necessary)N
+773(are)X
+900(used)X
+1075(to)X
+1165(determine)X
+1514(the)X
+1639(particular)X
+1974(bucket)X
+432 2218(on)N
+533(which)X
+750(a)X
+807(key)X
+944(resides.)X
+1228(An)X
+1347(in-memory)X
+1724(bitmap)X
+1967(is)X
+2041(used)X
+432 2306(to)N
+533(determine)X
+893(how)X
+1070(many)X
+1287(bits)X
+1441(are)X
+1579(required.)X
+1905(Each)X
+2104(bit)X
+432 2394(indicates)N
+746(whether)X
+1033(its)X
+1136(associated)X
+1494(bucket)X
+1736(has)X
+1871(been)X
+2051(split)X
+432 2482(yet)N
+562(\(a)X
+657(0)X
+728(indicating)X
+1079(that)X
+1230(the)X
+1359(bucket)X
+1604(has)X
+1742(not)X
+1875(yet)X
+2004(split\).)X
+432 2570(The)N
+590(use)X
+730(of)X
+830(the)X
+961(hash)X
+1141(function)X
+1441(and)X
+1590(the)X
+1720(bitmap)X
+1974(is)X
+2059(best)X
+432 2658(described)N
+769(by)X
+878(stepping)X
+1177(through)X
+1454(database)X
+1759(creation)X
+2046(with)X
+432 2746(multiple)N
+718(invocations)X
+1107(of)X
+1194(a)X
+2 f
+1250(store)X
+1 f
+1430(operation.)X
+604 2860(Initially,)N
+906(the)X
+1033(hash)X
+1209(table)X
+1394(contains)X
+1690(a)X
+1755(single)X
+1974(bucket)X
+432 2948(\(bucket)N
+711(0\),)X
+836(the)X
+972(bit)X
+1094(map)X
+1270(contains)X
+1575(a)X
+1649(single)X
+1878(bit)X
+2000(\(bit)X
+2148(0)X
+432 3036(corresponding)N
+913(to)X
+997(bucket)X
+1233(0\),)X
+1342(and)X
+1480(0)X
+1542(bits)X
+1699(of)X
+1788(a)X
+1846(hash)X
+2014(value)X
+432 3124(are)N
+560(examined)X
+901(to)X
+992(determine)X
+1342(where)X
+1568(a)X
+1633(key)X
+1778(is)X
+1860(placed)X
+2099(\(in)X
+432 3212(bucket)N
+670(0\).)X
+801(When)X
+1017(bucket)X
+1255(0)X
+1319(is)X
+1396(full,)X
+1551(its)X
+1650(bit)X
+1758(in)X
+1844(the)X
+1966(bitmap)X
+432 3300(\(bit)N
+564(0\))X
+652(is)X
+726(set,)X
+856(and)X
+993(its)X
+1089(contents)X
+1377(are)X
+1497(split)X
+1655(between)X
+1943(buckets)X
+432 3388(0)N
+499(and)X
+641(1,)X
+727(by)X
+833(considering)X
+1233(the)X
+1357(0)X
+2 f
+7 s
+3356(th)Y
+10 s
+1 f
+1480 3388(bit)N
+1590(\(the)X
+1741(lowest)X
+1976(bit)X
+2086(not)X
+432 3476(previously)N
+800(examined\))X
+1169(of)X
+1266(the)X
+1393(hash)X
+1569(value)X
+1772(for)X
+1895(each)X
+2072(key)X
+432 3564(within)N
+668(the)X
+798(bucket.)X
+1064(Given)X
+1292(a)X
+1359(well-designed)X
+1840(hash)X
+2018(func-)X
+432 3652(tion,)N
+613(approximately)X
+1112(half)X
+1273(of)X
+1376(the)X
+1510(keys)X
+1693(will)X
+1853(have)X
+2041(hash)X
+432 3740(values)N
+666(with)X
+837(the)X
+964(0)X
+2 f
+7 s
+3708(th)Y
+10 s
+1 f
+1090 3740(bit)N
+1203(set.)X
+1341(All)X
+1471(such)X
+1646(keys)X
+1821(and)X
+1965(associ-)X
+432 3828(ated)N
+586(data)X
+740(are)X
+859(moved)X
+1097(to)X
+1179(bucket)X
+1413(1,)X
+1493(and)X
+1629(the)X
+1747(rest)X
+1883(remain)X
+2126(in)X
+432 3916(bucket)N
+666(0.)X
+604 4030(After)N
+804(this)X
+949(split,)X
+1135(the)X
+1262(\256le)X
+1393(now)X
+1560(contains)X
+1856(two)X
+2005(buck-)X
+432 4118(ets,)N
+562(and)X
+699(the)X
+818(bitmap)X
+1061(contains)X
+1349(three)X
+1530(bits:)X
+1687(the)X
+1805(0)X
+2 f
+7 s
+4086(th)Y
+10 s
+1 f
+1922 4118(bit)N
+2026(is)X
+2099(set)X
+432 4206(to)N
+525(indicate)X
+810(a)X
+876(bucket)X
+1120(0)X
+1190(split)X
+1357(when)X
+1561(no)X
+1671(bits)X
+1816(of)X
+1913(the)X
+2041(hash)X
+432 4294(value)N
+648(are)X
+789(considered,)X
+1199(and)X
+1357(two)X
+1519(more)X
+1726(unset)X
+1937(bits)X
+2094(for)X
+432 4382(buckets)N
+706(0)X
+775(and)X
+920(1.)X
+1029(The)X
+1183(placement)X
+1542(of)X
+1638(an)X
+1742(incoming)X
+2072(key)X
+432 4470(now)N
+604(requires)X
+897(examination)X
+1327(of)X
+1428(the)X
+1560(0)X
+2 f
+7 s
+4438(th)Y
+10 s
+1 f
+1691 4470(bit)N
+1809(of)X
+1910(the)X
+2041(hash)X
+432 4558(value,)N
+667(and)X
+824(the)X
+963(key)X
+1119(is)X
+1212(placed)X
+1462(either)X
+1685(in)X
+1787(bucket)X
+2041(0)X
+2121(or)X
+432 4646(bucket)N
+674(1.)X
+782(If)X
+864(either)X
+1075(bucket)X
+1317(0)X
+1385(or)X
+1480(bucket)X
+1722(1)X
+1790(\256lls)X
+1937(up,)X
+2064(it)X
+2135(is)X
+432 4734(split)N
+598(as)X
+693(before,)X
+947(its)X
+1050(bit)X
+1162(is)X
+1243(set)X
+1360(in)X
+1450(the)X
+1576(bitmap,)X
+1846(and)X
+1990(a)X
+2054(new)X
+432 4822(set)N
+541(of)X
+628(unset)X
+817(bits)X
+952(are)X
+1071(added)X
+1283(to)X
+1365(the)X
+1483(bitmap.)X
+604 4936(Each)N
+791(time)X
+959(we)X
+1079(consider)X
+1376(a)X
+1437(new)X
+1596(bit)X
+1705(\(bit)X
+1841(n\),)X
+1953(we)X
+2072(add)X
+432 5024(2)N
+2 f
+7 s
+4992(n)Y
+9 f
+509(+)X
+1 f
+540(1)X
+10 s
+595 5024(bits)N
+737(to)X
+826(the)X
+951(bitmap)X
+1199(and)X
+1341(obtain)X
+1567(2)X
+2 f
+7 s
+4992(n)Y
+9 f
+1644(+)X
+1 f
+1675(1)X
+10 s
+1729 5024(more)N
+1920(address-)X
+432 5112(able)N
+595(buckets)X
+869(in)X
+960(the)X
+1087(\256le.)X
+1258(As)X
+1376(a)X
+1441(result,)X
+1668(the)X
+1795(bitmap)X
+2045(con-)X
+432 5200(tains)N
+618(the)X
+751(previous)X
+1062(2)X
+2 f
+7 s
+5168(n)Y
+9 f
+1139(+)X
+1 f
+1170(1)X
+2 f
+10 s
+9 f
+5200(-)Y
+1 f
+1242(1)X
+1317(bits)X
+1467(\(1)X
+2 f
+9 f
+1534(+)X
+1 f
+1578(2)X
+2 f
+9 f
+(+)S
+1 f
+1662(4)X
+2 f
+9 f
+(+)S
+1 f
+1746(...)X
+2 f
+9 f
+(+)S
+1 f
+1850(2)X
+2 f
+7 s
+5168(n)Y
+10 s
+1 f
+1931 5200(\))N
+1992(which)X
+432 5288(trace)N
+649(the)X
+807(entire)X
+2 f
+1050(split)X
+1247(history)X
+1 f
+1529(of)X
+1656(the)X
+1813(addressable)X
+16 s
+432 5433 MXY
+864 0 Dl
+2 f
+8 s
+472 5488(2)N
+1 f
+9 s
+523 5513(This)N
+670(bit-randomizing)X
+1153(property)X
+1416(is)X
+1482(important)X
+1780(to)X
+1854(obtain)X
+2052(radi-)X
+432 5593(cally)N
+599(different)X
+874(hash)X
+1033(values)X
+1244(for)X
+1355(nearly)X
+1562(identical)X
+1836(keys,)X
+2012(which)X
+432 5673(in)N
+506(turn)X
+640(avoids)X
+846(clustering)X
+1148(of)X
+1226(such)X
+1376(keys)X
+1526(in)X
+1600(a)X
+1650(single)X
+1840(bucket.)X
+10 s
+2418 538(buckets.)N
+2590 652(Given)N
+2809(a)X
+2868(key)X
+3007(and)X
+3146(the)X
+3267(bitmap)X
+3512(created)X
+3768(by)X
+3871(this)X
+4009(algo-)X
+2418 740(rithm,)N
+2638(we)X
+2759(\256rst)X
+2910(examine)X
+3209(bit)X
+3320(0)X
+3386(of)X
+3479(the)X
+3603(bitmap)X
+3851(\(the)X
+4002(bit)X
+4112(to)X
+2418 828(consult)N
+2673(when)X
+2871(0)X
+2934(bits)X
+3072(of)X
+3162(the)X
+3283(hash)X
+3453(value)X
+3650(are)X
+3772(being)X
+3973(exam-)X
+2418 916(ined\).)N
+2631(If)X
+2713(it)X
+2785(is)X
+2866(set)X
+2982(\(indicating)X
+3356(that)X
+3503(the)X
+3628(bucket)X
+3869(split\),)X
+4080(we)X
+2418 1004(begin)N
+2617(considering)X
+3012(the)X
+3131(bits)X
+3267(of)X
+3355(the)X
+3473(32-bit)X
+3684(hash)X
+3851(value.)X
+4085(As)X
+2418 1092(bit)N
+2525(n)X
+2587(is)X
+2662(revealed,)X
+2977(a)X
+3035(mask)X
+3226(equal)X
+3422(to)X
+3506(2)X
+2 f
+7 s
+1060(n)Y
+9 f
+3583(+)X
+1 f
+3614(1)X
+2 f
+10 s
+9 f
+1092(-)Y
+1 f
+3686(1)X
+3748(will)X
+3894(yield)X
+4076(the)X
+2418 1180(current)N
+2675(bucket)X
+2918(address.)X
+3228(Adding)X
+3496(2)X
+2 f
+7 s
+1148(n)Y
+9 f
+3573(+)X
+1 f
+3604(1)X
+2 f
+10 s
+9 f
+1180(-)Y
+1 f
+3676(1)X
+3744(to)X
+3834(the)X
+3960(bucket)X
+2418 1268(address)N
+2701(identi\256es)X
+3035(which)X
+3272(bit)X
+3397(in)X
+3500(the)X
+3639(bitmap)X
+3902(must)X
+4098(be)X
+2418 1356(checked.)N
+2743(We)X
+2876(continue)X
+3173(revealing)X
+3493(bits)X
+3628(of)X
+3715(the)X
+3833(hash)X
+4000(value)X
+2418 1444(until)N
+2591(all)X
+2698(set)X
+2814(bits)X
+2955(in)X
+3043(the)X
+3167(bitmap)X
+3415(are)X
+3540(exhausted.)X
+3907(The)X
+4058(fol-)X
+2418 1532(lowing)N
+2682(algorithm,)X
+3055(a)X
+3133(simpli\256cation)X
+3614(of)X
+3723(the)X
+3863(algorithm)X
+2418 1620(due)N
+2565(to)X
+2658(Ken)X
+2823(Thompson)X
+3196([THOM90,)X
+3590(TOR88],)X
+3908(uses)X
+4076(the)X
+2418 1708(hash)N
+2625(value)X
+2839(and)X
+2995(the)X
+3133(bitmap)X
+3395(to)X
+3497(calculate)X
+3823(the)X
+3960(bucket)X
+2418 1796(address)N
+2679(as)X
+2766(discussed)X
+3093(above.)X
+0(Courier)xf 0 f
+1 f
+0 f
+8 s
+2418 2095(hash)N
+2608(=)X
+2684 -0.4038(calchash\(key\);)AX
+2418 2183(mask)N
+2608(=)X
+2684(0;)X
+2418 2271(while)N
+2646 -0.4018(\(isbitset\(\(hash)AX
+3254(&)X
+3330(mask\))X
+3558(+)X
+3634(mask\)\))X
+2706 2359(mask)N
+2896(=)X
+2972(\(mask)X
+3200(<<)X
+3314(1\))X
+3428(+)X
+3504(1;)X
+2418 2447(bucket)N
+2684(=)X
+2760(hash)X
+2950(&)X
+3026(mask;)X
+2 f
+10 s
+3211 2812(sdbm)N
+1 f
+2590 2944(The)N
+2 f
+2738(sdbm)X
+1 f
+2930(library)X
+3167(is)X
+3243(a)X
+3302(public-domain)X
+3791(clone)X
+3987(of)X
+4076(the)X
+2 f
+2418 3032(ndbm)N
+1 f
+2638(library,)X
+2914(developed)X
+3286(by)X
+3408(Ozan)X
+3620(Yigit)X
+3826(to)X
+3929(provide)X
+2 f
+2418 3120(ndbm)N
+1 f
+2596('s)X
+2692(functionality)X
+3139(under)X
+3359(some)X
+3565(versions)X
+3869(of)X
+3973(UNIX)X
+2418 3208(that)N
+2559(exclude)X
+2830(it)X
+2894(for)X
+3008(licensing)X
+3317(reasons)X
+3578([YIG89].)X
+3895(The)X
+4040(pro-)X
+2418 3296(grammer)N
+2735(interface,)X
+3064(and)X
+3207(the)X
+3332(basic)X
+3524(structure)X
+3832(of)X
+2 f
+3926(sdbm)X
+1 f
+4121(is)X
+2418 3384(identical)N
+2733(to)X
+2 f
+2834(ndbm)X
+1 f
+3051(but)X
+3192(internal)X
+3476(details)X
+3723(of)X
+3828(the)X
+2 f
+3964(access)X
+1 f
+2418 3472(function,)N
+2726(such)X
+2894(as)X
+2982(the)X
+3101(calculation)X
+3474(of)X
+3561(the)X
+3679(bucket)X
+3913(address,)X
+2418 3560(and)N
+2563(the)X
+2690(use)X
+2825(of)X
+2920(different)X
+3225(hash)X
+3400(functions)X
+3726(make)X
+3928(the)X
+4054(two)X
+2418 3648(incompatible)N
+2856(at)X
+2934(the)X
+3052(database)X
+3349(level.)X
+2590 3762(The)N
+2 f
+2740(sdbm)X
+1 f
+2934(library)X
+3173(is)X
+3251(based)X
+3458(on)X
+3562(a)X
+3622(simpli\256ed)X
+3965(imple-)X
+2418 3850(mentation)N
+2778(of)X
+2885(Larson's)X
+3206(1978)X
+2 f
+3406(dynamic)X
+3717(hashing)X
+1 f
+4009(algo-)X
+2418 3938(rithm)N
+2616(including)X
+2943(the)X
+2 f
+3066(re\256nements)X
+3461(and)X
+3605(variations)X
+1 f
+3953(of)X
+4044(sec-)X
+2418 4026(tion)N
+2562(5)X
+2622([LAR78].)X
+2956(Larson's)X
+3257(original)X
+3526(algorithm)X
+3857(calls)X
+4024(for)X
+4138(a)X
+2418 4114(forest)N
+2635(of)X
+2736(binary)X
+2975(hash)X
+3156(trees)X
+3341(that)X
+3494(are)X
+3626(accessed)X
+3941(by)X
+4054(two)X
+2418 4202(hash)N
+2586(functions.)X
+2925(The)X
+3071(\256rst)X
+3216(hash)X
+3384(function)X
+3672(selects)X
+3907(a)X
+3964(partic-)X
+2418 4290(ular)N
+2571(tree)X
+2720(within)X
+2952(the)X
+3078(forest.)X
+3309(The)X
+3462(second)X
+3713(hash)X
+3887(function,)X
+2418 4378(which)N
+2659(is)X
+2757(required)X
+3070(to)X
+3177(be)X
+3297(a)X
+3377(boolean)X
+3675(pseudo-random)X
+2418 4466(number)N
+2687(generator)X
+3015(that)X
+3159(is)X
+3236(seeded)X
+3479(by)X
+3583(the)X
+3705(key,)X
+3865(is)X
+3942(used)X
+4112(to)X
+2418 4554(traverse)N
+2733(the)X
+2890(tree)X
+3070(until)X
+3275(internal)X
+3579(\(split\))X
+3829(nodes)X
+4075(are)X
+2418 4642(exhausted)N
+2763(and)X
+2903(an)X
+3003(external)X
+3286(\(non-split\))X
+3648(node)X
+3827(is)X
+3903(reached.)X
+2418 4730(The)N
+2571(bucket)X
+2813(addresses)X
+3149(are)X
+3276(stored)X
+3500(directly)X
+3772(in)X
+3861(the)X
+3986(exter-)X
+2418 4818(nal)N
+2536(nodes.)X
+2590 4932(Larson's)N
+2903(re\256nements)X
+3309(are)X
+3440(based)X
+3655(on)X
+3767(the)X
+3897(observa-)X
+2418 5020(tion)N
+2570(that)X
+2718(the)X
+2844(nodes)X
+3059(can)X
+3199(be)X
+3303(represented)X
+3702(by)X
+3809(a)X
+3872(single)X
+4090(bit)X
+2418 5108(that)N
+2569(is)X
+2653(set)X
+2773(for)X
+2898(internal)X
+3174(nodes)X
+3392(and)X
+3539(not)X
+3672(set)X
+3791(for)X
+3915(external)X
+2418 5196(nodes,)N
+2652(resulting)X
+2959(in)X
+3048(a)X
+3111(radix)X
+3303(search)X
+3536(trie.)X
+3709(Figure)X
+3944(1)X
+4010(illus-)X
+2418 5284(trates)N
+2621(this.)X
+2804(Nodes)X
+3037(A)X
+3123(and)X
+3267(B)X
+3348(are)X
+3475(internal)X
+3748(\(split\))X
+3967(nodes,)X
+2418 5372(thus)N
+2573(having)X
+2813(no)X
+2915(bucket)X
+3151(addresses)X
+3480(associated)X
+3831(with)X
+3994(them.)X
+2418 5460(Instead,)N
+2693(the)X
+2814(external)X
+3096(nodes)X
+3306(\(C,)X
+3429(D,)X
+3530(and)X
+3669(E\))X
+3768(each)X
+3938(need)X
+4112(to)X
+2418 5548(refer)N
+2594(to)X
+2679(a)X
+2738(bucket)X
+2975(address.)X
+3279(These)X
+3494(bucket)X
+3731(addresses)X
+4062(can)X
+2418 5636(be)N
+2529(stored)X
+2760(in)X
+2857(the)X
+2990(trie)X
+3132(itself)X
+3327(where)X
+3559(the)X
+3691(subtries)X
+3974(would)X
+3 f
+432 5960(2)N
+2970(USENIX)X
+9 f
+3292(-)X
+3 f
+3356(Winter)X
+3621('91)X
+9 f
+3748(-)X
+3 f
+3812(Dallas,)X
+4065(TX)X
+
+3 p
+%%Page: 3 3
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+720 258(Seltzer)N
+977(&)X
+1064(Yigit)X
+3278(A)X
+3356(New)X
+3528(Hashing)X
+3831(Package)X
+4136(for)X
+4259(UNIX)X
+1 f
+720 538(live)N
+862(if)X
+933(they)X
+1092(existed)X
+1340([KNU68].)X
+1709(For)X
+1841(example,)X
+2154(if)X
+2224(nodes)X
+2432(F)X
+720 626(and)N
+858(G)X
+938(were)X
+1117(the)X
+1237(children)X
+1522(of)X
+1610(node)X
+1787(C,)X
+1881(the)X
+2000(bucket)X
+2235(address)X
+720 714(L00)N
+886(could)X
+1101(reside)X
+1330(in)X
+1429(the)X
+1563(bits)X
+1714(that)X
+1870(will)X
+2030(eventually)X
+2400(be)X
+720 802(used)N
+887(to)X
+969(store)X
+1145(nodes)X
+1352(F)X
+1416(and)X
+1552(G)X
+1630(and)X
+1766(all)X
+1866(their)X
+2033(children.)X
+10 f
+720 890 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+1894 2247(L1)N
+784 1925(A)N
+1431(E)X
+1106 2247(D)N
+1428 1281(C)N
+1109 1603(B)N
+1884 1930(L01)N
+1879 1286(L00)N
+1221 1814(1)N
+903 2131(1)N
+1221 1402(0)N
+903 1714(0)N
+1 Dt
+1397 1821 MXY
+-8 -32 Dl
+-5 19 Dl
+-20 6 Dl
+33 7 Dl
+-187 -182 Dl
+1397 1322 MXY
+-33 7 Dl
+20 6 Dl
+5 19 Dl
+8 -32 Dl
+-187 182 Dl
+1069 1639 MXY
+-32 7 Dl
+20 6 Dl
+5 19 Dl
+7 -32 Dl
+-186 182 Dl
+1374 1891 MXY
+185 Dc
+1779 2133 MXY
+0 161 Dl
+322 0 Dl
+0 -161 Dl
+-322 0 Dl
+1811 MY
+0 161 Dl
+322 0 Dl
+0 -161 Dl
+-322 0 Dl
+1166 MY
+0 161 Dl
+322 0 Dl
+0 -161 Dl
+-322 0 Dl
+1052 2213 MXY
+185 Dc
+1569 MY
+185 Dc
+720 1881 MXY
+185 Dc
+1779 2213 MXY
+-28 -17 Dl
+10 17 Dl
+-10 18 Dl
+28 -18 Dl
+-543 0 Dl
+1769 1891 MXY
+-28 -18 Dl
+10 18 Dl
+-10 18 Dl
+28 -18 Dl
+-201 0 Dl
+1364 1247 MXY
+185 Dc
+1769 MX
+-28 -18 Dl
+10 18 Dl
+-10 18 Dl
+28 -18 Dl
+-201 0 Dl
+1064 2143 MXY
+-7 -32 Dl
+-5 19 Dl
+-20 6 Dl
+32 7 Dl
+-181 -181 Dl
+3 Dt
+-1 Ds
+8 s
+720 2482(Figure)N
+925(1:)X
+1 f
+1002(Radix)X
+1179(search)X
+1365(trie)X
+1474(with)X
+1612(internal)X
+1831(nodes)X
+2004(A)X
+2074(and)X
+2189(B,)X
+2271(external)X
+720 2570(nodes)N
+891(C,)X
+972(D,)X
+1056(and)X
+1170(E,)X
+1247(and)X
+1361(bucket)X
+1553(addresses)X
+1819(stored)X
+1997(in)X
+2069(the)X
+2168(unused)X
+2370(por-)X
+720 2658(tion)N
+836(of)X
+905(the)X
+999(trie.)X
+10 s
+10 f
+720 2922 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+1 f
+892 3124(Further)N
+1153(simpli\256cations)X
+1647(of)X
+1738(the)X
+1860(above)X
+2076([YIG89])X
+2377(are)X
+720 3212(possible.)N
+1038(Using)X
+1265(a)X
+1337(single)X
+1564(radix)X
+1765(trie)X
+1908(to)X
+2006(avoid)X
+2219(the)X
+2352(\256rst)X
+720 3300(hash)N
+904(function,)X
+1227(replacing)X
+1562(the)X
+1696(pseudo-random)X
+2231(number)X
+720 3388(generator)N
+1052(with)X
+1222(a)X
+1286(well)X
+1452(designed,)X
+1785(bit-randomizing)X
+2329(hash)X
+720 3476(function,)N
+1053(and)X
+1215(using)X
+1434(the)X
+1578(portion)X
+1855(of)X
+1967(the)X
+2110(hash)X
+2302(value)X
+720 3564(exposed)N
+1021(during)X
+1268(the)X
+1404(trie)X
+1549(traversal)X
+1864(as)X
+1969(a)X
+2042(direct)X
+2262(bucket)X
+720 3652(address)N
+990(results)X
+1228(in)X
+1319(an)X
+2 f
+1424(access)X
+1 f
+1663(function)X
+1959(that)X
+2108(works)X
+2333(very)X
+720 3740(similar)N
+974(to)X
+1068(Thompson's)X
+1499(algorithm)X
+1841(above.)X
+2084(The)X
+2240(follow-)X
+720 3828(ing)N
+847(algorithm)X
+1183(uses)X
+1346(the)X
+1469(hash)X
+1641(value)X
+1840(to)X
+1927(traverse)X
+2206(a)X
+2266(linear-)X
+720 3916(ized)N
+874(radix)X
+1059(trie)X
+2 f
+8 s
+1166 3891(3)N
+1 f
+10 s
+1218 3916(starting)N
+1478(at)X
+1556(the)X
+1674(0)X
+2 f
+7 s
+3884(th)Y
+10 s
+1 f
+1791 3916(bit.)N
+0 f
+8 s
+720 4215(tbit)N
+910(=)X
+986(0;)X
+1296(/*)X
+1410(radix)X
+1638(trie)X
+1828(index)X
+2056(*/)X
+720 4303(hbit)N
+910(=)X
+986(0;)X
+1296(/*)X
+1410(hash)X
+1600(bit)X
+1752(index)X
+2056(*/)X
+720 4391(mask)N
+910(=)X
+986(0;)X
+720 4479(hash)N
+910(=)X
+986 -0.4038(calchash\(key\);)AX
+720 4655(for)N
+872(\(mask)X
+1100(=)X
+1176(0;)X
+910 4743 -0.4018(isbitset\(tbit\);)AN
+910 4831(mask)N
+1100(=)X
+1176(\(mask)X
+1404(<<)X
+1518(1\))X
+1632(+)X
+1708(1\))X
+1008 4919(if)N
+1122(\(hash)X
+1350(&)X
+1426(\(1)X
+1540(<<)X
+1654 -0.4219(hbit++\)\)\))AX
+1160 5007(/*)N
+1274(right)X
+1502(son)X
+1692(*/)X
+1160 5095(tbit)N
+1350(=)X
+1426(2)X
+1502(*)X
+1578(tbit)X
+1768(+)X
+1844(2;)X
+1008 5183(else)N
+1 f
+16 s
+720 5353 MXY
+864 0 Dl
+2 f
+8 s
+760 5408(3)N
+1 f
+9 s
+818 5433(A)N
+896(linearized)X
+1206(radix)X
+1380(trie)X
+1502(is)X
+1576(merely)X
+1802(an)X
+1895(array)X
+2068(representation)X
+720 5513(of)N
+800(the)X
+908(radix)X
+1076(search)X
+1280(trie)X
+1396(described)X
+1692(above.)X
+1920(The)X
+2052(children)X
+2308(of)X
+2388(the)X
+720 5593(node)N
+885(with)X
+1038(index)X
+1223(i)X
+1267(can)X
+1391(be)X
+1483(found)X
+1675(at)X
+1751(the)X
+1863(nodes)X
+2055(indexed)X
+2307(2*i+1)X
+720 5673(and)N
+842(2*i+2.)X
+0 f
+8 s
+3146 538(/*)N
+3260(left)X
+3450(son)X
+3678(*/)X
+3146 626(tbit)N
+3336(=)X
+3412(2)X
+3488(*)X
+3564(tbit)X
+3754(+)X
+3830(1;)X
+2706 802(bucket)N
+2972(=)X
+3048(hash)X
+3238(&)X
+3314(mask;)X
+2 f
+10 s
+3495 1167(gdbm)N
+1 f
+2878 1299(The)N
+3027(gdbm)X
+3233(\(GNU)X
+3458(data)X
+3616(base)X
+3783(manager\))X
+4111(library)X
+4349(is)X
+4426(a)X
+2706 1387(UNIX)N
+2933(database)X
+3236(manager)X
+3539(written)X
+3792(by)X
+3897(Philip)X
+4112(A.)X
+4215(Nelson,)X
+2706 1475(and)N
+2848(made)X
+3048(available)X
+3364(as)X
+3457(a)X
+3518(part)X
+3668(of)X
+3760(the)X
+3883(FSF)X
+4040(software)X
+4342(dis-)X
+2706 1563(tribution.)N
+3052(The)X
+3207(gdbm)X
+3419(library)X
+3663(provides)X
+3969(the)X
+4097(same)X
+4292(func-)X
+2706 1651(tionality)N
+3028(of)X
+3151(the)X
+2 f
+3304(dbm)X
+1 f
+3442(/)X
+2 f
+3464(ndbm)X
+1 f
+3697(libraries)X
+4015([NEL90])X
+4360(but)X
+2706 1739(attempts)N
+3018(to)X
+3121(avoid)X
+3340(some)X
+3550(of)X
+3658(their)X
+3846(shortcomings.)X
+4337(The)X
+2706 1827(gdbm)N
+2918(library)X
+3162(allows)X
+3401(for)X
+3525(arbitrary-length)X
+4059(data,)X
+4242(and)X
+4387(its)X
+2706 1915(database)N
+3027(is)X
+3124(a)X
+3203(singular,)X
+3524(non-sparse)X
+2 f
+8 s
+3872 1890(4)N
+1 f
+10 s
+3947 1915(\256le.)N
+4112(The)X
+4280(gdbm)X
+2706 2003(library)N
+2947(also)X
+3103(includes)X
+2 f
+3396(dbm)X
+1 f
+3560(and)X
+2 f
+3702(ndbm)X
+1 f
+3906(compatible)X
+4288(inter-)X
+2706 2091(faces.)N
+2878 2205(The)N
+3025(gdbm)X
+3229(library)X
+3465(is)X
+3540(based)X
+3745(on)X
+2 f
+3847(extensible)X
+4189(hashing)X
+1 f
+4442(,)X
+2706 2293(a)N
+2766(dynamic)X
+3066(hashing)X
+3339(algorithm)X
+3674(by)X
+3778(Fagin)X
+3984(et)X
+4066(al)X
+4148([FAG79].)X
+2706 2381(This)N
+2881(algorithm)X
+3225(differs)X
+3467(from)X
+3655(the)X
+3785(previously)X
+4155(discussed)X
+2706 2469(algorithms)N
+3069(in)X
+3152(that)X
+3293(it)X
+3358(uses)X
+3517(a)X
+2 f
+3574(directory)X
+1 f
+3889(that)X
+4030(is)X
+4103(a)X
+4159(collapsed)X
+2706 2557(representation)N
+3192([ENB88])X
+3517(of)X
+3615(the)X
+3744(radix)X
+3940(search)X
+4177(trie)X
+4315(used)X
+2706 2645(by)N
+2 f
+2806(sdbm)X
+1 f
+2975(.)X
+10 f
+2706 2733 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+7 s
+3572 3761(L1)N
+1 Dt
+3485 3738 MXY
+-20 -13 Dl
+7 13 Dl
+-7 13 Dl
+20 -13 Dl
+-400 0 Dl
+3180 3027 MXY
+136 Dc
+2706 3494 MXY
+136 Dc
+2950 3264 MXY
+136 Dc
+3738 MY
+136 Dc
+3485 2968 MXY
+0 118 Dl
+238 0 Dl
+0 -118 Dl
+-238 0 Dl
+3442 MY
+0 119 Dl
+238 0 Dl
+0 -119 Dl
+-238 0 Dl
+3679 MY
+0 119 Dl
+238 0 Dl
+0 -119 Dl
+-238 0 Dl
+3187 3501 MXY
+136 Dc
+2963 3316 MXY
+-24 5 Dl
+15 4 Dl
+4 15 Dl
+5 -24 Dl
+-137 134 Dl
+3204 3083 MXY
+-24 5 Dl
+15 4 Dl
+3 14 Dl
+6 -23 Dl
+-137 133 Dl
+3204 3450 MXY
+-6 -24 Dl
+-3 14 Dl
+-15 5 Dl
+24 5 Dl
+-137 -134 Dl
+2842 3369(0)N
+3075 3139(0)N
+2842 3676(1)N
+3075 3443(1)N
+3562 3054(L00)N
+3565 3528(L01)N
+4197 2968 MXY
+0 118 Dl
+237 0 Dl
+0 -118 Dl
+-237 0 Dl
+3205 MY
+0 119 Dl
+237 0 Dl
+0 -119 Dl
+-237 0 Dl
+3561 MY
+0 118 Dl
+237 0 Dl
+0 -118 Dl
+-237 0 Dl
+3960 2909 MXY
+0 237 Dl
+118 0 Dl
+0 -237 Dl
+-118 0 Dl
+3146 MY
+0 237 Dl
+118 0 Dl
+0 -237 Dl
+-118 0 Dl
+3383 MY
+0 237 Dl
+118 0 Dl
+0 -237 Dl
+-118 0 Dl
+3620 MY
+0 237 Dl
+118 0 Dl
+0 -237 Dl
+-118 0 Dl
+4197 3027 MXY
+-21 -13 Dl
+8 13 Dl
+-8 13 Dl
+21 -13 Dl
+-119 0 Dl
+4197 3264 MXY
+-21 -13 Dl
+8 13 Dl
+-8 13 Dl
+21 -13 Dl
+-119 0 Dl
+3501 MY
+59 0 Dl
+0 89 Dl
+4078 3738 MXY
+59 0 Dl
+0 -88 Dl
+4197 3590 MXY
+-21 -13 Dl
+8 13 Dl
+-8 13 Dl
+21 -13 Dl
+-60 0 Dl
+4197 3650 MXY
+-21 -13 Dl
+8 13 Dl
+-8 13 Dl
+21 -13 Dl
+-60 0 Dl
+3991 3050(00)N
+3991 3287(01)N
+3991 3524(10)N
+3991 3761(11)N
+4269 3050(L00)N
+4269 3287(L01)N
+4283 3643(L1)N
+3485 3501 MXY
+-20 -13 Dl
+7 13 Dl
+-7 13 Dl
+20 -13 Dl
+-155 0 Dl
+3485 3027 MXY
+-20 -13 Dl
+7 13 Dl
+-7 13 Dl
+20 -13 Dl
+-163 0 Dl
+2967 3687 MXY
+-5 -24 Dl
+-4 14 Dl
+-15 4 Dl
+24 6 Dl
+-141 -141 Dl
+3 Dt
+-1 Ds
+8 s
+2706 4033(Figure)N
+2903(2:)X
+1 f
+2972(A)X
+3034(radix)X
+3181(search)X
+3359(trie)X
+3460(and)X
+3568(a)X
+3612(directory)X
+3858(representing)X
+4189(the)X
+4283(trie.)X
+10 s
+10 f
+2706 4209 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+1 f
+2878 4411(In)N
+2968(this)X
+3106(algorithm,)X
+3460(a)X
+3519(directory)X
+3832(consists)X
+4108(of)X
+4198(a)X
+4256(search)X
+2706 4499(trie)N
+2847(of)X
+2947(depth)X
+2 f
+3158(n)X
+1 f
+3211(,)X
+3264(containing)X
+3635(2)X
+2 f
+7 s
+4467(n)Y
+10 s
+1 f
+3749 4499(bucket)N
+3996(addresses)X
+4337(\(i.e.)X
+2706 4587(each)N
+2897(element)X
+3194(of)X
+3304(the)X
+3445(trie)X
+3594(is)X
+3689(a)X
+3767(bucket)X
+4023(address\).)X
+4373(To)X
+2706 4675(access)N
+2935(the)X
+3056(hash)X
+3226(table,)X
+3425(a)X
+3483(32-bit)X
+3696(hash)X
+3865(value)X
+4061(is)X
+4136(calculated)X
+2706 4763(and)N
+2 f
+2861(n)X
+1 f
+2953(bits)X
+3107(of)X
+3213(the)X
+3350(value)X
+3563(are)X
+3701(used)X
+3886(to)X
+3986(index)X
+4202(into)X
+4364(the)X
+2706 4851(directory)N
+3018(to)X
+3102(obtain)X
+3324(a)X
+3382(bucket)X
+3618(address.)X
+3921(It)X
+3992(is)X
+4067(important)X
+4400(to)X
+2706 4939(note)N
+2866(that)X
+3008(multiple)X
+3296(entries)X
+3532(of)X
+3620(this)X
+3756(directory)X
+4067(may)X
+4226(contain)X
+2706 5027(the)N
+2833(same)X
+3026(bucket)X
+3268(address)X
+3537(as)X
+3632(a)X
+3696(result)X
+3902(of)X
+3997(directory)X
+4315(dou-)X
+2706 5115(bling)N
+2903(during)X
+3145(bucket)X
+3392(splitting.)X
+3706(Figure)X
+3948(2)X
+4021(illustrates)X
+4364(the)X
+2706 5203(relationship)N
+3126(between)X
+3436(a)X
+3513(typical)X
+3772(\(skewed\))X
+4108(search)X
+4355(trie)X
+2706 5291(and)N
+2850(its)X
+2953(directory)X
+3271(representation.)X
+3774(The)X
+3927(formation)X
+4270(of)X
+4364(the)X
+2706 5379(directory)N
+3016(shown)X
+3245(in)X
+3327(the)X
+3445(\256gure)X
+3652(is)X
+3725(as)X
+3812(follows.)X
+16 s
+2706 5593 MXY
+864 0 Dl
+2 f
+8 s
+2746 5648(4)N
+1 f
+9 s
+2796 5673(It)N
+2858(does)X
+3008(not)X
+3118(contain)X
+3348(holes.)X
+3 f
+10 s
+720 5960(USENIX)N
+9 f
+1042(-)X
+3 f
+1106(Winter)X
+1371('91)X
+9 f
+1498(-)X
+3 f
+1562(Dallas,)X
+1815(TX)X
+4424(3)X
+
+4 p
+%%Page: 4 4
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+432 258(A)N
+510(New)X
+682(Hashing)X
+985(Package)X
+1290(for)X
+1413(UNIX)X
+3663(Seltzer)X
+3920(&)X
+4007(Yigit)X
+1 f
+604 538(Initially,)N
+937(there)X
+1158(is)X
+1271(one)X
+1446(slot)X
+1620(in)X
+1741(the)X
+1898(directory)X
+432 626(addressing)N
+802(a)X
+865(single)X
+1083(bucket.)X
+1364(The)X
+1515(depth)X
+1719(of)X
+1812(the)X
+1936(trie)X
+2069(is)X
+2148(0)X
+432 714(and)N
+577(0)X
+646(bits)X
+790(of)X
+886(each)X
+1063(hash)X
+1239(value)X
+1442(are)X
+1570(examined)X
+1910(to)X
+2000(deter-)X
+432 802(mine)N
+624(in)X
+718(which)X
+946(bucket)X
+1192(to)X
+1286(place)X
+1488(a)X
+1556(key;)X
+1726(all)X
+1837(keys)X
+2015(go)X
+2126(in)X
+432 890(bucket)N
+682(0.)X
+797(When)X
+1024(this)X
+1174(bucket)X
+1423(is)X
+1511(full,)X
+1677(its)X
+1787(contents)X
+2089(are)X
+432 978(divided)N
+698(between)X
+992(L0)X
+1107(and)X
+1249(L1)X
+1363(as)X
+1455(was)X
+1605(done)X
+1786(in)X
+1873(the)X
+1996(previ-)X
+432 1066(ously)N
+664(discussed)X
+1030(algorithms.)X
+1471(After)X
+1700(this)X
+1874(split,)X
+2090(the)X
+432 1154(address)N
+710(of)X
+814(the)X
+948(second)X
+1207(bucket)X
+1457(must)X
+1648(be)X
+1760(stored)X
+1992(in)X
+2090(the)X
+432 1242(directory.)N
+796(To)X
+939(accommodate)X
+1438(the)X
+1589(new)X
+1776(address,)X
+2090(the)X
+432 1330(directory)N
+752(is)X
+835(split)X
+2 f
+8 s
+972 1305(5)N
+1 f
+10 s
+1330(,)Y
+1054(by)X
+1163(doubling)X
+1476(it,)X
+1569(thus)X
+1731(increasing)X
+2090(the)X
+432 1418(depth)N
+630(of)X
+717(the)X
+835(directory)X
+1145(by)X
+1245(one.)X
+604 1532(After)N
+813(this)X
+967(split,)X
+1163(a)X
+1237(single)X
+1466(bit)X
+1588(of)X
+1693(the)X
+1829(hash)X
+2014(value)X
+432 1620(needs)N
+663(to)X
+773(be)X
+896(examined)X
+1255(to)X
+1364(decide)X
+1621(whether)X
+1927(the)X
+2072(key)X
+432 1708(belongs)N
+711(to)X
+803(L0)X
+922(or)X
+1019(L1.)X
+1158(Once)X
+1358(one)X
+1504(of)X
+1601(these)X
+1795(buckets)X
+2069(\256lls)X
+432 1796(\(L0)N
+578(for)X
+702(example\),)X
+1051(it)X
+1125(is)X
+1208(split)X
+1375(as)X
+1472(before,)X
+1728(and)X
+1873(the)X
+2000(direc-)X
+432 1884(tory)N
+585(is)X
+662(split)X
+823(again)X
+1021(to)X
+1107(make)X
+1305(room)X
+1498(for)X
+1615(the)X
+1736(address)X
+2000(of)X
+2090(the)X
+432 1972(third)N
+618(bucket.)X
+927(This)X
+1104(splitting)X
+1400(causes)X
+1645(the)X
+1778(addresses)X
+2121(of)X
+432 2060(the)N
+567(non-splitting)X
+1012(bucket)X
+1263(\(L1\))X
+1443(to)X
+1541(be)X
+1653(duplicated.)X
+2063(The)X
+432 2148(directory)N
+766(now)X
+948(has)X
+1099(four)X
+1277(entries,)X
+1555(a)X
+1635(depth)X
+1857(of)X
+1968(2,)X
+2072(and)X
+432 2236(indexes)N
+700(the)X
+821(buckets)X
+1089(L00,)X
+1261(L01)X
+1413(and)X
+1552(L1,)X
+1684(as)X
+1774(shown)X
+2006(in)X
+2090(the)X
+432 2324(Figure)N
+661(2.)X
+604 2438(The)N
+756(crucial)X
+1002(part)X
+1154(of)X
+1247(the)X
+1371(algorithm)X
+1708(is)X
+1787(the)X
+1911(observa-)X
+432 2526(tion)N
+580(that)X
+724(L1)X
+837(is)X
+914(addressed)X
+1255(twice)X
+1453(in)X
+1539(the)X
+1661(directory.)X
+1995(If)X
+2073(this)X
+432 2614(bucket)N
+679(were)X
+869(to)X
+964(split)X
+1134(now,)X
+1324(the)X
+1454(directory)X
+1776(already)X
+2045(con-)X
+432 2702(tains)N
+611(room)X
+808(to)X
+898(hold)X
+1067(the)X
+1192(address)X
+1460(of)X
+1554(the)X
+1679(new)X
+1840(bucket.)X
+2121(In)X
+432 2790(general,)N
+711(the)X
+831(relationship)X
+1231(between)X
+1521(the)X
+1641(directory)X
+1953(and)X
+2090(the)X
+432 2878(number)N
+704(of)X
+798(bucket)X
+1039(addresses)X
+1374(contained)X
+1713(therein)X
+1962(is)X
+2041(used)X
+432 2966(to)N
+517(decide)X
+750(when)X
+947(to)X
+1031(split)X
+1190(the)X
+1310(directory.)X
+1662(Each)X
+1845(bucket)X
+2081(has)X
+432 3054(a)N
+505(depth,)X
+740(\()X
+2 f
+767(n)X
+7 s
+3070(b)Y
+10 s
+1 f
+848 3054(\),)N
+932(associated)X
+1299(with)X
+1478(it)X
+1558(and)X
+1710(appears)X
+1992(in)X
+2090(the)X
+432 3142(directory)N
+744(exactly)X
+998(2)X
+2 f
+7 s
+3106(n)Y
+9 f
+1075(-)X
+2 f
+1106(n)X
+4 s
+3110(b)Y
+7 s
+1 f
+10 s
+1181 3142(times.)N
+1396(When)X
+1610(a)X
+1668(bucket)X
+1904(splits,)X
+2113(its)X
+432 3230(depth)N
+638(increases)X
+961(by)X
+1069(one.)X
+1253(The)X
+1406(directory)X
+1724(must)X
+1907(split)X
+2072(any)X
+432 3318(time)N
+602(a)X
+665(bucket's)X
+964(depth)X
+1169(exceeds)X
+1451(the)X
+1576(depth)X
+1781(of)X
+1875(the)X
+2000(direc-)X
+432 3406(tory.)N
+630(The)X
+784(following)X
+1123(code)X
+1303(fragment)X
+1621(helps)X
+1818(to)X
+1908(illustrate)X
+432 3494(the)N
+554(extendible)X
+912(hashing)X
+1185(algorithm)X
+1520([FAG79])X
+1838(for)X
+1955(access-)X
+432 3582(ing)N
+554(individual)X
+898(buckets)X
+1163(and)X
+1299(maintaining)X
+1701(the)X
+1819(directory.)X
+0 f
+8 s
+432 3881(hash)N
+622(=)X
+698 -0.4038(calchash\(key\);)AX
+432 3969(mask)N
+622(=)X
+698 -0.4018(maskvec[depth];)AX
+432 4145(bucket)N
+698(=)X
+774 -0.4038(directory[hash)AX
+1344(&)X
+1420(mask];)X
+432 4321(/*)N
+546(Key)X
+698 -0.4219(Insertion)AX
+1078(*/)X
+432 4409(if)N
+546 -0.4038(\(store\(bucket,)AX
+1116(key,)X
+1306(data\))X
+1534(==)X
+1648(FAIL\))X
+1876({)X
+720 4497(newbl)N
+948(=)X
+1024 -0.4167(getpage\(\);)AX
+720 4585 -0.4000(bucket->depth++;)AN
+720 4673 -0.4091(newbl->depth)AN
+1214(=)X
+1290 -0.4038(bucket->depth;)AX
+720 4761(if)N
+834 -0.4038(\(bucket->depth)AX
+1404(>)X
+1480(depth\))X
+1746({)X
+1008 4849(/*)N
+1122(double)X
+1388 -0.4219(directory)AX
+1768(*/)X
+1008 4937(depth++;)N
+1 f
+16 s
+432 5033 MXY
+864 0 Dl
+2 f
+8 s
+472 5088(5)N
+1 f
+9 s
+534 5113(This)N
+692(decision)X
+962(to)X
+1048(split)X
+1202(the)X
+1319(directory)X
+1608(is)X
+1685(based)X
+1878(on)X
+1979(a)X
+2040(com-)X
+432 5193(parison)N
+666(of)X
+748(the)X
+858(depth)X
+1040(of)X
+1121(the)X
+1230(page)X
+1387(being)X
+1568(split)X
+1713(and)X
+1838(the)X
+1947(depth)X
+2128(of)X
+432 5273(the)N
+543(trie.)X
+698(In)X
+781(Figure)X
+992(2,)X
+1069(the)X
+1180(depths)X
+1390(of)X
+1472(both)X
+1622(L00)X
+1760(and)X
+1886(L01)X
+2024(are)X
+2134(2,)X
+432 5353(whereas)N
+689(the)X
+798(depth)X
+979(of)X
+1060(L1)X
+1161(is)X
+1230(1.)X
+1323(Therefore,)X
+1646(if)X
+1710(L1)X
+1810(were)X
+1970(to)X
+2046(split,)X
+432 5433(the)N
+543(directory)X
+826(would)X
+1029(not)X
+1144(need)X
+1303(to)X
+1382(split.)X
+1565(In)X
+1648(reality,)X
+1872(a)X
+1926(bucket)X
+2140(is)X
+432 5513(allocated)N
+727(for)X
+846(the)X
+969(directory)X
+1264(at)X
+1351(the)X
+1474(time)X
+1637(of)X
+1732(\256le)X
+1858(creation)X
+2124(so)X
+432 5593(although)N
+707(the)X
+818(directory)X
+1100(splits)X
+1274(logically,)X
+1566(physical)X
+1828(splits)X
+2002(do)X
+2096(not)X
+432 5673(occur)N
+610(until)X
+760(the)X
+866(\256le)X
+976(becomes)X
+1246(quite)X
+1408(large.)X
+0 f
+8 s
+2994 538 -0.4219(directory)AN
+3374(=)X
+3450 -0.3971(double\(directory\);)AX
+2706 626(})N
+2706 714 -0.3958(splitbucket\(bucket,)AN
+3466(newbl\))X
+2706 802(...)N
+2418 890(})N
+2 f
+10 s
+3169 1255(hsearch)N
+1 f
+2590 1387(Since)N
+2 f
+2807(hsearch)X
+1 f
+3100(does)X
+3286(not)X
+3427(have)X
+3617(to)X
+3717(translate)X
+4027(hash)X
+2418 1475(values)N
+2659(into)X
+2819(disk)X
+2988(addresses,)X
+3352(it)X
+3432(can)X
+3579(use)X
+3721(much)X
+3934(simpler)X
+2418 1563(algorithms)N
+2808(than)X
+2994(those)X
+3211(de\256ned)X
+3495(above.)X
+3775(System)X
+4058(V's)X
+2 f
+2418 1651(hsearch)N
+1 f
+2708(constructs)X
+3069(a)X
+3141(\256xed-size)X
+3489(hash)X
+3671(table)X
+3862(\(speci\256ed)X
+2418 1739(by)N
+2519(the)X
+2637(user)X
+2791(at)X
+2869(table)X
+3045(creation\).)X
+3391(By)X
+3504(default,)X
+3767(a)X
+3823(multiplica-)X
+2418 1827(tive)N
+2570(hash)X
+2748(function)X
+3046(based)X
+3260(on)X
+3371(that)X
+3522(described)X
+3861(in)X
+3954(Knuth,)X
+2418 1915(Volume)N
+2710(3,)X
+2804(section)X
+3065(6.4)X
+3199([KNU68])X
+3541(is)X
+3628(used)X
+3809(to)X
+3905(obtain)X
+4138(a)X
+2418 2003(primary)N
+2694(bucket)X
+2930(address.)X
+3233(If)X
+3309(this)X
+3446(bucket)X
+3681(is)X
+3755(full,)X
+3907(a)X
+3964(secon-)X
+2418 2091(dary)N
+2593(multiplicative)X
+3069(hash)X
+3248(value)X
+3454(is)X
+3538(computed)X
+3885(to)X
+3978(de\256ne)X
+2418 2179(the)N
+2542(probe)X
+2751(interval.)X
+3062(The)X
+3213(probe)X
+3422(interval)X
+3693(is)X
+3772(added)X
+3989(to)X
+4076(the)X
+2418 2267(original)N
+2712(bucket)X
+2971(address)X
+3257(\(modulo)X
+3573(the)X
+3716(table)X
+3916(size\))X
+4112(to)X
+2418 2355(obtain)N
+2658(a)X
+2734(new)X
+2908(bucket)X
+3162(address.)X
+3483(This)X
+3665(process)X
+3946(repeats)X
+2418 2443(until)N
+2588(an)X
+2688(empty)X
+2911(bucket)X
+3148(is)X
+3224(found.)X
+3474(If)X
+3551(no)X
+3654(bucket)X
+3891(is)X
+3967(found,)X
+2418 2531(an)N
+2514(insertion)X
+2814(fails)X
+2972(with)X
+3134(a)X
+3190(``table)X
+3420(full'')X
+3605(condition.)X
+2590 2645(The)N
+2768(basic)X
+2986(algorithm)X
+3350(may)X
+3541(be)X
+3670(modi\256ed)X
+4006(by)X
+4138(a)X
+2418 2733(number)N
+2705(of)X
+2813(compile)X
+3112(time)X
+3295(options)X
+3571(available)X
+3902(to)X
+4005(those)X
+2418 2821(users)N
+2604(with)X
+2767(AT&T)X
+3006(source)X
+3237(code.)X
+3450(First,)X
+3637(the)X
+3756(package)X
+4040(pro-)X
+2418 2909(vides)N
+2638(two)X
+2809(options)X
+3094(for)X
+3238(hash)X
+3435(functions.)X
+3803(Users)X
+4036(may)X
+2418 2997(specify)N
+2690(their)X
+2877(own)X
+3055(hash)X
+3242(function)X
+3549(by)X
+3669(compiling)X
+4032(with)X
+2418 3085(``USCR'')N
+2757(de\256ned)X
+3016(and)X
+3155(declaring)X
+3477(and)X
+3616(de\256ning)X
+3901(the)X
+4022(vari-)X
+2418 3173(able)N
+2 f
+2578(hcompar)X
+1 f
+2863(,)X
+2909(a)X
+2971(function)X
+3263(taking)X
+3488(two)X
+3633(string)X
+3840(arguments)X
+2418 3261(and)N
+2560(returning)X
+2880(an)X
+2982(integer.)X
+3271(Users)X
+3480(may)X
+3643(also)X
+3797(request)X
+4054(that)X
+2418 3349(hash)N
+2587(values)X
+2814(be)X
+2912(computed)X
+3250(simply)X
+3489(by)X
+3590(taking)X
+3811(the)X
+3930(modulo)X
+2418 3437(of)N
+2521(key)X
+2673(\(using)X
+2909(division)X
+3201(rather)X
+3424(than)X
+3597(multiplication)X
+4080(for)X
+2418 3525(hash)N
+2589(value)X
+2787(calculation\).)X
+3230(If)X
+3308(this)X
+3447(technique)X
+3783(is)X
+3859(used,)X
+4049(col-)X
+2418 3613(lisions)N
+2651(are)X
+2775(resolved)X
+3072(by)X
+3176(scanning)X
+3485(sequentially)X
+3896(from)X
+4076(the)X
+2418 3701(selected)N
+2702(bucket)X
+2941(\(linear)X
+3176(probing\).)X
+3517(This)X
+3684(option)X
+3913(is)X
+3991(avail-)X
+2418 3789(able)N
+2572(by)X
+2672(de\256ning)X
+2954(the)X
+3072(variable)X
+3351(``DIV'')X
+3622(at)X
+3700(compile)X
+3978(time.)X
+2590 3903(A)N
+2720(second)X
+3015(option,)X
+3311(based)X
+3565(on)X
+3716(an)X
+3863(algorithm)X
+2418 3991(discovered)N
+2787(by)X
+2888(Richard)X
+3163(P.)X
+3248(Brent,)X
+3466(rearranges)X
+3822(the)X
+3940(table)X
+4116(at)X
+2418 4079(the)N
+2549(time)X
+2724(of)X
+2824(insertion)X
+3137(in)X
+3232(order)X
+3434(to)X
+3528(speed)X
+3743(up)X
+3855(retrievals.)X
+2418 4167(The)N
+2571(basic)X
+2764(idea)X
+2926(is)X
+3007(to)X
+3097(shorten)X
+3361(long)X
+3531(probe)X
+3741(sequences)X
+4094(by)X
+2418 4255(lengthening)N
+2833(short)X
+3030(probe)X
+3249(sequences.)X
+3651(Once)X
+3857(the)X
+3991(probe)X
+2418 4343(chain)N
+2613(has)X
+2741(exceeded)X
+3062(some)X
+3252(threshold)X
+3571(\(Brent)X
+3796(suggests)X
+4087(2\),)X
+2418 4431(we)N
+2541(attempt)X
+2809(to)X
+2899(shuf\257e)X
+3145(any)X
+3289(colliding)X
+3601(keys)X
+3776(\(keys)X
+3978(which)X
+2418 4519(appeared)N
+2734(in)X
+2821(the)X
+2944(probe)X
+3152(sequence)X
+3471(of)X
+3562(the)X
+3684(new)X
+3842(key\).)X
+4049(The)X
+2418 4607(details)N
+2652(of)X
+2744(this)X
+2884(key)X
+3025(shuf\257ing)X
+3333(can)X
+3469(be)X
+3569(found)X
+3780(in)X
+3866([KNU68])X
+2418 4695(and)N
+2576([BRE73].)X
+2946(This)X
+3129(algorithm)X
+3481(may)X
+3660(be)X
+3777(obtained)X
+4094(by)X
+2418 4783(de\256ning)N
+2700(the)X
+2818(variable)X
+3097(``BRENT'')X
+3487(at)X
+3565(compile)X
+3843(time.)X
+2590 4897(A)N
+2698(third)X
+2899(set)X
+3038(of)X
+3154(options,)X
+3458(obtained)X
+3783(by)X
+3912(de\256ning)X
+2418 4985(``CHAINED'',)N
+2943(use)X
+3086(linked)X
+3321(lists)X
+3484(to)X
+3581(resolve)X
+3848(collisions.)X
+2418 5073(Either)N
+2647(of)X
+2747(the)X
+2878(primary)X
+3164(hash)X
+3343(function)X
+3642(described)X
+3982(above)X
+2418 5161(may)N
+2584(be)X
+2688(used,)X
+2882(but)X
+3011(all)X
+3118(collisions)X
+3451(are)X
+3577(resolved)X
+3876(by)X
+3983(build-)X
+2418 5249(ing)N
+2554(a)X
+2623(linked)X
+2856(list)X
+2986(of)X
+3086(entries)X
+3333(from)X
+3522(the)X
+3653(primary)X
+3940(bucket.)X
+2418 5337(By)N
+2542(default,)X
+2816(new)X
+2981(entries)X
+3226(will)X
+3381(be)X
+3488(added)X
+3711(to)X
+3804(a)X
+3871(bucket)X
+4116(at)X
+2418 5425(the)N
+2541(beginning)X
+2886(of)X
+2978(the)X
+3101(bucket)X
+3339(chain.)X
+3577(However,)X
+3916(compile)X
+2418 5513(options)N
+2706(``SORTUP'')X
+3173(or)X
+3293(``SORTDOWN'')X
+3908(may)X
+4098(be)X
+2418 5601(speci\256ed)N
+2723(to)X
+2805(order)X
+2995(the)X
+3113(hash)X
+3280(chains)X
+3505(within)X
+3729(each)X
+3897(bucket.)X
+3 f
+432 5960(4)N
+2970(USENIX)X
+9 f
+3292(-)X
+3 f
+3356(Winter)X
+3621('91)X
+9 f
+3748(-)X
+3 f
+3812(Dallas,)X
+4065(TX)X
+
+5 p
+%%Page: 5 5
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+720 258(Seltzer)N
+977(&)X
+1064(Yigit)X
+3278(A)X
+3356(New)X
+3528(Hashing)X
+3831(Package)X
+4136(for)X
+4259(UNIX)X
+2 f
+1444 538(dynahash)N
+1 f
+892 670(The)N
+2 f
+1054(dynahash)X
+1 f
+1398(library,)X
+1669(written)X
+1932(by)X
+2048(Esmond)X
+2346(Pitt,)X
+720 758(implements)N
+1183(Larson's)X
+1554(linear)X
+1827(hashing)X
+2165(algorithm)X
+720 846([LAR88])N
+1097(with)X
+1302(an)X
+2 f
+1440(hsearch)X
+1 f
+1756(compatible)X
+2174(interface.)X
+720 934(Intuitively,)N
+1099(a)X
+1161(hash)X
+1334(table)X
+1516(begins)X
+1751(as)X
+1844(a)X
+1905(single)X
+2121(bucket)X
+2360(and)X
+720 1022(grows)N
+941(in)X
+1028(generations,)X
+1443(where)X
+1665(a)X
+1725(generation)X
+2088(corresponds)X
+720 1110(to)N
+815(a)X
+884(doubling)X
+1201(in)X
+1296(the)X
+1427(size)X
+1585(of)X
+1685(the)X
+1815(hash)X
+1994(table.)X
+2222(The)X
+2379(0)X
+2 f
+7 s
+1078(th)Y
+10 s
+1 f
+720 1198(generation)N
+1085(occurs)X
+1321(as)X
+1414(the)X
+1538(table)X
+1719(grows)X
+1940(from)X
+2121(one)X
+2262(bucket)X
+720 1286(to)N
+814(two.)X
+1006(In)X
+1105(the)X
+1235(next)X
+1405(generation)X
+1776(the)X
+1906(table)X
+2093(grows)X
+2320(from)X
+720 1374(two)N
+862(to)X
+946(four.)X
+1122(During)X
+1371(each)X
+1541(generation,)X
+1921(every)X
+2121(bucket)X
+2356(that)X
+720 1462(existed)N
+967(at)X
+1045(the)X
+1163(beginning)X
+1503(of)X
+1590(the)X
+1708(generation)X
+2067(is)X
+2140(split.)X
+892 1576(The)N
+1041(table)X
+1221(starts)X
+1414(as)X
+1505(a)X
+1565(single)X
+1780(bucket)X
+2018(\(numbered)X
+2389(0\),)X
+720 1664(the)N
+839(current)X
+1088(split)X
+1245(bucket)X
+1479(is)X
+1552(set)X
+1661(to)X
+1743(bucket)X
+1977(0,)X
+2057(and)X
+2193(the)X
+2311(max-)X
+720 1752(imum)N
+933(split)X
+1097(point)X
+1288(is)X
+1368(set)X
+1483(to)X
+1571(twice)X
+1771(the)X
+1895(current)X
+2149(split)X
+2312(point)X
+720 1840(\(0\).)N
+863(When)X
+1084(it)X
+1157(is)X
+1239(time)X
+1410(for)X
+1532(a)X
+1596(bucket)X
+1838(to)X
+1928(split,)X
+2113(the)X
+2239(keys)X
+2414(in)X
+720 1928(the)N
+872(current)X
+1154(split)X
+1345(bucket)X
+1612(are)X
+1764(divided)X
+2057(between)X
+2378(the)X
+720 2016(current)N
+981(split)X
+1151(bucket)X
+1397(and)X
+1545(a)X
+1613(new)X
+1779(bucket)X
+2025(whose)X
+2262(bucket)X
+720 2104(number)N
+1000(is)X
+1088(equal)X
+1297(to)X
+1394(1)X
+1469(+)X
+1549(current)X
+1812(split)X
+1984(bucket)X
+2232(+)X
+2311(max-)X
+720 2192(imum)N
+927(split)X
+1085(point.)X
+1310(We)X
+1442(can)X
+1574(determine)X
+1915(which)X
+2131(keys)X
+2298(move)X
+720 2280(to)N
+807(the)X
+929(new)X
+1087(bucket)X
+1325(by)X
+1429(examining)X
+1791(the)X
+2 f
+1913(n)X
+7 s
+1962 2248(th)N
+10 s
+1 f
+2043 2280(bit)N
+2151(of)X
+2242(a)X
+2302(key's)X
+720 2368(hash)N
+899(value)X
+1105(where)X
+1334(n)X
+1406(is)X
+1491(the)X
+1620(generation)X
+1990(number.)X
+2306(After)X
+720 2456(the)N
+846(bucket)X
+1088(at)X
+1174(the)X
+1300(maximum)X
+1651(split)X
+1815(point)X
+2006(has)X
+2140(been)X
+2319(split,)X
+720 2544(the)N
+839(generation)X
+1198(number)X
+1463(is)X
+1536(incremented,)X
+1973(the)X
+2091(current)X
+2339(split)X
+720 2632(point)N
+908(is)X
+985(set)X
+1098(back)X
+1274(to)X
+1360(zero,)X
+1543(and)X
+1683(the)X
+1805(maximum)X
+2152(split)X
+2312(point)X
+720 2720(is)N
+815(set)X
+946(to)X
+1050(the)X
+1190(number)X
+1477(of)X
+1586(the)X
+1725(last)X
+1877(bucket)X
+2132(in)X
+2235(the)X
+2374(\256le)X
+720 2808(\(which)N
+971(is)X
+1052(equal)X
+1253(to)X
+1342(twice)X
+1543(the)X
+1668(old)X
+1797(maximum)X
+2148(split)X
+2312(point)X
+720 2896(plus)N
+873(1\).)X
+892 3010(To)N
+1031(facilitate)X
+1361(locating)X
+1668(keys,)X
+1884(we)X
+2027(maintain)X
+2356(two)X
+720 3098(masks.)N
+989(The)X
+1143(low)X
+1291(mask)X
+1488(is)X
+1569(equal)X
+1771(to)X
+1861(the)X
+1987(maximum)X
+2339(split)X
+720 3186(bucket)N
+967(and)X
+1116(the)X
+1247(high)X
+1422(mask)X
+1624(is)X
+1710(equal)X
+1917(to)X
+2011(the)X
+2141(next)X
+2311(max-)X
+720 3274(imum)N
+931(split)X
+1093(bucket.)X
+1372(To)X
+1486(locate)X
+1703(a)X
+1764(speci\256c)X
+2033(key,)X
+2193(we)X
+2311(com-)X
+720 3362(pute)N
+881(a)X
+940(32-bit)X
+1154(hash)X
+1324(value)X
+1520(using)X
+1715(a)X
+1773(bit-randomizing)X
+2311(algo-)X
+720 3450(rithm)N
+932(such)X
+1118(as)X
+1224(the)X
+1361(one)X
+1516(described)X
+1862(in)X
+1962([LAR88].)X
+2334(This)X
+720 3538(hash)N
+893(value)X
+1093(is)X
+1172(then)X
+1336(masked)X
+1607(with)X
+1775(the)X
+1898(high)X
+2065(mask.)X
+2299(If)X
+2378(the)X
+720 3626(resulting)N
+1026(number)X
+1297(is)X
+1376(greater)X
+1626(than)X
+1790(the)X
+1913(maximum)X
+2262(bucket)X
+720 3714(in)N
+823(the)X
+962(table)X
+1159(\(current)X
+1455(split)X
+1633(bucket)X
+1888(+)X
+1974(maximum)X
+2339(split)X
+720 3802(point\),)N
+962(the)X
+1091(hash)X
+1269(value)X
+1474(is)X
+1558(masked)X
+1834(with)X
+2007(the)X
+2136(low)X
+2287(mask.)X
+720 3890(In)N
+825(either)X
+1046(case,)X
+1242(the)X
+1377(result)X
+1592(of)X
+1696(the)X
+1831(mask)X
+2037(is)X
+2127(the)X
+2262(bucket)X
+720 3978(number)N
+989(for)X
+1107(the)X
+1229(given)X
+1431(key.)X
+1611(The)X
+1759(algorithm)X
+2093(below)X
+2312(illus-)X
+720 4066(trates)N
+914(this)X
+1049(process.)X
+0 f
+8 s
+720 4365(h)N
+796(=)X
+872 -0.4038(calchash\(key\);)AX
+720 4453(bucket)N
+986(=)X
+1062(h)X
+1138(&)X
+1214 -0.4167(high_mask;)AX
+720 4541(if)N
+834(\()X
+910(bucket)X
+1176(>)X
+1252 -0.4167(max_bucket)AX
+1670(\))X
+1008 4629(bucket)N
+1274(=)X
+1350(h)X
+1426(&)X
+1502 -0.4219(low_mask;)AX
+720 4717 -0.4018(return\(bucket\);)AN
+1 f
+10 s
+892 5042(In)N
+1013(order)X
+1237(to)X
+1353(decide)X
+1617(when)X
+1845(to)X
+1961(split)X
+2152(a)X
+2242(bucket,)X
+2 f
+720 5130(dynahash)N
+1 f
+1050(uses)X
+2 f
+1210(controlled)X
+1561(splitting)X
+1 f
+1822(.)X
+1884(A)X
+1964(hash)X
+2133(table)X
+2311(has)X
+2440(a)X
+720 5218(\256ll)N
+837(factor)X
+1054(which)X
+1279(is)X
+1361(expressed)X
+1707(in)X
+1798(terms)X
+2004(of)X
+2099(the)X
+2225(average)X
+720 5306(number)N
+990(of)X
+1082(keys)X
+1253(in)X
+1339(each)X
+1511(bucket.)X
+1789(Each)X
+1974(time)X
+2140(the)X
+2262(table's)X
+720 5394(total)N
+885(number)X
+1153(of)X
+1243(keys)X
+1413(divided)X
+1676(by)X
+1778(its)X
+1875(number)X
+2142(of)X
+2231(buckets)X
+720 5482(exceeds)N
+995(this)X
+1130(\256ll)X
+1238(factor,)X
+1466(a)X
+1522(bucket)X
+1756(is)X
+1829(split.)X
+2878 538(Since)N
+3079(the)X
+2 f
+3200(hsearch)X
+1 f
+3477(create)X
+3693(interface)X
+3998(\()X
+2 f
+4025(hcreate)X
+1 f
+4266(\))X
+4315(calls)X
+2706 626(for)N
+2842(an)X
+2960(estimate)X
+3269(of)X
+3378(the)X
+3518(\256nal)X
+3702(size)X
+3869(of)X
+3978(the)X
+4118(hash)X
+4306(table)X
+2706 714(\()N
+2 f
+2733(nelem)X
+1 f
+2925(\),)X
+2 f
+3007(dynahash)X
+1 f
+3349(uses)X
+3522(this)X
+3672(information)X
+4085(to)X
+4182(initialize)X
+2706 802(the)N
+2848(table.)X
+3088(The)X
+3257(initial)X
+3486(number)X
+3774(of)X
+3884(buckets)X
+4172(is)X
+4268(set)X
+4400(to)X
+2 f
+2706 890(nelem)N
+1 f
+2926(rounded)X
+3217(to)X
+3306(the)X
+3431(next)X
+3596(higher)X
+3828(power)X
+4056(of)X
+4150(two.)X
+4337(The)X
+2706 978(current)N
+2958(split)X
+3118(point)X
+3305(is)X
+3381(set)X
+3493(to)X
+3578(0)X
+3641(and)X
+3780(the)X
+3901(maximum)X
+4248(bucket)X
+2706 1066(and)N
+2842(maximum)X
+3186(split)X
+3343(point)X
+3527(are)X
+3646(set)X
+3755(to)X
+3837(this)X
+3972(rounded)X
+4255(value.)X
+3 f
+3148 1220(The)N
+3301(New)X
+3473(Implementation)X
+1 f
+2878 1352(Our)N
+3042(implementation)X
+3583(is)X
+3675(also)X
+3842(based)X
+4063(on)X
+4181(Larson's)X
+2706 1440(linear)N
+2939(hashing)X
+3238([LAR88])X
+3582(algorithm)X
+3943(as)X
+4060(well)X
+4248(as)X
+4364(the)X
+2 f
+2706 1528(dynahash)N
+1 f
+3047(implementation.)X
+3623(The)X
+2 f
+3782(dbm)X
+1 f
+3954(family)X
+4197(of)X
+4297(algo-)X
+2706 1616(rithms)N
+2942(decide)X
+3184(dynamically)X
+3612(which)X
+3840(bucket)X
+4085(to)X
+4178(split)X
+4346(and)X
+2706 1704(when)N
+2914(to)X
+3010(split)X
+3180(it)X
+3257(\(when)X
+3491(it)X
+3568(over\257ows\))X
+3944(while)X
+2 f
+4155(dynahash)X
+1 f
+2706 1792(splits)N
+2933(in)X
+3054(a)X
+3149(prede\256ned)X
+3547(order)X
+3776(\(linearly\))X
+4134(and)X
+4309(at)X
+4426(a)X
+2706 1880(prede\256ned)N
+3116(time)X
+3328(\(when)X
+3599(the)X
+3767(table)X
+3993(\256ll)X
+4151(factor)X
+4409(is)X
+2706 1968(exceeded\).)N
+3121(We)X
+3280(use)X
+3434(a)X
+3517(hybrid)X
+3773(of)X
+3887(these)X
+4099(techniques.)X
+2706 2056(Splits)N
+2913(occur)X
+3118(in)X
+3206(the)X
+3330(prede\256ned)X
+3695(order)X
+3891(of)X
+3984(linear)X
+4193(hashing,)X
+2706 2144(but)N
+2845(the)X
+2980(time)X
+3159(at)X
+3253(which)X
+3485(pages)X
+3704(are)X
+3839(split)X
+4012(is)X
+4101(determined)X
+2706 2232(both)N
+2869(by)X
+2970(page)X
+3143(over\257ows)X
+3480(\()X
+2 f
+3507(uncontrolled)X
+3937(splitting)X
+1 f
+4198(\))X
+4246(and)X
+4382(by)X
+2706 2320(exceeding)N
+3052(the)X
+3170(\256ll)X
+3278(factor)X
+3486(\()X
+2 f
+3513(controlled)X
+3862(splitting)X
+1 f
+4123(\))X
+2878 2434(A)N
+2962(hash)X
+3135(table)X
+3317(is)X
+3395(parameterized)X
+3876(by)X
+3981(both)X
+4148(its)X
+4248(bucket)X
+2706 2522(size)N
+2904(\()X
+2 f
+2931(bsize)X
+1 f
+(\))S
+3191(and)X
+3380(\256ll)X
+3541(factor)X
+3801(\()X
+2 f
+3828(ffactor)X
+1 f
+4041(\).)X
+4180(Whereas)X
+2 f
+2706 2610(dynahash's)N
+1 f
+3095(buckets)X
+3364(can)X
+3500(be)X
+3599(represented)X
+3993(as)X
+4083(a)X
+4142(linked)X
+4365(list)X
+2706 2698(of)N
+2798(elements)X
+3108(in)X
+3195(memory,)X
+3507(our)X
+3639(package)X
+3928(needs)X
+4136(to)X
+4222(support)X
+2706 2786(disk)N
+2874(access,)X
+3135(and)X
+3286(must)X
+3476(represent)X
+3806(buckets)X
+4086(in)X
+4183(terms)X
+4395(of)X
+2706 2874(pages.)N
+2955(The)X
+2 f
+3106(bsize)X
+1 f
+3291(is)X
+3369(the)X
+3492(size)X
+3642(\(in)X
+3756(bytes\))X
+3977(of)X
+4069(these)X
+4259(pages.)X
+2706 2962(As)N
+2833(in)X
+2933(linear)X
+3154(hashing,)X
+3461(the)X
+3597(number)X
+3879(of)X
+3983(buckets)X
+4265(in)X
+4364(the)X
+2706 3050(table)N
+2906(is)X
+3003(equal)X
+3221(to)X
+3327(the)X
+3469(number)X
+3758(of)X
+3869(keys)X
+4060(in)X
+4165(the)X
+4306(table)X
+2706 3138(divided)N
+2988(by)X
+2 f
+3110(ffactor)X
+1 f
+3323(.)X
+2 f
+8 s
+3113(6)Y
+1 f
+10 s
+3417 3138(The)N
+3584(controlled)X
+3950(splitting)X
+4252(occurs)X
+2706 3226(each)N
+2878(time)X
+3044(the)X
+3166(number)X
+3435(of)X
+3526(keys)X
+3697(in)X
+3783(the)X
+3905(table)X
+4085(exceeds)X
+4364(the)X
+2706 3314(\256ll)N
+2814(factor)X
+3022(multiplied)X
+3370(by)X
+3470(the)X
+3588(number)X
+3853(of)X
+3940(buckets.)X
+2878 3428(Inserting)N
+3187(keys)X
+3358(and)X
+3498(splitting)X
+3783(buckets)X
+4051(is)X
+4127(performed)X
+2706 3516(precisely)N
+3018(as)X
+3107(described)X
+3437(previously)X
+3796(for)X
+2 f
+3911(dynahash)X
+1 f
+4218(.)X
+4279(How-)X
+2706 3604(ever,)N
+2897(since)X
+3094(buckets)X
+3371(are)X
+3502(now)X
+3671(comprised)X
+4036(of)X
+4134(pages,)X
+4368(we)X
+2706 3692(must)N
+2883(be)X
+2981(prepared)X
+3284(to)X
+3367(handle)X
+3602(cases)X
+3793(where)X
+4011(the)X
+4130(size)X
+4276(of)X
+4364(the)X
+2706 3780(keys)N
+2873(and)X
+3009(data)X
+3163(in)X
+3245(a)X
+3301(bucket)X
+3535(exceed)X
+3779(the)X
+3897(bucket)X
+4131(size.)X
+3 f
+3318 3934(Over\257ow)N
+3654(Pages)X
+1 f
+2878 4066(There)N
+3095(are)X
+3223(two)X
+3372(cases)X
+3571(where)X
+3797(a)X
+3862(key)X
+4007(may)X
+4174(not)X
+4305(\256t)X
+4400(in)X
+2706 4154(its)N
+2802(designated)X
+3166(bucket.)X
+3441(In)X
+3529(the)X
+3647(\256rst)X
+3791(case,)X
+3970(the)X
+4088(total)X
+4250(size)X
+4395(of)X
+2706 4242(the)N
+2833(key)X
+2978(and)X
+3123(data)X
+3286(may)X
+3453(exceed)X
+3706(the)X
+3833(bucket)X
+4076(size.)X
+4269(In)X
+4364(the)X
+2706 4330(second,)N
+3008(addition)X
+3328(of)X
+3453(a)X
+3547(new)X
+3739(key)X
+3913(could)X
+4149(cause)X
+4386(an)X
+2706 4418(over\257ow,)N
+3068(but)X
+3227(the)X
+3382(bucket)X
+3652(in)X
+3770(question)X
+4097(is)X
+4206(not)X
+4364(yet)X
+2706 4506(scheduled)N
+3049(to)X
+3133(be)X
+3230(split.)X
+3428(In)X
+3516(existing)X
+3790(implementations,)X
+4364(the)X
+2706 4594(second)N
+2953(case)X
+3115(never)X
+3317(arises)X
+3523(\(since)X
+3738(buckets)X
+4006(are)X
+4128(split)X
+4288(when)X
+2706 4682(they)N
+2871(over\257ow\))X
+3210(and)X
+3352(the)X
+3476(\256rst)X
+3626(case)X
+3791(is)X
+3870(not)X
+3998(handled)X
+4278(at)X
+4362(all.)X
+2706 4770(Although)N
+3036(large)X
+3225(key/data)X
+3525(pair)X
+3678(handling)X
+3986(is)X
+4066(dif\256cult)X
+4346(and)X
+2706 4858(expensive,)N
+3083(it)X
+3163(is)X
+3252(essential.)X
+3604(In)X
+3706(a)X
+3777(linear)X
+3995(hashed)X
+4253(imple-)X
+2706 4946(mentation,)N
+3087(over\257ow)X
+3413(pages)X
+3636(are)X
+3775(required)X
+4083(for)X
+4217(buckets)X
+2706 5034(which)N
+2935(over\257ow)X
+3253(before)X
+3492(they)X
+3662(are)X
+3793(split,)X
+3982(so)X
+4085(we)X
+4211(can)X
+4355(use)X
+2706 5122(the)N
+2833(same)X
+3027(mechanism)X
+3421(for)X
+3544(large)X
+3734(key/data)X
+4035(pairs)X
+4220(that)X
+4368(we)X
+2706 5210(use)N
+2837(for)X
+2955(over\257ow)X
+3264(pages.)X
+3511(Logically,)X
+3862(we)X
+3980(chain)X
+4177(over\257ow)X
+16 s
+2706 5353 MXY
+864 0 Dl
+2 f
+8 s
+2746 5408(6)N
+1 f
+9 s
+2801 5433(This)N
+2952(is)X
+3023(not)X
+3138(strictly)X
+3361(true.)X
+3532(The)X
+3667(\256le)X
+3782(does)X
+3937(not)X
+4052(contract)X
+4306(when)X
+2706 5513(keys)N
+2861(are)X
+2972(deleted,)X
+3221(so)X
+3308(the)X
+3419(number)X
+3662(of)X
+3744(buckets)X
+3986(is)X
+4056(actually)X
+4306(equal)X
+2706 5593(to)N
+2782(the)X
+2890(maximum)X
+3202(number)X
+3441(of)X
+3520(keys)X
+3671(ever)X
+3814(present)X
+4041(in)X
+4116(the)X
+4223(table)X
+4382(di-)X
+2706 5673(vided)N
+2884(by)X
+2974(the)X
+3080(\256ll)X
+3178(factor.)X
+3 f
+10 s
+720 5960(USENIX)N
+9 f
+1042(-)X
+3 f
+1106(Winter)X
+1371('91)X
+9 f
+1498(-)X
+3 f
+1562(Dallas,)X
+1815(TX)X
+4424(5)X
+
+6 p
+%%Page: 6 6
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+432 258(A)N
+510(New)X
+682(Hashing)X
+985(Package)X
+1290(for)X
+1413(UNIX)X
+3663(Seltzer)X
+3920(&)X
+4007(Yigit)X
+1 f
+432 538(pages)N
+639(to)X
+725(the)X
+847(buckets)X
+1116(\(also)X
+1296(called)X
+1512(primary)X
+1789(pages\).)X
+2062(In)X
+2152(a)X
+432 626(memory)N
+730(based)X
+943(representation,)X
+1448(over\257ow)X
+1763(pages)X
+1976(do)X
+2086(not)X
+432 714(pose)N
+628(any)X
+792(special)X
+1063(problems)X
+1409(because)X
+1712(we)X
+1854(can)X
+2014(chain)X
+432 802(over\257ow)N
+776(pages)X
+1017(to)X
+1137(primary)X
+1449(pages)X
+1690(using)X
+1921(memory)X
+432 890(pointers.)N
+776(However,)X
+1137(mapping)X
+1463(these)X
+1674(over\257ow)X
+2005(pages)X
+432 978(into)N
+584(a)X
+648(disk)X
+809(\256le)X
+939(is)X
+1019(more)X
+1211(of)X
+1305(a)X
+1368(challenge,)X
+1723(since)X
+1915(we)X
+2036(need)X
+432 1066(to)N
+547(be)X
+675(able)X
+861(to)X
+975(address)X
+1268(both)X
+1462(bucket)X
+1728(pages,)X
+1983(whose)X
+432 1154(numbers)N
+729(are)X
+849(growing)X
+1137(linearly,)X
+1422(and)X
+1558(some)X
+1747(indeterminate)X
+432 1242(number)N
+715(of)X
+820(over\257ow)X
+1143(pages)X
+1364(without)X
+1646(reorganizing)X
+2090(the)X
+432 1330(\256le.)N
+604 1444(One)N
+789(simple)X
+1053(solution)X
+1361(would)X
+1612(be)X
+1739(to)X
+1852(allocate)X
+2152(a)X
+432 1532(separate)N
+737(\256le)X
+880(for)X
+1015(over\257ow)X
+1341(pages.)X
+1604(The)X
+1769(disadvantage)X
+432 1620(with)N
+605(such)X
+783(a)X
+850(technique)X
+1193(is)X
+1276(that)X
+1426(it)X
+1500(requires)X
+1789(an)X
+1895(extra)X
+2086(\256le)X
+432 1708(descriptor,)N
+794(an)X
+891(extra)X
+1073(system)X
+1316(call)X
+1453(on)X
+1554(open)X
+1731(and)X
+1867(close,)X
+2072(and)X
+432 1796(logically)N
+739(associating)X
+1122(two)X
+1269(independent)X
+1687(\256les.)X
+1886(For)X
+2023(these)X
+432 1884(reasons,)N
+728(we)X
+857(wanted)X
+1123(to)X
+1219(map)X
+1391(both)X
+1567(primary)X
+1855(pages)X
+2072(and)X
+432 1972(over\257ow)N
+737(pages)X
+940(into)X
+1084(the)X
+1202(same)X
+1387(\256le)X
+1509(space.)X
+604 2086(The)N
+799(buddy-in-waiting)X
+1425(algorithm)X
+1806(provides)X
+2152(a)X
+432 2174(mechanism)N
+851(to)X
+966(support)X
+1259(multiple)X
+1578(pages)X
+1814(per)X
+1970(logical)X
+432 2262(bucket)N
+685(while)X
+902(retaining)X
+1226(the)X
+1362(simple)X
+1613(split)X
+1788(sequence)X
+2121(of)X
+432 2350(linear)N
+681(hashing.)X
+1015(Over\257ow)X
+1383(pages)X
+1631(are)X
+1795(preallocated)X
+432 2438(between)N
+781(generations)X
+1232(of)X
+1379(primary)X
+1713(pages.)X
+1996(These)X
+432 2526(over\257ow)N
+759(pages)X
+984(are)X
+1125(used)X
+1314(by)X
+1436(any)X
+1594(bucket)X
+1850(containing)X
+432 2614(more)N
+646(keys)X
+842(than)X
+1029(\256t)X
+1144(on)X
+1273(the)X
+1420(primary)X
+1723(page)X
+1924(and)X
+2089(are)X
+432 2702(reclaimed,)N
+808(if)X
+896(possible,)X
+1217(when)X
+1430(the)X
+1567(bucket)X
+1819(later)X
+2000(splits.)X
+432 2790(Figure)N
+687(3)X
+773(depicts)X
+1045(the)X
+1188(layout)X
+1433(of)X
+1545(primary)X
+1844(pages)X
+2072(and)X
+432 2878(over\257ow)N
+752(pages)X
+970(within)X
+1209(the)X
+1342(same)X
+1542(\256le.)X
+1699(Over\257ow)X
+2036(page)X
+432 2966(use)N
+586(information)X
+1011(is)X
+1111(recorded)X
+1440(in)X
+1548(bitmaps)X
+1847(which)X
+2089(are)X
+432 3054(themselves)N
+819(stored)X
+1046(on)X
+1157(over\257ow)X
+1472(pages.)X
+1725(The)X
+1880(addresses)X
+432 3142(of)N
+520(the)X
+639(bitmap)X
+882(pages)X
+1086(and)X
+1223(the)X
+1342(number)X
+1608(of)X
+1695(pages)X
+1898(allocated)X
+432 3230(at)N
+515(each)X
+688(split)X
+850(point)X
+1039(are)X
+1163(stored)X
+1384(in)X
+1470(the)X
+1592(\256le)X
+1718(header.)X
+1997(Using)X
+432 3318(this)N
+577(information,)X
+1005(both)X
+1177(over\257ow)X
+1492(addresses)X
+1829(and)X
+1974(bucket)X
+432 3406(addresses)N
+764(can)X
+900(be)X
+999(mapped)X
+1276(to)X
+1361(disk)X
+1517(addresses)X
+1848(by)X
+1951(the)X
+2072(fol-)X
+432 3494(lowing)N
+674(calculation:)X
+0 f
+8 s
+432 3793(int)N
+736(bucket;)X
+1192(/*)X
+1306(bucket)X
+1572(address)X
+1876(*/)X
+432 3881(u_short)N
+736(oaddr;)X
+1192(/*)X
+1306(OVERFLOW)X
+1648(address)X
+1952(*/)X
+432 3969(int)N
+736 -0.4125(nhdr_pages;)AX
+1192(/*)X
+1306(npages)X
+1572(in)X
+1686 -112.4062(\256le)AX
+1838(header)X
+2104(*/)X
+432 4057(int)N
+736 -0.4125(spares[32];)AX
+1192(/*)X
+1306(npages)X
+1572(at)X
+1686(each)X
+1876(split)X
+2104(*/)X
+432 4145(int)N
+736(log2\(\);)X
+1198(/*)X
+1312(ceil\(log)X
+1654(base)X
+1844(2\))X
+1958(*/)X
+432 4321(#DEFINE)N
+736 -0.3929(BUCKET_TO_PAGE\(bucket\))AX
+1610(\\)X
+584 4409(bucket)N
+850(+)X
+926 -0.4167(nhdr_pages)AX
+1344(+)X
+1420(\\)X
+584 4497 -0.3894(\(bucket?spares[logs2\(bucket)AN
+1648(+)X
+1724(1\)-1]:0\))X
+432 4673(#DEFINE)N
+736 -0.3947(OADDR_TO_PAGE\(oaddr\))AX
+1534(\\)X
+584 4761 -0.3984(BUCKET_TO_PAGE\(\(1)AN
+1268(<<)X
+1382 -0.4091(\(oaddr>>11\)\))AX
+1876(-)X
+1952(1\))X
+2066(+)X
+2142(\\)X
+584 4849(oaddr)N
+812(&)X
+888(0x7ff;)X
+1 f
+10 s
+604 5262(An)N
+728(over\257ow)X
+1039(page)X
+1217(is)X
+1295(addressed)X
+1637(by)X
+1742(its)X
+1842(split)X
+2004(point,)X
+432 5350(identifying)N
+858(the)X
+1031(generations)X
+1476(between)X
+1819(which)X
+2090(the)X
+432 5438(over\257ow)N
+740(page)X
+915(is)X
+991(allocated,)X
+1324(and)X
+1463(its)X
+1561(page)X
+1736(number,)X
+2023(iden-)X
+432 5526(tifying)N
+665(the)X
+783(particular)X
+1111(page)X
+1283(within)X
+1507(the)X
+1625(split)X
+1782(point.)X
+1986(In)X
+2073(this)X
+432 5614(implementation,)N
+983(offsets)X
+1225(within)X
+1457(pages)X
+1668(are)X
+1795(16)X
+1903(bits)X
+2046(long)X
+432 5702(\(limiting)N
+732(the)X
+851(maximum)X
+1196(page)X
+1368(size)X
+1513(to)X
+1595(32K\),)X
+1800(so)X
+1891(we)X
+2005(select)X
+2418 538(an)N
+2535(over\257ow)X
+2860(page)X
+3052(addressing)X
+3435(algorithm)X
+3786(that)X
+3946(can)X
+4098(be)X
+2418 626(expressed)N
+2760(in)X
+2847(16)X
+2952(bits)X
+3091(and)X
+3231(which)X
+3451(allows)X
+3684(quick)X
+3886(retrieval.)X
+2418 714(The)N
+2568(top)X
+2695(\256ve)X
+2840(bits)X
+2980(indicate)X
+3258(the)X
+3380(split)X
+3541(point)X
+3729(and)X
+3869(the)X
+3991(lower)X
+2418 802(eleven)N
+2650(indicate)X
+2926(the)X
+3046(page)X
+3220(number)X
+3487(within)X
+3713(the)X
+3832(split)X
+3990(point.)X
+2418 890(Since)N
+2633(\256ve)X
+2789(bits)X
+2940(are)X
+3075(reserved)X
+3384(for)X
+3514(the)X
+3648(split)X
+3821(point,)X
+4041(\256les)X
+2418 978(may)N
+2578(split)X
+2737(32)X
+2839(times)X
+3034(yielding)X
+3318(a)X
+3376(maximum)X
+3721(\256le)X
+3844(size)X
+3990(of)X
+4078(2)X
+7 s
+946(32)Y
+10 s
+2418 1066(buckets)N
+2698(and)X
+2849(32)X
+2 f
+(*)S
+1 f
+2982(2)X
+7 s
+1034(11)Y
+10 s
+3113 1066(over\257ow)N
+3433(pages.)X
+3691(The)X
+3850(maximum)X
+2418 1154(page)N
+2597(size)X
+2749(is)X
+2829(2)X
+7 s
+1122(15)Y
+10 s
+1154(,)Y
+2971(yielding)X
+3259(a)X
+3321(maximum)X
+3671(\256le)X
+3799(size)X
+3950(greater)X
+2418 1242(than)N
+2601(131,000)X
+2906(GB)X
+3061(\(on)X
+3212(\256le)X
+3358(systems)X
+3655(supporting)X
+4041(\256les)X
+2418 1330(larger)N
+2626(than)X
+2784(4GB\).)X
+10 f
+2418 1418 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+1 Dt
+4014 2275 MXY
+0 133 Dl
+3881 2275 MXY
+0 133 Dl
+3748 2275 MXY
+0 133 Dl
+3083 2275 MXY
+0 133 Dl
+5 s
+1 f
+3523 2475(2/3)N
+3390(2/2)X
+3257(2/1)X
+2859(1/2)X
+2726(1/1)X
+5 Dt
+3814 1743 MXY
+0 133 Dl
+3282 1743 MXY
+0 133 Dl
+3017 1743 MXY
+0 133 Dl
+2884 1743 MXY
+0 133 Dl
+1 Dt
+3681 1743 MXY
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3548 MX
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3415 MX
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3282 MX
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3150 MX
+0 133 Dl
+132 0 Dl
+0 -133 Dl
+-132 0 Dl
+3017 MX
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+2884 MX
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3 f
+8 s
+3017 2601(Over\257ow)N
+3285(Addresses)X
+3515 2833(Over\257ow)N
+3783(Pages)X
+2850(Buckets)X
+1 Di
+3349 2740 MXY
+ 3349 2740 lineto
+ 3482 2740 lineto
+ 3482 2873 lineto
+ 3349 2873 lineto
+ 3349 2740 lineto
+closepath 3 3349 2740 3482 2873 Dp
+2684 MX
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+5 Dt
+4146 2275 MXY
+0 133 Dl
+3216 2275 MXY
+0 133 Dl
+2684 2275 MXY
+0 133 Dl
+2551 2275 MXY
+0 133 Dl
+1 f
+3798 1963(3)N
+3266 1980(2)N
+3001(1)X
+2868(0)X
+1 Dt
+2751 1743 MXY
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3548 2275 MXY
+-15 -22 Dl
+2 16 Dl
+-13 11 Dl
+26 -5 Dl
+-282 -117 Dl
+3432 2275 MXY
+-10 -25 Dl
+-2 16 Dl
+-15 8 Dl
+27 1 Dl
+-166 -117 Dl
+3282 2275 MXY
+12 -25 Dl
+-14 10 Dl
+-15 -6 Dl
+17 21 Dl
+-16 -117 Dl
+2884 2275 MXY
+26 7 Dl
+-12 -12 Dl
+3 -16 Dl
+-17 21 Dl
+382 -117 Dl
+2751 2275 MXY
+25 9 Dl
+-11 -12 Dl
+5 -17 Dl
+-19 20 Dl
+515 -117 Dl
+3 f
+3070 2152(Over\257ow)N
+3338(Pages)X
+3482 2275 MXY
+ 3482 2275 lineto
+ 3615 2275 lineto
+ 3615 2408 lineto
+ 3482 2408 lineto
+ 3482 2275 lineto
+closepath 3 3482 2275 3615 2408 Dp
+3349 MX
+ 3349 2275 lineto
+ 3482 2275 lineto
+ 3482 2408 lineto
+ 3349 2408 lineto
+ 3349 2275 lineto
+closepath 3 3349 2275 3482 2408 Dp
+3216 MX
+ 3216 2275 lineto
+ 3349 2275 lineto
+ 3349 2408 lineto
+ 3216 2408 lineto
+ 3216 2275 lineto
+closepath 3 3216 2275 3349 2408 Dp
+2817 MX
+ 2817 2275 lineto
+ 2950 2275 lineto
+ 2950 2408 lineto
+ 2817 2408 lineto
+ 2817 2275 lineto
+closepath 3 2817 2275 2950 2408 Dp
+2684 MX
+ 2684 2275 lineto
+ 2817 2275 lineto
+ 2817 2408 lineto
+ 2684 2408 lineto
+ 2684 2275 lineto
+closepath 3 2684 2275 2817 2408 Dp
+3615 MX
+0 133 Dl
+531 0 Dl
+0 -133 Dl
+-531 0 Dl
+2950 MX
+0 133 Dl
+266 0 Dl
+0 -133 Dl
+-266 0 Dl
+2551 MX
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3798 1726 MXY
+-21 -18 Dl
+6 16 Dl
+-10 13 Dl
+25 -11 Dl
+-599 -99 Dl
+3266 1726 MXY
+-1 -27 Dl
+-7 15 Dl
+-17 1 Dl
+25 11 Dl
+-67 -99 Dl
+3033 1726 MXY
+27 1 Dl
+-14 -8 Dl
+-1 -17 Dl
+-12 24 Dl
+166 -99 Dl
+2900 1726 MXY
+27 7 Dl
+-13 -11 Dl
+3 -17 Dl
+-17 21 Dl
+299 -99 Dl
+3058 1621(Split)N
+3203(Points)X
+2418 2275 MXY
+0 133 Dl
+133 0 Dl
+0 -133 Dl
+-133 0 Dl
+3 Dt
+-1 Ds
+3137(Figure)Y
+2619(3:)X
+1 f
+2691(Split)X
+2832(points)X
+3008(occur)X
+3168(between)X
+3399(generations)X
+3712(and)X
+3823(are)X
+3919(numbered)X
+2418 3225(from)N
+2560(0.)X
+2642(In)X
+2713(this)X
+2824(\256gure)X
+2991(there)X
+3136(are)X
+3231(two)X
+3345(over\257ow)X
+3590(pages)X
+3753(allocated)X
+4000(at)X
+4063(split)X
+2418 3313(point)N
+2566(1)X
+2614(and)X
+2722(three)X
+2865(allocated)X
+3111(at)X
+3173(split)X
+3300(point)X
+3448(2.)X
+10 s
+10 f
+2418 3489 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+2949 3731(Buffer)N
+3192(Management)X
+1 f
+2590 3863(The)N
+2744(hash)X
+2920(table)X
+3105(is)X
+3187(stored)X
+3412(in)X
+3502(memory)X
+3797(as)X
+3892(a)X
+3956(logical)X
+2418 3951(array)N
+2633(of)X
+2749(bucket)X
+3012(pointers.)X
+3359(Physically,)X
+3761(the)X
+3907(array)X
+4121(is)X
+2418 4039(arranged)N
+2728(in)X
+2818(segments)X
+3144(of)X
+3239(256)X
+3387(pointers.)X
+3713(Initially,)X
+4013(there)X
+2418 4127(is)N
+2530(space)X
+2767(to)X
+2887(allocate)X
+3195(256)X
+3373(segments.)X
+3769(Reallocation)X
+2418 4215(occurs)N
+2651(when)X
+2847(the)X
+2967(number)X
+3234(of)X
+3323(buckets)X
+3590(exceeds)X
+3867(32K)X
+4027(\(256)X
+2418 4303(*)N
+2508(256\).)X
+2745(Primary)X
+3053(pages)X
+3286(may)X
+3473(be)X
+3598(accessed)X
+3929(directly)X
+2418 4391(through)N
+2711(the)X
+2853(array)X
+3062(by)X
+3185(bucket)X
+3442(number)X
+3730(and)X
+3889(over\257ow)X
+2418 4479(pages)N
+2628(are)X
+2754 0.4028(referenced)AX
+3122(logically)X
+3429(by)X
+3536(their)X
+3710(over\257ow)X
+4022(page)X
+2418 4567(address.)N
+2726(For)X
+2864(small)X
+3063(hash)X
+3236(tables,)X
+3469(it)X
+3539(is)X
+3618(desirable)X
+3934(to)X
+4022(keep)X
+2418 4655(all)N
+2525(pages)X
+2735(in)X
+2823(main)X
+3009(memory)X
+3302(while)X
+3506(on)X
+3612(larger)X
+3826(tables,)X
+4059(this)X
+2418 4743(is)N
+2523(probably)X
+2860(impossible.)X
+3298(To)X
+3438(satisfy)X
+3698(both)X
+3891(of)X
+4009(these)X
+2418 4831(requirements,)N
+2900(the)X
+3041(package)X
+3348(includes)X
+3658(buffer)X
+3897(manage-)X
+2418 4919(ment)N
+2598(with)X
+2760(LRU)X
+2940(\(least)X
+3134(recently)X
+3413(used\))X
+3607(replacement.)X
+2590 5033(By)N
+2730(default,)X
+3020(the)X
+3165(package)X
+3475(allocates)X
+3802(up)X
+3928(to)X
+4036(64K)X
+2418 5121(bytes)N
+2616(of)X
+2712(buffered)X
+3014(pages.)X
+3246(All)X
+3377(pages)X
+3589(in)X
+3680(the)X
+3807(buffer)X
+4032(pool)X
+2418 5209(are)N
+2542(linked)X
+2766(in)X
+2852(LRU)X
+3036(order)X
+3230(to)X
+3316(facilitate)X
+3621(fast)X
+3761(replacement.)X
+2418 5297(Whereas)N
+2724(ef\256cient)X
+3011(access)X
+3241(to)X
+3327(primary)X
+3605(pages)X
+3812(is)X
+3889(provided)X
+2418 5385(by)N
+2521(the)X
+2642(bucket)X
+2879(array,)X
+3087(ef\256cient)X
+3372(access)X
+3600(to)X
+3684(over\257ow)X
+3991(pages)X
+2418 5473(is)N
+2501(provided)X
+2816(by)X
+2926(linking)X
+3182(over\257ow)X
+3497(page)X
+3679(buffers)X
+3936(to)X
+4027(their)X
+2418 5561(predecessor)N
+2827(page)X
+3008(\(either)X
+3247(the)X
+3374(primary)X
+3657(page)X
+3838(or)X
+3933(another)X
+2418 5649(over\257ow)N
+2742(page\).)X
+3000(This)X
+3181(means)X
+3425(that)X
+3584(an)X
+3699(over\257ow)X
+4022(page)X
+3 f
+432 5960(6)N
+2970(USENIX)X
+9 f
+3292(-)X
+3 f
+3356(Winter)X
+3621('91)X
+9 f
+3748(-)X
+3 f
+3812(Dallas,)X
+4065(TX)X
+
+7 p
+%%Page: 7 7
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+720 258(Seltzer)N
+977(&)X
+1064(Yigit)X
+3278(A)X
+3356(New)X
+3528(Hashing)X
+3831(Package)X
+4136(for)X
+4259(UNIX)X
+1 f
+720 538(cannot)N
+955(be)X
+1052(present)X
+1305(in)X
+1388(the)X
+1507(buffer)X
+1724(pool)X
+1886(if)X
+1955(its)X
+2050(primary)X
+2324(page)X
+720 626(is)N
+804(not)X
+937(present.)X
+1240(This)X
+1413(does)X
+1591(not)X
+1724(impact)X
+1972(performance)X
+2409(or)X
+720 714(functionality,)N
+1209(because)X
+1524(an)X
+1660(over\257ow)X
+2005(page)X
+2217(will)X
+2400(be)X
+720 802(accessed)N
+1048(only)X
+1236(after)X
+1430(its)X
+1550(predecessor)X
+1975(page)X
+2172(has)X
+2324(been)X
+720 890(accessed.)N
+1068(Figure)X
+1303(4)X
+1369(depicts)X
+1622(the)X
+1746(data)X
+1905(structures)X
+2242(used)X
+2414(to)X
+720 978(manage)N
+990(the)X
+1108(buffer)X
+1325(pool.)X
+892 1092(The)N
+1040(in-memory)X
+1419(bucket)X
+1656(array)X
+1845(contains)X
+2134(pointers)X
+2414(to)X
+720 1180(buffer)N
+975(header)X
+1248(structures)X
+1617(which)X
+1870(represent)X
+2222(primary)X
+720 1268(pages.)N
+968(Buffer)X
+1203(headers)X
+1474(contain)X
+1735(modi\256ed)X
+2043(bits,)X
+2202(the)X
+2324(page)X
+720 1356(address)N
+995(of)X
+1096(the)X
+1228(buffer,)X
+1479(a)X
+1548(pointer)X
+1808(to)X
+1903(the)X
+2034(actual)X
+2259(buffer,)X
+720 1444(and)N
+875(a)X
+950(pointer)X
+1216(to)X
+1317(the)X
+1454(buffer)X
+1690(header)X
+1944(for)X
+2077(an)X
+2191(over\257ow)X
+720 1532(page)N
+901(if)X
+979(it)X
+1052(exists,)X
+1283(in)X
+1374(addition)X
+1665(to)X
+1756(the)X
+1883(LRU)X
+2072(links.)X
+2296(If)X
+2378(the)X
+720 1620(buffer)N
+950(corresponding)X
+1442(to)X
+1537(a)X
+1606(particular)X
+1947(bucket)X
+2194(is)X
+2280(not)X
+2414(in)X
+720 1708(memory,)N
+1048(its)X
+1164(pointer)X
+1432(is)X
+1526(NULL.)X
+1801(In)X
+1909(effect,)X
+2154(pages)X
+2377(are)X
+720 1796(linked)N
+950(in)X
+1042(three)X
+1233(ways.)X
+1468(Using)X
+1689(the)X
+1817(buffer)X
+2043(headers,)X
+2338(they)X
+720 1884(are)N
+851(linked)X
+1083(physically)X
+1444(through)X
+1725(the)X
+1854(LRU)X
+2045(links)X
+2231(and)X
+2378(the)X
+720 1972(over\257ow)N
+1036(links.)X
+1241(Using)X
+1462(the)X
+1590(pages)X
+1803(themselves,)X
+2209(they)X
+2377(are)X
+720 2060(linked)N
+943(logically)X
+1246(through)X
+1518(the)X
+1639(over\257ow)X
+1946(addresses)X
+2276(on)X
+2378(the)X
+720 2148(page.)N
+948(Since)X
+1162(over\257ow)X
+1482(pages)X
+1700(are)X
+1834(accessed)X
+2151(only)X
+2328(after)X
+720 2236(their)N
+904(predecessor)X
+1321(pages,)X
+1560(they)X
+1734(are)X
+1869(removed)X
+2186(from)X
+2378(the)X
+720 2324(buffer)N
+937(pool)X
+1099(when)X
+1293(their)X
+1460(primary)X
+1734(is)X
+1807(removed.)X
+10 f
+720 2412 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+1 Dt
+2309 3177 MXY
+24 15 Dl
+-8 -15 Dl
+8 -15 Dl
+-24 15 Dl
+52 0 Dl
+789 3160 MXY
+-35 0 Dl
+0 -156 Dl
+1607 0 Dl
+0 173 Dl
+789 3091 MXY
+-24 -15 Dl
+9 15 Dl
+-9 15 Dl
+24 -15 Dl
+-69 0 Dl
+2309 3125 MXY
+104 0 Dl
+0 -155 Dl
+-1693 0 Dl
+0 121 Dl
+927 3160 MXY
+24 15 Dl
+-9 -15 Dl
+9 -15 Dl
+-24 15 Dl
+553 0 Dl
+1618 3177 MXY
+8 27 Dl
+4 -17 Dl
+16 -6 Dl
+-28 -4 Dl
+138 121 Dl
+1895 3315 MXY
+28 3 Dl
+-15 -9 Dl
+1 -18 Dl
+-14 24 Dl
+276 -138 Dl
+3108 MY
+-28 -3 Dl
+15 10 Dl
+-1 17 Dl
+14 -24 Dl
+-276 138 Dl
+1756 3229 MXY
+-8 -27 Dl
+-3 17 Dl
+-16 6 Dl
+27 4 Dl
+-138 -121 Dl
+1480 MX
+-24 -15 Dl
+9 15 Dl
+-9 15 Dl
+24 -15 Dl
+-553 0 Dl
+3 f
+5 s
+1083 3073(LRU)N
+1178(chain)X
+4 Ds
+1402 3851 MXY
+ 1402 3851 lineto
+ 1471 3851 lineto
+ 1471 3920 lineto
+ 1402 3920 lineto
+ 1402 3851 lineto
+closepath 19 1402 3851 1471 3920 Dp
+1445 3747(Over\257ow)N
+1613(Address)X
+1549 3609 MXY
+0 69 Dl
+1756 MX
+-23 -15 Dl
+8 15 Dl
+-8 15 Dl
+23 -15 Dl
+-207 0 Dl
+-1 Ds
+3 Dt
+1756 3419 MXY
+-6 -28 Dl
+-4 17 Dl
+-17 5 Dl
+27 6 Dl
+-138 -138 Dl
+2240 3471 MXY
+15 -24 Dl
+-15 9 Dl
+-15 -9 Dl
+15 24 Dl
+0 -138 Dl
+1826 3609 MXY
+15 -24 Dl
+-15 9 Dl
+-16 -9 Dl
+16 24 Dl
+0 -138 Dl
+1549 MX
+15 -24 Dl
+-15 9 Dl
+-15 -9 Dl
+15 24 Dl
+0 -138 Dl
+858 3471 MXY
+15 -24 Dl
+-15 9 Dl
+-15 -9 Dl
+15 24 Dl
+0 -138 Dl
+2240 3056 MXY
+15 -24 Dl
+-15 9 Dl
+-15 -9 Dl
+15 24 Dl
+0 -138 Dl
+1549 3056 MXY
+15 -24 Dl
+-15 9 Dl
+-15 -9 Dl
+15 24 Dl
+0 -138 Dl
+858 3056 MXY
+15 -24 Dl
+-15 9 Dl
+-15 -9 Dl
+15 24 Dl
+0 -138 Dl
+1 Dt
+2171 3471 MXY
+ 2171 3471 lineto
+ 2448 3471 lineto
+ 2448 3609 lineto
+ 2171 3609 lineto
+ 2171 3471 lineto
+closepath 19 2171 3471 2448 3609 Dp
+1756 3609 MXY
+ 1756 3609 lineto
+ 2033 3609 lineto
+ 2033 3747 lineto
+ 1756 3747 lineto
+ 1756 3609 lineto
+closepath 3 1756 3609 2033 3747 Dp
+1480 3471 MXY
+ 1480 3471 lineto
+ 1756 3471 lineto
+ 1756 3609 lineto
+ 1480 3609 lineto
+ 1480 3471 lineto
+closepath 19 1480 3471 1756 3609 Dp
+789 MX
+ 789 3471 lineto
+ 1065 3471 lineto
+ 1065 3609 lineto
+ 789 3609 lineto
+ 789 3471 lineto
+closepath 19 789 3471 1065 3609 Dp
+962 3903(Buffer)N
+1083(Header)X
+849 3851 MXY
+ 849 3851 lineto
+ 918 3851 lineto
+ 918 3920 lineto
+ 849 3920 lineto
+ 849 3851 lineto
+closepath 14 849 3851 918 3920 Dp
+1756 3194 MXY
+ 1756 3194 lineto
+ 1895 3194 lineto
+ 1895 3471 lineto
+ 1756 3471 lineto
+ 1756 3194 lineto
+closepath 14 1756 3194 1895 3471 Dp
+2171 3056 MXY
+ 2171 3056 lineto
+ 2309 3056 lineto
+ 2309 3333 lineto
+ 2171 3333 lineto
+ 2171 3056 lineto
+closepath 14 2171 3056 2309 3333 Dp
+1480 MX
+ 1480 3056 lineto
+ 1618 3056 lineto
+ 1618 3333 lineto
+ 1480 3333 lineto
+ 1480 3056 lineto
+closepath 14 1480 3056 1618 3333 Dp
+789 MX
+ 789 3056 lineto
+ 927 3056 lineto
+ 927 3333 lineto
+ 789 3333 lineto
+ 789 3056 lineto
+closepath 14 789 3056 927 3333 Dp
+2780 MY
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+927 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+1065 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+1203 MX
+0 138 Dl
+139 0 Dl
+0 -138 Dl
+-139 0 Dl
+1342 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+1480 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+1618 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+1756 MX
+0 138 Dl
+139 0 Dl
+0 -138 Dl
+-139 0 Dl
+1895 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+2033 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+2171 MX
+0 138 Dl
+138 0 Dl
+0 -138 Dl
+-138 0 Dl
+2309 MX
+0 138 Dl
+139 0 Dl
+0 -138 Dl
+-139 0 Dl
+13 s
+1048 2720(In)N
+1173(Memory)X
+1580(Bucket)X
+1918(Array)X
+867 3584(B0)N
+1558(B5)X
+2223(B10)X
+1788 3722(O1/1)N
+5 s
+1515 3903(Primay)N
+1651(Buffer)X
+4 Ds
+1990 3851 MXY
+ 1990 3851 lineto
+ 2059 3851 lineto
+ 2059 3920 lineto
+ 1990 3920 lineto
+ 1990 3851 lineto
+closepath 3 1990 3851 2059 3920 Dp
+2102 3903(Over\257ow)N
+2270(Buffer)X
+3 Dt
+-1 Ds
+8 s
+720 4184(Figure)N
+922(4:)X
+1 f
+996(Three)X
+1164(primary)X
+1386(pages)X
+1551(\(B0,)X
+1683(B5,)X
+1794(B10\))X
+1942(are)X
+2039(accessed)X
+2281(directly)X
+720 4272(from)N
+862(the)X
+958(bucket)X
+1146(array.)X
+1326(The)X
+1443(one)X
+1553(over\257ow)X
+1798(page)X
+1935(\(O1/1\))X
+2122(is)X
+2182(linked)X
+2359(phy-)X
+720 4360(sically)N
+915(from)X
+1067(its)X
+1155(primary)X
+1384(page's)X
+1577(buffer)X
+1759(header)X
+1955(as)X
+2035(well)X
+2172(as)X
+2252(logically)X
+720 4448(from)N
+860(its)X
+937(predecessor)X
+1253(page)X
+1389(buffer)X
+1560(\(B5\).)X
+10 s
+10 f
+720 4624 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+1191 4954(Table)N
+1406(Parameterization)X
+1 f
+892 5086(When)N
+1107(a)X
+1166(hash)X
+1336(table)X
+1515(is)X
+1590(created,)X
+1865(the)X
+1985(bucket)X
+2221(size,)X
+2388(\256ll)X
+720 5174(factor,)N
+953(initial)X
+1164(number)X
+1434(of)X
+1526(elements,)X
+1856(number)X
+2125(of)X
+2216(bytes)X
+2409(of)X
+720 5262(main)N
+919(memory)X
+1225(used)X
+1411(for)X
+1543(caching,)X
+1851(and)X
+2005(a)X
+2079(user-de\256ned)X
+720 5350(hash)N
+892(function)X
+1184(may)X
+1347(be)X
+1448(speci\256ed.)X
+1797(The)X
+1946(bucket)X
+2184(size)X
+2333(\(and)X
+720 5438(page)N
+906(size)X
+1064(for)X
+1191(over\257ow)X
+1509(pages\))X
+1752(defaults)X
+2039(to)X
+2134(256)X
+2287(bytes.)X
+720 5526(For)N
+858(tables)X
+1072(with)X
+1241(large)X
+1429(data)X
+1590(items,)X
+1810(it)X
+1881(may)X
+2046(be)X
+2149(preferable)X
+720 5614(to)N
+803(increase)X
+1088(the)X
+1207(page)X
+1380(size,)X
+1545(and,)X
+1701(conversely,)X
+2089(applications)X
+720 5702(storing)N
+1002(small)X
+1235(items)X
+1467(exclusively)X
+1891(in)X
+2012(memory)X
+2338(may)X
+2706 538(bene\256t)N
+2966(from)X
+3164(a)X
+3242(smaller)X
+3520(bucket)X
+3776(size.)X
+3983(A)X
+4082(bucket)X
+4337(size)X
+2706 626(smaller)N
+2962(than)X
+3120(64)X
+3220(bytes)X
+3409(is)X
+3482(not)X
+3604(recommended.)X
+2878 740(The)N
+3031(\256ll)X
+3147(factor)X
+3363(indicates)X
+3676(a)X
+3740(desired)X
+4000(density)X
+4258(within)X
+2706 828(the)N
+2833(hash)X
+3009(table.)X
+3234(It)X
+3312(is)X
+3394(an)X
+3499(approximation)X
+3995(of)X
+4091(the)X
+4217(number)X
+2706 916(of)N
+2815(keys)X
+3004(allowed)X
+3300(to)X
+3404(accumulate)X
+3811(in)X
+3914(any)X
+4071(one)X
+4228(bucket,)X
+2706 1004(determining)N
+3119(when)X
+3319(the)X
+3442(hash)X
+3614(table)X
+3795(grows.)X
+4056(Its)X
+4161(default)X
+4409(is)X
+2706 1092(eight.)N
+2953(If)X
+3054(the)X
+3199(user)X
+3380(knows)X
+3636(the)X
+3781(average)X
+4079(size)X
+4251(of)X
+4364(the)X
+2706 1180(key/data)N
+3008(pairs)X
+3194(being)X
+3402(stored)X
+3627(in)X
+3718(the)X
+3845(table,)X
+4050(near)X
+4218(optimal)X
+2706 1268(bucket)N
+2943(sizes)X
+3122(and)X
+3261(\256ll)X
+3372(factors)X
+3614(may)X
+3775(be)X
+3874(selected)X
+4155(by)X
+4257(apply-)X
+2706 1356(ing)N
+2828(the)X
+2946(equation:)X
+0 f
+8 s
+2706 1655(\(1\))N
+2994 -0.3938(\(\(average_pair_length)AX
+3830(+)X
+3906(4\))X
+4020(*)X
+3032 1743(ffactor\))N
+3374(>=)X
+3488(bsize)X
+1 f
+10 s
+2706 2042(For)N
+2859(highly)X
+3104(time)X
+3287(critical)X
+3551(applications,)X
+3999(experimenting)X
+2706 2130(with)N
+2919(different)X
+3266(bucket)X
+3550(sizes)X
+3776(and)X
+3962(\256ll)X
+4120(factors)X
+4409(is)X
+2706 2218(encouraged.)N
+2878 2332(Figures)N
+3144(5a,b,)X
+3326(and)X
+3468(c)X
+3530(illustrate)X
+3836(the)X
+3960(effects)X
+4200(of)X
+4292(vary-)X
+2706 2420(ing)N
+2841(page)X
+3026(sizes)X
+3215(and)X
+3363(\256ll)X
+3483(factors)X
+3734(for)X
+3860(the)X
+3990(same)X
+4187(data)X
+4353(set.)X
+2706 2508(The)N
+2864(data)X
+3031(set)X
+3152(consisted)X
+3482(of)X
+3581(24474)X
+3813(keys)X
+3992(taken)X
+4198(from)X
+4386(an)X
+2706 2596(online)N
+2931(dictionary.)X
+3301(The)X
+3451(data)X
+3609(value)X
+3807(for)X
+3925(each)X
+4097(key)X
+4237(was)X
+4386(an)X
+2706 2684(ASCII)N
+2938(string)X
+3143(for)X
+3260(an)X
+3359(integer)X
+3605(from)X
+3784(1)X
+3847(to)X
+3931(24474)X
+4153(inclusive.)X
+2706 2772(The)N
+2867(test)X
+3013(run)X
+3155(consisted)X
+3488(of)X
+3590(creating)X
+3884(a)X
+3955(new)X
+4124(hash)X
+4306(table)X
+2706 2860(\(where)N
+2966(the)X
+3100(ultimate)X
+3398(size)X
+3559(of)X
+3662(the)X
+3796(table)X
+3987(was)X
+4147(known)X
+4400(in)X
+2706 2948(advance\),)N
+3054(entering)X
+3354(each)X
+3539(key/data)X
+3848(pair)X
+4010(into)X
+4171(the)X
+4306(table)X
+2706 3036(and)N
+2849(then)X
+3014(retrieving)X
+3353(each)X
+3528(key/data)X
+3827(pair)X
+3979(from)X
+4162(the)X
+4286(table.)X
+2706 3124(Each)N
+2898(of)X
+2996(the)X
+3125(graphs)X
+3369(shows)X
+3599(the)X
+3727(timings)X
+3996(resulting)X
+4306(from)X
+2706 3212(varying)N
+2973(the)X
+3093(pagesize)X
+3392(from)X
+3570(128)X
+3712(bytes)X
+3903(to)X
+3986(1M)X
+4118(and)X
+4255(the)X
+4374(\256ll)X
+2706 3300(factor)N
+2929(from)X
+3120(1)X
+3195(to)X
+3292(128.)X
+3486(For)X
+3631(each)X
+3813(run,)X
+3974(the)X
+4106(buffer)X
+4337(size)X
+2706 3388(was)N
+2874(set)X
+3006(at)X
+3106(1M.)X
+3299(The)X
+3466(tests)X
+3650(were)X
+3849(all)X
+3971(run)X
+4120(on)X
+4242(an)X
+4360(HP)X
+2706 3476(9000/370)N
+3077(\(33.3)X
+3312(Mhz)X
+3527(MC68030\),)X
+3966(with)X
+4176(16M)X
+4395(of)X
+2706 3564(memory,)N
+3042(64K)X
+3228(physically)X
+3605(addressed)X
+3970(cache,)X
+4222(and)X
+4386(an)X
+2706 3652(HP7959S)N
+3055(disk)X
+3231(drive,)X
+3459(running)X
+3751(4.3BSD-Reno)X
+4244(single-)X
+2706 3740(user.)N
+2878 3854(Both)N
+3066(system)X
+3321(time)X
+3496(\(Figure)X
+3764(5a\))X
+3899(and)X
+4047(elapsed)X
+4320(time)X
+2706 3942(\(Figure)N
+2966(5b\))X
+3097(show)X
+3290(that)X
+3434(for)X
+3552(all)X
+3655(bucket)X
+3892(sizes,)X
+4091(the)X
+4212(greatest)X
+2706 4030(performance)N
+3137(gains)X
+3329(are)X
+3451(made)X
+3648(by)X
+3751(increasing)X
+4104(the)X
+4225(\256ll)X
+4336(fac-)X
+2706 4118(tor)N
+2822(until)X
+2995(equation)X
+3298(1)X
+3365(is)X
+3445(satis\256ed.)X
+3774(The)X
+3925(user)X
+4085(time)X
+4253(shown)X
+2706 4206(in)N
+2791(Figure)X
+3023(5c)X
+3122(gives)X
+3314(a)X
+3373(more)X
+3561(detailed)X
+3838(picture)X
+4083(of)X
+4172(how)X
+4332(per-)X
+2706 4294(formance)N
+3054(varies.)X
+3330(The)X
+3499(smaller)X
+3778(bucket)X
+4035(sizes)X
+4234(require)X
+2706 4382(fewer)N
+2921(keys)X
+3099(per)X
+3233(page)X
+3416(to)X
+3509(satisfy)X
+3749(equation)X
+4056(1)X
+4127(and)X
+4274(there-)X
+2706 4470(fore)N
+2860(incur)X
+3049(fewer)X
+3257(collisions.)X
+3607(However,)X
+3946(when)X
+4144(the)X
+4265(buffer)X
+2706 4558(pool)N
+2884(size)X
+3045(is)X
+3134(\256xed,)X
+3349(smaller)X
+3620(pages)X
+3838(imply)X
+4059(more)X
+4259(pages.)X
+2706 4646(An)N
+2830(increased)X
+3160(number)X
+3430(of)X
+3522(pages)X
+3730(means)X
+3960(more)X
+2 f
+4150(malloc\(3\))X
+1 f
+2706 4734(calls)N
+2879(and)X
+3021(more)X
+3212(overhead)X
+3533(in)X
+3621(the)X
+3745(hash)X
+3918(package's)X
+4265(buffer)X
+2706 4822(manager)N
+3003(to)X
+3085(manage)X
+3355(the)X
+3473(additional)X
+3813(pages.)X
+2878 4936(The)N
+3028(tradeoff)X
+3308(works)X
+3529(out)X
+3655(most)X
+3834(favorably)X
+4166(when)X
+4364(the)X
+2706 5024(page)N
+2886(size)X
+3039(is)X
+3120(256)X
+3268(and)X
+3412(the)X
+3538(\256ll)X
+3654(factor)X
+3870(is)X
+3950(8.)X
+4057(Similar)X
+4319(con-)X
+2706 5112(clusions)N
+3009(were)X
+3207(obtained)X
+3524(if)X
+3614(the)X
+3753(test)X
+3905(was)X
+4071(run)X
+4218(without)X
+2706 5200(knowing)N
+3007(the)X
+3126(\256nal)X
+3289(table)X
+3466(size)X
+3612(in)X
+3695(advance.)X
+4020(If)X
+4095(the)X
+4214(\256le)X
+4337(was)X
+2706 5288(closed)N
+2942(and)X
+3088(written)X
+3345(to)X
+3437(disk,)X
+3620(the)X
+3748(conclusions)X
+4156(were)X
+4343(still)X
+2706 5376(the)N
+2832(same.)X
+3065(However,)X
+3408(rereading)X
+3740(the)X
+3865(\256le)X
+3994(from)X
+4177(disk)X
+4337(was)X
+2706 5464(slightly)N
+2983(faster)X
+3199(if)X
+3285(a)X
+3358(larger)X
+3583(bucket)X
+3834(size)X
+3996(and)X
+4149(\256ll)X
+4274(factor)X
+2706 5552(were)N
+2898(used)X
+3079(\(1K)X
+3238(bucket)X
+3486(size)X
+3645(and)X
+3795(32)X
+3909(\256ll)X
+4031(factor\).)X
+4320(This)X
+2706 5640(follows)N
+2987(intuitively)X
+3356(from)X
+3553(the)X
+3691(improved)X
+4038(ef\256ciency)X
+4395(of)X
+3 f
+720 5960(USENIX)N
+9 f
+1042(-)X
+3 f
+1106(Winter)X
+1371('91)X
+9 f
+1498(-)X
+3 f
+1562(Dallas,)X
+1815(TX)X
+4424(7)X
+
+8 p
+%%Page: 8 8
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+432 258(A)N
+510(New)X
+682(Hashing)X
+985(Package)X
+1290(for)X
+1413(UNIX)X
+3663(Seltzer)X
+3920(&)X
+4007(Yigit)X
+1 f
+432 538(performing)N
+830(1K)X
+965(reads)X
+1172(from)X
+1365(the)X
+1500(disk)X
+1670(rather)X
+1894(than)X
+2068(256)X
+432 626(byte)N
+609(reads.)X
+857(In)X
+962(general,)X
+1257(performance)X
+1702(for)X
+1834(disk)X
+2005(based)X
+432 714(tables)N
+639(is)X
+712(best)X
+861(when)X
+1055(the)X
+1173(page)X
+1345(size)X
+1490(is)X
+1563(approximately)X
+2046(1K.)X
+10 f
+432 802 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+619 2380 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+629 2437 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+648 2504 MXY
+-12 25 Dl
+24 0 Dl
+-12 -25 Dl
+686 2515 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+762 2516 MXY
+-12 24 Dl
+25 0 Dl
+-13 -24 Dl
+916 2515 MXY
+-13 24 Dl
+25 0 Dl
+-12 -24 Dl
+1222 2516 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+1834 2515 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+1 Dt
+619 2392 MXY
+10 57 Dl
+19 67 Dl
+38 11 Dl
+76 1 Dl
+154 -1 Dl
+306 1 Dl
+612 -1 Dl
+8 s
+1 f
+1628 2522(128)N
+3 Dt
+607 2245 MXY
+24 Dc
+617 2375 MXY
+23 Dc
+635 2442 MXY
+24 Dc
+674 2525 MXY
+23 Dc
+750 2529 MXY
+24 Dc
+904 2527 MXY
+23 Dc
+1210 MX
+23 Dc
+1822 2528 MXY
+23 Dc
+20 Ds
+1 Dt
+619 2245 MXY
+10 130 Dl
+19 67 Dl
+38 83 Dl
+76 4 Dl
+154 -2 Dl
+306 0 Dl
+612 1 Dl
+678 2482(256)N
+-1 Ds
+3 Dt
+619 2127 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+629 2191 MXY
+0 25 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+648 2334 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+686 2409 MXY
+0 25 Dl
+0 -13 Dl
+12 0 Dl
+-24 0 Dl
+762 2516 MXY
+0 25 Dl
+0 -12 Dl
+13 0 Dl
+-25 0 Dl
+916 2516 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-25 0 Dl
+1222 2515 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+1834 2515 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+5 Dt
+619 2139 MXY
+10 65 Dl
+19 142 Dl
+38 75 Dl
+76 108 Dl
+154 -1 Dl
+306 -1 Dl
+612 0 Dl
+694 2401(512)N
+3 Dt
+631 2064 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+641 2077 MXY
+-24 25 Dl
+12 -12 Dl
+-12 -13 Dl
+24 25 Dl
+660 2132 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+698 2292 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+775 2382 MXY
+-25 24 Dl
+12 -12 Dl
+-12 -12 Dl
+25 24 Dl
+928 2516 MXY
+-25 24 Dl
+13 -12 Dl
+-13 -12 Dl
+25 24 Dl
+1234 2516 MXY
+-24 25 Dl
+12 -12 Dl
+-12 -13 Dl
+24 25 Dl
+1846 2516 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+16 Ds
+1 Dt
+619 2076 MXY
+10 14 Dl
+19 54 Dl
+38 160 Dl
+76 90 Dl
+154 134 Dl
+306 1 Dl
+612 -1 Dl
+694 2257(1024)N
+-1 Ds
+3 Dt
+619 1877 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+629 1855 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+648 1838 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+686 1860 MXY
+12 -25 Dl
+-24 0 Dl
+12 25 Dl
+762 1923 MXY
+13 -24 Dl
+-25 0 Dl
+12 24 Dl
+916 2087 MXY
+12 -24 Dl
+-25 0 Dl
+13 24 Dl
+1222 2256 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+1834 2541 MXY
+12 -25 Dl
+-24 0 Dl
+12 25 Dl
+619 1865 MXY
+10 -22 Dl
+19 -17 Dl
+38 21 Dl
+76 64 Dl
+154 164 Dl
+306 169 Dl
+612 285 Dl
+1645 2427(4096)N
+619 1243 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+629 1196 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+648 1146 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+686 1174 MXY
+0 25 Dl
+0 -13 Dl
+12 0 Dl
+-24 0 Dl
+762 1249 MXY
+0 24 Dl
+0 -12 Dl
+13 0 Dl
+-25 0 Dl
+916 1371 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-25 0 Dl
+1222 1680 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+1834 1999 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+619 1255 MXY
+10 -47 Dl
+19 -50 Dl
+38 28 Dl
+76 75 Dl
+154 122 Dl
+306 309 Dl
+612 319 Dl
+1741 1934(8192)N
+5 Dt
+609 2531 MXY
+1225 0 Dl
+609 MX
+0 -1553 Dl
+2531 MY
+0 16 Dl
+4 Ds
+1 Dt
+2531 MY
+0 -1553 Dl
+593 2625(0)N
+-1 Ds
+5 Dt
+916 2531 MXY
+0 16 Dl
+4 Ds
+1 Dt
+2531 MY
+0 -1553 Dl
+884 2625(32)N
+-1 Ds
+5 Dt
+1222 2531 MXY
+0 16 Dl
+4 Ds
+1 Dt
+2531 MY
+0 -1553 Dl
+1190 2625(64)N
+-1 Ds
+5 Dt
+1528 2531 MXY
+0 16 Dl
+4 Ds
+1 Dt
+2531 MY
+0 -1553 Dl
+1496 2625(96)N
+-1 Ds
+5 Dt
+1834 2531 MXY
+0 16 Dl
+4 Ds
+1 Dt
+2531 MY
+0 -1553 Dl
+1786 2625(128)N
+-1 Ds
+5 Dt
+609 2531 MXY
+-16 0 Dl
+4 Ds
+1 Dt
+609 MX
+1225 0 Dl
+545 2558(0)N
+-1 Ds
+5 Dt
+609 2013 MXY
+-16 0 Dl
+4 Ds
+1 Dt
+609 MX
+1225 0 Dl
+481 2040(100)N
+-1 Ds
+5 Dt
+609 1496 MXY
+-16 0 Dl
+4 Ds
+1 Dt
+609 MX
+1225 0 Dl
+481 1523(200)N
+-1 Ds
+5 Dt
+609 978 MXY
+-16 0 Dl
+4 Ds
+1 Dt
+609 MX
+1225 0 Dl
+481 1005(300)N
+1088 2724(Fill)N
+1194(Factor)X
+422 1611(S)N
+426 1667(e)N
+426 1724(c)N
+424 1780(o)N
+424 1837(n)N
+424 1893(d)N
+428 1949(s)N
+3 Dt
+-1 Ds
+3 f
+432 2882(Figure)N
+636(5a:)X
+1 f
+744(System)X
+956(Time)X
+1113(for)X
+1209(dictionary)X
+1490(data)X
+1618(set)X
+1711(with)X
+1847(1M)X
+1958(of)X
+2033(buffer)X
+432 2970(space)N
+594(and)X
+707(varying)X
+923(bucket)X
+1114(sizes)X
+1259(and)X
+1372(\256ll)X
+1465(factors.)X
+1675(Each)X
+1823(line)X
+1940(is)X
+2004(labeled)X
+432 3058(with)N
+562(its)X
+639(bucket)X
+825(size.)X
+10 s
+10 f
+432 3234 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+8 s
+1 f
+428 4381(s)N
+424 4325(d)N
+424 4269(n)N
+424 4212(o)N
+426 4156(c)N
+426 4099(e)N
+422 4043(S)N
+1116 5156(Fill)N
+1222(Factor)X
+506 3437(3200)N
+4 Ds
+1 Dt
+666 3410 MXY
+1168 0 Dl
+-1 Ds
+5 Dt
+666 MX
+-16 0 Dl
+506 3825(2400)N
+4 Ds
+1 Dt
+666 3799 MXY
+1168 0 Dl
+-1 Ds
+5 Dt
+666 MX
+-16 0 Dl
+506 4214(1600)N
+4 Ds
+1 Dt
+666 4186 MXY
+1168 0 Dl
+-1 Ds
+5 Dt
+666 MX
+-16 0 Dl
+538 4602(800)N
+4 Ds
+1 Dt
+666 4575 MXY
+1168 0 Dl
+-1 Ds
+5 Dt
+666 MX
+-16 0 Dl
+602 4990(0)N
+4 Ds
+1 Dt
+666 4963 MXY
+1168 0 Dl
+-1 Ds
+5 Dt
+666 MX
+-16 0 Dl
+1786 5057(128)N
+4 Ds
+1 Dt
+1834 4963 MXY
+0 -1553 Dl
+-1 Ds
+5 Dt
+4963 MY
+0 16 Dl
+1510 5057(96)N
+4 Ds
+1 Dt
+1542 4963 MXY
+0 -1553 Dl
+-1 Ds
+5 Dt
+4963 MY
+0 16 Dl
+1218 5057(64)N
+4 Ds
+1 Dt
+1250 4963 MXY
+0 -1553 Dl
+-1 Ds
+5 Dt
+4963 MY
+0 16 Dl
+926 5057(32)N
+4 Ds
+1 Dt
+958 4963 MXY
+0 -1553 Dl
+-1 Ds
+5 Dt
+4963 MY
+0 16 Dl
+650 5057(0)N
+4 Ds
+1 Dt
+666 4963 MXY
+0 -1553 Dl
+-1 Ds
+5 Dt
+4963 MY
+0 16 Dl
+4963 MY
+0 -1553 Dl
+4963 MY
+1168 0 Dl
+1741 4752(8192)N
+3 Dt
+675 3732 MXY
+9 -172 Dl
+18 -118 Dl
+37 128 Dl
+73 -121 Dl
+146 623 Dl
+292 497 Dl
+584 245 Dl
+4802 MY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+1250 4557 MXY
+0 25 Dl
+0 -13 Dl
+12 0 Dl
+-24 0 Dl
+958 4060 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+812 3437 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+739 3558 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+702 3430 MXY
+0 25 Dl
+0 -13 Dl
+13 0 Dl
+-25 0 Dl
+684 3548 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+675 3720 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+1637 4912(4096)N
+675 4307 MXY
+9 -58 Dl
+18 30 Dl
+37 89 Dl
+73 144 Dl
+146 235 Dl
+292 122 Dl
+584 89 Dl
+4970 MY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+1250 4881 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+958 4759 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+812 4524 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+739 4380 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+702 4291 MXY
+13 -24 Dl
+-25 0 Dl
+12 24 Dl
+684 4261 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+675 4319 MXY
+12 -24 Dl
+-24 0 Dl
+12 24 Dl
+734 4662(1024)N
+16 Ds
+1 Dt
+675 4352 MXY
+9 60 Dl
+18 134 Dl
+37 266 Dl
+73 117 Dl
+146 30 Dl
+292 0 Dl
+584 -1 Dl
+-1 Ds
+3 Dt
+1846 4946 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+1262 4946 MXY
+-24 25 Dl
+12 -12 Dl
+-12 -13 Dl
+24 25 Dl
+970 4947 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+824 4917 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+751 4800 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+715 4534 MXY
+-25 25 Dl
+12 -13 Dl
+-12 -12 Dl
+25 25 Dl
+696 4400 MXY
+-24 24 Dl
+12 -12 Dl
+-12 -12 Dl
+24 24 Dl
+687 4339 MXY
+-24 25 Dl
+12 -12 Dl
+-12 -13 Dl
+24 25 Dl
+718 4792(512)N
+5 Dt
+675 4422 MXY
+9 137 Dl
+18 278 Dl
+37 105 Dl
+73 18 Dl
+146 -1 Dl
+292 0 Dl
+584 -1 Dl
+3 Dt
+4946 MY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+1250 4946 MXY
+0 25 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+958 4947 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+812 4948 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+739 4930 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+702 4824 MXY
+0 25 Dl
+0 -12 Dl
+13 0 Dl
+-25 0 Dl
+684 4547 MXY
+0 24 Dl
+0 -12 Dl
+12 0 Dl
+-24 0 Dl
+675 4410 MXY
+0 25 Dl
+0 -13 Dl
+12 0 Dl
+-24 0 Dl
+750 4921(256)N
+20 Ds
+1 Dt
+675 4597 MXY
+9 246 Dl
+18 106 Dl
+37 10 Dl
+73 0 Dl
+146 0 Dl
+292 0 Dl
+584 -1 Dl
+-1 Ds
+3 Dt
+1822 MX
+23 Dc
+1238 4959 MXY
+23 Dc
+946 MX
+23 Dc
+800 MX
+23 Dc
+727 MX
+23 Dc
+691 4949 MXY
+23 Dc
+672 4843 MXY
+24 Dc
+663 4597 MXY
+24 Dc
+1395 4961(128)N
+1 Dt
+675 4855 MXY
+9 93 Dl
+18 10 Dl
+37 1 Dl
+73 0 Dl
+146 -1 Dl
+292 0 Dl
+584 0 Dl
+3 Dt
+4946 MY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+1250 MX
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+958 MX
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+812 MX
+-12 25 Dl
+24 0 Dl
+-12 -25 Dl
+739 4947 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+702 4946 MXY
+-12 24 Dl
+25 0 Dl
+-13 -24 Dl
+684 4936 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+675 4843 MXY
+-12 24 Dl
+24 0 Dl
+-12 -24 Dl
+3 Dt
+-1 Ds
+3 f
+432 5314(Figure)N
+634(5b:)X
+1 f
+744(Elapsed)X
+967(Time)X
+1123(for)X
+1218(dictionary)X
+1498(data)X
+1625(set)X
+1717(with)X
+1851(1M)X
+1960(of)X
+2033(buffer)X
+432 5402(space)N
+593(and)X
+705(varying)X
+920(bucket)X
+1110(sizes)X
+1254(and)X
+1366(\256ll)X
+1457(factors.)X
+1681(Each)X
+1827(line)X
+1942(is)X
+2004(labeled)X
+432 5490(with)N
+562(its)X
+639(bucket)X
+825(size.)X
+10 s
+2590 538(If)N
+2677(an)X
+2785(approximation)X
+3284(of)X
+3383(the)X
+3513(number)X
+3790(of)X
+3889(elements)X
+2418 626(ultimately)N
+2773(to)X
+2866(be)X
+2973(stored)X
+3200(in)X
+3293(the)X
+3422(hash)X
+3599(table)X
+3785(is)X
+3868(known)X
+4116(at)X
+2418 714(the)N
+2564(time)X
+2754(of)X
+2869(creation,)X
+3196(the)X
+3342(hash)X
+3536(package)X
+3847(takes)X
+4059(this)X
+2418 802(number)N
+2688(as)X
+2779(a)X
+2839(parameter)X
+3185(and)X
+3325(uses)X
+3487(it)X
+3555(to)X
+3641(hash)X
+3812(entries)X
+4050(into)X
+2418 890(the)N
+2541(full)X
+2677(sized)X
+2867(table)X
+3048(rather)X
+3261(than)X
+3424(growing)X
+3716(the)X
+3838(table)X
+4018(from)X
+2418 978(a)N
+2477(single)X
+2691(bucket.)X
+2968(If)X
+3044(this)X
+3181(number)X
+3448(is)X
+3523(not)X
+3647(known,)X
+3907(the)X
+4027(hash)X
+2418 1066(table)N
+2632(starts)X
+2859(with)X
+3059(a)X
+3153(single)X
+3402(bucket)X
+3674(and)X
+3848(gracefully)X
+2418 1154(expands)N
+2707(as)X
+2800(elements)X
+3111(are)X
+3236(added,)X
+3474(although)X
+3780(a)X
+3842(slight)X
+4044(per-)X
+2418 1242(formance)N
+2747(degradation)X
+3151(may)X
+3313(be)X
+3413(noticed.)X
+3713(Figure)X
+3946(6)X
+4010(illus-)X
+2418 1330(trates)N
+2625(the)X
+2756(difference)X
+3116(in)X
+3211(performance)X
+3651(between)X
+3952(storing)X
+2418 1418(keys)N
+2588(in)X
+2673(a)X
+2732(\256le)X
+2857(when)X
+3054(the)X
+3174(ultimate)X
+3458(size)X
+3605(is)X
+3680(known)X
+3920(\(the)X
+4067(left)X
+2418 1506(bars)N
+2581(in)X
+2672(each)X
+2849(set\),)X
+3014(compared)X
+3360(to)X
+3450(building)X
+3744(the)X
+3870(\256le)X
+4000(when)X
+2418 1594(the)N
+2550(ultimate)X
+2846(size)X
+3005(is)X
+3091(unknown)X
+3422(\(the)X
+3580(right)X
+3764(bars)X
+3931(in)X
+4026(each)X
+2418 1682(set\).)N
+2609(Once)X
+2814(the)X
+2947(\256ll)X
+3069(factor)X
+3291(is)X
+3378(suf\256ciently)X
+3772(high)X
+3948(for)X
+4076(the)X
+2418 1770(page)N
+2596(size)X
+2747(\(8\),)X
+2887(growing)X
+3180(the)X
+3304(table)X
+3486(dynamically)X
+3908(does)X
+4081(lit-)X
+2418 1858(tle)N
+2518(to)X
+2600(degrade)X
+2875(performance.)X
+10 f
+2418 1946 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+9 s
+1 f
+2413 3238(s)N
+2409 3173(d)N
+2409 3108(n)N
+2409 3043(o)N
+2411 2979(c)N
+2411 2914(e)N
+2407 2849(S)N
+3143 4129(Fill)N
+3261(Factor)X
+2448 2152(15)N
+4 Ds
+1 Dt
+2557 2122 MXY
+1473 0 Dl
+-1 Ds
+5 Dt
+2557 MX
+-19 0 Dl
+2448 2747(10)N
+4 Ds
+1 Dt
+2557 2717 MXY
+1473 0 Dl
+-1 Ds
+5 Dt
+2557 MX
+-19 0 Dl
+2484 3343(5)N
+4 Ds
+1 Dt
+2557 3313 MXY
+1473 0 Dl
+-1 Ds
+5 Dt
+2557 MX
+-19 0 Dl
+2484 3938(0)N
+4 Ds
+1 Dt
+2557 3908 MXY
+1473 0 Dl
+-1 Ds
+5 Dt
+2557 MX
+-19 0 Dl
+3976 4015(128)N
+4 Ds
+1 Dt
+4030 3908 MXY
+0 -1786 Dl
+-1 Ds
+5 Dt
+3908 MY
+0 19 Dl
+3626 4015(96)N
+4 Ds
+1 Dt
+3662 3908 MXY
+0 -1786 Dl
+-1 Ds
+5 Dt
+3908 MY
+0 19 Dl
+3258 4015(64)N
+4 Ds
+1 Dt
+3294 3908 MXY
+0 -1786 Dl
+-1 Ds
+5 Dt
+3908 MY
+0 19 Dl
+2889 4015(32)N
+4 Ds
+1 Dt
+2925 3908 MXY
+0 -1786 Dl
+-1 Ds
+5 Dt
+3908 MY
+0 19 Dl
+2539 4015(0)N
+4 Ds
+1 Dt
+2557 3908 MXY
+0 -1786 Dl
+-1 Ds
+5 Dt
+3908 MY
+0 19 Dl
+3908 MY
+0 -1786 Dl
+3908 MY
+1473 0 Dl
+4053 2378(8192)N
+3 Dt
+2569 2277 MXY
+11 0 Dl
+23 48 Dl
+46 -167 Dl
+92 35 Dl
+184 12 Dl
+369 143 Dl
+736 0 Dl
+2334 MY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+3294 2334 MXY
+0 28 Dl
+0 -14 Dl
+13 0 Dl
+-27 0 Dl
+2925 2192 MXY
+0 27 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2741 2180 MXY
+0 27 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2649 2144 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2603 2311 MXY
+0 27 Dl
+0 -13 Dl
+14 0 Dl
+-28 0 Dl
+2580 2263 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2569 2263 MXY
+0 28 Dl
+0 -14 Dl
+13 0 Dl
+-27 0 Dl
+4053 2591(4096)N
+2569 2348 MXY
+11 -11 Dl
+23 -96 Dl
+46 71 Dl
+92 72 Dl
+184 226 Dl
+369 48 Dl
+736 -60 Dl
+2612 MY
+14 -28 Dl
+-28 0 Dl
+14 28 Dl
+3294 2672 MXY
+13 -28 Dl
+-27 0 Dl
+14 28 Dl
+2925 2624 MXY
+14 -28 Dl
+-28 0 Dl
+14 28 Dl
+2741 2398 MXY
+14 -28 Dl
+-28 0 Dl
+14 28 Dl
+2649 2326 MXY
+14 -27 Dl
+-28 0 Dl
+14 27 Dl
+2603 2255 MXY
+14 -28 Dl
+-28 0 Dl
+14 28 Dl
+2580 2350 MXY
+14 -27 Dl
+-28 0 Dl
+14 27 Dl
+2569 2362 MXY
+13 -28 Dl
+-27 0 Dl
+14 28 Dl
+4053 2681(1024)N
+16 Ds
+1 Dt
+2569 2300 MXY
+11 48 Dl
+23 96 Dl
+46 95 Dl
+92 274 Dl
+184 202 Dl
+369 -155 Dl
+736 -190 Dl
+-1 Ds
+3 Dt
+4044 2656 MXY
+-28 28 Dl
+14 -14 Dl
+-14 -14 Dl
+28 28 Dl
+3307 2846 MXY
+-27 28 Dl
+14 -14 Dl
+-14 -14 Dl
+27 28 Dl
+2939 3001 MXY
+-28 28 Dl
+14 -14 Dl
+-14 -14 Dl
+28 28 Dl
+2755 2799 MXY
+-28 28 Dl
+14 -14 Dl
+-14 -14 Dl
+28 28 Dl
+2663 2525 MXY
+-28 28 Dl
+14 -14 Dl
+-14 -14 Dl
+28 28 Dl
+2617 2430 MXY
+-28 28 Dl
+14 -14 Dl
+-14 -14 Dl
+28 28 Dl
+2594 2334 MXY
+-28 28 Dl
+14 -14 Dl
+-14 -14 Dl
+28 28 Dl
+2582 2287 MXY
+-27 27 Dl
+14 -14 Dl
+-14 -13 Dl
+27 27 Dl
+4053 2851(512)N
+5 Dt
+2569 2372 MXY
+11 -24 Dl
+23 405 Dl
+46 83 Dl
+92 227 Dl
+184 -72 Dl
+369 -119 Dl
+736 -107 Dl
+3 Dt
+2751 MY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+3294 2858 MXY
+0 28 Dl
+0 -14 Dl
+13 0 Dl
+-27 0 Dl
+2925 2977 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2741 3049 MXY
+0 27 Dl
+0 -13 Dl
+14 0 Dl
+-28 0 Dl
+2649 2823 MXY
+0 27 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2603 2739 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2580 2334 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2569 2358 MXY
+0 28 Dl
+0 -14 Dl
+13 0 Dl
+-27 0 Dl
+4053 2795(256)N
+20 Ds
+1 Dt
+2569 2456 MXY
+11 285 Dl
+23 95 Dl
+46 251 Dl
+92 -60 Dl
+184 -84 Dl
+369 -107 Dl
+736 -71 Dl
+-1 Ds
+3 Dt
+4016 MX
+27 Dc
+3280 2836 MXY
+27 Dc
+2912 2943 MXY
+27 Dc
+2728 3027 MXY
+27 Dc
+2635 3087 MXY
+28 Dc
+2589 2836 MXY
+28 Dc
+2566 2741 MXY
+27 Dc
+2554 2456 MXY
+28 Dc
+4053 2741(128)N
+1 Dt
+2569 2729 MXY
+11 203 Dl
+23 131 Dl
+46 -60 Dl
+92 -119 Dl
+184 -60 Dl
+369 -83 Dl
+736 -12 Dl
+3 Dt
+2716 MY
+-14 27 Dl
+28 0 Dl
+-14 -27 Dl
+3294 2727 MXY
+-14 28 Dl
+27 0 Dl
+-13 -28 Dl
+2925 2811 MXY
+-14 27 Dl
+28 0 Dl
+-14 -27 Dl
+2741 2870 MXY
+-14 28 Dl
+28 0 Dl
+-14 -28 Dl
+2649 2989 MXY
+-14 28 Dl
+28 0 Dl
+-14 -28 Dl
+2603 3049 MXY
+-14 27 Dl
+28 0 Dl
+-14 -27 Dl
+2580 2918 MXY
+-14 28 Dl
+28 0 Dl
+-14 -28 Dl
+2569 2716 MXY
+-14 27 Dl
+27 0 Dl
+-13 -27 Dl
+3 Dt
+-1 Ds
+3 f
+8 s
+2418 4286(Figure)N
+2628(5c:)X
+1 f
+2738(User)X
+2887(Time)X
+3051(for)X
+3154(dictionary)X
+3442(data)X
+3577(set)X
+3677(with)X
+3820(1M)X
+3938(of)X
+4019(buffer)X
+2418 4374(space)N
+2579(and)X
+2691(varying)X
+2906(bucket)X
+3096(sizes)X
+3240(and)X
+3352(\256ll)X
+3443(factors.)X
+3667(Each)X
+3813(line)X
+3928(is)X
+3990(labeled)X
+2418 4462(with)N
+2548(its)X
+2625(bucket)X
+2811(size.)X
+10 s
+10 f
+2418 4638 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+1 f
+2590 4840(Since)N
+2796(no)X
+2904(known)X
+3150(hash)X
+3325(function)X
+3620(performs)X
+3938(equally)X
+2418 4928(well)N
+2589(on)X
+2702(all)X
+2815(possible)X
+3110(data,)X
+3297(the)X
+3428(user)X
+3595(may)X
+3766(\256nd)X
+3923(that)X
+4076(the)X
+2418 5016(built-in)N
+2678(hash)X
+2849(function)X
+3140(does)X
+3311(poorly)X
+3544(on)X
+3648(a)X
+3708(particular)X
+4040(data)X
+2418 5104(set.)N
+2548(In)X
+2636(this)X
+2771(case,)X
+2950(a)X
+3006(hash)X
+3173(function,)X
+3480(taking)X
+3700(two)X
+3840(arguments)X
+2418 5192(\(a)N
+2507(pointer)X
+2760(to)X
+2848(a)X
+2910(byte)X
+3074(string)X
+3282(and)X
+3424(a)X
+3486(length\))X
+3739(and)X
+3880(returning)X
+2418 5280(an)N
+2517(unsigned)X
+2829(long)X
+2993(to)X
+3077(be)X
+3175(used)X
+3344(as)X
+3433(the)X
+3553(hash)X
+3722(value,)X
+3938(may)X
+4098(be)X
+2418 5368(speci\256ed)N
+2731(at)X
+2817(hash)X
+2992(table)X
+3176(creation)X
+3463(time.)X
+3673(When)X
+3893(an)X
+3996(exist-)X
+2418 5456(ing)N
+2570(hash)X
+2767(table)X
+2973(is)X
+3076(opened)X
+3358(and)X
+3524(a)X
+3609(hash)X
+3805(function)X
+4121(is)X
+2418 5544(speci\256ed,)N
+2752(the)X
+2879(hash)X
+3054(package)X
+3346(will)X
+3498(try)X
+3615(to)X
+3705(determine)X
+4054(that)X
+2418 5632(the)N
+2546(hash)X
+2723(function)X
+3020(supplied)X
+3321(is)X
+3404(the)X
+3532(one)X
+3678(with)X
+3850(which)X
+4076(the)X
+2418 5720(table)N
+2630(was)X
+2811(created.)X
+3139(There)X
+3382(are)X
+3536(a)X
+3627(variety)X
+3905(of)X
+4027(hash)X
+3 f
+432 5960(8)N
+2970(USENIX)X
+9 f
+3292(-)X
+3 f
+3356(Winter)X
+3621('91)X
+9 f
+3748(-)X
+3 f
+3812(Dallas,)X
+4065(TX)X
+
+9 p
+%%Page: 9 9
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+720 258(Seltzer)N
+977(&)X
+1064(Yigit)X
+3278(A)X
+3356(New)X
+3528(Hashing)X
+3831(Package)X
+4136(for)X
+4259(UNIX)X
+1 f
+720 538(functions)N
+1065(provided)X
+1397(with)X
+1586(the)X
+1731(package.)X
+2082(The)X
+2253(default)X
+720 626(function)N
+1014(for)X
+1135(the)X
+1260(package)X
+1551(is)X
+1631(the)X
+1755(one)X
+1897(which)X
+2119(offered)X
+2378(the)X
+720 714(best)N
+875(performance)X
+1308(in)X
+1396(terms)X
+1600(of)X
+1693(cycles)X
+1920(executed)X
+2232(per)X
+2360(call)X
+720 802(\(it)N
+827(did)X
+965(not)X
+1103(produce)X
+1398(the)X
+1531(fewest)X
+1776(collisions)X
+2117(although)X
+2432(it)X
+720 890(was)N
+866(within)X
+1091(a)X
+1148(small)X
+1341(percentage)X
+1710(of)X
+1797(the)X
+1915(function)X
+2202(that)X
+2342(pro-)X
+720 978(duced)N
+947(the)X
+1080(fewest)X
+1324(collisions\).)X
+1731(Again,)X
+1981(in)X
+2077(time)X
+2253(critical)X
+720 1066(applications,)N
+1152(users)X
+1342(are)X
+1466(encouraged)X
+1862(to)X
+1949(experiment)X
+2334(with)X
+720 1154(a)N
+783(variety)X
+1032(of)X
+1125(hash)X
+1298(functions)X
+1622(to)X
+1710(achieve)X
+1982(optimal)X
+2252(perfor-)X
+720 1242(mance.)N
+10 f
+720 1330 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+7 s
+1038 2925(Full)N
+1149(size)X
+1251(table)X
+1384(\(left\))X
+1547 2718(Fill)N
+1643(Factor)X
+2268 2662(64)N
+1964(32)X
+1674(16)X
+1384(8)X
+1093(4)X
+4 Ds
+1 Dt
+900 2280 MXY
+1548 0 Dl
+900 1879 MXY
+1548 0 Dl
+900 1506 MXY
+1548 0 Dl
+1563 2902 MXY
+111 0 Dl
+-1 Ds
+900 MX
+110 0 Dl
+1425 2828(System)N
+983(User)X
+1895 2778 MXY
+ 1895 2778 lineto
+ 1950 2778 lineto
+ 1950 2833 lineto
+ 1895 2833 lineto
+ 1895 2778 lineto
+closepath 21 1895 2778 1950 2833 Dp
+1342 MX
+ 1342 2778 lineto
+ 1397 2778 lineto
+ 1397 2833 lineto
+ 1342 2833 lineto
+ 1342 2778 lineto
+closepath 14 1342 2778 1397 2833 Dp
+900 MX
+ 900 2778 lineto
+ 955 2778 lineto
+ 955 2833 lineto
+ 900 2833 lineto
+ 900 2778 lineto
+closepath 3 900 2778 955 2833 Dp
+5 Dt
+2283 2211 MXY
+96 0 Dl
+1992 MX
+97 0 Dl
+1702 MX
+97 0 Dl
+1411 2252 MXY
+97 0 Dl
+4 Ds
+1 Dt
+2283 2211 MXY
+ 2283 2211 lineto
+ 2379 2211 lineto
+ 2379 2252 lineto
+ 2283 2252 lineto
+ 2283 2211 lineto
+closepath 14 2283 2211 2379 2252 Dp
+1992 MX
+ 1992 2211 lineto
+ 2089 2211 lineto
+ 2089 2252 lineto
+ 1992 2252 lineto
+ 1992 2211 lineto
+closepath 14 1992 2211 2089 2252 Dp
+1702 MX
+ 1702 2211 lineto
+ 1799 2211 lineto
+ 1799 2252 lineto
+ 1702 2252 lineto
+ 1702 2211 lineto
+closepath 14 1702 2211 1799 2252 Dp
+1411 2252 MXY
+ 1411 2252 lineto
+ 1508 2252 lineto
+ 1508 2294 lineto
+ 1411 2294 lineto
+ 1411 2252 lineto
+closepath 14 1411 2252 1508 2294 Dp
+2283 MX
+ 2283 2252 lineto
+ 2379 2252 lineto
+ 2379 2612 lineto
+ 2283 2612 lineto
+ 2283 2252 lineto
+closepath 3 2283 2252 2379 2612 Dp
+1992 MX
+ 1992 2252 lineto
+ 2089 2252 lineto
+ 2089 2612 lineto
+ 1992 2612 lineto
+ 1992 2252 lineto
+closepath 3 1992 2252 2089 2612 Dp
+1702 MX
+ 1702 2252 lineto
+ 1799 2252 lineto
+ 1799 2612 lineto
+ 1702 2612 lineto
+ 1702 2252 lineto
+closepath 3 1702 2252 1799 2612 Dp
+1411 2294 MXY
+ 1411 2294 lineto
+ 1508 2294 lineto
+ 1508 2612 lineto
+ 1411 2612 lineto
+ 1411 2294 lineto
+closepath 3 1411 2294 1508 2612 Dp
+-1 Ds
+2158 2238 MXY
+ 2158 2238 lineto
+ 2255 2238 lineto
+ 2255 2252 lineto
+ 2158 2252 lineto
+ 2158 2238 lineto
+closepath 21 2158 2238 2255 2252 Dp
+1868 MX
+ 1868 2238 lineto
+ 1965 2238 lineto
+ 1965 2280 lineto
+ 1868 2280 lineto
+ 1868 2238 lineto
+closepath 21 1868 2238 1965 2280 Dp
+1577 MX
+ 1577 2238 lineto
+ 1674 2238 lineto
+ 1674 2308 lineto
+ 1577 2308 lineto
+ 1577 2238 lineto
+closepath 21 1577 2238 1674 2308 Dp
+1287 2308 MXY
+ 1287 2308 lineto
+ 1287 2280 lineto
+ 1384 2280 lineto
+ 1384 2308 lineto
+ 1287 2308 lineto
+closepath 21 1287 2280 1384 2308 Dp
+2158 2280 MXY
+ 2158 2280 lineto
+ 2158 2252 lineto
+ 2255 2252 lineto
+ 2255 2280 lineto
+ 2158 2280 lineto
+closepath 14 2158 2252 2255 2280 Dp
+1868 2308 MXY
+ 1868 2308 lineto
+ 1868 2280 lineto
+ 1965 2280 lineto
+ 1965 2308 lineto
+ 1868 2308 lineto
+closepath 14 1868 2280 1965 2308 Dp
+1577 2335 MXY
+ 1577 2335 lineto
+ 1577 2308 lineto
+ 1674 2308 lineto
+ 1674 2335 lineto
+ 1577 2335 lineto
+closepath 14 1577 2308 1674 2335 Dp
+1287 2363 MXY
+ 1287 2363 lineto
+ 1287 2308 lineto
+ 1384 2308 lineto
+ 1384 2363 lineto
+ 1287 2363 lineto
+closepath 14 1287 2308 1384 2363 Dp
+2158 2280 MXY
+ 2158 2280 lineto
+ 2255 2280 lineto
+ 2255 2612 lineto
+ 2158 2612 lineto
+ 2158 2280 lineto
+closepath 3 2158 2280 2255 2612 Dp
+1868 2308 MXY
+ 1868 2308 lineto
+ 1965 2308 lineto
+ 1965 2612 lineto
+ 1868 2612 lineto
+ 1868 2308 lineto
+closepath 3 1868 2308 1965 2612 Dp
+1577 2335 MXY
+ 1577 2335 lineto
+ 1674 2335 lineto
+ 1674 2612 lineto
+ 1577 2612 lineto
+ 1577 2335 lineto
+closepath 3 1577 2335 1674 2612 Dp
+1287 2363 MXY
+ 1287 2363 lineto
+ 1384 2363 lineto
+ 1384 2612 lineto
+ 1287 2612 lineto
+ 1287 2363 lineto
+closepath 3 1287 2363 1384 2612 Dp
+4 Ds
+1121 2066 MXY
+ 1121 2066 lineto
+ 1218 2066 lineto
+ 1224 2080 lineto
+ 1127 2080 lineto
+ 1121 2066 lineto
+closepath 21 1121 2066 1224 2080 Dp
+2080 MY
+ 1121 2080 lineto
+ 1218 2080 lineto
+ 1218 2273 lineto
+ 1121 2273 lineto
+ 1121 2080 lineto
+closepath 14 1121 2080 1218 2273 Dp
+2273 MY
+ 1121 2273 lineto
+ 1218 2273 lineto
+ 1218 2612 lineto
+ 1121 2612 lineto
+ 1121 2273 lineto
+closepath 3 1121 2273 1218 2612 Dp
+-1 Ds
+997 1589 MXY
+ 997 1589 lineto
+ 1093 1589 lineto
+ 1093 1644 lineto
+ 997 1644 lineto
+ 997 1589 lineto
+closepath 21 997 1589 1093 1644 Dp
+1644 MY
+ 997 1644 lineto
+ 1093 1644 lineto
+ 1093 2280 lineto
+ 997 2280 lineto
+ 997 1644 lineto
+closepath 14 997 1644 1093 2280 Dp
+2280 MY
+ 997 2280 lineto
+ 1093 2280 lineto
+ 1093 2612 lineto
+ 997 2612 lineto
+ 997 2280 lineto
+closepath 3 997 2280 1093 2612 Dp
+10 s
+719 2093(s)N
+712 2037(d)N
+712 1982(n)N
+714 1927(o)N
+716 1872(c)N
+716 1816(e)N
+712 1761(S)N
+804 2286(10)N
+804 1899(20)N
+804 1540(30)N
+3 Dt
+900 1506 MXY
+0 1106 Dl
+1548 0 Dl
+7 s
+1978 2828(Elapsed)N
+1701 2925(Dynamically)N
+2018(grown)X
+2184(table)X
+2317(\(right\))X
+3 Dt
+-1 Ds
+8 s
+720 3180(Figure)N
+934(6:)X
+1 f
+1020(The)X
+1152(total)X
+1299(regions)X
+1520(indicate)X
+1755(the)X
+1865(difference)X
+2154(between)X
+2398(the)X
+720 3268(elapsed)N
+931(time)X
+1065(and)X
+1177(the)X
+1275(sum)X
+1402(of)X
+1475(the)X
+1573(system)X
+1771(and)X
+1883(user)X
+2008(time.)X
+2173(The)X
+2291(left)X
+2395(bar)X
+720 3356(of)N
+798(each)X
+939(set)X
+1035(depicts)X
+1241(the)X
+1344(timing)X
+1537(of)X
+1615(the)X
+1718(test)X
+1831(run)X
+1940(when)X
+2102(the)X
+2204(number)X
+2423(of)X
+720 3444(entries)N
+910(is)X
+973(known)X
+1167(in)X
+1237(advance.)X
+1496(The)X
+1614(right)X
+1754(bars)X
+1879(depict)X
+2054(the)X
+2151(timing)X
+2338(when)X
+720 3532(the)N
+814(\256le)X
+912(is)X
+971(grown)X
+1150(from)X
+1290(a)X
+1334(single)X
+1503(bucket.)X
+10 s
+10 f
+720 3708 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+1 f
+892 3910(Since)N
+1131(this)X
+1307(hashing)X
+1617(package)X
+1942(provides)X
+2279(buffer)X
+720 3998(management,)N
+1188(the)X
+1323(amount)X
+1600(of)X
+1704(space)X
+1920(allocated)X
+2247(for)X
+2378(the)X
+720 4086(buffer)N
+948(pool)X
+1121(may)X
+1290(be)X
+1397(speci\256ed)X
+1713(by)X
+1824(the)X
+1953(user.)X
+2157(Using)X
+2378(the)X
+720 4174(same)N
+910(data)X
+1069(set)X
+1183(and)X
+1324(test)X
+1459(procedure)X
+1805(as)X
+1896(used)X
+2067(to)X
+2153(derive)X
+2378(the)X
+720 4262(graphs)N
+962(in)X
+1052(Figures)X
+1320(5a-c,)X
+1507(Figure)X
+1744(7)X
+1812(shows)X
+2039(the)X
+2164(impact)X
+2409(of)X
+720 4350(varying)N
+997(the)X
+1126(size)X
+1282(of)X
+1380(the)X
+1509(buffer)X
+1737(pool.)X
+1950(The)X
+2106(bucket)X
+2351(size)X
+720 4438(was)N
+873(set)X
+989(to)X
+1078(256)X
+1225(bytes)X
+1421(and)X
+1564(the)X
+1689(\256ll)X
+1804(factor)X
+2019(was)X
+2171(set)X
+2287(to)X
+2376(16.)X
+720 4526(The)N
+869(buffer)X
+1090(pool)X
+1256(size)X
+1404(was)X
+1552(varied)X
+1776(from)X
+1955(0)X
+2018(\(the)X
+2166(minimum)X
+720 4614(number)N
+986(of)X
+1074(pages)X
+1277(required)X
+1565(to)X
+1647(be)X
+1743(buffered\))X
+2063(to)X
+2145(1M.)X
+2316(With)X
+720 4702(1M)N
+854(of)X
+944(buffer)X
+1164(space,)X
+1386(the)X
+1507(package)X
+1794(performed)X
+2151(no)X
+2253(I/O)X
+2382(for)X
+720 4790(this)N
+871(data)X
+1040(set.)X
+1204(As)X
+1328(Figure)X
+1572(7)X
+1647(illustrates,)X
+2013(increasing)X
+2378(the)X
+720 4878(buffer)N
+944(pool)X
+1113(size)X
+1265(can)X
+1404(have)X
+1583(a)X
+1646(dramatic)X
+1954(affect)X
+2165(on)X
+2271(result-)X
+720 4966(ing)N
+842(performance.)X
+2 f
+8 s
+1269 4941(7)N
+1 f
+16 s
+720 5353 MXY
+864 0 Dl
+2 f
+8 s
+760 5408(7)N
+1 f
+9 s
+826 5433(Some)N
+1024(allocators)X
+1338(are)X
+1460(extremely)X
+1782(inef\256cient)X
+2107(at)X
+2192(allocating)X
+720 5513(memory.)N
+1029(If)X
+1110(you)X
+1251(\256nd)X
+1396(that)X
+1536(applications)X
+1916(are)X
+2036(running)X
+2292(out)X
+2416(of)X
+720 5593(memory)N
+1005(before)X
+1234(you)X
+1386(think)X
+1578(they)X
+1746(should,)X
+2000(try)X
+2124(varying)X
+2388(the)X
+720 5673(pagesize)N
+986(to)X
+1060(get)X
+1166(better)X
+1348(utilization)X
+1658(from)X
+1816(the)X
+1922(memory)X
+2180(allocator.)X
+10 s
+2830 1975 MXY
+0 -28 Dl
+28 0 Dl
+0 28 Dl
+-28 0 Dl
+2853 2004 MXY
+0 -27 Dl
+28 0 Dl
+0 27 Dl
+-28 0 Dl
+2876 2016 MXY
+0 -27 Dl
+27 0 Dl
+0 27 Dl
+-27 0 Dl
+2922 1998 MXY
+0 -27 Dl
+27 0 Dl
+0 27 Dl
+-27 0 Dl
+2967 2025 MXY
+0 -28 Dl
+28 0 Dl
+0 28 Dl
+-28 0 Dl
+3013 2031 MXY
+0 -28 Dl
+28 0 Dl
+0 28 Dl
+-28 0 Dl
+3059 MX
+0 -28 Dl
+27 0 Dl
+0 28 Dl
+-27 0 Dl
+3196 2052 MXY
+0 -28 Dl
+27 0 Dl
+0 28 Dl
+-27 0 Dl
+3561 2102 MXY
+0 -28 Dl
+28 0 Dl
+0 28 Dl
+-28 0 Dl
+4292 2105 MXY
+0 -28 Dl
+27 0 Dl
+0 28 Dl
+-27 0 Dl
+4 Ds
+1 Dt
+2844 1961 MXY
+23 30 Dl
+23 12 Dl
+45 -18 Dl
+46 26 Dl
+46 6 Dl
+45 0 Dl
+137 21 Dl
+366 50 Dl
+730 3 Dl
+9 s
+4227 2158(User)N
+-1 Ds
+3 Dt
+2830 1211 MXY
+27 Dc
+2853 1261 MXY
+27 Dc
+2876 1267 MXY
+27 Dc
+2921 1341 MXY
+27 Dc
+2967 1385 MXY
+27 Dc
+3013 1450 MXY
+27 Dc
+3059 1497 MXY
+27 Dc
+3196 1686 MXY
+27 Dc
+3561 2109 MXY
+27 Dc
+4292 2295 MXY
+27 Dc
+20 Ds
+1 Dt
+2844 1211 MXY
+23 50 Dl
+23 6 Dl
+45 74 Dl
+46 44 Dl
+46 65 Dl
+45 47 Dl
+137 189 Dl
+366 423 Dl
+730 186 Dl
+4181 2270(System)N
+-1 Ds
+3 Dt
+2844 583 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2867 672 MXY
+0 27 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+2890 701 MXY
+0 28 Dl
+0 -14 Dl
+13 0 Dl
+-27 0 Dl
+2935 819 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-27 0 Dl
+2981 849 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+3027 908 MXY
+0 27 Dl
+0 -13 Dl
+14 0 Dl
+-28 0 Dl
+3072 1026 MXY
+0 27 Dl
+0 -13 Dl
+14 0 Dl
+-27 0 Dl
+3209 1292 MXY
+0 27 Dl
+0 -14 Dl
+14 0 Dl
+-27 0 Dl
+3575 1823 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-28 0 Dl
+4305 2059 MXY
+0 28 Dl
+0 -14 Dl
+14 0 Dl
+-27 0 Dl
+5 Dt
+2844 597 MXY
+23 88 Dl
+23 30 Dl
+45 118 Dl
+46 30 Dl
+46 59 Dl
+45 118 Dl
+137 265 Dl
+366 532 Dl
+730 236 Dl
+4328 2103(Total)N
+2844 2310 MXY
+1461 0 Dl
+2844 MX
+0 -1772 Dl
+2310 MY
+0 18 Dl
+4 Ds
+1 Dt
+2310 MY
+0 -1772 Dl
+2826 2416(0)N
+-1 Ds
+5 Dt
+3209 2310 MXY
+0 18 Dl
+4 Ds
+1 Dt
+2310 MY
+0 -1772 Dl
+3155 2416(256)N
+-1 Ds
+5 Dt
+3575 2310 MXY
+0 18 Dl
+4 Ds
+1 Dt
+2310 MY
+0 -1772 Dl
+3521 2416(512)N
+-1 Ds
+5 Dt
+3940 2310 MXY
+0 18 Dl
+4 Ds
+1 Dt
+2310 MY
+0 -1772 Dl
+3886 2416(768)N
+-1 Ds
+5 Dt
+4305 2310 MXY
+0 18 Dl
+4 Ds
+1 Dt
+2310 MY
+0 -1772 Dl
+4233 2416(1024)N
+-1 Ds
+5 Dt
+2844 2310 MXY
+-18 0 Dl
+4 Ds
+1 Dt
+2844 MX
+1461 0 Dl
+2771 2340(0)N
+-1 Ds
+5 Dt
+2844 2014 MXY
+-18 0 Dl
+2844 1719 MXY
+-18 0 Dl
+4 Ds
+1 Dt
+2844 MX
+1461 0 Dl
+2735 1749(20)N
+-1 Ds
+5 Dt
+2844 1423 MXY
+-18 0 Dl
+2844 1128 MXY
+-18 0 Dl
+4 Ds
+1 Dt
+2844 MX
+1461 0 Dl
+2735 1158(40)N
+-1 Ds
+5 Dt
+2844 833 MXY
+-18 0 Dl
+2844 538 MXY
+-18 0 Dl
+4 Ds
+1 Dt
+2844 MX
+1461 0 Dl
+2735 568(60)N
+3239 2529(Buffer)N
+3445(Pool)X
+3595(Size)X
+3737(\(in)X
+3835(K\))X
+2695 1259(S)N
+2699 1324(e)N
+2699 1388(c)N
+2697 1452(o)N
+2697 1517(n)N
+2697 1581(d)N
+2701 1645(s)N
+3 Dt
+-1 Ds
+3 f
+8 s
+2706 2773(Figure)N
+2908(7:)X
+1 f
+2982(User)X
+3123(time)X
+3258(is)X
+3322(virtually)X
+3560(insensitive)X
+3854(to)X
+3924(the)X
+4022(amount)X
+4234(of)X
+4307(buffer)X
+2706 2861(pool)N
+2852(available,)X
+3130(however,)X
+3396(both)X
+3541(system)X
+3750(time)X
+3895(and)X
+4018(elapsed)X
+4240(time)X
+4385(are)X
+2706 2949(inversely)N
+2960(proportional)X
+3296(to)X
+3366(the)X
+3464(size)X
+3583(of)X
+3656(the)X
+3753(buffer)X
+3927(pool.)X
+4092(Even)X
+4242(for)X
+4335(large)X
+2706 3037(data)N
+2831(sets)X
+2946(where)X
+3120(one)X
+3230(expects)X
+3439(few)X
+3552(collisions,)X
+3832(specifying)X
+4116(a)X
+4162(large)X
+4307(buffer)X
+2706 3125(pool)N
+2836(dramatically)X
+3171(improves)X
+3425(performance.)X
+10 s
+10 f
+2706 3301 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+3175 3543(Enhanced)N
+3536(Functionality)X
+1 f
+2878 3675(This)N
+3046(hashing)X
+3320(package)X
+3609(provides)X
+3910(a)X
+3971(set)X
+4085(of)X
+4177(compati-)X
+2706 3763(bility)N
+2895(routines)X
+3174(to)X
+3257(implement)X
+3620(the)X
+2 f
+3739(ndbm)X
+1 f
+3937(interface.)X
+4279(How-)X
+2706 3851(ever,)N
+2893(when)X
+3095(the)X
+3220(native)X
+3443(interface)X
+3752(is)X
+3832(used,)X
+4026(the)X
+4151(following)X
+2706 3939(additional)N
+3046(functionality)X
+3475(is)X
+3548(provided:)X
+10 f
+2798 4071(g)N
+1 f
+2946(Inserts)X
+3197(never)X
+3413(fail)X
+3556(because)X
+3847(too)X
+3985(many)X
+4199(keys)X
+2946 4159(hash)N
+3113(to)X
+3195(the)X
+3313(same)X
+3498(value.)X
+10 f
+2798 4247(g)N
+1 f
+2946(Inserts)X
+3187(never)X
+3393(fail)X
+3527(because)X
+3808(key)X
+3950(and/or)X
+4181(asso-)X
+2946 4335(ciated)N
+3158(data)X
+3312(is)X
+3385(too)X
+3507(large)X
+10 f
+2798 4423(g)N
+1 f
+2946(Hash)X
+3131(functions)X
+3449(may)X
+3607(be)X
+3703(user-speci\256ed.)X
+10 f
+2798 4511(g)N
+1 f
+2946(Multiple)X
+3268(pages)X
+3498(may)X
+3683(be)X
+3806(cached)X
+4077(in)X
+4186(main)X
+2946 4599(memory.)N
+2706 4731(It)N
+2801(also)X
+2976(provides)X
+3298(a)X
+3380(set)X
+3514(of)X
+3626(compatibility)X
+4097(routines)X
+4400(to)X
+2706 4819(implement)N
+3087(the)X
+2 f
+3224(hsearch)X
+1 f
+3516(interface.)X
+3876(Again,)X
+4130(the)X
+4266(native)X
+2706 4907(interface)N
+3008(offers)X
+3216(enhanced)X
+3540(functionality:)X
+10 f
+2798 5039(g)N
+1 f
+2946(Files)X
+3121(may)X
+3279(grow)X
+3464(beyond)X
+2 f
+3720(nelem)X
+1 f
+3932(elements.)X
+10 f
+2798 5127(g)N
+1 f
+2946(Multiple)X
+3247(hash)X
+3420(tables)X
+3632(may)X
+3795(be)X
+3896(accessed)X
+4203(con-)X
+2946 5215(currently.)N
+10 f
+2798 5303(g)N
+1 f
+2946(Hash)X
+3134(tables)X
+3344(may)X
+3505(be)X
+3604(stored)X
+3823(and)X
+3962(accessed)X
+4266(on)X
+2946 5391(disk.)N
+10 f
+2798 5479(g)N
+1 f
+2946(Hash)X
+3155(functions)X
+3497(may)X
+3679(be)X
+3799(user-speci\256ed)X
+4288(at)X
+2946 5567(runtime.)N
+3 f
+720 5960(USENIX)N
+9 f
+1042(-)X
+3 f
+1106(Winter)X
+1371('91)X
+9 f
+1498(-)X
+3 f
+1562(Dallas,)X
+1815(TX)X
+4424(9)X
+
+10 p
+%%Page: 10 10
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+432 258(A)N
+510(New)X
+682(Hashing)X
+985(Package)X
+1290(for)X
+1413(UNIX)X
+3663(Seltzer)X
+3920(&)X
+4007(Yigit)X
+459 538(Relative)N
+760(Performance)X
+1227(of)X
+1314(the)X
+1441(New)X
+1613(Implementation)X
+1 f
+604 670(The)N
+761(performance)X
+1200(testing)X
+1445(of)X
+1544(the)X
+1674(new)X
+1840(package)X
+2135(is)X
+432 758(divided)N
+711(into)X
+874(two)X
+1033(test)X
+1183(suites.)X
+1424(The)X
+1588(\256rst)X
+1751(suite)X
+1941(of)X
+2046(tests)X
+432 846(requires)N
+727(that)X
+882(the)X
+1015(tables)X
+1237(be)X
+1348(read)X
+1522(from)X
+1713(and)X
+1864(written)X
+2126(to)X
+432 934(disk.)N
+640(In)X
+742(these)X
+942(tests,)X
+1139(the)X
+1272(basis)X
+1467(for)X
+1595(comparison)X
+2003(is)X
+2090(the)X
+432 1022(4.3BSD-Reno)N
+908(version)X
+1169(of)X
+2 f
+1260(ndbm)X
+1 f
+1438(.)X
+1502(Based)X
+1722(on)X
+1826(the)X
+1948(designs)X
+432 1110(of)N
+2 f
+521(sdbm)X
+1 f
+712(and)X
+2 f
+850(gdbm)X
+1 f
+1028(,)X
+1070(they)X
+1230(are)X
+1351(expected)X
+1659(to)X
+1743(perform)X
+2024(simi-)X
+432 1198(larly)N
+605(to)X
+2 f
+693(ndbm)X
+1 f
+871(,)X
+917(and)X
+1059(we)X
+1179(do)X
+1285(not)X
+1413(show)X
+1608(their)X
+1781(performance)X
+432 1286(numbers.)N
+800(The)X
+977(second)X
+1252(suite)X
+1454(contains)X
+1772(the)X
+1921(memory)X
+432 1374(resident)N
+712(test)X
+849(which)X
+1071(does)X
+1243(not)X
+1370(require)X
+1623(that)X
+1768(the)X
+1891(\256les)X
+2049(ever)X
+432 1462(be)N
+533(written)X
+784(to)X
+870(disk,)X
+1047(only)X
+1213(that)X
+1357(hash)X
+1528(tables)X
+1739(may)X
+1901(be)X
+2001(mani-)X
+432 1550(pulated)N
+692(in)X
+778(main)X
+961(memory.)X
+1291(In)X
+1381(this)X
+1519(test,)X
+1673(we)X
+1790(compare)X
+2090(the)X
+432 1638(performance)N
+859(to)X
+941(that)X
+1081(of)X
+1168(the)X
+2 f
+1286(hsearch)X
+1 f
+1560(routines.)X
+604 1752(For)N
+760(both)X
+947(suites,)X
+1194(two)X
+1358(different)X
+1679(databases)X
+2031(were)X
+432 1840(used.)N
+656(The)X
+818(\256rst)X
+979(is)X
+1069(the)X
+1204(dictionary)X
+1566(database)X
+1880(described)X
+432 1928(previously.)N
+836(The)X
+987(second)X
+1236(was)X
+1386(constructed)X
+1781(from)X
+1962(a)X
+2023(pass-)X
+432 2016(word)N
+647(\256le)X
+799(with)X
+990(approximately)X
+1502(300)X
+1671(accounts.)X
+2041(Two)X
+432 2104(records)N
+700(were)X
+887(constructed)X
+1287(for)X
+1411(each)X
+1589(account.)X
+1909(The)X
+2064(\256rst)X
+432 2192(used)N
+604(the)X
+727(logname)X
+1028(as)X
+1120(the)X
+1243(key)X
+1384(and)X
+1525(the)X
+1648(remainder)X
+1999(of)X
+2090(the)X
+432 2280(password)N
+768(entry)X
+965(for)X
+1091(the)X
+1221(data.)X
+1427(The)X
+1584(second)X
+1839(was)X
+1996(keyed)X
+432 2368(by)N
+541(uid)X
+672(and)X
+817(contained)X
+1157(the)X
+1283(entire)X
+1494(password)X
+1825(entry)X
+2018(as)X
+2113(its)X
+432 2456(data)N
+589(\256eld.)X
+794(The)X
+942(tests)X
+1107(were)X
+1287(all)X
+1389(run)X
+1518(on)X
+1620(the)X
+1740(HP)X
+1864(9000)X
+2046(with)X
+432 2544(the)N
+574(same)X
+783(con\256guration)X
+1254(previously)X
+1636(described.)X
+2027(Each)X
+432 2632(test)N
+576(was)X
+734(run)X
+874(\256ve)X
+1027(times)X
+1232(and)X
+1380(the)X
+1510(timing)X
+1750(results)X
+1991(of)X
+2090(the)X
+432 2720(runs)N
+602(were)X
+791(averaged.)X
+1154(The)X
+1311(variance)X
+1616(across)X
+1849(the)X
+1979(5)X
+2050(runs)X
+432 2808(was)N
+591(approximately)X
+1088(1%)X
+1229(of)X
+1330(the)X
+1462(average)X
+1746(yielding)X
+2041(95%)X
+432 2896(con\256dence)N
+800(intervals)X
+1096(of)X
+1183(approximately)X
+1666(2%.)X
+3 f
+1021 3050(Disk)N
+1196(Based)X
+1420(Tests)X
+1 f
+604 3182(In)N
+693(these)X
+880(tests,)X
+1064(we)X
+1180(use)X
+1308(a)X
+1365(bucket)X
+1600(size)X
+1746(of)X
+1834(1024)X
+2015(and)X
+2152(a)X
+432 3270(\256ll)N
+540(factor)X
+748(of)X
+835(32.)X
+3 f
+432 3384(create)N
+663(test)X
+1 f
+547 3498(The)N
+703(keys)X
+881(are)X
+1011(entered)X
+1279(into)X
+1433(the)X
+1561(hash)X
+1738(table,)X
+1944(and)X
+2090(the)X
+547 3586(\256le)N
+669(is)X
+742(\257ushed)X
+993(to)X
+1075(disk.)X
+3 f
+432 3700(read)N
+608(test)X
+1 f
+547 3814(A)N
+640(lookup)X
+897(is)X
+984(performed)X
+1353(for)X
+1481(each)X
+1663(key)X
+1813(in)X
+1909(the)X
+2041(hash)X
+547 3902(table.)N
+3 f
+432 4016(verify)N
+653(test)X
+1 f
+547 4130(A)N
+640(lookup)X
+897(is)X
+984(performed)X
+1353(for)X
+1481(each)X
+1663(key)X
+1813(in)X
+1909(the)X
+2041(hash)X
+547 4218(table,)N
+759(and)X
+911(the)X
+1045(data)X
+1215(returned)X
+1519(is)X
+1608(compared)X
+1961(against)X
+547 4306(that)N
+687(originally)X
+1018(stored)X
+1234(in)X
+1316(the)X
+1434(hash)X
+1601(table.)X
+3 f
+432 4420(sequential)N
+798(retrieve)X
+1 f
+547 4534(All)N
+674(keys)X
+846(are)X
+970(retrieved)X
+1281(in)X
+1367(sequential)X
+1716(order)X
+1910(from)X
+2090(the)X
+547 4622(hash)N
+724(table.)X
+950(The)X
+2 f
+1105(ndbm)X
+1 f
+1313(interface)X
+1625(allows)X
+1863(sequential)X
+547 4710(retrieval)N
+848(of)X
+948(the)X
+1079(keys)X
+1259(from)X
+1448(the)X
+1578(database,)X
+1907(but)X
+2041(does)X
+547 4798(not)N
+701(return)X
+945(the)X
+1094(data)X
+1279(associated)X
+1660(with)X
+1853(each)X
+2052(key.)X
+547 4886(Therefore,)N
+929(we)X
+1067(compare)X
+1388(the)X
+1530(performance)X
+1980(of)X
+2090(the)X
+547 4974(new)N
+703(package)X
+989(to)X
+1073(two)X
+1215(different)X
+1514(runs)X
+1674(of)X
+2 f
+1763(ndbm)X
+1 f
+1941(.)X
+2002(In)X
+2090(the)X
+547 5062(\256rst)N
+697(case,)X
+2 f
+882(ndbm)X
+1 f
+1086(returns)X
+1335(only)X
+1503(the)X
+1627(keys)X
+1800(while)X
+2003(in)X
+2090(the)X
+547 5150(second,)N
+2 f
+823(ndbm)X
+1 f
+1034(returns)X
+1290(both)X
+1465(the)X
+1596(keys)X
+1776(and)X
+1924(the)X
+2054(data)X
+547 5238(\(requiring)N
+894(a)X
+956(second)X
+1204(call)X
+1345(to)X
+1432(the)X
+1555(library\).)X
+1861(There)X
+2074(is)X
+2152(a)X
+547 5326(single)N
+764(run)X
+897(for)X
+1017(the)X
+1141(new)X
+1300(library)X
+1539(since)X
+1729(it)X
+1798(returns)X
+2046(both)X
+547 5414(the)N
+665(key)X
+801(and)X
+937(the)X
+1055(data.)X
+3 f
+3014 538(In-Memory)N
+3431(Test)X
+1 f
+2590 670(This)N
+2757(test)X
+2892(uses)X
+3054(a)X
+3114(bucket)X
+3352(size)X
+3501(of)X
+3592(256)X
+3736(and)X
+3876(a)X
+3936(\256ll)X
+4048(fac-)X
+2418 758(tor)N
+2527(of)X
+2614(8.)X
+3 f
+2418 872(create/read)N
+2827(test)X
+1 f
+2533 986(In)N
+2627(this)X
+2769(test,)X
+2927(a)X
+2989(hash)X
+3162(table)X
+3344(is)X
+3423(created)X
+3682(by)X
+3788(inserting)X
+4094(all)X
+2533 1074(the)N
+2660(key/data)X
+2961(pairs.)X
+3186(Then)X
+3380(a)X
+3445(keyed)X
+3666(retrieval)X
+3963(is)X
+4044(per-)X
+2533 1162(formed)N
+2801(for)X
+2931(each)X
+3115(pair,)X
+3295(and)X
+3446(the)X
+3579(hash)X
+3761(table)X
+3952(is)X
+4040(des-)X
+2533 1250(troyed.)N
+3 f
+2938 1404(Performance)N
+3405(Results)X
+1 f
+2590 1536(Figures)N
+2866(8a)X
+2978(and)X
+3130(8b)X
+3246(show)X
+3451(the)X
+3585(user)X
+3755(time,)X
+3952(system)X
+2418 1624(time,)N
+2608(and)X
+2752(elapsed)X
+3021(time)X
+3191(for)X
+3312(each)X
+3487(test)X
+3625(for)X
+3746(both)X
+3915(the)X
+4040(new)X
+2418 1712(implementation)N
+2951(and)X
+3098(the)X
+3227(old)X
+3360(implementation)X
+3893(\()X
+2 f
+3920(hsearch)X
+1 f
+2418 1800(or)N
+2 f
+2528(ndbm)X
+1 f
+2706(,)X
+2769(whichever)X
+3147(is)X
+3243(appropriate\))X
+3678(as)X
+3787(well)X
+3967(as)X
+4076(the)X
+2418 1888(improvement.)N
+2929(The)X
+3098(improvement)X
+3569(is)X
+3666(expressed)X
+4027(as)X
+4138(a)X
+2418 1976(percentage)N
+2787(of)X
+2874(the)X
+2992(old)X
+3114(running)X
+3383(time:)X
+0 f
+8 s
+2418 2275(%)N
+2494(=)X
+2570(100)X
+2722(*)X
+2798 -0.4219(\(old_time)AX
+3178(-)X
+3254 -0.4219(new_time\))AX
+3634(/)X
+3710(old_time)X
+1 f
+10 s
+2590 2600(In)N
+2700(nearly)X
+2944(all)X
+3067(cases,)X
+3299(the)X
+3439(new)X
+3615(routines)X
+3915(perform)X
+2418 2688(better)N
+2628(than)X
+2793(the)X
+2918(old)X
+3047(routines)X
+3332(\(both)X
+2 f
+3527(hsearch)X
+1 f
+3807(and)X
+2 f
+3949(ndbm)X
+1 f
+4127(\).)X
+2418 2776(Although)N
+2755(the)X
+3 f
+2888(create)X
+1 f
+3134(tests)X
+3311(exhibit)X
+3567(superior)X
+3864(user)X
+4032(time)X
+2418 2864(performance,)N
+2869(the)X
+2991(test)X
+3126(time)X
+3292(is)X
+3369(dominated)X
+3731(by)X
+3834(the)X
+3955(cost)X
+4107(of)X
+2418 2952(writing)N
+2677(the)X
+2803(actual)X
+3023(\256le)X
+3153(to)X
+3243(disk.)X
+3444(For)X
+3583(the)X
+3709(large)X
+3897(database)X
+2418 3040(\(the)N
+2564(dictionary\),)X
+2957(this)X
+3093(completely)X
+3470(overwhelmed)X
+3927(the)X
+4045(sys-)X
+2418 3128(tem)N
+2570(time.)X
+2783(However,)X
+3129(for)X
+3254(the)X
+3383(small)X
+3587(data)X
+3752(base,)X
+3946(we)X
+4071(see)X
+2418 3216(that)N
+2569(differences)X
+2958(in)X
+3051(both)X
+3224(user)X
+3389(and)X
+3536(system)X
+3788(time)X
+3960(contri-)X
+2418 3304(bute)N
+2576(to)X
+2658(the)X
+2776(superior)X
+3059(performance)X
+3486(of)X
+3573(the)X
+3691(new)X
+3845(package.)X
+2590 3418(The)N
+3 f
+2764(read)X
+1 f
+2920(,)X
+3 f
+2989(verify)X
+1 f
+3190(,)X
+3259(and)X
+3 f
+3424(sequential)X
+1 f
+3818(results)X
+4075(are)X
+2418 3506(deceptive)N
+2758(for)X
+2883(the)X
+3012(small)X
+3216(database)X
+3524(since)X
+3720(the)X
+3849(entire)X
+4063(test)X
+2418 3594(ran)N
+2551(in)X
+2643(under)X
+2856(a)X
+2922(second.)X
+3215(However,)X
+3560(on)X
+3669(the)X
+3796(larger)X
+4013(data-)X
+2418 3682(base)N
+2590(the)X
+3 f
+2716(read)X
+1 f
+2900(and)X
+3 f
+3044(verify)X
+1 f
+3273(tests)X
+3443(bene\256t)X
+3689(from)X
+3873(the)X
+3999(cach-)X
+2418 3770(ing)N
+2546(of)X
+2639(buckets)X
+2910(in)X
+2998(the)X
+3122(new)X
+3282(package)X
+3571(to)X
+3658(improve)X
+3950(perfor-)X
+2418 3858(mance)N
+2666(by)X
+2784(over)X
+2965(80%.)X
+3169(Since)X
+3384(the)X
+3519(\256rst)X
+3 f
+3680(sequential)X
+1 f
+4063(test)X
+2418 3946(does)N
+2598(not)X
+2733(require)X
+2 f
+2994(ndbm)X
+1 f
+3205(to)X
+3299(return)X
+3523(the)X
+3653(data)X
+3819(values,)X
+4076(the)X
+2418 4034(user)N
+2573(time)X
+2735(is)X
+2808(lower)X
+3011(than)X
+3169(for)X
+3283(the)X
+3401(new)X
+3555(package.)X
+3879(However)X
+2418 4122(when)N
+2613(we)X
+2728(require)X
+2977(both)X
+3139(packages)X
+3454(to)X
+3536(return)X
+3748(data,)X
+3922(the)X
+4040(new)X
+2418 4210(package)N
+2702(excels)X
+2923(in)X
+3005(all)X
+3105(three)X
+3286(timings.)X
+2590 4324(The)N
+2773(small)X
+3003(database)X
+3337(runs)X
+3532(so)X
+3660(quickly)X
+3957(in)X
+4076(the)X
+2418 4412(memory-resident)N
+3000(case)X
+3173(that)X
+3326(the)X
+3457(results)X
+3699(are)X
+3831(uninterest-)X
+2418 4500(ing.)N
+2589(However,)X
+2933(for)X
+3056(the)X
+3183(larger)X
+3400(database)X
+3706(the)X
+3833(new)X
+3995(pack-)X
+2418 4588(age)N
+2567(pays)X
+2751(a)X
+2824(small)X
+3033(penalty)X
+3305(in)X
+3403(system)X
+3661(time)X
+3839(because)X
+4130(it)X
+2418 4676(limits)N
+2636(its)X
+2748(main)X
+2944(memory)X
+3247(utilization)X
+3607(and)X
+3759(swaps)X
+3991(pages)X
+2418 4764(out)N
+2550(to)X
+2642(temporary)X
+3002(storage)X
+3264(in)X
+3356(the)X
+3484(\256le)X
+3616(system)X
+3868(while)X
+4076(the)X
+2 f
+2418 4852(hsearch)N
+1 f
+2698(package)X
+2988(requires)X
+3273(that)X
+3419(the)X
+3543(application)X
+3924(allocate)X
+2418 4940(enough)N
+2692(space)X
+2909(for)X
+3041(all)X
+3159(key/data)X
+3468(pair.)X
+3670(However,)X
+4022(even)X
+2418 5028(with)N
+2600(the)X
+2738(system)X
+3000(time)X
+3182(penalty,)X
+3477(the)X
+3614(resulting)X
+3933(elapsed)X
+2418 5116(time)N
+2580(improves)X
+2898(by)X
+2998(over)X
+3161(50%.)X
+3 f
+432 5960(10)N
+2970(USENIX)X
+9 f
+3292(-)X
+3 f
+3356(Winter)X
+3621('91)X
+9 f
+3748(-)X
+3 f
+3812(Dallas,)X
+4065(TX)X
+
+11 p
+%%Page: 11 11
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+720 258(Seltzer)N
+977(&)X
+1064(Yigit)X
+3278(A)X
+3356(New)X
+3528(Hashing)X
+3831(Package)X
+4136(for)X
+4259(UNIX)X
+1 f
+10 f
+908 454(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2 f
+1379 546(hash)N
+1652(ndbm)X
+1950(%change)X
+1 f
+10 f
+908 550(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+948 642(CREATE)N
+10 f
+908 646(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+1125 738(user)N
+1424(6.4)X
+1671(12.2)X
+2073(48)X
+1157 826(sys)N
+1384(32.5)X
+1671(34.7)X
+2113(6)X
+3 f
+1006 914(elapsed)N
+10 f
+1310 922(c)N
+890(c)Y
+810(c)Y
+730(c)Y
+3 f
+1384 914(90.4)N
+10 f
+1581 922(c)N
+890(c)Y
+810(c)Y
+730(c)Y
+3 f
+1671 914(99.6)N
+10 f
+1883 922(c)N
+890(c)Y
+810(c)Y
+730(c)Y
+3 f
+2113 914(9)N
+1 f
+10 f
+908 910(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+908 926(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+948 1010(READ)N
+10 f
+908 1014(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+1125 1106(user)N
+1424(3.4)X
+1711(6.1)X
+2073(44)X
+1157 1194(sys)N
+1424(1.2)X
+1671(15.3)X
+2073(92)X
+3 f
+1006 1282(elapsed)N
+10 f
+1310 1290(c)N
+1258(c)Y
+1178(c)Y
+1098(c)Y
+3 f
+1424 1282(4.0)N
+10 f
+1581 1290(c)N
+1258(c)Y
+1178(c)Y
+1098(c)Y
+3 f
+1671 1282(21.2)N
+10 f
+1883 1290(c)N
+1258(c)Y
+1178(c)Y
+1098(c)Y
+3 f
+2073 1282(81)N
+1 f
+10 f
+908 1278(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+908 1294(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+948 1378(VERIFY)N
+10 f
+908 1382(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+1125 1474(user)N
+1424(3.5)X
+1711(6.3)X
+2073(44)X
+1157 1562(sys)N
+1424(1.2)X
+1671(15.3)X
+2073(92)X
+3 f
+1006 1650(elapsed)N
+10 f
+1310 1658(c)N
+1626(c)Y
+1546(c)Y
+1466(c)Y
+3 f
+1424 1650(4.0)N
+10 f
+1581 1658(c)N
+1626(c)Y
+1546(c)Y
+1466(c)Y
+3 f
+1671 1650(21.2)N
+10 f
+1883 1658(c)N
+1626(c)Y
+1546(c)Y
+1466(c)Y
+3 f
+2073 1650(81)N
+1 f
+10 f
+908 1646(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+908 1662(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+948 1746(SEQUENTIAL)N
+10 f
+908 1750(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+1125 1842(user)N
+1424(2.7)X
+1711(1.9)X
+2046(-42)X
+1157 1930(sys)N
+1424(0.7)X
+1711(3.9)X
+2073(82)X
+3 f
+1006 2018(elapsed)N
+10 f
+1310 2026(c)N
+1994(c)Y
+1914(c)Y
+1834(c)Y
+3 f
+1424 2018(3.0)N
+10 f
+1581 2026(c)N
+1994(c)Y
+1914(c)Y
+1834(c)Y
+3 f
+1711 2018(5.0)N
+10 f
+1883 2026(c)N
+1994(c)Y
+1914(c)Y
+1834(c)Y
+3 f
+2073 2018(40)N
+1 f
+10 f
+908 2014(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+908 2030(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+948 2114(SEQUENTIAL)N
+1467(\(with)X
+1656(data)X
+1810(retrieval\))X
+10 f
+908 2118(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+1125 2210(user)N
+1424(2.7)X
+1711(8.2)X
+2073(67)X
+1157 2298(sys)N
+1424(0.7)X
+1711(4.3)X
+2073(84)X
+3 f
+1006 2386(elapsed)N
+1424(3.0)X
+1671(12.0)X
+2073(75)X
+1 f
+10 f
+908 2390(i)N
+927(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+899 2394(c)N
+2378(c)Y
+2298(c)Y
+2218(c)Y
+2138(c)Y
+2058(c)Y
+1978(c)Y
+1898(c)Y
+1818(c)Y
+1738(c)Y
+1658(c)Y
+1578(c)Y
+1498(c)Y
+1418(c)Y
+1338(c)Y
+1258(c)Y
+1178(c)Y
+1098(c)Y
+1018(c)Y
+938(c)Y
+858(c)Y
+778(c)Y
+698(c)Y
+618(c)Y
+538(c)Y
+1310 2394(c)N
+2362(c)Y
+2282(c)Y
+2202(c)Y
+1581 2394(c)N
+2362(c)Y
+2282(c)Y
+2202(c)Y
+1883 2394(c)N
+2362(c)Y
+2282(c)Y
+2202(c)Y
+2278 2394(c)N
+2378(c)Y
+2298(c)Y
+2218(c)Y
+2138(c)Y
+2058(c)Y
+1978(c)Y
+1898(c)Y
+1818(c)Y
+1738(c)Y
+1658(c)Y
+1578(c)Y
+1498(c)Y
+1418(c)Y
+1338(c)Y
+1258(c)Y
+1178(c)Y
+1098(c)Y
+1018(c)Y
+938(c)Y
+858(c)Y
+778(c)Y
+698(c)Y
+618(c)Y
+538(c)Y
+905 2574(i)N
+930(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2 f
+1318 2666(hash)N
+1585(hsearch)X
+1953(%change)X
+1 f
+10 f
+905 2670(i)N
+930(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+945 2762(CREATE/READ)N
+10 f
+905 2766(i)N
+930(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+1064 2858(user)N
+1343(6.6)X
+1642(17.2)X
+2096(62)X
+1096 2946(sys)N
+1343(1.1)X
+1682(0.3)X
+2029(-266)X
+3 f
+945 3034(elapsed)N
+1343(7.8)X
+1642(17.0)X
+2096(54)X
+1 f
+10 f
+905 3038(i)N
+930(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+896 3050(c)N
+2978(c)Y
+2898(c)Y
+2818(c)Y
+2738(c)Y
+2658(c)Y
+1249 3034(c)N
+3010(c)Y
+2930(c)Y
+2850(c)Y
+1520 3034(c)N
+3010(c)Y
+2930(c)Y
+2850(c)Y
+1886 3034(c)N
+3010(c)Y
+2930(c)Y
+2850(c)Y
+2281 3050(c)N
+2978(c)Y
+2898(c)Y
+2818(c)Y
+2738(c)Y
+2658(c)Y
+3 f
+720 3174(Figure)N
+967(8a:)X
+1 f
+1094(Timing)X
+1349(results)X
+1578(for)X
+1692(the)X
+1810(dictionary)X
+2155(database.)X
+10 f
+720 3262 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+1407 3504(Conclusion)N
+1 f
+892 3636(This)N
+1063(paper)X
+1271(has)X
+1407(presented)X
+1744(the)X
+1871(design,)X
+2129(implemen-)X
+720 3724(tation)N
+928(and)X
+1070(performance)X
+1503(of)X
+1596(a)X
+1658(new)X
+1818(hashing)X
+2093(package)X
+2382(for)X
+720 3812(UNIX.)N
+993(The)X
+1150(new)X
+1316(package)X
+1612(provides)X
+1919(a)X
+1986(superset)X
+2280(of)X
+2378(the)X
+720 3900(functionality)N
+1159(of)X
+1255(existing)X
+1537(hashing)X
+1815(packages)X
+2139(and)X
+2284(incor-)X
+720 3988(porates)N
+975(additional)X
+1318(features)X
+1596(such)X
+1766(as)X
+1855(large)X
+2038(key)X
+2176(handling,)X
+720 4076(user)N
+876(de\256ned)X
+1134(hash)X
+1302(functions,)X
+1641(multiple)X
+1928(hash)X
+2096(tables,)X
+2324(vari-)X
+720 4164(able)N
+894(sized)X
+1099(pages,)X
+1342(and)X
+1498(linear)X
+1721(hashing.)X
+2050(In)X
+2156(nearly)X
+2396(all)X
+720 4252(cases,)N
+954(the)X
+1096(new)X
+1274(package)X
+1582(provides)X
+1902(improved)X
+2252(perfor-)X
+720 4340(mance)N
+974(on)X
+1098(the)X
+1240(order)X
+1454(of)X
+1565(50-80%)X
+1863(for)X
+2001(the)X
+2142(workloads)X
+720 4428(shown.)N
+990(Applications)X
+1420(such)X
+1588(as)X
+1676(the)X
+1794(loader,)X
+2035(compiler,)X
+2360(and)X
+720 4516(mail,)N
+921(which)X
+1156(currently)X
+1485(implement)X
+1866(their)X
+2051(own)X
+2227(hashing)X
+720 4604(routines,)N
+1032(should)X
+1279(be)X
+1389(modi\256ed)X
+1706(to)X
+1801(use)X
+1941(the)X
+2072(generic)X
+2342(rou-)X
+720 4692(tines.)N
+892 4806(This)N
+1087(hashing)X
+1389(package)X
+1705(is)X
+1810(one)X
+1978(access)X
+2236(method)X
+720 4894(which)N
+953(is)X
+1043(part)X
+1205(of)X
+1309(a)X
+1382(generic)X
+1656(database)X
+1970(access)X
+2212(package)X
+720 4982(being)N
+955(developed)X
+1342(at)X
+1457(the)X
+1612(University)X
+2007(of)X
+2131(California,)X
+720 5070(Berkeley.)N
+1089(It)X
+1177(will)X
+1340(include)X
+1614(a)X
+1688(btree)X
+1887(access)X
+2131(method)X
+2409(as)X
+720 5158(well)N
+916(as)X
+1041(\256xed)X
+1259(and)X
+1433(variable)X
+1750(length)X
+2007(record)X
+2270(access)X
+720 5246(methods)N
+1024(in)X
+1119(addition)X
+1414(to)X
+1509(the)X
+1640(hashed)X
+1896(support)X
+2168(presented)X
+720 5334(here.)N
+948(All)X
+1099(of)X
+1215(the)X
+1361(access)X
+1615(methods)X
+1934(are)X
+2081(based)X
+2312(on)X
+2440(a)X
+720 5422(key/data)N
+1037(pair)X
+1207(interface)X
+1533(and)X
+1693(appear)X
+1952(identical)X
+2272(to)X
+2378(the)X
+720 5510(application)N
+1121(layer,)X
+1347(allowing)X
+1671(application)X
+2071(implementa-)X
+720 5598(tions)N
+906(to)X
+999(be)X
+1106(largely)X
+1360(independent)X
+1783(of)X
+1881(the)X
+2010(database)X
+2318(type.)X
+720 5686(The)N
+873(package)X
+1165(is)X
+1246(expected)X
+1560(to)X
+1650(be)X
+1754(an)X
+1858(integral)X
+2131(part)X
+2284(of)X
+2378(the)X
+2706 538(4.4BSD)N
+3006(system,)X
+3293(with)X
+3479(various)X
+3759(standard)X
+4075(applications)X
+2706 626(such)N
+2879(as)X
+2972(more\(1\),)X
+3277(sort\(1\))X
+3517(and)X
+3659(vi\(1\))X
+3841(based)X
+4050(on)X
+4156(it.)X
+4266(While)X
+2706 714(the)N
+2833(current)X
+3089(design)X
+3326(does)X
+3501(not)X
+3631(support)X
+3899(multi-user)X
+4256(access)X
+2706 802(or)N
+2804(transactions,)X
+3238(they)X
+3407(could)X
+3616(be)X
+3723(incorporated)X
+4159(relatively)X
+2706 890(easily.)N
+10 f
+2894 938(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2 f
+3365 1030(hash)N
+3638(ndbm)X
+3936(%change)X
+1 f
+10 f
+2894 1034(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2934 1126(CREATE)N
+10 f
+2894 1130(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+3111 1222(user)N
+3390(0.2)X
+3677(0.4)X
+4079(50)X
+3143 1310(sys)N
+3390(0.1)X
+3677(1.0)X
+4079(90)X
+3 f
+2992 1398(elapsed)N
+10 f
+3296 1406(c)N
+1374(c)Y
+1294(c)Y
+1214(c)Y
+3 f
+3390 1398(0)N
+10 f
+3567 1406(c)N
+1374(c)Y
+1294(c)Y
+1214(c)Y
+3 f
+3677 1398(3.2)N
+10 f
+3869 1406(c)N
+1374(c)Y
+1294(c)Y
+1214(c)Y
+3 f
+4039 1398(100)N
+1 f
+10 f
+2894 1394(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2894 1410(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2934 1494(READ)N
+10 f
+2894 1498(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+3111 1590(user)N
+3390(0.1)X
+3677(0.1)X
+4119(0)X
+3143 1678(sys)N
+3390(0.1)X
+3677(0.4)X
+4079(75)X
+3 f
+2992 1766(elapsed)N
+10 f
+3296 1774(c)N
+1742(c)Y
+1662(c)Y
+1582(c)Y
+3 f
+3390 1766(0.0)N
+10 f
+3567 1774(c)N
+1742(c)Y
+1662(c)Y
+1582(c)Y
+3 f
+3677 1766(0.0)N
+10 f
+3869 1774(c)N
+1742(c)Y
+1662(c)Y
+1582(c)Y
+3 f
+4119 1766(0)N
+1 f
+10 f
+2894 1762(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2894 1778(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2934 1862(VERIFY)N
+10 f
+2894 1866(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+3111 1958(user)N
+3390(0.1)X
+3677(0.2)X
+4079(50)X
+3143 2046(sys)N
+3390(0.1)X
+3677(0.3)X
+4079(67)X
+3 f
+2992 2134(elapsed)N
+10 f
+3296 2142(c)N
+2110(c)Y
+2030(c)Y
+1950(c)Y
+3 f
+3390 2134(0.0)N
+10 f
+3567 2142(c)N
+2110(c)Y
+2030(c)Y
+1950(c)Y
+3 f
+3677 2134(0.0)N
+10 f
+3869 2142(c)N
+2110(c)Y
+2030(c)Y
+1950(c)Y
+3 f
+4119 2134(0)N
+1 f
+10 f
+2894 2130(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2894 2146(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2934 2230(SEQUENTIAL)N
+10 f
+2894 2234(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+3111 2326(user)N
+3390(0.1)X
+3677(0.0)X
+4012(-100)X
+3143 2414(sys)N
+3390(0.1)X
+3677(0.1)X
+4119(0)X
+3 f
+2992 2502(elapsed)N
+10 f
+3296 2510(c)N
+2478(c)Y
+2398(c)Y
+2318(c)Y
+3 f
+3390 2502(0.0)N
+10 f
+3567 2510(c)N
+2478(c)Y
+2398(c)Y
+2318(c)Y
+3 f
+3677 2502(0.0)N
+10 f
+3869 2510(c)N
+2478(c)Y
+2398(c)Y
+2318(c)Y
+3 f
+4119 2502(0)N
+1 f
+10 f
+2894 2498(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2894 2514(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2934 2598(SEQUENTIAL)N
+3453(\(with)X
+3642(data)X
+3796(retrieval\))X
+10 f
+2894 2602(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+3111 2694(user)N
+3390(0.1)X
+3677(0.1)X
+4119(0)X
+3143 2782(sys)N
+3390(0.1)X
+3677(0.1)X
+4119(0)X
+3 f
+2992 2870(elapsed)N
+3390(0.0)X
+3677(0.0)X
+4119(0)X
+1 f
+10 f
+2894 2874(i)N
+2913(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2885 2878(c)N
+2862(c)Y
+2782(c)Y
+2702(c)Y
+2622(c)Y
+2542(c)Y
+2462(c)Y
+2382(c)Y
+2302(c)Y
+2222(c)Y
+2142(c)Y
+2062(c)Y
+1982(c)Y
+1902(c)Y
+1822(c)Y
+1742(c)Y
+1662(c)Y
+1582(c)Y
+1502(c)Y
+1422(c)Y
+1342(c)Y
+1262(c)Y
+1182(c)Y
+1102(c)Y
+1022(c)Y
+3296 2878(c)N
+2846(c)Y
+2766(c)Y
+2686(c)Y
+3567 2878(c)N
+2846(c)Y
+2766(c)Y
+2686(c)Y
+3869 2878(c)N
+2846(c)Y
+2766(c)Y
+2686(c)Y
+4264 2878(c)N
+2862(c)Y
+2782(c)Y
+2702(c)Y
+2622(c)Y
+2542(c)Y
+2462(c)Y
+2382(c)Y
+2302(c)Y
+2222(c)Y
+2142(c)Y
+2062(c)Y
+1982(c)Y
+1902(c)Y
+1822(c)Y
+1742(c)Y
+1662(c)Y
+1582(c)Y
+1502(c)Y
+1422(c)Y
+1342(c)Y
+1262(c)Y
+1182(c)Y
+1102(c)Y
+1022(c)Y
+2891 3058(i)N
+2916(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2 f
+3304 3150(hash)N
+3571(hsearch)X
+3939(%change)X
+1 f
+10 f
+2891 3154(i)N
+2916(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2931 3246(CREATE/READ)N
+10 f
+2891 3250(i)N
+2916(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+3050 3342(user)N
+3329(0.3)X
+3648(0.4)X
+4048(25)X
+3082 3430(sys)N
+3329(0.0)X
+3648(0.0)X
+4088(0)X
+3 f
+2931 3518(elapsed)N
+3329(0.0)X
+3648(0.0)X
+4088(0)X
+1 f
+10 f
+2891 3522(i)N
+2916(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2882 3534(c)N
+3462(c)Y
+3382(c)Y
+3302(c)Y
+3222(c)Y
+3142(c)Y
+3235 3518(c)N
+3494(c)Y
+3414(c)Y
+3334(c)Y
+3506 3518(c)N
+3494(c)Y
+3414(c)Y
+3334(c)Y
+3872 3518(c)N
+3494(c)Y
+3414(c)Y
+3334(c)Y
+4267 3534(c)N
+3462(c)Y
+3382(c)Y
+3302(c)Y
+3222(c)Y
+3142(c)Y
+3 f
+2706 3658(Figure)N
+2953(8b:)X
+1 f
+3084(Timing)X
+3339(results)X
+3568(for)X
+3682(the)X
+3800(password)X
+4123(database.)X
+10 f
+2706 3746 -0.0930(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)AN
+3 f
+3396 3988(References)N
+1 f
+2706 4120([ATT79])N
+3058(AT&T,)X
+3358(DBM\(3X\),)X
+2 f
+3773(Unix)X
+3990(Programmer's)X
+2878 4208(Manual,)N
+3194(Seventh)X
+3491(Edition,)X
+3793(Volume)X
+4085(1)X
+1 f
+(,)S
+4192(January,)X
+2878 4296(1979.)N
+2706 4472([ATT85])N
+3027(AT&T,)X
+3296(HSEARCH\(BA_LIB\),)X
+2 f
+4053(Unix)X
+4239(System)X
+2878 4560(User's)N
+3112(Manual,)X
+3401(System)X
+3644(V.3)X
+1 f
+3753(,)X
+3793(pp.)X
+3913(506-508,)X
+4220(1985.)X
+2706 4736([BRE73])N
+3025(Brent,)X
+3253(Richard)X
+3537(P.,)X
+3651(``Reducing)X
+4041(the)X
+4168(Retrieval)X
+2878 4824(Time)N
+3071(of)X
+3162(Scatter)X
+3409(Storage)X
+3678(Techniques'',)X
+2 f
+4146(Commun-)X
+2878 4912(ications)N
+3175(of)X
+3281(the)X
+3422(ACM)X
+1 f
+3591(,)X
+3654(Volume)X
+3955(16,)X
+4098(No.)X
+4259(2,)X
+4362(pp.)X
+2878 5000(105-109,)N
+3185(February,)X
+3515(1973.)X
+2706 5176([BSD86])N
+3055(NDBM\(3\),)X
+2 f
+3469(4.3BSD)X
+3775(Unix)X
+3990(Programmer's)X
+2878 5264(Manual)N
+3155(Reference)X
+3505(Guide)X
+1 f
+3701(,)X
+3749(University)X
+4114(of)X
+4208(Califor-)X
+2878 5352(nia,)N
+3016(Berkeley,)X
+3346(1986.)X
+2706 5528([ENB88])N
+3025(Enbody,)X
+3319(R.)X
+3417(J.,)X
+3533(Du,)X
+3676(H.)X
+3779(C.,)X
+3897(``Dynamic)X
+4270(Hash-)X
+2878 5616(ing)N
+3034(Schemes'',)X
+2 f
+3427(ACM)X
+3630(Computing)X
+4019(Surveys)X
+1 f
+4269(,)X
+4322(Vol.)X
+2878 5704(20,)N
+2998(No.)X
+3136(2,)X
+3216(pp.)X
+3336(85-113,)X
+3603(June)X
+3770(1988.)X
+3 f
+720 5960(USENIX)N
+9 f
+1042(-)X
+3 f
+1106(Winter)X
+1371('91)X
+9 f
+1498(-)X
+3 f
+1562(Dallas,)X
+1815(TX)X
+4384(11)X
+
+12 p
+%%Page: 12 12
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+432 258(A)N
+510(New)X
+682(Hashing)X
+985(Package)X
+1290(for)X
+1413(UNIX)X
+3663(Seltzer)X
+3920(&)X
+4007(Yigit)X
+1 f
+432 538([FAG79])N
+776(Ronald)X
+1057(Fagin,)X
+1308(Jurg)X
+1495(Nievergelt,)X
+1903(Nicholas)X
+604 626(Pippenger,)N
+1003(H.)X
+1135(Raymond)X
+1500(Strong,)X
+1787(``Extendible)X
+604 714(Hashing)N
+901(--)X
+985(A)X
+1073(Fast)X
+1236(Access)X
+1493(Method)X
+1771(for)X
+1894(Dynamic)X
+604 802(Files'',)N
+2 f
+855(ACM)X
+1046(Transactions)X
+1485(on)X
+1586(Database)X
+1914(Systems)X
+1 f
+2168(,)X
+604 890(Volume)N
+882(4,)X
+962(No.)X
+1100(3.,)X
+1200(September)X
+1563(1979,)X
+1763(pp)X
+1863(315-34)X
+432 1066([KNU68],)N
+802(Knuth,)X
+1064(D.E.,)X
+2 f
+1273(The)X
+1434(Art)X
+1577(of)X
+1680(Computer)X
+2041(Pro-)X
+604 1154(gramming)N
+971(Vol.)X
+1140(3:)X
+1245(Sorting)X
+1518(and)X
+1676(Searching)X
+1 f
+2001(,)X
+2058(sec-)X
+604 1242(tions)N
+779(6.3-6.4,)X
+1046(pp)X
+1146(481-550.)X
+432 1418([LAR78])N
+747(Larson,)X
+1011(Per-Ake,)X
+1319(``Dynamic)X
+1687(Hashing'',)X
+2 f
+2048(BIT)X
+1 f
+(,)S
+604 1506(Vol.)N
+764(18,)X
+884(1978,)X
+1084(pp.)X
+1204(184-201.)X
+432 1682([LAR88])N
+752(Larson,)X
+1021(Per-Ake,)X
+1335(``Dynamic)X
+1709(Hash)X
+1900(Tables'',)X
+2 f
+604 1770(Communications)N
+1183(of)X
+1281(the)X
+1415(ACM)X
+1 f
+1584(,)X
+1640(Volume)X
+1934(31,)X
+2070(No.)X
+604 1858(4.,)N
+704(April)X
+893(1988,)X
+1093(pp)X
+1193(446-457.)X
+432 2034([LIT80])N
+731(Witold,)X
+1013(Litwin,)X
+1286(``Linear)X
+1590(Hashing:)X
+1939(A)X
+2036(New)X
+604 2122(Tool)N
+786(for)X
+911(File)X
+1065(and)X
+1211(Table)X
+1424(Addressing'',)X
+2 f
+1893(Proceed-)X
+604 2210(ings)N
+761(of)X
+847(the)X
+969(6th)X
+1095(International)X
+1540(Conference)X
+1933(on)X
+2036(Very)X
+604 2298(Large)N
+815(Databases)X
+1 f
+1153(,)X
+1193(1980.)X
+432 2474([NEL90])N
+743(Nelson,)X
+1011(Philip)X
+1222(A.,)X
+2 f
+1341(Gdbm)X
+1558(1.4)X
+1679(source)X
+1913(distribu-)X
+604 2562(tion)N
+748(and)X
+888(README)X
+1 f
+1209(,)X
+1249(August)X
+1500(1990.)X
+432 2738([THOM90])N
+840(Ken)X
+1011(Thompson,)X
+1410(private)X
+1670(communication,)X
+604 2826(Nov.)N
+782(1990.)X
+432 3002([TOR87])N
+790(Torek,)X
+1066(C.,)X
+1222(``Re:)X
+1470(dbm.a)X
+1751(and)X
+1950(ndbm.a)X
+604 3090(archives'',)N
+2 f
+966(USENET)X
+1279(newsgroup)X
+1650(comp.unix)X
+1 f
+2002(1987.)X
+432 3266([TOR88])N
+760(Torek,)X
+1006(C.,)X
+1133(``Re:)X
+1351(questions)X
+1686(regarding)X
+2027(data-)X
+604 3354(bases)N
+826(created)X
+1106(with)X
+1295(dbm)X
+1484(and)X
+1647(ndbm)X
+1876(routines'')X
+2 f
+604 3442(USENET)N
+937(newsgroup)X
+1328(comp.unix.questions)X
+1 f
+1982(,)X
+2041(June)X
+604 3530(1988.)N
+432 3706([WAL84])N
+773(Wales,)X
+1018(R.,)X
+1135(``Discussion)X
+1564(of)X
+1655("dbm")X
+1887(data)X
+2045(base)X
+604 3794(system'',)N
+2 f
+973(USENET)X
+1339(newsgroup)X
+1762(unix.wizards)X
+1 f
+2168(,)X
+604 3882(January,)N
+894(1984.)X
+432 4058([YIG89])N
+751(Ozan)X
+963(S.)X
+1069(Yigit,)X
+1294(``How)X
+1545(to)X
+1648(Roll)X
+1826(Your)X
+2032(Own)X
+604 4146(Dbm/Ndbm'',)N
+2 f
+1087(unpublished)X
+1504(manuscript)X
+1 f
+(,)S
+1910(Toronto,)X
+604 4234(July,)N
+777(1989)X
+3 f
+432 5960(12)N
+2970(USENIX)X
+9 f
+3292(-)X
+3 f
+3356(Winter)X
+3621('91)X
+9 f
+3748(-)X
+3 f
+3812(Dallas,)X
+4065(TX)X
+
+13 p
+%%Page: 13 13
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+720 258(Seltzer)N
+977(&)X
+1064(Yigit)X
+3278(A)X
+3356(New)X
+3528(Hashing)X
+3831(Package)X
+4136(for)X
+4259(UNIX)X
+1 f
+720 538(Margo)N
+960(I.)X
+1033(Seltzer)X
+1282(is)X
+1361(a)X
+1423(Ph.D.)X
+1631(student)X
+1887(in)X
+1974(the)X
+2097(Department)X
+720 626(of)N
+823(Electrical)X
+1167(Engineering)X
+1595(and)X
+1747(Computer)X
+2102(Sciences)X
+2418(at)X
+720 714(the)N
+850(University)X
+1220(of)X
+1318(California,)X
+1694(Berkeley.)X
+2055(Her)X
+2207(research)X
+720 802(interests)N
+1017(include)X
+1283(\256le)X
+1415(systems,)X
+1718(databases,)X
+2076(and)X
+2221(transac-)X
+720 890(tion)N
+896(processing)X
+1291(systems.)X
+1636(She)X
+1807(spent)X
+2027(several)X
+2306(years)X
+720 978(working)N
+1026(at)X
+1123(startup)X
+1380(companies)X
+1762(designing)X
+2112(and)X
+2267(imple-)X
+720 1066(menting)N
+1048(\256le)X
+1216(systems)X
+1535(and)X
+1716(transaction)X
+2133(processing)X
+720 1154(software)N
+1026(and)X
+1170(designing)X
+1509(microprocessors.)X
+2103(Ms.)X
+2253(Seltzer)X
+720 1242(received)N
+1057(her)X
+1223(AB)X
+1397(in)X
+1522(Applied)X
+1843(Mathematics)X
+2320(from)X
+720 1330 0.1953(Harvard/Radcliffe)AN
+1325(College)X
+1594(in)X
+1676(1983.)X
+720 1444(In)N
+810(her)X
+936(spare)X
+1129(time,)X
+1313(Margo)X
+1549(can)X
+1683(usually)X
+1936(be)X
+2034(found)X
+2243(prepar-)X
+720 1532(ing)N
+868(massive)X
+1171(quantities)X
+1527(of)X
+1639(food)X
+1831(for)X
+1970(hungry)X
+2242(hoards,)X
+720 1620(studying)N
+1022(Japanese,)X
+1355(or)X
+1449(playing)X
+1716(soccer)X
+1948(with)X
+2116(an)X
+2218(exciting)X
+720 1708(Bay)N
+912(Area)X
+1132(Women's)X
+1507(Soccer)X
+1788(team,)X
+2026(the)X
+2186(Berkeley)X
+720 1796(Bruisers.)N
+720 1910(Ozan)N
+915(\()X
+3 f
+942(Oz)X
+1 f
+1040(\))X
+1092(Yigit)X
+1281(is)X
+1358(currently)X
+1672(a)X
+1732(software)X
+2033(engineer)X
+2334(with)X
+720 1998(the)N
+886(Communications)X
+1499(Research)X
+1861(and)X
+2044(Development)X
+720 2086(group,)N
+948(Computing)X
+1328(Services,)X
+1641(York)X
+1826(University.)X
+2224(His)X
+2355(for-)X
+720 2174(mative)N
+967(years)X
+1166(were)X
+1352(also)X
+1510(spent)X
+1708(at)X
+1795(York,)X
+2009(where)X
+2234(he)X
+2338(held)X
+720 2262(system)N
+985(programmer)X
+1425(and)X
+1583(administrator)X
+2052(positions)X
+2382(for)X
+720 2350(various)N
+995(mixtures)X
+1314(of)X
+1420(of)X
+1526(UNIX)X
+1765(systems)X
+2056(starting)X
+2334(with)X
+720 2438(Berkeley)N
+1031(4.1)X
+1151(in)X
+1233(1982,)X
+1433(while)X
+1631(at)X
+1709(the)X
+1827(same)X
+2012(time)X
+2174(obtaining)X
+720 2526(a)N
+776(degree)X
+1011(in)X
+1093(Computer)X
+1433(Science.)X
+720 2640(In)N
+813(his)X
+931(copious)X
+1205(free)X
+1356(time,)X
+1543(Oz)X
+1662(enjoys)X
+1896(working)X
+2188(on)X
+2293(what-)X
+720 2728(ever)N
+890(software)X
+1197(looks)X
+1400(interesting,)X
+1788(which)X
+2014(often)X
+2209(includes)X
+720 2816(language)N
+1044(interpreters,)X
+1464(preprocessors,)X
+1960(and)X
+2110(lately,)X
+2342(pro-)X
+720 2904(gram)N
+905(generators)X
+1260(and)X
+1396(expert)X
+1617(systems.)X
+720 3018(Oz)N
+836(has)X
+964(authored)X
+1266(several)X
+1515(public-domain)X
+2003(software)X
+2301(tools,)X
+720 3106(including)N
+1069(an)X
+1191(nroff-like)X
+1545(text)X
+1711(formatter)X
+2 f
+2056(proff)X
+1 f
+2257(that)X
+2423(is)X
+720 3194(apparently)N
+1083(still)X
+1226(used)X
+1397(in)X
+1483(some)X
+1676(basement)X
+2002(PCs.)X
+2173(His)X
+2307(latest)X
+720 3282(obsessions)N
+1143(include)X
+1460(the)X
+1639(incredible)X
+2040(programming)X
+720 3370(language)N
+1030(Scheme,)X
+1324(and)X
+1460(Chinese)X
+1738(Brush)X
+1949(painting.)X
+3 f
+720 5960(USENIX)N
+9 f
+1042(-)X
+3 f
+1106(Winter)X
+1371('91)X
+9 f
+1498(-)X
+3 f
+1562(Dallas,)X
+1815(TX)X
+4384(13)X
+
+14 p
+%%Page: 14 14
+0(Courier)xf 0 f
+10 s 10 xH 0 xS 0 f
+3 f
+432 5960(14)N
+2970(USENIX)X
+9 f
+3292(-)X
+3 f
+3356(Winter)X
+3621('91)X
+9 f
+3748(-)X
+3 f
+3812(Dallas,)X
+4065(TX)X
+
+14 p
+%%Trailer
+xt
+
+xs
diff --git a/lib/libc/db/docs/libtp.usenix.ps b/lib/libc/db/docs/libtp.usenix.ps
new file mode 100644
index 0000000..b7e441a
--- /dev/null
+++ b/lib/libc/db/docs/libtp.usenix.ps
@@ -0,0 +1,12340 @@
+%!PS-Adobe-1.0
+%%Creator: utopia:margo (& Seltzer,608-13E,8072,)
+%%Title: stdin (ditroff)
+%%CreationDate: Thu Dec 12 15:32:11 1991
+%%EndComments
+% @(#)psdit.pro 1.3 4/15/88
+% lib/psdit.pro -- prolog for psdit (ditroff) files
+% Copyright (c) 1984, 1985 Adobe Systems Incorporated. All Rights Reserved.
+% last edit: shore Sat Nov 23 20:28:03 1985
+% RCSID: $FreeBSD$
+
+% Changed by Edward Wang (edward@ucbarpa.berkeley.edu) to handle graphics,
+% 17 Feb, 87.
+
+/$DITroff 140 dict def $DITroff begin
+/fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def
+/xi{0 72 11 mul translate 72 resolution div dup neg scale 0 0 moveto
+ /fontnum 1 def /fontsize 10 def /fontheight 10 def /fontslant 0 def F
+ /pagesave save def}def
+/PB{save /psv exch def currentpoint translate
+ resolution 72 div dup neg scale 0 0 moveto}def
+/PE{psv restore}def
+/arctoobig 90 def /arctoosmall .05 def
+/m1 matrix def /m2 matrix def /m3 matrix def /oldmat matrix def
+/tan{dup sin exch cos div}def
+/point{resolution 72 div mul}def
+/dround {transform round exch round exch itransform}def
+/xT{/devname exch def}def
+/xr{/mh exch def /my exch def /resolution exch def}def
+/xp{}def
+/xs{docsave restore end}def
+/xt{}def
+/xf{/fontname exch def /slotno exch def fontnames slotno get fontname eq not
+ {fonts slotno fontname findfont put fontnames slotno fontname put}if}def
+/xH{/fontheight exch def F}def
+/xS{/fontslant exch def F}def
+/s{/fontsize exch def /fontheight fontsize def F}def
+/f{/fontnum exch def F}def
+/F{fontheight 0 le{/fontheight fontsize def}if
+ fonts fontnum get fontsize point 0 0 fontheight point neg 0 0 m1 astore
+ fontslant 0 ne{1 0 fontslant tan 1 0 0 m2 astore m3 concatmatrix}if
+ makefont setfont .04 fontsize point mul 0 dround pop setlinewidth}def
+/X{exch currentpoint exch pop moveto show}def
+/N{3 1 roll moveto show}def
+/Y{exch currentpoint pop exch moveto show}def
+/S{show}def
+/ditpush{}def/ditpop{}def
+/AX{3 -1 roll currentpoint exch pop moveto 0 exch ashow}def
+/AN{4 2 roll moveto 0 exch ashow}def
+/AY{3 -1 roll currentpoint pop exch moveto 0 exch ashow}def
+/AS{0 exch ashow}def
+/MX{currentpoint exch pop moveto}def
+/MY{currentpoint pop exch moveto}def
+/MXY{moveto}def
+/cb{pop}def % action on unknown char -- nothing for now
+/n{}def/w{}def
+/p{pop showpage pagesave restore /pagesave save def}def
+/Dt{/Dlinewidth exch def}def 1 Dt
+/Ds{/Ddash exch def}def -1 Ds
+/Di{/Dstipple exch def}def 1 Di
+/Dsetlinewidth{2 Dlinewidth mul setlinewidth}def
+/Dsetdash{Ddash 4 eq{[8 12]}{Ddash 16 eq{[32 36]}
+ {Ddash 20 eq{[32 12 8 12]}{[]}ifelse}ifelse}ifelse 0 setdash}def
+/Dstroke{gsave Dsetlinewidth Dsetdash 1 setlinecap stroke grestore
+ currentpoint newpath moveto}def
+/Dl{rlineto Dstroke}def
+/arcellipse{/diamv exch def /diamh exch def oldmat currentmatrix pop
+ currentpoint translate 1 diamv diamh div scale /rad diamh 2 div def
+ currentpoint exch rad add exch rad -180 180 arc oldmat setmatrix}def
+/Dc{dup arcellipse Dstroke}def
+/De{arcellipse Dstroke}def
+/Da{/endv exch def /endh exch def /centerv exch def /centerh exch def
+ /cradius centerv centerv mul centerh centerh mul add sqrt def
+ /eradius endv endv mul endh endh mul add sqrt def
+ /endang endv endh atan def
+ /startang centerv neg centerh neg atan def
+ /sweep startang endang sub dup 0 lt{360 add}if def
+ sweep arctoobig gt
+ {/midang startang sweep 2 div sub def /midrad cradius eradius add 2 div def
+ /midh midang cos midrad mul def /midv midang sin midrad mul def
+ midh neg midv neg endh endv centerh centerv midh midv Da
+ Da}
+ {sweep arctoosmall ge
+ {/controldelt 1 sweep 2 div cos sub 3 sweep 2 div sin mul div 4 mul def
+ centerv neg controldelt mul centerh controldelt mul
+ endv neg controldelt mul centerh add endh add
+ endh controldelt mul centerv add endv add
+ centerh endh add centerv endv add rcurveto Dstroke}
+ {centerh endh add centerv endv add rlineto Dstroke}
+ ifelse}
+ ifelse}def
+/Dpatterns[
+[%cf[widthbits]
+[8<0000000000000010>]
+[8<0411040040114000>]
+[8<0204081020408001>]
+[8<0000103810000000>]
+[8<6699996666999966>]
+[8<0000800100001008>]
+[8<81c36666c3810000>]
+[8<0f0e0c0800000000>]
+[8<0000000000000010>]
+[8<0411040040114000>]
+[8<0204081020408001>]
+[8<0000001038100000>]
+[8<6699996666999966>]
+[8<0000800100001008>]
+[8<81c36666c3810000>]
+[8<0f0e0c0800000000>]
+[8<0042660000246600>]
+[8<0000990000990000>]
+[8<0804020180402010>]
+[8<2418814242811824>]
+[8<6699996666999966>]
+[8<8000000008000000>]
+[8<00001c3e363e1c00>]
+[8<0000000000000000>]
+[32<00000040000000c00000004000000040000000e0000000000000000000000000>]
+[32<00000000000060000000900000002000000040000000f0000000000000000000>]
+[32<000000000000000000e0000000100000006000000010000000e0000000000000>]
+[32<00000000000000002000000060000000a0000000f00000002000000000000000>]
+[32<0000000e0000000000000000000000000000000f000000080000000e00000001>]
+[32<0000090000000600000000000000000000000000000007000000080000000e00>]
+[32<00010000000200000004000000040000000000000000000000000000000f0000>]
+[32<0900000006000000090000000600000000000000000000000000000006000000>]]
+[%ug
+[8<0000020000000000>]
+[8<0000020000002000>]
+[8<0004020000002000>]
+[8<0004020000402000>]
+[8<0004060000402000>]
+[8<0004060000406000>]
+[8<0006060000406000>]
+[8<0006060000606000>]
+[8<00060e0000606000>]
+[8<00060e000060e000>]
+[8<00070e000060e000>]
+[8<00070e000070e000>]
+[8<00070e020070e000>]
+[8<00070e020070e020>]
+[8<04070e020070e020>]
+[8<04070e024070e020>]
+[8<04070e064070e020>]
+[8<04070e064070e060>]
+[8<06070e064070e060>]
+[8<06070e066070e060>]
+[8<06070f066070e060>]
+[8<06070f066070f060>]
+[8<060f0f066070f060>]
+[8<060f0f0660f0f060>]
+[8<060f0f0760f0f060>]
+[8<060f0f0760f0f070>]
+[8<0e0f0f0760f0f070>]
+[8<0e0f0f07e0f0f070>]
+[8<0e0f0f0fe0f0f070>]
+[8<0e0f0f0fe0f0f0f0>]
+[8<0f0f0f0fe0f0f0f0>]
+[8<0f0f0f0ff0f0f0f0>]
+[8<1f0f0f0ff0f0f0f0>]
+[8<1f0f0f0ff1f0f0f0>]
+[8<1f0f0f8ff1f0f0f0>]
+[8<1f0f0f8ff1f0f0f8>]
+[8<9f0f0f8ff1f0f0f8>]
+[8<9f0f0f8ff9f0f0f8>]
+[8<9f0f0f9ff9f0f0f8>]
+[8<9f0f0f9ff9f0f0f9>]
+[8<9f8f0f9ff9f0f0f9>]
+[8<9f8f0f9ff9f8f0f9>]
+[8<9f8f1f9ff9f8f0f9>]
+[8<9f8f1f9ff9f8f1f9>]
+[8<bf8f1f9ff9f8f1f9>]
+[8<bf8f1f9ffbf8f1f9>]
+[8<bf8f1fdffbf8f1f9>]
+[8<bf8f1fdffbf8f1fd>]
+[8<ff8f1fdffbf8f1fd>]
+[8<ff8f1fdffff8f1fd>]
+[8<ff8f1ffffff8f1fd>]
+[8<ff8f1ffffff8f1ff>]
+[8<ff9f1ffffff8f1ff>]
+[8<ff9f1ffffff9f1ff>]
+[8<ff9f9ffffff9f1ff>]
+[8<ff9f9ffffff9f9ff>]
+[8<ffbf9ffffff9f9ff>]
+[8<ffbf9ffffffbf9ff>]
+[8<ffbfdffffffbf9ff>]
+[8<ffbfdffffffbfdff>]
+[8<ffffdffffffbfdff>]
+[8<ffffdffffffffdff>]
+[8<fffffffffffffdff>]
+[8<ffffffffffffffff>]]
+[%mg
+[8<8000000000000000>]
+[8<0822080080228000>]
+[8<0204081020408001>]
+[8<40e0400000000000>]
+[8<66999966>]
+[8<8001000010080000>]
+[8<81c36666c3810000>]
+[8<f0e0c08000000000>]
+[16<07c00f801f003e007c00f800f001e003c007800f001f003e007c00f801f003e0>]
+[16<1f000f8007c003e001f000f8007c003e001f800fc007e003f001f8007c003e00>]
+[8<c3c300000000c3c3>]
+[16<0040008001000200040008001000200040008000000100020004000800100020>]
+[16<0040002000100008000400020001800040002000100008000400020001000080>]
+[16<1fc03fe07df0f8f8f07de03fc01f800fc01fe03ff07df8f87df03fe01fc00f80>]
+[8<80>]
+[8<8040201000000000>]
+[8<84cc000048cc0000>]
+[8<9900009900000000>]
+[8<08040201804020100800020180002010>]
+[8<2418814242811824>]
+[8<66999966>]
+[8<8000000008000000>]
+[8<70f8d8f870000000>]
+[8<0814224180402010>]
+[8<aa00440a11a04400>]
+[8<018245aa45820100>]
+[8<221c224180808041>]
+[8<88000000>]
+[8<0855800080550800>]
+[8<2844004482440044>]
+[8<0810204080412214>]
+[8<00>]]]def
+/Dfill{
+ transform /maxy exch def /maxx exch def
+ transform /miny exch def /minx exch def
+ minx maxx gt{/minx maxx /maxx minx def def}if
+ miny maxy gt{/miny maxy /maxy miny def def}if
+ Dpatterns Dstipple 1 sub get exch 1 sub get
+ aload pop /stip exch def /stipw exch def /stiph 128 def
+ /imatrix[stipw 0 0 stiph 0 0]def
+ /tmatrix[stipw 0 0 stiph 0 0]def
+ /minx minx cvi stiph idiv stiph mul def
+ /miny miny cvi stipw idiv stipw mul def
+ gsave eoclip 0 setgray
+ miny stiph maxy{
+ tmatrix exch 5 exch put
+ minx stipw maxx{
+ tmatrix exch 4 exch put tmatrix setmatrix
+ stipw stiph true imatrix {stip} imagemask
+ }for
+ }for
+ grestore
+}def
+/Dp{Dfill Dstroke}def
+/DP{Dfill currentpoint newpath moveto}def
+end
+
+/ditstart{$DITroff begin
+ /nfonts 60 def % NFONTS makedev/ditroff dependent!
+ /fonts[nfonts{0}repeat]def
+ /fontnames[nfonts{()}repeat]def
+/docsave save def
+}def
+
+% character outcalls
+/oc{
+ /pswid exch def /cc exch def /name exch def
+ /ditwid pswid fontsize mul resolution mul 72000 div def
+ /ditsiz fontsize resolution mul 72 div def
+ ocprocs name known{ocprocs name get exec}{name cb}ifelse
+}def
+/fractm [.65 0 0 .6 0 0] def
+/fraction{
+ /fden exch def /fnum exch def gsave /cf currentfont def
+ cf fractm makefont setfont 0 .3 dm 2 copy neg rmoveto
+ fnum show rmoveto currentfont cf setfont(\244)show setfont fden show
+ grestore ditwid 0 rmoveto
+}def
+/oce{grestore ditwid 0 rmoveto}def
+/dm{ditsiz mul}def
+/ocprocs 50 dict def ocprocs begin
+(14){(1)(4)fraction}def
+(12){(1)(2)fraction}def
+(34){(3)(4)fraction}def
+(13){(1)(3)fraction}def
+(23){(2)(3)fraction}def
+(18){(1)(8)fraction}def
+(38){(3)(8)fraction}def
+(58){(5)(8)fraction}def
+(78){(7)(8)fraction}def
+(sr){gsave 0 .06 dm rmoveto(\326)show oce}def
+(is){gsave 0 .15 dm rmoveto(\362)show oce}def
+(->){gsave 0 .02 dm rmoveto(\256)show oce}def
+(<-){gsave 0 .02 dm rmoveto(\254)show oce}def
+(==){gsave 0 .05 dm rmoveto(\272)show oce}def
+(uc){gsave currentpoint 400 .009 dm mul add translate
+ 8 -8 scale ucseal oce}def
+end
+
+% an attempt at a PostScript FONT to implement ditroff special chars
+% this will enable us to
+% cache the little buggers
+% generate faster, more compact PS out of psdit
+% confuse everyone (including myself)!
+50 dict dup begin
+/FontType 3 def
+/FontName /DIThacks def
+/FontMatrix [.001 0 0 .001 0 0] def
+/FontBBox [-260 -260 900 900] def% a lie but ...
+/Encoding 256 array def
+0 1 255{Encoding exch /.notdef put}for
+Encoding
+ dup 8#040/space put %space
+ dup 8#110/rc put %right ceil
+ dup 8#111/lt put %left top curl
+ dup 8#112/bv put %bold vert
+ dup 8#113/lk put %left mid curl
+ dup 8#114/lb put %left bot curl
+ dup 8#115/rt put %right top curl
+ dup 8#116/rk put %right mid curl
+ dup 8#117/rb put %right bot curl
+ dup 8#120/rf put %right floor
+ dup 8#121/lf put %left floor
+ dup 8#122/lc put %left ceil
+ dup 8#140/sq put %square
+ dup 8#141/bx put %box
+ dup 8#142/ci put %circle
+ dup 8#143/br put %box rule
+ dup 8#144/rn put %root extender
+ dup 8#145/vr put %vertical rule
+ dup 8#146/ob put %outline bullet
+ dup 8#147/bu put %bullet
+ dup 8#150/ru put %rule
+ dup 8#151/ul put %underline
+ pop
+/DITfd 100 dict def
+/BuildChar{0 begin
+ /cc exch def /fd exch def
+ /charname fd /Encoding get cc get def
+ /charwid fd /Metrics get charname get def
+ /charproc fd /CharProcs get charname get def
+ charwid 0 fd /FontBBox get aload pop setcachedevice
+ 2 setlinejoin 40 setlinewidth
+ newpath 0 0 moveto gsave charproc grestore
+ end}def
+/BuildChar load 0 DITfd put
+/CharProcs 50 dict def
+CharProcs begin
+/space{}def
+/.notdef{}def
+/ru{500 0 rls}def
+/rn{0 840 moveto 500 0 rls}def
+/vr{0 800 moveto 0 -770 rls}def
+/bv{0 800 moveto 0 -1000 rls}def
+/br{0 840 moveto 0 -1000 rls}def
+/ul{0 -140 moveto 500 0 rls}def
+/ob{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath stroke}def
+/bu{200 250 rmoveto currentpoint newpath 200 0 360 arc closepath fill}def
+/sq{80 0 rmoveto currentpoint dround newpath moveto
+ 640 0 rlineto 0 640 rlineto -640 0 rlineto closepath stroke}def
+/bx{80 0 rmoveto currentpoint dround newpath moveto
+ 640 0 rlineto 0 640 rlineto -640 0 rlineto closepath fill}def
+/ci{500 360 rmoveto currentpoint newpath 333 0 360 arc
+ 50 setlinewidth stroke}def
+
+/lt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 add exch s4 a4p stroke}def
+/lb{0 800 moveto 0 -550 rlineto currx -200 2cx s4 add exch s4 a4p stroke}def
+/rt{0 -200 moveto 0 550 rlineto currx 800 2cx s4 sub exch s4 a4p stroke}def
+/rb{0 800 moveto 0 -500 rlineto currx -200 2cx s4 sub exch s4 a4p stroke}def
+/lk{0 800 moveto 0 300 -300 300 s4 arcto pop pop 1000 sub
+ 0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
+/rk{0 800 moveto 0 300 s2 300 s4 arcto pop pop 1000 sub
+ 0 300 4 2 roll s4 a4p 0 -200 lineto stroke}def
+/lf{0 800 moveto 0 -1000 rlineto s4 0 rls}def
+/rf{0 800 moveto 0 -1000 rlineto s4 neg 0 rls}def
+/lc{0 -200 moveto 0 1000 rlineto s4 0 rls}def
+/rc{0 -200 moveto 0 1000 rlineto s4 neg 0 rls}def
+end
+
+/Metrics 50 dict def Metrics begin
+/.notdef 0 def
+/space 500 def
+/ru 500 def
+/br 0 def
+/lt 416 def
+/lb 416 def
+/rt 416 def
+/rb 416 def
+/lk 416 def
+/rk 416 def
+/rc 416 def
+/lc 416 def
+/rf 416 def
+/lf 416 def
+/bv 416 def
+/ob 350 def
+/bu 350 def
+/ci 750 def
+/bx 750 def
+/sq 750 def
+/rn 500 def
+/ul 500 def
+/vr 0 def
+end
+
+DITfd begin
+/s2 500 def /s4 250 def /s3 333 def
+/a4p{arcto pop pop pop pop}def
+/2cx{2 copy exch}def
+/rls{rlineto stroke}def
+/currx{currentpoint pop}def
+/dround{transform round exch round exch itransform} def
+end
+end
+/DIThacks exch definefont pop
+ditstart
+(psc)xT
+576 1 1 xr
+1(Times-Roman)xf 1 f
+2(Times-Italic)xf 2 f
+3(Times-Bold)xf 3 f
+4(Times-BoldItalic)xf 4 f
+5(Helvetica)xf 5 f
+6(Helvetica-Bold)xf 6 f
+7(Courier)xf 7 f
+8(Courier-Bold)xf 8 f
+9(Symbol)xf 9 f
+10(DIThacks)xf 10 f
+10 s
+1 f
+xi
+%%EndProlog
+
+%%Page: 1 1
+10 s 10 xH 0 xS 1 f
+3 f
+14 s
+1205 1206(LIBTP:)N
+1633(Portable,)X
+2100(M)X
+2206(odular)X
+2551(Transactions)X
+3202(for)X
+3374(UNIX)X
+1 f
+11 s
+3661 1162(1)N
+2 f
+12 s
+2182 1398(Margo)N
+2467(Seltzer)X
+2171 1494(Michael)N
+2511(Olson)X
+1800 1590(University)N
+2225(of)X
+2324(California,)X
+2773(Berkeley)X
+3 f
+2277 1878(Abstract)N
+1 f
+10 s
+755 2001(Transactions)N
+1198(provide)X
+1475(a)X
+1543(useful)X
+1771(programming)X
+2239(paradigm)X
+2574(for)X
+2700(maintaining)X
+3114(logical)X
+3364(consistency,)X
+3790(arbitrating)X
+4156(con-)X
+555 2091(current)N
+808(access,)X
+1059(and)X
+1200(managing)X
+1540(recovery.)X
+1886(In)X
+1977(traditional)X
+2330(UNIX)X
+2555(systems,)X
+2852(the)X
+2974(only)X
+3140(easy)X
+3307(way)X
+3465(of)X
+3556(using)X
+3753(transactions)X
+4160(is)X
+4237(to)X
+555 2181(purchase)N
+876(a)X
+947(database)X
+1258(system.)X
+1554(Such)X
+1748(systems)X
+2035(are)X
+2168(often)X
+2367(slow,)X
+2572(costly,)X
+2817(and)X
+2967(may)X
+3139(not)X
+3275(provide)X
+3554(the)X
+3686(exact)X
+3890(functionality)X
+555 2271(desired.)N
+848(This)X
+1011(paper)X
+1210(presents)X
+1493(the)X
+1611(design,)X
+1860(implementation,)X
+2402(and)X
+2538(performance)X
+2965(of)X
+3052(LIBTP,)X
+3314(a)X
+3370(simple,)X
+3623(non-proprietary)X
+4147(tran-)X
+555 2361(saction)N
+809(library)X
+1050(using)X
+1249(the)X
+1373(4.4BSD)X
+1654(database)X
+1957(access)X
+2189(routines)X
+2473(\()X
+3 f
+2500(db)X
+1 f
+2588(\(3\)\).)X
+2775(On)X
+2899(a)X
+2961(conventional)X
+3401(transaction)X
+3779(processing)X
+4148(style)X
+555 2451(benchmark,)N
+959(its)X
+1061(performance)X
+1495(is)X
+1575(approximately)X
+2065(85%)X
+2239(that)X
+2386(of)X
+2480(the)X
+2604(database)X
+2907(access)X
+3139(routines)X
+3423(without)X
+3693(transaction)X
+4071(protec-)X
+555 2541(tion,)N
+725(200%)X
+938(that)X
+1084(of)X
+1177(using)X
+3 f
+1376(fsync)X
+1 f
+1554(\(2\))X
+1674(to)X
+1761(commit)X
+2030(modi\256cations)X
+2490(to)X
+2577(disk,)X
+2755(and)X
+2896(125%)X
+3108(that)X
+3253(of)X
+3345(a)X
+3406(commercial)X
+3810(relational)X
+4138(data-)X
+555 2631(base)N
+718(system.)X
+3 f
+555 2817(1.)N
+655(Introduction)X
+1 f
+755 2940(Transactions)N
+1186(are)X
+1306(used)X
+1474(in)X
+1557(database)X
+1855(systems)X
+2129(to)X
+2212(enable)X
+2443(concurrent)X
+2807(users)X
+2992(to)X
+3074(apply)X
+3272(multi-operation)X
+3790(updates)X
+4055(without)X
+555 3030(violating)N
+863(the)X
+985(integrity)X
+1280(of)X
+1371(the)X
+1493(database.)X
+1814(They)X
+2003(provide)X
+2271(the)X
+2392(properties)X
+2736(of)X
+2826(atomicity,)X
+3171(consistency,)X
+3588(isolation,)X
+3906(and)X
+4045(durabil-)X
+555 3120(ity.)N
+701(By)X
+816(atomicity,)X
+1160(we)X
+1276(mean)X
+1472(that)X
+1614(the)X
+1734(set)X
+1845(of)X
+1934(updates)X
+2200(comprising)X
+2581(a)X
+2638(transaction)X
+3011(must)X
+3187(be)X
+3284(applied)X
+3541(as)X
+3629(a)X
+3686(single)X
+3898(unit;)X
+4085(that)X
+4226(is,)X
+555 3210(they)N
+714(must)X
+890(either)X
+1094(all)X
+1195(be)X
+1292(applied)X
+1549(to)X
+1632(the)X
+1751(database)X
+2049(or)X
+2137(all)X
+2238(be)X
+2335(absent.)X
+2601(Consistency)X
+3013(requires)X
+3293(that)X
+3434(a)X
+3491(transaction)X
+3864(take)X
+4019(the)X
+4138(data-)X
+555 3300(base)N
+725(from)X
+908(one)X
+1051(logically)X
+1358(consistent)X
+1704(state)X
+1877(to)X
+1965(another.)X
+2272(The)X
+2423(property)X
+2721(of)X
+2814(isolation)X
+3115(requires)X
+3400(that)X
+3546(concurrent)X
+3916(transactions)X
+555 3390(yield)N
+750(results)X
+994(which)X
+1225(are)X
+1358(indistinguishable)X
+1938(from)X
+2128(the)X
+2260(results)X
+2503(which)X
+2733(would)X
+2967(be)X
+3077(obtained)X
+3387(by)X
+3501(running)X
+3784(the)X
+3916(transactions)X
+555 3480(sequentially.)N
+1002(Finally,)X
+1268(durability)X
+1599(requires)X
+1878(that)X
+2018(once)X
+2190(transactions)X
+2593(have)X
+2765(been)X
+2937(committed,)X
+3319(their)X
+3486(results)X
+3715(must)X
+3890(be)X
+3986(preserved)X
+555 3570(across)N
+776(system)X
+1018(failures)X
+1279([TPCB90].)X
+755 3693(Although)N
+1080(these)X
+1268(properties)X
+1612(are)X
+1734(most)X
+1912(frequently)X
+2265(discussed)X
+2595(in)X
+2680(the)X
+2801(context)X
+3060(of)X
+3150(databases,)X
+3501(they)X
+3661(are)X
+3782(useful)X
+4000(program-)X
+555 3783(ming)N
+750(paradigms)X
+1114(for)X
+1238(more)X
+1433(general)X
+1700(purpose)X
+1984(applications.)X
+2441(There)X
+2659(are)X
+2788(several)X
+3046(different)X
+3353(situations)X
+3689(where)X
+3916(transactions)X
+555 3873(can)N
+687(be)X
+783(used)X
+950(to)X
+1032(replace)X
+1285(current)X
+1533(ad-hoc)X
+1772(mechanisms.)X
+755 3996(One)N
+910(situation)X
+1206(is)X
+1280(when)X
+1475(multiple)X
+1762(\256les)X
+1916(or)X
+2004(parts)X
+2181(of)X
+2269(\256les)X
+2422(need)X
+2594(to)X
+2676(be)X
+2772(updated)X
+3046(in)X
+3128(an)X
+3224(atomic)X
+3462(fashion.)X
+3758(For)X
+3889(example,)X
+4201(the)X
+555 4086(traditional)N
+907(UNIX)X
+1131(\256le)X
+1256(system)X
+1501(uses)X
+1661(ordering)X
+1955(constraints)X
+2324(to)X
+2408(achieve)X
+2676(recoverability)X
+3144(in)X
+3228(the)X
+3348(face)X
+3505(of)X
+3594(crashes.)X
+3893(When)X
+4107(a)X
+4165(new)X
+555 4176(\256le)N
+678(is)X
+752(created,)X
+1026(its)X
+1122(inode)X
+1321(is)X
+1395(written)X
+1642(to)X
+1724(disk)X
+1877(before)X
+2103(the)X
+2221(new)X
+2375(\256le)X
+2497(is)X
+2570(added)X
+2782(to)X
+2864(the)X
+2982(directory)X
+3292(structure.)X
+3633(This)X
+3795(guarantees)X
+4159(that,)X
+555 4266(if)N
+627(the)X
+748(system)X
+993(crashes)X
+1253(between)X
+1544(the)X
+1665(two)X
+1808(I/O's,)X
+2016(the)X
+2137(directory)X
+2450(does)X
+2620(not)X
+2744(contain)X
+3002(a)X
+3060 0.4531(reference)AX
+3383(to)X
+3467(an)X
+3565(invalid)X
+3809(inode.)X
+4049(In)X
+4138(actu-)X
+555 4356(ality,)N
+741(the)X
+863(desired)X
+1119(effect)X
+1326(is)X
+1402(that)X
+1545(these)X
+1733(two)X
+1876(updates)X
+2144(have)X
+2319(the)X
+2440(transactional)X
+2873(property)X
+3168(of)X
+3258(atomicity)X
+3583(\(either)X
+3816(both)X
+3981(writes)X
+4200(are)X
+555 4446(visible)N
+790(or)X
+879(neither)X
+1124(is\).)X
+1266(Rather)X
+1501(than)X
+1660(building)X
+1947(special)X
+2191(purpose)X
+2466(recovery)X
+2769(mechanisms)X
+3186(into)X
+3331(the)X
+3450(\256le)X
+3573(system)X
+3816(or)X
+3904(related)X
+4144(tools)X
+555 4536(\()N
+2 f
+582(e.g.)X
+3 f
+726(fsck)X
+1 f
+864(\(8\)\),)X
+1033(one)X
+1177(could)X
+1383(use)X
+1518(general)X
+1783(purpose)X
+2064(transaction)X
+2443(recovery)X
+2752(protocols)X
+3077(after)X
+3252(system)X
+3501(failure.)X
+3778(Any)X
+3943(application)X
+555 4626(that)N
+705(needs)X
+918(to)X
+1010(keep)X
+1192(multiple,)X
+1508(related)X
+1757(\256les)X
+1920(\(or)X
+2044(directories\))X
+2440(consistent)X
+2790(should)X
+3032(do)X
+3141(so)X
+3241(using)X
+3443(transactions.)X
+3895(Source)X
+4147(code)X
+555 4716(control)N
+805(systems,)X
+1101(such)X
+1271(as)X
+1361(RCS)X
+1534(and)X
+1673(SCCS,)X
+1910(should)X
+2146(use)X
+2276(transaction)X
+2651(semantics)X
+2990(to)X
+3075(allow)X
+3276(the)X
+3397(``checking)X
+3764(in'')X
+3903(of)X
+3992(groups)X
+4232(of)X
+555 4806(related)N
+801(\256les.)X
+1001(In)X
+1095(this)X
+1237(way,)X
+1418(if)X
+1493(the)X
+1617 0.2841(``check-in'')AX
+2028(fails,)X
+2212(the)X
+2336(transaction)X
+2714(may)X
+2878(be)X
+2980(aborted,)X
+3267(backing)X
+3547(out)X
+3675(the)X
+3799(partial)X
+4030(``check-)X
+555 4896(in'')N
+691(leaving)X
+947(the)X
+1065(source)X
+1295(repository)X
+1640(in)X
+1722(a)X
+1778(consistent)X
+2118(state.)X
+755 5019(A)N
+842(second)X
+1094(situation)X
+1398(where)X
+1624(transactions)X
+2036(can)X
+2177(be)X
+2282(used)X
+2458(to)X
+2549(replace)X
+2811(current)X
+3068(ad-hoc)X
+3316(mechanisms)X
+3741(is)X
+3822(in)X
+3912(applications)X
+555 5109(where)N
+776(concurrent)X
+1144(updates)X
+1413(to)X
+1499(a)X
+1559(shared)X
+1793(\256le)X
+1919(are)X
+2042(desired,)X
+2318(but)X
+2444(there)X
+2629(is)X
+2706(logical)X
+2948(consistency)X
+3345(of)X
+3435(the)X
+3556(data)X
+3713(which)X
+3932(needs)X
+4138(to)X
+4223(be)X
+555 5199(preserved.)N
+928(For)X
+1059(example,)X
+1371(when)X
+1565(the)X
+1683(password)X
+2006(\256le)X
+2128(is)X
+2201(updated,)X
+2495(\256le)X
+2617(locking)X
+2877(is)X
+2950(used)X
+3117(to)X
+3199(disallow)X
+3490(concurrent)X
+3854(access.)X
+4120(Tran-)X
+555 5289(saction)N
+804(semantics)X
+1142(on)X
+1244(the)X
+1364(password)X
+1689(\256les)X
+1844(would)X
+2066(allow)X
+2266(concurrent)X
+2632(updates,)X
+2919(while)X
+3119(preserving)X
+3479(the)X
+3598(logical)X
+3837(consistency)X
+4232(of)X
+555 5379(the)N
+681(password)X
+1012(database.)X
+1357(Similarly,)X
+1702(UNIX)X
+1930(utilities)X
+2196(which)X
+2419(rewrite)X
+2674(\256les)X
+2834(face)X
+2996(a)X
+3059(potential)X
+3366(race)X
+3528(condition)X
+3857(between)X
+4152(their)X
+555 5469(rewriting)N
+871(a)X
+929(\256le)X
+1053(and)X
+1191(another)X
+1453(process)X
+1715(reading)X
+1977(the)X
+2096(\256le.)X
+2259(For)X
+2391(example,)X
+2704(the)X
+2823(compiler)X
+3129(\(more)X
+3342(precisely,)X
+3673(the)X
+3792(assembler\))X
+4161(may)X
+8 s
+10 f
+555 5541(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)N
+5 s
+1 f
+727 5619(1)N
+8 s
+763 5644(To)N
+850(appear)X
+1035(in)X
+1101(the)X
+2 f
+1195(Proceedings)X
+1530(of)X
+1596(the)X
+1690(1992)X
+1834(Winter)X
+2024(Usenix)X
+1 f
+2201(,)X
+2233(San)X
+2345(Francisco,)X
+2625(CA,)X
+2746(January)X
+2960(1992.)X
+
+2 p
+%%Page: 2 2
+8 s 8 xH 0 xS 1 f
+10 s
+3 f
+1 f
+555 630(have)N
+737(to)X
+829(rewrite)X
+1087(a)X
+1152(\256le)X
+1283(to)X
+1374(which)X
+1599(it)X
+1672(has)X
+1808(write)X
+2002(permission)X
+2382(in)X
+2473(a)X
+2538(directory)X
+2857(to)X
+2948(which)X
+3173(it)X
+3246(does)X
+3422(not)X
+3553(have)X
+3734(write)X
+3928(permission.)X
+555 720(While)N
+779(the)X
+904(``.o'')X
+1099(\256le)X
+1228(is)X
+1308(being)X
+1513(written,)X
+1787(another)X
+2055(utility)X
+2272(such)X
+2446(as)X
+3 f
+2540(nm)X
+1 f
+2651(\(1\))X
+2772(or)X
+3 f
+2866(ar)X
+1 f
+2942(\(1\))X
+3063(may)X
+3228(read)X
+3394(the)X
+3519(\256le)X
+3648(and)X
+3791(produce)X
+4077(invalid)X
+555 810(results)N
+790(since)X
+981(the)X
+1105(\256le)X
+1233(has)X
+1366(not)X
+1494(been)X
+1672(completely)X
+2054(written.)X
+2347(Currently,)X
+2700(some)X
+2895(utilities)X
+3160(use)X
+3293(special)X
+3542(purpose)X
+3821(code)X
+3998(to)X
+4085(handle)X
+555 900(such)N
+722(cases)X
+912(while)X
+1110(others)X
+1326(ignore)X
+1551(the)X
+1669(problem)X
+1956(and)X
+2092(force)X
+2278(users)X
+2463(to)X
+2545(live)X
+2685(with)X
+2847(the)X
+2965(consequences.)X
+755 1023(In)N
+845(this)X
+983(paper,)X
+1205(we)X
+1322(present)X
+1577(a)X
+1635(simple)X
+1870(library)X
+2106(which)X
+2324(provides)X
+2622(transaction)X
+2996(semantics)X
+3334(\(atomicity,)X
+3705(consistency,)X
+4121(isola-)X
+555 1113(tion,)N
+720(and)X
+857(durability\).)X
+1236(The)X
+1382(4.4BSD)X
+1658(database)X
+1956(access)X
+2182(methods)X
+2473(have)X
+2645(been)X
+2817(modi\256ed)X
+3121(to)X
+3203(use)X
+3330(this)X
+3465(library,)X
+3719(optionally)X
+4063(provid-)X
+555 1203(ing)N
+682(shared)X
+917(buffer)X
+1139(management)X
+1574(between)X
+1867(applications,)X
+2298(locking,)X
+2582(and)X
+2722(transaction)X
+3098(semantics.)X
+3478(Any)X
+3640(UNIX)X
+3865(program)X
+4161(may)X
+555 1293(transaction)N
+930(protect)X
+1176(its)X
+1274(data)X
+1430(by)X
+1532(requesting)X
+1888(transaction)X
+2262(protection)X
+2609(with)X
+2773(the)X
+3 f
+2893(db)X
+1 f
+2981(\(3\))X
+3097(library)X
+3333(or)X
+3422(by)X
+3524(adding)X
+3764(appropriate)X
+4152(calls)X
+555 1383(to)N
+646(the)X
+773(transaction)X
+1154(manager,)X
+1480(buffer)X
+1706(manager,)X
+2032(lock)X
+2199(manager,)X
+2525(and)X
+2670(log)X
+2801(manager.)X
+3147(The)X
+3301(library)X
+3543(routines)X
+3829(may)X
+3995(be)X
+4099(linked)X
+555 1473(into)N
+708(the)X
+834(host)X
+995(application)X
+1379(and)X
+1523(called)X
+1743(by)X
+1851(subroutine)X
+2217(interface,)X
+2547(or)X
+2642(they)X
+2808(may)X
+2974(reside)X
+3194(in)X
+3284(a)X
+3348(separate)X
+3640(server)X
+3865(process.)X
+4174(The)X
+555 1563(server)N
+772(architecture)X
+1172(provides)X
+1468(for)X
+1582(network)X
+1865(access)X
+2091(and)X
+2227(better)X
+2430(protection)X
+2775(mechanisms.)X
+3 f
+555 1749(2.)N
+655(Related)X
+938(Work)X
+1 f
+755 1872(There)N
+1000(has)X
+1164(been)X
+1373(much)X
+1608(discussion)X
+1998(in)X
+2117(recent)X
+2371(years)X
+2597(about)X
+2831(new)X
+3021(transaction)X
+3429(models)X
+3716(and)X
+3888(architectures)X
+555 1962 0.1172([SPEC88][NODI90][CHEN91][MOHA91].)AN
+2009(Much)X
+2220(of)X
+2310(this)X
+2448(work)X
+2636(focuses)X
+2900(on)X
+3003(new)X
+3160(ways)X
+3348(to)X
+3433(model)X
+3656(transactions)X
+4062(and)X
+4201(the)X
+555 2052(interactions)N
+953(between)X
+1245(them,)X
+1449(while)X
+1651(the)X
+1772(work)X
+1960(presented)X
+2291(here)X
+2453(focuses)X
+2717(on)X
+2820(the)X
+2941(implementation)X
+3466(and)X
+3605(performance)X
+4035(of)X
+4125(tradi-)X
+555 2142(tional)N
+757(transaction)X
+1129(techniques)X
+1492(\(write-ahead)X
+1919(logging)X
+2183(and)X
+2319(two-phase)X
+2669(locking\))X
+2956(on)X
+3056(a)X
+3112(standard)X
+3404(operating)X
+3727(system)X
+3969(\(UNIX\).)X
+755 2265(Such)N
+947(traditional)X
+1308(operating)X
+1643(systems)X
+1928(are)X
+2059(often)X
+2256(criticized)X
+2587(for)X
+2713(their)X
+2892(inability)X
+3190(to)X
+3283(perform)X
+3573(transaction)X
+3956(processing)X
+555 2355(adequately.)N
+971([STON81])X
+1342(cites)X
+1517(three)X
+1706(main)X
+1894(areas)X
+2088(of)X
+2183(inadequate)X
+2559(support:)X
+2849(buffer)X
+3074(management,)X
+3532(the)X
+3658(\256le)X
+3788(system,)X
+4058(and)X
+4201(the)X
+555 2445(process)N
+823(structure.)X
+1191(These)X
+1410(arguments)X
+1771(are)X
+1897(summarized)X
+2316(in)X
+2405(table)X
+2587(one.)X
+2769(Fortunately,)X
+3184(much)X
+3388(has)X
+3521(changed)X
+3815(since)X
+4006(1981.)X
+4232(In)X
+555 2535(the)N
+683(area)X
+848(of)X
+945(buffer)X
+1172(management,)X
+1632(most)X
+1817(UNIX)X
+2048(systems)X
+2331(provide)X
+2606(the)X
+2734(ability)X
+2968(to)X
+3060(memory)X
+3357(map)X
+3525(\256les,)X
+3708(thus)X
+3870(obviating)X
+4201(the)X
+555 2625(need)N
+734(for)X
+855(a)X
+918(copy)X
+1101(between)X
+1396(kernel)X
+1624(and)X
+1766(user)X
+1926(space.)X
+2171(If)X
+2251(a)X
+2313(database)X
+2616(system)X
+2864(is)X
+2943(going)X
+3151(to)X
+3239(use)X
+3372(the)X
+3496(\256le)X
+3624(system)X
+3872(buffer)X
+4095(cache,)X
+555 2715(then)N
+719(a)X
+781(system)X
+1029(call)X
+1171(is)X
+1250(required.)X
+1584(However,)X
+1924(if)X
+1998(buffering)X
+2322(is)X
+2400(provided)X
+2710(at)X
+2793(user)X
+2952(level)X
+3133(using)X
+3331(shared)X
+3566(memory,)X
+3878(as)X
+3970(in)X
+4057(LIBTP,)X
+555 2805(buffer)N
+776(management)X
+1210(is)X
+1287(only)X
+1452(as)X
+1542(slow)X
+1716(as)X
+1806(access)X
+2035(to)X
+2120(shared)X
+2353(memory)X
+2643(and)X
+2782(any)X
+2921(replacement)X
+3337(algorithm)X
+3671(may)X
+3832(be)X
+3931(used.)X
+4121(Since)X
+555 2895(multiple)N
+849(processes)X
+1185(can)X
+1325(access)X
+1559(the)X
+1685(shared)X
+1923(data,)X
+2105(prefetching)X
+2499(may)X
+2665(be)X
+2769(accomplished)X
+3238(by)X
+3346(separate)X
+3638(processes)X
+3973(or)X
+4067(threads)X
+555 2985(whose)N
+782(sole)X
+932(purpose)X
+1207(is)X
+1281(to)X
+1364(prefetch)X
+1649(pages)X
+1853(and)X
+1990(wait)X
+2149(on)X
+2250(them.)X
+2471(There)X
+2680(is)X
+2754(still)X
+2894(no)X
+2995(way)X
+3150(to)X
+3233(enforce)X
+3496(write)X
+3682(ordering)X
+3975(other)X
+4161(than)X
+555 3075(keeping)N
+829(pages)X
+1032(in)X
+1114(user)X
+1268(memory)X
+1555(and)X
+1691(using)X
+1884(the)X
+3 f
+2002(fsync)X
+1 f
+2180(\(3\))X
+2294(system)X
+2536(call)X
+2672(to)X
+2754(perform)X
+3033(synchronous)X
+3458(writes.)X
+755 3198(In)N
+845(the)X
+966(area)X
+1124(of)X
+1214(\256le)X
+1339(systems,)X
+1635(the)X
+1756(fast)X
+1895(\256le)X
+2020(system)X
+2265(\(FFS\))X
+2474([MCKU84])X
+2871(allows)X
+3103(allocation)X
+3442(in)X
+3527(units)X
+3704(up)X
+3806(to)X
+3890(64KBytes)X
+4232(as)X
+555 3288(opposed)N
+846(to)X
+932(the)X
+1054(4KByte)X
+1327(and)X
+1466(8KByte)X
+1738(\256gures)X
+1979(quoted)X
+2220(in)X
+2305([STON81].)X
+2711(The)X
+2859(measurements)X
+3341(in)X
+3426(this)X
+3564(paper)X
+3766(were)X
+3946(taken)X
+4143(from)X
+555 3378(an)N
+655(8KByte)X
+928(FFS,)X
+1104(but)X
+1230(as)X
+1320(LIBTP)X
+1565(runs)X
+1726(exclusively)X
+2114(in)X
+2199(user)X
+2356(space,)X
+2578(there)X
+2762(is)X
+2838(nothing)X
+3105(to)X
+3190(prevent)X
+3454(it)X
+3521(from)X
+3700(being)X
+3901(run)X
+4031(on)X
+4134(other)X
+555 3468(UNIX)N
+776(compatible)X
+1152(\256le)X
+1274(systems)X
+1547(\(e.g.)X
+1710(log-structured)X
+2180([ROSE91],)X
+2558(extent-based,)X
+3004(or)X
+3091(multi-block)X
+3484([SELT91]\).)X
+755 3591(Finally,)N
+1029(with)X
+1199(regard)X
+1433(to)X
+1523(the)X
+1648(process)X
+1916(structure,)X
+2244(neither)X
+2494(context)X
+2757(switch)X
+2993(time)X
+3162(nor)X
+3296(scheduling)X
+3670(around)X
+3920(semaphores)X
+555 3681(seems)N
+785(to)X
+881(affect)X
+1099(the)X
+1231(system)X
+1487(performance.)X
+1968(However,)X
+2317(the)X
+2449(implementation)X
+2984(of)X
+3084(semaphores)X
+3496(can)X
+3641(impact)X
+3892(performance)X
+555 3771(tremendously.)N
+1051(This)X
+1213(is)X
+1286(discussed)X
+1613(in)X
+1695(more)X
+1880(detail)X
+2078(in)X
+2160(section)X
+2407(4.3.)X
+755 3894(The)N
+908(Tuxedo)X
+1181(system)X
+1431(from)X
+1615(AT&T)X
+1861(is)X
+1941(a)X
+2004(transaction)X
+2383(manager)X
+2687(which)X
+2910(coordinates)X
+3307(distributed)X
+3676(transaction)X
+4055(commit)X
+555 3984(from)N
+738(a)X
+801(variety)X
+1051(of)X
+1145(different)X
+1449(local)X
+1632(transaction)X
+2011(managers.)X
+2386(At)X
+2493(this)X
+2634(time,)X
+2822(LIBTP)X
+3070(does)X
+3243(not)X
+3371(have)X
+3549(its)X
+3650(own)X
+3814(mechanism)X
+4205(for)X
+555 4074(distributed)N
+942(commit)X
+1231(processing,)X
+1639(but)X
+1786(could)X
+2009(be)X
+2130(used)X
+2322(as)X
+2434(a)X
+2515(local)X
+2716(transaction)X
+3113(agent)X
+3331(by)X
+3455(systems)X
+3752(such)X
+3943(as)X
+4054(Tuxedo)X
+555 4164([ANDR89].)N
+10 f
+863 4393(i)N
+870(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+903 4483(Buffer)N
+1133(Management)X
+10 f
+1672(g)X
+1 f
+1720(Data)X
+1892(must)X
+2067(be)X
+2163(copied)X
+2397(between)X
+2685(kernel)X
+2906(space)X
+3105(and)X
+3241(user)X
+3395(space.)X
+10 f
+1672 4573(g)N
+1 f
+1720(Buffer)X
+1950(pool)X
+2112(access)X
+2338(is)X
+2411(too)X
+2533(slow.)X
+10 f
+1672 4663(g)N
+1 f
+1720(There)X
+1928(is)X
+2001(no)X
+2101(way)X
+2255(to)X
+2337(request)X
+2589(prefetch.)X
+10 f
+1672 4753(g)N
+1 f
+1720(Replacement)X
+2159(is)X
+2232(usually)X
+2483(LRU)X
+2663(which)X
+2879(may)X
+3037(be)X
+3133(suboptimal)X
+3508(for)X
+3622(databases.)X
+10 f
+1672 4843(g)N
+1 f
+1720(There)X
+1928(is)X
+2001(no)X
+2101(way)X
+2255(to)X
+2337(guarantee)X
+2670(write)X
+2855(ordering.)X
+10 f
+863 4853(i)N
+870(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+903 4943(File)N
+1047(System)X
+10 f
+1672(g)X
+1 f
+1720(Allocation)X
+2078(is)X
+2151(done)X
+2327(in)X
+2409(small)X
+2602(blocks)X
+2831(\(usually)X
+3109(4K)X
+3227(or)X
+3314(8K\).)X
+10 f
+1672 5033(g)N
+1 f
+1720(Logical)X
+1985(organization)X
+2406(of)X
+2493(\256les)X
+2646(is)X
+2719(redundantly)X
+3122(expressed.)X
+10 f
+863 5043(i)N
+870(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+903 5133(Process)N
+1168(Structure)X
+10 f
+1672(g)X
+1 f
+1720(Context)X
+1993(switching)X
+2324(and)X
+2460(message)X
+2752(passing)X
+3012(are)X
+3131(too)X
+3253(slow.)X
+10 f
+1672 5223(g)N
+1 f
+1720(A)X
+1798(process)X
+2059(may)X
+2217(be)X
+2313(descheduled)X
+2730(while)X
+2928(holding)X
+3192(a)X
+3248(semaphore.)X
+10 f
+863 5233(i)N
+870(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+863(c)X
+5193(c)Y
+5113(c)Y
+5033(c)Y
+4953(c)Y
+4873(c)Y
+4793(c)Y
+4713(c)Y
+4633(c)Y
+4553(c)Y
+4473(c)Y
+3990 5233(c)N
+5193(c)Y
+5113(c)Y
+5033(c)Y
+4953(c)Y
+4873(c)Y
+4793(c)Y
+4713(c)Y
+4633(c)Y
+4553(c)Y
+4473(c)Y
+3 f
+1156 5446(Table)N
+1371(One:)X
+1560(Shortcomings)X
+2051(of)X
+2138(UNIX)X
+2363(transaction)X
+2770(support)X
+3056(cited)X
+3241(in)X
+3327([STON81].)X
+
+3 p
+%%Page: 3 3
+10 s 10 xH 0 xS 3 f
+1 f
+755 630(The)N
+901(transaction)X
+1274(architecture)X
+1675(presented)X
+2004(in)X
+2087([YOUN91])X
+2474(is)X
+2548(very)X
+2712(similar)X
+2955(to)X
+3038(that)X
+3179(implemented)X
+3618(in)X
+3701(the)X
+3820(LIBTP.)X
+4103(While)X
+555 720([YOUN91])N
+947(presents)X
+1236(a)X
+1298(model)X
+1524(for)X
+1644(providing)X
+1981(transaction)X
+2359(services,)X
+2663(this)X
+2803(paper)X
+3007(focuses)X
+3273(on)X
+3378(the)X
+3501(implementation)X
+4028(and)X
+4169(per-)X
+555 810(formance)N
+881(of)X
+970(a)X
+1028(particular)X
+1358(system.)X
+1642(In)X
+1731(addition,)X
+2034(we)X
+2149(provide)X
+2415(detailed)X
+2690(comparisons)X
+3116(with)X
+3279(alternative)X
+3639(solutions:)X
+3970(traditional)X
+555 900(UNIX)N
+776(services)X
+1055(and)X
+1191(commercial)X
+1590(database)X
+1887(management)X
+2317(systems.)X
+3 f
+555 1086(3.)N
+655(Architecture)X
+1 f
+755 1209(The)N
+906(library)X
+1146(is)X
+1224(designed)X
+1534(to)X
+1621(provide)X
+1891(well)X
+2054(de\256ned)X
+2315(interfaces)X
+2653(to)X
+2740(the)X
+2863(services)X
+3147(required)X
+3440(for)X
+3559(transaction)X
+3936(processing.)X
+555 1299(These)N
+777(services)X
+1066(are)X
+1195(recovery,)X
+1527(concurrency)X
+1955(control,)X
+2232(and)X
+2378(the)X
+2506(management)X
+2946(of)X
+3043(shared)X
+3283(data.)X
+3487(First)X
+3663(we)X
+3787(will)X
+3941(discuss)X
+4201(the)X
+555 1389(design)N
+795(tradeoffs)X
+1112(in)X
+1205(the)X
+1334(selection)X
+1650(of)X
+1748(recovery,)X
+2081(concurrency)X
+2510(control,)X
+2787(and)X
+2933(buffer)X
+3160(management)X
+3600(implementations,)X
+4183(and)X
+555 1479(then)N
+713(we)X
+827(will)X
+971(present)X
+1223(the)X
+1341(overall)X
+1584(library)X
+1818(architecture)X
+2218(and)X
+2354(module)X
+2614(descriptions.)X
+3 f
+555 1665(3.1.)N
+715(Design)X
+966(Tradeoffs)X
+1 f
+3 f
+555 1851(3.1.1.)N
+775(Crash)X
+1004(Recovery)X
+1 f
+755 1974(The)N
+909(recovery)X
+1220(protocol)X
+1516(is)X
+1598(responsible)X
+1992(for)X
+2115(providing)X
+2455(the)X
+2582(transaction)X
+2963(semantics)X
+3308(discussed)X
+3644(earlier.)X
+3919(There)X
+4136(are)X
+4263(a)X
+555 2064(wide)N
+739(range)X
+946(of)X
+1041(recovery)X
+1351(protocols)X
+1677(available)X
+1995([HAER83],)X
+2395(but)X
+2525(we)X
+2647(can)X
+2786(crudely)X
+3054(divide)X
+3281(them)X
+3468(into)X
+3619(two)X
+3766(main)X
+3953(categories.)X
+555 2154(The)N
+706(\256rst)X
+856(category)X
+1159(records)X
+1422(all)X
+1528(modi\256cations)X
+1989(to)X
+2077(the)X
+2201(database)X
+2504(in)X
+2592(a)X
+2653(separate)X
+2942(\256le,)X
+3089(and)X
+3230(uses)X
+3393(this)X
+3533(\256le)X
+3660(\(log\))X
+3841(to)X
+3928(back)X
+4105(out)X
+4232(or)X
+555 2244(reapply)N
+825(these)X
+1019(modi\256cations)X
+1483(if)X
+1561(a)X
+1626(transaction)X
+2007(aborts)X
+2232(or)X
+2328(the)X
+2455(system)X
+2706(crashes.)X
+3012(We)X
+3153(call)X
+3298(this)X
+3442(set)X
+3560(the)X
+3 f
+3687(logging)X
+3963(protocols)X
+1 f
+4279(.)X
+555 2334(The)N
+703(second)X
+949(category)X
+1249(avoids)X
+1481(the)X
+1602(use)X
+1732(of)X
+1822(a)X
+1881(log)X
+2006(by)X
+2109(carefully)X
+2418(controlling)X
+2792(when)X
+2989(data)X
+3146(are)X
+3268(written)X
+3518(to)X
+3603(disk.)X
+3799(We)X
+3934(call)X
+4073(this)X
+4210(set)X
+555 2424(the)N
+3 f
+673(non-logging)X
+1096(protocols)X
+1 f
+1412(.)X
+755 2547(Non-logging)N
+1185(protocols)X
+1504(hold)X
+1666(dirty)X
+1837(buffers)X
+2085(in)X
+2167(main)X
+2347(memory)X
+2634(or)X
+2721(temporary)X
+3071(\256les)X
+3224(until)X
+3390(commit)X
+3654(and)X
+3790(then)X
+3948(force)X
+4134(these)X
+555 2637(pages)N
+769(to)X
+862(disk)X
+1026(at)X
+1115(transaction)X
+1498(commit.)X
+1813(While)X
+2040(we)X
+2165(can)X
+2308(use)X
+2446(temporary)X
+2807(\256les)X
+2971(to)X
+3064(hold)X
+3237(dirty)X
+3418(pages)X
+3631(that)X
+3781(may)X
+3949(need)X
+4131(to)X
+4223(be)X
+555 2727(evicted)N
+810(from)X
+988(memory)X
+1277(during)X
+1508(a)X
+1566(long-running)X
+2006(transaction,)X
+2400(the)X
+2520(only)X
+2684(user-level)X
+3023(mechanism)X
+3410(to)X
+3494(force)X
+3682(pages)X
+3887(to)X
+3971(disk)X
+4126(is)X
+4201(the)X
+3 f
+555 2817(fsync)N
+1 f
+733(\(2\))X
+850(system)X
+1095(call.)X
+1274(Unfortunately,)X
+3 f
+1767(fsync)X
+1 f
+1945(\(2\))X
+2062(is)X
+2138(an)X
+2237(expensive)X
+2581(system)X
+2826(call)X
+2965(in)X
+3050(that)X
+3193(it)X
+3260(forces)X
+3480(all)X
+3583(pages)X
+3789(of)X
+3879(a)X
+3938(\256le)X
+4062(to)X
+4146(disk,)X
+555 2907(and)N
+691(transactions)X
+1094(that)X
+1234(manage)X
+1504(more)X
+1689(than)X
+1847(one)X
+1983(\256le)X
+2105(must)X
+2280(issue)X
+2460(one)X
+2596(call)X
+2732(per)X
+2855(\256le.)X
+755 3030(In)N
+853(addition,)X
+3 f
+1166(fsync)X
+1 f
+1344(\(2\))X
+1469(provides)X
+1776(no)X
+1887(way)X
+2051(to)X
+2143(control)X
+2400(the)X
+2528(order)X
+2728(in)X
+2820(which)X
+3046(dirty)X
+3227(pages)X
+3440(are)X
+3569(written)X
+3826(to)X
+3918(disk.)X
+4121(Since)X
+555 3120(non-logging)N
+976(protocols)X
+1304(must)X
+1489(sometimes)X
+1861(order)X
+2061(writes)X
+2287(carefully)X
+2603([SULL92],)X
+2987(they)X
+3155(are)X
+3284(dif\256cult)X
+3567(to)X
+3659(implement)X
+4030(on)X
+4139(Unix)X
+555 3210(systems.)N
+868(As)X
+977(a)X
+1033(result,)X
+1251(we)X
+1365(have)X
+1537(chosen)X
+1780(to)X
+1862(implement)X
+2224(a)X
+2280(logging)X
+2544(protocol.)X
+755 3333(Logging)N
+1050(protocols)X
+1372(may)X
+1534(be)X
+1634(categorized)X
+2029(based)X
+2236(on)X
+2340(how)X
+2502(information)X
+2904(is)X
+2981(logged)X
+3223(\(physically)X
+3602(or)X
+3692(logically\))X
+4022(and)X
+4161(how)X
+555 3423(much)N
+767(is)X
+854(logged)X
+1106(\(before)X
+1373(images,)X
+1654(after)X
+1836(images)X
+2097(or)X
+2198(both\).)X
+2441(In)X
+3 f
+2542(physical)X
+2855(logging)X
+1 f
+3103(,)X
+3157(images)X
+3417(of)X
+3517(complete)X
+3844(physical)X
+4144(units)X
+555 3513(\(pages)N
+786(or)X
+874(buffers\))X
+1150(are)X
+1270(recorded,)X
+1593(while)X
+1792(in)X
+3 f
+1875(logical)X
+2118(logging)X
+1 f
+2387(a)X
+2444(description)X
+2820(of)X
+2907(the)X
+3025(operation)X
+3348(is)X
+3421(recorded.)X
+3763(Therefore,)X
+4121(while)X
+555 3603(we)N
+675(may)X
+839(record)X
+1071(entire)X
+1280(pages)X
+1489(in)X
+1577(a)X
+1639(physical)X
+1932(log,)X
+2080(we)X
+2200(need)X
+2378(only)X
+2546(record)X
+2777(the)X
+2900(records)X
+3162(being)X
+3365(modi\256ed)X
+3674(in)X
+3761(a)X
+3822(logical)X
+4065(log.)X
+4232(In)X
+555 3693(fact,)N
+718(physical)X
+1006(logging)X
+1271(can)X
+1404(be)X
+1501(thought)X
+1766(of)X
+1854(as)X
+1942(a)X
+1999(special)X
+2243(case)X
+2403(of)X
+2491(logical)X
+2730(logging,)X
+3015(since)X
+3201(the)X
+3320 0.3125(``records'')AX
+3686(that)X
+3827(we)X
+3942(log)X
+4065(in)X
+4148(logi-)X
+555 3783(cal)N
+673(logging)X
+941(might)X
+1151(be)X
+1251(physical)X
+1542(pages.)X
+1789(Since)X
+1991(logical)X
+2233(logging)X
+2501(is)X
+2578(both)X
+2743(more)X
+2931(space-ef\256cient)X
+3423(and)X
+3562(more)X
+3750(general,)X
+4030(we)X
+4147(have)X
+555 3873(chosen)N
+798(it)X
+862(for)X
+976(our)X
+1103(logging)X
+1367(protocol.)X
+755 3996(In)N
+3 f
+843(before-image)X
+1315(logging)X
+1 f
+1563(,)X
+1604(we)X
+1719(log)X
+1842(a)X
+1899(copy)X
+2076(of)X
+2164(the)X
+2283(data)X
+2438(before)X
+2665(the)X
+2784(update,)X
+3039(while)X
+3238(in)X
+3 f
+3321(after-image)X
+3739(logging)X
+1 f
+3987(,)X
+4027(we)X
+4141(log)X
+4263(a)X
+555 4086(copy)N
+740(of)X
+836(the)X
+963(data)X
+1126(after)X
+1303(the)X
+1429(update.)X
+1711(If)X
+1793(we)X
+1915(log)X
+2045(only)X
+2215(before-images,)X
+2723(then)X
+2889(there)X
+3078(is)X
+3159(suf\256cient)X
+3485(information)X
+3891(in)X
+3981(the)X
+4107(log)X
+4237(to)X
+555 4176(allow)N
+761(us)X
+860(to)X
+3 f
+950(undo)X
+1 f
+1150(the)X
+1276(transaction)X
+1656(\(go)X
+1791(back)X
+1971(to)X
+2061(the)X
+2187(state)X
+2361(represented)X
+2759(by)X
+2866(the)X
+2991(before-image\).)X
+3514(However,)X
+3876(if)X
+3952(the)X
+4077(system)X
+555 4266(crashes)N
+814(and)X
+952(a)X
+1010(committed)X
+1374(transaction's)X
+1806(changes)X
+2087(have)X
+2261(not)X
+2385(reached)X
+2658(the)X
+2778(disk,)X
+2953(we)X
+3068(have)X
+3241(no)X
+3342(means)X
+3568(to)X
+3 f
+3651(redo)X
+1 f
+3828(the)X
+3947(transaction)X
+555 4356(\(reapply)N
+849(the)X
+973(updates\).)X
+1311(Therefore,)X
+1675(logging)X
+1945(only)X
+2113(before-images)X
+2599(necessitates)X
+3004(forcing)X
+3262(dirty)X
+3439(pages)X
+3648(at)X
+3732(commit)X
+4002(time.)X
+4210(As)X
+555 4446(mentioned)N
+913(above,)X
+1145(forcing)X
+1397(pages)X
+1600(at)X
+1678(commit)X
+1942(is)X
+2015(considered)X
+2383(too)X
+2505(costly.)X
+755 4569(If)N
+834(we)X
+953(log)X
+1080(only)X
+1247(after-images,)X
+1694(then)X
+1857(there)X
+2043(is)X
+2121(suf\256cient)X
+2444(information)X
+2847(in)X
+2934(the)X
+3057(log)X
+3184(to)X
+3271(allow)X
+3474(us)X
+3570(to)X
+3657(redo)X
+3825(the)X
+3947(transaction)X
+555 4659(\(go)N
+687(forward)X
+967(to)X
+1054(the)X
+1177(state)X
+1348(represented)X
+1743(by)X
+1847(the)X
+1969(after-image\),)X
+2411(but)X
+2537(we)X
+2655(do)X
+2759(not)X
+2885(have)X
+3061(the)X
+3183(information)X
+3585(required)X
+3877(to)X
+3963(undo)X
+4147(tran-)X
+555 4749(sactions)N
+845(which)X
+1073(aborted)X
+1346(after)X
+1526(dirty)X
+1709(pages)X
+1924(were)X
+2113(written)X
+2372(to)X
+2466(disk.)X
+2670(Therefore,)X
+3039(logging)X
+3314(only)X
+3487(after-images)X
+3920(necessitates)X
+555 4839(holding)N
+819(all)X
+919(dirty)X
+1090(buffers)X
+1338(in)X
+1420(main)X
+1600(memory)X
+1887(until)X
+2053(commit)X
+2317(or)X
+2404(writing)X
+2655(them)X
+2835(to)X
+2917(a)X
+2973(temporary)X
+3323(\256le.)X
+755 4962(Since)N
+956(neither)X
+1202(constraint)X
+1541(\(forcing)X
+1823(pages)X
+2029(on)X
+2132(commit)X
+2399(or)X
+2489(buffering)X
+2811(pages)X
+3016(until)X
+3184(commit\))X
+3477(was)X
+3624(feasible,)X
+3916(we)X
+4032(chose)X
+4237(to)X
+555 5052(log)N
+683(both)X
+851(before)X
+1083(and)X
+1225(after)X
+1399(images.)X
+1672(The)X
+1823(only)X
+1991(remaining)X
+2342(consideration)X
+2800(is)X
+2879(when)X
+3079(changes)X
+3363(get)X
+3486(written)X
+3738(to)X
+3825(disk.)X
+4023(Changes)X
+555 5142(affect)N
+764(both)X
+931(data)X
+1090(pages)X
+1298(and)X
+1438(the)X
+1560(log.)X
+1726(If)X
+1804(the)X
+1926(changed)X
+2218(data)X
+2376(page)X
+2552(is)X
+2629(written)X
+2880(before)X
+3110(the)X
+3232(log)X
+3358(page,)X
+3554(and)X
+3694(the)X
+3816(system)X
+4062(crashes)X
+555 5232(before)N
+787(the)X
+911(log)X
+1039(page)X
+1217(is)X
+1296(written,)X
+1569(the)X
+1693(log)X
+1820(will)X
+1969(contain)X
+2230(insuf\256cient)X
+2615(information)X
+3018(to)X
+3105(undo)X
+3290(the)X
+3413(change.)X
+3706(This)X
+3873(violates)X
+4147(tran-)X
+555 5322(saction)N
+803(semantics,)X
+1160(since)X
+1346(some)X
+1536(changed)X
+1825(data)X
+1980(pages)X
+2184(may)X
+2343(not)X
+2466(have)X
+2638(been)X
+2810(written,)X
+3077(and)X
+3213(the)X
+3331(database)X
+3628(cannot)X
+3862(be)X
+3958(restored)X
+4237(to)X
+555 5412(its)N
+650(pre-transaction)X
+1152(state.)X
+755 5535(The)N
+914(log)X
+1050(record)X
+1290(describing)X
+1658(an)X
+1768(update)X
+2016(must)X
+2205(be)X
+2315(written)X
+2576(to)X
+2672(stable)X
+2893(storage)X
+3159(before)X
+3398(the)X
+3529(modi\256ed)X
+3846(page.)X
+4071(This)X
+4246(is)X
+3 f
+555 5625(write-ahead)N
+992(logging)X
+1 f
+1240(.)X
+1307(If)X
+1388(log)X
+1517(records)X
+1781(are)X
+1907(safely)X
+2126(written)X
+2380(to)X
+2469(disk,)X
+2649(data)X
+2810(pages)X
+3020(may)X
+3185(be)X
+3288(written)X
+3542(at)X
+3627(any)X
+3770(time)X
+3939(afterwards.)X
+555 5715(This)N
+721(means)X
+950(that)X
+1094(the)X
+1216(only)X
+1382(\256le)X
+1508(that)X
+1652(ever)X
+1815(needs)X
+2022(to)X
+2108(be)X
+2208(forced)X
+2438(to)X
+2524(disk)X
+2681(is)X
+2758(the)X
+2880(log.)X
+3046(Since)X
+3248(the)X
+3370(log)X
+3495(is)X
+3571(append-only,)X
+4015(modi\256ed)X
+
+4 p
+%%Page: 4 4
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+555 630(pages)N
+760(always)X
+1005(appear)X
+1242(at)X
+1322(the)X
+1442(end)X
+1580(and)X
+1718(may)X
+1878(be)X
+1976(written)X
+2224(to)X
+2307(disk)X
+2461(ef\256ciently)X
+2807(in)X
+2890(any)X
+3027(\256le)X
+3150(system)X
+3393(that)X
+3534(favors)X
+3756(sequential)X
+4102(order-)X
+555 720(ing)N
+677(\()X
+2 f
+704(e.g.)X
+1 f
+820(,)X
+860(FFS,)X
+1032(log-structured)X
+1502(\256le)X
+1624(system,)X
+1886(or)X
+1973(an)X
+2069(extent-based)X
+2495(system\).)X
+3 f
+555 906(3.1.2.)N
+775(Concurrency)X
+1245(Control)X
+1 f
+755 1029(The)N
+918(concurrency)X
+1354(control)X
+1619(protocol)X
+1923(is)X
+2013(responsible)X
+2415(for)X
+2546(maintaining)X
+2965(consistency)X
+3376(in)X
+3475(the)X
+3610(presence)X
+3929(of)X
+4033(multiple)X
+555 1119(accesses.)N
+897(There)X
+1114(are)X
+1242(several)X
+1499(alternative)X
+1867(solutions)X
+2183(such)X
+2358(as)X
+2453(locking,)X
+2741(optimistic)X
+3088(concurrency)X
+3514(control)X
+3769([KUNG81],)X
+4183(and)X
+555 1209(timestamp)N
+912(ordering)X
+1208([BERN80].)X
+1619(Since)X
+1821(optimistic)X
+2164(methods)X
+2459(and)X
+2599(timestamp)X
+2956(ordering)X
+3252(are)X
+3374(generally)X
+3696(more)X
+3884(complex)X
+4183(and)X
+555 1299(restrict)N
+804(concurrency)X
+1228(without)X
+1498(eliminating)X
+1888(starvation)X
+2230(or)X
+2323(deadlocks,)X
+2690(we)X
+2810(chose)X
+3018(two-phase)X
+3373(locking)X
+3638(\(2PL\).)X
+3890(Strict)X
+4088(2PL)X
+4246(is)X
+555 1389(suboptimal)N
+935(for)X
+1054(certain)X
+1297(data)X
+1455(structures)X
+1791(such)X
+1962(as)X
+2053(B-trees)X
+2309(because)X
+2588(it)X
+2656(can)X
+2792(limit)X
+2966(concurrency,)X
+3408(so)X
+3503(we)X
+3621(use)X
+3752(a)X
+3812(special)X
+4059(locking)X
+555 1479(protocol)N
+842(based)X
+1045(on)X
+1145(one)X
+1281(described)X
+1609(in)X
+1691([LEHM81].)X
+755 1602(The)N
+901(B-tree)X
+1123(locking)X
+1384(protocol)X
+1672(we)X
+1787(implemented)X
+2226(releases)X
+2502(locks)X
+2691(at)X
+2769(internal)X
+3034(nodes)X
+3241(in)X
+3323(the)X
+3441(tree)X
+3582(as)X
+3669(it)X
+3733(descends.)X
+4083(A)X
+4161(lock)X
+555 1692(on)N
+658(an)X
+757(internal)X
+1025(page)X
+1200(is)X
+1276(always)X
+1522(released)X
+1808(before)X
+2036(a)X
+2094(lock)X
+2254(on)X
+2356(its)X
+2453(child)X
+2635(is)X
+2710(obtained)X
+3008(\(that)X
+3177(is,)X
+3272(locks)X
+3463(are)X
+3584(not)X
+3 f
+3708(coupled)X
+1 f
+3996([BAY77])X
+555 1782(during)N
+786(descent\).)X
+1116(When)X
+1330(a)X
+1388(leaf)X
+1531(\(or)X
+1647(internal\))X
+1941(page)X
+2115(is)X
+2190(split,)X
+2369(a)X
+2427(write)X
+2614(lock)X
+2774(is)X
+2849(acquired)X
+3148(on)X
+3250(the)X
+3370(parent)X
+3593(before)X
+3821(the)X
+3941(lock)X
+4100(on)X
+4201(the)X
+555 1872(just-split)N
+855(page)X
+1028(is)X
+1102(released)X
+1387(\(locks)X
+1604(are)X
+3 f
+1724(coupled)X
+1 f
+2011(during)X
+2241(ascent\).)X
+2530(Write)X
+2734(locks)X
+2924(on)X
+3025(internal)X
+3291(pages)X
+3495(are)X
+3615(released)X
+3899(immediately)X
+555 1962(after)N
+723(the)X
+841(page)X
+1013(is)X
+1086(updated,)X
+1380(but)X
+1502(locks)X
+1691(on)X
+1791(leaf)X
+1932(pages)X
+2135(are)X
+2254(held)X
+2412(until)X
+2578(the)X
+2696(end)X
+2832(of)X
+2919(the)X
+3037(transaction.)X
+755 2085(Since)N
+964(locks)X
+1164(are)X
+1294(released)X
+1589(during)X
+1828(descent,)X
+2119(the)X
+2247(structure)X
+2558(of)X
+2655(the)X
+2783(tree)X
+2934(may)X
+3102(change)X
+3360(above)X
+3582(a)X
+3648(node)X
+3834(being)X
+4042(used)X
+4219(by)X
+555 2175(some)N
+752(process.)X
+1061(If)X
+1143(that)X
+1291(process)X
+1560(must)X
+1743(later)X
+1914(ascend)X
+2161(the)X
+2287(tree)X
+2435(because)X
+2717(of)X
+2811(a)X
+2874(page)X
+3053(split,)X
+3237(any)X
+3380(such)X
+3554(change)X
+3809(must)X
+3991(not)X
+4120(cause)X
+555 2265(confusion.)N
+938(We)X
+1077(use)X
+1211(the)X
+1336(technique)X
+1675(described)X
+2010(in)X
+2099([LEHM81])X
+2487(which)X
+2710(exploits)X
+2989(the)X
+3113(ordering)X
+3411(of)X
+3504(data)X
+3664(on)X
+3770(a)X
+3832(B-tree)X
+4059(page)X
+4237(to)X
+555 2355(guarantee)N
+888(that)X
+1028(no)X
+1128(process)X
+1389(ever)X
+1548(gets)X
+1697(lost)X
+1832(as)X
+1919(a)X
+1975(result)X
+2173(of)X
+2260(internal)X
+2525(page)X
+2697(updates)X
+2962(made)X
+3156(by)X
+3256(other)X
+3441(processes.)X
+755 2478(If)N
+836(a)X
+899(transaction)X
+1278(that)X
+1425(updates)X
+1697(a)X
+1760(B-tree)X
+1988(aborts,)X
+2231(the)X
+2356(user-visible)X
+2757(changes)X
+3043(to)X
+3131(the)X
+3255(tree)X
+3402(must)X
+3583(be)X
+3685(rolled)X
+3898(back.)X
+4116(How-)X
+555 2568(ever,)N
+735(changes)X
+1015(to)X
+1097(the)X
+1215(internal)X
+1480(nodes)X
+1687(of)X
+1774(the)X
+1892(tree)X
+2033(need)X
+2205(not)X
+2327(be)X
+2423(rolled)X
+2630(back,)X
+2822(since)X
+3007(these)X
+3192(pages)X
+3395(contain)X
+3651(no)X
+3751(user-visible)X
+4145(data.)X
+555 2658(When)N
+771(rolling)X
+1008(back)X
+1184(a)X
+1244(transaction,)X
+1640(we)X
+1758(roll)X
+1893(back)X
+2069(all)X
+2173(leaf)X
+2318(page)X
+2494(updates,)X
+2783(but)X
+2909(no)X
+3013(internal)X
+3281(insertions)X
+3615(or)X
+3705(page)X
+3880(splits.)X
+4111(In)X
+4201(the)X
+555 2748(worst)N
+759(case,)X
+944(this)X
+1085(will)X
+1235(leave)X
+1431(a)X
+1493(leaf)X
+1640(page)X
+1818(less)X
+1964(than)X
+2128(half)X
+2279(full.)X
+2456(This)X
+2624(may)X
+2788(cause)X
+2993(poor)X
+3166(space)X
+3371(utilization,)X
+3741(but)X
+3869(does)X
+4042(not)X
+4170(lose)X
+555 2838(user)N
+709(data.)X
+755 2961(Holding)N
+1038(locks)X
+1228(on)X
+1329(leaf)X
+1471(pages)X
+1675(until)X
+1842(transaction)X
+2215(commit)X
+2480(guarantees)X
+2845(that)X
+2986(no)X
+3087(other)X
+3273(process)X
+3535(can)X
+3668(insert)X
+3866(or)X
+3953(delete)X
+4165(data)X
+555 3051(that)N
+711(has)X
+854(been)X
+1042(touched)X
+1332(by)X
+1448(this)X
+1598(process.)X
+1914(Rolling)X
+2188(back)X
+2375(insertions)X
+2721(and)X
+2872(deletions)X
+3196(on)X
+3311(leaf)X
+3467(pages)X
+3685(guarantees)X
+4064(that)X
+4219(no)X
+555 3141(aborted)N
+819(updates)X
+1087(are)X
+1209(ever)X
+1371(visible)X
+1607(to)X
+1692(other)X
+1880(transactions.)X
+2326(Leaving)X
+2612(page)X
+2787(splits)X
+2978(intact)X
+3179(permits)X
+3442(us)X
+3536(to)X
+3621(release)X
+3867(internal)X
+4134(write)X
+555 3231(locks)N
+744(early.)X
+965(Thus)X
+1145(transaction)X
+1517(semantics)X
+1853(are)X
+1972(preserved,)X
+2325(and)X
+2461(locks)X
+2650(are)X
+2769(held)X
+2927(for)X
+3041(shorter)X
+3284(periods.)X
+755 3354(The)N
+901(extra)X
+1083(complexity)X
+1464(introduced)X
+1828(by)X
+1929(this)X
+2065(locking)X
+2326(protocol)X
+2614(appears)X
+2881(substantial,)X
+3264(but)X
+3387(it)X
+3452(is)X
+3525(important)X
+3856(for)X
+3970(multi-user)X
+555 3444(execution.)N
+950(The)X
+1118(bene\256ts)X
+1410(of)X
+1520(non-two-phase)X
+2040(locking)X
+2323(on)X
+2446(B-trees)X
+2721(are)X
+2863(well)X
+3044(established)X
+3443(in)X
+3548(the)X
+3689(database)X
+4009(literature)X
+555 3534([BAY77],)N
+899([LEHM81].)X
+1320(If)X
+1394(a)X
+1450(process)X
+1711(held)X
+1869(locks)X
+2058(until)X
+2224(it)X
+2288(committed,)X
+2670(then)X
+2828(a)X
+2884(long-running)X
+3322(update)X
+3556(could)X
+3754(lock)X
+3912(out)X
+4034(all)X
+4134(other)X
+555 3624(transactions)N
+967(by)X
+1076(preventing)X
+1448(any)X
+1593(other)X
+1787(process)X
+2057(from)X
+2241(locking)X
+2509(the)X
+2635(root)X
+2792(page)X
+2972(of)X
+3067(the)X
+3193(tree.)X
+3382(The)X
+3535(B-tree)X
+3764(locking)X
+4032(protocol)X
+555 3714(described)N
+884(above)X
+1096(guarantees)X
+1460(that)X
+1600(locks)X
+1789(on)X
+1889(internal)X
+2154(pages)X
+2357(are)X
+2476(held)X
+2634(for)X
+2748(extremely)X
+3089(short)X
+3269(periods,)X
+3545(thereby)X
+3806(increasing)X
+4156(con-)X
+555 3804(currency.)N
+3 f
+555 3990(3.1.3.)N
+775(Management)X
+1245(of)X
+1332(Shared)X
+1596(Data)X
+1 f
+755 4113(Database)N
+1075(systems)X
+1353(permit)X
+1587(many)X
+1790(users)X
+1980(to)X
+2067(examine)X
+2364(and)X
+2505(update)X
+2744(the)X
+2866(same)X
+3055(data)X
+3213(concurrently.)X
+3683(In)X
+3774(order)X
+3968(to)X
+4054(provide)X
+555 4203(this)N
+702(concurrent)X
+1078(access)X
+1316(and)X
+1464(enforce)X
+1738(the)X
+1868(write-ahead)X
+2280(logging)X
+2556(protocol)X
+2855(described)X
+3195(in)X
+3289(section)X
+3548(3.1.1,)X
+3759(we)X
+3884(use)X
+4022(a)X
+4089(shared)X
+555 4293(memory)N
+848(buffer)X
+1071(manager.)X
+1414(Not)X
+1559(only)X
+1726(does)X
+1898(this)X
+2038(provide)X
+2308(the)X
+2431(guarantees)X
+2800(we)X
+2919(require,)X
+3192(but)X
+3319(a)X
+3380(user-level)X
+3722(buffer)X
+3944(manager)X
+4246(is)X
+555 4383(frequently)N
+916(faster)X
+1126(than)X
+1295(using)X
+1498(the)X
+1626(\256le)X
+1758(system)X
+2010(buffer)X
+2237(cache.)X
+2491(Reads)X
+2717(or)X
+2814(writes)X
+3040(involving)X
+3376(the)X
+3504(\256le)X
+3636(system)X
+3888(buffer)X
+4115(cache)X
+555 4473(often)N
+746(require)X
+1000(copying)X
+1284(data)X
+1444(between)X
+1738(user)X
+1898(and)X
+2040(kernel)X
+2266(space)X
+2470(while)X
+2673(a)X
+2734(user-level)X
+3076(buffer)X
+3298(manager)X
+3600(can)X
+3737(return)X
+3954(pointers)X
+4237(to)X
+555 4563(data)N
+709(pages)X
+912(directly.)X
+1217(Additionally,)X
+1661(if)X
+1730(more)X
+1915(than)X
+2073(one)X
+2209(process)X
+2470(uses)X
+2628(the)X
+2746(same)X
+2931(page,)X
+3123(then)X
+3281(fewer)X
+3485(copies)X
+3710(may)X
+3868(be)X
+3964(required.)X
+3 f
+555 4749(3.2.)N
+715(Module)X
+997(Architecture)X
+1 f
+755 4872(The)N
+913(preceding)X
+1262(sections)X
+1552(described)X
+1892(modules)X
+2195(for)X
+2321(managing)X
+2669(the)X
+2799(transaction)X
+3183(log,)X
+3337(locks,)X
+3558(and)X
+3706(a)X
+3774(cache)X
+3990(of)X
+4089(shared)X
+555 4962(buffers.)N
+847(In)X
+938(addition,)X
+1244(we)X
+1362(need)X
+1538(to)X
+1624(provide)X
+1893(functionality)X
+2326(for)X
+2444(transaction)X
+2 f
+2819(begin)X
+1 f
+2997(,)X
+2 f
+3040(commit)X
+1 f
+3276(,)X
+3319(and)X
+2 f
+3458(abort)X
+1 f
+3654(processing,)X
+4040(necessi-)X
+555 5052(tating)N
+769(a)X
+837(transaction)X
+1221(manager.)X
+1570(In)X
+1669(order)X
+1871(to)X
+1965(arbitrate)X
+2265(concurrent)X
+2641(access)X
+2879(to)X
+2973(locks)X
+3173(and)X
+3320(buffers,)X
+3599(we)X
+3724(include)X
+3991(a)X
+4058(process)X
+555 5142(management)N
+995(module)X
+1264(which)X
+1489(manages)X
+1799(a)X
+1864(collection)X
+2209(of)X
+2305(semaphores)X
+2713(used)X
+2889(to)X
+2980(block)X
+3187(and)X
+3332(release)X
+3585(processes.)X
+3962(Finally,)X
+4237(in)X
+555 5232(order)N
+752(to)X
+841(provide)X
+1113(a)X
+1176(simple,)X
+1436(standard)X
+1735(interface)X
+2044(we)X
+2165(have)X
+2344(modi\256ed)X
+2655(the)X
+2780(database)X
+3084(access)X
+3317(routines)X
+3602(\()X
+3 f
+3629(db)X
+1 f
+3717(\(3\)\).)X
+3904(For)X
+4041(the)X
+4165(pur-)X
+555 5322(poses)N
+758(of)X
+850(this)X
+990(paper)X
+1194(we)X
+1313(call)X
+1453(the)X
+1575(modi\256ed)X
+1883(package)X
+2171(the)X
+3 f
+2293(Record)X
+2567(Manager)X
+1 f
+2879(.)X
+2943(Figure)X
+3176(one)X
+3316(shows)X
+3540(the)X
+3662(main)X
+3846(interfaces)X
+4183(and)X
+555 5412(architecture)N
+955(of)X
+1042(LIBTP.)X
+
+5 p
+%%Page: 5 5
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+11 s
+1851 1520(log_commit)N
+2764 2077(buf_unpin)N
+2764 1987(buf_get)N
+3633 1408(buf_unpin)N
+3633 1319(buf_pin)N
+3633 1230(buf_get)N
+3 f
+17 s
+1163 960(Txn)N
+1430(M)X
+1559(anager)X
+2582(Record)X
+3040(M)X
+3169(anager)X
+1 Dt
+2363 726 MXY
+0 355 Dl
+1426 0 Dl
+0 -355 Dl
+-1426 0 Dl
+3255 1616 MXY
+0 535 Dl
+534 0 Dl
+0 -535 Dl
+-534 0 Dl
+2185 MX
+0 535 Dl
+535 0 Dl
+0 -535 Dl
+-535 0 Dl
+1116 MX
+0 535 Dl
+534 0 Dl
+0 -535 Dl
+-534 0 Dl
+726 MY
+0 355 Dl
+891 0 Dl
+0 -355 Dl
+-891 0 Dl
+1 f
+11 s
+2207 1297(lock)N
+2564 1386(log)N
+865(unlock_all)X
+1851 1609(log_unroll)N
+1650 2508 MXY
+0 178 Dl
+1605 0 Dl
+0 -178 Dl
+-1605 0 Dl
+1294 1616 MXY
+19 -30 Dl
+-19 11 Dl
+-20 -11 Dl
+20 30 Dl
+0 -535 Dl
+2319 2508 MXY
+-22 -30 Dl
+4 23 Dl
+-18 14 Dl
+36 -7 Dl
+-936 -357 Dl
+3277 2455(sleep_on)N
+1405 1616 MXY
+36 4 Dl
+-18 -13 Dl
+1 -22 Dl
+-19 31 Dl
+1070 -535 Dl
+2631 2508 MXY
+36 6 Dl
+-18 -14 Dl
+3 -22 Dl
+-21 30 Dl
+891 -357 Dl
+1426 2455(sleep_on)N
+3255 1884 MXY
+-31 -20 Dl
+11 20 Dl
+-11 19 Dl
+31 -19 Dl
+-535 0 Dl
+1554 2366(wake)N
+3277(wake)X
+2185 1884 MXY
+-31 -20 Dl
+12 20 Dl
+-12 19 Dl
+31 -19 Dl
+-356 0 Dl
+0 -803 Dl
+3 f
+17 s
+1236 1851(Lock)N
+1118 2030(M)N
+1247(anager)X
+2339 1851(Log)N
+2187 2030(M)N
+2316(anager)X
+3333 1851(Buffer)N
+3257 2030(M)N
+3386(anager)X
+3522 1616 MXY
+20 -30 Dl
+-20 11 Dl
+-20 -11 Dl
+20 30 Dl
+0 -535 Dl
+1950 2654(Process)N
+2424(M)X
+2553(anager)X
+2542 1616 MXY
+19 -30 Dl
+-19 11 Dl
+-20 -11 Dl
+20 30 Dl
+0 -535 Dl
+1 f
+11 s
+2207 1364(unlock)N
+2452 2508 MXY
+20 -31 Dl
+-20 11 Dl
+-19 -11 Dl
+19 31 Dl
+0 -357 Dl
+2497 2322(sleep_on)N
+2497 2233(wake)N
+3 Dt
+-1 Ds
+3 f
+10 s
+1790 2830(Figure)N
+2037(1:)X
+2144(Library)X
+2435(module)X
+2708(interfaces.)X
+1 f
+10 f
+555 3010(h)N
+579(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)X
+3 f
+555 3286(3.2.1.)N
+775(The)X
+928(Log)X
+1081(Manager)X
+1 f
+755 3409(The)N
+3 f
+907(Log)X
+1067(Manager)X
+1 f
+1406(enforces)X
+1706(the)X
+1831(write-ahead)X
+2238(logging)X
+2509(protocol.)X
+2843(Its)X
+2949(primitive)X
+3268(operations)X
+3628(are)X
+2 f
+3753(log)X
+1 f
+3855(,)X
+2 f
+3901(log_commit)X
+1 f
+4279(,)X
+2 f
+555 3499(log_read)N
+1 f
+844(,)X
+2 f
+889(log_roll)X
+1 f
+1171(and)X
+2 f
+1312(log_unroll)X
+1 f
+1649(.)X
+1714(The)X
+2 f
+1864(log)X
+1 f
+1991(call)X
+2132(performs)X
+2447(a)X
+2508(buffered)X
+2806(write)X
+2996(of)X
+3088(the)X
+3211(speci\256ed)X
+3520(log)X
+3646(record)X
+3876(and)X
+4016(returns)X
+4263(a)X
+555 3589(unique)N
+809(log)X
+947(sequence)X
+1278(number)X
+1559(\(LSN\).)X
+1840(This)X
+2017(LSN)X
+2203(may)X
+2376(then)X
+2549(be)X
+2660(used)X
+2842(to)X
+2939(retrieve)X
+3220(a)X
+3291(record)X
+3532(from)X
+3723(the)X
+3856(log)X
+3993(using)X
+4201(the)X
+2 f
+555 3679(log_read)N
+1 f
+865(call.)X
+1042(The)X
+2 f
+1188(log)X
+1 f
+1311(interface)X
+1614(knows)X
+1844(very)X
+2008(little)X
+2175(about)X
+2374(the)X
+2493(internal)X
+2759(format)X
+2993(of)X
+3080(the)X
+3198(log)X
+3320(records)X
+3577(it)X
+3641(receives.)X
+3965(Rather,)X
+4219(all)X
+555 3769(log)N
+681(records)X
+942(are)X
+1065 0.4028(referenced)AX
+1430(by)X
+1534(a)X
+1594(header)X
+1833(structure,)X
+2158(a)X
+2218(log)X
+2344(record)X
+2574(type,)X
+2756(and)X
+2896(a)X
+2956(character)X
+3276(buffer)X
+3497(containing)X
+3859(the)X
+3981(data)X
+4138(to)X
+4223(be)X
+555 3859(logged.)N
+834(The)X
+980(log)X
+1103(record)X
+1330(type)X
+1489(is)X
+1563(used)X
+1731(to)X
+1814(call)X
+1951(the)X
+2070(appropriate)X
+2457(redo)X
+2621(and)X
+2758(undo)X
+2939(routines)X
+3217(during)X
+2 f
+3446(abort)X
+1 f
+3639(and)X
+2 f
+3775(commit)X
+1 f
+4031(process-)X
+555 3949(ing.)N
+721(While)X
+941(we)X
+1059(have)X
+1235(used)X
+1406(the)X
+3 f
+1528(Log)X
+1684(Manager)X
+1 f
+2019(to)X
+2104(provide)X
+2372(before)X
+2601(and)X
+2740(after)X
+2911(image)X
+3130(logging,)X
+3417(it)X
+3484(may)X
+3645(also)X
+3797(be)X
+3896(used)X
+4066(for)X
+4183(any)X
+555 4039(of)N
+642(the)X
+760(logging)X
+1024(algorithms)X
+1386(discussed.)X
+755 4162(The)N
+2 f
+905(log_commit)X
+1 f
+1308(operation)X
+1636(behaves)X
+1920(exactly)X
+2177(like)X
+2322(the)X
+2 f
+2445(log)X
+1 f
+2572(operation)X
+2900(but)X
+3026(guarantees)X
+3394(that)X
+3538(the)X
+3660(log)X
+3786(has)X
+3917(been)X
+4093(forced)X
+555 4252(to)N
+643(disk)X
+802(before)X
+1034(returning.)X
+1394(A)X
+1478(discussion)X
+1837(of)X
+1930(our)X
+2063(commit)X
+2333(strategy)X
+2613(appears)X
+2884(in)X
+2971(the)X
+3094(implementation)X
+3621(section)X
+3873(\(section)X
+4152(4.2\).)X
+2 f
+555 4342(Log_unroll)N
+1 f
+935(reads)X
+1126(log)X
+1249(records)X
+1507(from)X
+1684(the)X
+1803(log,)X
+1946(following)X
+2278(backward)X
+2611(transaction)X
+2983(pointers)X
+3261(and)X
+3397(calling)X
+3635(the)X
+3753(appropriate)X
+4139(undo)X
+555 4432(routines)N
+839(to)X
+927(implement)X
+1295(transaction)X
+1673(abort.)X
+1904(In)X
+1997(a)X
+2059(similar)X
+2307(manner,)X
+2 f
+2594(log_roll)X
+1 f
+2877(reads)X
+3073(log)X
+3201(records)X
+3464(sequentially)X
+3877(forward,)X
+4178(cal-)X
+555 4522(ling)N
+699(the)X
+817(appropriate)X
+1203(redo)X
+1366(routines)X
+1644(to)X
+1726(recover)X
+1988(committed)X
+2350(transactions)X
+2753(after)X
+2921(a)X
+2977(system)X
+3219(crash.)X
+3 f
+555 4708(3.2.2.)N
+775(The)X
+928(Buffer)X
+1171(Manager)X
+1 f
+755 4831(The)N
+3 f
+912(Buffer)X
+1167(Manager)X
+1 f
+1511(uses)X
+1681(a)X
+1749(pool)X
+1923(of)X
+2022(shared)X
+2264(memory)X
+2563(to)X
+2657(provide)X
+2934(a)X
+3002(least-recently-used)X
+3641(\(LRU\))X
+3886(block)X
+4095(cache.)X
+555 4921(Although)N
+886(the)X
+1013(current)X
+1270(library)X
+1513(provides)X
+1818(an)X
+1923(LRU)X
+2112(cache,)X
+2345(it)X
+2418(would)X
+2647(be)X
+2752(simple)X
+2994(to)X
+3085(add)X
+3229(alternate)X
+3534(replacement)X
+3955(policies)X
+4232(as)X
+555 5011(suggested)N
+903(by)X
+1015([CHOU85])X
+1408(or)X
+1507(to)X
+1601(provide)X
+1878(multiple)X
+2176(buffer)X
+2405(pools)X
+2610(with)X
+2784(different)X
+3092(policies.)X
+3412(Transactions)X
+3853(request)X
+4116(pages)X
+555 5101(from)N
+736(the)X
+859(buffer)X
+1081(manager)X
+1383(and)X
+1524(keep)X
+1701(them)X
+3 f
+1886(pinned)X
+1 f
+2145(to)X
+2232(ensure)X
+2466(that)X
+2610(they)X
+2772(are)X
+2895(not)X
+3021(written)X
+3272(to)X
+3358(disk)X
+3515(while)X
+3717(they)X
+3879(are)X
+4002(in)X
+4088(a)X
+4148(logi-)X
+555 5191(cally)N
+732(inconsistent)X
+1135(state.)X
+1343(When)X
+1556(page)X
+1729(replacement)X
+2143(is)X
+2217(necessary,)X
+2571(the)X
+3 f
+2689(Buffer)X
+2932(Manager)X
+1 f
+3264(\256nds)X
+3439(an)X
+3535(unpinned)X
+3853(page)X
+4025(and)X
+4161(then)X
+555 5281(checks)N
+794(with)X
+956(the)X
+3 f
+1074(Log)X
+1227(Manager)X
+1 f
+1559(to)X
+1641(ensure)X
+1871(that)X
+2011(the)X
+2129(write-ahead)X
+2529(protocol)X
+2816(is)X
+2889(enforced.)X
+3 f
+555 5467(3.2.3.)N
+775(The)X
+928(Lock)X
+1121(Manager)X
+1 f
+755 5590(The)N
+3 f
+901(Lock)X
+1095(Manager)X
+1 f
+1428(supports)X
+1720(general)X
+1978(purpose)X
+2253(locking)X
+2514(\(single)X
+2753(writer,)X
+2986(multiple)X
+3273(readers\))X
+3553(which)X
+3769(is)X
+3842(currently)X
+4152(used)X
+555 5680(to)N
+638(provide)X
+904(two-phase)X
+1254(locking)X
+1514(and)X
+1650(high)X
+1812(concurrency)X
+2230(B-tree)X
+2451(locking.)X
+2751(However,)X
+3086(the)X
+3204(general)X
+3461(purpose)X
+3735(nature)X
+3956(of)X
+4043(the)X
+4161(lock)X
+
+6 p
+%%Page: 6 6
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+555 630(manager)N
+857(provides)X
+1158(the)X
+1281(ability)X
+1510(to)X
+1597(support)X
+1862(a)X
+1923(variety)X
+2171(of)X
+2263(locking)X
+2528(protocols.)X
+2890(Currently,)X
+3241(all)X
+3345(locks)X
+3538(are)X
+3661(issued)X
+3885(at)X
+3967(the)X
+4089(granu-)X
+555 720(larity)N
+747(of)X
+837(a)X
+896(page)X
+1071(\(the)X
+1219(size)X
+1367(of)X
+1457(a)X
+1516(buffer)X
+1736(in)X
+1821(the)X
+1942(buffer)X
+2161(pool\))X
+2352(which)X
+2570(is)X
+2645(identi\256ed)X
+2969(by)X
+3071(two)X
+3213(4-byte)X
+3440(integers)X
+3716(\(a)X
+3801(\256le)X
+3925(id)X
+4009(and)X
+4147(page)X
+555 810(number\).)N
+898(This)X
+1071(provides)X
+1378(the)X
+1507(necessary)X
+1851(information)X
+2259(to)X
+2351(extend)X
+2595(the)X
+3 f
+2723(Lock)X
+2926(Manager)X
+1 f
+3268(to)X
+3360(perform)X
+3649(hierarchical)X
+4059(locking)X
+555 900([GRAY76].)N
+982(The)X
+1133(current)X
+1387(implementation)X
+1915(does)X
+2088(not)X
+2216(support)X
+2482(locks)X
+2677(at)X
+2760(other)X
+2950(granularities)X
+3376(and)X
+3517(does)X
+3689(not)X
+3816(promote)X
+4108(locks;)X
+555 990(these)N
+740(are)X
+859(obvious)X
+1132(future)X
+1344(additions)X
+1657(to)X
+1739(the)X
+1857(system.)X
+755 1113(If)N
+831(an)X
+929(incoming)X
+1253(lock)X
+1413(request)X
+1667(cannot)X
+1903(be)X
+2001(granted,)X
+2284(the)X
+2404(requesting)X
+2760(process)X
+3023(is)X
+3098(queued)X
+3352(for)X
+3467(the)X
+3586(lock)X
+3745(and)X
+3882(descheduled.)X
+555 1203(When)N
+769(a)X
+827(lock)X
+987(is)X
+1062(released,)X
+1368(the)X
+1488(wait)X
+1647(queue)X
+1860(is)X
+1934(traversed)X
+2250(and)X
+2387(any)X
+2524(newly)X
+2741(compatible)X
+3118(locks)X
+3308(are)X
+3428(granted.)X
+3730(Locks)X
+3947(are)X
+4067(located)X
+555 1293(via)N
+680(a)X
+743(\256le)X
+872(and)X
+1015(page)X
+1194(hash)X
+1368(table)X
+1551(and)X
+1694(are)X
+1820(chained)X
+2097(both)X
+2266(by)X
+2373(object)X
+2595(and)X
+2737(by)X
+2843(transaction,)X
+3241(facilitating)X
+3614(rapid)X
+3805(traversal)X
+4108(of)X
+4201(the)X
+555 1383(lock)N
+713(table)X
+889(during)X
+1118(transaction)X
+1490(commit)X
+1754(and)X
+1890(abort.)X
+755 1506(The)N
+907(primary)X
+1188(interfaces)X
+1528(to)X
+1617(the)X
+1742(lock)X
+1907(manager)X
+2211(are)X
+2 f
+2337(lock)X
+1 f
+2471(,)X
+2 f
+2518(unlock)X
+1 f
+2732(,)X
+2779(and)X
+2 f
+2922(lock_unlock_all)X
+1 f
+3434(.)X
+2 f
+3500(Lock)X
+1 f
+3682(obtains)X
+3939(a)X
+4001(new)X
+4161(lock)X
+555 1596(for)N
+680(a)X
+747(speci\256c)X
+1023(object.)X
+1290(There)X
+1509(are)X
+1638(also)X
+1797(two)X
+1947(variants)X
+2231(of)X
+2328(the)X
+2 f
+2456(lock)X
+1 f
+2620(request,)X
+2 f
+2902(lock_upgrade)X
+1 f
+3373(and)X
+2 f
+3519(lock_downgrade)X
+1 f
+4053(,)X
+4103(which)X
+555 1686(allow)N
+755(the)X
+875(caller)X
+1076(to)X
+1160(atomically)X
+1519(trade)X
+1701(a)X
+1758(lock)X
+1917(of)X
+2005(one)X
+2142(type)X
+2301(for)X
+2416(a)X
+2473(lock)X
+2632(of)X
+2720(another.)X
+2 f
+3022(Unlock)X
+1 f
+3275(releases)X
+3551(a)X
+3608(speci\256c)X
+3874(mode)X
+4073(of)X
+4161(lock)X
+555 1776(on)N
+655(a)X
+711(speci\256c)X
+976(object.)X
+2 f
+1232(Lock_unlock_all)X
+1 f
+1786(releases)X
+2061(all)X
+2161(the)X
+2279(locks)X
+2468(associated)X
+2818(with)X
+2980(a)X
+3036(speci\256c)X
+3301(transaction.)X
+3 f
+555 1962(3.2.4.)N
+775(The)X
+928(Process)X
+1207(Manager)X
+1 f
+755 2085(The)N
+3 f
+900(Process)X
+1179(Manager)X
+1 f
+1511(acts)X
+1656(as)X
+1743(a)X
+1799(user-level)X
+2136(scheduler)X
+2464(to)X
+2546(make)X
+2740(processes)X
+3068(wait)X
+3226(on)X
+3326(unavailable)X
+3716(locks)X
+3905(and)X
+4041(pending)X
+555 2175(buffer)N
+778(cache)X
+988(I/O.)X
+1161(For)X
+1297(each)X
+1470(process,)X
+1756(a)X
+1817(semaphore)X
+2190(is)X
+2268(maintained)X
+2649(upon)X
+2834(which)X
+3055(that)X
+3200(process)X
+3466(waits)X
+3660(when)X
+3859(it)X
+3928(needs)X
+4136(to)X
+4223(be)X
+555 2265(descheduled.)N
+1014(When)X
+1228(a)X
+1286(process)X
+1549(needs)X
+1754(to)X
+1838(be)X
+1936(run,)X
+2084(its)X
+2180(semaphore)X
+2549(is)X
+2623(cleared,)X
+2897(and)X
+3034(the)X
+3153(operating)X
+3477(system)X
+3720(reschedules)X
+4116(it.)X
+4201(No)X
+555 2355(sophisticated)N
+1002(scheduling)X
+1378(algorithm)X
+1718(is)X
+1799(applied;)X
+2085(if)X
+2162(the)X
+2288(lock)X
+2454(for)X
+2576(which)X
+2800(a)X
+2864(process)X
+3133(was)X
+3286(waiting)X
+3554(becomes)X
+3863(available,)X
+4201(the)X
+555 2445(process)N
+824(is)X
+905(made)X
+1107(runnable.)X
+1456(It)X
+1533(would)X
+1761(have)X
+1941(been)X
+2121(possible)X
+2411(to)X
+2501(change)X
+2757(the)X
+2883(kernel's)X
+3170(process)X
+3439(scheduler)X
+3775(to)X
+3865(interact)X
+4134(more)X
+555 2535(ef\256ciently)N
+900(with)X
+1062(the)X
+1180(lock)X
+1338(manager,)X
+1655(but)X
+1777(doing)X
+1979(so)X
+2070(would)X
+2290(have)X
+2462(compromised)X
+2918(our)X
+3045(commitment)X
+3469(to)X
+3551(a)X
+3607(user-level)X
+3944(package.)X
+3 f
+555 2721(3.2.5.)N
+775(The)X
+928(Transaction)X
+1361(Manager)X
+1 f
+755 2844(The)N
+3 f
+901(Transaction)X
+1335(Manager)X
+1 f
+1668(provides)X
+1965(the)X
+2084(standard)X
+2377(interface)X
+2680(of)X
+2 f
+2768(txn_begin)X
+1 f
+3084(,)X
+2 f
+3125(txn_commit)X
+1 f
+3499(,)X
+3540(and)X
+2 f
+3676(txn_abort)X
+1 f
+3987(.)X
+4047(It)X
+4116(keeps)X
+555 2934(track)N
+742(of)X
+835(all)X
+941(active)X
+1159(transactions,)X
+1588(assigns)X
+1845(unique)X
+2089(transaction)X
+2467(identi\256ers,)X
+2833(and)X
+2974(directs)X
+3213(the)X
+3336(abort)X
+3526(and)X
+3667(commit)X
+3936(processing.)X
+555 3024(When)N
+772(a)X
+2 f
+833(txn_begin)X
+1 f
+1174(is)X
+1252(issued,)X
+1497(the)X
+3 f
+1620(Transaction)X
+2058(Manager)X
+1 f
+2395(assigns)X
+2651(the)X
+2773(next)X
+2935(available)X
+3249(transaction)X
+3625(identi\256er,)X
+3958(allocates)X
+4263(a)X
+555 3114(per-process)N
+948(transaction)X
+1322(structure)X
+1625(in)X
+1709(shared)X
+1941(memory,)X
+2249(increments)X
+2622(the)X
+2741(count)X
+2940(of)X
+3028(active)X
+3241(transactions,)X
+3665(and)X
+3802(returns)X
+4046(the)X
+4165(new)X
+555 3204(transaction)N
+937(identi\256er)X
+1256(to)X
+1348(the)X
+1476(calling)X
+1724(process.)X
+2034(The)X
+2188(in-memory)X
+2573(transaction)X
+2954(structure)X
+3264(contains)X
+3560(a)X
+3625(pointer)X
+3881(into)X
+4034(the)X
+4161(lock)X
+555 3294(table)N
+734(for)X
+851(locks)X
+1043(held)X
+1204(by)X
+1307(this)X
+1445(transaction,)X
+1840(the)X
+1961(last)X
+2095(log)X
+2220(sequence)X
+2538(number,)X
+2826(a)X
+2885(transaction)X
+3260(state)X
+3430(\()X
+2 f
+3457(idle)X
+1 f
+(,)S
+2 f
+3620(running)X
+1 f
+3873(,)X
+2 f
+3915(aborting)X
+1 f
+4190(,)X
+4232(or)X
+2 f
+555 3384(committing\))N
+1 f
+942(,)X
+982(an)X
+1078(error)X
+1255(code,)X
+1447(and)X
+1583(a)X
+1639(semaphore)X
+2007(identi\256er.)X
+755 3507(At)N
+859(commit,)X
+1147(the)X
+3 f
+1269(Transaction)X
+1706(Manager)X
+1 f
+2042(calls)X
+2 f
+2213(log_commit)X
+1 f
+2615(to)X
+2700(record)X
+2929(the)X
+3050(end)X
+3189(of)X
+3279(transaction)X
+3654(and)X
+3793(to)X
+3878(\257ush)X
+4056(the)X
+4177(log.)X
+555 3597(Then)N
+743(it)X
+810(directs)X
+1047(the)X
+3 f
+1168(Lock)X
+1364(Manager)X
+1 f
+1699(to)X
+1784(release)X
+2031(all)X
+2134(locks)X
+2325(associated)X
+2677(with)X
+2841(the)X
+2961(given)X
+3161(transaction.)X
+3575(If)X
+3651(a)X
+3709(transaction)X
+4083(aborts,)X
+555 3687(the)N
+3 f
+680(Transaction)X
+1120(Manager)X
+1 f
+1459(calls)X
+1633(on)X
+2 f
+1739(log_unroll)X
+1 f
+2102(to)X
+2190(read)X
+2355(the)X
+2479(transaction's)X
+2915(log)X
+3043(records)X
+3306(and)X
+3448(undo)X
+3634(any)X
+3776(modi\256cations)X
+4237(to)X
+555 3777(the)N
+673(database.)X
+1010(As)X
+1119(in)X
+1201(the)X
+1319(commit)X
+1583(case,)X
+1762(it)X
+1826(then)X
+1984(calls)X
+2 f
+2151(lock_unlock_all)X
+1 f
+2683(to)X
+2765(release)X
+3009(the)X
+3127(transaction's)X
+3557(locks.)X
+3 f
+555 3963(3.2.6.)N
+775(The)X
+928(Record)X
+1198(Manager)X
+1 f
+755 4086(The)N
+3 f
+919(Record)X
+1208(Manager)X
+1 f
+1559(supports)X
+1869(the)X
+2006(abstraction)X
+2397(of)X
+2503(reading)X
+2783(and)X
+2938(writing)X
+3208(records)X
+3484(to)X
+3585(a)X
+3660(database.)X
+3996(We)X
+4147(have)X
+555 4176(modi\256ed)N
+861(the)X
+981(the)X
+1101(database)X
+1399(access)X
+1626(routines)X
+3 f
+1905(db)X
+1 f
+1993(\(3\))X
+2108([BSD91])X
+2418(to)X
+2501(call)X
+2638(the)X
+2757(log,)X
+2900(lock,)X
+3079(and)X
+3216(buffer)X
+3434(managers.)X
+3803(In)X
+3891(order)X
+4082(to)X
+4165(pro-)X
+555 4266(vide)N
+718(functionality)X
+1152(to)X
+1239(perform)X
+1523(undo)X
+1708(and)X
+1849(redo,)X
+2037(the)X
+3 f
+2160(Record)X
+2434(Manager)X
+1 f
+2770(de\256nes)X
+3021(a)X
+3081(collection)X
+3421(of)X
+3512(log)X
+3638(record)X
+3868(types)X
+4061(and)X
+4201(the)X
+555 4356(associated)N
+920(undo)X
+1115(and)X
+1266(redo)X
+1444(routines.)X
+1777(The)X
+3 f
+1937(Log)X
+2105(Manager)X
+1 f
+2452(performs)X
+2777(a)X
+2848(table)X
+3039(lookup)X
+3296(on)X
+3411(the)X
+3543(record)X
+3783(type)X
+3955(to)X
+4051(call)X
+4201(the)X
+555 4446(appropriate)N
+951(routines.)X
+1299(For)X
+1440(example,)X
+1762(the)X
+1890(B-tree)X
+2121(access)X
+2356(method)X
+2625(requires)X
+2913(two)X
+3062(log)X
+3193(record)X
+3428(types:)X
+3648(insert)X
+3855(and)X
+4000(delete.)X
+4241(A)X
+555 4536(replace)N
+808(operation)X
+1131(is)X
+1204(implemented)X
+1642(as)X
+1729(a)X
+1785(delete)X
+1997(followed)X
+2302(by)X
+2402(an)X
+2498(insert)X
+2696(and)X
+2832(is)X
+2905(logged)X
+3143(accordingly.)X
+3 f
+555 4722(3.3.)N
+715(Application)X
+1134(Architectures)X
+1 f
+755 4845(The)N
+907(structure)X
+1215(of)X
+1309(LIBTP)X
+1558(allows)X
+1794(application)X
+2177(designers)X
+2507(to)X
+2596(trade)X
+2784(off)X
+2905(performance)X
+3339(and)X
+3481(protection.)X
+3872(Since)X
+4076(a)X
+4138(large)X
+555 4935(portion)N
+810(of)X
+901(LIBTP's)X
+1205(functionality)X
+1638(is)X
+1715(provided)X
+2024(by)X
+2128(managing)X
+2468(structures)X
+2804(in)X
+2889(shared)X
+3122(memory,)X
+3432(its)X
+3530(structures)X
+3865(are)X
+3987(subject)X
+4237(to)X
+555 5025(corruption)N
+926(by)X
+1043(applications)X
+1467(when)X
+1678(the)X
+1813(library)X
+2064(is)X
+2154(linked)X
+2391(directly)X
+2673(with)X
+2852(the)X
+2987(application.)X
+3420(For)X
+3568(this)X
+3720(reason,)X
+3987(LIBTP)X
+4246(is)X
+555 5115(designed)N
+864(to)X
+950(allow)X
+1152(compilation)X
+1558(into)X
+1706(a)X
+1766(separate)X
+2053(server)X
+2273(process)X
+2537(which)X
+2756(may)X
+2917(be)X
+3016(accessed)X
+3321(via)X
+3442(a)X
+3501(socket)X
+3729(interface.)X
+4094(In)X
+4184(this)X
+555 5205(way)N
+712(LIBTP's)X
+1015(data)X
+1172(structures)X
+1507(are)X
+1629(protected)X
+1951(from)X
+2130(application)X
+2509(code,)X
+2704(but)X
+2829(communication)X
+3349(overhead)X
+3666(is)X
+3741(increased.)X
+4107(When)X
+555 5295(applications)N
+975(are)X
+1107(trusted,)X
+1377(LIBTP)X
+1631(may)X
+1801(be)X
+1909(compiled)X
+2239(directly)X
+2516(into)X
+2672(the)X
+2802(application)X
+3190(providing)X
+3533(improved)X
+3872(performance.)X
+555 5385(Figures)N
+815(two)X
+955(and)X
+1091(three)X
+1272(show)X
+1461(the)X
+1579(two)X
+1719(alternate)X
+2016(application)X
+2392(architectures.)X
+755 5508(There)N
+964(are)X
+1084(potentially)X
+1447(two)X
+1588(modes)X
+1818(in)X
+1901(which)X
+2118(one)X
+2255(might)X
+2462(use)X
+2590(LIBTP)X
+2833(in)X
+2916(a)X
+2972(server)X
+3189(based)X
+3392(architecture.)X
+3832(In)X
+3919(the)X
+4037(\256rst,)X
+4201(the)X
+555 5598(server)N
+778(would)X
+1004(provide)X
+1275(the)X
+1399(capability)X
+1741(to)X
+1829(respond)X
+2109(to)X
+2197(requests)X
+2486(to)X
+2574(each)X
+2747(of)X
+2839(the)X
+2962(low)X
+3107(level)X
+3288(modules)X
+3584(\(lock,)X
+3794(log,)X
+3941(buffer,)X
+4183(and)X
+555 5688(transaction)N
+944(managers\).)X
+1356(Unfortunately,)X
+1863(the)X
+1998(performance)X
+2442(of)X
+2546(such)X
+2730(a)X
+2803(system)X
+3062(is)X
+3152(likely)X
+3371(to)X
+3470(be)X
+3583(blindingly)X
+3947(slow)X
+4134(since)X
+
+7 p
+%%Page: 7 7
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+1 Dt
+1864 1125 MXY
+15 -26 Dl
+-15 10 Dl
+-14 -10 Dl
+14 26 Dl
+0 -266 Dl
+1315 1125 MXY
+15 -26 Dl
+-15 10 Dl
+-14 -10 Dl
+14 26 Dl
+0 -266 Dl
+3 Dt
+1133 1125 MXY
+0 798 Dl
+931 0 Dl
+0 -798 Dl
+-931 0 Dl
+1 Dt
+1266 1257 MXY
+0 133 Dl
+665 0 Dl
+0 -133 Dl
+-665 0 Dl
+3 f
+8 s
+1513 1351(driver)N
+1502 1617(LIBTP)N
+1266 1390 MXY
+0 400 Dl
+665 0 Dl
+0 -400 Dl
+-665 0 Dl
+3 Dt
+1133 726 MXY
+0 133 Dl
+931 0 Dl
+0 -133 Dl
+-931 0 Dl
+1 f
+1029 1098(txn_abort)N
+964 1015(txn_commit)N
+1018 932(txn_begin)N
+1910 1015(db_ops)N
+3 f
+1308 820(Application)N
+1645(Program)X
+1398 1218(Server)N
+1594(Process)X
+1 f
+1390 986(socket)N
+1569(interface)X
+1 Dt
+1848 967 MXY
+-23 -14 Dl
+8 14 Dl
+-8 15 Dl
+23 -15 Dl
+-50 0 Dl
+1324 MX
+23 15 Dl
+-9 -15 Dl
+9 -14 Dl
+-23 14 Dl
+50 0 Dl
+3 Dt
+2862 859 MXY
+0 1064 Dl
+932 0 Dl
+0 -1064 Dl
+-932 0 Dl
+1 Dt
+3178 1390 MXY
+24 -12 Dl
+-17 0 Dl
+-8 -15 Dl
+1 27 Dl
+150 -265 Dl
+3494 1390 MXY
+0 -27 Dl
+-8 15 Dl
+-16 1 Dl
+24 11 Dl
+-166 -265 Dl
+3 f
+3232 1617(LIBTP)N
+2995 1390 MXY
+0 400 Dl
+666 0 Dl
+0 -400 Dl
+-666 0 Dl
+992 MY
+0 133 Dl
+666 0 Dl
+0 -133 Dl
+-666 0 Dl
+3168 1086(Application)N
+1 f
+2939 1201(txn_begin)N
+2885 1284(txn_commit)N
+2950 1368(txn_abort)N
+3465 1284(db_ops)N
+3 f
+3155 766(Single)N
+3339(Process)X
+3 Dt
+-1 Ds
+811 2100(Figure)N
+1023(2:)X
+1107(Server)X
+1318(Architecture.)X
+1 f
+1727(In)X
+1811(this)X
+1934(con\256guration,)X
+811 2190(the)N
+916(library)X
+1113(is)X
+1183(loaded)X
+1380(into)X
+1507(a)X
+1562(server)X
+1744(process)X
+1962(which)X
+2145(is)X
+2214(ac-)X
+811 2280(cessed)N
+993(via)X
+1087(a)X
+1131(socket)X
+1310(interface.)X
+3 f
+2563 2100(Figure)N
+2803(3:)X
+2914(Single)X
+3140(Process)X
+3403(Architecture.)X
+1 f
+3839(In)X
+3950(this)X
+2563 2190(con\256guration,)N
+2948(the)X
+3053(library)X
+3250(routines)X
+3483(are)X
+3587(loaded)X
+3784(as)X
+3864(part)X
+3990(of)X
+2563 2280(the)N
+2657(application)X
+2957(and)X
+3065(accessed)X
+3303(via)X
+3397(a)X
+3441(subroutine)X
+3727(interface.)X
+10 s
+10 f
+555 2403(h)N
+579(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)X
+1 f
+555 2679(modifying)N
+909(a)X
+966(piece)X
+1157(of)X
+1245(data)X
+1400(would)X
+1621(require)X
+1870(three)X
+2051(or)X
+2138(possibly)X
+2424(four)X
+2578(separate)X
+2862(communications:)X
+3433(one)X
+3569(to)X
+3651(lock)X
+3809(the)X
+3927(data,)X
+4101(one)X
+4237(to)X
+555 2769(obtain)N
+781(the)X
+905(data,)X
+1085(one)X
+1227(to)X
+1315(log)X
+1443(the)X
+1567(modi\256cation,)X
+2017(and)X
+2159(possibly)X
+2451(one)X
+2593(to)X
+2681(transmit)X
+2969(the)X
+3093(modi\256ed)X
+3403(data.)X
+3583(Figure)X
+3817(four)X
+3976(shows)X
+4201(the)X
+555 2859(relative)N
+826(performance)X
+1263(for)X
+1387(retrieving)X
+1728(a)X
+1793(single)X
+2013(record)X
+2248(using)X
+2450(the)X
+2577(record)X
+2812(level)X
+2997(call)X
+3142(versus)X
+3376(using)X
+3578(the)X
+3705(lower)X
+3917(level)X
+4102(buffer)X
+555 2949(management)N
+987(and)X
+1125(locking)X
+1387(calls.)X
+1616(The)X
+1763(2:1)X
+1887(ratio)X
+2056(observed)X
+2367(in)X
+2450(the)X
+2569(single)X
+2781(process)X
+3043(case)X
+3203(re\257ects)X
+3456(the)X
+3575(additional)X
+3916(overhead)X
+4232(of)X
+555 3039(parsing)N
+819(eight)X
+1006(commands)X
+1380(rather)X
+1595(than)X
+1760(one)X
+1903(while)X
+2108(the)X
+2233(3:1)X
+2362(ratio)X
+2536(observed)X
+2853(in)X
+2942(the)X
+3067(client/server)X
+3491(architecture)X
+3898(re\257ects)X
+4157(both)X
+555 3129(the)N
+679(parsing)X
+941(and)X
+1083(the)X
+1207(communication)X
+1731(overheard.)X
+2118(Although)X
+2445(there)X
+2631(may)X
+2794(be)X
+2895(applications)X
+3307(which)X
+3528(could)X
+3731(tolerate)X
+3997(such)X
+4169(per-)X
+555 3219(formance,)N
+904(it)X
+973(seems)X
+1194(far)X
+1309(more)X
+1499(feasible)X
+1774(to)X
+1861(support)X
+2126(a)X
+2187(higher)X
+2417(level)X
+2597(interface,)X
+2923(such)X
+3094(as)X
+3185(that)X
+3329(provided)X
+3638(by)X
+3742(a)X
+3802(query)X
+4009(language)X
+555 3309(\()N
+2 f
+582(e.g.)X
+1 f
+718(SQL)X
+889([SQL86]\).)X
+755 3432(Although)N
+1081(LIBTP)X
+1327(does)X
+1498(not)X
+1624(have)X
+1800(an)X
+1900(SQL)X
+2075(parser,)X
+2316(we)X
+2433(have)X
+2608(built)X
+2777(a)X
+2836(server)X
+3056(application)X
+3435(using)X
+3631(the)X
+3752(toolkit)X
+3983(command)X
+555 3522(language)N
+882(\(TCL\))X
+1124([OUST90].)X
+1544(The)X
+1706(server)X
+1940(supports)X
+2248(a)X
+2321(command)X
+2674(line)X
+2831(interface)X
+3150(similar)X
+3409(to)X
+3508(the)X
+3643(subroutine)X
+4017(interface)X
+555 3612(de\256ned)N
+811(in)X
+3 f
+893(db)X
+1 f
+981(\(3\).)X
+1135(Since)X
+1333(it)X
+1397(is)X
+1470(based)X
+1673(on)X
+1773(TCL,)X
+1964(it)X
+2028(provides)X
+2324(control)X
+2571(structures)X
+2903(as)X
+2990(well.)X
+3 f
+555 3798(4.)N
+655(Implementation)X
+1 f
+3 f
+555 3984(4.1.)N
+715(Locking)X
+1014(and)X
+1162(Deadlock)X
+1502(Detection)X
+1 f
+755 4107(LIBTP)N
+1007(uses)X
+1175(two-phase)X
+1535(locking)X
+1805(for)X
+1929(user)X
+2093(data.)X
+2297(Strictly)X
+2562(speaking,)X
+2897(the)X
+3024(two)X
+3173(phases)X
+3416(in)X
+3507(two-phase)X
+3866(locking)X
+4135(are)X
+4263(a)X
+3 f
+555 4197(grow)N
+1 f
+756(phase,)X
+986(during)X
+1221(which)X
+1443(locks)X
+1638(are)X
+1763(acquired,)X
+2086(and)X
+2228(a)X
+3 f
+2290(shrink)X
+1 f
+2537(phase,)X
+2766(during)X
+3001(which)X
+3223(locks)X
+3418(are)X
+3543(released.)X
+3873(No)X
+3997(lock)X
+4161(may)X
+555 4287(ever)N
+720(be)X
+822(acquired)X
+1124(during)X
+1358(the)X
+1481(shrink)X
+1706(phase.)X
+1954(The)X
+2104(grow)X
+2294(phase)X
+2502(lasts)X
+2669(until)X
+2840(the)X
+2963(\256rst)X
+3112(release,)X
+3381(which)X
+3602(marks)X
+3823(the)X
+3946(start)X
+4109(of)X
+4201(the)X
+555 4377(shrink)N
+780(phase.)X
+1028(In)X
+1120(practice,)X
+1420(the)X
+1543(grow)X
+1733(phase)X
+1941(lasts)X
+2108(for)X
+2227(the)X
+2350(duration)X
+2642(of)X
+2734(a)X
+2795(transaction)X
+3172(in)X
+3259(LIBTP)X
+3506(and)X
+3647(in)X
+3734(commercial)X
+4138(data-)X
+555 4467(base)N
+721(systems.)X
+1037(The)X
+1184(shrink)X
+1406(phase)X
+1611(takes)X
+1798(place)X
+1990(during)X
+2221(transaction)X
+2595(commit)X
+2861(or)X
+2950(abort.)X
+3177(This)X
+3341(means)X
+3568(that)X
+3710(locks)X
+3901(are)X
+4022(acquired)X
+555 4557(on)N
+655(demand)X
+929(during)X
+1158(the)X
+1276(lifetime)X
+1545(of)X
+1632(a)X
+1688(transaction,)X
+2080(and)X
+2216(held)X
+2374(until)X
+2540(commit)X
+2804(time,)X
+2986(at)X
+3064(which)X
+3280(point)X
+3464(all)X
+3564(locks)X
+3753(are)X
+3872(released.)X
+755 4680(If)N
+832(multiple)X
+1121(transactions)X
+1527(are)X
+1649(active)X
+1864(concurrently,)X
+2313(deadlocks)X
+2657(can)X
+2792(occur)X
+2994(and)X
+3133(must)X
+3311(be)X
+3410(detected)X
+3701(and)X
+3840(resolved.)X
+4174(The)X
+555 4770(lock)N
+715(table)X
+893(can)X
+1027(be)X
+1125(thought)X
+1391(of)X
+1480(as)X
+1569(a)X
+1627(representation)X
+2104(of)X
+2193(a)X
+2251(directed)X
+2532(graph.)X
+2777(The)X
+2924(nodes)X
+3133(in)X
+3216(the)X
+3335(graph)X
+3539(are)X
+3659(transactions.)X
+4103(Edges)X
+555 4860(represent)N
+878(the)X
+3 f
+1004(waits-for)X
+1 f
+1340(relation)X
+1613(between)X
+1909(transactions;)X
+2342(if)X
+2419(transaction)X
+2 f
+2799(A)X
+1 f
+2876(is)X
+2957(waiting)X
+3225(for)X
+3347(a)X
+3411(lock)X
+3577(held)X
+3743(by)X
+3851(transaction)X
+2 f
+4230(B)X
+1 f
+4279(,)X
+555 4950(then)N
+716(a)X
+775(directed)X
+1057(edge)X
+1232(exists)X
+1437(from)X
+2 f
+1616(A)X
+1 f
+1687(to)X
+2 f
+1771(B)X
+1 f
+1842(in)X
+1926(the)X
+2046(graph.)X
+2291(A)X
+2371(deadlock)X
+2683(exists)X
+2887(if)X
+2958(a)X
+3016(cycle)X
+3208(appears)X
+3476(in)X
+3560(the)X
+3680(graph.)X
+3925(By)X
+4040(conven-)X
+555 5040(tion,)N
+719(no)X
+819(transaction)X
+1191(ever)X
+1350(waits)X
+1539(for)X
+1653(a)X
+1709(lock)X
+1867(it)X
+1931(already)X
+2188(holds,)X
+2401(so)X
+2492(re\257exive)X
+2793(edges)X
+2996(are)X
+3115(impossible.)X
+755 5163(A)N
+836(distinguished)X
+1285(process)X
+1549(monitors)X
+1856(the)X
+1977(lock)X
+2138(table,)X
+2337(searching)X
+2668(for)X
+2785(cycles.)X
+3048(The)X
+3195(frequency)X
+3539(with)X
+3703(which)X
+3921(this)X
+4058(process)X
+555 5253(runs)N
+716(is)X
+792(user-settable;)X
+1243(for)X
+1360(the)X
+1481(multi-user)X
+1833(tests)X
+1998(discussed)X
+2328(in)X
+2413(section)X
+2663(5.1.2,)X
+2866(it)X
+2933(has)X
+3063(been)X
+3238(set)X
+3350(to)X
+3435(wake)X
+3628(up)X
+3731(every)X
+3932(second,)X
+4197(but)X
+555 5343(more)N
+742(sophisticated)X
+1182(schedules)X
+1516(are)X
+1636(certainly)X
+1938(possible.)X
+2261(When)X
+2474(a)X
+2531(cycle)X
+2722(is)X
+2796(detected,)X
+3105(one)X
+3242(of)X
+3330(the)X
+3449(transactions)X
+3853(in)X
+3936(the)X
+4055(cycle)X
+4246(is)X
+555 5433(nominated)N
+917(and)X
+1057(aborted.)X
+1362(When)X
+1578(the)X
+1700(transaction)X
+2076(aborts,)X
+2315(it)X
+2382(rolls)X
+2547(back)X
+2722(its)X
+2820(changes)X
+3102(and)X
+3241(releases)X
+3519(its)X
+3617(locks,)X
+3829(thereby)X
+4093(break-)X
+555 5523(ing)N
+677(the)X
+795(cycle)X
+985(in)X
+1067(the)X
+1185(graph.)X
+
+8 p
+%%Page: 8 8
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+4 Ds
+1 Dt
+1866 865 MXY
+1338 0 Dl
+1866 1031 MXY
+1338 0 Dl
+1866 1199 MXY
+1338 0 Dl
+1866 1366 MXY
+1338 0 Dl
+1866 1533 MXY
+1338 0 Dl
+1866 1701 MXY
+1338 0 Dl
+-1 Ds
+5 Dt
+1866 1868 MXY
+1338 0 Dl
+1 Dt
+1 Di
+2981 MX
+ 2981 1868 lineto
+ 2981 1575 lineto
+ 3092 1575 lineto
+ 3092 1868 lineto
+ 2981 1868 lineto
+closepath 21 2981 1575 3092 1868 Dp
+2646 MX
+ 2646 1868 lineto
+ 2646 949 lineto
+ 2758 949 lineto
+ 2758 1868 lineto
+ 2646 1868 lineto
+closepath 14 2646 949 2758 1868 Dp
+2312 MX
+ 2312 1868 lineto
+ 2312 1701 lineto
+ 2423 1701 lineto
+ 2423 1868 lineto
+ 2312 1868 lineto
+closepath 3 2312 1701 2423 1868 Dp
+1977 MX
+ 1977 1868 lineto
+ 1977 1512 lineto
+ 2089 1512 lineto
+ 2089 1868 lineto
+ 1977 1868 lineto
+closepath 19 1977 1512 2089 1868 Dp
+3 f
+2640 2047(Client/Server)N
+1957(Single)X
+2185(Process)X
+7 s
+2957 1957(record)N
+2570(component)X
+2289(record)X
+1890(components)X
+1733 1724(.1)N
+1733 1556(.2)N
+1733 1389(.3)N
+1733 1222(.4)N
+1733 1055(.5)N
+1733 889(.6)N
+1590 726(Elapsed)N
+1794(Time)X
+1613 782(\(in)N
+1693(seconds\))X
+3 Dt
+-1 Ds
+8 s
+555 2255(Figure)N
+756(4:)X
+829(Comparison)X
+1187(of)X
+1260(High)X
+1416(and)X
+1540(Low)X
+1681(Level)X
+1850(Interfaces.)X
+1 f
+2174(Elapsed)X
+2395(time)X
+2528(in)X
+2597(seconds)X
+2818(to)X
+2887(perform)X
+3111(a)X
+3158(single)X
+3330(record)X
+3511(retrieval)X
+3742(from)X
+3885(a)X
+3932(command)X
+4203(line)X
+555 2345(\(rather)N
+751(than)X
+888(a)X
+943(procedural)X
+1241(interface\))X
+1510(is)X
+1579(shown)X
+1772(on)X
+1862(the)X
+1966(y)X
+2024(axis.)X
+2185(The)X
+2310(``component'')X
+2704(numbers)X
+2950(re\257ect)X
+3135(the)X
+3239(timings)X
+3458(when)X
+3622(the)X
+3726(record)X
+3914(is)X
+3983(retrieved)X
+4235(by)X
+555 2435(separate)N
+785(calls)X
+924(to)X
+996(the)X
+1096(lock)X
+1228(manager)X
+1469(and)X
+1583(buffer)X
+1760(manager)X
+2001(while)X
+2165(the)X
+2264(``record'')X
+2531(timings)X
+2745(were)X
+2889(obtained)X
+3130(by)X
+3215(using)X
+3375(a)X
+3424(single)X
+3598(call)X
+3711(to)X
+3782(the)X
+3881(record)X
+4064(manager.)X
+555 2525(The)N
+674(2:1)X
+776(ratio)X
+913(observed)X
+1163(for)X
+1257(the)X
+1355(single)X
+1528(process)X
+1739(case)X
+1868(is)X
+1930(a)X
+1977(re\257ection)X
+2237(of)X
+2309(the)X
+2406(parsing)X
+2613(overhead)X
+2865(for)X
+2958(executing)X
+3225(eight)X
+3372(separate)X
+3599(commands)X
+3895(rather)X
+4062(than)X
+4191(one.)X
+555 2615(The)N
+673(additional)X
+948(factor)X
+1115(of)X
+1187(one)X
+1298(re\257ected)X
+1536(in)X
+1605(the)X
+1702(3:1)X
+1803(ratio)X
+1939(for)X
+2031(the)X
+2127(client/server)X
+2460(architecture)X
+2794(is)X
+2855(due)X
+2965(to)X
+3033(the)X
+3129(communication)X
+3545(overhead.)X
+3828(The)X
+3945(true)X
+4062(ratios)X
+4222(are)X
+555 2705(actually)N
+775(worse)X
+945(since)X
+1094(the)X
+1190(component)X
+1492(timings)X
+1703(do)X
+1785(not)X
+1884(re\257ect)X
+2060(the)X
+2155(search)X
+2334(times)X
+2490(within)X
+2671(each)X
+2804(page)X
+2941(or)X
+3011(the)X
+3106(time)X
+3237(required)X
+3466(to)X
+3533(transmit)X
+3760(the)X
+3855(page)X
+3992(between)X
+4221(the)X
+555 2795(two)N
+667(processes.)X
+10 s
+10 f
+555 2885(h)N
+579(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)X
+3 f
+555 3161(4.2.)N
+715(Group)X
+961(Commit)X
+1 f
+755 3284(Since)N
+959(the)X
+1083(log)X
+1211(must)X
+1392(be)X
+1494(\257ushed)X
+1751(to)X
+1839(disk)X
+1997(at)X
+2080(commit)X
+2349(time,)X
+2536(disk)X
+2694(bandwidth)X
+3057(fundamentally)X
+3545(limits)X
+3751(the)X
+3874(rate)X
+4020(at)X
+4103(which)X
+555 3374(transactions)N
+959(complete.)X
+1314(Since)X
+1513(most)X
+1688(transactions)X
+2091(write)X
+2276(only)X
+2438(a)X
+2494(few)X
+2635(small)X
+2828(records)X
+3085(to)X
+3167(the)X
+3285(log,)X
+3427(the)X
+3545(last)X
+3676(page)X
+3848(of)X
+3935(the)X
+4053(log)X
+4175(will)X
+555 3464(be)N
+658(\257ushed)X
+916(once)X
+1095(by)X
+1202(every)X
+1408(transaction)X
+1787(which)X
+2010(writes)X
+2233(to)X
+2322(it.)X
+2433(In)X
+2527(the)X
+2652(naive)X
+2853(implementation,)X
+3402(these)X
+3593(\257ushes)X
+3841(would)X
+4067(happen)X
+555 3554(serially.)N
+755 3677(LIBTP)N
+1008(uses)X
+3 f
+1177(group)X
+1412(commit)X
+1 f
+1702([DEWI84])X
+2077(in)X
+2170(order)X
+2371(to)X
+2464(amortize)X
+2775(the)X
+2903(cost)X
+3062(of)X
+3159(one)X
+3305(synchronous)X
+3740(disk)X
+3903(write)X
+4098(across)X
+555 3767(multiple)N
+851(transactions.)X
+1304(Group)X
+1539(commit)X
+1812(provides)X
+2117(a)X
+2182(way)X
+2345(for)X
+2468(a)X
+2533(group)X
+2749(of)X
+2845(transactions)X
+3257(to)X
+3348(commit)X
+3621(simultaneously.)X
+4174(The)X
+555 3857(\256rst)N
+709(several)X
+967(transactions)X
+1380(to)X
+1472(commit)X
+1745(write)X
+1939(their)X
+2115(changes)X
+2403(to)X
+2494(the)X
+2621(in-memory)X
+3006(log)X
+3137(page,)X
+3338(then)X
+3505(sleep)X
+3699(on)X
+3808(a)X
+3873(distinguished)X
+555 3947(semaphore.)N
+966(Later,)X
+1179(a)X
+1238(committing)X
+1629(transaction)X
+2004(\257ushes)X
+2249(the)X
+2370(page)X
+2545(to)X
+2630(disk,)X
+2805(and)X
+2943(wakes)X
+3166(up)X
+3268(all)X
+3370(its)X
+3467(sleeping)X
+3756(peers.)X
+3988(The)X
+4135(point)X
+555 4037(at)N
+635(which)X
+853(changes)X
+1134(are)X
+1255(actually)X
+1531(written)X
+1780(is)X
+1855(determined)X
+2238(by)X
+2340(three)X
+2523(thresholds.)X
+2914(The)X
+3061(\256rst)X
+3207(is)X
+3281(the)X
+2 f
+3400(group)X
+3612(threshold)X
+1 f
+3935(and)X
+4072(de\256nes)X
+555 4127(the)N
+674(minimum)X
+1005(number)X
+1271(of)X
+1359(transactions)X
+1763(which)X
+1979(must)X
+2154(be)X
+2250(active)X
+2462(in)X
+2544(the)X
+2662(system)X
+2904(before)X
+3130(transactions)X
+3533(are)X
+3652(forced)X
+3878(to)X
+3960(participate)X
+555 4217(in)N
+646(a)X
+711(group)X
+927(commit.)X
+1240(The)X
+1394(second)X
+1646(is)X
+1728(the)X
+2 f
+1855(wait)X
+2021(threshold)X
+1 f
+2352(which)X
+2577(is)X
+2658(expressed)X
+3003(as)X
+3098(the)X
+3224(percentage)X
+3601(of)X
+3696(active)X
+3916(transactions)X
+555 4307(waiting)N
+826(to)X
+919(be)X
+1026(committed.)X
+1439(The)X
+1595(last)X
+1737(is)X
+1821(the)X
+2 f
+1950(logdelay)X
+2257(threshold)X
+1 f
+2590(which)X
+2816(indicates)X
+3131(how)X
+3299(much)X
+3507(un\257ushed)X
+3848(log)X
+3980(should)X
+4223(be)X
+555 4397(allowed)N
+829(to)X
+911(accumulate)X
+1297(before)X
+1523(a)X
+1579(waiting)X
+1839(transaction's)X
+2289(commit)X
+2553(record)X
+2779(is)X
+2852(\257ushed.)X
+755 4520(Group)N
+981(commit)X
+1246(can)X
+1379(substantially)X
+1803(improve)X
+2090(performance)X
+2517(for)X
+2631(high-concurrency)X
+3218(environments.)X
+3714(If)X
+3788(only)X
+3950(a)X
+4006(few)X
+4147(tran-)X
+555 4610(sactions)N
+836(are)X
+957(running,)X
+1248(it)X
+1314(is)X
+1389(unlikely)X
+1673(to)X
+1757(improve)X
+2046(things)X
+2263(at)X
+2343(all.)X
+2485(The)X
+2632(crossover)X
+2962(point)X
+3148(is)X
+3223(the)X
+3343(point)X
+3529(at)X
+3609(which)X
+3827(the)X
+3947(transaction)X
+555 4700(commit)N
+823(rate)X
+968(is)X
+1045(limited)X
+1295(by)X
+1399(the)X
+1521(bandwidth)X
+1883(of)X
+1974(the)X
+2096(device)X
+2330(on)X
+2434(which)X
+2654(the)X
+2776(log)X
+2902(resides.)X
+3189(If)X
+3267(processes)X
+3599(are)X
+3722(trying)X
+3937(to)X
+4023(\257ush)X
+4201(the)X
+555 4790(log)N
+677(faster)X
+876(than)X
+1034(the)X
+1152(log)X
+1274(disk)X
+1427(can)X
+1559(accept)X
+1785(data,)X
+1959(then)X
+2117(group)X
+2324(commit)X
+2588(will)X
+2732(increase)X
+3016(the)X
+3134(commit)X
+3398(rate.)X
+3 f
+555 4976(4.3.)N
+715(Kernel)X
+971(Intervention)X
+1418(for)X
+1541(Synchronization)X
+1 f
+755 5099(Since)N
+954(LIBTP)X
+1197(uses)X
+1356(data)X
+1511(in)X
+1594(shared)X
+1825(memory)X
+2113(\()X
+2 f
+2140(e.g.)X
+1 f
+2277(the)X
+2395(lock)X
+2553(table)X
+2729(and)X
+2865(buffer)X
+3082(pool\))X
+3271(it)X
+3335(must)X
+3510(be)X
+3606(possible)X
+3888(for)X
+4002(a)X
+4058(process)X
+555 5189(to)N
+640(acquire)X
+900(exclusive)X
+1226(access)X
+1454(to)X
+1538(shared)X
+1770(data)X
+1926(in)X
+2010(order)X
+2202(to)X
+2286(prevent)X
+2549(corruption.)X
+2945(In)X
+3034(addition,)X
+3338(the)X
+3458(process)X
+3721(manager)X
+4020(must)X
+4197(put)X
+555 5279(processes)N
+886(to)X
+971(sleep)X
+1159(when)X
+1356(the)X
+1477(lock)X
+1638(or)X
+1728(buffer)X
+1948(they)X
+2109(request)X
+2364(is)X
+2440(in)X
+2525(use)X
+2655(by)X
+2758(some)X
+2950(other)X
+3138(process.)X
+3441(In)X
+3530(the)X
+3650(LIBTP)X
+3894(implementa-)X
+555 5385(tion)N
+705(under)X
+914(Ultrix)X
+1131(4.0)X
+7 s
+5353(2)Y
+10 s
+5385(,)Y
+1305(we)X
+1424(use)X
+1556(System)X
+1816(V)X
+1899(semaphores)X
+2303(to)X
+2390(provide)X
+2660(this)X
+2800(synchronization.)X
+3377(Semaphores)X
+3794(implemented)X
+4237(in)X
+555 5475(this)N
+701(fashion)X
+968(turn)X
+1128(out)X
+1261(to)X
+1354(be)X
+1461(an)X
+1568(expensive)X
+1920(choice)X
+2161(for)X
+2285(synchronization,)X
+2847(because)X
+3132(each)X
+3310(access)X
+3546(traps)X
+3732(to)X
+3824(the)X
+3952(kernel)X
+4183(and)X
+8 s
+10 f
+555 5547(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)N
+5 s
+1 f
+727 5625(2)N
+8 s
+763 5650(Ultrix)N
+932(and)X
+1040(DEC)X
+1184(are)X
+1277(trademarks)X
+1576(of)X
+1645(Digital)X
+1839(Equipment)X
+2136(Corporation.)X
+
+9 p
+%%Page: 9 9
+8 s 8 xH 0 xS 1 f
+10 s
+3 f
+1 f
+555 630(executes)N
+852(atomically)X
+1210(there.)X
+755 753(On)N
+878(architectures)X
+1314(that)X
+1459(support)X
+1724(atomic)X
+1967(test-and-set,)X
+2382(a)X
+2443(much)X
+2646(better)X
+2854(choice)X
+3089(would)X
+3314(be)X
+3415(to)X
+3502(attempt)X
+3767(to)X
+3854(obtain)X
+4079(a)X
+4139(spin-)X
+555 843(lock)N
+714(with)X
+877(a)X
+934(test-and-set,)X
+1345(and)X
+1482(issue)X
+1663(a)X
+1720(system)X
+1963(call)X
+2100(only)X
+2263(if)X
+2333(the)X
+2452(spinlock)X
+2744(is)X
+2818(unavailable.)X
+3249(Since)X
+3447(virtually)X
+3738(all)X
+3838(semaphores)X
+4237(in)X
+555 933(LIBTP)N
+801(are)X
+924(uncontested)X
+1330(and)X
+1469(are)X
+1591(held)X
+1752(for)X
+1869(very)X
+2035(short)X
+2218(periods)X
+2477(of)X
+2567(time,)X
+2752(this)X
+2890(would)X
+3113(improve)X
+3403(performance.)X
+3873(For)X
+4007(example,)X
+555 1023(processes)N
+885(must)X
+1062(acquire)X
+1321(exclusive)X
+1646(access)X
+1874(to)X
+1958(buffer)X
+2177(pool)X
+2341(metadata)X
+2653(in)X
+2737(order)X
+2929(to)X
+3013(\256nd)X
+3159(and)X
+3297(pin)X
+3421(a)X
+3479(buffer)X
+3698(in)X
+3781(shared)X
+4012(memory.)X
+555 1113(This)N
+721(semaphore)X
+1093(is)X
+1170(requested)X
+1502(most)X
+1681(frequently)X
+2034(in)X
+2119(LIBTP.)X
+2404(However,)X
+2742(once)X
+2917(it)X
+2984(is)X
+3060(acquired,)X
+3380(only)X
+3545(a)X
+3604(few)X
+3748(instructions)X
+4144(must)X
+555 1203(be)N
+656(executed)X
+966(before)X
+1196(it)X
+1264(is)X
+1341(released.)X
+1669(On)X
+1791(one)X
+1931(architecture)X
+2335(for)X
+2453(which)X
+2673(we)X
+2791(were)X
+2972(able)X
+3130(to)X
+3216(gather)X
+3441(detailed)X
+3719(pro\256ling)X
+4018(informa-)X
+555 1293(tion,)N
+729(the)X
+857(cost)X
+1015(of)X
+1111(the)X
+1238(semaphore)X
+1615(calls)X
+1791(accounted)X
+2146(for)X
+2269(25%)X
+2445(of)X
+2541(the)X
+2668(total)X
+2839(time)X
+3010(spent)X
+3208(updating)X
+3517(the)X
+3644(metadata.)X
+4003(This)X
+4174(was)X
+555 1383(fairly)N
+749(consistent)X
+1089(across)X
+1310(most)X
+1485(of)X
+1572(the)X
+1690(critical)X
+1933(sections.)X
+755 1506(In)N
+848(an)X
+950(attempt)X
+1216(to)X
+1304(quantify)X
+1597(the)X
+1720(overhead)X
+2040(of)X
+2132(kernel)X
+2358(synchronization,)X
+2915(we)X
+3034(ran)X
+3162(tests)X
+3329(on)X
+3434(a)X
+3495(version)X
+3756(of)X
+3848(4.3BSD-Reno)X
+555 1596(which)N
+786(had)X
+937(been)X
+1123(modi\256ed)X
+1441(to)X
+1537(support)X
+1811(binary)X
+2050(semaphore)X
+2432(facilities)X
+2742(similar)X
+2998(to)X
+3094(those)X
+3297(described)X
+3639(in)X
+3735([POSIX91].)X
+4174(The)X
+555 1686(hardware)N
+880(platform)X
+1181(consisted)X
+1504(of)X
+1595(an)X
+1695(HP300)X
+1941(\(33MHz)X
+2237(MC68030\))X
+2612(workstation)X
+3014(with)X
+3180(16MBytes)X
+3537(of)X
+3628(main)X
+3812(memory,)X
+4123(and)X
+4263(a)X
+555 1776(600MByte)N
+920(HP7959)X
+1205(SCSI)X
+1396(disk)X
+1552(\(17)X
+1682(ms)X
+1798(average)X
+2072(seek)X
+2237(time\).)X
+2468(We)X
+2602(ran)X
+2727(three)X
+2910(sets)X
+3052(of)X
+3141(comparisons)X
+3568(which)X
+3786(are)X
+3907(summarized)X
+555 1866(in)N
+645(\256gure)X
+860(\256ve.)X
+1028(In)X
+1123(each)X
+1299(comparison)X
+1701(we)X
+1823(ran)X
+1954(two)X
+2102(tests,)X
+2292(one)X
+2436(using)X
+2637(hardware)X
+2965(spinlocks)X
+3295(and)X
+3438(the)X
+3563(other)X
+3755(using)X
+3955(kernel)X
+4183(call)X
+555 1956(synchronization.)N
+1135(Since)X
+1341(the)X
+1467(test)X
+1606(was)X
+1758(run)X
+1892(single-user,)X
+2291(none)X
+2474(of)X
+2568(the)X
+2693(the)X
+2818(locks)X
+3014(were)X
+3198(contested.)X
+3568(In)X
+3662(the)X
+3787(\256rst)X
+3938(two)X
+4085(sets)X
+4232(of)X
+555 2046(tests,)N
+743(we)X
+863(ran)X
+992(the)X
+1116(full)X
+1253(transaction)X
+1631(processing)X
+2000(benchmark)X
+2383(described)X
+2717(in)X
+2805(section)X
+3058(5.1.)X
+3223(In)X
+3315(one)X
+3456(case)X
+3620(we)X
+3739(ran)X
+3867(with)X
+4034(both)X
+4201(the)X
+555 2136(database)N
+854(and)X
+992(log)X
+1116(on)X
+1218(the)X
+1338(same)X
+1525(disk)X
+1680(\(1)X
+1769(Disk\))X
+1969(and)X
+2107(in)X
+2191(the)X
+2311(second,)X
+2576(we)X
+2692(ran)X
+2817(with)X
+2981(the)X
+3101(database)X
+3400(and)X
+3538(log)X
+3661(on)X
+3762(separate)X
+4047(disks)X
+4232(\(2)X
+555 2226(Disk\).)N
+800(In)X
+894(the)X
+1019(last)X
+1157(test,)X
+1315(we)X
+1436(wanted)X
+1695(to)X
+1784(create)X
+2004(a)X
+2067(CPU)X
+2249(bound)X
+2476(environment,)X
+2928(so)X
+3026(we)X
+3146(used)X
+3319(a)X
+3381(database)X
+3684(small)X
+3883(enough)X
+4145(to)X
+4233(\256t)X
+555 2316(completely)N
+941(in)X
+1033(the)X
+1161(cache)X
+1375(and)X
+1521(issued)X
+1751(read-only)X
+2089(transactions.)X
+2541(The)X
+2695(results)X
+2933(in)X
+3024(\256gure)X
+3240(\256ve)X
+3389(express)X
+3659(the)X
+3786(kernel)X
+4016(call)X
+4161(syn-)X
+555 2406(chronization)N
+980(performance)X
+1411(as)X
+1502(a)X
+1562(percentage)X
+1935(of)X
+2026(the)X
+2148(spinlock)X
+2443(performance.)X
+2914(For)X
+3049(example,)X
+3365(in)X
+3451(the)X
+3573(1)X
+3637(disk)X
+3794(case,)X
+3977(the)X
+4098(kernel)X
+555 2496(call)N
+697(implementation)X
+1225(achieved)X
+1537(4.4)X
+1662(TPS)X
+1824(\(transactions)X
+2259(per)X
+2387(second\))X
+2662(while)X
+2865(the)X
+2988(semaphore)X
+3361(implementation)X
+3888(achieved)X
+4199(4.6)X
+555 2586(TPS,)N
+735(and)X
+874(the)X
+995(relative)X
+1259(performance)X
+1689(of)X
+1779(the)X
+1900(kernel)X
+2123(synchronization)X
+2657(is)X
+2732(96%)X
+2901(that)X
+3043(of)X
+3132(the)X
+3252(spinlock)X
+3545(\(100)X
+3714(*)X
+3776(4.4)X
+3898(/)X
+3942(4.6\).)X
+4111(There)X
+555 2676(are)N
+674(two)X
+814(striking)X
+1078(observations)X
+1503(from)X
+1679(these)X
+1864(results:)X
+10 f
+635 2799(g)N
+1 f
+755(even)X
+927(when)X
+1121(the)X
+1239(system)X
+1481(is)X
+1554(disk)X
+1707(bound,)X
+1947(the)X
+2065(CPU)X
+2240(cost)X
+2389(of)X
+2476(synchronization)X
+3008(is)X
+3081(noticeable,)X
+3451(and)X
+10 f
+635 2922(g)N
+1 f
+755(when)X
+949(we)X
+1063(are)X
+1182(CPU)X
+1357(bound,)X
+1597(the)X
+1715(difference)X
+2062(is)X
+2135(dramatic)X
+2436(\(67%\).)X
+3 f
+555 3108(4.4.)N
+715(Transaction)X
+1148(Protected)X
+1499(Access)X
+1747(Methods)X
+1 f
+755 3231(The)N
+903(B-tree)X
+1127(and)X
+1266(\256xed)X
+1449(length)X
+1671(recno)X
+1872(\(record)X
+2127(number\))X
+2421(access)X
+2649(methods)X
+2942(have)X
+3116(been)X
+3290(modi\256ed)X
+3596(to)X
+3680(provide)X
+3947(transaction)X
+555 3321(protection.)N
+941(Whereas)X
+1244(the)X
+1363(previously)X
+1722(published)X
+2054(interface)X
+2357(to)X
+2440(the)X
+2559(access)X
+2786(routines)X
+3065(had)X
+3202(separate)X
+3487(open)X
+3664(calls)X
+3832(for)X
+3946(each)X
+4114(of)X
+4201(the)X
+10 f
+555 3507(h)N
+579(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)X
+1 Dt
+2978 5036 MXY
+ 2978 5036 lineto
+ 2978 4662 lineto
+ 3093 4662 lineto
+ 3093 5036 lineto
+ 2978 5036 lineto
+closepath 21 2978 4662 3093 5036 Dp
+2518 MX
+ 2518 5036 lineto
+ 2518 3960 lineto
+ 2633 3960 lineto
+ 2633 5036 lineto
+ 2518 5036 lineto
+closepath 3 2518 3960 2633 5036 Dp
+2059 MX
+ 2059 5036 lineto
+ 2059 3946 lineto
+ 2174 3946 lineto
+ 2174 5036 lineto
+ 2059 5036 lineto
+closepath 1 2059 3946 2174 5036 Dp
+3 f
+7 s
+2912 5141(Read-only)N
+1426 3767(of)N
+1487(Spinlock)X
+1710(Throughput)X
+1480 3710(Throughput)N
+1786(as)X
+1850(a)X
+1892(%)X
+11 s
+1670 4843(20)N
+1670 4614(40)N
+1670 4384(60)N
+1670 4155(80)N
+1648 3925(100)N
+7 s
+2041 5141(1)N
+2083(Disk)X
+2490(2)X
+2532(Disks)X
+5 Dt
+1829 5036 MXY
+1494 0 Dl
+4 Ds
+1 Dt
+1829 4806 MXY
+1494 0 Dl
+1829 4577 MXY
+1494 0 Dl
+1829 4347 MXY
+1494 0 Dl
+1829 4118 MXY
+1494 0 Dl
+1829 3888 MXY
+1494 0 Dl
+3 Dt
+-1 Ds
+8 s
+555 5360(Figure)N
+753(5:)X
+823(Kernel)X
+1028(Overhead)X
+1315(for)X
+1413(System)X
+1625(Call)X
+1756(Synchronization.)X
+1 f
+2254(The)X
+2370(performance)X
+2708(of)X
+2778(the)X
+2873(kernel)X
+3049(call)X
+3158(synchronization)X
+3583(is)X
+3643(expressed)X
+3911(as)X
+3980(a)X
+4024(percentage)X
+555 5450(of)N
+625(the)X
+720(spinlock)X
+954(synchronization)X
+1379(performance.)X
+1749(In)X
+1819(disk)X
+1943(bound)X
+2120(cases)X
+2271(\(1)X
+2341(Disk)X
+2479(and)X
+2588(2)X
+2637(Disks\),)X
+2837(we)X
+2928(see)X
+3026(that)X
+3139(4-6%)X
+3294(of)X
+3364(the)X
+3459(performance)X
+3797(is)X
+3857(lost)X
+3966(due)X
+4074(to)X
+4140(kernel)X
+555 5540(calls)N
+688(while)X
+846(in)X
+912(the)X
+1006(CPU)X
+1147(bound)X
+1323(case,)X
+1464(we)X
+1554(have)X
+1690(lost)X
+1799(67%)X
+1932(of)X
+2001(the)X
+2095(performance)X
+2432(due)X
+2540(to)X
+2606(kernel)X
+2781(calls.)X
+
+10 p
+%%Page: 10 10
+8 s 8 xH 0 xS 1 f
+10 s
+3 f
+1 f
+555 630(access)N
+781(methods,)X
+1092(we)X
+1206(now)X
+1364(have)X
+1536(an)X
+1632(integrated)X
+1973(open)X
+2149(call)X
+2285(with)X
+2447(the)X
+2565(following)X
+2896(calling)X
+3134(conventions:)X
+7 f
+715 753(DB)N
+859(*dbopen)X
+1243(\(const)X
+1579(char)X
+1819(*file,)X
+2155(int)X
+2347(flags,)X
+2683(int)X
+2875(mode,)X
+3163(DBTYPE)X
+3499(type,)X
+1291 843(int)N
+1483(dbflags,)X
+1915(const)X
+2203(void)X
+2443(*openinfo\))X
+1 f
+555 966(where)N
+2 f
+774(\256le)X
+1 f
+894(is)X
+969(the)X
+1089(name)X
+1285(of)X
+1374(the)X
+1494(\256le)X
+1618(being)X
+1818(opened,)X
+2 f
+2092(\257ags)X
+1 f
+2265(and)X
+2 f
+2402(mode)X
+1 f
+2597(are)X
+2717(the)X
+2836(standard)X
+3129(arguments)X
+3484(to)X
+3 f
+3567(open)X
+1 f
+3731(\(2\),)X
+2 f
+3866(type)X
+1 f
+4021(is)X
+4095(one)X
+4232(of)X
+555 1056(the)N
+680(access)X
+913(method)X
+1180(types,)X
+2 f
+1396(db\257ags)X
+1 f
+1654(indicates)X
+1966(the)X
+2091(mode)X
+2296(of)X
+2390(the)X
+2515(buffer)X
+2739(pool)X
+2907(and)X
+3049(transaction)X
+3427(protection,)X
+3798(and)X
+2 f
+3940(openinfo)X
+1 f
+4246(is)X
+555 1146(the)N
+681(access)X
+915(method)X
+1183(speci\256c)X
+1456(information.)X
+1902(Currently,)X
+2257(the)X
+2383(possible)X
+2673(values)X
+2906(for)X
+2 f
+3028(db\257ags)X
+1 f
+3287(are)X
+3414(DB_SHARED)X
+3912(and)X
+4055(DB_TP)X
+555 1236(indicating)N
+895(that)X
+1035(buffers)X
+1283(should)X
+1516(be)X
+1612(kept)X
+1770(in)X
+1852(a)X
+1908(shared)X
+2138(buffer)X
+2355(pool)X
+2517(and)X
+2653(that)X
+2793(the)X
+2911(\256le)X
+3033(should)X
+3266(be)X
+3362(transaction)X
+3734(protected.)X
+755 1359(The)N
+900(modi\256cations)X
+1355(required)X
+1643(to)X
+1725(add)X
+1861(transaction)X
+2233(protection)X
+2578(to)X
+2660(an)X
+2756(access)X
+2982(method)X
+3242(are)X
+3361(quite)X
+3541(simple)X
+3774(and)X
+3910(localized.)X
+715 1482(1.)N
+795(Replace)X
+1074(\256le)X
+2 f
+1196(open)X
+1 f
+1372(with)X
+2 f
+1534(buf_open)X
+1 f
+1832(.)X
+715 1572(2.)N
+795(Replace)X
+1074(\256le)X
+2 f
+1196(read)X
+1 f
+1363(and)X
+2 f
+1499(write)X
+1 f
+1683(calls)X
+1850(with)X
+2012(buffer)X
+2229(manager)X
+2526(calls)X
+2693(\()X
+2 f
+2720(buf_get)X
+1 f
+(,)S
+2 f
+3000(buf_unpin)X
+1 f
+3324(\).)X
+715 1662(3.)N
+795(Precede)X
+1070(buffer)X
+1287(manager)X
+1584(calls)X
+1751(with)X
+1913(an)X
+2009(appropriate)X
+2395(\(read)X
+2581(or)X
+2668(write\))X
+2880(lock)X
+3038(call.)X
+715 1752(4.)N
+795(Before)X
+1034(updates,)X
+1319(issue)X
+1499(a)X
+1555(logging)X
+1819(operation.)X
+715 1842(5.)N
+795(After)X
+985(data)X
+1139(have)X
+1311(been)X
+1483(accessed,)X
+1805(release)X
+2049(the)X
+2167(buffer)X
+2384(manager)X
+2681(pin.)X
+715 1932(6.)N
+795(Provide)X
+1064(undo/redo)X
+1409(code)X
+1581(for)X
+1695(each)X
+1863(type)X
+2021(of)X
+2108(log)X
+2230(record)X
+2456(de\256ned.)X
+555 2071(The)N
+702(following)X
+1035(code)X
+1209(fragments)X
+1552(show)X
+1743(how)X
+1903(to)X
+1987(transaction)X
+2361(protect)X
+2606(several)X
+2856(updates)X
+3123(to)X
+3206(a)X
+3263(B-tree.)X
+7 s
+3484 2039(3)N
+10 s
+3533 2071(In)N
+3621(the)X
+3740(unprotected)X
+4140(case,)X
+555 2161(an)N
+652(open)X
+829(call)X
+966(is)X
+1040(followed)X
+1346(by)X
+1447(a)X
+1504(read)X
+1664(call)X
+1801(to)X
+1884(obtain)X
+2105(the)X
+2224(meta-data)X
+2562(for)X
+2677(the)X
+2796(B-tree.)X
+3058(Instead,)X
+3331(we)X
+3446(issue)X
+3627(an)X
+3724(open)X
+3901(to)X
+3984(the)X
+4102(buffer)X
+555 2251(manager)N
+852(to)X
+934(obtain)X
+1154(a)X
+1210(\256le)X
+1332(id)X
+1414(and)X
+1550(a)X
+1606(buffer)X
+1823(request)X
+2075(to)X
+2157(obtain)X
+2377(the)X
+2495(meta-data)X
+2832(as)X
+2919(shown)X
+3148(below.)X
+7 f
+715 2374(char)N
+955(*path;)X
+715 2464(int)N
+907(fid,)X
+1147(flags,)X
+1483(len,)X
+1723(mode;)X
+715 2644(/*)N
+859(Obtain)X
+1195(a)X
+1291(file)X
+1531(id)X
+1675(with)X
+1915(which)X
+2203(to)X
+2347(access)X
+2683(the)X
+2875(buffer)X
+3211(pool)X
+3451(*/)X
+715 2734(fid)N
+907(=)X
+1003(buf_open\(path,)X
+1723(flags,)X
+2059(mode\);)X
+715 2914(/*)N
+859(Read)X
+1099(the)X
+1291(meta)X
+1531(data)X
+1771(\(page)X
+2059(0\))X
+2203(for)X
+2395(the)X
+2587(B-tree)X
+2923(*/)X
+715 3004(if)N
+859(\(tp_lock\(fid,)X
+1531(0,)X
+1675(READ_LOCK\)\))X
+1003 3094(return)N
+1339(error;)X
+715 3184(meta_data_ptr)N
+1387(=)X
+1483(buf_get\(fid,)X
+2107(0,)X
+2251(BF_PIN,)X
+2635(&len\);)X
+1 f
+555 3307(The)N
+714(BF_PIN)X
+1014(argument)X
+1350(to)X
+2 f
+1445(buf_get)X
+1 f
+1718(indicates)X
+2036(that)X
+2189(we)X
+2316(wish)X
+2500(to)X
+2595(leave)X
+2798(this)X
+2946(page)X
+3131(pinned)X
+3382(in)X
+3477(memory)X
+3777(so)X
+3881(that)X
+4034(it)X
+4111(is)X
+4197(not)X
+555 3397(swapped)N
+862(out)X
+990(while)X
+1194(we)X
+1314(are)X
+1439(accessing)X
+1772(it.)X
+1881(The)X
+2031(last)X
+2167(argument)X
+2495(to)X
+2 f
+2582(buf_get)X
+1 f
+2847(returns)X
+3095(the)X
+3218(number)X
+3488(of)X
+3580(bytes)X
+3774(on)X
+3879(the)X
+4002(page)X
+4179(that)X
+555 3487(were)N
+732(valid)X
+912(so)X
+1003(that)X
+1143(the)X
+1261(access)X
+1487(method)X
+1747(may)X
+1905(initialize)X
+2205(the)X
+2323(page)X
+2495(if)X
+2564(necessary.)X
+755 3610(Next,)N
+955(consider)X
+1251(inserting)X
+1555(a)X
+1615(record)X
+1845(on)X
+1949(a)X
+2009(particular)X
+2341(page)X
+2517(of)X
+2608(a)X
+2668(B-tree.)X
+2932(In)X
+3022(the)X
+3143(unprotected)X
+3545(case,)X
+3727(we)X
+3844(read)X
+4006(the)X
+4127(page,)X
+555 3700(call)N
+2 f
+693(_bt_insertat)X
+1 f
+1079(,)X
+1121(and)X
+1258(write)X
+1444(the)X
+1563(page.)X
+1776(Instead,)X
+2049(we)X
+2164(lock)X
+2323(the)X
+2442(page,)X
+2635(request)X
+2888(the)X
+3007(buffer,)X
+3245(log)X
+3368(the)X
+3487(change,)X
+3756(modify)X
+4008(the)X
+4127(page,)X
+555 3790(and)N
+691(release)X
+935(the)X
+1053(buffer.)X
+7 f
+715 3913(int)N
+907(fid,)X
+1147(len,)X
+1387(pageno;)X
+1867(/*)X
+2011(Identifies)X
+2539(the)X
+2731(buffer)X
+3067(*/)X
+715 4003(int)N
+907(index;)X
+1867(/*)X
+2011(Location)X
+2443(at)X
+2587(which)X
+2875(to)X
+3019(insert)X
+3355(the)X
+3547(new)X
+3739(pair)X
+3979(*/)X
+715 4093(DBT)N
+907(*keyp,)X
+1243(*datap;)X
+1867(/*)X
+2011(Key/Data)X
+2443(pair)X
+2683(to)X
+2827(be)X
+2971(inserted)X
+3403(*/)X
+715 4183(DATUM)N
+1003(*d;)X
+1867(/*)X
+2011(Key/data)X
+2443(structure)X
+2923(to)X
+3067(insert)X
+3403(*/)X
+715 4363(/*)N
+859(Lock)X
+1099(and)X
+1291(request)X
+1675(the)X
+1867(buffer)X
+2203(*/)X
+715 4453(if)N
+859(\(tp_lock\(fid,)X
+1531(pageno,)X
+1915(WRITE_LOCK\)\))X
+1003 4543(return)N
+1339(error;)X
+715 4633(buffer_ptr)N
+1243(=)X
+1339(buf_get\(fid,)X
+1963(pageno,)X
+2347(BF_PIN,)X
+2731(&len\);)X
+715 4813(/*)N
+859(Log)X
+1051(and)X
+1243(perform)X
+1627(the)X
+1819(update)X
+2155(*/)X
+715 4903(log_insdel\(BTREE_INSERT,)N
+1915(fid,)X
+2155(pageno,)X
+2539(keyp,)X
+2827(datap\);)X
+715 4993(_bt_insertat\(buffer_ptr,)N
+1915(d,)X
+2059(index\);)X
+715 5083(buf_unpin\(buffer_ptr\);)N
+1 f
+555 5206(Succinctly,)N
+942(the)X
+1068(algorithm)X
+1407(for)X
+1529(turning)X
+1788(unprotected)X
+2195(code)X
+2375(into)X
+2527(protected)X
+2854(code)X
+3034(is)X
+3115(to)X
+3205(replace)X
+3466(read)X
+3633(operations)X
+3995(with)X
+2 f
+4165(lock)X
+1 f
+555 5296(and)N
+2 f
+691(buf_get)X
+1 f
+951(operations)X
+1305(and)X
+1441(write)X
+1626(operations)X
+1980(with)X
+2 f
+2142(log)X
+1 f
+2264(and)X
+2 f
+2400(buf_unpin)X
+1 f
+2744(operations.)X
+8 s
+10 f
+555 5458(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)N
+5 s
+1 f
+727 5536(3)N
+8 s
+766 5561(The)N
+884(following)X
+1152(code)X
+1291(fragments)X
+1565(are)X
+1661(examples,)X
+1937(but)X
+2038(do)X
+2120(not)X
+2220(de\256ne)X
+2394(the)X
+2490(\256nal)X
+2622(interface.)X
+2894(The)X
+3011(\256nal)X
+3143(interface)X
+3383(will)X
+3501(be)X
+3579(determined)X
+3884(after)X
+4018(LIBTP)X
+4214(has)X
+555 5633(been)N
+691(fully)X
+828(integrated)X
+1099(with)X
+1229(the)X
+1323(most)X
+1464(recent)X
+3 f
+1635(db)X
+1 f
+1707(\(3\))X
+1797(release)X
+1989(from)X
+2129(the)X
+2223(Computer)X
+2495(Systems)X
+2725(Research)X
+2974(Group)X
+3153(at)X
+3215(University)X
+3501(of)X
+3570(California,)X
+3861(Berkeley.)X
+
+11 p
+%%Page: 11 11
+8 s 8 xH 0 xS 1 f
+10 s
+3 f
+555 630(5.)N
+655(Performance)X
+1 f
+755 753(In)N
+845(this)X
+983(section,)X
+1253(we)X
+1370(present)X
+1625(the)X
+1746(results)X
+1978(of)X
+2067(two)X
+2209(very)X
+2374(different)X
+2673(benchmarks.)X
+3103(The)X
+3250(\256rst)X
+3396(is)X
+3471(an)X
+3569(online)X
+3791(transaction)X
+4165(pro-)X
+555 843(cessing)N
+824(benchmark,)X
+1234(similar)X
+1489(to)X
+1584(the)X
+1715(standard)X
+2020(TPCB,)X
+2272(but)X
+2407(has)X
+2547(been)X
+2732(adapted)X
+3015(to)X
+3110(run)X
+3250(in)X
+3345(a)X
+3414(desktop)X
+3696(environment.)X
+4174(The)X
+555 933(second)N
+798(emulates)X
+1103(a)X
+1159(computer-aided)X
+1683(design)X
+1912(environment)X
+2337(and)X
+2473(provides)X
+2769(more)X
+2954(complex)X
+3250(query)X
+3453(processing.)X
+3 f
+555 1119(5.1.)N
+715(Transaction)X
+1148(Processing)X
+1533(Benchmark)X
+1 f
+755 1242(For)N
+887(this)X
+1023(section,)X
+1291(all)X
+1392(performance)X
+1820(numbers)X
+2117(shown)X
+2346(except)X
+2576(for)X
+2690(the)X
+2808(commercial)X
+3207(database)X
+3504(system)X
+3746(were)X
+3923(obtained)X
+4219(on)X
+555 1332(a)N
+614(DECstation)X
+1009(5000/200)X
+1333(with)X
+1497(32MBytes)X
+1852(of)X
+1941(memory)X
+2230(running)X
+2501(Ultrix)X
+2714(V4.0,)X
+2914(accessing)X
+3244(a)X
+3302(DEC)X
+3484(RZ57)X
+3688(1GByte)X
+3959(disk)X
+4114(drive.)X
+555 1422(The)N
+720(commercial)X
+1139(relational)X
+1482(database)X
+1799(system)X
+2061(tests)X
+2242(were)X
+2438(run)X
+2584(on)X
+2703(a)X
+2778(comparable)X
+3192(machine,)X
+3523(a)X
+3598(Sparcstation)X
+4033(1+)X
+4157(with)X
+555 1512(32MBytes)N
+915(memory)X
+1209(and)X
+1352(a)X
+1415(1GByte)X
+1691(external)X
+1976(disk)X
+2135(drive.)X
+2366(The)X
+2517(database,)X
+2840(binaries)X
+3120(and)X
+3262(log)X
+3390(resided)X
+3648(on)X
+3754(the)X
+3878(same)X
+4069(device.)X
+555 1602(Reported)N
+869(times)X
+1062(are)X
+1181(the)X
+1299(means)X
+1524(of)X
+1611(\256ve)X
+1751(tests)X
+1913(and)X
+2049(have)X
+2221(standard)X
+2513(deviations)X
+2862(within)X
+3086(two)X
+3226(percent)X
+3483(of)X
+3570(the)X
+3688(mean.)X
+755 1725(The)N
+905(test)X
+1041(database)X
+1343(was)X
+1493(con\256gured)X
+1861(according)X
+2203(to)X
+2290(the)X
+2413(TPCB)X
+2637(scaling)X
+2889(rules)X
+3070(for)X
+3189(a)X
+3250(10)X
+3355(transaction)X
+3732(per)X
+3860(second)X
+4108(\(TPS\))X
+555 1815(system)N
+817(with)X
+999(1,000,000)X
+1359(account)X
+1649(records,)X
+1946(100)X
+2106(teller)X
+2311(records,)X
+2607(and)X
+2762(10)X
+2881(branch)X
+3139(records.)X
+3455(Where)X
+3709(TPS)X
+3885(numbers)X
+4200(are)X
+555 1905(reported,)N
+865(we)X
+981(are)X
+1102(running)X
+1373(a)X
+1431(modi\256ed)X
+1737(version)X
+1995(of)X
+2084(the)X
+2203(industry)X
+2486(standard)X
+2779(transaction)X
+3152(processing)X
+3516(benchmark,)X
+3914(TPCB.)X
+4174(The)X
+555 1995(TPCB)N
+780(benchmark)X
+1163(simulates)X
+1491(a)X
+1553(withdrawal)X
+1940(performed)X
+2301(by)X
+2407(a)X
+2469(hypothetical)X
+2891(teller)X
+3082(at)X
+3166(a)X
+3228(hypothetical)X
+3650(bank.)X
+3872(The)X
+4022(database)X
+555 2085(consists)N
+831(of)X
+921(relations)X
+1220(\(\256les\))X
+1430(for)X
+1547(accounts,)X
+1871(branches,)X
+2200(tellers,)X
+2439(and)X
+2578(history.)X
+2863(For)X
+2997(each)X
+3168(transaction,)X
+3563(the)X
+3684(account,)X
+3976(teller,)X
+4183(and)X
+555 2175(branch)N
+795(balances)X
+1093(must)X
+1269(be)X
+1366(updated)X
+1641(to)X
+1724(re\257ect)X
+1946(the)X
+2065(withdrawal)X
+2447(and)X
+2584(a)X
+2640(history)X
+2882(record)X
+3108(is)X
+3181(written)X
+3428(which)X
+3644(contains)X
+3931(the)X
+4049(account)X
+555 2265(id,)N
+657(branch)X
+896(id,)X
+998(teller)X
+1183(id,)X
+1285(and)X
+1421(the)X
+1539(amount)X
+1799(of)X
+1886(the)X
+2004(withdrawal)X
+2385([TPCB90].)X
+755 2388(Our)N
+914(implementation)X
+1450(of)X
+1551(the)X
+1683(benchmark)X
+2074(differs)X
+2317(from)X
+2506(the)X
+2637(speci\256cation)X
+3075(in)X
+3170(several)X
+3431(aspects.)X
+3736(The)X
+3894(speci\256cation)X
+555 2478(requires)N
+840(that)X
+985(the)X
+1108(database)X
+1410(keep)X
+1587(redundant)X
+1933(logs)X
+2091(on)X
+2196(different)X
+2498(devices,)X
+2784(but)X
+2911(we)X
+3030(use)X
+3162(a)X
+3223(single)X
+3439(log.)X
+3606(Furthermore,)X
+4052(all)X
+4157(tests)X
+555 2568(were)N
+734(run)X
+863(on)X
+965(a)X
+1023(single,)X
+1256(centralized)X
+1631(system)X
+1875(so)X
+1968(there)X
+2151(is)X
+2226(no)X
+2328(notion)X
+2553(of)X
+2641(remote)X
+2885(accesses.)X
+3219(Finally,)X
+3486(we)X
+3601(calculated)X
+3948(throughput)X
+555 2658(by)N
+662(dividing)X
+955(the)X
+1080(total)X
+1249(elapsed)X
+1517(time)X
+1686(by)X
+1793(the)X
+1918(number)X
+2190(of)X
+2284(transactions)X
+2694(processed)X
+3038(rather)X
+3253(than)X
+3418(by)X
+3525(computing)X
+3894(the)X
+4018(response)X
+555 2748(time)N
+717(for)X
+831(each)X
+999(transaction.)X
+755 2871(The)N
+912(performance)X
+1351(comparisons)X
+1788(focus)X
+1993(on)X
+2104(traditional)X
+2464(Unix)X
+2655(techniques)X
+3029(\(unprotected,)X
+3486(using)X
+3 f
+3690(\257ock)X
+1 f
+3854(\(2\))X
+3979(and)X
+4126(using)X
+3 f
+555 2961(fsync)N
+1 f
+733(\(2\)\))X
+884(and)X
+1030(a)X
+1096(commercial)X
+1504(relational)X
+1836(database)X
+2142(system.)X
+2433(Well-behaved)X
+2913(applications)X
+3329(using)X
+3 f
+3531(\257ock)X
+1 f
+3695(\(2\))X
+3818(are)X
+3946(guaranteed)X
+555 3051(that)N
+704(concurrent)X
+1077(processes')X
+1441(updates)X
+1715(do)X
+1824(not)X
+1955(interact)X
+2225(with)X
+2396(one)X
+2541(another,)X
+2831(but)X
+2962(no)X
+3070(guarantees)X
+3442(about)X
+3648(atomicity)X
+3978(are)X
+4105(made.)X
+555 3141(That)N
+731(is,)X
+833(if)X
+911(the)X
+1038(system)X
+1289(crashes)X
+1555(in)X
+1646(mid-transaction,)X
+2198(only)X
+2369(parts)X
+2554(of)X
+2649(that)X
+2797(transaction)X
+3177(will)X
+3329(be)X
+3433(re\257ected)X
+3738(in)X
+3828(the)X
+3954 0.3125(after-crash)AX
+555 3231(state)N
+725(of)X
+815(the)X
+936(database.)X
+1276(The)X
+1424(use)X
+1554(of)X
+3 f
+1643(fsync)X
+1 f
+1821(\(2\))X
+1937(at)X
+2017(transaction)X
+2391(commit)X
+2657(time)X
+2821(provides)X
+3119(guarantees)X
+3485(of)X
+3574(durability)X
+3907(after)X
+4077(system)X
+555 3321(failure.)N
+825(However,)X
+1160(there)X
+1341(is)X
+1414(no)X
+1514(mechanism)X
+1899(to)X
+1981(perform)X
+2260(transaction)X
+2632(abort.)X
+3 f
+555 3507(5.1.1.)N
+775(Single-User)X
+1191(Tests)X
+1 f
+755 3630(These)N
+978(tests)X
+1151(compare)X
+1459(LIBTP)X
+1712(in)X
+1804(a)X
+1870(variety)X
+2123(of)X
+2220(con\256gurations)X
+2708(to)X
+2800(traditional)X
+3159(UNIX)X
+3390(solutions)X
+3708(and)X
+3854(a)X
+3920(commercial)X
+555 3720(relational)N
+884(database)X
+1187(system)X
+1435(\(RDBMS\).)X
+1814(To)X
+1929(demonstrate)X
+2347(the)X
+2471(server)X
+2694(architecture)X
+3100(we)X
+3220(built)X
+3392(a)X
+3454(front)X
+3636(end)X
+3777(test)X
+3913(process)X
+4179(that)X
+555 3810(uses)N
+732(TCL)X
+922([OUST90])X
+1304(to)X
+1405(parse)X
+1614(database)X
+1930(access)X
+2175(commands)X
+2561(and)X
+2716(call)X
+2870(the)X
+3006(database)X
+3321(access)X
+3565(routines.)X
+3901(In)X
+4006(one)X
+4160(case)X
+555 3900(\(SERVER\),)N
+956(frontend)X
+1249(and)X
+1386(backend)X
+1675(processes)X
+2004(were)X
+2181(created)X
+2434(which)X
+2650(communicated)X
+3142(via)X
+3260(an)X
+3356(IP)X
+3447(socket.)X
+3712(In)X
+3799(the)X
+3917(second)X
+4160(case)X
+555 3990(\(TCL\),)N
+802(a)X
+860(single)X
+1073(process)X
+1336(read)X
+1497(queries)X
+1751(from)X
+1929(standard)X
+2223(input,)X
+2429(parsed)X
+2660(them,)X
+2861(and)X
+2998(called)X
+3211(the)X
+3330(database)X
+3628(access)X
+3855(routines.)X
+4174(The)X
+555 4080(performance)N
+987(difference)X
+1338(between)X
+1630(the)X
+1752(TCL)X
+1927(and)X
+2067(SERVER)X
+2397(tests)X
+2563(quanti\256es)X
+2898(the)X
+3020(communication)X
+3542(overhead)X
+3861(of)X
+3952(the)X
+4074(socket.)X
+555 4170(The)N
+732(RDBMS)X
+1063(implementation)X
+1617(used)X
+1816(embedded)X
+2198(SQL)X
+2401(in)X
+2515(C)X
+2620(with)X
+2814(stored)X
+3062(database)X
+3391(procedures.)X
+3835(Therefore,)X
+4224(its)X
+555 4260(con\256guration)N
+1003(is)X
+1076(a)X
+1132(hybrid)X
+1361(of)X
+1448(the)X
+1566(single)X
+1777(process)X
+2038(architecture)X
+2438(and)X
+2574(the)X
+2692(server)X
+2909(architecture.)X
+3349(The)X
+3494(graph)X
+3697(in)X
+3779(\256gure)X
+3986(six)X
+4099(shows)X
+555 4350(a)N
+611(comparison)X
+1005(of)X
+1092(the)X
+1210(following)X
+1541(six)X
+1654(con\256gurations:)X
+1126 4506(LIBTP)N
+1552(Uses)X
+1728(the)X
+1846(LIBTP)X
+2088(library)X
+2322(in)X
+2404(a)X
+2460(single)X
+2671(application.)X
+1126 4596(TCL)N
+1552(Uses)X
+1728(the)X
+1846(LIBTP)X
+2088(library)X
+2322(in)X
+2404(a)X
+2460(single)X
+2671(application,)X
+3067(requires)X
+3346(query)X
+3549(parsing.)X
+1126 4686(SERVER)N
+1552(Uses)X
+1728(the)X
+1846(LIBTP)X
+2088(library)X
+2322(in)X
+2404(a)X
+2460(server)X
+2677(con\256guration,)X
+3144(requires)X
+3423(query)X
+3626(parsing.)X
+1126 4776(NOTP)N
+1552(Uses)X
+1728(no)X
+1828(locking,)X
+2108(logging,)X
+2392(or)X
+2479(concurrency)X
+2897(control.)X
+1126 4866(FLOCK)N
+1552(Uses)X
+3 f
+1728(\257ock)X
+1 f
+1892(\(2\))X
+2006(for)X
+2120(concurrency)X
+2538(control)X
+2785(and)X
+2921(nothing)X
+3185(for)X
+3299(durability.)X
+1126 4956(FSYNC)N
+1552(Uses)X
+3 f
+1728(fsync)X
+1 f
+1906(\(2\))X
+2020(for)X
+2134(durability)X
+2465(and)X
+2601(nothing)X
+2865(for)X
+2979(concurrency)X
+3397(control.)X
+1126 5046(RDBMS)N
+1552(Uses)X
+1728(a)X
+1784(commercial)X
+2183(relational)X
+2506(database)X
+2803(system.)X
+755 5235(The)N
+902(results)X
+1133(show)X
+1324(that)X
+1466(LIBTP,)X
+1730(both)X
+1894(in)X
+1978(the)X
+2098(procedural)X
+2464(and)X
+2602(parsed)X
+2834(environments,)X
+3312(is)X
+3387(competitive)X
+3787(with)X
+3951(a)X
+4009(commer-)X
+555 5325(cial)N
+692(system)X
+935(\(comparing)X
+1326(LIBTP,)X
+1589(TCL,)X
+1781(and)X
+1917(RDBMS\).)X
+2263(Compared)X
+2617(to)X
+2699(existing)X
+2972(UNIX)X
+3193(solutions,)X
+3521(LIBTP)X
+3763(is)X
+3836(approximately)X
+555 5415(15%)N
+738(slower)X
+988(than)X
+1162(using)X
+3 f
+1371(\257ock)X
+1 f
+1535(\(2\))X
+1665(or)X
+1768(no)X
+1884(protection)X
+2245(but)X
+2383(over)X
+2562(80%)X
+2745(better)X
+2964(than)X
+3137(using)X
+3 f
+3345(fsync)X
+1 f
+3523(\(2\))X
+3652(\(comparing)X
+4057(LIBTP,)X
+555 5505(FLOCK,)N
+857(NOTP,)X
+1106(and)X
+1242(FSYNC\).)X
+
+12 p
+%%Page: 12 12
+10 s 10 xH 0 xS 1 f
+3 f
+8 s
+3500 2184(RDBMS)N
+1 Dt
+3553 2085 MXY
+ 3553 2085 lineto
+ 3676 2085 lineto
+ 3676 1351 lineto
+ 3553 1351 lineto
+ 3553 2085 lineto
+closepath 16 3553 1351 3676 2085 Dp
+2018 2184(SERVER)N
+1720 1168 MXY
+0 917 Dl
+122 0 Dl
+0 -917 Dl
+-122 0 Dl
+1715 2184(TCL)N
+2087 1534 MXY
+ 2087 1534 lineto
+ 2209 1534 lineto
+ 2209 2085 lineto
+ 2087 2085 lineto
+ 2087 1534 lineto
+closepath 12 2087 1534 2209 2085 Dp
+3187 MX
+ 3187 1534 lineto
+ 3309 1534 lineto
+ 3309 2085 lineto
+ 3187 2085 lineto
+ 3187 1534 lineto
+closepath 19 3187 1534 3309 2085 Dp
+3142 2184(FSYNC)N
+2425(NOTP)X
+2453 955 MXY
+ 2453 955 lineto
+ 2576 955 lineto
+ 2576 2085 lineto
+ 2453 2085 lineto
+ 2453 955 lineto
+closepath 21 2453 955 2576 2085 Dp
+2820 1000 MXY
+ 2820 1000 lineto
+ 2942 1000 lineto
+ 2942 2085 lineto
+ 2820 2085 lineto
+ 2820 1000 lineto
+closepath 14 2820 1000 2942 2085 Dp
+5 Dt
+1231 2085 MXY
+2567 0 Dl
+4 Ds
+1 Dt
+1231 1840 MXY
+2567 0 Dl
+1231 1596 MXY
+2567 0 Dl
+1231 1351 MXY
+2567 0 Dl
+1231 1108 MXY
+2567 0 Dl
+1231 863 MXY
+2567 0 Dl
+11 s
+1087 1877(2)N
+1087 1633(4)N
+1087 1388(6)N
+1087 1145(8)N
+1065 900(10)N
+1028 763(TPS)N
+-1 Ds
+1353 2085 MXY
+ 1353 2085 lineto
+ 1353 1151 lineto
+ 1476 1151 lineto
+ 1476 2085 lineto
+ 1353 2085 lineto
+closepath 3 1353 1151 1476 2085 Dp
+8 s
+1318 2184(LIBTP)N
+2767(FLOCK)X
+3 Dt
+-1 Ds
+10 s
+1597 2399(Figure)N
+1844(6:)X
+1931(Single-User)X
+2347(Performance)X
+2814(Comparison.)X
+1 f
+10 f
+555 2579(h)N
+579(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)X
+3 f
+555 2855(5.1.2.)N
+775(Multi-User)X
+1174(Tests)X
+1 f
+755 2978(While)N
+975(the)X
+1097(single-user)X
+1473(tests)X
+1639(form)X
+1819(a)X
+1878(basis)X
+2061(for)X
+2178(comparing)X
+2544(LIBTP)X
+2789(to)X
+2874(other)X
+3062(systems,)X
+3358(our)X
+3488(goal)X
+3649(in)X
+3734(multi-user)X
+4086(testing)X
+555 3068(was)N
+714(to)X
+810(analyze)X
+1089(its)X
+1197(scalability.)X
+1579(To)X
+1701(this)X
+1849(end,)X
+2018(we)X
+2145(have)X
+2330(run)X
+2470(the)X
+2601(benchmark)X
+2991(in)X
+3086(three)X
+3280(modes,)X
+3542(the)X
+3673(normal)X
+3933(disk)X
+4099(bound)X
+555 3158(con\256guration)N
+1010(\(\256gure)X
+1252(seven\),)X
+1510(a)X
+1573(CPU)X
+1755(bound)X
+1982(con\256guration)X
+2436(\(\256gure)X
+2677(eight,)X
+2884(READ-ONLY\),)X
+3426(and)X
+3569(lock)X
+3734(contention)X
+4099(bound)X
+555 3248(\(\256gure)N
+796(eight,)X
+1003(NO_FSYNC\).)X
+1510(Since)X
+1715(the)X
+1840(normal)X
+2094(con\256guration)X
+2548(is)X
+2628(completely)X
+3011(disk)X
+3171(bound)X
+3398(\(each)X
+3600(transaction)X
+3978(requires)X
+4263(a)X
+555 3354(random)N
+823(read,)X
+1005(a)X
+1064(random)X
+1332(write,)X
+1540(and)X
+1679(a)X
+1738(sequential)X
+2086(write)X
+7 s
+2251 3322(4)N
+10 s
+3354(\))Y
+2329(we)X
+2446(expect)X
+2679(to)X
+2764(see)X
+2890(little)X
+3059(performance)X
+3489(improvement)X
+3939(as)X
+4028(the)X
+4148(mul-)X
+555 3444(tiprogramming)N
+1064(level)X
+1249(increases.)X
+1613(In)X
+1709(fact,)X
+1879(\256gure)X
+2095(seven)X
+2307(reveals)X
+2564(that)X
+2713(we)X
+2836(are)X
+2964(able)X
+3127(to)X
+3218(overlap)X
+3487(CPU)X
+3670(and)X
+3814(disk)X
+3975(utilization)X
+555 3534(slightly)N
+825(producing)X
+1181(approximately)X
+1674(a)X
+1740(10%)X
+1917(performance)X
+2354(improvement)X
+2811(with)X
+2983(two)X
+3133(processes.)X
+3511(After)X
+3711(that)X
+3861(point,)X
+4075(perfor-)X
+555 3624(mance)N
+785(drops)X
+983(off,)X
+1117(and)X
+1253(at)X
+1331(a)X
+1387(multi-programming)X
+2038(level)X
+2214(of)X
+2301(4,)X
+2381(we)X
+2495(are)X
+2614(performing)X
+2995(worse)X
+3207(than)X
+3365(in)X
+3447(the)X
+3565(single)X
+3776(process)X
+4037(case.)X
+755 3747(Similar)N
+1021(behavior)X
+1333(was)X
+1489(reported)X
+1787(on)X
+1897(the)X
+2025(commercial)X
+2434(relational)X
+2767(database)X
+3074(system)X
+3326(using)X
+3529(the)X
+3657(same)X
+3852(con\256guration.)X
+555 3837(The)N
+707(important)X
+1045(conclusion)X
+1419(to)X
+1508(draw)X
+1696(from)X
+1879(this)X
+2021(is)X
+2101(that)X
+2248(you)X
+2395(cannot)X
+2636(attain)X
+2841(good)X
+3028(multi-user)X
+3384(scaling)X
+3638(on)X
+3745(a)X
+3808(badly)X
+4013(balanced)X
+555 3927(system.)N
+839(If)X
+915(multi-user)X
+1266(performance)X
+1695(on)X
+1797(applications)X
+2205(of)X
+2293(this)X
+2429(sort)X
+2570(is)X
+2644(important,)X
+2996(one)X
+3133(must)X
+3309(have)X
+3482(a)X
+3539(separate)X
+3824(logging)X
+4089(device)X
+555 4017(and)N
+697(horizontally)X
+1110(partition)X
+1407(the)X
+1531(database)X
+1834(to)X
+1921(allow)X
+2124(a)X
+2185(suf\256ciently)X
+2570(high)X
+2737(degree)X
+2977(of)X
+3069(multiprogramming)X
+3698(that)X
+3843(group)X
+4055(commit)X
+555 4107(can)N
+687(amortize)X
+988(the)X
+1106(cost)X
+1255(of)X
+1342(log)X
+1464(\257ushing.)X
+755 4230(By)N
+871(using)X
+1067(a)X
+1126(very)X
+1292(small)X
+1488(database)X
+1788(\(one)X
+1954(that)X
+2097(can)X
+2232(be)X
+2331(entirely)X
+2599(cached)X
+2846(in)X
+2930(main)X
+3112(memory\))X
+3428(and)X
+3566(read-only)X
+3896(transactions,)X
+555 4320(we)N
+670(generated)X
+1004(a)X
+1061(CPU)X
+1236(bound)X
+1456(environment.)X
+1921(By)X
+2034(using)X
+2227(the)X
+2345(same)X
+2530(small)X
+2723(database,)X
+3040(the)X
+3158(complete)X
+3472(TPCB)X
+3691(transaction,)X
+4083(and)X
+4219(no)X
+3 f
+555 4410(fsync)N
+1 f
+733(\(2\))X
+862(on)X
+977(the)X
+1110(log)X
+1247(at)X
+1340(commit,)X
+1639(we)X
+1768(created)X
+2036(a)X
+2107(lock)X
+2280(contention)X
+2652(bound)X
+2886(environment.)X
+3365(The)X
+3524(small)X
+3731(database)X
+4042(used)X
+4223(an)X
+555 4500(account)N
+828(\256le)X
+953(containing)X
+1314(only)X
+1479(1000)X
+1662(records)X
+1922(rather)X
+2133(than)X
+2294(the)X
+2415(full)X
+2549(1,000,000)X
+2891(records)X
+3150(and)X
+3288(ran)X
+3413(enough)X
+3671(transactions)X
+4076(to)X
+4160(read)X
+555 4590(the)N
+677(entire)X
+883(database)X
+1183(into)X
+1330(the)X
+1451(buffer)X
+1671(pool)X
+1836(\(2000\))X
+2073(before)X
+2302(beginning)X
+2645(measurements.)X
+3147(The)X
+3295(read-only)X
+3626(transaction)X
+4001(consisted)X
+555 4680(of)N
+646(three)X
+831(database)X
+1132(reads)X
+1326(\(from)X
+1533(the)X
+1655(1000)X
+1839(record)X
+2069(account)X
+2343(\256le,)X
+2489(the)X
+2611(100)X
+2754(record)X
+2983(teller)X
+3171(\256le,)X
+3316(and)X
+3455(the)X
+3576(10)X
+3679(record)X
+3908(branch)X
+4150(\256le\).)X
+555 4770(Since)N
+759(no)X
+865(data)X
+1025(were)X
+1208(modi\256ed)X
+1518(and)X
+1660(no)X
+1766(history)X
+2014(records)X
+2277(were)X
+2460(written,)X
+2733(no)X
+2839(log)X
+2966(records)X
+3228(were)X
+3410(written.)X
+3702(For)X
+3838(the)X
+3961(contention)X
+555 4860(bound)N
+780(con\256guration,)X
+1252(we)X
+1371(used)X
+1543(the)X
+1666(normal)X
+1918(TPCB)X
+2142(transaction)X
+2519(\(against)X
+2798(the)X
+2920(small)X
+3117(database\))X
+3445(and)X
+3585(disabled)X
+3876(the)X
+3998(log)X
+4124(\257ush.)X
+555 4950(Figure)N
+784(eight)X
+964(shows)X
+1184(both)X
+1346(of)X
+1433(these)X
+1618(results.)X
+755 5073(The)N
+902(read-only)X
+1231(test)X
+1363(indicates)X
+1669(that)X
+1810(we)X
+1925(barely)X
+2147(scale)X
+2329(at)X
+2408(all)X
+2509(in)X
+2592(the)X
+2711(CPU)X
+2887(bound)X
+3108(case.)X
+3308(The)X
+3454(explanation)X
+3849(for)X
+3964(that)X
+4105(is)X
+4179(that)X
+555 5163(even)N
+735(with)X
+905(a)X
+969(single)X
+1188(process,)X
+1477(we)X
+1599(are)X
+1726(able)X
+1888(to)X
+1978(drive)X
+2171(the)X
+2297(CPU)X
+2480(utilization)X
+2832(to)X
+2922(96%.)X
+3137(As)X
+3254(a)X
+3317(result,)X
+3542(that)X
+3689(gives)X
+3885(us)X
+3983(very)X
+4153(little)X
+555 5253(room)N
+753(for)X
+876(improvement,)X
+1352(and)X
+1497(it)X
+1570(takes)X
+1764(a)X
+1829(multiprogramming)X
+2462(level)X
+2647(of)X
+2743(four)X
+2906(to)X
+2997(approach)X
+3321(100%)X
+3537(CPU)X
+3721(saturation.)X
+4106(In)X
+4201(the)X
+555 5343(case)N
+718(where)X
+939(we)X
+1057(do)X
+1161(perform)X
+1444(writes,)X
+1684(we)X
+1802(are)X
+1925(interested)X
+2261(in)X
+2347(detecting)X
+2665(when)X
+2863(lock)X
+3025(contention)X
+3387(becomes)X
+3691(a)X
+3750(dominant)X
+4075(perfor-)X
+555 5433(mance)N
+787(factor.)X
+1037(Contention)X
+1414(will)X
+1560(cause)X
+1761(two)X
+1903(phenomena;)X
+2317(we)X
+2433(will)X
+2579(see)X
+2704(transactions)X
+3109(queueing)X
+3425(behind)X
+3665(frequently)X
+4017(accessed)X
+555 5523(data,)N
+731(and)X
+869(we)X
+985(will)X
+1131(see)X
+1256(transaction)X
+1629(abort)X
+1815(rates)X
+1988(increasing)X
+2339(due)X
+2476(to)X
+2559(deadlock.)X
+2910(Given)X
+3127(that)X
+3268(the)X
+3387(branch)X
+3627(\256le)X
+3750(contains)X
+4038(only)X
+4201(ten)X
+8 s
+10 f
+555 5595(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)N
+5 s
+1 f
+727 5673(4)N
+8 s
+763 5698(Although)N
+1021(the)X
+1115(log)X
+1213(is)X
+1272(written)X
+1469(sequentially,)X
+1810(we)X
+1900(do)X
+1980(not)X
+2078(get)X
+2172(the)X
+2266(bene\256t)X
+2456(of)X
+2525(sequentiality)X
+2868(since)X
+3015(the)X
+3109(log)X
+3207(and)X
+3315(database)X
+3550(reside)X
+3718(on)X
+3798(the)X
+3892(same)X
+4039(disk.)X
+
+13 p
+%%Page: 13 13
+8 s 8 xH 0 xS 1 f
+10 s
+3 f
+1 f
+3187 2051 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3286 2028 MXY
+0 17 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3384 1926 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3483 1910 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3581 1910 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3680 1832 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3778 1909 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3877 1883 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3975 1679 MXY
+0 17 Dl
+0 -8 Dl
+9 0 Dl
+-18 0 Dl
+4074 1487 MXY
+0 17 Dl
+0 -8 Dl
+9 0 Dl
+-18 0 Dl
+5 Dt
+3187 2060 MXY
+99 -24 Dl
+98 -101 Dl
+99 -16 Dl
+98 0 Dl
+99 -78 Dl
+98 77 Dl
+99 -26 Dl
+98 -204 Dl
+99 -192 Dl
+3 f
+6 s
+4088 1516(SMALL)N
+3 Dt
+3187 2051 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3286 2051 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3384 2041 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3483 1990 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3581 1843 MXY
+0 17 Dl
+0 -8 Dl
+9 0 Dl
+-18 0 Dl
+3680 1578 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3778 1496 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3877 1430 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+3975 1269 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+4074 1070 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1 Dt
+3187 2060 MXY
+99 0 Dl
+98 -10 Dl
+99 -51 Dl
+98 -147 Dl
+99 -265 Dl
+98 -82 Dl
+99 -66 Dl
+98 -161 Dl
+99 -199 Dl
+4088 1099(LARGE)N
+5 Dt
+3089 2060 MXY
+985 0 Dl
+3089 MX
+0 -1174 Dl
+4 Ds
+1 Dt
+3581 2060 MXY
+0 -1174 Dl
+4074 2060 MXY
+0 -1174 Dl
+3089 1825 MXY
+985 0 Dl
+9 s
+2993 1855(25)N
+3089 1591 MXY
+985 0 Dl
+2993 1621(50)N
+3089 1356 MXY
+985 0 Dl
+2993 1386(75)N
+3089 1121 MXY
+985 0 Dl
+2957 1151(100)N
+3089 886 MXY
+985 0 Dl
+2957 916(125)N
+3281 2199(Multiprogramming)N
+3071 2152(0)N
+3569(5)X
+4038(10)X
+2859 787(Aborts)N
+3089(per)X
+3211(500)X
+2901 847(transactions)N
+-1 Ds
+3 Dt
+2037 1342 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2125 1358 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2213 1341 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2301 1191 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2388 1124 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-17 0 Dl
+2476 1157 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2564 1157 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2652 1161 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2740 1153 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2828 1150 MXY
+0 18 Dl
+0 -9 Dl
+8 0 Dl
+-17 0 Dl
+5 Dt
+2037 1351 MXY
+88 16 Dl
+88 -17 Dl
+88 -150 Dl
+87 -67 Dl
+88 33 Dl
+88 0 Dl
+88 4 Dl
+88 -8 Dl
+88 -3 Dl
+6 s
+2685 1234(READ-ONLY)N
+3 Dt
+2037 1464 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2125 1640 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2213 1854 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2301 1872 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2388 1871 MXY
+0 17 Dl
+0 -9 Dl
+9 0 Dl
+-17 0 Dl
+2476 1933 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2564 1914 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2652 1903 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2740 1980 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+2828 2004 MXY
+0 18 Dl
+0 -9 Dl
+8 0 Dl
+-17 0 Dl
+1 Dt
+2037 1473 MXY
+88 176 Dl
+88 214 Dl
+88 18 Dl
+87 -2 Dl
+88 63 Dl
+88 -19 Dl
+88 -11 Dl
+88 77 Dl
+88 24 Dl
+2759 1997(NO-FSYNC)N
+5 Dt
+1949 2060 MXY
+879 0 Dl
+1949 MX
+0 -1174 Dl
+4 Ds
+1 Dt
+2388 2060 MXY
+0 -1174 Dl
+2828 2060 MXY
+0 -1174 Dl
+1949 1825 MXY
+879 0 Dl
+9 s
+1842 1855(40)N
+1949 1591 MXY
+879 0 Dl
+1842 1621(80)N
+1949 1356 MXY
+879 0 Dl
+1806 1386(120)N
+1949 1121 MXY
+879 0 Dl
+1806 1151(160)N
+1949 886 MXY
+879 0 Dl
+1806 916(200)N
+2088 2199(Multiprogramming)N
+1844 863(in)N
+1922(TPS)X
+1761 792(Throughput)N
+1931 2121(0)N
+2370 2133(5)N
+2792(10)X
+6 s
+1679 1833(LIBTP)N
+-1 Ds
+3 Dt
+837 1019 MXY
+0 17 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+929 878 MXY
+0 17 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1021 939 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1113 1043 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1205 1314 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1297 1567 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1389 1665 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1481 1699 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1573 1828 MXY
+0 18 Dl
+0 -9 Dl
+9 0 Dl
+-18 0 Dl
+1665 1804 MXY
+0 18 Dl
+0 -9 Dl
+8 0 Dl
+-17 0 Dl
+5 Dt
+837 1027 MXY
+92 -141 Dl
+92 62 Dl
+92 104 Dl
+92 271 Dl
+92 253 Dl
+92 98 Dl
+92 34 Dl
+92 129 Dl
+92 -24 Dl
+745 2060 MXY
+920 0 Dl
+745 MX
+0 -1174 Dl
+4 Ds
+1 Dt
+1205 2060 MXY
+0 -1174 Dl
+1665 2060 MXY
+0 -1174 Dl
+745 1766 MXY
+920 0 Dl
+9 s
+673 1796(3)N
+745 1473 MXY
+920 0 Dl
+673 1503(5)N
+745 1180 MXY
+920 0 Dl
+673 1210(8)N
+745 886 MXY
+920 0 Dl
+637 916(10)N
+905 2199(Multiprogramming)N
+622 851(in)N
+700(TPS)X
+575 792(Throughput)N
+733 2152(0)N
+1196(5)X
+1629(10)X
+3 Dt
+-1 Ds
+8 s
+655 2441(Figure)N
+872(7:)X
+960(Multi-user)X
+1286(Performance.)X
+1 f
+655 2531(Since)N
+825(the)X
+931(con\256guration)X
+1300(is)X
+1371(completely)X
+655 2621(disk)N
+790(bound,)X
+994(we)X
+1096(see)X
+1204(only)X
+1345(a)X
+1400(small)X
+1566(im-)X
+655 2711(provement)N
+964(by)X
+1064(adding)X
+1274(a)X
+1337(second)X
+1549(pro-)X
+655 2801(cess.)N
+849(Adding)X
+1081(any)X
+1213(more)X
+1383(concurrent)X
+655 2891(processes)N
+935(causes)X
+1137(performance)X
+1493(degra-)X
+655 2981(dation.)N
+3 f
+1927 2441(Figure)N
+2149(8:)X
+2243(Multi-user)X
+2574(Performance)X
+1927 2531(on)N
+2021(a)X
+2079(small)X
+2251(database.)X
+1 f
+2551(With)X
+2704(one)X
+2821(pro-)X
+1927 2621(cess,)N
+2075(we)X
+2174(are)X
+2276(driving)X
+2486(the)X
+2589(CPU)X
+2739(at)X
+2810(96%)X
+1927 2711(utilization)N
+2215(leaving)X
+2430(little)X
+2575(room)X
+2737(for)X
+2838(im-)X
+1927 2801(provement)N
+2238(as)X
+2328(the)X
+2443(multiprogramming)X
+1927 2891(level)N
+2091(increases.)X
+2396(In)X
+2489(the)X
+2607(NO-FSYNC)X
+1927 2981(case,)N
+2076(lock)X
+2209(contention)X
+2502(degrades)X
+2751(perfor-)X
+1927 3071(mance)N
+2117(as)X
+2194(soon)X
+2339(as)X
+2416(a)X
+2468(second)X
+2669(process)X
+2884(is)X
+1927 3161(added.)N
+3 f
+3199 2441(Figure)N
+3405(9:)X
+3482(Abort)X
+3669(rates)X
+3827(on)X
+3919(the)X
+4028(TPCB)X
+3199 2531(Benchmark.)N
+1 f
+3589(The)X
+3726(abort)X
+3895(rate)X
+4028(climbs)X
+3199 2621(more)N
+3366(quickly)X
+3594(for)X
+3704(the)X
+3818(large)X
+3980(database)X
+3199 2711(test)N
+3324(since)X
+3491(processes)X
+3771(are)X
+3884(descheduled)X
+3199 2801(more)N
+3409(frequently,)X
+3766(allowing)X
+4068(more)X
+3199 2891(processes)N
+3459(to)X
+3525(vie)X
+3619(for)X
+3709(the)X
+3803(same)X
+3950(locks.)X
+10 s
+10 f
+555 3284(h)N
+579(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)X
+1 f
+555 3560(records,)N
+835(we)X
+952(expect)X
+1185(contention)X
+1546(to)X
+1631(become)X
+1904(a)X
+1963(factor)X
+2174(quickly)X
+2437(and)X
+2576(the)X
+2697(NO-FSYNC)X
+3120(line)X
+3263(in)X
+3348(\256gure)X
+3557(eight)X
+3739(demonstrates)X
+4184(this)X
+555 3650(dramatically.)N
+1022(Each)X
+1209(additional)X
+1555(process)X
+1822(causes)X
+2058(both)X
+2226(more)X
+2417(waiting)X
+2682(and)X
+2823(more)X
+3013(deadlocking.)X
+3470(Figure)X
+3704(nine)X
+3867(shows)X
+4092(that)X
+4237(in)X
+555 3740(the)N
+681(small)X
+882(database)X
+1187(case)X
+1353(\(SMALL\),)X
+1725(waiting)X
+1992(is)X
+2072(the)X
+2197(dominant)X
+2526(cause)X
+2732(of)X
+2826(declining)X
+3151(performance)X
+3585(\(the)X
+3737(number)X
+4009(of)X
+4103(aborts)X
+555 3830(increases)N
+878(less)X
+1026(steeply)X
+1281(than)X
+1447(the)X
+1573(performance)X
+2008(drops)X
+2214(off)X
+2336(in)X
+2426(\256gure)X
+2641(eight\),)X
+2876(while)X
+3082(in)X
+3172(the)X
+3298(large)X
+3487(database)X
+3792(case)X
+3958(\(LARGE\),)X
+555 3920(deadlocking)N
+967(contributes)X
+1343(more)X
+1528(to)X
+1610(the)X
+1728(declining)X
+2046(performance.)X
+755 4043(Deadlocks)N
+1116(are)X
+1237(more)X
+1424(likely)X
+1628(to)X
+1712(occur)X
+1913(in)X
+1997(the)X
+2116(LARGE)X
+2404(test)X
+2536(than)X
+2695(in)X
+2778(the)X
+2897(SMALL)X
+3189(test)X
+3321(because)X
+3597(there)X
+3779(are)X
+3899(more)X
+4085(oppor-)X
+555 4133(tunities)N
+814(to)X
+900(wait.)X
+1082(In)X
+1173(the)X
+1295(SMALL)X
+1590(case,)X
+1773(processes)X
+2105(never)X
+2307(do)X
+2410(I/O)X
+2540(and)X
+2679(are)X
+2801(less)X
+2944(likely)X
+3149(to)X
+3234(be)X
+3333(descheduled)X
+3753(during)X
+3985(a)X
+4044(transac-)X
+555 4223(tion.)N
+740(In)X
+828(the)X
+947(LARGE)X
+1235(case,)X
+1415(processes)X
+1744(will)X
+1889(frequently)X
+2240(be)X
+2337(descheduled)X
+2755(since)X
+2941(they)X
+3100(have)X
+3273(to)X
+3356(perform)X
+3636(I/O.)X
+3804(This)X
+3967(provides)X
+4263(a)X
+555 4313(window)N
+837(where)X
+1058(a)X
+1118(second)X
+1365(process)X
+1630(can)X
+1766(request)X
+2022(locks)X
+2215(on)X
+2318(already)X
+2578(locked)X
+2815(pages,)X
+3041(thus)X
+3197(increasing)X
+3550(the)X
+3671(likelihood)X
+4018(of)X
+4108(build-)X
+555 4403(ing)N
+677(up)X
+777(long)X
+939(chains)X
+1164(of)X
+1251(waiting)X
+1511(processes.)X
+1879(Eventually,)X
+2266(this)X
+2401(leads)X
+2586(to)X
+2668(deadlock.)X
+3 f
+555 4589(5.2.)N
+715(The)X
+868(OO1)X
+1052(Benchmark)X
+1 f
+755 4712(The)N
+903(TPCB)X
+1125(benchmark)X
+1505(described)X
+1836(in)X
+1921(the)X
+2042(previous)X
+2341(section)X
+2591(measures)X
+2913(performance)X
+3343(under)X
+3549(a)X
+3608(conventional)X
+4044(transac-)X
+555 4802(tion)N
+706(processing)X
+1076(workload.)X
+1446(Other)X
+1656(application)X
+2039(domains,)X
+2357(such)X
+2531(as)X
+2625(computer-aided)X
+3156(design,)X
+3412(have)X
+3591(substantially)X
+4022(different)X
+555 4892(access)N
+786(patterns.)X
+1105(In)X
+1197(order)X
+1392(to)X
+1479(measure)X
+1772(the)X
+1895(performance)X
+2327(of)X
+2418(LIBTP)X
+2664(under)X
+2871(workloads)X
+3229(of)X
+3320(this)X
+3459(type,)X
+3641(we)X
+3759(implemented)X
+4201(the)X
+555 4982(OO1)N
+731(benchmark)X
+1108(described)X
+1436(in)X
+1518([CATT91].)X
+755 5105(The)N
+908(database)X
+1213(models)X
+1472(a)X
+1535(set)X
+1651(of)X
+1745(electronics)X
+2120(components)X
+2534(with)X
+2703(connections)X
+3113(among)X
+3358(them.)X
+3585(One)X
+3746(table)X
+3929(stores)X
+4143(parts)X
+555 5195(and)N
+696(another)X
+962(stores)X
+1174(connections.)X
+1622(There)X
+1835(are)X
+1959(three)X
+2145(connections)X
+2552(originating)X
+2927(at)X
+3009(any)X
+3149(given)X
+3351(part.)X
+3540(Ninety)X
+3782(percent)X
+4043(of)X
+4134(these)X
+555 5285(connections)N
+960(are)X
+1081(to)X
+1165(nearby)X
+1406(parts)X
+1584(\(those)X
+1802(with)X
+1966(nearby)X
+2 f
+2207(ids)X
+1 f
+2300(\))X
+2348(to)X
+2431(model)X
+2652(the)X
+2771(spatial)X
+3001(locality)X
+3262(often)X
+3448(exhibited)X
+3767(in)X
+3850(CAD)X
+4040(applica-)X
+555 5375(tions.)N
+779(Ten)X
+933(percent)X
+1198(of)X
+1293(the)X
+1419(connections)X
+1830(are)X
+1957(randomly)X
+2292(distributed)X
+2662(among)X
+2908(all)X
+3016(other)X
+3209(parts)X
+3393(in)X
+3483(the)X
+3609(database.)X
+3954(Every)X
+4174(part)X
+555 5465(appears)N
+829(exactly)X
+1089(three)X
+1278(times)X
+1479(in)X
+1569(the)X
+2 f
+1695(from)X
+1 f
+1874(\256eld)X
+2043(of)X
+2137(a)X
+2200(connection)X
+2579(record,)X
+2832(and)X
+2975(zero)X
+3141(or)X
+3235(more)X
+3427(times)X
+3627(in)X
+3716(the)X
+2 f
+3841(to)X
+1 f
+3930(\256eld.)X
+4139(Parts)X
+555 5555(have)N
+2 f
+727(x)X
+1 f
+783(and)X
+2 f
+919(y)X
+1 f
+975(locations)X
+1284(set)X
+1393(randomly)X
+1720(in)X
+1802(an)X
+1898(appropriate)X
+2284(range.)X
+
+14 p
+%%Page: 14 14
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+755 630(The)N
+900(intent)X
+1102(of)X
+1189(OO1)X
+1365(is)X
+1438(to)X
+1520(measure)X
+1808(the)X
+1926(overall)X
+2169(cost)X
+2318(of)X
+2405(a)X
+2461(query)X
+2664(mix)X
+2808(characteristic)X
+3257(of)X
+3344(engineering)X
+3743(database)X
+4040(applica-)X
+555 720(tions.)N
+770(There)X
+978(are)X
+1097(three)X
+1278(tests:)X
+10 f
+635 843(g)N
+2 f
+755(Lookup)X
+1 f
+1022(generates)X
+1353(1,000)X
+1560(random)X
+1832(part)X
+2 f
+1984(ids)X
+1 f
+2077(,)X
+2124(fetches)X
+2378(the)X
+2502(corresponding)X
+2987(parts)X
+3169(from)X
+3351(the)X
+3475(database,)X
+3798(and)X
+3940(calls)X
+4113(a)X
+4175(null)X
+755 933(procedure)N
+1097(in)X
+1179(the)X
+1297(host)X
+1450(programming)X
+1906(language)X
+2216(with)X
+2378(the)X
+2496(parts')X
+2 f
+2699(x)X
+1 f
+2755(and)X
+2 f
+2891(y)X
+1 f
+2947(positions.)X
+10 f
+635 1056(g)N
+2 f
+755(Traverse)X
+1 f
+1067(retrieves)X
+1371(a)X
+1434(random)X
+1706(part)X
+1858(from)X
+2041(the)X
+2166(database)X
+2470(and)X
+2613(follows)X
+2880(connections)X
+3290(from)X
+3473(it)X
+3544(to)X
+3632(other)X
+3823(parts.)X
+4045(Each)X
+4232(of)X
+755 1146(those)N
+947(parts)X
+1126(is)X
+1202(retrieved,)X
+1531(and)X
+1670(all)X
+1773(connections)X
+2179(from)X
+2358(it)X
+2424(followed.)X
+2771(This)X
+2935(procedure)X
+3279(is)X
+3354(repeated)X
+3649(depth-\256rst)X
+4000(for)X
+4116(seven)X
+755 1236(hops)N
+930(from)X
+1110(the)X
+1232(original)X
+1505(part,)X
+1674(for)X
+1792(a)X
+1852(total)X
+2018(of)X
+2109(3280)X
+2293(parts.)X
+2513(Backward)X
+2862(traversal)X
+3162(also)X
+3314(exists,)X
+3539(and)X
+3678(follows)X
+3941(all)X
+4044(connec-)X
+755 1326(tions)N
+930(into)X
+1074(a)X
+1130(given)X
+1328(part)X
+1473(to)X
+1555(their)X
+1722(origin.)X
+10 f
+635 1449(g)N
+2 f
+755(Insert)X
+1 f
+962(adds)X
+1129(100)X
+1269(new)X
+1423(parts)X
+1599(and)X
+1735(their)X
+1902(connections.)X
+755 1572(The)N
+913(benchmark)X
+1303(is)X
+1389(single-user,)X
+1794(but)X
+1929(multi-user)X
+2291(access)X
+2530(controls)X
+2821(\(locking)X
+3120(and)X
+3268(transaction)X
+3652(protection\))X
+4036(must)X
+4223(be)X
+555 1662(enforced.)N
+898(It)X
+968(is)X
+1042(designed)X
+1348(to)X
+1431(be)X
+1528(run)X
+1656(on)X
+1757(a)X
+1814(database)X
+2112(with)X
+2275(20,000)X
+2516(parts,)X
+2713(and)X
+2850(on)X
+2951(one)X
+3087(with)X
+3249(200,000)X
+3529(parts.)X
+3745(Because)X
+4033(we)X
+4147(have)X
+555 1752(insuf\256cient)N
+935(disk)X
+1088(space)X
+1287(for)X
+1401(the)X
+1519(larger)X
+1727(database,)X
+2044(we)X
+2158(report)X
+2370(results)X
+2599(only)X
+2761(for)X
+2875(the)X
+2993(20,000)X
+3233(part)X
+3378(database.)X
+3 f
+555 1938(5.2.1.)N
+775(Implementation)X
+1 f
+755 2061(The)N
+920(LIBTP)X
+1182(implementation)X
+1724(of)X
+1831(OO1)X
+2027(uses)X
+2205(the)X
+2342(TCL)X
+2532([OUST90])X
+2914(interface)X
+3235(described)X
+3582(earlier.)X
+3867(The)X
+4031(backend)X
+555 2151(accepts)N
+813(commands)X
+1181(over)X
+1345(an)X
+1442(IP)X
+1534(socket)X
+1760(and)X
+1897(performs)X
+2208(the)X
+2327(requested)X
+2656(database)X
+2954(actions.)X
+3242(The)X
+3387(frontend)X
+3679(opens)X
+3886(and)X
+4022(executes)X
+555 2241(a)N
+618(TCL)X
+796(script.)X
+1041(This)X
+1210(script)X
+1415(contains)X
+1709(database)X
+2013(accesses)X
+2313(interleaved)X
+2697(with)X
+2866(ordinary)X
+3165(program)X
+3463(control)X
+3716(statements.)X
+4120(Data-)X
+555 2331(base)N
+718(commands)X
+1085(are)X
+1204(submitted)X
+1539(to)X
+1621(the)X
+1739(backend)X
+2027(and)X
+2163(results)X
+2392(are)X
+2511(bound)X
+2731(to)X
+2813(program)X
+3105(variables.)X
+755 2454(The)N
+903(parts)X
+1082(table)X
+1261(was)X
+1409(stored)X
+1628(as)X
+1718(a)X
+1776(B-tree)X
+1999(indexed)X
+2275(by)X
+2 f
+2377(id)X
+1 f
+2439(.)X
+2501(The)X
+2648(connection)X
+3022(table)X
+3200(was)X
+3347(stored)X
+3565(as)X
+3654(a)X
+3712(set)X
+3823(of)X
+3912(\256xed-length)X
+555 2544(records)N
+824(using)X
+1029(the)X
+1159(4.4BSD)X
+1446(recno)X
+1657(access)X
+1895(method.)X
+2207(In)X
+2306(addition,)X
+2620(two)X
+2771(B-tree)X
+3003(indices)X
+3261(were)X
+3449(maintained)X
+3836(on)X
+3947(connection)X
+555 2634(table)N
+732(entries.)X
+1007(One)X
+1162(index)X
+1360(mapped)X
+1634(the)X
+2 f
+1752(from)X
+1 f
+1923(\256eld)X
+2085(to)X
+2167(a)X
+2223(connection)X
+2595(record)X
+2821(number,)X
+3106(and)X
+3242(the)X
+3360(other)X
+3545(mapped)X
+3819(the)X
+2 f
+3937(to)X
+1 f
+4019(\256eld)X
+4181(to)X
+4263(a)X
+555 2724(connection)N
+932(record)X
+1163(number.)X
+1473(These)X
+1690(indices)X
+1941(support)X
+2205(fast)X
+2345(lookups)X
+2622(on)X
+2726(connections)X
+3133(in)X
+3219(both)X
+3385(directions.)X
+3765(For)X
+3900(the)X
+4022(traversal)X
+555 2814(tests,)N
+743(the)X
+867(frontend)X
+1165(does)X
+1338(an)X
+1439(index)X
+1642(lookup)X
+1889(to)X
+1976(discover)X
+2273(the)X
+2396(connected)X
+2747(part's)X
+2 f
+2955(id)X
+1 f
+3017(,)X
+3062(and)X
+3203(then)X
+3366(does)X
+3538(another)X
+3804(lookup)X
+4051(to)X
+4138(fetch)X
+555 2904(the)N
+673(part)X
+818(itself.)X
+3 f
+555 3090(5.2.2.)N
+775(Performance)X
+1242(Measurements)X
+1766(for)X
+1889(OO1)X
+1 f
+755 3213(We)N
+888(compare)X
+1186(LIBTP's)X
+1487(OO1)X
+1664(performance)X
+2092(to)X
+2174(that)X
+2314(reported)X
+2602(in)X
+2684([CATT91].)X
+3087(Those)X
+3303(results)X
+3532(were)X
+3709(collected)X
+4019(on)X
+4119(a)X
+4175(Sun)X
+555 3303(3/280)N
+759(\(25)X
+888(MHz)X
+1075(MC68020\))X
+1448(with)X
+1612(16)X
+1714(MBytes)X
+1989(of)X
+2078(memory)X
+2367(and)X
+2505(two)X
+2647(Hitachi)X
+2904(892MByte)X
+3267(disks)X
+3452(\(15)X
+3580(ms)X
+3694(average)X
+3966(seek)X
+4130(time\))X
+555 3393(behind)N
+793(an)X
+889(SMD-4)X
+1149(controller.)X
+1521(Frontends)X
+1861(ran)X
+1984(on)X
+2084(an)X
+2180(8MByte)X
+2462(Sun)X
+2606(3/260.)X
+755 3516(In)N
+844(order)X
+1036(to)X
+1120(measure)X
+1410(performance)X
+1839(on)X
+1941(a)X
+1999(machine)X
+2293(of)X
+2382(roughly)X
+2653(equivalent)X
+3009(processor)X
+3339(power,)X
+3582(we)X
+3698(ran)X
+3822(one)X
+3959(set)X
+4069(of)X
+4157(tests)X
+555 3606(on)N
+666(a)X
+733(standalone)X
+1107(MC68030-based)X
+1671(HP300)X
+1923(\(33MHz)X
+2225(MC68030\).)X
+2646(The)X
+2801(database)X
+3108(was)X
+3263(stored)X
+3489(on)X
+3599(a)X
+3665(300MByte)X
+4037(HP7959)X
+555 3696(SCSI)N
+744(disk)X
+898(\(17)X
+1026(ms)X
+1139(average)X
+1410(seek)X
+1573(time\).)X
+1802(Since)X
+2000(this)X
+2135(machine)X
+2427(is)X
+2500(not)X
+2622(connected)X
+2968(to)X
+3050(a)X
+3106(network,)X
+3409(we)X
+3523(ran)X
+3646(local)X
+3822(tests)X
+3984(where)X
+4201(the)X
+555 3786(frontend)N
+855(and)X
+999(backend)X
+1295(run)X
+1430(on)X
+1538(the)X
+1664(same)X
+1856(machine.)X
+2195(We)X
+2334(compare)X
+2638(these)X
+2830(measurements)X
+3316(with)X
+3485(Cattell's)X
+3783(local)X
+3966(Sun)X
+4117(3/280)X
+555 3876(numbers.)N
+755 3999(Because)N
+1051(the)X
+1177(benchmark)X
+1562(requires)X
+1849(remote)X
+2100(access,)X
+2354(we)X
+2476(ran)X
+2607(another)X
+2876(set)X
+2993(of)X
+3088(tests)X
+3258(on)X
+3365(a)X
+3428(DECstation)X
+3828(5000/200)X
+4157(with)X
+555 4089(32M)N
+732(of)X
+825(memory)X
+1118(running)X
+1393(Ultrix)X
+1610(V4.0)X
+1794(and)X
+1936(a)X
+1998(DEC)X
+2184(1GByte)X
+2459(RZ57)X
+2666(SCSI)X
+2859(disk.)X
+3057(We)X
+3194(compare)X
+3496(the)X
+3619(local)X
+3800(performance)X
+4232(of)X
+555 4179(OO1)N
+734(on)X
+837(the)X
+958(DECstation)X
+1354(to)X
+1439(its)X
+1536(remote)X
+1781(performance.)X
+2250(For)X
+2383(the)X
+2503(remote)X
+2748(case,)X
+2929(we)X
+3045(ran)X
+3170(the)X
+3290(frontend)X
+3584(on)X
+3686(a)X
+3744(DECstation)X
+4139(3100)X
+555 4269(with)N
+717(16)X
+817(MBytes)X
+1090(of)X
+1177(main)X
+1357(memory.)X
+755 4392(The)N
+900(databases)X
+1228(tested)X
+1435(in)X
+1517([CATT91])X
+1880(are)X
+10 f
+635 4515(g)N
+1 f
+755(INDEX,)X
+1045(a)X
+1101(highly-optimized)X
+1672(access)X
+1898(method)X
+2158(package)X
+2442(developed)X
+2792(at)X
+2870(Sun)X
+3014(Microsystems.)X
+10 f
+635 4638(g)N
+1 f
+755(OODBMS,)X
+1137(a)X
+1193(beta)X
+1347(release)X
+1591(of)X
+1678(a)X
+1734(commercial)X
+2133(object-oriented)X
+2639(database)X
+2936(management)X
+3366(system.)X
+10 f
+635 4761(g)N
+1 f
+755(RDBMS,)X
+1076(a)X
+1133(UNIX-based)X
+1565(commercial)X
+1965(relational)X
+2289(data)X
+2444(manager)X
+2742(at)X
+2821(production)X
+3189(release.)X
+3474(The)X
+3620(OO1)X
+3797(implementation)X
+755 4851(used)N
+922(embedded)X
+1272(SQL)X
+1443(in)X
+1525(C.)X
+1638(Stored)X
+1867(procedures)X
+2240(were)X
+2417(de\256ned)X
+2673(to)X
+2755(reduce)X
+2990(client-server)X
+3412(traf\256c.)X
+755 4974(Table)N
+974(two)X
+1130(shows)X
+1366(the)X
+1500(measurements)X
+1995(from)X
+2187([CATT91])X
+2566(and)X
+2718(LIBTP)X
+2976(for)X
+3106(a)X
+3178(local)X
+3370(test)X
+3517(on)X
+3632(the)X
+3765(MC680x0-based)X
+555 5064(hardware.)N
+915(All)X
+1037(caches)X
+1272(are)X
+1391(cleared)X
+1644(before)X
+1870(each)X
+2038(test.)X
+2209(All)X
+2331(times)X
+2524(are)X
+2643(in)X
+2725(seconds.)X
+755 5187(Table)N
+960(two)X
+1102(shows)X
+1324(that)X
+1466(LIBTP)X
+1710(outperforms)X
+2123(the)X
+2242(commercial)X
+2642(relational)X
+2966(system,)X
+3229(but)X
+3352(is)X
+3426(slower)X
+3661(than)X
+3820(OODBMS)X
+4183(and)X
+555 5277(INDEX.)N
+872(Since)X
+1077(the)X
+1202(caches)X
+1444(were)X
+1628(cleared)X
+1888(at)X
+1973(the)X
+2098(start)X
+2263(of)X
+2356(each)X
+2530(test,)X
+2687(disk)X
+2846(throughput)X
+3223(is)X
+3302(critical)X
+3551(in)X
+3639(this)X
+3780(test.)X
+3957(The)X
+4108(single)X
+555 5367(SCSI)N
+749(HP)X
+877(drive)X
+1068(used)X
+1241(by)X
+1347(LIBTP)X
+1595(is)X
+1674(approximately)X
+2163(13%)X
+2336(slower)X
+2576(than)X
+2739(the)X
+2862(disks)X
+3051(used)X
+3223(in)X
+3310([CATT91])X
+3678(which)X
+3899(accounts)X
+4205(for)X
+555 5457(part)N
+700(of)X
+787(the)X
+905(difference.)X
+755 5580(OODBMS)N
+1118(and)X
+1255(INDEX)X
+1525(outperform)X
+1906(LIBTP)X
+2148(most)X
+2323(dramatically)X
+2744(on)X
+2844(traversal.)X
+3181(This)X
+3343(is)X
+3416(because)X
+3691(we)X
+3805(use)X
+3932(index)X
+4130(look-)X
+555 5670(ups)N
+689(to)X
+774(\256nd)X
+921(connections,)X
+1347(whereas)X
+1634(the)X
+1755(other)X
+1942(two)X
+2084(systems)X
+2359(use)X
+2488(a)X
+2546(link)X
+2692(access)X
+2920(method.)X
+3222(The)X
+3369(index)X
+3569(requires)X
+3850(us)X
+3943(to)X
+4027(examine)X
+
+15 p
+%%Page: 15 15
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+10 f
+555 679(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)N
+2 f
+606 769(Measure)N
+1 f
+1019(INDEX)X
+1389(OODBMS)X
+1851(RDBMS)X
+2250(LIBTP)X
+10 f
+555 771(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)N
+555 787(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)N
+1 f
+595 869(Lookup)N
+1114(5.4)X
+1490(12.9)X
+1950(27)X
+2291(27.2)X
+595 959(Traversal)N
+1074(13)X
+1530(9.8)X
+1950(90)X
+2291(47.3)X
+595 1049(Insert)N
+1114(7.4)X
+1530(1.5)X
+1950(22)X
+2331(9.7)X
+10 f
+555 1059(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)N
+555(c)X
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+959 1059(c)N
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+1329 1059(c)N
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+1791 1059(c)N
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+2190 1059(c)N
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+2512 1059(c)N
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+2618 679(i)N
+2629(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2 f
+2829 769(Measure)N
+3401(Cache)X
+3726(Local)X
+4028(Remote)X
+1 f
+10 f
+2618 771(i)N
+2629(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2618 787(i)N
+2629(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2658 869(Lookup)N
+3401(cold)X
+3747(15.7)X
+4078(20.6)X
+3401 959(warm)N
+3787(7.8)X
+4078(12.4)X
+10 f
+2618 969(i)N
+2629(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2658 1059(Forward)N
+2950(traversal)X
+3401(cold)X
+3747(28.4)X
+4078(52.6)X
+3401 1149(warm)N
+3747(23.5)X
+4078(47.4)X
+10 f
+2618 1159(i)N
+2629(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2658 1249(Backward)N
+3004(traversal)X
+3401(cold)X
+3747(24.2)X
+4078(47.4)X
+3401 1339(warm)N
+3747(24.3)X
+4078(47.6)X
+10 f
+2618 1349(i)N
+2629(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+1 f
+2658 1439(Insert)N
+3401(cold)X
+3787(7.5)X
+4078(10.3)X
+3401 1529(warm)N
+3787(6.7)X
+4078(10.9)X
+10 f
+2618 1539(i)N
+2629(iiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiii)X
+2618(c)X
+1479(c)Y
+1399(c)Y
+1319(c)Y
+1239(c)Y
+1159(c)Y
+1079(c)Y
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+3341 1539(c)N
+1479(c)Y
+1399(c)Y
+1319(c)Y
+1239(c)Y
+1159(c)Y
+1079(c)Y
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+3666 1539(c)N
+1479(c)Y
+1399(c)Y
+1319(c)Y
+1239(c)Y
+1159(c)Y
+1079(c)Y
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+3968 1539(c)N
+1479(c)Y
+1399(c)Y
+1319(c)Y
+1239(c)Y
+1159(c)Y
+1079(c)Y
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+4309 1539(c)N
+1479(c)Y
+1399(c)Y
+1319(c)Y
+1239(c)Y
+1159(c)Y
+1079(c)Y
+999(c)Y
+919(c)Y
+839(c)Y
+759(c)Y
+3 f
+587 1785(Table)N
+823(2:)X
+931(Local)X
+1163(MC680x0)X
+1538(Performance)X
+2026(of)X
+2133(Several)X
+587 1875(Systems)N
+883(on)X
+987(OO1.)X
+2667 1785(Table)N
+2909(3:)X
+3023(Local)X
+3260(vs.)X
+3397(Remote)X
+3707(Performance)X
+4200(of)X
+2667 1875(LIBTP)N
+2926(on)X
+3030(OO1.)X
+1 f
+10 f
+555 1998(h)N
+579(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)X
+1 f
+555 2274(two)N
+696(disk)X
+850(pages,)X
+1074(but)X
+1197(the)X
+1316(links)X
+1492(require)X
+1741(only)X
+1904(one,)X
+2061(regardless)X
+2408(of)X
+2496(database)X
+2794(size.)X
+2980(Cattell)X
+3214(reports)X
+3458(that)X
+3599(lookups)X
+3873(using)X
+4067(B-trees)X
+555 2364(instead)N
+808(of)X
+901(links)X
+1082(makes)X
+1313(traversal)X
+1616(take)X
+1776(twice)X
+1976(as)X
+2069(long)X
+2237(in)X
+2325(INDEX.)X
+2641(Adding)X
+2907(a)X
+2969(link)X
+3119(access)X
+3351(method)X
+3617(to)X
+3 f
+3704(db)X
+1 f
+3792(\(3\))X
+3911(or)X
+4003(using)X
+4201(the)X
+555 2454(existing)N
+828(hash)X
+995(method)X
+1255(would)X
+1475(apparently)X
+1834(be)X
+1930(a)X
+1986(good)X
+2166(idea.)X
+755 2577(Both)N
+936(OODBMS)X
+1304(and)X
+1446(INDEX)X
+1722(issue)X
+1908 0.1944(coarser-granularity)AX
+2545(locks)X
+2739(than)X
+2902(LIBTP.)X
+3189(This)X
+3356(limits)X
+3562(concurrency)X
+3985(for)X
+4104(multi-)X
+555 2667(user)N
+711(applications,)X
+1140(but)X
+1264(helps)X
+1455(single-user)X
+1829(applications.)X
+2278(In)X
+2367(addition,)X
+2671(the)X
+2791(fact)X
+2934(that)X
+3076(LIBTP)X
+3319(releases)X
+3595(B-tree)X
+3817(locks)X
+4007(early)X
+4189(is)X
+4263(a)X
+555 2757(drawback)N
+896(in)X
+986(OO1.)X
+1210(Since)X
+1416(there)X
+1605(is)X
+1686(no)X
+1793(concurrency)X
+2218(in)X
+2307(the)X
+2432(benchmark,)X
+2836(high-concurrency)X
+3430(strategies)X
+3760(only)X
+3929(show)X
+4125(up)X
+4232(as)X
+555 2847(increased)N
+882(locking)X
+1145(overhead.)X
+1503(Finally,)X
+1772(the)X
+1892(architecture)X
+2294(of)X
+2383(the)X
+2503(LIBTP)X
+2747(implementation)X
+3271(was)X
+3418(substantially)X
+3844(different)X
+4143(from)X
+555 2937(that)N
+702(of)X
+796(either)X
+1006(OODBMS)X
+1375(or)X
+1469(INDEX.)X
+1786(Both)X
+1968(of)X
+2062(those)X
+2258(systems)X
+2538(do)X
+2645(the)X
+2770(searches)X
+3070(in)X
+3159(the)X
+3284(user's)X
+3503(address)X
+3771(space,)X
+3997(and)X
+4139(issue)X
+555 3027(requests)N
+844(for)X
+964(pages)X
+1173(to)X
+1260(the)X
+1383(server)X
+1605(process.)X
+1911(Pages)X
+2123(are)X
+2247(cached)X
+2496(in)X
+2583(the)X
+2706(client,)X
+2929(and)X
+3070(many)X
+3273(queries)X
+3530(can)X
+3667(be)X
+3768(satis\256ed)X
+4055(without)X
+555 3117(contacting)N
+910(the)X
+1029(server)X
+1247(at)X
+1326(all.)X
+1467(LIBTP)X
+1710(submits)X
+1979(all)X
+2080(the)X
+2199(queries)X
+2452(to)X
+2535(the)X
+2653(server)X
+2870(process,)X
+3151(and)X
+3287(receives)X
+3571(database)X
+3868(records)X
+4125(back;)X
+555 3207(it)N
+619(does)X
+786(no)X
+886(client)X
+1084(caching.)X
+755 3330(The)N
+911(RDBMS)X
+1221(architecture)X
+1632(is)X
+1716(much)X
+1925(closer)X
+2148(to)X
+2241(that)X
+2392(of)X
+2490(LIBTP.)X
+2783(A)X
+2872(server)X
+3100(process)X
+3372(receives)X
+3667(queries)X
+3930(and)X
+4076(returns)X
+555 3420(results)N
+786(to)X
+870(a)X
+928(client.)X
+1168(The)X
+1315(timing)X
+1545(results)X
+1776(in)X
+1860(table)X
+2038(two)X
+2180(clearly)X
+2421(show)X
+2612(that)X
+2754(the)X
+2874(conventional)X
+3309(database)X
+3607(client/server)X
+4025(model)X
+4246(is)X
+555 3510(expensive.)N
+941(LIBTP)X
+1188(outperforms)X
+1605(the)X
+1728(RDBMS)X
+2032(on)X
+2136(traversal)X
+2437(and)X
+2577(insertion.)X
+2921(We)X
+3057(speculate)X
+3380(that)X
+3524(this)X
+3663(is)X
+3740(due)X
+3880(in)X
+3966(part)X
+4115(to)X
+4201(the)X
+555 3600(overhead)N
+870(of)X
+957(query)X
+1160(parsing,)X
+1436(optimization,)X
+1880(and)X
+2016(repeated)X
+2309(interpretation)X
+2761(of)X
+2848(the)X
+2966(plan)X
+3124(tree)X
+3265(in)X
+3347(the)X
+3465(RDBMS')X
+3791(query)X
+3994(executor.)X
+755 3723(Table)N
+962(three)X
+1147(shows)X
+1371(the)X
+1492(differences)X
+1873(between)X
+2164(local)X
+2343(and)X
+2482(remote)X
+2728(execution)X
+3063(of)X
+3153(LIBTP's)X
+3456(OO1)X
+3635(implementation)X
+4160(on)X
+4263(a)X
+555 3813(DECstation.)N
+989(We)X
+1122(measured)X
+1451(performance)X
+1879(with)X
+2042(a)X
+2099(populated)X
+2436(\(warm\))X
+2694(cache)X
+2899(and)X
+3036(an)X
+3133(empty)X
+3354(\(cold\))X
+3567(cache.)X
+3812(Reported)X
+4126(times)X
+555 3903(are)N
+681(the)X
+806(means)X
+1037(of)X
+1130(twenty)X
+1374(tests,)X
+1562(and)X
+1704(are)X
+1829(in)X
+1917(seconds.)X
+2237(Standard)X
+2548(deviations)X
+2903(were)X
+3086(within)X
+3316(seven)X
+3525(percent)X
+3788(of)X
+3881(the)X
+4005(mean)X
+4205(for)X
+555 3993(remote,)N
+818(and)X
+954(two)X
+1094(percent)X
+1351(of)X
+1438(the)X
+1556(mean)X
+1750(for)X
+1864(local.)X
+755 4116(The)N
+914(20ms)X
+1121(overhead)X
+1450(of)X
+1551(TCP/IP)X
+1824(on)X
+1938(an)X
+2048(Ethernet)X
+2354(entirely)X
+2633(accounts)X
+2948(for)X
+3076(the)X
+3207(difference)X
+3567(in)X
+3662(speed.)X
+3918(The)X
+4076(remote)X
+555 4206(traversal)N
+857(times)X
+1055(are)X
+1179(nearly)X
+1405(double)X
+1648(the)X
+1771(local)X
+1952(times)X
+2150(because)X
+2430(we)X
+2549(do)X
+2653(index)X
+2855(lookups)X
+3132(and)X
+3272(part)X
+3421(fetches)X
+3673(in)X
+3759(separate)X
+4047(queries.)X
+555 4296(It)N
+629(would)X
+854(make)X
+1053(sense)X
+1252(to)X
+1339(do)X
+1444(indexed)X
+1723(searches)X
+2021(on)X
+2126(the)X
+2248(server,)X
+2489(but)X
+2615(we)X
+2733(were)X
+2914(unwilling)X
+3244(to)X
+3330(hard-code)X
+3676(knowledge)X
+4052(of)X
+4143(OO1)X
+555 4386(indices)N
+803(into)X
+948(our)X
+1075(LIBTP)X
+1317(TCL)X
+1488(server.)X
+1745(Cold)X
+1920(and)X
+2056(warm)X
+2259(insertion)X
+2559(times)X
+2752(are)X
+2871(identical)X
+3167(since)X
+3352(insertions)X
+3683(do)X
+3783(not)X
+3905(bene\256t)X
+4143(from)X
+555 4476(caching.)N
+755 4599(One)N
+915(interesting)X
+1279(difference)X
+1632(shown)X
+1867(by)X
+1973(table)X
+2155(three)X
+2342(is)X
+2421(the)X
+2545(cost)X
+2700(of)X
+2793(forward)X
+3074(versus)X
+3305(backward)X
+3644(traversal.)X
+3987(When)X
+4205(we)X
+555 4689(built)N
+725(the)X
+847(database,)X
+1168(we)X
+1285(inserted)X
+1562(parts)X
+1741(in)X
+1826(part)X
+2 f
+1974(id)X
+1 f
+2059(order.)X
+2292(We)X
+2427(built)X
+2596(the)X
+2717(indices)X
+2967(at)X
+3048(the)X
+3169(same)X
+3357(time.)X
+3562(Therefore,)X
+3923(the)X
+4044(forward)X
+555 4779(index)N
+757(had)X
+897(keys)X
+1068(inserted)X
+1346(in)X
+1432(order,)X
+1646(while)X
+1848(the)X
+1970(backward)X
+2307(index)X
+2509(had)X
+2649(keys)X
+2820(inserted)X
+3098(more)X
+3286(randomly.)X
+3656(In-order)X
+3943(insertion)X
+4246(is)X
+555 4885(pessimal)N
+858(for)X
+975(B-tree)X
+1199(indices,)X
+1469(so)X
+1563(the)X
+1684(forward)X
+1962(index)X
+2163(is)X
+2239(much)X
+2440(larger)X
+2651(than)X
+2812(the)X
+2933(backward)X
+3269(one)X
+7 s
+3385 4853(5)N
+10 s
+4885(.)Y
+3476(This)X
+3640(larger)X
+3850(size)X
+3997(shows)X
+4219(up)X
+555 4975(as)N
+642(extra)X
+823(disk)X
+976(reads)X
+1166(in)X
+1248(the)X
+1366(cold)X
+1524(benchmark.)X
+3 f
+555 5161(6.)N
+655(Conclusions)X
+1 f
+755 5284(LIBTP)N
+1006(provides)X
+1311(the)X
+1438(basic)X
+1632(building)X
+1927(blocks)X
+2165(to)X
+2256(support)X
+2525(transaction)X
+2906(protection.)X
+3300(In)X
+3396(comparison)X
+3799(with)X
+3970(traditional)X
+555 5374(Unix)N
+746(libraries)X
+1040(and)X
+1187(commercial)X
+1597(systems,)X
+1900(it)X
+1974(offers)X
+2192(a)X
+2258(variety)X
+2511(of)X
+2608(tradeoffs.)X
+2964(Using)X
+3185(complete)X
+3509(transaction)X
+3891(protection)X
+4246(is)X
+555 5464(more)N
+747(complicated)X
+1166(than)X
+1331(simply)X
+1575(adding)X
+3 f
+1820(fsync)X
+1 f
+1998(\(2\))X
+2119(and)X
+3 f
+2262(\257ock)X
+1 f
+2426(\(2\))X
+2547(calls)X
+2721(to)X
+2810(code,)X
+3008(but)X
+3136(it)X
+3206(is)X
+3285(faster)X
+3490(in)X
+3578(some)X
+3773(cases)X
+3969(and)X
+4111(offers)X
+8 s
+10 f
+555 5536(hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh)N
+5 s
+1 f
+727 5614(5)N
+8 s
+763 5639(The)N
+878(next)X
+1004(release)X
+1196(of)X
+1265(the)X
+1359(4.4BSD)X
+1580(access)X
+1758(method)X
+1966(will)X
+2082(automatically)X
+2446(detect)X
+2614(and)X
+2722(compensate)X
+3039(for)X
+3129(in-order)X
+3350(insertion,)X
+3606(eliminating)X
+3914(this)X
+4023(problem.)X
+
+16 p
+%%Page: 16 16
+8 s 8 xH 0 xS 1 f
+10 s
+3 f
+1 f
+555 630(stricter)N
+801(guarantees)X
+1168(\(atomicity,)X
+1540(consistency,)X
+1957(isolation,)X
+2275(and)X
+2414(durability\).)X
+2815(If)X
+2892(the)X
+3013(data)X
+3170(to)X
+3255(be)X
+3354(protected)X
+3676(are)X
+3798(already)X
+4058(format-)X
+555 720(ted)N
+675(\()X
+2 f
+702(i.e.)X
+1 f
+821(use)X
+949(one)X
+1086(of)X
+1174(the)X
+1293(database)X
+1591(access)X
+1818(methods\),)X
+2157(then)X
+2316(adding)X
+2555(transaction)X
+2928(protection)X
+3274(requires)X
+3554(no)X
+3655(additional)X
+3996(complex-)X
+555 810(ity,)N
+679(but)X
+801(incurs)X
+1017(a)X
+1073(performance)X
+1500(penalty)X
+1756(of)X
+1843(approximately)X
+2326(15%.)X
+755 933(In)N
+844(comparison)X
+1240(with)X
+1404(commercial)X
+1805(database)X
+2104(systems,)X
+2399(the)X
+2519(tradeoffs)X
+2827(are)X
+2948(more)X
+3135(complex.)X
+3473(LIBTP)X
+3717(does)X
+3886(not)X
+4009(currently)X
+555 1023(support)N
+825(a)X
+891(standard)X
+1193(query)X
+1406(language.)X
+1766(The)X
+1921(TCL-based)X
+2312(server)X
+2539(process)X
+2810(allows)X
+3049(a)X
+3115(certain)X
+3364(ease)X
+3533(of)X
+3630(use)X
+3767(which)X
+3993(would)X
+4223(be)X
+555 1113(enhanced)N
+882(with)X
+1047(a)X
+1106(more)X
+1294(user-friendly)X
+1732(interface)X
+2037(\()X
+2 f
+2064(e.g.)X
+1 f
+2203(a)X
+2261(windows)X
+2572(based)X
+2777(query-by-form)X
+3272(application\),)X
+3697(for)X
+3813(which)X
+4031(we)X
+4147(have)X
+555 1203(a)N
+620(working)X
+916(prototype.)X
+1292(When)X
+1513(accesses)X
+1815(do)X
+1924(not)X
+2055(require)X
+2312(sophisticated)X
+2758(query)X
+2969(processing,)X
+3360(the)X
+3486(TCL)X
+3665(interface)X
+3975(is)X
+4056(an)X
+4160(ade-)X
+555 1293(quate)N
+756(solution.)X
+1080(What)X
+1281(LIBTP)X
+1529(fails)X
+1693(to)X
+1781(provide)X
+2052(in)X
+2140(functionality,)X
+2595(it)X
+2665(makes)X
+2896(up)X
+3002(for)X
+3122(in)X
+3210(performance)X
+3643(and)X
+3785(\257exibility.)X
+4161(Any)X
+555 1383(application)N
+931(may)X
+1089(make)X
+1283(use)X
+1410(of)X
+1497(its)X
+1592(record)X
+1818(interface)X
+2120(or)X
+2207(the)X
+2325(more)X
+2510(primitive)X
+2823(log,)X
+2965(lock,)X
+3143(and)X
+3279(buffer)X
+3496(calls.)X
+755 1506(Future)N
+987(work)X
+1175(will)X
+1322(focus)X
+1519(on)X
+1621(overcoming)X
+2026(some)X
+2217(of)X
+2306(the)X
+2426(areas)X
+2614(in)X
+2698(which)X
+2916(LIBTP)X
+3160(is)X
+3235(currently)X
+3547(de\256cient)X
+3845(and)X
+3983(extending)X
+555 1596(its)N
+652(transaction)X
+1026(model.)X
+1288(The)X
+1435(addition)X
+1719(of)X
+1808(an)X
+1905(SQL)X
+2077(parser)X
+2295(and)X
+2432(forms)X
+2640(front)X
+2817(end)X
+2954(will)X
+3099(improve)X
+3387(the)X
+3506(system's)X
+3807(ease)X
+3967(of)X
+4055(use)X
+4183(and)X
+555 1686(make)N
+750(it)X
+815(more)X
+1001(competitive)X
+1400(with)X
+1563(commercial)X
+1963(systems.)X
+2277(In)X
+2365(the)X
+2484(long)X
+2647(term,)X
+2835(we)X
+2950(would)X
+3170(like)X
+3310(to)X
+3392(add)X
+3528(generalized)X
+3919(hierarchical)X
+555 1776(locking,)N
+836(nested)X
+1062(transactions,)X
+1486(parallel)X
+1748(transactions,)X
+2171(passing)X
+2431(of)X
+2518(transactions)X
+2921(between)X
+3209(processes,)X
+3557(and)X
+3693(distributed)X
+4055(commit)X
+555 1866(handling.)N
+900(In)X
+992(the)X
+1115(short)X
+1300(term,)X
+1492(the)X
+1614(next)X
+1776(step)X
+1929(is)X
+2006(to)X
+2092(integrate)X
+2397(LIBTP)X
+2643(with)X
+2809(the)X
+2931(most)X
+3110(recent)X
+3331(release)X
+3579(of)X
+3670(the)X
+3792(database)X
+4093(access)X
+555 1956(routines)N
+833(and)X
+969(make)X
+1163(it)X
+1227(freely)X
+1435(available)X
+1745(via)X
+1863(anonymous)X
+2252(ftp.)X
+3 f
+555 2142(7.)N
+655(Acknowledgements)X
+1 f
+755 2265(We)N
+888(would)X
+1109(like)X
+1250(to)X
+1332(thank)X
+1530(John)X
+1701(Wilkes)X
+1948(and)X
+2084(Carl)X
+2242(Staelin)X
+2484(of)X
+2571(Hewlett-Packard)X
+3131(Laboratories)X
+3557(and)X
+3693(Jon)X
+3824(Krueger.)X
+4148(John)X
+555 2355(and)N
+694(Carl)X
+855(provided)X
+1162(us)X
+1255(with)X
+1419(an)X
+1517(extra)X
+1700(disk)X
+1855(for)X
+1971(the)X
+2091(HP)X
+2215(testbed)X
+2464(less)X
+2606(than)X
+2766(24)X
+2868(hours)X
+3068(after)X
+3238(we)X
+3354(requested)X
+3684(it.)X
+3770(Jon)X
+3903(spent)X
+4094(count-)X
+555 2445(less)N
+699(hours)X
+901(helping)X
+1164(us)X
+1258(understand)X
+1633(the)X
+1754(intricacies)X
+2107(of)X
+2197(commercial)X
+2599(database)X
+2899(products)X
+3198(and)X
+3337(their)X
+3507(behavior)X
+3811(under)X
+4017(a)X
+4076(variety)X
+555 2535(of)N
+642(system)X
+884(con\256gurations.)X
+3 f
+555 2721(8.)N
+655(References)X
+1 f
+555 2901([ANDR89])N
+942(Andrade,)X
+1265(J.,)X
+1361(Carges,)X
+1629(M.,)X
+1765(Kovach,)X
+2060(K.,)X
+2183(``Building)X
+2541(an)X
+2642(On-Line)X
+2939(Transaction)X
+3343(Processing)X
+3715(System)X
+3975(On)X
+4098(UNIX)X
+727 2991(System)N
+982(V'',)X
+2 f
+1134(CommUNIXations)X
+1 f
+1725(,)X
+1765 0.2188(November/December)AX
+2477(1989.)X
+555 3171([BAY77])N
+878(Bayer,)X
+1110(R.,)X
+1223(Schkolnick,)X
+1623(M.,)X
+1754(``Concurrency)X
+2243(of)X
+2330(Operations)X
+2702(on)X
+2802(B-Trees'',)X
+2 f
+3155(Acta)X
+3322(Informatica)X
+1 f
+3700(,)X
+3740(1977.)X
+555 3351([BERN80])N
+936(Bernstein,)X
+1297(P.,)X
+1415(Goodman,)X
+1785(N.,)X
+1917(``Timestamp)X
+2365(Based)X
+2595(Algorithms)X
+2992(for)X
+3119(Concurrency)X
+3567(Control)X
+3844(in)X
+3939(Distributed)X
+727 3441(Database)N
+1042(Systems'',)X
+2 f
+1402(Proceedings)X
+1823(6th)X
+1945(International)X
+2387(Conference)X
+2777(on)X
+2877(Very)X
+3049(Large)X
+3260(Data)X
+3440(Bases)X
+1 f
+3627(,)X
+3667(October)X
+3946(1980.)X
+555 3621([BSD91])N
+864(DB\(3\),)X
+2 f
+1109(4.4BSD)X
+1376(Unix)X
+1552(Programmer's)X
+2044(Manual)X
+2313(Reference)X
+2655(Guide)X
+1 f
+2851(,)X
+2891(University)X
+3249(of)X
+3336(California,)X
+3701(Berkeley,)X
+4031(1991.)X
+555 3801([CATT91])N
+923(Cattell,)X
+1181(R.G.G.,)X
+1455(``An)X
+1632(Engineering)X
+2049(Database)X
+2369(Benchmark'',)X
+2 f
+2838(The)X
+2983(Benchmark)X
+3373(Handbook)X
+3731(for)X
+3848(Database)X
+4179(and)X
+727 3891(Transaction)N
+1133(Processing)X
+1509(Systems)X
+1 f
+1763(,)X
+1803(J.)X
+1874(Gray,)X
+2075(editor,)X
+2302(Morgan)X
+2576(Kaufman)X
+2895(1991.)X
+555 4071([CHEN91])N
+929(Cheng,)X
+1180(E.,)X
+1291(Chang,)X
+1542(E.,)X
+1653(Klein,)X
+1872(J.,)X
+1964(Lee,)X
+2126(D.,)X
+2245(Lu,)X
+2375(E.,)X
+2485(Lutgardo,)X
+2820(A.,)X
+2939(Obermarck,)X
+3342(R.,)X
+3456(``An)X
+3629(Open)X
+3824(and)X
+3961(Extensible)X
+727 4161(Event-Based)N
+1157(Transaction)X
+1556(Manager'',)X
+2 f
+1936(Proceedings)X
+2357(1991)X
+2537(Summer)X
+2820(Usenix)X
+1 f
+3043(,)X
+3083(Nashville,)X
+3430(TN,)X
+3577(June)X
+3744(1991.)X
+555 4341([CHOU85])N
+943(Chou,)X
+1163(H.,)X
+1288(DeWitt,)X
+1570(D.,)X
+1694(``An)X
+1872(Evaluation)X
+2245(of)X
+2338(Buffer)X
+2574(Management)X
+3019(Strategies)X
+3361(for)X
+3481(Relational)X
+3836(Database)X
+4157(Sys-)X
+727 4431(tems'',)N
+2 f
+972(Proceedings)X
+1393(of)X
+1475(the)X
+1593(11th)X
+1755(International)X
+2197(Conference)X
+2587(on)X
+2687(Very)X
+2859(Large)X
+3070(Databases)X
+1 f
+3408(,)X
+3448(1985.)X
+555 4611([DEWI84])N
+925(DeWitt,)X
+1207(D.,)X
+1331(Katz,)X
+1529(R.,)X
+1648(Olken,)X
+1890(F.,)X
+2000(Shapiro,)X
+2295(L.,)X
+2410(Stonebraker,)X
+2843(M.,)X
+2979(Wood,)X
+3220(D.,)X
+3343(``Implementation)X
+3929(Techniques)X
+727 4701(for)N
+841(Main)X
+1030(Memory)X
+1326(Database)X
+1641(Systems'',)X
+2 f
+2001(Proceedings)X
+2422(of)X
+2504(SIGMOD)X
+1 f
+2812(,)X
+2852(pp.)X
+2972(1-8,)X
+3119(June)X
+3286(1984.)X
+555 4881([GRAY76])N
+944(Gray,)X
+1153(J.,)X
+1252(Lorie,)X
+1474(R.,)X
+1595(Putzolu,)X
+1887(F.,)X
+1999(and)X
+2143(Traiger,)X
+2428(I.,)X
+2522(``Granularity)X
+2973(of)X
+3067(locks)X
+3263(and)X
+3406(degrees)X
+3679(of)X
+3773(consistency)X
+4174(in)X
+4263(a)X
+727 4971(large)N
+909(shared)X
+1140(data)X
+1295(base'',)X
+2 f
+1533(Modeling)X
+1861(in)X
+1944(Data)X
+2125(Base)X
+2301(Management)X
+2740(Systems)X
+1 f
+2994(,)X
+3034(Elsevier)X
+3317(North)X
+3524(Holland,)X
+3822(New)X
+3994(York,)X
+4199(pp.)X
+727 5061(365-394.)N
+555 5241([HAER83])N
+931(Haerder,)X
+1235(T.)X
+1348(Reuter,)X
+1606(A.)X
+1728(``Principles)X
+2126(of)X
+2217(Transaction-Oriented)X
+2928(Database)X
+3246(Recovery'',)X
+2 f
+3651(Computing)X
+4029(Surveys)X
+1 f
+4279(,)X
+727 5331(15\(4\);)N
+943(237-318,)X
+1250(1983.)X
+555 5511([KUNG81])N
+943(Kung,)X
+1162(H.)X
+1261(T.,)X
+1371(Richardson,)X
+1777(J.,)X
+1869(``On)X
+2042(Optimistic)X
+2400(Methods)X
+2701(for)X
+2816(Concurrency)X
+3252(Control'',)X
+2 f
+3591(ACM)X
+3781(Transactions)X
+4219(on)X
+727 5601(Database)N
+1054(Systems)X
+1 f
+1328(6\(2\);)X
+1504(213-226,)X
+1811(1981.)X
+
+17 p
+%%Page: 17 17
+10 s 10 xH 0 xS 1 f
+3 f
+1 f
+555 630([LEHM81])N
+939(Lehman,)X
+1245(P.,)X
+1352(Yao,)X
+1529(S.,)X
+1636(``Ef\256cient)X
+1989(Locking)X
+2279(for)X
+2396(Concurrent)X
+2780(Operations)X
+3155(on)X
+3258(B-trees'',)X
+2 f
+3587(ACM)X
+3779(Transactions)X
+4219(on)X
+727 720(Database)N
+1054(Systems)X
+1 f
+1308(,)X
+1348(6\(4\),)X
+1522(December)X
+1873(1981.)X
+555 900([MOHA91])N
+964(Mohan,)X
+1241(C.,)X
+1364(Pirahesh,)X
+1690(H.,)X
+1818(``ARIES-RRH:)X
+2366(Restricted)X
+2721(Repeating)X
+3076(of)X
+3173(History)X
+3442(in)X
+3533(the)X
+3660(ARIES)X
+3920(Transaction)X
+727 990(Recovery)N
+1055(Method'',)X
+2 f
+1398(Proceedings)X
+1819(7th)X
+1941(International)X
+2383(Conference)X
+2773(on)X
+2873(Data)X
+3053(Engineering)X
+1 f
+3449(,)X
+3489(Kobe,)X
+3703(Japan,)X
+3926(April)X
+4115(1991.)X
+555 1170([NODI90])N
+914(Nodine,)X
+1194(M.,)X
+1328(Zdonik,)X
+1602(S.,)X
+1709(``Cooperative)X
+2178(Transaction)X
+2580(Hierarchies:)X
+2996(A)X
+3077(Transaction)X
+3479(Model)X
+3711(to)X
+3796(Support)X
+4072(Design)X
+727 1260(Applications'',)N
+2 f
+1242(Proceedings)X
+1675(16th)X
+1849(International)X
+2303(Conference)X
+2704(on)X
+2815(Very)X
+2998(Large)X
+3220(Data)X
+3411(Bases)X
+1 f
+3598(,)X
+3649(Brisbane,)X
+3985(Australia,)X
+727 1350(August)N
+978(1990.)X
+555 1530([OUST90])N
+923(Ousterhout,)X
+1324(J.,)X
+1420(``Tcl:)X
+1648(An)X
+1771(Embeddable)X
+2197(Command)X
+2555(Language'',)X
+2 f
+2971(Proceedings)X
+3396(1990)X
+3580(Winter)X
+3822(Usenix)X
+1 f
+4045(,)X
+4089(Wash-)X
+727 1620(ington,)N
+971(D.C.,)X
+1162(January)X
+1432(1990.)X
+555 1800([POSIX91])N
+955(``Unapproved)X
+1441(Draft)X
+1645(for)X
+1773(Realtime)X
+2096(Extension)X
+2450(for)X
+2578(Portable)X
+2879(Operating)X
+3234(Systems'',)X
+3608(Draft)X
+3812(11,)X
+3946(October)X
+4239(7,)X
+727 1890(1991,)N
+927(IEEE)X
+1121(Computer)X
+1461(Society.)X
+555 2070([ROSE91])N
+925(Rosenblum,)X
+1341(M.,)X
+1484(Ousterhout,)X
+1892(J.,)X
+1995(``The)X
+2206(Design)X
+2464(and)X
+2611(Implementation)X
+3149(of)X
+3247(a)X
+3314(Log-Structured)X
+3835(File)X
+3990(System'',)X
+2 f
+727 2160(Proceedings)N
+1148(of)X
+1230(the)X
+1348(13th)X
+1510(Symposium)X
+1895(on)X
+1995(Operating)X
+2344(Systems)X
+2618(Principles)X
+1 f
+2947(,)X
+2987(1991.)X
+555 2340([SELT91])N
+904(Seltzer,)X
+1171(M.,)X
+1306(Stonebraker,)X
+1738(M.,)X
+1873(``Read)X
+2116(Optimized)X
+2478(File)X
+2626(Systems:)X
+2938(A)X
+3020(Performance)X
+3454(Evaluation'',)X
+2 f
+3898(Proceedings)X
+727 2430(7th)N
+849(Annual)X
+1100(International)X
+1542(Conference)X
+1932(on)X
+2032(Data)X
+2212(Engineering)X
+1 f
+2608(,)X
+2648(Kobe,)X
+2862(Japan,)X
+3085(April)X
+3274(1991.)X
+555 2610([SPEC88])N
+907(Spector,)X
+1200(Rausch,)X
+1484(Bruell,)X
+1732(``Camelot:)X
+2107(A)X
+2192(Flexible,)X
+2501(Distributed)X
+2888(Transaction)X
+3294(Processing)X
+3668(System'',)X
+2 f
+4004(Proceed-)X
+727 2700(ings)N
+880(of)X
+962(Spring)X
+1195(COMPCON)X
+1606(1988)X
+1 f
+(,)S
+1806(February)X
+2116(1988.)X
+555 2880([SQL86])N
+862(American)X
+1201(National)X
+1499(Standards)X
+1836(Institute,)X
+2139(``Database)X
+2509(Language)X
+2847(SQL'',)X
+3093(ANSI)X
+3301(X3.135-1986)X
+3747(\(ISO)X
+3924(9075\),)X
+4152(May)X
+727 2970(1986.)N
+555 3150([STON81])N
+919(Stonebraker,)X
+1348(M.,)X
+1480(``Operating)X
+1876(System)X
+2132(Support)X
+2406(for)X
+2520(Database)X
+2835(Management'',)X
+2 f
+3348(Communications)X
+3910(of)X
+3992(the)X
+4110(ACM)X
+1 f
+4279(,)X
+727 3240(1981.)N
+555 3420([SULL92])N
+925(Sullivan,)X
+1247(M.,)X
+1394(Olson,)X
+1641(M.,)X
+1788(``An)X
+1976(Index)X
+2195(Implementation)X
+2737(Supporting)X
+3127(Fast)X
+3295(Recovery)X
+3638(for)X
+3767(the)X
+3900(POSTGRES)X
+727 3510(Storage)N
+1014(System'',)X
+1365(to)X
+1469(appear)X
+1726(in)X
+2 f
+1830(Proceedings)X
+2272(8th)X
+2415(Annual)X
+2687(International)X
+3150(Conference)X
+3561(on)X
+3682(Data)X
+3883(Engineering)X
+1 f
+4279(,)X
+727 3600(Tempe,)N
+990(Arizona,)X
+1289(February)X
+1599(1992.)X
+555 3780([TPCB90])N
+914(Transaction)X
+1319(Processing)X
+1692(Performance)X
+2129(Council,)X
+2428(``TPC)X
+2653(Benchmark)X
+3048(B'',)X
+3200(Standard)X
+3510(Speci\256cation,)X
+3973(Waterside)X
+727 3870(Associates,)N
+1110(Fremont,)X
+1421(CA.,)X
+1592(1990.)X
+555 4050([YOUN91])N
+947(Young,)X
+1211(M.)X
+1328(W.,)X
+1470(Thompson,)X
+1858(D.)X
+1962(S.,)X
+2072(Jaffe,)X
+2274(E.,)X
+2388(``A)X
+2525(Modular)X
+2826(Architecture)X
+3253(for)X
+3372(Distributed)X
+3757(Transaction)X
+4161(Pro-)X
+727 4140(cessing'',)N
+2 f
+1057(Proceedings)X
+1478(1991)X
+1658(Winter)X
+1896(Usenix)X
+1 f
+2119(,)X
+2159(Dallas,)X
+2404(TX,)X
+2551(January)X
+2821(1991.)X
+3 f
+755 4263(Margo)N
+1008(I.)X
+1080(Seltzer)X
+1 f
+1338(is)X
+1411(a)X
+1467(Ph.D.)X
+1669(student)X
+1920(in)X
+2002(the)X
+2120(Department)X
+2519(of)X
+2606(Electrical)X
+2934(Engineering)X
+3346(and)X
+3482(Computer)X
+3822(Sciences)X
+4123(at)X
+4201(the)X
+555 4353(University)N
+919(of)X
+1012(California,)X
+1383(Berkeley.)X
+1739(Her)X
+1886(research)X
+2181(interests)X
+2474(include)X
+2735(\256le)X
+2862(systems,)X
+3160(databases,)X
+3513(and)X
+3654(transaction)X
+4031(process-)X
+555 4443(ing)N
+686(systems.)X
+1008(She)X
+1157(spent)X
+1355(several)X
+1612(years)X
+1811(working)X
+2107(at)X
+2194(startup)X
+2441(companies)X
+2813(designing)X
+3153(and)X
+3298(implementing)X
+3771(\256le)X
+3902(systems)X
+4183(and)X
+555 4533(transaction)N
+929(processing)X
+1294(software)X
+1592(and)X
+1729(designing)X
+2061(microprocessors.)X
+2648(Ms.)X
+2791(Seltzer)X
+3035(received)X
+3329(her)X
+3453(AB)X
+3585(in)X
+3668(Applied)X
+3947(Mathemat-)X
+555 4623(ics)N
+664(from)X
+840 0.1953(Harvard/Radcliffe)AX
+1445(College)X
+1714(in)X
+1796(1983.)X
+755 4746(In)N
+845(her)X
+971(spare)X
+1163(time,)X
+1347(Margo)X
+1583(can)X
+1717(usually)X
+1970(be)X
+2068(found)X
+2277(preparing)X
+2607(massive)X
+2887(quantities)X
+3220(of)X
+3309(food)X
+3478(for)X
+3594(hungry)X
+3843(hordes,)X
+4099(study-)X
+555 4836(ing)N
+677(Japanese,)X
+1003(or)X
+1090(playing)X
+1350(soccer)X
+1576(with)X
+1738(an)X
+1834(exciting)X
+2112(Bay)X
+2261(Area)X
+2438(Women's)X
+2770(Soccer)X
+3009(team,)X
+3205(the)X
+3323(Berkeley)X
+3633(Bruisers.)X
+3 f
+755 5049(Michael)N
+1056(A.)X
+1159(Olson)X
+1 f
+1383(is)X
+1461(a)X
+1522(Master's)X
+1828(student)X
+2084(in)X
+2170(the)X
+2292(Department)X
+2695(of)X
+2786(Electrical)X
+3118(Engineering)X
+3534(and)X
+3674(Computer)X
+4018(Sciences)X
+555 5139(at)N
+645(the)X
+774(University)X
+1143(of)X
+1241(California,)X
+1617(Berkeley.)X
+1978(His)X
+2120(primary)X
+2405(interests)X
+2703(are)X
+2833(database)X
+3141(systems)X
+3425(and)X
+3572(mass)X
+3763(storage)X
+4026(systems.)X
+555 5229(Mike)N
+759(spent)X
+963(two)X
+1118(years)X
+1323(working)X
+1625(for)X
+1754(a)X
+1825(commercial)X
+2239(database)X
+2551(system)X
+2808(vendor)X
+3066(before)X
+3307(joining)X
+3567(the)X
+3699(Postgres)X
+4004(Research)X
+555 5319(Group)N
+780(at)X
+858(Berkeley)X
+1168(in)X
+1250(1988.)X
+1470(He)X
+1584(received)X
+1877(his)X
+1990(B.A.)X
+2161(in)X
+2243(Computer)X
+2583(Science)X
+2853(from)X
+3029(Berkeley)X
+3339(in)X
+3421(May)X
+3588(1991.)X
+755 5442(Mike)N
+945(only)X
+1108(recently)X
+1388(transferred)X
+1758(into)X
+1903(Sin)X
+2030(City,)X
+2208(but)X
+2330(is)X
+2403(rapidly)X
+2650(adopting)X
+2950(local)X
+3126(customs)X
+3408(and)X
+3544(coloration.)X
+3929(In)X
+4016(his)X
+4129(spare)X
+555 5532(time,)N
+742(he)X
+843(organizes)X
+1176(informal)X
+1477(Friday)X
+1711(afternoon)X
+2043(study)X
+2240(groups)X
+2482(to)X
+2568(discuss)X
+2823(recent)X
+3044(technical)X
+3358(and)X
+3498(economic)X
+3834(developments.)X
+555 5622(Among)N
+815(his)X
+928(hobbies)X
+1197(are)X
+1316(Charles)X
+1581(Dickens,)X
+1884(Red)X
+2033(Rock,)X
+2242(and)X
+2378(speaking)X
+2683(Dutch)X
+2899(to)X
+2981(anyone)X
+3233(who)X
+3391(will)X
+3535(permit)X
+3764(it.)X
+
+17 p
+%%Trailer
+xt
+
+xs
+
diff --git a/lib/libc/db/hash/Makefile.inc b/lib/libc/db/hash/Makefile.inc
new file mode 100644
index 0000000..2ecb817
--- /dev/null
+++ b/lib/libc/db/hash/Makefile.inc
@@ -0,0 +1,7 @@
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/db/hash
+
+SRCS+= hash.c hash_bigkey.c hash_buf.c hash_func.c hash_log2.c \
+ hash_page.c ndbm.c
diff --git a/lib/libc/db/hash/README b/lib/libc/db/hash/README
new file mode 100644
index 0000000..80d6743
--- /dev/null
+++ b/lib/libc/db/hash/README
@@ -0,0 +1,69 @@
+# @(#)README 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+This package implements a superset of the hsearch and dbm/ndbm libraries.
+
+Test Programs:
+ All test programs which need key/data pairs expect them entered
+ with key and data on separate lines
+
+ tcreat3.c
+ Takes
+ bucketsize (bsize),
+ fill factor (ffactor), and
+ initial number of elements (nelem).
+ Creates a hash table named hashtest containing the
+ keys/data pairs entered from standard in.
+ thash4.c
+ Takes
+ bucketsize (bsize),
+ fill factor (ffactor),
+ initial number of elements (nelem)
+ bytes of cache (ncached), and
+ file from which to read data (fname)
+ Creates a table from the key/data pairs on standard in and
+ then does a read of each key/data in fname
+ tdel.c
+ Takes
+ bucketsize (bsize), and
+ fill factor (ffactor).
+ file from which to read data (fname)
+ Reads each key/data pair from fname and deletes the
+ key from the hash table hashtest
+ tseq.c
+ Reads the key/data pairs in the file hashtest and writes them
+ to standard out.
+ tread2.c
+ Takes
+ butes of cache (ncached).
+ Reads key/data pairs from standard in and looks them up
+ in the file hashtest.
+ tverify.c
+ Reads key/data pairs from standard in, looks them up
+ in the file hashtest, and verifies that the data is
+ correct.
+
+NOTES:
+
+The man page ../man/db.3 explains the interface to the hashing system.
+The file hash.ps is a postscript copy of a paper explaining
+the history, implementation, and performance of the hash package.
+
+"bugs" or idiosyncracies
+
+If you have a lot of overflows, it is possible to run out of overflow
+pages. Currently, this will cause a message to be printed on stderr.
+Eventually, this will be indicated by a return error code.
+
+If you are using the ndbm interface and exit without flushing or closing the
+file, you may lose updates since the package buffers all writes. Also,
+the db interface only creates a single database file. To avoid overwriting
+the user's original file, the suffix ".db" is appended to the file name
+passed to dbm_open. Additionally, if your code "knows" about the historic
+.dir and .pag files, it will break.
+
+There is a fundamental difference between this package and the old hsearch.
+Hsearch requires the user to maintain the keys and data in the application's
+allocated memory while hash takes care of all storage management. The down
+side is that the byte strings passed in the ENTRY structure must be null
+terminated (both the keys and the data).
diff --git a/lib/libc/db/hash/extern.h b/lib/libc/db/hash/extern.h
new file mode 100644
index 0000000..c75c0ac
--- /dev/null
+++ b/lib/libc/db/hash/extern.h
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)extern.h 8.4 (Berkeley) 6/16/94
+ * $FreeBSD$
+ */
+
+BUFHEAD *__add_ovflpage(HTAB *, BUFHEAD *);
+int __addel(HTAB *, BUFHEAD *, const DBT *, const DBT *);
+int __big_delete(HTAB *, BUFHEAD *);
+int __big_insert(HTAB *, BUFHEAD *, const DBT *, const DBT *);
+int __big_keydata(HTAB *, BUFHEAD *, DBT *, DBT *, int);
+int __big_return(HTAB *, BUFHEAD *, int, DBT *, int);
+int __big_split(HTAB *, BUFHEAD *, BUFHEAD *, BUFHEAD *,
+ int, u_int32_t, SPLIT_RETURN *);
+int __buf_free(HTAB *, int, int);
+void __buf_init(HTAB *, int);
+u_int32_t __call_hash(HTAB *, char *, int);
+int __delpair(HTAB *, BUFHEAD *, int);
+int __expand_table(HTAB *);
+int __find_bigpair(HTAB *, BUFHEAD *, int, char *, int);
+u_int16_t __find_last_page(HTAB *, BUFHEAD **);
+void __free_ovflpage(HTAB *, BUFHEAD *);
+BUFHEAD *__get_buf(HTAB *, u_int32_t, BUFHEAD *, int);
+int __get_page(HTAB *, char *, u_int32_t, int, int, int);
+int __ibitmap(HTAB *, int, int, int);
+u_int32_t __log2(u_int32_t);
+int __put_page(HTAB *, char *, u_int32_t, int, int);
+void __reclaim_buf(HTAB *, BUFHEAD *);
+int __split_page(HTAB *, u_int32_t, u_int32_t);
+
+/* Default hash routine. */
+extern u_int32_t (*__default_hash)(const void *, size_t);
+
+#ifdef HASH_STATISTICS
+extern int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
+#endif
diff --git a/lib/libc/db/hash/hash.c b/lib/libc/db/hash/hash.c
new file mode 100644
index 0000000..638814c
--- /dev/null
+++ b/lib/libc/db/hash/hash.c
@@ -0,0 +1,965 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash.c 8.9 (Berkeley) 6/16/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef DEBUG
+#include <assert.h>
+#endif
+#include "un-namespace.h"
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static int alloc_segs(HTAB *, int);
+static int flush_meta(HTAB *);
+static int hash_access(HTAB *, ACTION, DBT *, DBT *);
+static int hash_close(DB *);
+static int hash_delete(const DB *, const DBT *, u_int32_t);
+static int hash_fd(const DB *);
+static int hash_get(const DB *, const DBT *, DBT *, u_int32_t);
+static int hash_put(const DB *, DBT *, const DBT *, u_int32_t);
+static void *hash_realloc(SEGMENT **, int, int);
+static int hash_seq(const DB *, DBT *, DBT *, u_int32_t);
+static int hash_sync(const DB *, u_int32_t);
+static int hdestroy(HTAB *);
+static HTAB *init_hash(HTAB *, const char *, const HASHINFO *);
+static int init_htab(HTAB *, int);
+#if BYTE_ORDER == LITTLE_ENDIAN
+static void swap_header(HTAB *);
+static void swap_header_copy(HASHHDR *, HASHHDR *);
+#endif
+
+/* Fast arithmetic, relying on powers of 2, */
+#define MOD(x, y) ((x) & ((y) - 1))
+
+#define RETURN_ERROR(ERR, LOC) { save_errno = ERR; goto LOC; }
+
+/* Return values */
+#define SUCCESS (0)
+#define ERROR (-1)
+#define ABNORMAL (1)
+
+#ifdef HASH_STATISTICS
+int hash_accesses, hash_collisions, hash_expansions, hash_overflows;
+#endif
+
+/************************** INTERFACE ROUTINES ***************************/
+/* OPEN/CLOSE */
+
+/* ARGSUSED */
+DB *
+__hash_open(const char *file, int flags, int mode,
+ const HASHINFO *info, /* Special directives for create */
+ int dflags)
+{
+ HTAB *hashp;
+ struct stat statbuf;
+ DB *dbp;
+ int bpages, hdrsize, new_table, nsegs, save_errno;
+
+ if ((flags & O_ACCMODE) == O_WRONLY) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (!(hashp = (HTAB *)calloc(1, sizeof(HTAB))))
+ return (NULL);
+ hashp->fp = -1;
+
+ /*
+ * Even if user wants write only, we need to be able to read
+ * the actual file, so we need to open it read/write. But, the
+ * field in the hashp structure needs to be accurate so that
+ * we can check accesses.
+ */
+ hashp->flags = flags;
+
+ if (file) {
+ if ((hashp->fp = _open(file, flags, mode)) == -1)
+ RETURN_ERROR(errno, error0);
+ (void)_fcntl(hashp->fp, F_SETFD, 1);
+ new_table = _fstat(hashp->fp, &statbuf) == 0 &&
+ statbuf.st_size == 0 && (flags & O_ACCMODE) != O_RDONLY;
+ } else
+ new_table = 1;
+
+ if (new_table) {
+ if (!(hashp = init_hash(hashp, file, info)))
+ RETURN_ERROR(errno, error1);
+ } else {
+ /* Table already exists */
+ if (info && info->hash)
+ hashp->hash = info->hash;
+ else
+ hashp->hash = __default_hash;
+
+ hdrsize = _read(hashp->fp, &hashp->hdr, sizeof(HASHHDR));
+#if BYTE_ORDER == LITTLE_ENDIAN
+ swap_header(hashp);
+#endif
+ if (hdrsize == -1)
+ RETURN_ERROR(errno, error1);
+ if (hdrsize != sizeof(HASHHDR))
+ RETURN_ERROR(EFTYPE, error1);
+ /* Verify file type, versions and hash function */
+ if (hashp->MAGIC != HASHMAGIC)
+ RETURN_ERROR(EFTYPE, error1);
+#define OLDHASHVERSION 1
+ if (hashp->VERSION != HASHVERSION &&
+ hashp->VERSION != OLDHASHVERSION)
+ RETURN_ERROR(EFTYPE, error1);
+ if ((int32_t)hashp->hash(CHARKEY, sizeof(CHARKEY)) != hashp->H_CHARKEY)
+ RETURN_ERROR(EFTYPE, error1);
+ /*
+ * Figure out how many segments we need. Max_Bucket is the
+ * maximum bucket number, so the number of buckets is
+ * max_bucket + 1.
+ */
+ nsegs = (hashp->MAX_BUCKET + 1 + hashp->SGSIZE - 1) /
+ hashp->SGSIZE;
+ if (alloc_segs(hashp, nsegs))
+ /*
+ * If alloc_segs fails, table will have been destroyed
+ * and errno will have been set.
+ */
+ return (NULL);
+ /* Read in bitmaps */
+ bpages = (hashp->SPARES[hashp->OVFL_POINT] +
+ (hashp->BSIZE << BYTE_SHIFT) - 1) >>
+ (hashp->BSHIFT + BYTE_SHIFT);
+
+ hashp->nmaps = bpages;
+ (void)memset(&hashp->mapp[0], 0, bpages * sizeof(u_int32_t *));
+ }
+
+ /* Initialize Buffer Manager */
+ if (info && info->cachesize)
+ __buf_init(hashp, info->cachesize);
+ else
+ __buf_init(hashp, DEF_BUFSIZE);
+
+ hashp->new_file = new_table;
+ hashp->save_file = file && (hashp->flags & O_RDWR);
+ hashp->cbucket = -1;
+ if (!(dbp = (DB *)malloc(sizeof(DB)))) {
+ save_errno = errno;
+ hdestroy(hashp);
+ errno = save_errno;
+ return (NULL);
+ }
+ dbp->internal = hashp;
+ dbp->close = hash_close;
+ dbp->del = hash_delete;
+ dbp->fd = hash_fd;
+ dbp->get = hash_get;
+ dbp->put = hash_put;
+ dbp->seq = hash_seq;
+ dbp->sync = hash_sync;
+ dbp->type = DB_HASH;
+
+#ifdef DEBUG
+ (void)fprintf(stderr,
+"%s\n%s%p\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%d\n%s%x\n%s%x\n%s%d\n%s%d\n",
+ "init_htab:",
+ "TABLE POINTER ", hashp,
+ "BUCKET SIZE ", hashp->BSIZE,
+ "BUCKET SHIFT ", hashp->BSHIFT,
+ "DIRECTORY SIZE ", hashp->DSIZE,
+ "SEGMENT SIZE ", hashp->SGSIZE,
+ "SEGMENT SHIFT ", hashp->SSHIFT,
+ "FILL FACTOR ", hashp->FFACTOR,
+ "MAX BUCKET ", hashp->MAX_BUCKET,
+ "OVFL POINT ", hashp->OVFL_POINT,
+ "LAST FREED ", hashp->LAST_FREED,
+ "HIGH MASK ", hashp->HIGH_MASK,
+ "LOW MASK ", hashp->LOW_MASK,
+ "NSEGS ", hashp->nsegs,
+ "NKEYS ", hashp->NKEYS);
+#endif
+#ifdef HASH_STATISTICS
+ hash_overflows = hash_accesses = hash_collisions = hash_expansions = 0;
+#endif
+ return (dbp);
+
+error1:
+ if (hashp != NULL)
+ (void)_close(hashp->fp);
+
+error0:
+ free(hashp);
+ errno = save_errno;
+ return (NULL);
+}
+
+static int
+hash_close(DB *dbp)
+{
+ HTAB *hashp;
+ int retval;
+
+ if (!dbp)
+ return (ERROR);
+
+ hashp = (HTAB *)dbp->internal;
+ retval = hdestroy(hashp);
+ free(dbp);
+ return (retval);
+}
+
+static int
+hash_fd(const DB *dbp)
+{
+ HTAB *hashp;
+
+ if (!dbp)
+ return (ERROR);
+
+ hashp = (HTAB *)dbp->internal;
+ if (hashp->fp == -1) {
+ errno = ENOENT;
+ return (-1);
+ }
+ return (hashp->fp);
+}
+
+/************************** LOCAL CREATION ROUTINES **********************/
+static HTAB *
+init_hash(HTAB *hashp, const char *file, const HASHINFO *info)
+{
+ struct stat statbuf;
+ int nelem;
+
+ nelem = 1;
+ hashp->NKEYS = 0;
+ hashp->LORDER = BYTE_ORDER;
+ hashp->BSIZE = DEF_BUCKET_SIZE;
+ hashp->BSHIFT = DEF_BUCKET_SHIFT;
+ hashp->SGSIZE = DEF_SEGSIZE;
+ hashp->SSHIFT = DEF_SEGSIZE_SHIFT;
+ hashp->DSIZE = DEF_DIRSIZE;
+ hashp->FFACTOR = DEF_FFACTOR;
+ hashp->hash = __default_hash;
+ memset(hashp->SPARES, 0, sizeof(hashp->SPARES));
+ memset(hashp->BITMAPS, 0, sizeof (hashp->BITMAPS));
+
+ /* Fix bucket size to be optimal for file system */
+ if (file != NULL) {
+ if (stat(file, &statbuf))
+ return (NULL);
+ hashp->BSIZE = statbuf.st_blksize;
+ if (hashp->BSIZE > MAX_BSIZE)
+ hashp->BSIZE = MAX_BSIZE;
+ hashp->BSHIFT = __log2(hashp->BSIZE);
+ }
+
+ if (info) {
+ if (info->bsize) {
+ /* Round pagesize up to power of 2 */
+ hashp->BSHIFT = __log2(info->bsize);
+ hashp->BSIZE = 1 << hashp->BSHIFT;
+ if (hashp->BSIZE > MAX_BSIZE) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ }
+ if (info->ffactor)
+ hashp->FFACTOR = info->ffactor;
+ if (info->hash)
+ hashp->hash = info->hash;
+ if (info->nelem)
+ nelem = info->nelem;
+ if (info->lorder) {
+ if (info->lorder != BIG_ENDIAN &&
+ info->lorder != LITTLE_ENDIAN) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ hashp->LORDER = info->lorder;
+ }
+ }
+ /* init_htab should destroy the table and set errno if it fails */
+ if (init_htab(hashp, nelem))
+ return (NULL);
+ else
+ return (hashp);
+}
+/*
+ * This calls alloc_segs which may run out of memory. Alloc_segs will destroy
+ * the table and set errno, so we just pass the error information along.
+ *
+ * Returns 0 on No Error
+ */
+static int
+init_htab(HTAB *hashp, int nelem)
+{
+ int nbuckets, nsegs, l2;
+
+ /*
+ * Divide number of elements by the fill factor and determine a
+ * desired number of buckets. Allocate space for the next greater
+ * power of two number of buckets.
+ */
+ nelem = (nelem - 1) / hashp->FFACTOR + 1;
+
+ l2 = __log2(MAX(nelem, 2));
+ nbuckets = 1 << l2;
+
+ hashp->SPARES[l2] = l2 + 1;
+ hashp->SPARES[l2 + 1] = l2 + 1;
+ hashp->OVFL_POINT = l2;
+ hashp->LAST_FREED = 2;
+
+ /* First bitmap page is at: splitpoint l2 page offset 1 */
+ if (__ibitmap(hashp, OADDR_OF(l2, 1), l2 + 1, 0))
+ return (-1);
+
+ hashp->MAX_BUCKET = hashp->LOW_MASK = nbuckets - 1;
+ hashp->HIGH_MASK = (nbuckets << 1) - 1;
+ hashp->HDRPAGES = ((MAX(sizeof(HASHHDR), MINHDRSIZE) - 1) >>
+ hashp->BSHIFT) + 1;
+
+ nsegs = (nbuckets - 1) / hashp->SGSIZE + 1;
+ nsegs = 1 << __log2(nsegs);
+
+ if (nsegs > hashp->DSIZE)
+ hashp->DSIZE = nsegs;
+ return (alloc_segs(hashp, nsegs));
+}
+
+/********************** DESTROY/CLOSE ROUTINES ************************/
+
+/*
+ * Flushes any changes to the file if necessary and destroys the hashp
+ * structure, freeing all allocated space.
+ */
+static int
+hdestroy(HTAB *hashp)
+{
+ int i, save_errno;
+
+ save_errno = 0;
+
+#ifdef HASH_STATISTICS
+ (void)fprintf(stderr, "hdestroy: accesses %ld collisions %ld\n",
+ hash_accesses, hash_collisions);
+ (void)fprintf(stderr, "hdestroy: expansions %ld\n",
+ hash_expansions);
+ (void)fprintf(stderr, "hdestroy: overflows %ld\n",
+ hash_overflows);
+ (void)fprintf(stderr, "keys %ld maxp %d segmentcount %d\n",
+ hashp->NKEYS, hashp->MAX_BUCKET, hashp->nsegs);
+
+ for (i = 0; i < NCACHED; i++)
+ (void)fprintf(stderr,
+ "spares[%d] = %d\n", i, hashp->SPARES[i]);
+#endif
+ /*
+ * Call on buffer manager to free buffers, and if required,
+ * write them to disk.
+ */
+ if (__buf_free(hashp, 1, hashp->save_file))
+ save_errno = errno;
+ if (hashp->dir) {
+ free(*hashp->dir); /* Free initial segments */
+ /* Free extra segments */
+ while (hashp->exsegs--)
+ free(hashp->dir[--hashp->nsegs]);
+ free(hashp->dir);
+ }
+ if (flush_meta(hashp) && !save_errno)
+ save_errno = errno;
+ /* Free Bigmaps */
+ for (i = 0; i < hashp->nmaps; i++)
+ if (hashp->mapp[i])
+ free(hashp->mapp[i]);
+ if (hashp->tmp_key)
+ free(hashp->tmp_key);
+ if (hashp->tmp_buf)
+ free(hashp->tmp_buf);
+
+ if (hashp->fp != -1)
+ (void)_close(hashp->fp);
+
+ free(hashp);
+
+ if (save_errno) {
+ errno = save_errno;
+ return (ERROR);
+ }
+ return (SUCCESS);
+}
+/*
+ * Write modified pages to disk
+ *
+ * Returns:
+ * 0 == OK
+ * -1 ERROR
+ */
+static int
+hash_sync(const DB *dbp, u_int32_t flags)
+{
+ HTAB *hashp;
+
+ if (flags != 0) {
+ errno = EINVAL;
+ return (ERROR);
+ }
+
+ if (!dbp)
+ return (ERROR);
+
+ hashp = (HTAB *)dbp->internal;
+ if (!hashp->save_file)
+ return (0);
+ if (__buf_free(hashp, 0, 1) || flush_meta(hashp))
+ return (ERROR);
+ hashp->new_file = 0;
+ return (0);
+}
+
+/*
+ * Returns:
+ * 0 == OK
+ * -1 indicates that errno should be set
+ */
+static int
+flush_meta(HTAB *hashp)
+{
+ HASHHDR *whdrp;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ HASHHDR whdr;
+#endif
+ int fp, i, wsize;
+
+ if (!hashp->save_file)
+ return (0);
+ hashp->MAGIC = HASHMAGIC;
+ hashp->VERSION = HASHVERSION;
+ hashp->H_CHARKEY = hashp->hash(CHARKEY, sizeof(CHARKEY));
+
+ fp = hashp->fp;
+ whdrp = &hashp->hdr;
+#if BYTE_ORDER == LITTLE_ENDIAN
+ whdrp = &whdr;
+ swap_header_copy(&hashp->hdr, whdrp);
+#endif
+ if ((wsize = pwrite(fp, whdrp, sizeof(HASHHDR), (off_t)0)) == -1)
+ return (-1);
+ else
+ if (wsize != sizeof(HASHHDR)) {
+ errno = EFTYPE;
+ hashp->error = errno;
+ return (-1);
+ }
+ for (i = 0; i < NCACHED; i++)
+ if (hashp->mapp[i])
+ if (__put_page(hashp, (char *)hashp->mapp[i],
+ hashp->BITMAPS[i], 0, 1))
+ return (-1);
+ return (0);
+}
+
+/*******************************SEARCH ROUTINES *****************************/
+/*
+ * All the access routines return
+ *
+ * Returns:
+ * 0 on SUCCESS
+ * 1 to indicate an external ERROR (i.e. key not found, etc)
+ * -1 to indicate an internal ERROR (i.e. out of memory, etc)
+ */
+static int
+hash_get(const DB *dbp, const DBT *key, DBT *data, u_int32_t flag)
+{
+ HTAB *hashp;
+
+ hashp = (HTAB *)dbp->internal;
+ if (flag) {
+ hashp->error = errno = EINVAL;
+ return (ERROR);
+ }
+ return (hash_access(hashp, HASH_GET, (DBT *)key, data));
+}
+
+static int
+hash_put(const DB *dbp, DBT *key, const DBT *data, u_int32_t flag)
+{
+ HTAB *hashp;
+
+ hashp = (HTAB *)dbp->internal;
+ if (flag && flag != R_NOOVERWRITE) {
+ hashp->error = errno = EINVAL;
+ return (ERROR);
+ }
+ if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
+ hashp->error = errno = EPERM;
+ return (ERROR);
+ }
+ return (hash_access(hashp, flag == R_NOOVERWRITE ?
+ HASH_PUTNEW : HASH_PUT, (DBT *)key, (DBT *)data));
+}
+
+static int
+hash_delete(const DB *dbp, const DBT *key,
+ u_int32_t flag) /* Ignored */
+{
+ HTAB *hashp;
+
+ hashp = (HTAB *)dbp->internal;
+ if (flag && flag != R_CURSOR) {
+ hashp->error = errno = EINVAL;
+ return (ERROR);
+ }
+ if ((hashp->flags & O_ACCMODE) == O_RDONLY) {
+ hashp->error = errno = EPERM;
+ return (ERROR);
+ }
+ return (hash_access(hashp, HASH_DELETE, (DBT *)key, NULL));
+}
+
+/*
+ * Assume that hashp has been set in wrapper routine.
+ */
+static int
+hash_access(HTAB *hashp, ACTION action, DBT *key, DBT *val)
+{
+ BUFHEAD *rbufp;
+ BUFHEAD *bufp, *save_bufp;
+ u_int16_t *bp;
+ int n, ndx, off, size;
+ char *kp;
+ u_int16_t pageno;
+
+#ifdef HASH_STATISTICS
+ hash_accesses++;
+#endif
+
+ off = hashp->BSIZE;
+ size = key->size;
+ kp = (char *)key->data;
+ rbufp = __get_buf(hashp, __call_hash(hashp, kp, size), NULL, 0);
+ if (!rbufp)
+ return (ERROR);
+ save_bufp = rbufp;
+
+ /* Pin the bucket chain */
+ rbufp->flags |= BUF_PIN;
+ for (bp = (u_int16_t *)rbufp->page, n = *bp++, ndx = 1; ndx < n;)
+ if (bp[1] >= REAL_KEY) {
+ /* Real key/data pair */
+ if (size == off - *bp &&
+ memcmp(kp, rbufp->page + *bp, size) == 0)
+ goto found;
+ off = bp[1];
+#ifdef HASH_STATISTICS
+ hash_collisions++;
+#endif
+ bp += 2;
+ ndx += 2;
+ } else if (bp[1] == OVFLPAGE) {
+ rbufp = __get_buf(hashp, *bp, rbufp, 0);
+ if (!rbufp) {
+ save_bufp->flags &= ~BUF_PIN;
+ return (ERROR);
+ }
+ /* FOR LOOP INIT */
+ bp = (u_int16_t *)rbufp->page;
+ n = *bp++;
+ ndx = 1;
+ off = hashp->BSIZE;
+ } else if (bp[1] < REAL_KEY) {
+ if ((ndx =
+ __find_bigpair(hashp, rbufp, ndx, kp, size)) > 0)
+ goto found;
+ if (ndx == -2) {
+ bufp = rbufp;
+ if (!(pageno =
+ __find_last_page(hashp, &bufp))) {
+ ndx = 0;
+ rbufp = bufp;
+ break; /* FOR */
+ }
+ rbufp = __get_buf(hashp, pageno, bufp, 0);
+ if (!rbufp) {
+ save_bufp->flags &= ~BUF_PIN;
+ return (ERROR);
+ }
+ /* FOR LOOP INIT */
+ bp = (u_int16_t *)rbufp->page;
+ n = *bp++;
+ ndx = 1;
+ off = hashp->BSIZE;
+ } else {
+ save_bufp->flags &= ~BUF_PIN;
+ return (ERROR);
+ }
+ }
+
+ /* Not found */
+ switch (action) {
+ case HASH_PUT:
+ case HASH_PUTNEW:
+ if (__addel(hashp, rbufp, key, val)) {
+ save_bufp->flags &= ~BUF_PIN;
+ return (ERROR);
+ } else {
+ save_bufp->flags &= ~BUF_PIN;
+ return (SUCCESS);
+ }
+ case HASH_GET:
+ case HASH_DELETE:
+ default:
+ save_bufp->flags &= ~BUF_PIN;
+ return (ABNORMAL);
+ }
+
+found:
+ switch (action) {
+ case HASH_PUTNEW:
+ save_bufp->flags &= ~BUF_PIN;
+ return (ABNORMAL);
+ case HASH_GET:
+ bp = (u_int16_t *)rbufp->page;
+ if (bp[ndx + 1] < REAL_KEY) {
+ if (__big_return(hashp, rbufp, ndx, val, 0))
+ return (ERROR);
+ } else {
+ val->data = (u_char *)rbufp->page + (int)bp[ndx + 1];
+ val->size = bp[ndx] - bp[ndx + 1];
+ }
+ break;
+ case HASH_PUT:
+ if ((__delpair(hashp, rbufp, ndx)) ||
+ (__addel(hashp, rbufp, key, val))) {
+ save_bufp->flags &= ~BUF_PIN;
+ return (ERROR);
+ }
+ break;
+ case HASH_DELETE:
+ if (__delpair(hashp, rbufp, ndx))
+ return (ERROR);
+ break;
+ default:
+ abort();
+ }
+ save_bufp->flags &= ~BUF_PIN;
+ return (SUCCESS);
+}
+
+static int
+hash_seq(const DB *dbp, DBT *key, DBT *data, u_int32_t flag)
+{
+ u_int32_t bucket;
+ BUFHEAD *bufp;
+ HTAB *hashp;
+ u_int16_t *bp, ndx;
+
+ hashp = (HTAB *)dbp->internal;
+ if (flag && flag != R_FIRST && flag != R_NEXT) {
+ hashp->error = errno = EINVAL;
+ return (ERROR);
+ }
+#ifdef HASH_STATISTICS
+ hash_accesses++;
+#endif
+ if ((hashp->cbucket < 0) || (flag == R_FIRST)) {
+ hashp->cbucket = 0;
+ hashp->cndx = 1;
+ hashp->cpage = NULL;
+ }
+next_bucket:
+ for (bp = NULL; !bp || !bp[0]; ) {
+ if (!(bufp = hashp->cpage)) {
+ for (bucket = hashp->cbucket;
+ bucket <= hashp->MAX_BUCKET;
+ bucket++, hashp->cndx = 1) {
+ bufp = __get_buf(hashp, bucket, NULL, 0);
+ if (!bufp)
+ return (ERROR);
+ hashp->cpage = bufp;
+ bp = (u_int16_t *)bufp->page;
+ if (bp[0])
+ break;
+ }
+ hashp->cbucket = bucket;
+ if ((u_int32_t)hashp->cbucket > hashp->MAX_BUCKET) {
+ hashp->cbucket = -1;
+ return (ABNORMAL);
+ }
+ } else {
+ bp = (u_int16_t *)hashp->cpage->page;
+ if (flag == R_NEXT || flag == 0) {
+ hashp->cndx += 2;
+ if (hashp->cndx > bp[0]) {
+ hashp->cpage = NULL;
+ hashp->cbucket++;
+ hashp->cndx = 1;
+ goto next_bucket;
+ }
+ }
+ }
+
+#ifdef DEBUG
+ assert(bp);
+ assert(bufp);
+#endif
+ while (bp[hashp->cndx + 1] == OVFLPAGE) {
+ bufp = hashp->cpage =
+ __get_buf(hashp, bp[hashp->cndx], bufp, 0);
+ if (!bufp)
+ return (ERROR);
+ bp = (u_int16_t *)(bufp->page);
+ hashp->cndx = 1;
+ }
+ if (!bp[0]) {
+ hashp->cpage = NULL;
+ ++hashp->cbucket;
+ }
+ }
+ ndx = hashp->cndx;
+ if (bp[ndx + 1] < REAL_KEY) {
+ if (__big_keydata(hashp, bufp, key, data, 1))
+ return (ERROR);
+ } else {
+ if (hashp->cpage == 0)
+ return (ERROR);
+ key->data = (u_char *)hashp->cpage->page + bp[ndx];
+ key->size = (ndx > 1 ? bp[ndx - 1] : hashp->BSIZE) - bp[ndx];
+ data->data = (u_char *)hashp->cpage->page + bp[ndx + 1];
+ data->size = bp[ndx] - bp[ndx + 1];
+ }
+ return (SUCCESS);
+}
+
+/********************************* UTILITIES ************************/
+
+/*
+ * Returns:
+ * 0 ==> OK
+ * -1 ==> Error
+ */
+int
+__expand_table(HTAB *hashp)
+{
+ u_int32_t old_bucket, new_bucket;
+ int dirsize, new_segnum, spare_ndx;
+
+#ifdef HASH_STATISTICS
+ hash_expansions++;
+#endif
+ new_bucket = ++hashp->MAX_BUCKET;
+ old_bucket = (hashp->MAX_BUCKET & hashp->LOW_MASK);
+
+ new_segnum = new_bucket >> hashp->SSHIFT;
+
+ /* Check if we need a new segment */
+ if (new_segnum >= hashp->nsegs) {
+ /* Check if we need to expand directory */
+ if (new_segnum >= hashp->DSIZE) {
+ /* Reallocate directory */
+ dirsize = hashp->DSIZE * sizeof(SEGMENT *);
+ if (!hash_realloc(&hashp->dir, dirsize, dirsize << 1))
+ return (-1);
+ hashp->DSIZE = dirsize << 1;
+ }
+ if ((hashp->dir[new_segnum] =
+ (SEGMENT)calloc(hashp->SGSIZE, sizeof(SEGMENT))) == NULL)
+ return (-1);
+ hashp->exsegs++;
+ hashp->nsegs++;
+ }
+ /*
+ * If the split point is increasing (MAX_BUCKET's log base 2
+ * * increases), we need to copy the current contents of the spare
+ * split bucket to the next bucket.
+ */
+ spare_ndx = __log2(hashp->MAX_BUCKET + 1);
+ if (spare_ndx > hashp->OVFL_POINT) {
+ hashp->SPARES[spare_ndx] = hashp->SPARES[hashp->OVFL_POINT];
+ hashp->OVFL_POINT = spare_ndx;
+ }
+
+ if (new_bucket > hashp->HIGH_MASK) {
+ /* Starting a new doubling */
+ hashp->LOW_MASK = hashp->HIGH_MASK;
+ hashp->HIGH_MASK = new_bucket | hashp->LOW_MASK;
+ }
+ /* Relocate records to the new bucket */
+ return (__split_page(hashp, old_bucket, new_bucket));
+}
+
+/*
+ * If realloc guarantees that the pointer is not destroyed if the realloc
+ * fails, then this routine can go away.
+ */
+static void *
+hash_realloc(SEGMENT **p_ptr, int oldsize, int newsize)
+{
+ void *p;
+
+ if ( (p = malloc(newsize)) ) {
+ memmove(p, *p_ptr, oldsize);
+ memset((char *)p + oldsize, 0, newsize - oldsize);
+ free(*p_ptr);
+ *p_ptr = p;
+ }
+ return (p);
+}
+
+u_int32_t
+__call_hash(HTAB *hashp, char *k, int len)
+{
+ unsigned int n, bucket;
+
+ n = hashp->hash(k, len);
+ bucket = n & hashp->HIGH_MASK;
+ if (bucket > hashp->MAX_BUCKET)
+ bucket = bucket & hashp->LOW_MASK;
+ return (bucket);
+}
+
+/*
+ * Allocate segment table. On error, destroy the table and set errno.
+ *
+ * Returns 0 on success
+ */
+static int
+alloc_segs(HTAB *hashp, int nsegs)
+{
+ int i;
+ SEGMENT store;
+
+ int save_errno;
+
+ if ((hashp->dir =
+ (SEGMENT *)calloc(hashp->DSIZE, sizeof(SEGMENT *))) == NULL) {
+ save_errno = errno;
+ (void)hdestroy(hashp);
+ errno = save_errno;
+ return (-1);
+ }
+ hashp->nsegs = nsegs;
+ if (nsegs == 0)
+ return (0);
+ /* Allocate segments */
+ if ((store = (SEGMENT)calloc(nsegs << hashp->SSHIFT,
+ sizeof(SEGMENT))) == NULL) {
+ save_errno = errno;
+ (void)hdestroy(hashp);
+ errno = save_errno;
+ return (-1);
+ }
+ for (i = 0; i < nsegs; i++)
+ hashp->dir[i] = &store[i << hashp->SSHIFT];
+ return (0);
+}
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+/*
+ * Hashp->hdr needs to be byteswapped.
+ */
+static void
+swap_header_copy(HASHHDR *srcp, HASHHDR *destp)
+{
+ int i;
+
+ P_32_COPY(srcp->magic, destp->magic);
+ P_32_COPY(srcp->version, destp->version);
+ P_32_COPY(srcp->lorder, destp->lorder);
+ P_32_COPY(srcp->bsize, destp->bsize);
+ P_32_COPY(srcp->bshift, destp->bshift);
+ P_32_COPY(srcp->dsize, destp->dsize);
+ P_32_COPY(srcp->ssize, destp->ssize);
+ P_32_COPY(srcp->sshift, destp->sshift);
+ P_32_COPY(srcp->ovfl_point, destp->ovfl_point);
+ P_32_COPY(srcp->last_freed, destp->last_freed);
+ P_32_COPY(srcp->max_bucket, destp->max_bucket);
+ P_32_COPY(srcp->high_mask, destp->high_mask);
+ P_32_COPY(srcp->low_mask, destp->low_mask);
+ P_32_COPY(srcp->ffactor, destp->ffactor);
+ P_32_COPY(srcp->nkeys, destp->nkeys);
+ P_32_COPY(srcp->hdrpages, destp->hdrpages);
+ P_32_COPY(srcp->h_charkey, destp->h_charkey);
+ for (i = 0; i < NCACHED; i++) {
+ P_32_COPY(srcp->spares[i], destp->spares[i]);
+ P_16_COPY(srcp->bitmaps[i], destp->bitmaps[i]);
+ }
+}
+
+static void
+swap_header(HTAB *hashp)
+{
+ HASHHDR *hdrp;
+ int i;
+
+ hdrp = &hashp->hdr;
+
+ M_32_SWAP(hdrp->magic);
+ M_32_SWAP(hdrp->version);
+ M_32_SWAP(hdrp->lorder);
+ M_32_SWAP(hdrp->bsize);
+ M_32_SWAP(hdrp->bshift);
+ M_32_SWAP(hdrp->dsize);
+ M_32_SWAP(hdrp->ssize);
+ M_32_SWAP(hdrp->sshift);
+ M_32_SWAP(hdrp->ovfl_point);
+ M_32_SWAP(hdrp->last_freed);
+ M_32_SWAP(hdrp->max_bucket);
+ M_32_SWAP(hdrp->high_mask);
+ M_32_SWAP(hdrp->low_mask);
+ M_32_SWAP(hdrp->ffactor);
+ M_32_SWAP(hdrp->nkeys);
+ M_32_SWAP(hdrp->hdrpages);
+ M_32_SWAP(hdrp->h_charkey);
+ for (i = 0; i < NCACHED; i++) {
+ M_32_SWAP(hdrp->spares[i]);
+ M_16_SWAP(hdrp->bitmaps[i]);
+ }
+}
+#endif
diff --git a/lib/libc/db/hash/hash.h b/lib/libc/db/hash/hash.h
new file mode 100644
index 0000000..cd11a3a
--- /dev/null
+++ b/lib/libc/db/hash/hash.h
@@ -0,0 +1,290 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)hash.h 8.3 (Berkeley) 5/31/94
+ * $FreeBSD$
+ */
+
+/* Operations */
+typedef enum {
+ HASH_GET, HASH_PUT, HASH_PUTNEW, HASH_DELETE, HASH_FIRST, HASH_NEXT
+} ACTION;
+
+/* Buffer Management structures */
+typedef struct _bufhead BUFHEAD;
+
+struct _bufhead {
+ BUFHEAD *prev; /* LRU links */
+ BUFHEAD *next; /* LRU links */
+ BUFHEAD *ovfl; /* Overflow page buffer header */
+ u_int32_t addr; /* Address of this page */
+ char *page; /* Actual page data */
+ char flags;
+#define BUF_MOD 0x0001
+#define BUF_DISK 0x0002
+#define BUF_BUCKET 0x0004
+#define BUF_PIN 0x0008
+};
+
+#define IS_BUCKET(X) ((X) & BUF_BUCKET)
+
+typedef BUFHEAD **SEGMENT;
+
+/* Hash Table Information */
+typedef struct hashhdr { /* Disk resident portion */
+ int32_t magic; /* Magic NO for hash tables */
+ int32_t version; /* Version ID */
+ u_int32_t lorder; /* Byte Order */
+ int32_t bsize; /* Bucket/Page Size */
+ int32_t bshift; /* Bucket shift */
+ int32_t dsize; /* Directory Size */
+ int32_t ssize; /* Segment Size */
+ int32_t sshift; /* Segment shift */
+ int32_t ovfl_point; /* Where overflow pages are being
+ * allocated */
+ int32_t last_freed; /* Last overflow page freed */
+ u_int32_t max_bucket; /* ID of Maximum bucket in use */
+ u_int32_t high_mask; /* Mask to modulo into entire table */
+ u_int32_t low_mask; /* Mask to modulo into lower half of
+ * table */
+ u_int32_t ffactor; /* Fill factor */
+ int32_t nkeys; /* Number of keys in hash table */
+ int32_t hdrpages; /* Size of table header */
+ int32_t h_charkey; /* value of hash(CHARKEY) */
+#define NCACHED 32 /* number of bit maps and spare
+ * points */
+ int32_t spares[NCACHED];/* spare pages for overflow */
+ u_int16_t bitmaps[NCACHED]; /* address of overflow page
+ * bitmaps */
+} HASHHDR;
+
+typedef struct htab { /* Memory resident data structure */
+ HASHHDR hdr; /* Header */
+ int nsegs; /* Number of allocated segments */
+ int exsegs; /* Number of extra allocated
+ * segments */
+ u_int32_t /* Hash function */
+ (*hash)(const void *, size_t);
+ int flags; /* Flag values */
+ int fp; /* File pointer */
+ char *tmp_buf; /* Temporary Buffer for BIG data */
+ char *tmp_key; /* Temporary Buffer for BIG keys */
+ BUFHEAD *cpage; /* Current page */
+ int cbucket; /* Current bucket */
+ int cndx; /* Index of next item on cpage */
+ int error; /* Error Number -- for DBM
+ * compatibility */
+ int new_file; /* Indicates if fd is backing store
+ * or no */
+ int save_file; /* Indicates whether we need to flush
+ * file at
+ * exit */
+ u_int32_t *mapp[NCACHED]; /* Pointers to page maps */
+ int nmaps; /* Initial number of bitmaps */
+ int nbufs; /* Number of buffers left to
+ * allocate */
+ BUFHEAD bufhead; /* Header of buffer lru list */
+ SEGMENT *dir; /* Hash Bucket directory */
+} HTAB;
+
+/*
+ * Constants
+ */
+#define MAX_BSIZE 32768 /* 2^15 but should be 65536 */
+#define MIN_BUFFERS 6
+#define MINHDRSIZE 512
+#define DEF_BUFSIZE 65536 /* 64 K */
+#define DEF_BUCKET_SIZE 4096
+#define DEF_BUCKET_SHIFT 12 /* log2(BUCKET) */
+#define DEF_SEGSIZE 256
+#define DEF_SEGSIZE_SHIFT 8 /* log2(SEGSIZE) */
+#define DEF_DIRSIZE 256
+#define DEF_FFACTOR 65536
+#define MIN_FFACTOR 4
+#define SPLTMAX 8
+#define CHARKEY "%$sniglet^&"
+#define NUMKEY 1038583
+#define BYTE_SHIFT 3
+#define INT_TO_BYTE 2
+#define INT_BYTE_SHIFT 5
+#define ALL_SET ((u_int32_t)0xFFFFFFFF)
+#define ALL_CLEAR 0
+
+#define PTROF(X) ((BUFHEAD *)((ptrdiff_t)(X)&~0x3))
+#define ISMOD(X) ((u_int32_t)(ptrdiff_t)(X)&0x1)
+#define DOMOD(X) ((X) = (char *)((ptrdiff_t)(X)|0x1))
+#define ISDISK(X) ((u_int32_t)(ptrdiff_t)(X)&0x2)
+#define DODISK(X) ((X) = (char *)((ptrdiff_t)(X)|0x2))
+
+#define BITS_PER_MAP 32
+
+/* Given the address of the beginning of a big map, clear/set the nth bit */
+#define CLRBIT(A, N) ((A)[(N)/BITS_PER_MAP] &= ~(1<<((N)%BITS_PER_MAP)))
+#define SETBIT(A, N) ((A)[(N)/BITS_PER_MAP] |= (1<<((N)%BITS_PER_MAP)))
+#define ISSET(A, N) ((A)[(N)/BITS_PER_MAP] & (1<<((N)%BITS_PER_MAP)))
+
+/* Overflow management */
+/*
+ * Overflow page numbers are allocated per split point. At each doubling of
+ * the table, we can allocate extra pages. So, an overflow page number has
+ * the top 5 bits indicate which split point and the lower 11 bits indicate
+ * which page at that split point is indicated (pages within split points are
+ * numberered starting with 1).
+ */
+
+#define SPLITSHIFT 11
+#define SPLITMASK 0x7FF
+#define SPLITNUM(N) (((u_int32_t)(N)) >> SPLITSHIFT)
+#define OPAGENUM(N) ((N) & SPLITMASK)
+#define OADDR_OF(S,O) ((u_int32_t)((u_int32_t)(S) << SPLITSHIFT) + (O))
+
+#define BUCKET_TO_PAGE(B) \
+ (B) + hashp->HDRPAGES + ((B) ? hashp->SPARES[__log2((B)+1)-1] : 0)
+#define OADDR_TO_PAGE(B) \
+ BUCKET_TO_PAGE ( (1 << SPLITNUM((B))) -1 ) + OPAGENUM((B));
+
+/*
+ * page.h contains a detailed description of the page format.
+ *
+ * Normally, keys and data are accessed from offset tables in the top of
+ * each page which point to the beginning of the key and data. There are
+ * four flag values which may be stored in these offset tables which indicate
+ * the following:
+ *
+ *
+ * OVFLPAGE Rather than a key data pair, this pair contains
+ * the address of an overflow page. The format of
+ * the pair is:
+ * OVERFLOW_PAGE_NUMBER OVFLPAGE
+ *
+ * PARTIAL_KEY This must be the first key/data pair on a page
+ * and implies that page contains only a partial key.
+ * That is, the key is too big to fit on a single page
+ * so it starts on this page and continues on the next.
+ * The format of the page is:
+ * KEY_OFF PARTIAL_KEY OVFL_PAGENO OVFLPAGE
+ *
+ * KEY_OFF -- offset of the beginning of the key
+ * PARTIAL_KEY -- 1
+ * OVFL_PAGENO - page number of the next overflow page
+ * OVFLPAGE -- 0
+ *
+ * FULL_KEY This must be the first key/data pair on the page. It
+ * is used in two cases.
+ *
+ * Case 1:
+ * There is a complete key on the page but no data
+ * (because it wouldn't fit). The next page contains
+ * the data.
+ *
+ * Page format it:
+ * KEY_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
+ *
+ * KEY_OFF -- offset of the beginning of the key
+ * FULL_KEY -- 2
+ * OVFL_PAGENO - page number of the next overflow page
+ * OVFLPAGE -- 0
+ *
+ * Case 2:
+ * This page contains no key, but part of a large
+ * data field, which is continued on the next page.
+ *
+ * Page format it:
+ * DATA_OFF FULL_KEY OVFL_PAGENO OVFL_PAGE
+ *
+ * KEY_OFF -- offset of the beginning of the data on
+ * this page
+ * FULL_KEY -- 2
+ * OVFL_PAGENO - page number of the next overflow page
+ * OVFLPAGE -- 0
+ *
+ * FULL_KEY_DATA
+ * This must be the first key/data pair on the page.
+ * There are two cases:
+ *
+ * Case 1:
+ * This page contains a key and the beginning of the
+ * data field, but the data field is continued on the
+ * next page.
+ *
+ * Page format is:
+ * KEY_OFF FULL_KEY_DATA OVFL_PAGENO DATA_OFF
+ *
+ * KEY_OFF -- offset of the beginning of the key
+ * FULL_KEY_DATA -- 3
+ * OVFL_PAGENO - page number of the next overflow page
+ * DATA_OFF -- offset of the beginning of the data
+ *
+ * Case 2:
+ * This page contains the last page of a big data pair.
+ * There is no key, only the tail end of the data
+ * on this page.
+ *
+ * Page format is:
+ * DATA_OFF FULL_KEY_DATA <OVFL_PAGENO> <OVFLPAGE>
+ *
+ * DATA_OFF -- offset of the beginning of the data on
+ * this page
+ * FULL_KEY_DATA -- 3
+ * OVFL_PAGENO - page number of the next overflow page
+ * OVFLPAGE -- 0
+ *
+ * OVFL_PAGENO and OVFLPAGE are optional (they are
+ * not present if there is no next page).
+ */
+
+#define OVFLPAGE 0
+#define PARTIAL_KEY 1
+#define FULL_KEY 2
+#define FULL_KEY_DATA 3
+#define REAL_KEY 4
+
+/* Short hands for accessing structure */
+#define BSIZE hdr.bsize
+#define BSHIFT hdr.bshift
+#define DSIZE hdr.dsize
+#define SGSIZE hdr.ssize
+#define SSHIFT hdr.sshift
+#define LORDER hdr.lorder
+#define OVFL_POINT hdr.ovfl_point
+#define LAST_FREED hdr.last_freed
+#define MAX_BUCKET hdr.max_bucket
+#define FFACTOR hdr.ffactor
+#define HIGH_MASK hdr.high_mask
+#define LOW_MASK hdr.low_mask
+#define NKEYS hdr.nkeys
+#define HDRPAGES hdr.hdrpages
+#define SPARES hdr.spares
+#define BITMAPS hdr.bitmaps
+#define VERSION hdr.version
+#define MAGIC hdr.magic
+#define NEXT_FREE hdr.next_free
+#define H_CHARKEY hdr.h_charkey
diff --git a/lib/libc/db/hash/hash_bigkey.c b/lib/libc/db/hash/hash_bigkey.c
new file mode 100644
index 0000000..c1914a5
--- /dev/null
+++ b/lib/libc/db/hash/hash_bigkey.c
@@ -0,0 +1,646 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_bigkey.c 8.3 (Berkeley) 5/31/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * PACKAGE: hash
+ * DESCRIPTION:
+ * Big key/data handling for the hashing package.
+ *
+ * ROUTINES:
+ * External
+ * __big_keydata
+ * __big_split
+ * __big_insert
+ * __big_return
+ * __big_delete
+ * __find_last_page
+ * Internal
+ * collect_key
+ * collect_data
+ */
+
+#include <sys/param.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static int collect_key(HTAB *, BUFHEAD *, int, DBT *, int);
+static int collect_data(HTAB *, BUFHEAD *, int, int);
+
+/*
+ * Big_insert
+ *
+ * You need to do an insert and the key/data pair is too big
+ *
+ * Returns:
+ * 0 ==> OK
+ *-1 ==> ERROR
+ */
+int
+__big_insert(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
+{
+ u_int16_t *p;
+ int key_size, n;
+ unsigned int val_size;
+ u_int16_t space, move_bytes, off;
+ char *cp, *key_data, *val_data;
+
+ cp = bufp->page; /* Character pointer of p. */
+ p = (u_int16_t *)cp;
+
+ key_data = (char *)key->data;
+ key_size = key->size;
+ val_data = (char *)val->data;
+ val_size = val->size;
+
+ /* First move the Key */
+ for (space = FREESPACE(p) - BIGOVERHEAD; key_size;
+ space = FREESPACE(p) - BIGOVERHEAD) {
+ move_bytes = MIN(space, key_size);
+ off = OFFSET(p) - move_bytes;
+ memmove(cp + off, key_data, move_bytes);
+ key_size -= move_bytes;
+ key_data += move_bytes;
+ n = p[0];
+ p[++n] = off;
+ p[0] = ++n;
+ FREESPACE(p) = off - PAGE_META(n);
+ OFFSET(p) = off;
+ p[n] = PARTIAL_KEY;
+ bufp = __add_ovflpage(hashp, bufp);
+ if (!bufp)
+ return (-1);
+ n = p[0];
+ if (!key_size) {
+ space = FREESPACE(p);
+ if (space) {
+ move_bytes = MIN(space, val_size);
+ /*
+ * If the data would fit exactly in the
+ * remaining space, we must overflow it to the
+ * next page; otherwise the invariant that the
+ * data must end on a page with FREESPACE
+ * non-zero would fail.
+ */
+ if (space == val_size && val_size == val->size)
+ goto toolarge;
+ off = OFFSET(p) - move_bytes;
+ memmove(cp + off, val_data, move_bytes);
+ val_data += move_bytes;
+ val_size -= move_bytes;
+ p[n] = off;
+ p[n - 2] = FULL_KEY_DATA;
+ FREESPACE(p) = FREESPACE(p) - move_bytes;
+ OFFSET(p) = off;
+ } else {
+ toolarge:
+ p[n - 2] = FULL_KEY;
+ }
+ }
+ p = (u_int16_t *)bufp->page;
+ cp = bufp->page;
+ bufp->flags |= BUF_MOD;
+ }
+
+ /* Now move the data */
+ for (space = FREESPACE(p) - BIGOVERHEAD; val_size;
+ space = FREESPACE(p) - BIGOVERHEAD) {
+ move_bytes = MIN(space, val_size);
+ /*
+ * Here's the hack to make sure that if the data ends on the
+ * same page as the key ends, FREESPACE is at least one.
+ */
+ if (space == val_size && val_size == val->size)
+ move_bytes--;
+ off = OFFSET(p) - move_bytes;
+ memmove(cp + off, val_data, move_bytes);
+ val_size -= move_bytes;
+ val_data += move_bytes;
+ n = p[0];
+ p[++n] = off;
+ p[0] = ++n;
+ FREESPACE(p) = off - PAGE_META(n);
+ OFFSET(p) = off;
+ if (val_size) {
+ p[n] = FULL_KEY;
+ bufp = __add_ovflpage(hashp, bufp);
+ if (!bufp)
+ return (-1);
+ cp = bufp->page;
+ p = (u_int16_t *)cp;
+ } else
+ p[n] = FULL_KEY_DATA;
+ bufp->flags |= BUF_MOD;
+ }
+ return (0);
+}
+
+/*
+ * Called when bufp's page contains a partial key (index should be 1)
+ *
+ * All pages in the big key/data pair except bufp are freed. We cannot
+ * free bufp because the page pointing to it is lost and we can't get rid
+ * of its pointer.
+ *
+ * Returns:
+ * 0 => OK
+ *-1 => ERROR
+ */
+int
+__big_delete(HTAB *hashp, BUFHEAD *bufp)
+{
+ BUFHEAD *last_bfp, *rbufp;
+ u_int16_t *bp, pageno;
+ int key_done, n;
+
+ rbufp = bufp;
+ last_bfp = NULL;
+ bp = (u_int16_t *)bufp->page;
+ pageno = 0;
+ key_done = 0;
+
+ while (!key_done || (bp[2] != FULL_KEY_DATA)) {
+ if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA)
+ key_done = 1;
+
+ /*
+ * If there is freespace left on a FULL_KEY_DATA page, then
+ * the data is short and fits entirely on this page, and this
+ * is the last page.
+ */
+ if (bp[2] == FULL_KEY_DATA && FREESPACE(bp))
+ break;
+ pageno = bp[bp[0] - 1];
+ rbufp->flags |= BUF_MOD;
+ rbufp = __get_buf(hashp, pageno, rbufp, 0);
+ if (last_bfp)
+ __free_ovflpage(hashp, last_bfp);
+ last_bfp = rbufp;
+ if (!rbufp)
+ return (-1); /* Error. */
+ bp = (u_int16_t *)rbufp->page;
+ }
+
+ /*
+ * If we get here then rbufp points to the last page of the big
+ * key/data pair. Bufp points to the first one -- it should now be
+ * empty pointing to the next page after this pair. Can't free it
+ * because we don't have the page pointing to it.
+ */
+
+ /* This is information from the last page of the pair. */
+ n = bp[0];
+ pageno = bp[n - 1];
+
+ /* Now, bp is the first page of the pair. */
+ bp = (u_int16_t *)bufp->page;
+ if (n > 2) {
+ /* There is an overflow page. */
+ bp[1] = pageno;
+ bp[2] = OVFLPAGE;
+ bufp->ovfl = rbufp->ovfl;
+ } else
+ /* This is the last page. */
+ bufp->ovfl = NULL;
+ n -= 2;
+ bp[0] = n;
+ FREESPACE(bp) = hashp->BSIZE - PAGE_META(n);
+ OFFSET(bp) = hashp->BSIZE;
+
+ bufp->flags |= BUF_MOD;
+ if (rbufp)
+ __free_ovflpage(hashp, rbufp);
+ if (last_bfp && last_bfp != rbufp)
+ __free_ovflpage(hashp, last_bfp);
+
+ hashp->NKEYS--;
+ return (0);
+}
+/*
+ * Returns:
+ * 0 = key not found
+ * -1 = get next overflow page
+ * -2 means key not found and this is big key/data
+ * -3 error
+ */
+int
+__find_bigpair(HTAB *hashp, BUFHEAD *bufp, int ndx, char *key, int size)
+{
+ u_int16_t *bp;
+ char *p;
+ int ksize;
+ u_int16_t bytes;
+ char *kkey;
+
+ bp = (u_int16_t *)bufp->page;
+ p = bufp->page;
+ ksize = size;
+ kkey = key;
+
+ for (bytes = hashp->BSIZE - bp[ndx];
+ bytes <= size && bp[ndx + 1] == PARTIAL_KEY;
+ bytes = hashp->BSIZE - bp[ndx]) {
+ if (memcmp(p + bp[ndx], kkey, bytes))
+ return (-2);
+ kkey += bytes;
+ ksize -= bytes;
+ bufp = __get_buf(hashp, bp[ndx + 2], bufp, 0);
+ if (!bufp)
+ return (-3);
+ p = bufp->page;
+ bp = (u_int16_t *)p;
+ ndx = 1;
+ }
+
+ if (bytes != ksize || memcmp(p + bp[ndx], kkey, bytes)) {
+#ifdef HASH_STATISTICS
+ ++hash_collisions;
+#endif
+ return (-2);
+ } else
+ return (ndx);
+}
+
+/*
+ * Given the buffer pointer of the first overflow page of a big pair,
+ * find the end of the big pair
+ *
+ * This will set bpp to the buffer header of the last page of the big pair.
+ * It will return the pageno of the overflow page following the last page
+ * of the pair; 0 if there isn't any (i.e. big pair is the last key in the
+ * bucket)
+ */
+u_int16_t
+__find_last_page(HTAB *hashp, BUFHEAD **bpp)
+{
+ BUFHEAD *bufp;
+ u_int16_t *bp, pageno;
+ int n;
+
+ bufp = *bpp;
+ bp = (u_int16_t *)bufp->page;
+ for (;;) {
+ n = bp[0];
+
+ /*
+ * This is the last page if: the tag is FULL_KEY_DATA and
+ * either only 2 entries OVFLPAGE marker is explicit there
+ * is freespace on the page.
+ */
+ if (bp[2] == FULL_KEY_DATA &&
+ ((n == 2) || (bp[n] == OVFLPAGE) || (FREESPACE(bp))))
+ break;
+
+ pageno = bp[n - 1];
+ bufp = __get_buf(hashp, pageno, bufp, 0);
+ if (!bufp)
+ return (0); /* Need to indicate an error! */
+ bp = (u_int16_t *)bufp->page;
+ }
+
+ *bpp = bufp;
+ if (bp[0] > 2)
+ return (bp[3]);
+ else
+ return (0);
+}
+
+/*
+ * Return the data for the key/data pair that begins on this page at this
+ * index (index should always be 1).
+ */
+int
+__big_return(HTAB *hashp, BUFHEAD *bufp, int ndx, DBT *val, int set_current)
+{
+ BUFHEAD *save_p;
+ u_int16_t *bp, len, off, save_addr;
+ char *tp;
+
+ bp = (u_int16_t *)bufp->page;
+ while (bp[ndx + 1] == PARTIAL_KEY) {
+ bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+ if (!bufp)
+ return (-1);
+ bp = (u_int16_t *)bufp->page;
+ ndx = 1;
+ }
+
+ if (bp[ndx + 1] == FULL_KEY) {
+ bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+ if (!bufp)
+ return (-1);
+ bp = (u_int16_t *)bufp->page;
+ save_p = bufp;
+ save_addr = save_p->addr;
+ off = bp[1];
+ len = 0;
+ } else
+ if (!FREESPACE(bp)) {
+ /*
+ * This is a hack. We can't distinguish between
+ * FULL_KEY_DATA that contains complete data or
+ * incomplete data, so we require that if the data
+ * is complete, there is at least 1 byte of free
+ * space left.
+ */
+ off = bp[bp[0]];
+ len = bp[1] - off;
+ save_p = bufp;
+ save_addr = bufp->addr;
+ bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+ if (!bufp)
+ return (-1);
+ bp = (u_int16_t *)bufp->page;
+ } else {
+ /* The data is all on one page. */
+ tp = (char *)bp;
+ off = bp[bp[0]];
+ val->data = (u_char *)tp + off;
+ val->size = bp[1] - off;
+ if (set_current) {
+ if (bp[0] == 2) { /* No more buckets in
+ * chain */
+ hashp->cpage = NULL;
+ hashp->cbucket++;
+ hashp->cndx = 1;
+ } else {
+ hashp->cpage = __get_buf(hashp,
+ bp[bp[0] - 1], bufp, 0);
+ if (!hashp->cpage)
+ return (-1);
+ hashp->cndx = 1;
+ if (!((u_int16_t *)
+ hashp->cpage->page)[0]) {
+ hashp->cbucket++;
+ hashp->cpage = NULL;
+ }
+ }
+ }
+ return (0);
+ }
+
+ val->size = (size_t)collect_data(hashp, bufp, (int)len, set_current);
+ if (val->size == (size_t)-1)
+ return (-1);
+ if (save_p->addr != save_addr) {
+ /* We are pretty short on buffers. */
+ errno = EINVAL; /* OUT OF BUFFERS */
+ return (-1);
+ }
+ memmove(hashp->tmp_buf, (save_p->page) + off, len);
+ val->data = (u_char *)hashp->tmp_buf;
+ return (0);
+}
+/*
+ * Count how big the total datasize is by recursing through the pages. Then
+ * allocate a buffer and copy the data as you recurse up.
+ */
+static int
+collect_data(HTAB *hashp, BUFHEAD *bufp, int len, int set)
+{
+ u_int16_t *bp;
+ char *p;
+ BUFHEAD *xbp;
+ u_int16_t save_addr;
+ int mylen, totlen;
+
+ p = bufp->page;
+ bp = (u_int16_t *)p;
+ mylen = hashp->BSIZE - bp[1];
+ save_addr = bufp->addr;
+
+ if (bp[2] == FULL_KEY_DATA) { /* End of Data */
+ totlen = len + mylen;
+ if (hashp->tmp_buf)
+ free(hashp->tmp_buf);
+ if ((hashp->tmp_buf = (char *)malloc(totlen)) == NULL)
+ return (-1);
+ if (set) {
+ hashp->cndx = 1;
+ if (bp[0] == 2) { /* No more buckets in chain */
+ hashp->cpage = NULL;
+ hashp->cbucket++;
+ } else {
+ hashp->cpage =
+ __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+ if (!hashp->cpage)
+ return (-1);
+ else if (!((u_int16_t *)hashp->cpage->page)[0]) {
+ hashp->cbucket++;
+ hashp->cpage = NULL;
+ }
+ }
+ }
+ } else {
+ xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+ if (!xbp || ((totlen =
+ collect_data(hashp, xbp, len + mylen, set)) < 1))
+ return (-1);
+ }
+ if (bufp->addr != save_addr) {
+ errno = EINVAL; /* Out of buffers. */
+ return (-1);
+ }
+ memmove(&hashp->tmp_buf[len], (bufp->page) + bp[1], mylen);
+ return (totlen);
+}
+
+/*
+ * Fill in the key and data for this big pair.
+ */
+int
+__big_keydata(HTAB *hashp, BUFHEAD *bufp, DBT *key, DBT *val, int set)
+{
+ key->size = (size_t)collect_key(hashp, bufp, 0, val, set);
+ if (key->size == (size_t)-1)
+ return (-1);
+ key->data = (u_char *)hashp->tmp_key;
+ return (0);
+}
+
+/*
+ * Count how big the total key size is by recursing through the pages. Then
+ * collect the data, allocate a buffer and copy the key as you recurse up.
+ */
+static int
+collect_key(HTAB *hashp, BUFHEAD *bufp, int len, DBT *val, int set)
+{
+ BUFHEAD *xbp;
+ char *p;
+ int mylen, totlen;
+ u_int16_t *bp, save_addr;
+
+ p = bufp->page;
+ bp = (u_int16_t *)p;
+ mylen = hashp->BSIZE - bp[1];
+
+ save_addr = bufp->addr;
+ totlen = len + mylen;
+ if (bp[2] == FULL_KEY || bp[2] == FULL_KEY_DATA) { /* End of Key. */
+ if (hashp->tmp_key != NULL)
+ free(hashp->tmp_key);
+ if ((hashp->tmp_key = (char *)malloc(totlen)) == NULL)
+ return (-1);
+ if (__big_return(hashp, bufp, 1, val, set))
+ return (-1);
+ } else {
+ xbp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+ if (!xbp || ((totlen =
+ collect_key(hashp, xbp, totlen, val, set)) < 1))
+ return (-1);
+ }
+ if (bufp->addr != save_addr) {
+ errno = EINVAL; /* MIS -- OUT OF BUFFERS */
+ return (-1);
+ }
+ memmove(&hashp->tmp_key[len], (bufp->page) + bp[1], mylen);
+ return (totlen);
+}
+
+/*
+ * Returns:
+ * 0 => OK
+ * -1 => error
+ */
+int
+__big_split(HTAB *hashp,
+ BUFHEAD *op, /* Pointer to where to put keys that go in old bucket */
+ BUFHEAD *np, /* Pointer to new bucket page */
+ BUFHEAD *big_keyp, /* Pointer to first page containing the big key/data */
+ int addr, /* Address of big_keyp */
+ u_int32_t obucket, /* Old Bucket */
+ SPLIT_RETURN *ret)
+{
+ BUFHEAD *bp, *tmpp;
+ DBT key, val;
+ u_int32_t change;
+ u_int16_t free_space, n, off, *tp;
+
+ bp = big_keyp;
+
+ /* Now figure out where the big key/data goes */
+ if (__big_keydata(hashp, big_keyp, &key, &val, 0))
+ return (-1);
+ change = (__call_hash(hashp, key.data, key.size) != obucket);
+
+ if ( (ret->next_addr = __find_last_page(hashp, &big_keyp)) ) {
+ if (!(ret->nextp =
+ __get_buf(hashp, ret->next_addr, big_keyp, 0)))
+ return (-1);
+ } else
+ ret->nextp = NULL;
+
+ /* Now make one of np/op point to the big key/data pair */
+#ifdef DEBUG
+ assert(np->ovfl == NULL);
+#endif
+ if (change)
+ tmpp = np;
+ else
+ tmpp = op;
+
+ tmpp->flags |= BUF_MOD;
+#ifdef DEBUG1
+ (void)fprintf(stderr,
+ "BIG_SPLIT: %d->ovfl was %d is now %d\n", tmpp->addr,
+ (tmpp->ovfl ? tmpp->ovfl->addr : 0), (bp ? bp->addr : 0));
+#endif
+ tmpp->ovfl = bp; /* one of op/np point to big_keyp */
+ tp = (u_int16_t *)tmpp->page;
+#ifdef DEBUG
+ assert(FREESPACE(tp) >= OVFLSIZE);
+#endif
+ n = tp[0];
+ off = OFFSET(tp);
+ free_space = FREESPACE(tp);
+ tp[++n] = (u_int16_t)addr;
+ tp[++n] = OVFLPAGE;
+ tp[0] = n;
+ OFFSET(tp) = off;
+ FREESPACE(tp) = free_space - OVFLSIZE;
+
+ /*
+ * Finally, set the new and old return values. BIG_KEYP contains a
+ * pointer to the last page of the big key_data pair. Make sure that
+ * big_keyp has no following page (2 elements) or create an empty
+ * following page.
+ */
+
+ ret->newp = np;
+ ret->oldp = op;
+
+ tp = (u_int16_t *)big_keyp->page;
+ big_keyp->flags |= BUF_MOD;
+ if (tp[0] > 2) {
+ /*
+ * There may be either one or two offsets on this page. If
+ * there is one, then the overflow page is linked on normally
+ * and tp[4] is OVFLPAGE. If there are two, tp[4] contains
+ * the second offset and needs to get stuffed in after the
+ * next overflow page is added.
+ */
+ n = tp[4];
+ free_space = FREESPACE(tp);
+ off = OFFSET(tp);
+ tp[0] -= 2;
+ FREESPACE(tp) = free_space + OVFLSIZE;
+ OFFSET(tp) = off;
+ tmpp = __add_ovflpage(hashp, big_keyp);
+ if (!tmpp)
+ return (-1);
+ tp[4] = n;
+ } else
+ tmpp = big_keyp;
+
+ if (change)
+ ret->newp = tmpp;
+ else
+ ret->oldp = tmpp;
+ return (0);
+}
diff --git a/lib/libc/db/hash/hash_buf.c b/lib/libc/db/hash/hash_buf.c
new file mode 100644
index 0000000..4445fc5
--- /dev/null
+++ b/lib/libc/db/hash/hash_buf.c
@@ -0,0 +1,358 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_buf.c 8.5 (Berkeley) 7/15/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * PACKAGE: hash
+ *
+ * DESCRIPTION:
+ * Contains buffer management
+ *
+ * ROUTINES:
+ * External
+ * __buf_init
+ * __get_buf
+ * __buf_free
+ * __reclaim_buf
+ * Internal
+ * newbuf
+ */
+
+#include <sys/param.h>
+
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef DEBUG
+#include <assert.h>
+#endif
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static BUFHEAD *newbuf(HTAB *, u_int32_t, BUFHEAD *);
+
+/* Unlink B from its place in the lru */
+#define BUF_REMOVE(B) { \
+ (B)->prev->next = (B)->next; \
+ (B)->next->prev = (B)->prev; \
+}
+
+/* Insert B after P */
+#define BUF_INSERT(B, P) { \
+ (B)->next = (P)->next; \
+ (B)->prev = (P); \
+ (P)->next = (B); \
+ (B)->next->prev = (B); \
+}
+
+#define MRU hashp->bufhead.next
+#define LRU hashp->bufhead.prev
+
+#define MRU_INSERT(B) BUF_INSERT((B), &hashp->bufhead)
+#define LRU_INSERT(B) BUF_INSERT((B), LRU)
+
+/*
+ * We are looking for a buffer with address "addr". If prev_bp is NULL, then
+ * address is a bucket index. If prev_bp is not NULL, then it points to the
+ * page previous to an overflow page that we are trying to find.
+ *
+ * CAVEAT: The buffer header accessed via prev_bp's ovfl field may no longer
+ * be valid. Therefore, you must always verify that its address matches the
+ * address you are seeking.
+ */
+BUFHEAD *
+__get_buf(HTAB *hashp, u_int32_t addr,
+ BUFHEAD *prev_bp, /* If prev_bp set, indicates a new overflow page. */
+ int newpage)
+{
+ BUFHEAD *bp;
+ u_int32_t is_disk_mask;
+ int is_disk, segment_ndx;
+ SEGMENT segp;
+
+ is_disk = 0;
+ is_disk_mask = 0;
+ if (prev_bp) {
+ bp = prev_bp->ovfl;
+ if (!bp || (bp->addr != addr))
+ bp = NULL;
+ if (!newpage)
+ is_disk = BUF_DISK;
+ } else {
+ /* Grab buffer out of directory */
+ segment_ndx = addr & (hashp->SGSIZE - 1);
+
+ /* valid segment ensured by __call_hash() */
+ segp = hashp->dir[addr >> hashp->SSHIFT];
+#ifdef DEBUG
+ assert(segp != NULL);
+#endif
+ bp = PTROF(segp[segment_ndx]);
+ is_disk_mask = ISDISK(segp[segment_ndx]);
+ is_disk = is_disk_mask || !hashp->new_file;
+ }
+
+ if (!bp) {
+ bp = newbuf(hashp, addr, prev_bp);
+ if (!bp ||
+ __get_page(hashp, bp->page, addr, !prev_bp, is_disk, 0))
+ return (NULL);
+ if (!prev_bp)
+ segp[segment_ndx] =
+ (BUFHEAD *)((ptrdiff_t)bp | is_disk_mask);
+ } else {
+ BUF_REMOVE(bp);
+ MRU_INSERT(bp);
+ }
+ return (bp);
+}
+
+/*
+ * We need a buffer for this page. Either allocate one, or evict a resident
+ * one (if we have as many buffers as we're allowed) and put this one in.
+ *
+ * If newbuf finds an error (returning NULL), it also sets errno.
+ */
+static BUFHEAD *
+newbuf(HTAB *hashp, u_int32_t addr, BUFHEAD *prev_bp)
+{
+ BUFHEAD *bp; /* The buffer we're going to use */
+ BUFHEAD *xbp; /* Temp pointer */
+ BUFHEAD *next_xbp;
+ SEGMENT segp;
+ int segment_ndx;
+ u_int16_t oaddr, *shortp;
+
+ oaddr = 0;
+ bp = LRU;
+
+ /* It is bad to overwrite the page under the cursor. */
+ if (bp == hashp->cpage) {
+ BUF_REMOVE(bp);
+ MRU_INSERT(bp);
+ bp = LRU;
+ }
+
+ /* If prev_bp is part of bp overflow, create a new buffer. */
+ if (hashp->nbufs == 0 && prev_bp && bp->ovfl) {
+ BUFHEAD *ovfl;
+
+ for (ovfl = bp->ovfl; ovfl ; ovfl = ovfl->ovfl) {
+ if (ovfl == prev_bp) {
+ hashp->nbufs++;
+ break;
+ }
+ }
+ }
+
+ /*
+ * If LRU buffer is pinned, the buffer pool is too small. We need to
+ * allocate more buffers.
+ */
+ if (hashp->nbufs || (bp->flags & BUF_PIN) || bp == hashp->cpage) {
+ /* Allocate a new one */
+ if ((bp = (BUFHEAD *)calloc(1, sizeof(BUFHEAD))) == NULL)
+ return (NULL);
+ if ((bp->page = (char *)calloc(1, hashp->BSIZE)) == NULL) {
+ free(bp);
+ return (NULL);
+ }
+ if (hashp->nbufs)
+ hashp->nbufs--;
+ } else {
+ /* Kick someone out */
+ BUF_REMOVE(bp);
+ /*
+ * If this is an overflow page with addr 0, it's already been
+ * flushed back in an overflow chain and initialized.
+ */
+ if ((bp->addr != 0) || (bp->flags & BUF_BUCKET)) {
+ /*
+ * Set oaddr before __put_page so that you get it
+ * before bytes are swapped.
+ */
+ shortp = (u_int16_t *)bp->page;
+ if (shortp[0])
+ oaddr = shortp[shortp[0] - 1];
+ if ((bp->flags & BUF_MOD) && __put_page(hashp, bp->page,
+ bp->addr, (int)IS_BUCKET(bp->flags), 0))
+ return (NULL);
+ /*
+ * Update the pointer to this page (i.e. invalidate it).
+ *
+ * If this is a new file (i.e. we created it at open
+ * time), make sure that we mark pages which have been
+ * written to disk so we retrieve them from disk later,
+ * rather than allocating new pages.
+ */
+ if (IS_BUCKET(bp->flags)) {
+ segment_ndx = bp->addr & (hashp->SGSIZE - 1);
+ segp = hashp->dir[bp->addr >> hashp->SSHIFT];
+#ifdef DEBUG
+ assert(segp != NULL);
+#endif
+
+ if (hashp->new_file &&
+ ((bp->flags & BUF_MOD) ||
+ ISDISK(segp[segment_ndx])))
+ segp[segment_ndx] = (BUFHEAD *)BUF_DISK;
+ else
+ segp[segment_ndx] = NULL;
+ }
+ /*
+ * Since overflow pages can only be access by means of
+ * their bucket, free overflow pages associated with
+ * this bucket.
+ */
+ for (xbp = bp; xbp->ovfl;) {
+ next_xbp = xbp->ovfl;
+ xbp->ovfl = 0;
+ xbp = next_xbp;
+
+ /* Check that ovfl pointer is up date. */
+ if (IS_BUCKET(xbp->flags) ||
+ (oaddr != xbp->addr))
+ break;
+
+ shortp = (u_int16_t *)xbp->page;
+ if (shortp[0])
+ /* set before __put_page */
+ oaddr = shortp[shortp[0] - 1];
+ if ((xbp->flags & BUF_MOD) && __put_page(hashp,
+ xbp->page, xbp->addr, 0, 0))
+ return (NULL);
+ xbp->addr = 0;
+ xbp->flags = 0;
+ BUF_REMOVE(xbp);
+ LRU_INSERT(xbp);
+ }
+ }
+ }
+
+ /* Now assign this buffer */
+ bp->addr = addr;
+#ifdef DEBUG1
+ (void)fprintf(stderr, "NEWBUF1: %d->ovfl was %d is now %d\n",
+ bp->addr, (bp->ovfl ? bp->ovfl->addr : 0), 0);
+#endif
+ bp->ovfl = NULL;
+ if (prev_bp) {
+ /*
+ * If prev_bp is set, this is an overflow page, hook it in to
+ * the buffer overflow links.
+ */
+#ifdef DEBUG1
+ (void)fprintf(stderr, "NEWBUF2: %d->ovfl was %d is now %d\n",
+ prev_bp->addr, (prev_bp->ovfl ? prev_bp->ovfl->addr : 0),
+ (bp ? bp->addr : 0));
+#endif
+ prev_bp->ovfl = bp;
+ bp->flags = 0;
+ } else
+ bp->flags = BUF_BUCKET;
+ MRU_INSERT(bp);
+ return (bp);
+}
+
+void
+__buf_init(HTAB *hashp, int nbytes)
+{
+ BUFHEAD *bfp;
+ int npages;
+
+ bfp = &(hashp->bufhead);
+ npages = (nbytes + hashp->BSIZE - 1) >> hashp->BSHIFT;
+ npages = MAX(npages, MIN_BUFFERS);
+
+ hashp->nbufs = npages;
+ bfp->next = bfp;
+ bfp->prev = bfp;
+ /*
+ * This space is calloc'd so these are already null.
+ *
+ * bfp->ovfl = NULL;
+ * bfp->flags = 0;
+ * bfp->page = NULL;
+ * bfp->addr = 0;
+ */
+}
+
+int
+__buf_free(HTAB *hashp, int do_free, int to_disk)
+{
+ BUFHEAD *bp;
+
+ /* Need to make sure that buffer manager has been initialized */
+ if (!LRU)
+ return (0);
+ for (bp = LRU; bp != &hashp->bufhead;) {
+ /* Check that the buffer is valid */
+ if (bp->addr || IS_BUCKET(bp->flags)) {
+ if (to_disk && (bp->flags & BUF_MOD) &&
+ __put_page(hashp, bp->page,
+ bp->addr, IS_BUCKET(bp->flags), 0))
+ return (-1);
+ }
+ /* Check if we are freeing stuff */
+ if (do_free) {
+ if (bp->page) {
+ (void)memset(bp->page, 0, hashp->BSIZE);
+ free(bp->page);
+ }
+ BUF_REMOVE(bp);
+ free(bp);
+ bp = LRU;
+ } else
+ bp = bp->prev;
+ }
+ return (0);
+}
+
+void
+__reclaim_buf(HTAB *hashp, BUFHEAD *bp)
+{
+ bp->ovfl = 0;
+ bp->addr = 0;
+ bp->flags = 0;
+ BUF_REMOVE(bp);
+ LRU_INSERT(bp);
+}
diff --git a/lib/libc/db/hash/hash_func.c b/lib/libc/db/hash/hash_func.c
new file mode 100644
index 0000000..db32a75
--- /dev/null
+++ b/lib/libc/db/hash/hash_func.c
@@ -0,0 +1,190 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_func.c 8.2 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+#ifdef notdef
+static u_int32_t hash1(const void *, size_t) __unused;
+static u_int32_t hash2(const void *, size_t) __unused;
+static u_int32_t hash3(const void *, size_t) __unused;
+#endif
+static u_int32_t hash4(const void *, size_t);
+
+/* Default hash function. */
+u_int32_t (*__default_hash)(const void *, size_t) = hash4;
+
+#ifdef notdef
+/*
+ * Assume that we've already split the bucket to which this key hashes,
+ * calculate that bucket, and check that in fact we did already split it.
+ *
+ * EJB's original hsearch hash.
+ */
+#define PRIME1 37
+#define PRIME2 1048583
+
+u_int32_t
+hash1(const void *key, size_t len)
+{
+ u_int32_t h;
+ u_int8_t *k;
+
+ h = 0;
+ k = (u_int8_t *)key;
+ /* Convert string to integer */
+ while (len--)
+ h = h * PRIME1 ^ (*k++ - ' ');
+ h %= PRIME2;
+ return (h);
+}
+
+/*
+ * Phong Vo's linear congruential hash
+ */
+#define dcharhash(h, c) ((h) = 0x63c63cd9*(h) + 0x9c39c33d + (c))
+
+u_int32_t
+hash2(const void *key, size_t len)
+{
+ u_int32_t h;
+ u_int8_t *e, c, *k;
+
+ k = (u_int8_t *)key;
+ e = k + len;
+ for (h = 0; k != e;) {
+ c = *k++;
+ if (!c && k > e)
+ break;
+ dcharhash(h, c);
+ }
+ return (h);
+}
+
+/*
+ * This is INCREDIBLY ugly, but fast. We break the string up into 8 byte
+ * units. On the first time through the loop we get the "leftover bytes"
+ * (strlen % 8). On every other iteration, we perform 8 HASHC's so we handle
+ * all 8 bytes. Essentially, this saves us 7 cmp & branch instructions. If
+ * this routine is heavily used enough, it's worth the ugly coding.
+ *
+ * Ozan Yigit's original sdbm hash.
+ */
+u_int32_t
+hash3(const void *key, size_t len)
+{
+ u_int32_t n, loop;
+ u_int8_t *k;
+
+#define HASHC n = *k++ + 65599 * n
+
+ n = 0;
+ k = (u_int8_t *)key;
+ if (len > 0) {
+ loop = (len + 8 - 1) >> 3;
+
+ switch (len & (8 - 1)) {
+ case 0:
+ do { /* All fall throughs */
+ HASHC;
+ case 7:
+ HASHC;
+ case 6:
+ HASHC;
+ case 5:
+ HASHC;
+ case 4:
+ HASHC;
+ case 3:
+ HASHC;
+ case 2:
+ HASHC;
+ case 1:
+ HASHC;
+ } while (--loop);
+ }
+
+ }
+ return (n);
+}
+#endif /* notdef */
+
+/* Chris Torek's hash function. */
+u_int32_t
+hash4(const void *key, size_t len)
+{
+ u_int32_t h, loop;
+ const u_int8_t *k;
+
+#define HASH4a h = (h << 5) - h + *k++;
+#define HASH4b h = (h << 5) + h + *k++;
+#define HASH4 HASH4b
+
+ h = 0;
+ k = key;
+ if (len > 0) {
+ loop = (len + 8 - 1) >> 3;
+
+ switch (len & (8 - 1)) {
+ case 0:
+ do { /* All fall throughs */
+ HASH4;
+ case 7:
+ HASH4;
+ case 6:
+ HASH4;
+ case 5:
+ HASH4;
+ case 4:
+ HASH4;
+ case 3:
+ HASH4;
+ case 2:
+ HASH4;
+ case 1:
+ HASH4;
+ } while (--loop);
+ }
+
+ }
+ return (h);
+}
diff --git a/lib/libc/db/hash/hash_log2.c b/lib/libc/db/hash/hash_log2.c
new file mode 100644
index 0000000..0586aa7
--- /dev/null
+++ b/lib/libc/db/hash/hash_log2.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_log2.c 8.2 (Berkeley) 5/31/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+u_int32_t
+__log2(u_int32_t num)
+{
+ u_int32_t i, limit;
+
+ limit = 1;
+ for (i = 0; limit < num; limit = limit << 1, i++);
+ return (i);
+}
diff --git a/lib/libc/db/hash/hash_page.c b/lib/libc/db/hash/hash_page.c
new file mode 100644
index 0000000..fa01775
--- /dev/null
+++ b/lib/libc/db/hash/hash_page.c
@@ -0,0 +1,936 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)hash_page.c 8.7 (Berkeley) 8/16/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * PACKAGE: hashing
+ *
+ * DESCRIPTION:
+ * Page manipulation for hashing package.
+ *
+ * ROUTINES:
+ *
+ * External
+ * __get_page
+ * __add_ovflpage
+ * Internal
+ * overflow_page
+ * open_temp
+ */
+
+#include "namespace.h"
+#include <sys/param.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#ifdef DEBUG
+#include <assert.h>
+#endif
+#include "un-namespace.h"
+
+#include <db.h>
+#include "hash.h"
+#include "page.h"
+#include "extern.h"
+
+static u_int32_t *fetch_bitmap(HTAB *, int);
+static u_int32_t first_free(u_int32_t);
+static int open_temp(HTAB *);
+static u_int16_t overflow_page(HTAB *);
+static void putpair(char *, const DBT *, const DBT *);
+static void squeeze_key(u_int16_t *, const DBT *, const DBT *);
+static int ugly_split(HTAB *, u_int32_t, BUFHEAD *, BUFHEAD *, int, int);
+
+#define PAGE_INIT(P) { \
+ ((u_int16_t *)(P))[0] = 0; \
+ ((u_int16_t *)(P))[1] = hashp->BSIZE - 3 * sizeof(u_int16_t); \
+ ((u_int16_t *)(P))[2] = hashp->BSIZE; \
+}
+
+/*
+ * This is called AFTER we have verified that there is room on the page for
+ * the pair (PAIRFITS has returned true) so we go right ahead and start moving
+ * stuff on.
+ */
+static void
+putpair(char *p, const DBT *key, const DBT *val)
+{
+ u_int16_t *bp, n, off;
+
+ bp = (u_int16_t *)p;
+
+ /* Enter the key first. */
+ n = bp[0];
+
+ off = OFFSET(bp) - key->size;
+ memmove(p + off, key->data, key->size);
+ bp[++n] = off;
+
+ /* Now the data. */
+ off -= val->size;
+ memmove(p + off, val->data, val->size);
+ bp[++n] = off;
+
+ /* Adjust page info. */
+ bp[0] = n;
+ bp[n + 1] = off - ((n + 3) * sizeof(u_int16_t));
+ bp[n + 2] = off;
+}
+
+/*
+ * Returns:
+ * 0 OK
+ * -1 error
+ */
+int
+__delpair(HTAB *hashp, BUFHEAD *bufp, int ndx)
+{
+ u_int16_t *bp, newoff, pairlen;
+ int n;
+
+ bp = (u_int16_t *)bufp->page;
+ n = bp[0];
+
+ if (bp[ndx + 1] < REAL_KEY)
+ return (__big_delete(hashp, bufp));
+ if (ndx != 1)
+ newoff = bp[ndx - 1];
+ else
+ newoff = hashp->BSIZE;
+ pairlen = newoff - bp[ndx + 1];
+
+ if (ndx != (n - 1)) {
+ /* Hard Case -- need to shuffle keys */
+ int i;
+ char *src = bufp->page + (int)OFFSET(bp);
+ char *dst = src + (int)pairlen;
+ memmove(dst, src, bp[ndx + 1] - OFFSET(bp));
+
+ /* Now adjust the pointers */
+ for (i = ndx + 2; i <= n; i += 2) {
+ if (bp[i + 1] == OVFLPAGE) {
+ bp[i - 2] = bp[i];
+ bp[i - 1] = bp[i + 1];
+ } else {
+ bp[i - 2] = bp[i] + pairlen;
+ bp[i - 1] = bp[i + 1] + pairlen;
+ }
+ }
+ if (ndx == hashp->cndx) {
+ /*
+ * We just removed pair we were "pointing" to.
+ * By moving back the cndx we ensure subsequent
+ * hash_seq() calls won't skip over any entries.
+ */
+ hashp->cndx -= 2;
+ }
+ }
+ /* Finally adjust the page data */
+ bp[n] = OFFSET(bp) + pairlen;
+ bp[n - 1] = bp[n + 1] + pairlen + 2 * sizeof(u_int16_t);
+ bp[0] = n - 2;
+ hashp->NKEYS--;
+
+ bufp->flags |= BUF_MOD;
+ return (0);
+}
+/*
+ * Returns:
+ * 0 ==> OK
+ * -1 ==> Error
+ */
+int
+__split_page(HTAB *hashp, u_int32_t obucket, u_int32_t nbucket)
+{
+ BUFHEAD *new_bufp, *old_bufp;
+ u_int16_t *ino;
+ char *np;
+ DBT key, val;
+ int n, ndx, retval;
+ u_int16_t copyto, diff, off, moved;
+ char *op;
+
+ copyto = (u_int16_t)hashp->BSIZE;
+ off = (u_int16_t)hashp->BSIZE;
+ old_bufp = __get_buf(hashp, obucket, NULL, 0);
+ if (old_bufp == NULL)
+ return (-1);
+ new_bufp = __get_buf(hashp, nbucket, NULL, 0);
+ if (new_bufp == NULL)
+ return (-1);
+
+ old_bufp->flags |= (BUF_MOD | BUF_PIN);
+ new_bufp->flags |= (BUF_MOD | BUF_PIN);
+
+ ino = (u_int16_t *)(op = old_bufp->page);
+ np = new_bufp->page;
+
+ moved = 0;
+
+ for (n = 1, ndx = 1; n < ino[0]; n += 2) {
+ if (ino[n + 1] < REAL_KEY) {
+ retval = ugly_split(hashp, obucket, old_bufp, new_bufp,
+ (int)copyto, (int)moved);
+ old_bufp->flags &= ~BUF_PIN;
+ new_bufp->flags &= ~BUF_PIN;
+ return (retval);
+
+ }
+ key.data = (u_char *)op + ino[n];
+ key.size = off - ino[n];
+
+ if (__call_hash(hashp, key.data, key.size) == obucket) {
+ /* Don't switch page */
+ diff = copyto - off;
+ if (diff) {
+ copyto = ino[n + 1] + diff;
+ memmove(op + copyto, op + ino[n + 1],
+ off - ino[n + 1]);
+ ino[ndx] = copyto + ino[n] - ino[n + 1];
+ ino[ndx + 1] = copyto;
+ } else
+ copyto = ino[n + 1];
+ ndx += 2;
+ } else {
+ /* Switch page */
+ val.data = (u_char *)op + ino[n + 1];
+ val.size = ino[n] - ino[n + 1];
+ putpair(np, &key, &val);
+ moved += 2;
+ }
+
+ off = ino[n + 1];
+ }
+
+ /* Now clean up the page */
+ ino[0] -= moved;
+ FREESPACE(ino) = copyto - sizeof(u_int16_t) * (ino[0] + 3);
+ OFFSET(ino) = copyto;
+
+#ifdef DEBUG3
+ (void)fprintf(stderr, "split %d/%d\n",
+ ((u_int16_t *)np)[0] / 2,
+ ((u_int16_t *)op)[0] / 2);
+#endif
+ /* unpin both pages */
+ old_bufp->flags &= ~BUF_PIN;
+ new_bufp->flags &= ~BUF_PIN;
+ return (0);
+}
+
+/*
+ * Called when we encounter an overflow or big key/data page during split
+ * handling. This is special cased since we have to begin checking whether
+ * the key/data pairs fit on their respective pages and because we may need
+ * overflow pages for both the old and new pages.
+ *
+ * The first page might be a page with regular key/data pairs in which case
+ * we have a regular overflow condition and just need to go on to the next
+ * page or it might be a big key/data pair in which case we need to fix the
+ * big key/data pair.
+ *
+ * Returns:
+ * 0 ==> success
+ * -1 ==> failure
+ */
+static int
+ugly_split(HTAB *hashp,
+ u_int32_t obucket, /* Same as __split_page. */
+ BUFHEAD *old_bufp,
+ BUFHEAD *new_bufp,
+ int copyto, /* First byte on page which contains key/data values. */
+ int moved) /* Number of pairs moved to new page. */
+{
+ BUFHEAD *bufp; /* Buffer header for ino */
+ u_int16_t *ino; /* Page keys come off of */
+ u_int16_t *np; /* New page */
+ u_int16_t *op; /* Page keys go on to if they aren't moving */
+
+ BUFHEAD *last_bfp; /* Last buf header OVFL needing to be freed */
+ DBT key, val;
+ SPLIT_RETURN ret;
+ u_int16_t n, off, ov_addr, scopyto;
+ char *cino; /* Character value of ino */
+
+ bufp = old_bufp;
+ ino = (u_int16_t *)old_bufp->page;
+ np = (u_int16_t *)new_bufp->page;
+ op = (u_int16_t *)old_bufp->page;
+ last_bfp = NULL;
+ scopyto = (u_int16_t)copyto; /* ANSI */
+
+ n = ino[0] - 1;
+ while (n < ino[0]) {
+ if (ino[2] < REAL_KEY && ino[2] != OVFLPAGE) {
+ if (__big_split(hashp, old_bufp,
+ new_bufp, bufp, bufp->addr, obucket, &ret))
+ return (-1);
+ old_bufp = ret.oldp;
+ if (!old_bufp)
+ return (-1);
+ op = (u_int16_t *)old_bufp->page;
+ new_bufp = ret.newp;
+ if (!new_bufp)
+ return (-1);
+ np = (u_int16_t *)new_bufp->page;
+ bufp = ret.nextp;
+ if (!bufp)
+ return (0);
+ cino = (char *)bufp->page;
+ ino = (u_int16_t *)cino;
+ last_bfp = ret.nextp;
+ } else if (ino[n + 1] == OVFLPAGE) {
+ ov_addr = ino[n];
+ /*
+ * Fix up the old page -- the extra 2 are the fields
+ * which contained the overflow information.
+ */
+ ino[0] -= (moved + 2);
+ FREESPACE(ino) =
+ scopyto - sizeof(u_int16_t) * (ino[0] + 3);
+ OFFSET(ino) = scopyto;
+
+ bufp = __get_buf(hashp, ov_addr, bufp, 0);
+ if (!bufp)
+ return (-1);
+
+ ino = (u_int16_t *)bufp->page;
+ n = 1;
+ scopyto = hashp->BSIZE;
+ moved = 0;
+
+ if (last_bfp)
+ __free_ovflpage(hashp, last_bfp);
+ last_bfp = bufp;
+ }
+ /* Move regular sized pairs of there are any */
+ off = hashp->BSIZE;
+ for (n = 1; (n < ino[0]) && (ino[n + 1] >= REAL_KEY); n += 2) {
+ cino = (char *)ino;
+ key.data = (u_char *)cino + ino[n];
+ key.size = off - ino[n];
+ val.data = (u_char *)cino + ino[n + 1];
+ val.size = ino[n] - ino[n + 1];
+ off = ino[n + 1];
+
+ if (__call_hash(hashp, key.data, key.size) == obucket) {
+ /* Keep on old page */
+ if (PAIRFITS(op, (&key), (&val)))
+ putpair((char *)op, &key, &val);
+ else {
+ old_bufp =
+ __add_ovflpage(hashp, old_bufp);
+ if (!old_bufp)
+ return (-1);
+ op = (u_int16_t *)old_bufp->page;
+ putpair((char *)op, &key, &val);
+ }
+ old_bufp->flags |= BUF_MOD;
+ } else {
+ /* Move to new page */
+ if (PAIRFITS(np, (&key), (&val)))
+ putpair((char *)np, &key, &val);
+ else {
+ new_bufp =
+ __add_ovflpage(hashp, new_bufp);
+ if (!new_bufp)
+ return (-1);
+ np = (u_int16_t *)new_bufp->page;
+ putpair((char *)np, &key, &val);
+ }
+ new_bufp->flags |= BUF_MOD;
+ }
+ }
+ }
+ if (last_bfp)
+ __free_ovflpage(hashp, last_bfp);
+ return (0);
+}
+
+/*
+ * Add the given pair to the page
+ *
+ * Returns:
+ * 0 ==> OK
+ * 1 ==> failure
+ */
+int
+__addel(HTAB *hashp, BUFHEAD *bufp, const DBT *key, const DBT *val)
+{
+ u_int16_t *bp, *sop;
+ int do_expand;
+
+ bp = (u_int16_t *)bufp->page;
+ do_expand = 0;
+ while (bp[0] && (bp[2] < REAL_KEY || bp[bp[0]] < REAL_KEY))
+ /* Exception case */
+ if (bp[2] == FULL_KEY_DATA && bp[0] == 2)
+ /* This is the last page of a big key/data pair
+ and we need to add another page */
+ break;
+ else if (bp[2] < REAL_KEY && bp[bp[0]] != OVFLPAGE) {
+ bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+ if (!bufp)
+ return (-1);
+ bp = (u_int16_t *)bufp->page;
+ } else if (bp[bp[0]] != OVFLPAGE) {
+ /* Short key/data pairs, no more pages */
+ break;
+ } else {
+ /* Try to squeeze key on this page */
+ if (bp[2] >= REAL_KEY &&
+ FREESPACE(bp) >= PAIRSIZE(key, val)) {
+ squeeze_key(bp, key, val);
+ goto stats;
+ } else {
+ bufp = __get_buf(hashp, bp[bp[0] - 1], bufp, 0);
+ if (!bufp)
+ return (-1);
+ bp = (u_int16_t *)bufp->page;
+ }
+ }
+
+ if (PAIRFITS(bp, key, val))
+ putpair(bufp->page, key, val);
+ else {
+ do_expand = 1;
+ bufp = __add_ovflpage(hashp, bufp);
+ if (!bufp)
+ return (-1);
+ sop = (u_int16_t *)bufp->page;
+
+ if (PAIRFITS(sop, key, val))
+ putpair((char *)sop, key, val);
+ else
+ if (__big_insert(hashp, bufp, key, val))
+ return (-1);
+ }
+stats:
+ bufp->flags |= BUF_MOD;
+ /*
+ * If the average number of keys per bucket exceeds the fill factor,
+ * expand the table.
+ */
+ hashp->NKEYS++;
+ if (do_expand ||
+ (hashp->NKEYS / (hashp->MAX_BUCKET + 1) > hashp->FFACTOR))
+ return (__expand_table(hashp));
+ return (0);
+}
+
+/*
+ *
+ * Returns:
+ * pointer on success
+ * NULL on error
+ */
+BUFHEAD *
+__add_ovflpage(HTAB *hashp, BUFHEAD *bufp)
+{
+ u_int16_t *sp, ndx, ovfl_num;
+#ifdef DEBUG1
+ int tmp1, tmp2;
+#endif
+ sp = (u_int16_t *)bufp->page;
+
+ /* Check if we are dynamically determining the fill factor */
+ if (hashp->FFACTOR == DEF_FFACTOR) {
+ hashp->FFACTOR = sp[0] >> 1;
+ if (hashp->FFACTOR < MIN_FFACTOR)
+ hashp->FFACTOR = MIN_FFACTOR;
+ }
+ bufp->flags |= BUF_MOD;
+ ovfl_num = overflow_page(hashp);
+#ifdef DEBUG1
+ tmp1 = bufp->addr;
+ tmp2 = bufp->ovfl ? bufp->ovfl->addr : 0;
+#endif
+ if (!ovfl_num || !(bufp->ovfl = __get_buf(hashp, ovfl_num, bufp, 1)))
+ return (NULL);
+ bufp->ovfl->flags |= BUF_MOD;
+#ifdef DEBUG1
+ (void)fprintf(stderr, "ADDOVFLPAGE: %d->ovfl was %d is now %d\n",
+ tmp1, tmp2, bufp->ovfl->addr);
+#endif
+ ndx = sp[0];
+ /*
+ * Since a pair is allocated on a page only if there's room to add
+ * an overflow page, we know that the OVFL information will fit on
+ * the page.
+ */
+ sp[ndx + 4] = OFFSET(sp);
+ sp[ndx + 3] = FREESPACE(sp) - OVFLSIZE;
+ sp[ndx + 1] = ovfl_num;
+ sp[ndx + 2] = OVFLPAGE;
+ sp[0] = ndx + 2;
+#ifdef HASH_STATISTICS
+ hash_overflows++;
+#endif
+ return (bufp->ovfl);
+}
+
+/*
+ * Returns:
+ * 0 indicates SUCCESS
+ * -1 indicates FAILURE
+ */
+int
+__get_page(HTAB *hashp, char *p, u_int32_t bucket, int is_bucket, int is_disk,
+ int is_bitmap)
+{
+ int fd, page, size, rsize;
+ u_int16_t *bp;
+
+ fd = hashp->fp;
+ size = hashp->BSIZE;
+
+ if ((fd == -1) || !is_disk) {
+ PAGE_INIT(p);
+ return (0);
+ }
+ if (is_bucket)
+ page = BUCKET_TO_PAGE(bucket);
+ else
+ page = OADDR_TO_PAGE(bucket);
+ if ((rsize = pread(fd, p, size, (off_t)page << hashp->BSHIFT)) == -1)
+ return (-1);
+ bp = (u_int16_t *)p;
+ if (!rsize)
+ bp[0] = 0; /* We hit the EOF, so initialize a new page */
+ else
+ if (rsize != size) {
+ errno = EFTYPE;
+ return (-1);
+ }
+ if (!is_bitmap && !bp[0]) {
+ PAGE_INIT(p);
+ } else
+ if (hashp->LORDER != BYTE_ORDER) {
+ int i, max;
+
+ if (is_bitmap) {
+ max = hashp->BSIZE >> 2; /* divide by 4 */
+ for (i = 0; i < max; i++)
+ M_32_SWAP(((int *)p)[i]);
+ } else {
+ M_16_SWAP(bp[0]);
+ max = bp[0] + 2;
+ for (i = 1; i <= max; i++)
+ M_16_SWAP(bp[i]);
+ }
+ }
+ return (0);
+}
+
+/*
+ * Write page p to disk
+ *
+ * Returns:
+ * 0 ==> OK
+ * -1 ==>failure
+ */
+int
+__put_page(HTAB *hashp, char *p, u_int32_t bucket, int is_bucket, int is_bitmap)
+{
+ int fd, page, size, wsize;
+
+ size = hashp->BSIZE;
+ if ((hashp->fp == -1) && open_temp(hashp))
+ return (-1);
+ fd = hashp->fp;
+
+ if (hashp->LORDER != BYTE_ORDER) {
+ int i, max;
+
+ if (is_bitmap) {
+ max = hashp->BSIZE >> 2; /* divide by 4 */
+ for (i = 0; i < max; i++)
+ M_32_SWAP(((int *)p)[i]);
+ } else {
+ max = ((u_int16_t *)p)[0] + 2;
+ for (i = 0; i <= max; i++)
+ M_16_SWAP(((u_int16_t *)p)[i]);
+ }
+ }
+ if (is_bucket)
+ page = BUCKET_TO_PAGE(bucket);
+ else
+ page = OADDR_TO_PAGE(bucket);
+ if ((wsize = pwrite(fd, p, size, (off_t)page << hashp->BSHIFT)) == -1)
+ /* Errno is set */
+ return (-1);
+ if (wsize != size) {
+ errno = EFTYPE;
+ return (-1);
+ }
+ return (0);
+}
+
+#define BYTE_MASK ((1 << INT_BYTE_SHIFT) -1)
+/*
+ * Initialize a new bitmap page. Bitmap pages are left in memory
+ * once they are read in.
+ */
+int
+__ibitmap(HTAB *hashp, int pnum, int nbits, int ndx)
+{
+ u_int32_t *ip;
+ int clearbytes, clearints;
+
+ if ((ip = (u_int32_t *)malloc(hashp->BSIZE)) == NULL)
+ return (1);
+ hashp->nmaps++;
+ clearints = ((nbits - 1) >> INT_BYTE_SHIFT) + 1;
+ clearbytes = clearints << INT_TO_BYTE;
+ (void)memset((char *)ip, 0, clearbytes);
+ (void)memset(((char *)ip) + clearbytes, 0xFF,
+ hashp->BSIZE - clearbytes);
+ ip[clearints - 1] = ALL_SET << (nbits & BYTE_MASK);
+ SETBIT(ip, 0);
+ hashp->BITMAPS[ndx] = (u_int16_t)pnum;
+ hashp->mapp[ndx] = ip;
+ return (0);
+}
+
+static u_int32_t
+first_free(u_int32_t map)
+{
+ u_int32_t i, mask;
+
+ mask = 0x1;
+ for (i = 0; i < BITS_PER_MAP; i++) {
+ if (!(mask & map))
+ return (i);
+ mask = mask << 1;
+ }
+ return (i);
+}
+
+static u_int16_t
+overflow_page(HTAB *hashp)
+{
+ u_int32_t *freep;
+ int max_free, offset, splitnum;
+ u_int16_t addr;
+ int bit, first_page, free_bit, free_page, i, in_use_bits, j;
+#ifdef DEBUG2
+ int tmp1, tmp2;
+#endif
+ splitnum = hashp->OVFL_POINT;
+ max_free = hashp->SPARES[splitnum];
+
+ free_page = (max_free - 1) >> (hashp->BSHIFT + BYTE_SHIFT);
+ free_bit = (max_free - 1) & ((hashp->BSIZE << BYTE_SHIFT) - 1);
+
+ /* Look through all the free maps to find the first free block */
+ first_page = hashp->LAST_FREED >>(hashp->BSHIFT + BYTE_SHIFT);
+ for ( i = first_page; i <= free_page; i++ ) {
+ if (!(freep = (u_int32_t *)hashp->mapp[i]) &&
+ !(freep = fetch_bitmap(hashp, i)))
+ return (0);
+ if (i == free_page)
+ in_use_bits = free_bit;
+ else
+ in_use_bits = (hashp->BSIZE << BYTE_SHIFT) - 1;
+
+ if (i == first_page) {
+ bit = hashp->LAST_FREED &
+ ((hashp->BSIZE << BYTE_SHIFT) - 1);
+ j = bit / BITS_PER_MAP;
+ bit = bit & ~(BITS_PER_MAP - 1);
+ } else {
+ bit = 0;
+ j = 0;
+ }
+ for (; bit <= in_use_bits; j++, bit += BITS_PER_MAP)
+ if (freep[j] != ALL_SET)
+ goto found;
+ }
+
+ /* No Free Page Found */
+ hashp->LAST_FREED = hashp->SPARES[splitnum];
+ hashp->SPARES[splitnum]++;
+ offset = hashp->SPARES[splitnum] -
+ (splitnum ? hashp->SPARES[splitnum - 1] : 0);
+
+#define OVMSG "HASH: Out of overflow pages. Increase page size\n"
+ if (offset > SPLITMASK) {
+ if (++splitnum >= NCACHED) {
+ (void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+ errno = EFBIG;
+ return (0);
+ }
+ hashp->OVFL_POINT = splitnum;
+ hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
+ hashp->SPARES[splitnum-1]--;
+ offset = 1;
+ }
+
+ /* Check if we need to allocate a new bitmap page */
+ if (free_bit == (hashp->BSIZE << BYTE_SHIFT) - 1) {
+ free_page++;
+ if (free_page >= NCACHED) {
+ (void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+ errno = EFBIG;
+ return (0);
+ }
+ /*
+ * This is tricky. The 1 indicates that you want the new page
+ * allocated with 1 clear bit. Actually, you are going to
+ * allocate 2 pages from this map. The first is going to be
+ * the map page, the second is the overflow page we were
+ * looking for. The init_bitmap routine automatically, sets
+ * the first bit of itself to indicate that the bitmap itself
+ * is in use. We would explicitly set the second bit, but
+ * don't have to if we tell init_bitmap not to leave it clear
+ * in the first place.
+ */
+ if (__ibitmap(hashp,
+ (int)OADDR_OF(splitnum, offset), 1, free_page))
+ return (0);
+ hashp->SPARES[splitnum]++;
+#ifdef DEBUG2
+ free_bit = 2;
+#endif
+ offset++;
+ if (offset > SPLITMASK) {
+ if (++splitnum >= NCACHED) {
+ (void)_write(STDERR_FILENO, OVMSG,
+ sizeof(OVMSG) - 1);
+ errno = EFBIG;
+ return (0);
+ }
+ hashp->OVFL_POINT = splitnum;
+ hashp->SPARES[splitnum] = hashp->SPARES[splitnum-1];
+ hashp->SPARES[splitnum-1]--;
+ offset = 0;
+ }
+ } else {
+ /*
+ * Free_bit addresses the last used bit. Bump it to address
+ * the first available bit.
+ */
+ free_bit++;
+ SETBIT(freep, free_bit);
+ }
+
+ /* Calculate address of the new overflow page */
+ addr = OADDR_OF(splitnum, offset);
+#ifdef DEBUG2
+ (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
+ addr, free_bit, free_page);
+#endif
+ return (addr);
+
+found:
+ bit = bit + first_free(freep[j]);
+ SETBIT(freep, bit);
+#ifdef DEBUG2
+ tmp1 = bit;
+ tmp2 = i;
+#endif
+ /*
+ * Bits are addressed starting with 0, but overflow pages are addressed
+ * beginning at 1. Bit is a bit addressnumber, so we need to increment
+ * it to convert it to a page number.
+ */
+ bit = 1 + bit + (i * (hashp->BSIZE << BYTE_SHIFT));
+ if (bit >= hashp->LAST_FREED)
+ hashp->LAST_FREED = bit - 1;
+
+ /* Calculate the split number for this page */
+ for (i = 0; (i < splitnum) && (bit > hashp->SPARES[i]); i++);
+ offset = (i ? bit - hashp->SPARES[i - 1] : bit);
+ if (offset >= SPLITMASK) {
+ (void)_write(STDERR_FILENO, OVMSG, sizeof(OVMSG) - 1);
+ errno = EFBIG;
+ return (0); /* Out of overflow pages */
+ }
+ addr = OADDR_OF(i, offset);
+#ifdef DEBUG2
+ (void)fprintf(stderr, "OVERFLOW_PAGE: ADDR: %d BIT: %d PAGE %d\n",
+ addr, tmp1, tmp2);
+#endif
+
+ /* Allocate and return the overflow page */
+ return (addr);
+}
+
+/*
+ * Mark this overflow page as free.
+ */
+void
+__free_ovflpage(HTAB *hashp, BUFHEAD *obufp)
+{
+ u_int16_t addr;
+ u_int32_t *freep;
+ int bit_address, free_page, free_bit;
+ u_int16_t ndx;
+
+ addr = obufp->addr;
+#ifdef DEBUG1
+ (void)fprintf(stderr, "Freeing %d\n", addr);
+#endif
+ ndx = (((u_int16_t)addr) >> SPLITSHIFT);
+ bit_address =
+ (ndx ? hashp->SPARES[ndx - 1] : 0) + (addr & SPLITMASK) - 1;
+ if (bit_address < hashp->LAST_FREED)
+ hashp->LAST_FREED = bit_address;
+ free_page = (bit_address >> (hashp->BSHIFT + BYTE_SHIFT));
+ free_bit = bit_address & ((hashp->BSIZE << BYTE_SHIFT) - 1);
+
+ if (!(freep = hashp->mapp[free_page]))
+ freep = fetch_bitmap(hashp, free_page);
+#ifdef DEBUG
+ /*
+ * This had better never happen. It means we tried to read a bitmap
+ * that has already had overflow pages allocated off it, and we
+ * failed to read it from the file.
+ */
+ if (!freep)
+ assert(0);
+#endif
+ CLRBIT(freep, free_bit);
+#ifdef DEBUG2
+ (void)fprintf(stderr, "FREE_OVFLPAGE: ADDR: %d BIT: %d PAGE %d\n",
+ obufp->addr, free_bit, free_page);
+#endif
+ __reclaim_buf(hashp, obufp);
+}
+
+/*
+ * Returns:
+ * 0 success
+ * -1 failure
+ */
+static int
+open_temp(HTAB *hashp)
+{
+ sigset_t set, oset;
+ int len;
+ char *envtmp = NULL;
+ char path[MAXPATHLEN];
+
+ if (issetugid() == 0)
+ envtmp = getenv("TMPDIR");
+ len = snprintf(path,
+ sizeof(path), "%s/_hash.XXXXXX", envtmp ? envtmp : "/tmp");
+ if (len < 0 || len >= (int)sizeof(path)) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+
+ /* Block signals; make sure file goes away at process exit. */
+ (void)sigfillset(&set);
+ (void)_sigprocmask(SIG_BLOCK, &set, &oset);
+ if ((hashp->fp = mkstemp(path)) != -1) {
+ (void)unlink(path);
+ (void)_fcntl(hashp->fp, F_SETFD, 1);
+ }
+ (void)_sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL);
+ return (hashp->fp != -1 ? 0 : -1);
+}
+
+/*
+ * We have to know that the key will fit, but the last entry on the page is
+ * an overflow pair, so we need to shift things.
+ */
+static void
+squeeze_key(u_int16_t *sp, const DBT *key, const DBT *val)
+{
+ char *p;
+ u_int16_t free_space, n, off, pageno;
+
+ p = (char *)sp;
+ n = sp[0];
+ free_space = FREESPACE(sp);
+ off = OFFSET(sp);
+
+ pageno = sp[n - 1];
+ off -= key->size;
+ sp[n - 1] = off;
+ memmove(p + off, key->data, key->size);
+ off -= val->size;
+ sp[n] = off;
+ memmove(p + off, val->data, val->size);
+ sp[0] = n + 2;
+ sp[n + 1] = pageno;
+ sp[n + 2] = OVFLPAGE;
+ FREESPACE(sp) = free_space - PAIRSIZE(key, val);
+ OFFSET(sp) = off;
+}
+
+static u_int32_t *
+fetch_bitmap(HTAB *hashp, int ndx)
+{
+ if (ndx >= hashp->nmaps)
+ return (NULL);
+ if ((hashp->mapp[ndx] = (u_int32_t *)malloc(hashp->BSIZE)) == NULL)
+ return (NULL);
+ if (__get_page(hashp,
+ (char *)hashp->mapp[ndx], hashp->BITMAPS[ndx], 0, 1, 1)) {
+ free(hashp->mapp[ndx]);
+ return (NULL);
+ }
+ return (hashp->mapp[ndx]);
+}
+
+#ifdef DEBUG4
+int
+print_chain(int addr)
+{
+ BUFHEAD *bufp;
+ short *bp, oaddr;
+
+ (void)fprintf(stderr, "%d ", addr);
+ bufp = __get_buf(hashp, addr, NULL, 0);
+ bp = (short *)bufp->page;
+ while (bp[0] && ((bp[bp[0]] == OVFLPAGE) ||
+ ((bp[0] > 2) && bp[2] < REAL_KEY))) {
+ oaddr = bp[bp[0] - 1];
+ (void)fprintf(stderr, "%d ", (int)oaddr);
+ bufp = __get_buf(hashp, (int)oaddr, bufp, 0);
+ bp = (short *)bufp->page;
+ }
+ (void)fprintf(stderr, "\n");
+}
+#endif
diff --git a/lib/libc/db/hash/ndbm.c b/lib/libc/db/hash/ndbm.c
new file mode 100644
index 0000000..42ffb1b
--- /dev/null
+++ b/lib/libc/db/hash/ndbm.c
@@ -0,0 +1,227 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ndbm.c 8.4 (Berkeley) 7/21/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * This package provides a dbm compatible interface to the new hashing
+ * package described in db(3).
+ */
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+
+#include <ndbm.h>
+#include "hash.h"
+
+/*
+ * Returns:
+ * *DBM on success
+ * NULL on failure
+ */
+extern DBM *
+dbm_open(file, flags, mode)
+ const char *file;
+ int flags, mode;
+{
+ HASHINFO info;
+ char path[MAXPATHLEN];
+
+ info.bsize = 4096;
+ info.ffactor = 40;
+ info.nelem = 1;
+ info.cachesize = 0;
+ info.hash = NULL;
+ info.lorder = 0;
+
+ if( strlen(file) >= sizeof(path) - strlen(DBM_SUFFIX)) {
+ errno = ENAMETOOLONG;
+ return(NULL);
+ }
+ (void)strcpy(path, file);
+ (void)strcat(path, DBM_SUFFIX);
+ return ((DBM *)__hash_open(path, flags, mode, &info, 0));
+}
+
+extern void
+dbm_close(db)
+ DBM *db;
+{
+ (void)(db->close)(db);
+}
+
+/*
+ * Returns:
+ * DATUM on success
+ * NULL on failure
+ */
+extern datum
+dbm_fetch(db, key)
+ DBM *db;
+ datum key;
+{
+ datum retdata;
+ int status;
+ DBT dbtkey, dbtretdata;
+
+ dbtkey.data = key.dptr;
+ dbtkey.size = key.dsize;
+ status = (db->get)(db, &dbtkey, &dbtretdata, 0);
+ if (status) {
+ dbtretdata.data = NULL;
+ dbtretdata.size = 0;
+ }
+ retdata.dptr = dbtretdata.data;
+ retdata.dsize = dbtretdata.size;
+ return (retdata);
+}
+
+/*
+ * Returns:
+ * DATUM on success
+ * NULL on failure
+ */
+extern datum
+dbm_firstkey(db)
+ DBM *db;
+{
+ int status;
+ datum retkey;
+ DBT dbtretkey, dbtretdata;
+
+ status = (db->seq)(db, &dbtretkey, &dbtretdata, R_FIRST);
+ if (status)
+ dbtretkey.data = NULL;
+ retkey.dptr = dbtretkey.data;
+ retkey.dsize = dbtretkey.size;
+ return (retkey);
+}
+
+/*
+ * Returns:
+ * DATUM on success
+ * NULL on failure
+ */
+extern datum
+dbm_nextkey(db)
+ DBM *db;
+{
+ int status;
+ datum retkey;
+ DBT dbtretkey, dbtretdata;
+
+ status = (db->seq)(db, &dbtretkey, &dbtretdata, R_NEXT);
+ if (status)
+ dbtretkey.data = NULL;
+ retkey.dptr = dbtretkey.data;
+ retkey.dsize = dbtretkey.size;
+ return (retkey);
+}
+
+/*
+ * Returns:
+ * 0 on success
+ * <0 failure
+ */
+extern int
+dbm_delete(db, key)
+ DBM *db;
+ datum key;
+{
+ int status;
+ DBT dbtkey;
+
+ dbtkey.data = key.dptr;
+ dbtkey.size = key.dsize;
+ status = (db->del)(db, &dbtkey, 0);
+ if (status)
+ return (-1);
+ else
+ return (0);
+}
+
+/*
+ * Returns:
+ * 0 on success
+ * <0 failure
+ * 1 if DBM_INSERT and entry exists
+ */
+extern int
+dbm_store(db, key, data, flags)
+ DBM *db;
+ datum key, data;
+ int flags;
+{
+ DBT dbtkey, dbtdata;
+
+ dbtkey.data = key.dptr;
+ dbtkey.size = key.dsize;
+ dbtdata.data = data.dptr;
+ dbtdata.size = data.dsize;
+ return ((db->put)(db, &dbtkey, &dbtdata,
+ (flags == DBM_INSERT) ? R_NOOVERWRITE : 0));
+}
+
+extern int
+dbm_error(db)
+ DBM *db;
+{
+ HTAB *hp;
+
+ hp = (HTAB *)db->internal;
+ return (hp->error);
+}
+
+extern int
+dbm_clearerr(db)
+ DBM *db;
+{
+ HTAB *hp;
+
+ hp = (HTAB *)db->internal;
+ hp->error = 0;
+ return (0);
+}
+
+extern int
+dbm_dirfno(db)
+ DBM *db;
+{
+ return(((HTAB *)db->internal)->fp);
+}
diff --git a/lib/libc/db/hash/page.h b/lib/libc/db/hash/page.h
new file mode 100644
index 0000000..6959fe8
--- /dev/null
+++ b/lib/libc/db/hash/page.h
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)page.h 8.2 (Berkeley) 5/31/94
+ * $FreeBSD$
+ */
+
+/*
+ * Definitions for hashing page file format.
+ */
+
+/*
+ * routines dealing with a data page
+ *
+ * page format:
+ * +------------------------------+
+ * p | n | keyoff | datoff | keyoff |
+ * +------------+--------+--------+
+ * | datoff | free | ptr | --> |
+ * +--------+---------------------+
+ * | F R E E A R E A |
+ * +--------------+---------------+
+ * | <---- - - - | data |
+ * +--------+-----+----+----------+
+ * | key | data | key |
+ * +--------+----------+----------+
+ *
+ * Pointer to the free space is always: p[p[0] + 2]
+ * Amount of free space on the page is: p[p[0] + 1]
+ */
+
+/*
+ * How many bytes required for this pair?
+ * 2 shorts in the table at the top of the page + room for the
+ * key and room for the data
+ *
+ * We prohibit entering a pair on a page unless there is also room to append
+ * an overflow page. The reason for this it that you can get in a situation
+ * where a single key/data pair fits on a page, but you can't append an
+ * overflow page and later you'd have to split the key/data and handle like
+ * a big pair.
+ * You might as well do this up front.
+ */
+
+#define PAIRSIZE(K,D) (2*sizeof(u_int16_t) + (K)->size + (D)->size)
+#define BIGOVERHEAD (4*sizeof(u_int16_t))
+#define KEYSIZE(K) (4*sizeof(u_int16_t) + (K)->size);
+#define OVFLSIZE (2*sizeof(u_int16_t))
+#define FREESPACE(P) ((P)[(P)[0]+1])
+#define OFFSET(P) ((P)[(P)[0]+2])
+#define PAIRFITS(P,K,D) \
+ (((P)[2] >= REAL_KEY) && \
+ (PAIRSIZE((K),(D)) + OVFLSIZE) <= FREESPACE((P)))
+#define PAGE_META(N) (((N)+3) * sizeof(u_int16_t))
+
+typedef struct {
+ BUFHEAD *newp;
+ BUFHEAD *oldp;
+ BUFHEAD *nextp;
+ u_int16_t next_addr;
+} SPLIT_RETURN;
diff --git a/lib/libc/db/man/Makefile.inc b/lib/libc/db/man/Makefile.inc
new file mode 100644
index 0000000..349b029
--- /dev/null
+++ b/lib/libc/db/man/Makefile.inc
@@ -0,0 +1,18 @@
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/db/man
+
+MAN+= btree.3 dbm.3 dbopen.3 hash.3 mpool.3 recno.3
+
+MLINKS+= dbm.3 dbm_clearerr.3
+MLINKS+= dbm.3 dbm_close.3
+MLINKS+= dbm.3 dbm_delete.3
+MLINKS+= dbm.3 dbm_dirnfo.3
+MLINKS+= dbm.3 dbm_error.3
+MLINKS+= dbm.3 dbm_fetch.3
+MLINKS+= dbm.3 dbm_firstkey.3
+MLINKS+= dbm.3 dbm_nextkey.3
+MLINKS+= dbm.3 dbm_open.3
+MLINKS+= dbm.3 dbm_store.3
+MLINKS+= dbopen.3 db.3
diff --git a/lib/libc/db/man/btree.3 b/lib/libc/db/man/btree.3
new file mode 100644
index 0000000..42fc254
--- /dev/null
+++ b/lib/libc/db/man/btree.3
@@ -0,0 +1,271 @@
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)btree.3 8.4 (Berkeley) 8/18/94
+.\" $FreeBSD$
+.\"
+.Dd August 18, 1994
+.Dt BTREE 3
+.Os
+.Sh NAME
+.Nm btree
+.Nd "btree database access method"
+.Sh SYNOPSIS
+.In sys/types.h
+.In db.h
+.Sh DESCRIPTION
+The routine
+.Fn dbopen
+is the library interface to database files.
+One of the supported file formats is
+.Nm
+files.
+The general description of the database access methods is in
+.Xr dbopen 3 ,
+this manual page describes only the
+.Nm
+specific information.
+.Pp
+The
+.Nm
+data structure is a sorted, balanced tree structure storing
+associated key/data pairs.
+.Pp
+The
+.Nm
+access method specific data structure provided to
+.Fn dbopen
+is defined in the
+.In db.h
+include file as follows:
+.Bd -literal
+typedef struct {
+ u_long flags;
+ u_int cachesize;
+ int maxkeypage;
+ int minkeypage;
+ u_int psize;
+ int (*compare)(const DBT *key1, const DBT *key2);
+ size_t (*prefix)(const DBT *key1, const DBT *key2);
+ int lorder;
+} BTREEINFO;
+.Ed
+.Pp
+The elements of this structure are as follows:
+.Bl -tag -width indent
+.It Va flags
+The flag value is specified by
+.Em or Ns 'ing
+any of the following values:
+.Bl -tag -width indent
+.It Dv R_DUP
+Permit duplicate keys in the tree, i.e., permit insertion if the key to be
+inserted already exists in the tree.
+The default behavior, as described in
+.Xr dbopen 3 ,
+is to overwrite a matching key when inserting a new key or to fail if
+the
+.Dv R_NOOVERWRITE
+flag is specified.
+The
+.Dv R_DUP
+flag is overridden by the
+.Dv R_NOOVERWRITE
+flag, and if the
+.Dv R_NOOVERWRITE
+flag is specified, attempts to insert duplicate keys into
+the tree will fail.
+.Pp
+If the database contains duplicate keys, the order of retrieval of
+key/data pairs is undefined if the
+.Va get
+routine is used, however,
+.Va seq
+routine calls with the
+.Dv R_CURSOR
+flag set will always return the logical
+.Dq first
+of any group of duplicate keys.
+.El
+.It Va cachesize
+A suggested maximum size (in bytes) of the memory cache.
+This value is
+.Em only
+advisory, and the access method will allocate more memory rather than fail.
+Since every search examines the root page of the tree, caching the most
+recently used pages substantially improves access time.
+In addition, physical writes are delayed as long as possible, so a moderate
+cache can reduce the number of I/O operations significantly.
+Obviously, using a cache increases (but only increases) the likelihood of
+corruption or lost data if the system crashes while a tree is being modified.
+If
+.Va cachesize
+is 0 (no size is specified) a default cache is used.
+.It Va maxkeypage
+The maximum number of keys which will be stored on any single page.
+Not currently implemented.
+.\" The maximum number of keys which will be stored on any single page.
+.\" Because of the way the
+.\" .Nm
+.\" data structure works,
+.\" .Va maxkeypage
+.\" must always be greater than or equal to 2.
+.\" If
+.\" .Va maxkeypage
+.\" is 0 (no maximum number of keys is specified) the page fill factor is
+.\" made as large as possible (which is almost invariably what is wanted).
+.It Va minkeypage
+The minimum number of keys which will be stored on any single page.
+This value is used to determine which keys will be stored on overflow
+pages, i.e., if a key or data item is longer than the pagesize divided
+by the minkeypage value, it will be stored on overflow pages instead
+of in the page itself.
+If
+.Va minkeypage
+is 0 (no minimum number of keys is specified) a value of 2 is used.
+.It Va psize
+Page size is the size (in bytes) of the pages used for nodes in the tree.
+The minimum page size is 512 bytes and the maximum page size is 64K.
+If
+.Va psize
+is 0 (no page size is specified) a page size is chosen based on the
+underlying file system I/O block size.
+.It Va compare
+Compare is the key comparison function.
+It must return an integer less than, equal to, or greater than zero if the
+first key argument is considered to be respectively less than, equal to,
+or greater than the second key argument.
+The same comparison function must be used on a given tree every time it
+is opened.
+If
+.Va compare
+is
+.Dv NULL
+(no comparison function is specified), the keys are compared
+lexically, with shorter keys considered less than longer keys.
+.It Va prefix
+The
+.Va prefix
+element
+is the prefix comparison function.
+If specified, this routine must return the number of bytes of the second key
+argument which are necessary to determine that it is greater than the first
+key argument.
+If the keys are equal, the key length should be returned.
+Note, the usefulness of this routine is very data dependent, but, in some
+data sets can produce significantly reduced tree sizes and search times.
+If
+.Va prefix
+is
+.Dv NULL
+(no prefix function is specified),
+.Em and
+no comparison function is specified, a default lexical comparison routine
+is used.
+If
+.Va prefix
+is
+.Dv NULL
+and a comparison routine is specified, no prefix comparison is
+done.
+.It Va lorder
+The byte order for integers in the stored database metadata.
+The number should represent the order as an integer; for example,
+big endian order would be the number 4,321.
+If
+.Va lorder
+is 0 (no order is specified) the current host order is used.
+.El
+.Pp
+If the file already exists (and the
+.Dv O_TRUNC
+flag is not specified), the
+values specified for the
+.Va flags , lorder
+and
+.Va psize
+arguments
+are ignored
+in favor of the values used when the tree was created.
+.Pp
+Forward sequential scans of a tree are from the least key to the greatest.
+.Pp
+Space freed up by deleting key/data pairs from the tree is never reclaimed,
+although it is normally made available for reuse.
+This means that the
+.Nm
+storage structure is grow-only.
+The only solutions are to avoid excessive deletions, or to create a fresh
+tree periodically from a scan of an existing one.
+.Pp
+Searches, insertions, and deletions in a
+.Nm
+will all complete in
+O lg base N where base is the average fill factor.
+Often, inserting ordered data into
+.Nm Ns s
+results in a low fill factor.
+This implementation has been modified to make ordered insertion the best
+case, resulting in a much better than normal page fill factor.
+.Sh ERRORS
+The
+.Nm
+access method routines may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr dbopen 3 .
+.Sh SEE ALSO
+.Xr dbopen 3 ,
+.Xr hash 3 ,
+.Xr mpool 3 ,
+.Xr recno 3
+.Rs
+.%T "The Ubiquitous B-tree"
+.%A Douglas Comer
+.%J "ACM Comput. Surv. 11"
+.%N 2
+.%D June 1979
+.%P 121-138
+.Re
+.Rs
+.%A Bayer
+.%A Unterauer
+.%T "Prefix B-trees"
+.%J "ACM Transactions on Database Systems"
+.%N 1
+.%V Vol. 2
+.%D March 1977
+.%P 11-26
+.Re
+.Rs
+.%B "The Art of Computer Programming Vol. 3: Sorting and Searching"
+.%A D. E. Knuth
+.%D 1968
+.%P 471-480
+.Re
+.Sh BUGS
+Only big and little endian byte order is supported.
diff --git a/lib/libc/db/man/dbm.3 b/lib/libc/db/man/dbm.3
new file mode 100644
index 0000000..fabce8a
--- /dev/null
+++ b/lib/libc/db/man/dbm.3
@@ -0,0 +1,228 @@
+.\" Copyright (c) 1999 Tim Singletary
+.\" No copyright is claimed.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 16, 2006
+.Dt DBM 3
+.Os
+.Sh NAME
+.Nm dbm_clearerr ,
+.Nm dbm_close ,
+.Nm dbm_delete ,
+.Nm dbm_dirfno ,
+.Nm dbm_error ,
+.Nm dbm_fetch ,
+.Nm dbm_firstkey ,
+.Nm dbm_nextkey ,
+.Nm dbm_open ,
+.Nm dbm_store
+.Nd database access functions
+.Sh SYNOPSIS
+.In fcntl.h
+.In ndbm.h
+.Ft DBM *
+.Fn dbm_open "const char *base" "int flags" "int mode"
+.Ft void
+.Fn dbm_close "DBM *db"
+.Ft int
+.Fn dbm_store "DBM *db" "datum key" "datum data" "int flags"
+.Ft datum
+.Fn dbm_fetch "DBM *db" "datum key"
+.Ft int
+.Fn dbm_delete "DBM *db" "datum key"
+.Ft datum
+.Fn dbm_firstkey "DBM *db"
+.Ft datum
+.Fn dbm_nextkey "DBM *db"
+.Ft int
+.Fn dbm_error "DBM *db"
+.Ft int
+.Fn dbm_clearerr "DBM *db"
+.Ft int
+.Fn dbm_dirfno "DBM *db"
+.Sh DESCRIPTION
+Database access functions.
+These functions are implemented using
+.Xr dbopen 3
+with a
+.Xr hash 3
+database.
+.Pp
+.Vt datum
+is declared in
+.In ndbm.h :
+.Bd -literal
+typedef struct {
+ char *dptr;
+ int dsize;
+} datum;
+.Ed
+.Pp
+The
+.Fn dbm_open base flags mode
+function
+opens or creates a database.
+The
+.Fa base
+argument
+is the basename of the file containing
+the database; the actual database has a
+.Pa .db
+suffix.
+I.e., if
+.Fa base
+is
+.Qq Li /home/me/mystuff
+then the actual database is in the file
+.Pa /home/me/mystuff.db .
+The
+.Fa flags
+and
+.Fa mode
+arguments
+are passed to
+.Xr open 2 .
+.Pq Dv O_RDWR | O_CREAT
+is a typical value for
+.Fa flags ;
+.Li 0660
+is a typical value for
+.Fa mode .
+.Dv O_WRONLY
+is not allowed in
+.Fa flags .
+The pointer returned by
+.Fn dbm_open
+identifies the database and is the
+.Fa db
+argument to the other functions.
+The
+.Fn dbm_open
+function
+returns
+.Dv NULL
+and sets
+.Va errno
+if there were any errors.
+.Pp
+The
+.Fn dbm_close db
+function
+closes the database.
+.Pp
+The
+.Fn dbm_store db key data flags
+function
+inserts or replaces an entry in the database.
+The
+.Fa flags
+argument
+is either
+.Dv DBM_INSERT
+or
+.Dv DBM_REPLACE .
+If
+.Fa flags
+is
+.Dv DBM_INSERT
+and the database already contains an entry for
+.Fa key ,
+that entry is not replaced.
+Otherwise the entry is replaced or inserted.
+The
+.Fn dbm_store
+function
+normally returns zero but returns 1 if the entry could not be
+inserted (because
+.Fa flags
+is
+.Dv DBM_INSERT ,
+and an entry with
+.Fa key
+already exists) or returns -1 and sets
+.Va errno
+if there were any errors.
+.Pp
+The
+.Fn dbm_fetch db key
+function
+returns
+.Dv NULL
+or the
+.Fa data
+corresponding to
+.Fa key .
+.Pp
+The
+.Fn dbm_delete db key
+function
+deletes the entry for
+.Fa key .
+The
+.Fn dbm_delete
+function
+normally returns zero but returns 1 if there was no entry with
+.Fa key
+in the database or returns -1 and sets
+.Va errno
+if there were any errors.
+.Pp
+The
+.Fn dbm_firstkey db
+function
+returns the first key in the database.
+The
+.Fn dbm_nextkey db
+function
+returns subsequent keys.
+The
+.Fn db_firstkey
+function
+must be called before
+.Fn dbm_nextkey .
+The order in which keys are returned is unspecified and may appear
+random.
+The
+.Fn dbm_nextkey
+function
+returns
+.Dv NULL
+after all keys have been returned.
+.Pp
+The
+.Fn dbm_error db
+function
+returns the
+.Va errno
+value of the most recent error.
+The
+.Fn dbm_clearerr db
+function
+resets this value to 0 and returns 0.
+.Pp
+The
+.Fn dbm_dirfno db
+function
+returns the file descriptor to the database.
+.Sh SEE ALSO
+.Xr open 2 ,
+.Xr dbopen 3 ,
+.Xr hash 3
+.Sh STANDARDS
+These functions (except
+.Fn dbm_dirfno )
+are included in the
+.St -susv2 .
diff --git a/lib/libc/db/man/dbopen.3 b/lib/libc/db/man/dbopen.3
new file mode 100644
index 0000000..13481dd
--- /dev/null
+++ b/lib/libc/db/man/dbopen.3
@@ -0,0 +1,546 @@
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)dbopen.3 8.5 (Berkeley) 1/2/94
+.\" $FreeBSD$
+.\"
+.Dd September 10, 2010
+.Dt DBOPEN 3
+.Os
+.Sh NAME
+.Nm dbopen
+.Nd "database access methods"
+.Sh SYNOPSIS
+.In sys/types.h
+.In db.h
+.In fcntl.h
+.In limits.h
+.Ft DB *
+.Fn dbopen "const char *file" "int flags" "int mode" "DBTYPE type" "const void *openinfo"
+.Sh DESCRIPTION
+The
+.Fn dbopen
+function
+is the library interface to database files.
+The supported file formats are btree, hashed and UNIX file oriented.
+The btree format is a representation of a sorted, balanced tree structure.
+The hashed format is an extensible, dynamic hashing scheme.
+The flat-file format is a byte stream file with fixed or variable length
+records.
+The formats and file format specific information are described in detail
+in their respective manual pages
+.Xr btree 3 ,
+.Xr hash 3
+and
+.Xr recno 3 .
+.Pp
+The
+.Fn dbopen
+function
+opens
+.Fa file
+for reading and/or writing.
+Files never intended to be preserved on disk may be created by setting
+the
+.Fa file
+argument to
+.Dv NULL .
+.Pp
+The
+.Fa flags
+and
+.Fa mode
+arguments
+are as specified to the
+.Xr open 2
+routine, however, only the
+.Dv O_CREAT , O_EXCL , O_EXLOCK , O_NOFOLLOW , O_NONBLOCK ,
+.Dv O_RDONLY , O_RDWR , O_SHLOCK , O_SYNC
+and
+.Dv O_TRUNC
+flags are meaningful.
+(Note, opening a database file
+.Dv O_WRONLY
+is not possible.)
+.\"Three additional options may be specified by
+.\".Em or Ns 'ing
+.\"them into the
+.\".Fa flags
+.\"argument.
+.\".Bl -tag -width indent
+.\".It Dv DB_LOCK
+.\"Do the necessary locking in the database to support concurrent access.
+.\"If concurrent access is not needed or the database is read-only this
+.\"flag should not be set, as it tends to have an associated performance
+.\"penalty.
+.\".It Dv DB_SHMEM
+.\"Place the underlying memory pool used by the database in shared
+.\"memory.
+.\"Necessary for concurrent access.
+.\".It Dv DB_TXN
+.\"Support transactions in the database.
+.\"The
+.\".Dv DB_LOCK
+.\"and
+.\".Dv DB_SHMEM
+.\"flags must be set as well.
+.\".El
+.Pp
+The
+.Fa type
+argument is of type
+.Ft DBTYPE
+(as defined in the
+.In db.h
+include file) and
+may be set to
+.Dv DB_BTREE , DB_HASH
+or
+.Dv DB_RECNO .
+.Pp
+The
+.Fa openinfo
+argument is a pointer to an access method specific structure described
+in the access method's manual page.
+If
+.Fa openinfo
+is
+.Dv NULL ,
+each access method will use defaults appropriate for the system
+and the access method.
+.Pp
+The
+.Fn dbopen
+function
+returns a pointer to a
+.Ft DB
+structure on success and
+.Dv NULL
+on error.
+The
+.Ft DB
+structure is defined in the
+.In db.h
+include file, and contains at
+least the following fields:
+.Bd -literal
+typedef struct {
+ DBTYPE type;
+ int (*close)(DB *db);
+ int (*del)(const DB *db, const DBT *key, u_int flags);
+ int (*fd)(const DB *db);
+ int (*get)(const DB *db, const DBT *key, DBT *data, u_int flags);
+ int (*put)(const DB *db, DBT *key, const DBT *data,
+ u_int flags);
+ int (*sync)(const DB *db, u_int flags);
+ int (*seq)(const DB *db, DBT *key, DBT *data, u_int flags);
+} DB;
+.Ed
+.Pp
+These elements describe a database type and a set of functions performing
+various actions.
+These functions take a pointer to a structure as returned by
+.Fn dbopen ,
+and sometimes one or more pointers to key/data structures and a flag value.
+.Bl -tag -width indent
+.It Va type
+The type of the underlying access method (and file format).
+.It Va close
+A pointer to a routine to flush any cached information to disk, free any
+allocated resources, and close the underlying file(s).
+Since key/data pairs may be cached in memory, failing to sync the file
+with a
+.Va close
+or
+.Va sync
+function may result in inconsistent or lost information.
+.Va close
+routines return -1 on error (setting
+.Va errno )
+and 0 on success.
+.It Va del
+A pointer to a routine to remove key/data pairs from the database.
+.Pp
+The
+.Fa flags
+argument
+may be set to the following value:
+.Bl -tag -width indent
+.It Dv R_CURSOR
+Delete the record referenced by the cursor.
+The cursor must have previously been initialized.
+.El
+.Pp
+.Va delete
+routines return -1 on error (setting
+.Va errno ) ,
+0 on success, and 1 if the specified
+.Fa key
+was not in the file.
+.It Va fd
+A pointer to a routine which returns a file descriptor representative
+of the underlying database.
+A file descriptor referencing the same file will be returned to all
+processes which call
+.Fn dbopen
+with the same
+.Fa file
+name.
+This file descriptor may be safely used as an argument to the
+.Xr fcntl 2
+and
+.Xr flock 2
+locking functions.
+The file descriptor is not necessarily associated with any of the
+underlying files used by the access method.
+No file descriptor is available for in memory databases.
+.Va \&Fd
+routines return -1 on error (setting
+.Va errno ) ,
+and the file descriptor on success.
+.It Va get
+A pointer to a routine which is the interface for keyed retrieval from
+the database.
+The address and length of the data associated with the specified
+.Fa key
+are returned in the structure referenced by
+.Fa data .
+.Va get
+routines return -1 on error (setting
+.Va errno ) ,
+0 on success, and 1 if the
+.Fa key
+was not in the file.
+.It Va put
+A pointer to a routine to store key/data pairs in the database.
+.Pp
+The
+.Fa flags
+argument
+may be set to one of the following values:
+.Bl -tag -width indent
+.It Dv R_CURSOR
+Replace the key/data pair referenced by the cursor.
+The cursor must have previously been initialized.
+.It Dv R_IAFTER
+Append the data immediately after the data referenced by
+.Fa key ,
+creating a new key/data pair.
+The record number of the appended key/data pair is returned in the
+.Fa key
+structure.
+(Applicable only to the
+.Dv DB_RECNO
+access method.)
+.It Dv R_IBEFORE
+Insert the data immediately before the data referenced by
+.Fa key ,
+creating a new key/data pair.
+The record number of the inserted key/data pair is returned in the
+.Fa key
+structure.
+(Applicable only to the
+.Dv DB_RECNO
+access method.)
+.It Dv R_NOOVERWRITE
+Enter the new key/data pair only if the key does not previously exist.
+.It Dv R_SETCURSOR
+Store the key/data pair, setting or initializing the position of the
+cursor to reference it.
+(Applicable only to the
+.Dv DB_BTREE
+and
+.Dv DB_RECNO
+access methods.)
+.El
+.Pp
+.Dv R_SETCURSOR
+is available only for the
+.Dv DB_BTREE
+and
+.Dv DB_RECNO
+access
+methods because it implies that the keys have an inherent order
+which does not change.
+.Pp
+.Dv R_IAFTER
+and
+.Dv R_IBEFORE
+are available only for the
+.Dv DB_RECNO
+access method because they each imply that the access method is able to
+create new keys.
+This is only true if the keys are ordered and independent, record numbers
+for example.
+.Pp
+The default behavior of the
+.Va put
+routines is to enter the new key/data pair, replacing any previously
+existing key.
+.Pp
+.Va put
+routines return -1 on error (setting
+.Va errno ) ,
+0 on success, and 1 if the
+.Dv R_NOOVERWRITE
+flag
+was set and the key already exists in the file.
+.It Va seq
+A pointer to a routine which is the interface for sequential
+retrieval from the database.
+The address and length of the key are returned in the structure
+referenced by
+.Fa key ,
+and the address and length of the data are returned in the
+structure referenced
+by
+.Fa data .
+.Pp
+Sequential key/data pair retrieval may begin at any time, and the
+position of the
+.Dq cursor
+is not affected by calls to the
+.Va del ,
+.Va get ,
+.Va put ,
+or
+.Va sync
+routines.
+Modifications to the database during a sequential scan will be reflected
+in the scan, i.e., records inserted behind the cursor will not be returned
+while records inserted in front of the cursor will be returned.
+.Pp
+The
+.Fa flags
+argument
+.Em must
+be set to one of the following values:
+.Bl -tag -width indent
+.It Dv R_CURSOR
+The data associated with the specified key is returned.
+This differs from the
+.Va get
+routines in that it sets or initializes the cursor to the location of
+the key as well.
+(Note, for the
+.Dv DB_BTREE
+access method, the returned key is not necessarily an
+exact match for the specified key.
+The returned key is the smallest key greater than or equal to the specified
+key, permitting partial key matches and range searches.)
+.It Dv R_FIRST
+The first key/data pair of the database is returned, and the cursor
+is set or initialized to reference it.
+.It Dv R_LAST
+The last key/data pair of the database is returned, and the cursor
+is set or initialized to reference it.
+(Applicable only to the
+.Dv DB_BTREE
+and
+.Dv DB_RECNO
+access methods.)
+.It Dv R_NEXT
+Retrieve the key/data pair immediately after the cursor.
+If the cursor is not yet set, this is the same as the
+.Dv R_FIRST
+flag.
+.It Dv R_PREV
+Retrieve the key/data pair immediately before the cursor.
+If the cursor is not yet set, this is the same as the
+.Dv R_LAST
+flag.
+(Applicable only to the
+.Dv DB_BTREE
+and
+.Dv DB_RECNO
+access methods.)
+.El
+.Pp
+.Dv R_LAST
+and
+.Dv R_PREV
+are available only for the
+.Dv DB_BTREE
+and
+.Dv DB_RECNO
+access methods because they each imply that the keys have an inherent
+order which does not change.
+.Pp
+.Va seq
+routines return -1 on error (setting
+.Va errno ) ,
+0 on success and 1 if there are no key/data pairs less than or greater
+than the specified or current key.
+If the
+.Dv DB_RECNO
+access method is being used, and if the database file
+is a character special file and no complete key/data pairs are currently
+available, the
+.Va seq
+routines return 2.
+.It Va sync
+A pointer to a routine to flush any cached information to disk.
+If the database is in memory only, the
+.Va sync
+routine has no effect and will always succeed.
+.Pp
+The
+.Fa flags
+argument may be set to the following value:
+.Bl -tag -width indent
+.It Dv R_RECNOSYNC
+If the
+.Dv DB_RECNO
+access method is being used, this flag causes
+the
+.Va sync
+routine to apply to the btree file which underlies the
+recno file, not the recno file itself.
+(See the
+.Va bfname
+field of the
+.Xr recno 3
+manual page for more information.)
+.El
+.Pp
+.Va sync
+routines return -1 on error (setting
+.Va errno )
+and 0 on success.
+.El
+.Sh "KEY/DATA PAIRS"
+Access to all file types is based on key/data pairs.
+Both keys and data are represented by the following data structure:
+.Bd -literal
+typedef struct {
+ void *data;
+ size_t size;
+} DBT;
+.Ed
+.Pp
+The elements of the
+.Ft DBT
+structure are defined as follows:
+.Bl -tag -width "data"
+.It Va data
+A pointer to a byte string.
+.It Va size
+The length of the byte string.
+.El
+.Pp
+Key and data byte strings may reference strings of essentially unlimited
+length although any two of them must fit into available memory at the same
+time.
+It should be noted that the access methods provide no guarantees about
+byte string alignment.
+.Sh ERRORS
+The
+.Fn dbopen
+routine may fail and set
+.Va errno
+for any of the errors specified for the library routines
+.Xr open 2
+and
+.Xr malloc 3
+or the following:
+.Bl -tag -width Er
+.It Bq Er EFTYPE
+A file is incorrectly formatted.
+.It Bq Er EINVAL
+An argument has been specified (hash function, pad byte etc.) that is
+incompatible with the current file specification or which is not
+meaningful for the function (for example, use of the cursor without
+prior initialization) or there is a mismatch between the version
+number of file and the software.
+.El
+.Pp
+The
+.Va close
+routines may fail and set
+.Va errno
+for any of the errors specified for the library routines
+.Xr close 2 ,
+.Xr read 2 ,
+.Xr write 2 ,
+.Xr free 3 ,
+or
+.Xr fsync 2 .
+.Pp
+The
+.Va del ,
+.Va get ,
+.Va put
+and
+.Va seq
+routines may fail and set
+.Va errno
+for any of the errors specified for the library routines
+.Xr read 2 ,
+.Xr write 2 ,
+.Xr free 3
+or
+.Xr malloc 3 .
+.Pp
+The
+.Va fd
+routines will fail and set
+.Va errno
+to
+.Er ENOENT
+for in memory databases.
+.Pp
+The
+.Va sync
+routines may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr fsync 2 .
+.Sh SEE ALSO
+.Xr btree 3 ,
+.Xr hash 3 ,
+.Xr mpool 3 ,
+.Xr recno 3
+.Rs
+.%T "LIBTP: Portable, Modular Transactions for UNIX"
+.%A Margo Seltzer
+.%A Michael Olson
+.%R "USENIX proceedings"
+.%D Winter 1992
+.Re
+.Sh BUGS
+The typedef
+.Ft DBT
+is a mnemonic for
+.Dq "data base thang" ,
+and was used
+because noone could think of a reasonable name that was not already used.
+.Pp
+The file descriptor interface is a kluge and will be deleted in a
+future version of the interface.
+.Pp
+None of the access methods provide any form of concurrent access,
+locking, or transactions.
diff --git a/lib/libc/db/man/hash.3 b/lib/libc/db/man/hash.3
new file mode 100644
index 0000000..a2a8bca
--- /dev/null
+++ b/lib/libc/db/man/hash.3
@@ -0,0 +1,196 @@
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)hash.3 8.6 (Berkeley) 8/18/94
+.\" $FreeBSD$
+.\"
+.Dd August 18, 1994
+.Dt HASH 3
+.Os
+.Sh NAME
+.Nm hash
+.Nd "hash database access method"
+.Sh SYNOPSIS
+.In sys/types.h
+.In db.h
+.Sh DESCRIPTION
+The routine
+.Fn dbopen
+is the library interface to database files.
+One of the supported file formats is
+.Nm
+files.
+The general description of the database access methods is in
+.Xr dbopen 3 ,
+this manual page describes only the
+.Nm
+specific information.
+.Pp
+The
+.Nm
+data structure is an extensible, dynamic hashing scheme.
+.Pp
+The access method specific data structure provided to
+.Fn dbopen
+is defined in the
+.In db.h
+include file as follows:
+.Bd -literal
+typedef struct {
+ u_int bsize;
+ u_int ffactor;
+ u_int nelem;
+ u_int cachesize;
+ uint32_t (*hash)(const void *, size_t);
+ int lorder;
+} HASHINFO;
+.Ed
+.Pp
+The elements of this structure are as follows:
+.Bl -tag -width indent
+.It Va bsize
+The
+.Va bsize
+element
+defines the
+.Nm
+table bucket size, and is, by default, 4096 bytes.
+It may be preferable to increase the page size for disk-resident tables
+and tables with large data items.
+.It Va ffactor
+The
+.Va ffactor
+element
+indicates a desired density within the
+.Nm
+table.
+It is an approximation of the number of keys allowed to accumulate in any
+one bucket, determining when the
+.Nm
+table grows or shrinks.
+The default value is 8.
+.It Va nelem
+The
+.Va nelem
+element
+is an estimate of the final size of the
+.Nm
+table.
+If not set or set too low,
+.Nm
+tables will expand gracefully as keys
+are entered, although a slight performance degradation may be noticed.
+The default value is 1.
+.It Va cachesize
+A suggested maximum size, in bytes, of the memory cache.
+This value is
+.Em only
+advisory, and the access method will allocate more memory rather
+than fail.
+.It Va hash
+The
+.Va hash
+element
+is a user defined
+.Nm
+function.
+Since no
+.Nm
+function performs equally well on all possible data, the
+user may find that the built-in
+.Nm
+function does poorly on a particular
+data set.
+User specified
+.Nm
+functions must take two arguments (a pointer to a byte
+string and a length) and return a 32-bit quantity to be used as the
+.Nm
+value.
+.It Va lorder
+The byte order for integers in the stored database metadata.
+The number should represent the order as an integer; for example,
+big endian order would be the number 4,321.
+If
+.Va lorder
+is 0 (no order is specified) the current host order is used.
+If the file already exists, the specified value is ignored and the
+value specified when the tree was created is used.
+.El
+.Pp
+If the file already exists (and the
+.Dv O_TRUNC
+flag is not specified), the
+values specified for the
+.Va bsize , ffactor , lorder
+and
+.Va nelem
+arguments
+are
+ignored and the values specified when the tree was created are used.
+.Pp
+If a
+.Nm
+function is specified,
+.Fn hash_open
+will attempt to determine if the
+.Nm
+function specified is the same as
+the one with which the database was created, and will fail if it is not.
+.Pp
+Backward compatible interfaces to the older
+.Em dbm
+and
+.Em ndbm
+routines are provided, however these interfaces are not compatible with
+previous file formats.
+.Sh ERRORS
+The
+.Nm
+access method routines may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr dbopen 3 .
+.Sh SEE ALSO
+.Xr btree 3 ,
+.Xr dbopen 3 ,
+.Xr mpool 3 ,
+.Xr recno 3
+.Rs
+.%T "Dynamic Hash Tables"
+.%A Per-Ake Larson
+.%R "Communications of the ACM"
+.%D April 1988
+.Re
+.Rs
+.%T "A New Hash Package for UNIX"
+.%A Margo Seltzer
+.%R "USENIX Proceedings"
+.%D Winter 1991
+.Re
+.Sh BUGS
+Only big and little endian byte order is supported.
diff --git a/lib/libc/db/man/mpool.3 b/lib/libc/db/man/mpool.3
new file mode 100644
index 0000000..5af7d27
--- /dev/null
+++ b/lib/libc/db/man/mpool.3
@@ -0,0 +1,254 @@
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mpool.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 17, 2011
+.Dt MPOOL 3
+.Os
+.Sh NAME
+.Nm mpool
+.Nd "shared memory buffer pool"
+.Sh SYNOPSIS
+.In db.h
+.In mpool.h
+.Ft MPOOL *
+.Fn mpool_open "void *key" "int fd" "pgno_t pagesize" "pgno_t maxcache"
+.Ft void
+.Fo mpool_filter
+.Fa "MPOOL *mp"
+.Fa "void (*pgin)(void *, pgno_t, void *)"
+.Fa "void (*pgout)(void *, pgno_t, void *)"
+.Fa "void *pgcookie"
+.Fc
+.Ft void *
+.Fn mpool_new "MPOOL *mp" "pgno_t *pgnoaddr" "u_int flags"
+.Ft int
+.Fn mpool_delete "MPOOL *mp" "void *page"
+.Ft void *
+.Fn mpool_get "MPOOL *mp" "pgno_t pgno" "u_int flags"
+.Ft int
+.Fn mpool_put "MPOOL *mp" "void *pgaddr" "u_int flags"
+.Ft int
+.Fn mpool_sync "MPOOL *mp"
+.Ft int
+.Fn mpool_close "MPOOL *mp"
+.Sh DESCRIPTION
+The
+.Nm mpool
+library interface is intended to provide page oriented buffer management
+of files.
+.Pp
+The
+.Fn mpool_open
+function initializes a memory pool.
+The
+.Fa key
+argument is currently ignored.
+The
+.Fa fd
+argument is a file descriptor for the underlying file, which must be seekable.
+.Pp
+The
+.Fa pagesize
+argument is the size, in bytes, of the pages into which the file is broken up.
+The
+.Fa maxcache
+argument is the maximum number of pages from the underlying file to cache
+at any one time.
+This value is not relative to the number of processes which share a file's
+buffers, but will be the largest value specified by any of the processes
+sharing the file.
+.Pp
+The
+.Fn mpool_filter
+function is intended to make transparent input and output processing of the
+pages possible.
+If the
+.Fa pgin
+function is specified, it is called each time a buffer is read into the memory
+pool from the backing file.
+If the
+.Fa pgout
+function is specified, it is called each time a buffer is written into the
+backing file.
+Both functions are called with the
+.Fa pgcookie
+pointer, the page number and a pointer to the page to being read or written.
+.Pp
+The function
+.Fn mpool_new
+takes an
+.Dv MPOOL
+pointer, an address, and a set of flags as arguments.
+If a new page can be allocated, a pointer to the page is returned and
+the page number is stored into the
+.Fa pgnoaddr
+address.
+Otherwise,
+.Dv NULL
+is returned and
+.Va errno
+is set.
+The flags value is formed by
+.Tn OR Ns 'ing
+the following values:
+.Bl -tag -width Ds
+.It Dv MPOOL_PAGE_REQUEST
+Allocate a new page with a specific page number.
+.It Dv MPOOL_PAGE_NEXT
+Allocate a new page with the next page number.
+.El
+.Pp
+The function
+.Fn mpool_delete
+deletes the specified page from a pool and frees the page.
+It takes an
+.Dv MPOOL
+pointer and a page as arguments.
+The page must have been generated by
+.Fn mpool_new .
+.Pp
+The
+.Fn mpool_get
+function takes a
+.Ft MPOOL
+pointer and a page number as arguments.
+If the page exists, a pointer to the page is returned.
+Otherwise,
+.Dv NULL
+is returned and
+.Va errno
+is set.
+The
+.Fa flags
+argument is specified by
+.Em or Ns 'ing
+any of the following values:
+.Bl -tag -width indent
+.It Dv MPOOL_IGNOREPIN
+The page returned is not pinned;
+page will otherwise be pinned on return.
+.El
+.Pp
+The
+.Fn mpool_put
+function unpins the page referenced by
+.Fa pgaddr .
+The
+.Fa pgaddr
+argument
+must be an address previously returned by
+.Fn mpool_get
+or
+.Fn mpool_new .
+The
+.Fa flags
+argument is specified by
+.Em or Ns 'ing
+any of the following values:
+.Bl -tag -width indent
+.It Dv MPOOL_DIRTY
+The page has been modified and needs to be written to the backing file.
+.El
+.Pp
+The
+.Fn mpool_put
+function
+returns 0 on success and -1 if an error occurs.
+.Pp
+The
+.Fn mpool_sync
+function writes all modified pages associated with the
+.Ft MPOOL
+pointer to the
+backing file.
+The
+.Fn mpool_sync
+function
+returns 0 on success and -1 if an error occurs.
+.Pp
+The
+.Fn mpool_close
+function free's up any allocated memory associated with the memory pool
+cookie.
+Modified pages are
+.Em not
+written to the backing file.
+The
+.Fn mpool_close
+function
+returns 0 on success and -1 if an error occurs.
+.Sh ERRORS
+The
+.Fn mpool_open
+function may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr malloc 3 .
+.Pp
+The
+.Fn mpool_get
+function may fail and set
+.Va errno
+for the following:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The requested record does not exist.
+.El
+.Pp
+The
+.Fn mpool_new
+and
+.Fn mpool_get
+functions may fail and set
+.Va errno
+for any of the errors specified for the library routines
+.Xr read 2 ,
+.Xr write 2 ,
+and
+.Xr malloc 3 .
+.Pp
+The
+.Fn mpool_sync
+function may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr write 2 .
+.Pp
+The
+.Fn mpool_close
+function may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr free 3 .
+.Sh SEE ALSO
+.Xr btree 3 ,
+.Xr dbopen 3 ,
+.Xr hash 3 ,
+.Xr recno 3
diff --git a/lib/libc/db/man/recno.3 b/lib/libc/db/man/recno.3
new file mode 100644
index 0000000..22d5567
--- /dev/null
+++ b/lib/libc/db/man/recno.3
@@ -0,0 +1,228 @@
+.\" Copyright (c) 1990, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)recno.3 8.5 (Berkeley) 8/18/94
+.\" $FreeBSD$
+.\"
+.Dd August 18, 1994
+.Dt RECNO 3
+.Os
+.Sh NAME
+.Nm recno
+.Nd "record number database access method"
+.Sh SYNOPSIS
+.In sys/types.h
+.In db.h
+.Sh DESCRIPTION
+The routine
+.Fn dbopen
+is the library interface to database files.
+One of the supported file formats is record number files.
+The general description of the database access methods is in
+.Xr dbopen 3 ,
+this manual page describes only the
+.Nm
+specific information.
+.Pp
+The record number data structure is either variable or fixed-length
+records stored in a flat-file format, accessed by the logical record
+number.
+The existence of record number five implies the existence of records
+one through four, and the deletion of record number one causes
+record number five to be renumbered to record number four, as well
+as the cursor, if positioned after record number one, to shift down
+one record.
+.Pp
+The
+.Nm
+access method specific data structure provided to
+.Fn dbopen
+is defined in the
+.In db.h
+include file as follows:
+.Bd -literal
+typedef struct {
+ u_long flags;
+ u_int cachesize;
+ u_int psize;
+ int lorder;
+ size_t reclen;
+ u_char bval;
+ char *bfname;
+} RECNOINFO;
+.Ed
+.Pp
+The elements of this structure are defined as follows:
+.Bl -tag -width indent
+.It Va flags
+The flag value is specified by
+.Em or Ns 'ing
+any of the following values:
+.Bl -tag -width indent
+.It Dv R_FIXEDLEN
+The records are fixed-length, not byte delimited.
+The structure element
+.Va reclen
+specifies the length of the record, and the structure element
+.Va bval
+is used as the pad character.
+Any records, inserted into the database, that are less than
+.Va reclen
+bytes long are automatically padded.
+.It Dv R_NOKEY
+In the interface specified by
+.Fn dbopen ,
+the sequential record retrieval fills in both the caller's key and
+data structures.
+If the
+.Dv R_NOKEY
+flag is specified, the
+.Em cursor
+routines are not required to fill in the key structure.
+This permits applications to retrieve records at the end of files without
+reading all of the intervening records.
+.It Dv R_SNAPSHOT
+This flag requires that a snapshot of the file be taken when
+.Fn dbopen
+is called, instead of permitting any unmodified records to be read from
+the original file.
+.El
+.It Va cachesize
+A suggested maximum size, in bytes, of the memory cache.
+This value is
+.Em only
+advisory, and the access method will allocate more memory rather than fail.
+If
+.Va cachesize
+is 0 (no size is specified) a default cache is used.
+.It Va psize
+The
+.Nm
+access method stores the in-memory copies of its records
+in a btree.
+This value is the size (in bytes) of the pages used for nodes in that tree.
+If
+.Va psize
+is 0 (no page size is specified) a page size is chosen based on the
+underlying file system I/O block size.
+See
+.Xr btree 3
+for more information.
+.It Va lorder
+The byte order for integers in the stored database metadata.
+The number should represent the order as an integer; for example,
+big endian order would be the number 4,321.
+If
+.Va lorder
+is 0 (no order is specified) the current host order is used.
+.It Va reclen
+The length of a fixed-length record.
+.It Va bval
+The delimiting byte to be used to mark the end of a record for
+variable-length records, and the pad character for fixed-length
+records.
+If no value is specified, newlines
+.Pq Dq \en
+are used to mark the end
+of variable-length records and fixed-length records are padded with
+spaces.
+.It Va bfname
+The
+.Nm
+access method stores the in-memory copies of its records
+in a btree.
+If
+.Va bfname
+is
+.No non\- Ns Dv NULL ,
+it specifies the name of the btree file,
+as if specified as the file name for a
+.Fn dbopen
+of a btree file.
+.El
+.Pp
+The data part of the key/data pair used by the
+.Nm
+access method
+is the same as other access methods.
+The key is different.
+The
+.Va data
+field of the key should be a pointer to a memory location of type
+.Ft recno_t ,
+as defined in the
+.In db.h
+include file.
+This type is normally the largest unsigned integral type available to
+the implementation.
+The
+.Va size
+field of the key should be the size of that type.
+.Pp
+Because there can be no meta-data associated with the underlying
+.Nm
+access method files, any changes made to the default values
+(e.g.\& fixed record length or byte separator value) must be explicitly
+specified each time the file is opened.
+.Pp
+In the interface specified by
+.Fn dbopen ,
+using the
+.Va put
+interface to create a new record will cause the creation of multiple,
+empty records if the record number is more than one greater than the
+largest record currently in the database.
+.Sh ERRORS
+The
+.Nm
+access method routines may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr dbopen 3
+or the following:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+An attempt was made to add a record to a fixed-length database that
+was too large to fit.
+.El
+.Sh SEE ALSO
+.Xr btree 3 ,
+.Xr dbopen 3 ,
+.Xr hash 3 ,
+.Xr mpool 3
+.Rs
+.%T "Document Processing in a Relational Database System"
+.%A Michael Stonebraker
+.%A Heidi Stettner
+.%A Joseph Kalash
+.%A Antonin Guttman
+.%A Nadene Lynn
+.%R "Memorandum No. UCB/ERL M82/32"
+.%D May 1982
+.Re
+.Sh BUGS
+Only big and little endian byte order is supported.
diff --git a/lib/libc/db/mpool/Makefile.inc b/lib/libc/db/mpool/Makefile.inc
new file mode 100644
index 0000000..832e54d
--- /dev/null
+++ b/lib/libc/db/mpool/Makefile.inc
@@ -0,0 +1,6 @@
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/db/mpool
+
+SRCS+= mpool.c mpool-compat.c
diff --git a/lib/libc/db/mpool/README b/lib/libc/db/mpool/README
new file mode 100644
index 0000000..0f01fbc
--- /dev/null
+++ b/lib/libc/db/mpool/README
@@ -0,0 +1,7 @@
+# @(#)README 8.1 (Berkeley) 6/4/93
+
+These are the current memory pool routines.
+They aren't ready for prime time, yet, and
+the interface is expected to change.
+
+--keith
diff --git a/lib/libc/db/mpool/mpool-compat.c b/lib/libc/db/mpool/mpool-compat.c
new file mode 100644
index 0000000..9df76ff
--- /dev/null
+++ b/lib/libc/db/mpool/mpool-compat.c
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2009 Xin LI <delphij@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <db.h>
+#include <mpool.h>
+
+void *__mpool_new__44bsd(MPOOL *, pgno_t *);
+
+void *
+__mpool_new__44bsd(MPOOL *mp, pgno_t *pgnoaddr)
+{
+
+ return (mpool_new(mp, pgnoaddr, MPOOL_PAGE_NEXT));
+}
+
+__sym_compat(mpool_new, __mpool_new_44bsd, FBSD_1.0);
diff --git a/lib/libc/db/mpool/mpool.c b/lib/libc/db/mpool/mpool.c
new file mode 100644
index 0000000..c3a19e0
--- /dev/null
+++ b/lib/libc/db/mpool/mpool.c
@@ -0,0 +1,493 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)mpool.c 8.7 (Berkeley) 11/2/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+
+#define __MPOOLINTERFACE_PRIVATE
+#include <mpool.h>
+
+static BKT *mpool_bkt(MPOOL *);
+static BKT *mpool_look(MPOOL *, pgno_t);
+static int mpool_write(MPOOL *, BKT *);
+
+/*
+ * mpool_open --
+ * Initialize a memory pool.
+ */
+/* ARGSUSED */
+MPOOL *
+mpool_open(void *key, int fd, pgno_t pagesize, pgno_t maxcache)
+{
+ struct stat sb;
+ MPOOL *mp;
+ int entry;
+
+ /*
+ * Get information about the file.
+ *
+ * XXX
+ * We don't currently handle pipes, although we should.
+ */
+ if (_fstat(fd, &sb))
+ return (NULL);
+ if (!S_ISREG(sb.st_mode)) {
+ errno = ESPIPE;
+ return (NULL);
+ }
+
+ /* Allocate and initialize the MPOOL cookie. */
+ if ((mp = (MPOOL *)calloc(1, sizeof(MPOOL))) == NULL)
+ return (NULL);
+ TAILQ_INIT(&mp->lqh);
+ for (entry = 0; entry < HASHSIZE; ++entry)
+ TAILQ_INIT(&mp->hqh[entry]);
+ mp->maxcache = maxcache;
+ mp->npages = sb.st_size / pagesize;
+ mp->pagesize = pagesize;
+ mp->fd = fd;
+ return (mp);
+}
+
+/*
+ * mpool_filter --
+ * Initialize input/output filters.
+ */
+void
+mpool_filter(MPOOL *mp, void (*pgin) (void *, pgno_t, void *),
+ void (*pgout) (void *, pgno_t, void *), void *pgcookie)
+{
+ mp->pgin = pgin;
+ mp->pgout = pgout;
+ mp->pgcookie = pgcookie;
+}
+
+/*
+ * mpool_new --
+ * Get a new page of memory.
+ */
+void *
+mpool_new(MPOOL *mp, pgno_t *pgnoaddr, u_int flags)
+{
+ struct _hqh *head;
+ BKT *bp;
+
+ if (mp->npages == MAX_PAGE_NUMBER) {
+ (void)fprintf(stderr, "mpool_new: page allocation overflow.\n");
+ abort();
+ }
+#ifdef STATISTICS
+ ++mp->pagenew;
+#endif
+ /*
+ * Get a BKT from the cache. Assign a new page number, attach
+ * it to the head of the hash chain, the tail of the lru chain,
+ * and return.
+ */
+ if ((bp = mpool_bkt(mp)) == NULL)
+ return (NULL);
+ if (flags == MPOOL_PAGE_REQUEST) {
+ mp->npages++;
+ bp->pgno = *pgnoaddr;
+ } else
+ bp->pgno = *pgnoaddr = mp->npages++;
+
+ bp->flags = MPOOL_PINNED | MPOOL_INUSE;
+
+ head = &mp->hqh[HASHKEY(bp->pgno)];
+ TAILQ_INSERT_HEAD(head, bp, hq);
+ TAILQ_INSERT_TAIL(&mp->lqh, bp, q);
+ return (bp->page);
+}
+
+int
+mpool_delete(MPOOL *mp, void *page)
+{
+ struct _hqh *head;
+ BKT *bp;
+
+ bp = (BKT *)((char *)page - sizeof(BKT));
+
+#ifdef DEBUG
+ if (!(bp->flags & MPOOL_PINNED)) {
+ (void)fprintf(stderr,
+ "mpool_delete: page %d not pinned\n", bp->pgno);
+ abort();
+ }
+#endif
+
+ /* Remove from the hash and lru queues. */
+ head = &mp->hqh[HASHKEY(bp->pgno)];
+ TAILQ_REMOVE(head, bp, hq);
+ TAILQ_REMOVE(&mp->lqh, bp, q);
+
+ free(bp);
+ mp->curcache--;
+ return (RET_SUCCESS);
+}
+
+/*
+ * mpool_get
+ * Get a page.
+ */
+/* ARGSUSED */
+void *
+mpool_get(MPOOL *mp, pgno_t pgno,
+ u_int flags) /* XXX not used? */
+{
+ struct _hqh *head;
+ BKT *bp;
+ off_t off;
+ int nr;
+
+#ifdef STATISTICS
+ ++mp->pageget;
+#endif
+
+ /* Check for a page that is cached. */
+ if ((bp = mpool_look(mp, pgno)) != NULL) {
+#ifdef DEBUG
+ if (!(flags & MPOOL_IGNOREPIN) && bp->flags & MPOOL_PINNED) {
+ (void)fprintf(stderr,
+ "mpool_get: page %d already pinned\n", bp->pgno);
+ abort();
+ }
+#endif
+ /*
+ * Move the page to the head of the hash chain and the tail
+ * of the lru chain.
+ */
+ head = &mp->hqh[HASHKEY(bp->pgno)];
+ TAILQ_REMOVE(head, bp, hq);
+ TAILQ_INSERT_HEAD(head, bp, hq);
+ TAILQ_REMOVE(&mp->lqh, bp, q);
+ TAILQ_INSERT_TAIL(&mp->lqh, bp, q);
+
+ /* Return a pinned page. */
+ bp->flags |= MPOOL_PINNED;
+ return (bp->page);
+ }
+
+ /* Get a page from the cache. */
+ if ((bp = mpool_bkt(mp)) == NULL)
+ return (NULL);
+
+ /* Read in the contents. */
+ off = mp->pagesize * pgno;
+ if ((nr = pread(mp->fd, bp->page, mp->pagesize, off)) != (ssize_t)mp->pagesize) {
+ switch (nr) {
+ case -1:
+ /* errno is set for us by pread(). */
+ free(bp);
+ mp->curcache--;
+ return (NULL);
+ case 0:
+ /*
+ * A zero-length read means you need to create a
+ * new page.
+ */
+ memset(bp->page, 0, mp->pagesize);
+ break;
+ default:
+ /* A partial read is definitely bad. */
+ free(bp);
+ mp->curcache--;
+ errno = EINVAL;
+ return (NULL);
+ }
+ }
+#ifdef STATISTICS
+ ++mp->pageread;
+#endif
+
+ /* Set the page number, pin the page. */
+ bp->pgno = pgno;
+ if (!(flags & MPOOL_IGNOREPIN))
+ bp->flags = MPOOL_PINNED;
+ bp->flags |= MPOOL_INUSE;
+
+ /*
+ * Add the page to the head of the hash chain and the tail
+ * of the lru chain.
+ */
+ head = &mp->hqh[HASHKEY(bp->pgno)];
+ TAILQ_INSERT_HEAD(head, bp, hq);
+ TAILQ_INSERT_TAIL(&mp->lqh, bp, q);
+
+ /* Run through the user's filter. */
+ if (mp->pgin != NULL)
+ (mp->pgin)(mp->pgcookie, bp->pgno, bp->page);
+
+ return (bp->page);
+}
+
+/*
+ * mpool_put
+ * Return a page.
+ */
+/* ARGSUSED */
+int
+mpool_put(MPOOL *mp, void *page, u_int flags)
+{
+ BKT *bp;
+
+#ifdef STATISTICS
+ ++mp->pageput;
+#endif
+ bp = (BKT *)((char *)page - sizeof(BKT));
+#ifdef DEBUG
+ if (!(bp->flags & MPOOL_PINNED)) {
+ (void)fprintf(stderr,
+ "mpool_put: page %d not pinned\n", bp->pgno);
+ abort();
+ }
+#endif
+ bp->flags &= ~MPOOL_PINNED;
+ if (flags & MPOOL_DIRTY)
+ bp->flags |= flags & MPOOL_DIRTY;
+ return (RET_SUCCESS);
+}
+
+/*
+ * mpool_close
+ * Close the buffer pool.
+ */
+int
+mpool_close(MPOOL *mp)
+{
+ BKT *bp;
+
+ /* Free up any space allocated to the lru pages. */
+ while (!TAILQ_EMPTY(&mp->lqh)) {
+ bp = TAILQ_FIRST(&mp->lqh);
+ TAILQ_REMOVE(&mp->lqh, bp, q);
+ free(bp);
+ }
+
+ /* Free the MPOOL cookie. */
+ free(mp);
+ return (RET_SUCCESS);
+}
+
+/*
+ * mpool_sync
+ * Sync the pool to disk.
+ */
+int
+mpool_sync(MPOOL *mp)
+{
+ BKT *bp;
+
+ /* Walk the lru chain, flushing any dirty pages to disk. */
+ TAILQ_FOREACH(bp, &mp->lqh, q)
+ if (bp->flags & MPOOL_DIRTY &&
+ mpool_write(mp, bp) == RET_ERROR)
+ return (RET_ERROR);
+
+ /* Sync the file descriptor. */
+ return (_fsync(mp->fd) ? RET_ERROR : RET_SUCCESS);
+}
+
+/*
+ * mpool_bkt
+ * Get a page from the cache (or create one).
+ */
+static BKT *
+mpool_bkt(MPOOL *mp)
+{
+ struct _hqh *head;
+ BKT *bp;
+
+ /* If under the max cached, always create a new page. */
+ if (mp->curcache < mp->maxcache)
+ goto new;
+
+ /*
+ * If the cache is max'd out, walk the lru list for a buffer we
+ * can flush. If we find one, write it (if necessary) and take it
+ * off any lists. If we don't find anything we grow the cache anyway.
+ * The cache never shrinks.
+ */
+ TAILQ_FOREACH(bp, &mp->lqh, q)
+ if (!(bp->flags & MPOOL_PINNED)) {
+ /* Flush if dirty. */
+ if (bp->flags & MPOOL_DIRTY &&
+ mpool_write(mp, bp) == RET_ERROR)
+ return (NULL);
+#ifdef STATISTICS
+ ++mp->pageflush;
+#endif
+ /* Remove from the hash and lru queues. */
+ head = &mp->hqh[HASHKEY(bp->pgno)];
+ TAILQ_REMOVE(head, bp, hq);
+ TAILQ_REMOVE(&mp->lqh, bp, q);
+#ifdef DEBUG
+ { void *spage;
+ spage = bp->page;
+ memset(bp, 0xff, sizeof(BKT) + mp->pagesize);
+ bp->page = spage;
+ }
+#endif
+ bp->flags = 0;
+ return (bp);
+ }
+
+new: if ((bp = (BKT *)calloc(1, sizeof(BKT) + mp->pagesize)) == NULL)
+ return (NULL);
+#ifdef STATISTICS
+ ++mp->pagealloc;
+#endif
+ bp->page = (char *)bp + sizeof(BKT);
+ bp->flags = 0;
+ ++mp->curcache;
+ return (bp);
+}
+
+/*
+ * mpool_write
+ * Write a page to disk.
+ */
+static int
+mpool_write(MPOOL *mp, BKT *bp)
+{
+ off_t off;
+
+#ifdef STATISTICS
+ ++mp->pagewrite;
+#endif
+
+ /* Run through the user's filter. */
+ if (mp->pgout)
+ (mp->pgout)(mp->pgcookie, bp->pgno, bp->page);
+
+ off = mp->pagesize * bp->pgno;
+ if (pwrite(mp->fd, bp->page, mp->pagesize, off) != (ssize_t)mp->pagesize)
+ return (RET_ERROR);
+
+ /*
+ * Re-run through the input filter since this page may soon be
+ * accessed via the cache, and whatever the user's output filter
+ * did may screw things up if we don't let the input filter
+ * restore the in-core copy.
+ */
+ if (mp->pgin)
+ (mp->pgin)(mp->pgcookie, bp->pgno, bp->page);
+
+ bp->flags &= ~MPOOL_DIRTY;
+ return (RET_SUCCESS);
+}
+
+/*
+ * mpool_look
+ * Lookup a page in the cache.
+ */
+static BKT *
+mpool_look(MPOOL *mp, pgno_t pgno)
+{
+ struct _hqh *head;
+ BKT *bp;
+
+ head = &mp->hqh[HASHKEY(pgno)];
+ TAILQ_FOREACH(bp, head, hq)
+ if ((bp->pgno == pgno) &&
+ ((bp->flags & MPOOL_INUSE) == MPOOL_INUSE)) {
+#ifdef STATISTICS
+ ++mp->cachehit;
+#endif
+ return (bp);
+ }
+#ifdef STATISTICS
+ ++mp->cachemiss;
+#endif
+ return (NULL);
+}
+
+#ifdef STATISTICS
+/*
+ * mpool_stat
+ * Print out cache statistics.
+ */
+void
+mpool_stat(MPOOL *mp)
+{
+ BKT *bp;
+ int cnt;
+ char *sep;
+
+ (void)fprintf(stderr, "%lu pages in the file\n", mp->npages);
+ (void)fprintf(stderr,
+ "page size %lu, cacheing %lu pages of %lu page max cache\n",
+ mp->pagesize, mp->curcache, mp->maxcache);
+ (void)fprintf(stderr, "%lu page puts, %lu page gets, %lu page new\n",
+ mp->pageput, mp->pageget, mp->pagenew);
+ (void)fprintf(stderr, "%lu page allocs, %lu page flushes\n",
+ mp->pagealloc, mp->pageflush);
+ if (mp->cachehit + mp->cachemiss)
+ (void)fprintf(stderr,
+ "%.0f%% cache hit rate (%lu hits, %lu misses)\n",
+ ((double)mp->cachehit / (mp->cachehit + mp->cachemiss))
+ * 100, mp->cachehit, mp->cachemiss);
+ (void)fprintf(stderr, "%lu page reads, %lu page writes\n",
+ mp->pageread, mp->pagewrite);
+
+ sep = "";
+ cnt = 0;
+ TAILQ_FOREACH(bp, &mp->lqh, q) {
+ (void)fprintf(stderr, "%s%d", sep, bp->pgno);
+ if (bp->flags & MPOOL_DIRTY)
+ (void)fprintf(stderr, "d");
+ if (bp->flags & MPOOL_PINNED)
+ (void)fprintf(stderr, "P");
+ if (++cnt == 10) {
+ sep = "\n";
+ cnt = 0;
+ } else
+ sep = ", ";
+
+ }
+ (void)fprintf(stderr, "\n");
+}
+#endif
diff --git a/lib/libc/db/mpool/mpool.libtp b/lib/libc/db/mpool/mpool.libtp
new file mode 100644
index 0000000..bcd827d
--- /dev/null
+++ b/lib/libc/db/mpool/mpool.libtp
@@ -0,0 +1,746 @@
+/******************************************************************************
+
+VERSION $FreeBSD$
+PACKAGE: User Level Shared Memory Manager
+
+DESCRIPTION:
+ This package provides a buffer pool interface implemented as
+ a collection of file pages mapped into shared memory.
+
+ Based on Mark's buffer manager
+
+ROUTINES:
+ External
+ buf_alloc
+ buf_flags
+ buf_get
+ buf_init
+ buf_last
+ buf_open
+ buf_pin
+ buf_sync
+ buf_unpin
+ Internal
+ bf_assign_buf
+ bf_fid_to_fd
+ bf_newbuf
+ bf_put_page
+
+
+******************************************************************************/
+#include <sys/types.h>
+#include <assert.h>
+#include <sys/file.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <errno.h>
+#include "list.h"
+#include "user.h"
+#include "txn_sys.h"
+#include "buf.h"
+#include "semkeys.h"
+#include "error.h"
+
+/*
+ we need to translate between some type of file id that the user
+ process passes and a file descriptor. For now, it's a nop.
+*/
+#define GET_MASTER get_sem ( buf_spinlock )
+#define RELEASE_MASTER release_sem ( buf_spinlock )
+
+#define LRUID *buf_lru
+#define LRUP (bufhdr_table+*buf_lru)
+#define MRU bufhdr_table[*buf_lru].lru.prev
+
+/* Global indicator that you have started reusing buffers */
+int do_statistics = 0;
+/*
+ Process Statics (pointers into shared memory)
+*/
+static BUF_T *buf_table = 0;
+static BUFHDR_T *bufhdr_table;
+static int *buf_hash_table;
+static int *buf_lru; /* LRU is the free list */
+static int buf_spinlock;
+static FINFO_T *buf_fids;
+static int *buf_sp; /* Pointer to string free space */
+static char *buf_strings;
+
+/* Process Local FID->FD table */
+static int fds[NUM_FILE_ENTRIES];
+
+/* Static routines */
+static BUFHDR_T *bf_assign_buf();
+static int bf_fid_to_fd();
+static BUFHDR_T *bf_newbuf();
+static int bf_put_page();
+
+/*
+ Return 0 on success
+ 1 on failure
+*/
+extern int
+buf_init ( )
+{
+ ADDR_T buf_region;
+ BUFHDR_T *bhp;
+ int i;
+ int ref_count;
+ int *spinlockp;
+
+ /*
+ Initialize Process local structures
+ */
+ for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {
+ fds[i] = -1;
+ }
+
+ buf_region = attach_region ( BUF_REGION_NAME, BUF_REGION_NUM,
+ BUF_REGION_SIZE, &ref_count );
+ if ( !buf_region ) {
+ return (1);
+ }
+ error_log3 ( "Buf Region: ADDR: %d ID: %d SIZE: %d\n", buf_region,
+ BUF_REGION_NUM, BUF_REGION_SIZE );
+
+ buf_table = (BUF_T *)buf_region;
+ bufhdr_table = (BUFHDR_T *)(buf_table + NUM_BUFS);
+ buf_hash_table = (int *)(bufhdr_table + NUM_BUFS);
+ buf_lru = buf_hash_table + NUMTABLE_ENTRIES;
+ spinlockp = buf_lru + 1;
+ buf_fids = (FINFO_T *)(spinlockp+1);
+ buf_sp = (int *)(buf_fids + NUM_FILE_ENTRIES);
+ buf_strings = (char *)(buf_sp + 1);
+
+ /* Create locking spinlock (gets creating holding the lock) */
+ buf_spinlock = create_sem ( BUF_SPIN_NAME, BUF_SPIN_NUM, ref_count <= 1 );
+ if ( buf_spinlock < 0 ) {
+ return(1);
+ }
+ if ( ref_count <= 1 ) {
+ *spinlockp = buf_spinlock;
+
+ /* Now initialize the buffer manager */
+
+ /* 1. Free list */
+ *buf_lru = 0;
+
+ /* 2. Buffer headers */
+ for ( i = 0, bhp = bufhdr_table; i < NUM_BUFS; bhp++, i++ ) {
+ bhp->lru.next = i+1;
+ bhp->lru.prev = i-1;
+ bhp->flags = 0; /* All Flags off */
+ bhp->refcount = 0;
+ bhp->wait_proc = -1; /* No sleepers */
+ LISTPE_INIT ( hash, bhp, i ); /* Hash chains */
+ }
+ bufhdr_table[0].lru.prev = NUM_BUFS-1;
+ bufhdr_table[NUM_BUFS-1].lru.next = 0;
+
+ /* 3. Hash Table */
+ for ( i = 0; i < NUMTABLE_ENTRIES; i++ ) {
+ buf_hash_table[i] = NUM_BUFS;
+ }
+
+ /* 4. File ID Table */
+ for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {
+ buf_fids[i].offset = -1;
+ buf_fids[i].npages = -1;
+ buf_fids[i].refcount = 0;
+ }
+
+ /* 5. Free String Pointer */
+ *buf_sp = (FILE_NAME_LEN*NUM_FILE_ENTRIES);
+ if (RELEASE_MASTER) {
+ return(1);
+ }
+ error_log0 ( "Initialized buffer region\n" );
+ }
+ return (0);
+}
+
+extern void
+buf_exit()
+{
+ int ref;
+ int i;
+
+ /* Flush Buffer Pool on Exit */
+ for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {
+ if ( fds[i] != -1 ) {
+ close ( fds[i] );
+ }
+ }
+ if ( buf_table ) {
+ detach_region ( buf_table, BUF_REGION_NUM, BUF_REGION_SIZE, &ref );
+ }
+ return;
+}
+
+/*
+ We need an empty buffer. Find the LRU unpinned NON-Dirty page.
+*/
+static BUFHDR_T *
+bf_newbuf()
+{
+ int fd;
+ int lruid;
+ int nbytes;
+ int ndx;
+ BUFHDR_T *bhp;
+
+ lruid = LRUID;
+ for ( bhp = LRUP;
+ bhp->flags & (BUF_PINNED|BUF_IO_IN_PROGRESS);
+ bhp = LISTP_NEXTP (bufhdr_table, lru, bhp ) ) {
+
+ if ( bhp->lru.next == lruid ) {
+ /* OUT OF BUFFERS */
+ error_log1 ( "All buffers are pinned. %s\n",
+ "Unable to grant buffer request" );
+ return(NULL);
+ }
+ }
+ /* BHP can be used */
+ if ( bhp->flags & BUF_DIRTY ) {
+ do_statistics = 1;
+ /*
+ MIS Check for log flushed appropriately
+ */
+ fd = bf_fid_to_fd(bhp->id.file_id);
+ if ( fd == -1 ) {
+ error_log1 ("Invalid fid %d\n", bhp->id.file_id);
+ return(NULL);
+ }
+ if ( bf_put_page(fd, bhp) < 0 ) {
+ return(NULL);
+ }
+ }
+ /* Update Hash Pointers */
+ ndx = BUF_HASH ( bhp->id.file_id, bhp->id.obj_id );
+ LISTP_REMOVE(bufhdr_table, hash, bhp);
+ if ( buf_hash_table[ndx] == (bhp-bufhdr_table) ) {
+ if ( bhp->hash.next != (bhp-bufhdr_table) ) {
+ buf_hash_table[ndx] = bhp->hash.next;
+ } else {
+ buf_hash_table[ndx] = NUM_BUFS;
+ }
+ }
+ INIT_BUF(bhp);
+
+ return(bhp);
+}
+/*
+ buf_alloc
+
+ Add a page to a file and return a buffer for it.
+
+*/
+ADDR_T
+buf_alloc ( fid, new_pageno )
+int fid;
+int *new_pageno;
+{
+ BUFHDR_T *bhp;
+ int fd;
+ int len;
+ int ndx;
+ OBJ_T fobj;
+
+ if (GET_MASTER) {
+ return(NULL);
+ }
+ if ( buf_fids[fid].npages == -1 ) {
+ /* initialize npages field */
+ fd = bf_fid_to_fd ( fid );
+ }
+ assert (fid < NUM_FILE_ENTRIES);
+
+ *new_pageno = buf_fids[fid].npages;
+ if ( *new_pageno == -1 ) {
+ RELEASE_MASTER;
+ return ( NULL );
+ }
+ buf_fids[fid].npages++;
+ ndx = BUF_HASH ( fid, *new_pageno );
+ fobj.file_id = fid;
+ fobj.obj_id = *new_pageno;
+ bhp = bf_assign_buf ( ndx, &fobj, BF_PIN|BF_DIRTY|BF_EMPTY, &len );
+ if ( RELEASE_MASTER ) {
+ /* Memory leak */
+ return(NULL);
+ }
+ if ( bhp ) {
+ return ((ADDR_T)(buf_table+(bhp-bufhdr_table)));
+ } else {
+ return ( NULL );
+ }
+}
+
+
+/*
+ Buffer Flags
+ BF_DIRTY Mark page as dirty
+ BF_EMPTY Don't initialize page, just get buffer
+ BF_PIN Retrieve with pin
+
+MIS
+Might want to add a flag that sets an LSN for this buffer is the
+DIRTY flag is set
+
+Eventually, you may want a flag that indicates the I/O and lock
+request should be shipped off together, but not for now.
+*/
+extern ADDR_T
+buf_get ( file_id, page_id, flags, len )
+int file_id;
+int page_id;
+u_long flags;
+int *len; /* Number of bytes read into buffer */
+{
+ BUFHDR_T *bhp;
+ int bufid;
+ int fd;
+ int ndx;
+ int next_bufid;
+ int stat;
+ OBJ_T fobj;
+
+ ndx = BUF_HASH ( file_id, page_id );
+ fobj.file_id = (long) file_id;
+ fobj.obj_id = (long) page_id;
+ if ( GET_MASTER ) {
+ return(NULL);
+ }
+ /*
+ This could be a for loop, but we lose speed
+ by making all the cases general purpose so we
+ optimize for the no-collision case.
+ */
+ bufid = buf_hash_table[ndx];
+ if ( bufid < NUM_BUFS ) {
+ for ( bhp = bufhdr_table+bufid;
+ !OBJ_EQ (bhp->id, fobj) || !(bhp->flags & BUF_VALID);
+ bhp = LISTP_NEXTP ( bufhdr_table, hash, bhp ) ) {
+
+ if ( bhp->hash.next == bufid ) {
+ goto not_found;
+ }
+ }
+/* found */
+ if ( flags & BF_PIN ) {
+ bhp->flags |= BUF_PINNED;
+ bhp->refcount++;
+#ifdef PIN_DEBUG
+ fprintf(stderr, "buf_get: %X PINNED (%d)\n",
+ buf_table + (bhp-bufhdr_table), bhp->refcount);
+#endif
+ }
+ if ( flags & BF_DIRTY ) {
+ bhp->flags |= BUF_DIRTY;
+ }
+
+ while ( bhp->flags & BUF_IO_IN_PROGRESS ) {
+ /* MIS -- eventually err check here */
+#ifdef DEBUG
+ printf("About to sleep on %d (me: %d\n)\n", bhp->wait_proc,
+ my_txnp - txn_table);
+#endif
+#ifdef WAIT_STATS
+ buf_waits++;
+#endif
+ stat = proc_sleep_on ( &(bhp->wait_proc), buf_spinlock );
+ if ( stat ) {
+ /* Memory leak */
+ return(NULL);
+ }
+ if (!( bhp->flags & BUF_IO_IN_PROGRESS) &&
+ (!OBJ_EQ (bhp->id, fobj) || !(bhp->flags & BUF_VALID))) {
+ if (RELEASE_MASTER)
+ return(NULL);
+ return(buf_get ( file_id, page_id, flags, len ));
+ }
+ }
+ MAKE_MRU( bhp );
+ *len = BUFSIZE;
+ } else {
+not_found:
+ /* If you get here, the page isn't in the hash table */
+ bhp = bf_assign_buf ( ndx, &fobj, flags, len );
+ }
+ /* Common code between found and not found */
+
+ if ( bhp && bhp->flags & BUF_NEWPAGE ) {
+ *len = 0;
+ }
+ if (RELEASE_MASTER){
+ /* Memory leak */
+ return(NULL);
+ }
+ if ( bhp ) {
+ return ((ADDR_T)(buf_table+(bhp-bufhdr_table)));
+ } else {
+ return ( NULL );
+ }
+}
+
+/*
+ MIS - do I want to add file links to buffer pool?
+*/
+extern int
+buf_sync ( fid, close )
+int fid;
+int close; /* should we dec refcount and possibly
+ invalidate all the buffers */
+{
+ int i;
+ int fd;
+ int invalidate;
+ BUFHDR_T *bhp;
+
+ if ( (fd = bf_fid_to_fd ( fid )) < 0 ) {
+ return(1);
+ }
+ if (GET_MASTER) {
+ return(1);
+ }
+ invalidate = (buf_fids[fid].refcount == 1 && close);
+ if ( invalidate )
+ for ( bhp = bufhdr_table, i = 0; i < NUM_BUFS; bhp++, i++ ) {
+ if (bhp->id.file_id == fid) {
+ if ((bhp->flags & BF_DIRTY) && (bf_put_page( fd, bhp ) < 0)) {
+ return(1);
+ }
+ bhp->id.file_id = -1;
+ }
+ }
+ if (invalidate || close)
+ buf_fids[fid].refcount--;
+
+ if (RELEASE_MASTER) {
+ return(1);
+ }
+ return(0);
+
+
+}
+
+extern int
+buf_flags ( addr, set_flags, unset_flags )
+ADDR_T addr;
+u_long set_flags;
+u_long unset_flags;
+{
+ int bufid;
+ BUFHDR_T *bhp;
+
+#ifdef PIN_DEBUG
+ fprintf(stderr, "buf_flags: %X setting %s%s%s%s%s releasing %s%s%s%s%s\n",
+ addr,
+ set_flags&BUF_DIRTY ? "DIRTY " : "",
+ set_flags&BUF_VALID ? "VALID " : "",
+ set_flags&BUF_PINNED ? "PINNED " : "",
+ set_flags&BUF_IO_ERROR ? "IO_ERROR " : "",
+ set_flags&BUF_IO_IN_PROGRESS ? "IO_IN_PROG " : "",
+ set_flags&BUF_NEWPAGE ? "NEWPAGE " : "",
+ unset_flags&BUF_DIRTY ? "DIRTY " : "",
+ unset_flags&BUF_VALID ? "VALID " : "",
+ unset_flags&BUF_PINNED ? "PINNED " : "",
+ unset_flags&BUF_IO_ERROR ? "IO_ERROR " : "",
+ unset_flags&BUF_IO_IN_PROGRESS ? "IO_IN_PROG " : "",
+ unset_flags&BUF_NEWPAGE ? "NEWPAGE " : "" );
+#endif
+ if (!ADDR_OK(addr)) {
+ error_log1 ( "buf_pin: Invalid Buffer Address %x\n", addr );
+ return(1);
+ }
+ bufid = ((BUF_T *)addr) - buf_table;
+ assert ( bufid < NUM_BUFS);
+ bhp = &bufhdr_table[bufid];
+ if (GET_MASTER) {
+ return(1);
+ }
+ bhp->flags |= set_flags;
+ if ( set_flags & BUF_PINNED ) {
+ bhp->refcount++;
+ }
+ if ( set_flags & BUF_DIRTY ) {
+ unset_flags |= BUF_NEWPAGE;
+ }
+
+ if ( unset_flags & BUF_PINNED ) {
+ bhp->refcount--;
+ if ( bhp->refcount ) {
+ /* Turn off pin bit so it doesn't get unset */
+ unset_flags &= ~BUF_PINNED;
+ }
+ }
+ bhp->flags &= ~unset_flags;
+ MAKE_MRU(bhp);
+ if (RELEASE_MASTER) {
+ return(1);
+ }
+ return(0);
+}
+
+/*
+ Take a string name and produce an fid.
+
+ returns -1 on error
+
+ MIS -- this is a potential problem -- you keep actual names
+ here -- what if people run from different directories?
+*/
+extern int
+buf_name_lookup ( fname )
+char *fname;
+{
+ int i;
+ int fid;
+ int ndx;
+
+ fid = -1;
+ if (GET_MASTER) {
+ return(-1);
+ }
+ for ( i = 0; i < NUM_FILE_ENTRIES; i++ ) {
+ if ( buf_fids[i].offset == -1 ) {
+ fid = i;
+ } else {
+ if (!strcmp (fname, buf_strings+buf_fids[i].offset)) {
+ if (RELEASE_MASTER) {
+ return(-1);
+ }
+ buf_fids[i].refcount++;
+ return(i);
+ }
+ }
+ }
+ if ( fid == -1 ) {
+ error_log0 ( "No more file ID's\n" );
+ } else {
+ ndx = *buf_sp - strlen(fname) - 1;
+ if ( ndx < 0 ) {
+ error_log0 ( "Out of string space\n" );
+ fid = -1;
+ } else {
+ *buf_sp = ndx;
+ strcpy ( buf_strings+ndx, fname );
+ buf_fids[fid].offset = ndx;
+ }
+ buf_fids[fid].refcount = 1;
+ }
+ if (RELEASE_MASTER) {
+ return(-1);
+ }
+ return(fid);
+}
+
+static int
+bf_fid_to_fd ( fid )
+int fid;
+{
+ struct stat sbuf;
+
+ assert ( (fid < NUM_FILE_ENTRIES) && (buf_fids[fid].offset != -1) );
+ if ( fds[fid] != -1 ) {
+ return(fds[fid]);
+
+ }
+ fds[fid] = open ( buf_strings+buf_fids[fid].offset, O_RDWR|O_CREAT,
+ 0666 );
+ if ( fds[fid] < 0 ) {
+ error_log3 ( "Error Opening File %s FID: %d FD: %d. Errno = %d\n",
+ buf_strings+buf_fids[fid].offset, fid, fds[fid],
+ errno );
+ return(-1);
+ }
+ error_log3 ( "Opening File %s FID: %d FD: %d\n",
+ buf_strings+buf_fids[fid].offset, fid, fds[fid] );
+ if ( buf_fids[fid].npages == -1 ) {
+ /* Initialize the npages field */
+ if ( fstat ( fds[fid], &sbuf ) ) {
+ error_log3 ( "Error Fstating %s FID: %d. Errno = %d\n",
+ buf_strings+buf_fids[fid].offset, fid, errno );
+ } else {
+ buf_fids[fid].npages = ( sbuf.st_size / BUFSIZE );
+ }
+ }
+
+ return ( fds[fid] );
+}
+
+static int
+bf_put_page ( fd, bhp )
+int fd;
+BUFHDR_T *bhp;
+{
+ int nbytes;
+
+ assert ( (bhp-bufhdr_table) < NUM_BUFS );
+ if ( lseek ( fd, bhp->id.obj_id << BUFSHIFT, L_SET ) < 0 ) {
+ return(-1);
+ }
+ bhp->flags |= BUF_IO_IN_PROGRESS;
+ if (RELEASE_MASTER) {
+ return(-1);
+ }
+ nbytes = write(fd, buf_table[bhp-bufhdr_table], BUFSIZE);
+ if (GET_MASTER) {
+ return(-2);
+ }
+ if ( nbytes < 0 ) {
+ error_log1 ("Write failed with error code %d\n", errno);
+ return(-1);
+ } else if ( nbytes != BUFSIZE ) {
+ error_log1 ("Short write: %d bytes of %d\n", nbytes, BUFSIZE );
+ }
+ bhp->flags &= ~(BUF_DIRTY|BUF_IO_IN_PROGRESS);
+ return (0);
+}
+
+static BUFHDR_T *
+bf_assign_buf ( ndx, obj, flags, len )
+int ndx;
+OBJ_T *obj;
+u_long flags;
+int *len; /* Number of bytes read */
+{
+ BUFHDR_T *bhp;
+ int fd;
+
+ assert ( obj->file_id < NUM_FILE_ENTRIES );
+ bhp = bf_newbuf();
+ if ( !bhp ) {
+ return(NULL);
+ }
+ OBJ_ASSIGN ( (*obj), bhp->id );
+ if ( buf_hash_table[ndx] >= NUM_BUFS ) {
+ buf_hash_table[ndx] = bhp-bufhdr_table;
+ } else {
+ LISTPE_INSERT ( bufhdr_table, hash, bhp, buf_hash_table[ndx] );
+ }
+
+ bhp->flags |= BUF_VALID;
+ if ( flags & BF_PIN ) {
+ bhp->flags |= BUF_PINNED;
+ bhp->refcount++;
+#ifdef PIN_DEBUG
+ fprintf(stderr, "bf_assign_buf: %X PINNED (%d)\n",
+ buf_table + (bhp-bufhdr_table), bhp->refcount);
+#endif
+ }
+ fd = bf_fid_to_fd(obj->file_id);
+ if ( fd == -1 ) {
+ error_log1 ("Invalid fid %d\n", obj->file_id);
+ bhp->flags |= ~BUF_IO_ERROR;
+ return(NULL);
+ }
+ if ( obj->obj_id >= buf_fids[obj->file_id].npages) {
+ buf_fids[obj->file_id].npages = obj->obj_id+1;
+ *len = 0;
+ } else if ( flags & BF_EMPTY ) {
+ *len = 0;
+ } else {
+ bhp->flags |= BUF_IO_IN_PROGRESS;
+ if (RELEASE_MASTER) {
+ return(NULL);
+ }
+ if ( lseek ( fd, obj->obj_id << BUFSHIFT, L_SET ) < -1 ) {
+ error_log2 ("Unable to perform seek on file: %d to page %d",
+ obj->file_id, obj->obj_id );
+ bhp->flags &= ~BUF_IO_IN_PROGRESS;
+ bhp->flags |= ~BUF_IO_ERROR;
+ return(NULL);
+ }
+ *len = read(fd, buf_table[bhp-bufhdr_table], BUFSIZE);
+ if ( *len < 0 ) {
+ error_log2 ("Unable to perform read on file: %d to page %d",
+ obj->file_id, obj->obj_id );
+ bhp->flags &= ~BUF_IO_IN_PROGRESS;
+ bhp->flags |= ~BUF_IO_ERROR;
+ return(NULL);
+ }
+ if (GET_MASTER) {
+ return(NULL);
+ }
+ bhp->flags &= ~BUF_IO_IN_PROGRESS;
+ if ( bhp->wait_proc != -1 ) {
+ /* wake up waiter and anyone waiting on it */
+#ifdef DEBUG
+ printf("Waking transaction %d due to completed I/O\n",
+ bhp->wait_proc);
+#endif
+ proc_wake_id ( bhp->wait_proc );
+ bhp->wait_proc = -1;
+ }
+ MAKE_MRU(bhp);
+ }
+
+ if ( flags & BF_DIRTY ) {
+ bhp->flags |= BUF_DIRTY;
+ } else if ( *len < BUFSIZE ) {
+ bhp->flags |= BUF_NEWPAGE;
+ }
+ return ( bhp );
+}
+
+int
+buf_last ( fid )
+int fid;
+{
+ int val;
+
+ if (GET_MASTER) {
+ return(-1);
+ }
+ assert ( fid < NUM_FILE_ENTRIES );
+ if ( buf_fids[fid].npages == -1 ) {
+ /* initialize npages field */
+ (void) bf_fid_to_fd ( fid );
+ }
+ val = buf_fids[fid].npages;
+ if ( val ) {
+ val--; /* Convert to page number */
+ }
+ if (RELEASE_MASTER) {
+ return(-1);
+ }
+ return(val);
+}
+
+#ifdef DEBUG
+extern void
+buf_dump ( id, all )
+int id;
+int all;
+{
+ int i;
+ BUFHDR_T *bhp;
+
+ printf ( "LRU + %d\n", *buf_lru );
+ if ( all ) {
+ printf("ID\tFID\tPID\tLNEXT\tLPREV\tHNEXT\tHPREV\tSLEEP\tFLAG\tREFS\n");
+ for ( bhp = bufhdr_table, i = 0; i < NUM_BUFS; bhp++, i++ ) {
+ printf ( "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%x\t%d\n", i,
+ bhp->id.file_id, bhp->id.obj_id,
+ bhp->lru.next, bhp->lru.prev,
+ bhp->hash.next, bhp->hash.prev,
+ bhp->wait_proc, bhp->flags, bhp->refcount );
+ }
+ } else {
+ if ( id >= NUM_BUFS ) {
+ printf ( "Buffer ID (%d) too high\n", id );
+ return;
+ }
+ bhp = bufhdr_table+id;
+ printf ( "%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%x\t%d\n", i,
+ bhp->id.file_id, bhp->id.obj_id,
+ bhp->lru.next, bhp->lru.prev,
+ bhp->hash.next, bhp->hash.prev,
+ bhp->wait_proc, bhp->flags, bhp->refcount );
+ }
+ return;
+}
+#endif
+
diff --git a/lib/libc/db/recno/Makefile.inc b/lib/libc/db/recno/Makefile.inc
new file mode 100644
index 0000000..6e08e3f
--- /dev/null
+++ b/lib/libc/db/recno/Makefile.inc
@@ -0,0 +1,7 @@
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/db/recno
+
+SRCS+= rec_close.c rec_delete.c rec_get.c rec_open.c rec_put.c rec_search.c \
+ rec_seq.c rec_utils.c
diff --git a/lib/libc/db/recno/extern.h b/lib/libc/db/recno/extern.h
new file mode 100644
index 0000000..53916bd
--- /dev/null
+++ b/lib/libc/db/recno/extern.h
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)extern.h 8.3 (Berkeley) 6/4/94
+ * $FreeBSD$
+ */
+
+#include "../btree/extern.h"
+
+int __rec_close(DB *);
+int __rec_delete(const DB *, const DBT *, u_int);
+int __rec_dleaf(BTREE *, PAGE *, u_int32_t);
+int __rec_fd(const DB *);
+int __rec_fmap(BTREE *, recno_t);
+int __rec_fout(BTREE *);
+int __rec_fpipe(BTREE *, recno_t);
+int __rec_get(const DB *, const DBT *, DBT *, u_int);
+int __rec_iput(BTREE *, recno_t, const DBT *, u_int);
+int __rec_put(const DB *dbp, DBT *, const DBT *, u_int);
+int __rec_ret(BTREE *, EPG *, recno_t, DBT *, DBT *);
+EPG *__rec_search(BTREE *, recno_t, enum SRCHOP);
+int __rec_seq(const DB *, DBT *, DBT *, u_int);
+int __rec_sync(const DB *, u_int);
+int __rec_vmap(BTREE *, recno_t);
+int __rec_vout(BTREE *);
+int __rec_vpipe(BTREE *, recno_t);
diff --git a/lib/libc/db/recno/rec_close.c b/lib/libc/db/recno/rec_close.c
new file mode 100644
index 0000000..2d1ff84
--- /dev/null
+++ b/lib/libc/db/recno/rec_close.c
@@ -0,0 +1,182 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_close.c 8.6 (Berkeley) 8/18/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/mman.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_CLOSE -- Close a recno tree.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_close(DB *dbp)
+{
+ BTREE *t;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ if (__rec_sync(dbp, 0) == RET_ERROR)
+ return (RET_ERROR);
+
+ /* Committed to closing. */
+ status = RET_SUCCESS;
+ if (F_ISSET(t, R_MEMMAPPED) && munmap(t->bt_smap, t->bt_msize))
+ status = RET_ERROR;
+
+ if (!F_ISSET(t, R_INMEM)) {
+ if (F_ISSET(t, R_CLOSEFP)) {
+ if (fclose(t->bt_rfp))
+ status = RET_ERROR;
+ } else {
+ if (_close(t->bt_rfd))
+ status = RET_ERROR;
+ }
+ }
+
+ if (__bt_close(dbp) == RET_ERROR)
+ status = RET_ERROR;
+
+ return (status);
+}
+
+/*
+ * __REC_SYNC -- sync the recno tree to disk.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_sync(const DB *dbp, u_int flags)
+{
+ struct iovec iov[2];
+ BTREE *t;
+ DBT data, key;
+ off_t off;
+ recno_t scursor, trec;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ if (flags == R_RECNOSYNC)
+ return (__bt_sync(dbp, 0));
+
+ if (F_ISSET(t, R_RDONLY | R_INMEM) || !F_ISSET(t, R_MODIFIED))
+ return (RET_SUCCESS);
+
+ /* Read any remaining records into the tree. */
+ if (!F_ISSET(t, R_EOF) && t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+ return (RET_ERROR);
+
+ /* Rewind the file descriptor. */
+ if (lseek(t->bt_rfd, (off_t)0, SEEK_SET) != 0)
+ return (RET_ERROR);
+
+ /* Save the cursor. */
+ scursor = t->bt_cursor.rcursor;
+
+ key.size = sizeof(recno_t);
+ key.data = &trec;
+
+ if (F_ISSET(t, R_FIXLEN)) {
+ /*
+ * We assume that fixed length records are all fixed length.
+ * Any that aren't are either EINVAL'd or corrected by the
+ * record put code.
+ */
+ status = (dbp->seq)(dbp, &key, &data, R_FIRST);
+ while (status == RET_SUCCESS) {
+ if (_write(t->bt_rfd, data.data, data.size) !=
+ (ssize_t)data.size)
+ return (RET_ERROR);
+ status = (dbp->seq)(dbp, &key, &data, R_NEXT);
+ }
+ } else {
+ iov[1].iov_base = &t->bt_bval;
+ iov[1].iov_len = 1;
+
+ status = (dbp->seq)(dbp, &key, &data, R_FIRST);
+ while (status == RET_SUCCESS) {
+ iov[0].iov_base = data.data;
+ iov[0].iov_len = data.size;
+ if (_writev(t->bt_rfd, iov, 2) != (ssize_t)(data.size + 1))
+ return (RET_ERROR);
+ status = (dbp->seq)(dbp, &key, &data, R_NEXT);
+ }
+ }
+
+ /* Restore the cursor. */
+ t->bt_cursor.rcursor = scursor;
+
+ if (status == RET_ERROR)
+ return (RET_ERROR);
+ if ((off = lseek(t->bt_rfd, (off_t)0, SEEK_CUR)) == -1)
+ return (RET_ERROR);
+ if (ftruncate(t->bt_rfd, off))
+ return (RET_ERROR);
+ F_CLR(t, R_MODIFIED);
+ return (RET_SUCCESS);
+}
diff --git a/lib/libc/db/recno/rec_delete.c b/lib/libc/db/recno/rec_delete.c
new file mode 100644
index 0000000..d799da2
--- /dev/null
+++ b/lib/libc/db/recno/rec_delete.c
@@ -0,0 +1,187 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_delete.c 8.7 (Berkeley) 7/14/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+static int rec_rdelete(BTREE *, recno_t);
+
+/*
+ * __REC_DELETE -- Delete the item(s) referenced by a key.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ * key: key to delete
+ * flags: R_CURSOR if deleting what the cursor references
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__rec_delete(const DB *dbp, const DBT *key, u_int flags)
+{
+ BTREE *t;
+ recno_t nrec;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ switch(flags) {
+ case 0:
+ if ((nrec = *(recno_t *)key->data) == 0)
+ goto einval;
+ if (nrec > t->bt_nrecs)
+ return (RET_SPECIAL);
+ --nrec;
+ status = rec_rdelete(t, nrec);
+ break;
+ case R_CURSOR:
+ if (!F_ISSET(&t->bt_cursor, CURS_INIT))
+ goto einval;
+ if (t->bt_nrecs == 0)
+ return (RET_SPECIAL);
+ status = rec_rdelete(t, t->bt_cursor.rcursor - 1);
+ if (status == RET_SUCCESS)
+ --t->bt_cursor.rcursor;
+ break;
+ default:
+einval: errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ if (status == RET_SUCCESS)
+ F_SET(t, B_MODIFIED | R_MODIFIED);
+ return (status);
+}
+
+/*
+ * REC_RDELETE -- Delete the data matching the specified key.
+ *
+ * Parameters:
+ * tree: tree
+ * nrec: record to delete
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+static int
+rec_rdelete(BTREE *t, recno_t nrec)
+{
+ EPG *e;
+ PAGE *h;
+ int status;
+
+ /* Find the record; __rec_search pins the page. */
+ if ((e = __rec_search(t, nrec, SDELETE)) == NULL)
+ return (RET_ERROR);
+
+ /* Delete the record. */
+ h = e->page;
+ status = __rec_dleaf(t, h, e->index);
+ if (status != RET_SUCCESS) {
+ mpool_put(t->bt_mp, h, 0);
+ return (status);
+ }
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ return (RET_SUCCESS);
+}
+
+/*
+ * __REC_DLEAF -- Delete a single record from a recno leaf page.
+ *
+ * Parameters:
+ * t: tree
+ * idx: index on current page to delete
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_dleaf(BTREE *t, PAGE *h, u_int32_t idx)
+{
+ RLEAF *rl;
+ indx_t *ip, cnt, offset;
+ u_int32_t nbytes;
+ char *from;
+ void *to;
+
+ /*
+ * Delete a record from a recno leaf page. Internal records are never
+ * deleted from internal pages, regardless of the records that caused
+ * them to be added being deleted. Pages made empty by deletion are
+ * not reclaimed. They are, however, made available for reuse.
+ *
+ * Pack the remaining entries at the end of the page, shift the indices
+ * down, overwriting the deleted record and its index. If the record
+ * uses overflow pages, make them available for reuse.
+ */
+ to = rl = GETRLEAF(h, idx);
+ if (rl->flags & P_BIGDATA && __ovfl_delete(t, rl->bytes) == RET_ERROR)
+ return (RET_ERROR);
+ nbytes = NRLEAF(rl);
+
+ /*
+ * Compress the key/data pairs. Compress and adjust the [BR]LEAF
+ * offsets. Reset the headers.
+ */
+ from = (char *)h + h->upper;
+ memmove(from + nbytes, from, (char *)to - from);
+ h->upper += nbytes;
+
+ offset = h->linp[idx];
+ for (cnt = &h->linp[idx] - (ip = &h->linp[0]); cnt--; ++ip)
+ if (ip[0] < offset)
+ ip[0] += nbytes;
+ for (cnt = &h->linp[NEXTINDEX(h)] - ip; --cnt; ++ip)
+ ip[0] = ip[1] < offset ? ip[1] + nbytes : ip[1];
+ h->lower -= sizeof(indx_t);
+ --t->bt_nrecs;
+ return (RET_SUCCESS);
+}
diff --git a/lib/libc/db/recno/rec_get.c b/lib/libc/db/recno/rec_get.c
new file mode 100644
index 0000000..b543d47
--- /dev/null
+++ b/lib/libc/db/recno/rec_get.c
@@ -0,0 +1,291 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_get.c 8.9 (Berkeley) 8/18/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_GET -- Get a record from the btree.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ * key: key to find
+ * data: data to return
+ * flag: currently unused
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key not found.
+ */
+int
+__rec_get(const DB *dbp, const DBT *key, DBT *data, u_int flags)
+{
+ BTREE *t;
+ EPG *e;
+ recno_t nrec;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* Get currently doesn't take any flags, and keys of 0 are illegal. */
+ if (flags || (nrec = *(recno_t *)key->data) == 0) {
+ errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ /*
+ * If we haven't seen this record yet, try to find it in the
+ * original file.
+ */
+ if (nrec > t->bt_nrecs) {
+ if (F_ISSET(t, R_EOF | R_INMEM))
+ return (RET_SPECIAL);
+ if ((status = t->bt_irec(t, nrec)) != RET_SUCCESS)
+ return (status);
+ }
+
+ --nrec;
+ if ((e = __rec_search(t, nrec, SEARCH)) == NULL)
+ return (RET_ERROR);
+
+ status = __rec_ret(t, e, 0, NULL, data);
+ if (F_ISSET(t, B_DB_LOCK))
+ mpool_put(t->bt_mp, e->page, 0);
+ else
+ t->bt_pinned = e->page;
+ return (status);
+}
+
+/*
+ * __REC_FPIPE -- Get fixed length records from a pipe.
+ *
+ * Parameters:
+ * t: tree
+ * cnt: records to read
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_fpipe(BTREE *t, recno_t top)
+{
+ DBT data;
+ recno_t nrec;
+ size_t len;
+ int ch;
+ u_char *p;
+
+ if (t->bt_rdata.size < t->bt_reclen) {
+ t->bt_rdata.data = reallocf(t->bt_rdata.data, t->bt_reclen);
+ if (t->bt_rdata.data == NULL)
+ return (RET_ERROR);
+ t->bt_rdata.size = t->bt_reclen;
+ }
+ data.data = t->bt_rdata.data;
+ data.size = t->bt_reclen;
+
+ for (nrec = t->bt_nrecs; nrec < top;) {
+ len = t->bt_reclen;
+ for (p = t->bt_rdata.data;; *p++ = ch)
+ if ((ch = getc(t->bt_rfp)) == EOF || !--len) {
+ if (ch != EOF)
+ *p = ch;
+ if (len != 0)
+ memset(p, t->bt_bval, len);
+ if (__rec_iput(t,
+ nrec, &data, 0) != RET_SUCCESS)
+ return (RET_ERROR);
+ ++nrec;
+ break;
+ }
+ if (ch == EOF)
+ break;
+ }
+ if (nrec < top) {
+ F_SET(t, R_EOF);
+ return (RET_SPECIAL);
+ }
+ return (RET_SUCCESS);
+}
+
+/*
+ * __REC_VPIPE -- Get variable length records from a pipe.
+ *
+ * Parameters:
+ * t: tree
+ * cnt: records to read
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_vpipe(BTREE *t, recno_t top)
+{
+ DBT data;
+ recno_t nrec;
+ size_t len;
+ size_t sz;
+ int bval, ch;
+ u_char *p;
+
+ bval = t->bt_bval;
+ for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+ for (p = t->bt_rdata.data,
+ sz = t->bt_rdata.size;; *p++ = ch, --sz) {
+ if ((ch = getc(t->bt_rfp)) == EOF || ch == bval) {
+ data.data = t->bt_rdata.data;
+ data.size = p - (u_char *)t->bt_rdata.data;
+ if (ch == EOF && data.size == 0)
+ break;
+ if (__rec_iput(t, nrec, &data, 0)
+ != RET_SUCCESS)
+ return (RET_ERROR);
+ break;
+ }
+ if (sz == 0) {
+ len = p - (u_char *)t->bt_rdata.data;
+ t->bt_rdata.size += (sz = 256);
+ t->bt_rdata.data = reallocf(t->bt_rdata.data, t->bt_rdata.size);
+ if (t->bt_rdata.data == NULL)
+ return (RET_ERROR);
+ p = (u_char *)t->bt_rdata.data + len;
+ }
+ }
+ if (ch == EOF)
+ break;
+ }
+ if (nrec < top) {
+ F_SET(t, R_EOF);
+ return (RET_SPECIAL);
+ }
+ return (RET_SUCCESS);
+}
+
+/*
+ * __REC_FMAP -- Get fixed length records from a file.
+ *
+ * Parameters:
+ * t: tree
+ * cnt: records to read
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_fmap(BTREE *t, recno_t top)
+{
+ DBT data;
+ recno_t nrec;
+ u_char *sp, *ep, *p;
+ size_t len;
+
+ if (t->bt_rdata.size < t->bt_reclen) {
+ t->bt_rdata.data = reallocf(t->bt_rdata.data, t->bt_reclen);
+ if (t->bt_rdata.data == NULL)
+ return (RET_ERROR);
+ t->bt_rdata.size = t->bt_reclen;
+ }
+ data.data = t->bt_rdata.data;
+ data.size = t->bt_reclen;
+
+ sp = (u_char *)t->bt_cmap;
+ ep = (u_char *)t->bt_emap;
+ for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+ if (sp >= ep) {
+ F_SET(t, R_EOF);
+ return (RET_SPECIAL);
+ }
+ len = t->bt_reclen;
+ for (p = t->bt_rdata.data;
+ sp < ep && len > 0; *p++ = *sp++, --len);
+ if (len != 0)
+ memset(p, t->bt_bval, len);
+ if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
+ return (RET_ERROR);
+ }
+ t->bt_cmap = (caddr_t)sp;
+ return (RET_SUCCESS);
+}
+
+/*
+ * __REC_VMAP -- Get variable length records from a file.
+ *
+ * Parameters:
+ * t: tree
+ * cnt: records to read
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_vmap(BTREE *t, recno_t top)
+{
+ DBT data;
+ u_char *sp, *ep;
+ recno_t nrec;
+ int bval;
+
+ sp = (u_char *)t->bt_cmap;
+ ep = (u_char *)t->bt_emap;
+ bval = t->bt_bval;
+
+ for (nrec = t->bt_nrecs; nrec < top; ++nrec) {
+ if (sp >= ep) {
+ F_SET(t, R_EOF);
+ return (RET_SPECIAL);
+ }
+ for (data.data = sp; sp < ep && *sp != bval; ++sp);
+ data.size = sp - (u_char *)data.data;
+ if (__rec_iput(t, nrec, &data, 0) != RET_SUCCESS)
+ return (RET_ERROR);
+ ++sp;
+ }
+ t->bt_cmap = (caddr_t)sp;
+ return (RET_SUCCESS);
+}
diff --git a/lib/libc/db/recno/rec_open.c b/lib/libc/db/recno/rec_open.c
new file mode 100644
index 0000000..dd286c0
--- /dev/null
+++ b/lib/libc/db/recno/rec_open.c
@@ -0,0 +1,238 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_open.c 8.10 (Berkeley) 9/1/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+#include "recno.h"
+
+DB *
+__rec_open(const char *fname, int flags, int mode, const RECNOINFO *openinfo,
+ int dflags)
+{
+ BTREE *t;
+ BTREEINFO btopeninfo;
+ DB *dbp;
+ PAGE *h;
+ struct stat sb;
+ int rfd, sverrno;
+
+ /* Open the user's file -- if this fails, we're done. */
+ if (fname != NULL && (rfd = _open(fname, flags, mode)) < 0)
+ return (NULL);
+
+ /* Create a btree in memory (backed by disk). */
+ dbp = NULL;
+ if (openinfo) {
+ if (openinfo->flags & ~(R_FIXEDLEN | R_NOKEY | R_SNAPSHOT))
+ goto einval;
+ btopeninfo.flags = 0;
+ btopeninfo.cachesize = openinfo->cachesize;
+ btopeninfo.maxkeypage = 0;
+ btopeninfo.minkeypage = 0;
+ btopeninfo.psize = openinfo->psize;
+ btopeninfo.compare = NULL;
+ btopeninfo.prefix = NULL;
+ btopeninfo.lorder = openinfo->lorder;
+ dbp = __bt_open(openinfo->bfname,
+ O_RDWR, S_IRUSR | S_IWUSR, &btopeninfo, dflags);
+ } else
+ dbp = __bt_open(NULL, O_RDWR, S_IRUSR | S_IWUSR, NULL, dflags);
+ if (dbp == NULL)
+ goto err;
+
+ /*
+ * Some fields in the tree structure are recno specific. Fill them
+ * in and make the btree structure look like a recno structure. We
+ * don't change the bt_ovflsize value, it's close enough and slightly
+ * bigger.
+ */
+ t = dbp->internal;
+ if (openinfo) {
+ if (openinfo->flags & R_FIXEDLEN) {
+ F_SET(t, R_FIXLEN);
+ t->bt_reclen = openinfo->reclen;
+ if (t->bt_reclen == 0)
+ goto einval;
+ }
+ t->bt_bval = openinfo->bval;
+ } else
+ t->bt_bval = '\n';
+
+ F_SET(t, R_RECNO);
+ if (fname == NULL)
+ F_SET(t, R_EOF | R_INMEM);
+ else
+ t->bt_rfd = rfd;
+
+ if (fname != NULL) {
+ /*
+ * In 4.4BSD, stat(2) returns true for ISSOCK on pipes.
+ * Unfortunately, that's not portable, so we use lseek
+ * and check the errno values.
+ */
+ errno = 0;
+ if (lseek(rfd, (off_t)0, SEEK_CUR) == -1 && errno == ESPIPE) {
+ switch (flags & O_ACCMODE) {
+ case O_RDONLY:
+ F_SET(t, R_RDONLY);
+ break;
+ default:
+ goto einval;
+ }
+slow: if ((t->bt_rfp = fdopen(rfd, "r")) == NULL)
+ goto err;
+ F_SET(t, R_CLOSEFP);
+ t->bt_irec =
+ F_ISSET(t, R_FIXLEN) ? __rec_fpipe : __rec_vpipe;
+ } else {
+ switch (flags & O_ACCMODE) {
+ case O_RDONLY:
+ F_SET(t, R_RDONLY);
+ break;
+ case O_RDWR:
+ break;
+ default:
+ goto einval;
+ }
+
+ if (_fstat(rfd, &sb))
+ goto err;
+ /*
+ * Kluge -- we'd like to test to see if the file is too
+ * big to mmap. Since, we don't know what size or type
+ * off_t's or size_t's are, what the largest unsigned
+ * integral type is, or what random insanity the local
+ * C compiler will perpetrate, doing the comparison in
+ * a portable way is flatly impossible. Hope that mmap
+ * fails if the file is too large.
+ */
+ if (sb.st_size == 0)
+ F_SET(t, R_EOF);
+ else {
+#ifdef MMAP_NOT_AVAILABLE
+ /*
+ * XXX
+ * Mmap doesn't work correctly on many current
+ * systems. In particular, it can fail subtly,
+ * with cache coherency problems. Don't use it
+ * for now.
+ */
+ t->bt_msize = sb.st_size;
+ if ((t->bt_smap = mmap(NULL, t->bt_msize,
+ PROT_READ, MAP_PRIVATE, rfd,
+ (off_t)0)) == MAP_FAILED)
+ goto slow;
+ t->bt_cmap = t->bt_smap;
+ t->bt_emap = t->bt_smap + sb.st_size;
+ t->bt_irec = F_ISSET(t, R_FIXLEN) ?
+ __rec_fmap : __rec_vmap;
+ F_SET(t, R_MEMMAPPED);
+#else
+ goto slow;
+#endif
+ }
+ }
+ }
+
+ /* Use the recno routines. */
+ dbp->close = __rec_close;
+ dbp->del = __rec_delete;
+ dbp->fd = __rec_fd;
+ dbp->get = __rec_get;
+ dbp->put = __rec_put;
+ dbp->seq = __rec_seq;
+ dbp->sync = __rec_sync;
+
+ /* If the root page was created, reset the flags. */
+ if ((h = mpool_get(t->bt_mp, P_ROOT, 0)) == NULL)
+ goto err;
+ if ((h->flags & P_TYPE) == P_BLEAF) {
+ F_CLR(h, P_TYPE);
+ F_SET(h, P_RLEAF);
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ } else
+ mpool_put(t->bt_mp, h, 0);
+
+ if (openinfo && openinfo->flags & R_SNAPSHOT &&
+ !F_ISSET(t, R_EOF | R_INMEM) &&
+ t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+ goto err;
+ return (dbp);
+
+einval: errno = EINVAL;
+err: sverrno = errno;
+ if (dbp != NULL)
+ (void)__bt_close(dbp);
+ if (fname != NULL)
+ (void)_close(rfd);
+ errno = sverrno;
+ return (NULL);
+}
+
+int
+__rec_fd(const DB *dbp)
+{
+ BTREE *t;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /* In-memory database can't have a file descriptor. */
+ if (F_ISSET(t, R_INMEM)) {
+ errno = ENOENT;
+ return (-1);
+ }
+ return (t->bt_rfd);
+}
diff --git a/lib/libc/db/recno/rec_put.c b/lib/libc/db/recno/rec_put.c
new file mode 100644
index 0000000..441cced
--- /dev/null
+++ b/lib/libc/db/recno/rec_put.c
@@ -0,0 +1,275 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_put.c 8.7 (Berkeley) 8/18/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_PUT -- Add a recno item to the tree.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ * key: key
+ * data: data
+ * flag: R_CURSOR, R_IAFTER, R_IBEFORE, R_NOOVERWRITE
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS and RET_SPECIAL if the key is
+ * already in the tree and R_NOOVERWRITE specified.
+ */
+int
+__rec_put(const DB *dbp, DBT *key, const DBT *data, u_int flags)
+{
+ BTREE *t;
+ DBT fdata, tdata;
+ recno_t nrec;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ /*
+ * If using fixed-length records, and the record is long, return
+ * EINVAL. If it's short, pad it out. Use the record data return
+ * memory, it's only short-term.
+ */
+ if (F_ISSET(t, R_FIXLEN) && data->size != t->bt_reclen) {
+ if (data->size > t->bt_reclen)
+ goto einval;
+
+ if (t->bt_rdata.size < t->bt_reclen) {
+ t->bt_rdata.data =
+ reallocf(t->bt_rdata.data, t->bt_reclen);
+ if (t->bt_rdata.data == NULL)
+ return (RET_ERROR);
+ t->bt_rdata.size = t->bt_reclen;
+ }
+ memmove(t->bt_rdata.data, data->data, data->size);
+ memset((char *)t->bt_rdata.data + data->size,
+ t->bt_bval, t->bt_reclen - data->size);
+ fdata.data = t->bt_rdata.data;
+ fdata.size = t->bt_reclen;
+ } else {
+ fdata.data = data->data;
+ fdata.size = data->size;
+ }
+
+ switch (flags) {
+ case R_CURSOR:
+ if (!F_ISSET(&t->bt_cursor, CURS_INIT))
+ goto einval;
+ nrec = t->bt_cursor.rcursor;
+ break;
+ case R_SETCURSOR:
+ if ((nrec = *(recno_t *)key->data) == 0)
+ goto einval;
+ break;
+ case R_IAFTER:
+ if ((nrec = *(recno_t *)key->data) == 0) {
+ nrec = 1;
+ flags = R_IBEFORE;
+ }
+ break;
+ case 0:
+ case R_IBEFORE:
+ if ((nrec = *(recno_t *)key->data) == 0)
+ goto einval;
+ break;
+ case R_NOOVERWRITE:
+ if ((nrec = *(recno_t *)key->data) == 0)
+ goto einval;
+ if (nrec <= t->bt_nrecs)
+ return (RET_SPECIAL);
+ break;
+ default:
+einval: errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ /*
+ * Make sure that records up to and including the put record are
+ * already in the database. If skipping records, create empty ones.
+ */
+ if (nrec > t->bt_nrecs) {
+ if (!F_ISSET(t, R_EOF | R_INMEM) &&
+ t->bt_irec(t, nrec) == RET_ERROR)
+ return (RET_ERROR);
+ if (nrec > t->bt_nrecs + 1) {
+ if (F_ISSET(t, R_FIXLEN)) {
+ if ((tdata.data =
+ (void *)malloc(t->bt_reclen)) == NULL)
+ return (RET_ERROR);
+ tdata.size = t->bt_reclen;
+ memset(tdata.data, t->bt_bval, tdata.size);
+ } else {
+ tdata.data = NULL;
+ tdata.size = 0;
+ }
+ while (nrec > t->bt_nrecs + 1)
+ if (__rec_iput(t,
+ t->bt_nrecs, &tdata, 0) != RET_SUCCESS)
+ return (RET_ERROR);
+ if (F_ISSET(t, R_FIXLEN))
+ free(tdata.data);
+ }
+ }
+
+ if ((status = __rec_iput(t, nrec - 1, &fdata, flags)) != RET_SUCCESS)
+ return (status);
+
+ switch (flags) {
+ case R_IAFTER:
+ nrec++;
+ break;
+ case R_SETCURSOR:
+ t->bt_cursor.rcursor = nrec;
+ break;
+ }
+
+ F_SET(t, R_MODIFIED);
+ return (__rec_ret(t, NULL, nrec, key, NULL));
+}
+
+/*
+ * __REC_IPUT -- Add a recno item to the tree.
+ *
+ * Parameters:
+ * t: tree
+ * nrec: record number
+ * data: data
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS
+ */
+int
+__rec_iput(BTREE *t, recno_t nrec, const DBT *data, u_int flags)
+{
+ DBT tdata;
+ EPG *e;
+ PAGE *h;
+ indx_t idx, nxtindex;
+ pgno_t pg;
+ u_int32_t nbytes;
+ int dflags, status;
+ char *dest, db[NOVFLSIZE];
+
+ /*
+ * If the data won't fit on a page, store it on indirect pages.
+ *
+ * XXX
+ * If the insert fails later on, these pages aren't recovered.
+ */
+ if (data->size > t->bt_ovflsize) {
+ if (__ovfl_put(t, data, &pg) == RET_ERROR)
+ return (RET_ERROR);
+ tdata.data = db;
+ tdata.size = NOVFLSIZE;
+ *(pgno_t *)db = pg;
+ *(u_int32_t *)(db + sizeof(pgno_t)) = data->size;
+ dflags = P_BIGDATA;
+ data = &tdata;
+ } else
+ dflags = 0;
+
+ /* __rec_search pins the returned page. */
+ if ((e = __rec_search(t, nrec,
+ nrec > t->bt_nrecs || flags == R_IAFTER || flags == R_IBEFORE ?
+ SINSERT : SEARCH)) == NULL)
+ return (RET_ERROR);
+
+ h = e->page;
+ idx = e->index;
+
+ /*
+ * Add the specified key/data pair to the tree. The R_IAFTER and
+ * R_IBEFORE flags insert the key after/before the specified key.
+ *
+ * Pages are split as required.
+ */
+ switch (flags) {
+ case R_IAFTER:
+ ++idx;
+ break;
+ case R_IBEFORE:
+ break;
+ default:
+ if (nrec < t->bt_nrecs &&
+ __rec_dleaf(t, h, idx) == RET_ERROR) {
+ mpool_put(t->bt_mp, h, 0);
+ return (RET_ERROR);
+ }
+ break;
+ }
+
+ /*
+ * If not enough room, split the page. The split code will insert
+ * the key and data and unpin the current page. If inserting into
+ * the offset array, shift the pointers up.
+ */
+ nbytes = NRLEAFDBT(data->size);
+ if ((u_int32_t)(h->upper - h->lower) < nbytes + sizeof(indx_t)) {
+ status = __bt_split(t, h, NULL, data, dflags, nbytes, idx);
+ if (status == RET_SUCCESS)
+ ++t->bt_nrecs;
+ return (status);
+ }
+
+ if (idx < (nxtindex = NEXTINDEX(h)))
+ memmove(h->linp + idx + 1, h->linp + idx,
+ (nxtindex - idx) * sizeof(indx_t));
+ h->lower += sizeof(indx_t);
+
+ h->linp[idx] = h->upper -= nbytes;
+ dest = (char *)h + h->upper;
+ WR_RLEAF(dest, data, dflags);
+
+ ++t->bt_nrecs;
+ F_SET(t, B_MODIFIED);
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+
+ return (RET_SUCCESS);
+}
diff --git a/lib/libc/db/recno/rec_search.c b/lib/libc/db/recno/rec_search.c
new file mode 100644
index 0000000..8115e0f
--- /dev/null
+++ b/lib/libc/db/recno/rec_search.c
@@ -0,0 +1,121 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_search.c 8.4 (Berkeley) 7/14/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdio.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_SEARCH -- Search a btree for a key.
+ *
+ * Parameters:
+ * t: tree to search
+ * recno: key to find
+ * op: search operation
+ *
+ * Returns:
+ * EPG for matching record, if any, or the EPG for the location of the
+ * key, if it were inserted into the tree.
+ *
+ * Returns:
+ * The EPG for matching record, if any, or the EPG for the location
+ * of the key, if it were inserted into the tree, is entered into
+ * the bt_cur field of the tree. A pointer to the field is returned.
+ */
+EPG *
+__rec_search(BTREE *t, recno_t recno, enum SRCHOP op)
+{
+ indx_t idx;
+ PAGE *h;
+ EPGNO *parent;
+ RINTERNAL *r;
+ pgno_t pg;
+ indx_t top;
+ recno_t total;
+ int sverrno;
+
+ BT_CLR(t);
+ for (pg = P_ROOT, total = 0;;) {
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL)
+ goto err;
+ if (h->flags & P_RLEAF) {
+ t->bt_cur.page = h;
+ t->bt_cur.index = recno - total;
+ return (&t->bt_cur);
+ }
+ for (idx = 0, top = NEXTINDEX(h);;) {
+ r = GETRINTERNAL(h, idx);
+ if (++idx == top || total + r->nrecs > recno)
+ break;
+ total += r->nrecs;
+ }
+
+ BT_PUSH(t, pg, idx - 1);
+
+ pg = r->pgno;
+ switch (op) {
+ case SDELETE:
+ --GETRINTERNAL(h, (idx - 1))->nrecs;
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ break;
+ case SINSERT:
+ ++GETRINTERNAL(h, (idx - 1))->nrecs;
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ break;
+ case SEARCH:
+ mpool_put(t->bt_mp, h, 0);
+ break;
+ }
+
+ }
+ /* Try and recover the tree. */
+err: sverrno = errno;
+ if (op != SEARCH)
+ while ((parent = BT_POP(t)) != NULL) {
+ if ((h = mpool_get(t->bt_mp, parent->pgno, 0)) == NULL)
+ break;
+ if (op == SINSERT)
+ --GETRINTERNAL(h, parent->index)->nrecs;
+ else
+ ++GETRINTERNAL(h, parent->index)->nrecs;
+ mpool_put(t->bt_mp, h, MPOOL_DIRTY);
+ }
+ errno = sverrno;
+ return (NULL);
+}
diff --git a/lib/libc/db/recno/rec_seq.c b/lib/libc/db/recno/rec_seq.c
new file mode 100644
index 0000000..42d98d7
--- /dev/null
+++ b/lib/libc/db/recno/rec_seq.c
@@ -0,0 +1,127 @@
+/*-
+ * Copyright (c) 1991, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+/* XXX use __SCCSID */
+static char sccsid[] __unused = "@(#)rec_seq.c 8.3 (Berkeley) 7/14/94";
+#endif /* not lint */
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __REC_SEQ -- Recno sequential scan interface.
+ *
+ * Parameters:
+ * dbp: pointer to access method
+ * key: key for positioning and return value
+ * data: data return value
+ * flags: R_CURSOR, R_FIRST, R_LAST, R_NEXT, R_PREV.
+ *
+ * Returns:
+ * RET_ERROR, RET_SUCCESS or RET_SPECIAL if there's no next key.
+ */
+int
+__rec_seq(const DB *dbp, DBT *key, DBT *data, u_int flags)
+{
+ BTREE *t;
+ EPG *e;
+ recno_t nrec;
+ int status;
+
+ t = dbp->internal;
+
+ /* Toss any page pinned across calls. */
+ if (t->bt_pinned != NULL) {
+ mpool_put(t->bt_mp, t->bt_pinned, 0);
+ t->bt_pinned = NULL;
+ }
+
+ switch(flags) {
+ case R_CURSOR:
+ if ((nrec = *(recno_t *)key->data) == 0)
+ goto einval;
+ break;
+ case R_NEXT:
+ if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+ nrec = t->bt_cursor.rcursor + 1;
+ break;
+ }
+ /* FALLTHROUGH */
+ case R_FIRST:
+ nrec = 1;
+ break;
+ case R_PREV:
+ if (F_ISSET(&t->bt_cursor, CURS_INIT)) {
+ if ((nrec = t->bt_cursor.rcursor - 1) == 0)
+ return (RET_SPECIAL);
+ break;
+ }
+ /* FALLTHROUGH */
+ case R_LAST:
+ if (!F_ISSET(t, R_EOF | R_INMEM) &&
+ t->bt_irec(t, MAX_REC_NUMBER) == RET_ERROR)
+ return (RET_ERROR);
+ nrec = t->bt_nrecs;
+ break;
+ default:
+einval: errno = EINVAL;
+ return (RET_ERROR);
+ }
+
+ if (t->bt_nrecs == 0 || nrec > t->bt_nrecs) {
+ if (!F_ISSET(t, R_EOF | R_INMEM) &&
+ (status = t->bt_irec(t, nrec)) != RET_SUCCESS)
+ return (status);
+ if (t->bt_nrecs == 0 || nrec > t->bt_nrecs)
+ return (RET_SPECIAL);
+ }
+
+ if ((e = __rec_search(t, nrec - 1, SEARCH)) == NULL)
+ return (RET_ERROR);
+
+ F_SET(&t->bt_cursor, CURS_INIT);
+ t->bt_cursor.rcursor = nrec;
+
+ status = __rec_ret(t, e, nrec, key, data);
+ if (F_ISSET(t, B_DB_LOCK))
+ mpool_put(t->bt_mp, e->page, 0);
+ else
+ t->bt_pinned = e->page;
+ return (status);
+}
diff --git a/lib/libc/db/recno/rec_utils.c b/lib/libc/db/recno/rec_utils.c
new file mode 100644
index 0000000..39285a5
--- /dev/null
+++ b/lib/libc/db/recno/rec_utils.c
@@ -0,0 +1,112 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rec_utils.c 8.6 (Berkeley) 7/16/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <db.h>
+#include "recno.h"
+
+/*
+ * __rec_ret --
+ * Build return data.
+ *
+ * Parameters:
+ * t: tree
+ * e: key/data pair to be returned
+ * nrec: record number
+ * key: user's key structure
+ * data: user's data structure
+ *
+ * Returns:
+ * RET_SUCCESS, RET_ERROR.
+ */
+int
+__rec_ret(BTREE *t, EPG *e, recno_t nrec, DBT *key, DBT *data)
+{
+ RLEAF *rl;
+ void *p;
+
+ if (key == NULL)
+ goto dataonly;
+
+ /* We have to copy the key, it's not on the page. */
+ if (sizeof(recno_t) > t->bt_rkey.size) {
+ p = realloc(t->bt_rkey.data, sizeof(recno_t));
+ if (p == NULL)
+ return (RET_ERROR);
+ t->bt_rkey.data = p;
+ t->bt_rkey.size = sizeof(recno_t);
+ }
+ memmove(t->bt_rkey.data, &nrec, sizeof(recno_t));
+ key->size = sizeof(recno_t);
+ key->data = t->bt_rkey.data;
+
+dataonly:
+ if (data == NULL)
+ return (RET_SUCCESS);
+
+ /*
+ * We must copy big keys/data to make them contigous. Otherwise,
+ * leave the page pinned and don't copy unless the user specified
+ * concurrent access.
+ */
+ rl = GETRLEAF(e->page, e->index);
+ if (rl->flags & P_BIGDATA) {
+ if (__ovfl_get(t, rl->bytes,
+ &data->size, &t->bt_rdata.data, &t->bt_rdata.size))
+ return (RET_ERROR);
+ data->data = t->bt_rdata.data;
+ } else if (F_ISSET(t, B_DB_LOCK)) {
+ /* Use +1 in case the first record retrieved is 0 length. */
+ if (rl->dsize + 1 > t->bt_rdata.size) {
+ p = realloc(t->bt_rdata.data, rl->dsize + 1);
+ if (p == NULL)
+ return (RET_ERROR);
+ t->bt_rdata.data = p;
+ t->bt_rdata.size = rl->dsize + 1;
+ }
+ memmove(t->bt_rdata.data, rl->bytes, rl->dsize);
+ data->size = rl->dsize;
+ data->data = t->bt_rdata.data;
+ } else {
+ data->size = rl->dsize;
+ data->data = rl->bytes;
+ }
+ return (RET_SUCCESS);
+}
diff --git a/lib/libc/db/recno/recno.h b/lib/libc/db/recno/recno.h
new file mode 100644
index 0000000..5c56170
--- /dev/null
+++ b/lib/libc/db/recno/recno.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)recno.h 8.1 (Berkeley) 6/4/93
+ * $FreeBSD$
+ */
+
+enum SRCHOP { SDELETE, SINSERT, SEARCH}; /* Rec_search operation. */
+
+#include "../btree/btree.h"
+#include "extern.h"
diff --git a/lib/libc/db/test/Makefile b/lib/libc/db/test/Makefile
new file mode 100644
index 0000000..712ad62
--- /dev/null
+++ b/lib/libc/db/test/Makefile
@@ -0,0 +1,24 @@
+# @(#)Makefile 8.15 (Berkeley) 7/28/94
+# $FreeBSD$
+
+PROG= dbtest
+OBJS= dbtest.o strerror.o
+
+# Uncomment the STAT line get hash and btree statistical use info. This
+# also forces ld to load the btree debug functions for use by gdb, which
+# is useful. The db library has to be compiled with -DSTATISTICS as well.
+INC= -I${PORTDIR}/include -I${PORTDIR}
+OORG= -g
+#STAT= -DSTATISTICS
+CFLAGS+=-D__DBINTERFACE_PRIVATE -DDEBUG ${STAT} ${OORG} ${INC}
+
+dbtest: ${OBJS} ${PORTDIR}/libdb.a
+ ${CC} -o ${.TARGET} ${OBJS} ${PORTDIR}/libdb.a
+
+strerror.o: ${PORTDIR}/clib/strerror.c
+ ${CC} -c ${PORTDIR}/clib/strerror.c
+
+clean:
+ rm -f dbtest.core gmon.out ${OBJS} ${PROG} t1 t2 t3
+
+${OBJS}: Makefile
diff --git a/lib/libc/db/test/README b/lib/libc/db/test/README
new file mode 100644
index 0000000..0c0cd13
--- /dev/null
+++ b/lib/libc/db/test/README
@@ -0,0 +1,74 @@
+# @(#)README 8.8 (Berkeley) 7/31/94
+
+To build this portably, try something like:
+
+ make PORTDIR="../PORT/MACH"
+
+where MACH is the machine, i.e. "sunos.4.1.1".
+
+To run the tests, enter "sh run.test". If your system dictionary isn't
+in /usr/share/dict/words, edit run.test to reflect the correct place.
+
+Fairly large files (the command files) are built in this directory during
+the test runs, and even larger files (the database files) are created in
+"/var/tmp". If the latter directory doesn't exist, set the environmental
+variable TMPDIR to a directory where the files can be built.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+The script file consists of lines with an initial character which is
+the command for that line, or an initial character indicating a key
+or data entry for a previous command.
+
+Legal command characters are as follows:
+
+c: compare a record
+ + must be followed by [kK][dD]; the data value in the database
+ associated with the specified key is compared to the specified
+ data value.
+e: echo a string
+ + writes out the rest of the line into the output file; if the
+ last character is not a carriage-return, a newline is appended.
+f: set the flags for the next command
+ + no value zero's the flags
+g: do a get command
+ + must be followed by [kK]
+ + writes out the retrieved data DBT.
+o [r]: dump [reverse]
+ + dump the database out, if 'r' is set, in reverse order.
+p: do a put command
+ + must be followed by [kK][dD]
+r: do a del command
+ + must be followed by [kK] unless R_CURSOR flag set.
+S: sync the database
+s: do a seq command
+ + must be followed by [kK] if R_CURSOR flag set.
+ + writes out the retrieved data DBT.
+
+Legal key/data characters are as follows:
+
+D [file]: data file
+ + set the current data value to the contents of the file
+d [data]:
+ + set the current key value to the contents of the line.
+K [file]: key file
+ + set the current key value to the contents of the file
+k [data]:
+ + set the current key value to the contents of the line.
+
+Blank lines, lines with leading white space, and lines with leading
+hash marks (#) are ignored.
+
+Options to dbtest are as follows:
+
+ -d: Set the DB_LOCK flag.
+ -f: Use the file argument as the database file.
+ -i: Use the rest of the argument to set elements in the info
+ structure. If the type is btree, then "-i cachesize=10240"
+ will set BTREEINFO.cachesize to 10240.
+ -o: The rest of the argument is the output file instead of
+ using stdout.
+ -s: Don't delete the database file before opening it, i.e.
+ use the database file from a previous run.
+
+Dbtest requires two arguments, the type of access "hash", "recno"
+or "btree", and the script name or "-" to indicate stdin.
diff --git a/lib/libc/db/test/btree.tests/main.c b/lib/libc/db/test/btree.tests/main.c
new file mode 100644
index 0000000..ec17b58
--- /dev/null
+++ b/lib/libc/db/test/btree.tests/main.c
@@ -0,0 +1,763 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Olson.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)main.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <fcntl.h>
+#include <db.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+#include "btree.h"
+
+typedef struct cmd_table {
+ char *cmd;
+ int nargs;
+ int rconv;
+ void (*func)(DB *, char **);
+ char *usage, *descrip;
+} cmd_table;
+
+int stopstop;
+DB *globaldb;
+
+void append(DB *, char **);
+void bstat(DB *, char **);
+void cursor(DB *, char **);
+void delcur(DB *, char **);
+void delete(DB *, char **);
+void dump(DB *, char **);
+void first(DB *, char **);
+void get(DB *, char **);
+void help(DB *, char **);
+void iafter(DB *, char **);
+void ibefore(DB *, char **);
+void icursor(DB *, char **);
+void insert(DB *, char **);
+void keydata(DBT *, DBT *);
+void last(DB *, char **);
+void list(DB *, char **);
+void load(DB *, char **);
+void mstat(DB *, char **);
+void next(DB *, char **);
+int parse(char *, char **, int);
+void previous(DB *, char **);
+void show(DB *, char **);
+void usage(void);
+void user(DB *);
+
+cmd_table commands[] = {
+ "?", 0, 0, help, "help", NULL,
+ "a", 2, 1, append, "append key def", "append key with data def",
+ "b", 0, 0, bstat, "bstat", "stat btree",
+ "c", 1, 1, cursor, "cursor word", "move cursor to word",
+ "delc", 0, 0, delcur, "delcur", "delete key the cursor references",
+ "dele", 1, 1, delete, "delete word", "delete word",
+ "d", 0, 0, dump, "dump", "dump database",
+ "f", 0, 0, first, "first", "move cursor to first record",
+ "g", 1, 1, get, "get key", "locate key",
+ "h", 0, 0, help, "help", "print command summary",
+ "ia", 2, 1, iafter, "iafter key data", "insert data after key",
+ "ib", 2, 1, ibefore, "ibefore key data", "insert data before key",
+ "ic", 2, 1, icursor, "icursor key data", "replace cursor",
+ "in", 2, 1, insert, "insert key def", "insert key with data def",
+ "la", 0, 0, last, "last", "move cursor to last record",
+ "li", 1, 1, list, "list file", "list to a file",
+ "loa", 1, 0, load, "load file", NULL,
+ "loc", 1, 1, get, "get key", NULL,
+ "m", 0, 0, mstat, "mstat", "stat memory pool",
+ "n", 0, 0, next, "next", "move cursor forward one record",
+ "p", 0, 0, previous, "previous", "move cursor back one record",
+ "q", 0, 0, NULL, "quit", "quit",
+ "sh", 1, 0, show, "show page", "dump a page",
+ { NULL },
+};
+
+int recno; /* use record numbers */
+char *dict = "words"; /* default dictionary */
+char *progname;
+
+int
+main(argc, argv)
+ int argc;
+ char **argv;
+{
+ int c;
+ DB *db;
+ BTREEINFO b;
+
+ progname = *argv;
+
+ b.flags = 0;
+ b.cachesize = 0;
+ b.maxkeypage = 0;
+ b.minkeypage = 0;
+ b.psize = 0;
+ b.compare = NULL;
+ b.prefix = NULL;
+ b.lorder = 0;
+
+ while ((c = getopt(argc, argv, "bc:di:lp:ru")) != -1) {
+ switch (c) {
+ case 'b':
+ b.lorder = BIG_ENDIAN;
+ break;
+ case 'c':
+ b.cachesize = atoi(optarg);
+ break;
+ case 'd':
+ b.flags |= R_DUP;
+ break;
+ case 'i':
+ dict = optarg;
+ break;
+ case 'l':
+ b.lorder = LITTLE_ENDIAN;
+ break;
+ case 'p':
+ b.psize = atoi(optarg);
+ break;
+ case 'r':
+ recno = 1;
+ break;
+ case 'u':
+ b.flags = 0;
+ break;
+ default:
+ usage();
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (recno)
+ db = dbopen(*argv == NULL ? NULL : *argv, O_RDWR,
+ 0, DB_RECNO, NULL);
+ else
+ db = dbopen(*argv == NULL ? NULL : *argv, O_CREAT|O_RDWR,
+ 0600, DB_BTREE, &b);
+
+ if (db == NULL) {
+ (void)fprintf(stderr, "dbopen: %s\n", strerror(errno));
+ exit(1);
+ }
+ globaldb = db;
+ user(db);
+ exit(0);
+ /* NOTREACHED */
+}
+
+void
+user(db)
+ DB *db;
+{
+ FILE *ifp;
+ int argc, i, last;
+ char *lbuf, *argv[4], buf[512];
+
+ if ((ifp = fopen("/dev/tty", "r")) == NULL) {
+ (void)fprintf(stderr,
+ "/dev/tty: %s\n", strerror(errno));
+ exit(1);
+ }
+ for (last = 0;;) {
+ (void)printf("> ");
+ (void)fflush(stdout);
+ if ((lbuf = fgets(&buf[0], 512, ifp)) == NULL)
+ break;
+ if (lbuf[0] == '\n') {
+ i = last;
+ goto uselast;
+ }
+ lbuf[strlen(lbuf) - 1] = '\0';
+
+ if (lbuf[0] == 'q')
+ break;
+
+ argc = parse(lbuf, &argv[0], 3);
+ if (argc == 0)
+ continue;
+
+ for (i = 0; commands[i].cmd != NULL; i++)
+ if (strncmp(commands[i].cmd, argv[0],
+ strlen(commands[i].cmd)) == 0)
+ break;
+
+ if (commands[i].cmd == NULL) {
+ (void)fprintf(stderr,
+ "%s: command unknown ('help' for help)\n", lbuf);
+ continue;
+ }
+
+ if (commands[i].nargs != argc - 1) {
+ (void)fprintf(stderr, "usage: %s\n", commands[i].usage);
+ continue;
+ }
+
+ if (recno && commands[i].rconv) {
+ static recno_t nlong;
+ nlong = atoi(argv[1]);
+ argv[1] = (char *)&nlong;
+ }
+uselast: last = i;
+ (*commands[i].func)(db, argv);
+ }
+ if ((db->sync)(db) == RET_ERROR)
+ perror("dbsync");
+ else if ((db->close)(db) == RET_ERROR)
+ perror("dbclose");
+}
+
+int
+parse(lbuf, argv, maxargc)
+ char *lbuf, **argv;
+ int maxargc;
+{
+ int argc = 0;
+ char *c;
+
+ c = lbuf;
+ while (isspace(*c))
+ c++;
+ while (*c != '\0' && argc < maxargc) {
+ *argv++ = c;
+ argc++;
+ while (!isspace(*c) && *c != '\0') {
+ c++;
+ }
+ while (isspace(*c))
+ *c++ = '\0';
+ }
+ return (argc);
+}
+
+void
+append(db, argv)
+ DB *db;
+ char **argv;
+{
+ DBT key, data;
+ int status;
+
+ if (!recno) {
+ (void)fprintf(stderr,
+ "append only available for recno db's.\n");
+ return;
+ }
+ key.data = argv[1];
+ key.size = sizeof(recno_t);
+ data.data = argv[2];
+ data.size = strlen(data.data);
+ status = (db->put)(db, &key, &data, R_APPEND);
+ switch (status) {
+ case RET_ERROR:
+ perror("append/put");
+ break;
+ case RET_SPECIAL:
+ (void)printf("%s (duplicate key)\n", argv[1]);
+ break;
+ case RET_SUCCESS:
+ break;
+ }
+}
+
+void
+cursor(db, argv)
+ DB *db;
+ char **argv;
+{
+ DBT data, key;
+ int status;
+
+ key.data = argv[1];
+ if (recno)
+ key.size = sizeof(recno_t);
+ else
+ key.size = strlen(argv[1]) + 1;
+ status = (*db->seq)(db, &key, &data, R_CURSOR);
+ switch (status) {
+ case RET_ERROR:
+ perror("cursor/seq");
+ break;
+ case RET_SPECIAL:
+ (void)printf("key not found\n");
+ break;
+ case RET_SUCCESS:
+ keydata(&key, &data);
+ break;
+ }
+}
+
+void
+delcur(db, argv)
+ DB *db;
+ char **argv;
+{
+ int status;
+
+ status = (*db->del)(db, NULL, R_CURSOR);
+
+ if (status == RET_ERROR)
+ perror("delcur/del");
+}
+
+void
+delete(db, argv)
+ DB *db;
+ char **argv;
+{
+ DBT key;
+ int status;
+
+ key.data = argv[1];
+ if (recno)
+ key.size = sizeof(recno_t);
+ else
+ key.size = strlen(argv[1]) + 1;
+
+ status = (*db->del)(db, &key, 0);
+ switch (status) {
+ case RET_ERROR:
+ perror("delete/del");
+ break;
+ case RET_SPECIAL:
+ (void)printf("key not found\n");
+ break;
+ case RET_SUCCESS:
+ break;
+ }
+}
+
+void
+dump(db, argv)
+ DB *db;
+ char **argv;
+{
+ __bt_dump(db);
+}
+
+void
+first(db, argv)
+ DB *db;
+ char **argv;
+{
+ DBT data, key;
+ int status;
+
+ status = (*db->seq)(db, &key, &data, R_FIRST);
+
+ switch (status) {
+ case RET_ERROR:
+ perror("first/seq");
+ break;
+ case RET_SPECIAL:
+ (void)printf("no more keys\n");
+ break;
+ case RET_SUCCESS:
+ keydata(&key, &data);
+ break;
+ }
+}
+
+void
+get(db, argv)
+ DB *db;
+ char **argv;
+{
+ DBT data, key;
+ int status;
+
+ key.data = argv[1];
+ if (recno)
+ key.size = sizeof(recno_t);
+ else
+ key.size = strlen(argv[1]) + 1;
+
+ status = (*db->get)(db, &key, &data, 0);
+
+ switch (status) {
+ case RET_ERROR:
+ perror("get/get");
+ break;
+ case RET_SPECIAL:
+ (void)printf("key not found\n");
+ break;
+ case RET_SUCCESS:
+ keydata(&key, &data);
+ break;
+ }
+}
+
+void
+help(db, argv)
+ DB *db;
+ char **argv;
+{
+ int i;
+
+ for (i = 0; commands[i].cmd; i++)
+ if (commands[i].descrip)
+ (void)printf("%s: %s\n",
+ commands[i].usage, commands[i].descrip);
+}
+
+void
+iafter(db, argv)
+ DB *db;
+ char **argv;
+{
+ DBT key, data;
+ int status;
+
+ if (!recno) {
+ (void)fprintf(stderr,
+ "iafter only available for recno db's.\n");
+ return;
+ }
+ key.data = argv[1];
+ key.size = sizeof(recno_t);
+ data.data = argv[2];
+ data.size = strlen(data.data);
+ status = (db->put)(db, &key, &data, R_IAFTER);
+ switch (status) {
+ case RET_ERROR:
+ perror("iafter/put");
+ break;
+ case RET_SPECIAL:
+ (void)printf("%s (duplicate key)\n", argv[1]);
+ break;
+ case RET_SUCCESS:
+ break;
+ }
+}
+
+void
+ibefore(db, argv)
+ DB *db;
+ char **argv;
+{
+ DBT key, data;
+ int status;
+
+ if (!recno) {
+ (void)fprintf(stderr,
+ "ibefore only available for recno db's.\n");
+ return;
+ }
+ key.data = argv[1];
+ key.size = sizeof(recno_t);
+ data.data = argv[2];
+ data.size = strlen(data.data);
+ status = (db->put)(db, &key, &data, R_IBEFORE);
+ switch (status) {
+ case RET_ERROR:
+ perror("ibefore/put");
+ break;
+ case RET_SPECIAL:
+ (void)printf("%s (duplicate key)\n", argv[1]);
+ break;
+ case RET_SUCCESS:
+ break;
+ }
+}
+
+void
+icursor(db, argv)
+ DB *db;
+ char **argv;
+{
+ int status;
+ DBT data, key;
+
+ key.data = argv[1];
+ if (recno)
+ key.size = sizeof(recno_t);
+ else
+ key.size = strlen(argv[1]) + 1;
+ data.data = argv[2];
+ data.size = strlen(argv[2]) + 1;
+
+ status = (*db->put)(db, &key, &data, R_CURSOR);
+ switch (status) {
+ case RET_ERROR:
+ perror("icursor/put");
+ break;
+ case RET_SPECIAL:
+ (void)printf("%s (duplicate key)\n", argv[1]);
+ break;
+ case RET_SUCCESS:
+ break;
+ }
+}
+
+void
+insert(db, argv)
+ DB *db;
+ char **argv;
+{
+ int status;
+ DBT data, key;
+
+ key.data = argv[1];
+ if (recno)
+ key.size = sizeof(recno_t);
+ else
+ key.size = strlen(argv[1]) + 1;
+ data.data = argv[2];
+ data.size = strlen(argv[2]) + 1;
+
+ status = (*db->put)(db, &key, &data, R_NOOVERWRITE);
+ switch (status) {
+ case RET_ERROR:
+ perror("insert/put");
+ break;
+ case RET_SPECIAL:
+ (void)printf("%s (duplicate key)\n", argv[1]);
+ break;
+ case RET_SUCCESS:
+ break;
+ }
+}
+
+void
+last(db, argv)
+ DB *db;
+ char **argv;
+{
+ DBT data, key;
+ int status;
+
+ status = (*db->seq)(db, &key, &data, R_LAST);
+
+ switch (status) {
+ case RET_ERROR:
+ perror("last/seq");
+ break;
+ case RET_SPECIAL:
+ (void)printf("no more keys\n");
+ break;
+ case RET_SUCCESS:
+ keydata(&key, &data);
+ break;
+ }
+}
+
+void
+list(db, argv)
+ DB *db;
+ char **argv;
+{
+ DBT data, key;
+ FILE *fp;
+ int status;
+
+ if ((fp = fopen(argv[1], "w")) == NULL) {
+ (void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
+ return;
+ }
+ status = (*db->seq)(db, &key, &data, R_FIRST);
+ while (status == RET_SUCCESS) {
+ (void)fprintf(fp, "%s\n", key.data);
+ status = (*db->seq)(db, &key, &data, R_NEXT);
+ }
+ if (status == RET_ERROR)
+ perror("list/seq");
+}
+
+DB *BUGdb;
+void
+load(db, argv)
+ DB *db;
+ char **argv;
+{
+ char *p, *t;
+ FILE *fp;
+ DBT data, key;
+ recno_t cnt;
+ size_t len;
+ int status;
+ char *lp, buf[16 * 1024];
+
+ BUGdb = db;
+ if ((fp = fopen(argv[1], "r")) == NULL) {
+ (void)fprintf(stderr, "%s: %s\n", argv[1], strerror(errno));
+ return;
+ }
+ (void)printf("loading %s...\n", argv[1]);
+
+ for (cnt = 1; (lp = fgetline(fp, &len)) != NULL; ++cnt) {
+ if (recno) {
+ key.data = &cnt;
+ key.size = sizeof(recno_t);
+ data.data = lp;
+ data.size = len + 1;
+ } else {
+ key.data = lp;
+ key.size = len + 1;
+ for (p = lp + len - 1, t = buf; p >= lp; *t++ = *p--);
+ *t = '\0';
+ data.data = buf;
+ data.size = len + 1;
+ }
+
+ status = (*db->put)(db, &key, &data, R_NOOVERWRITE);
+ switch (status) {
+ case RET_ERROR:
+ perror("load/put");
+ exit(1);
+ case RET_SPECIAL:
+ if (recno)
+ (void)fprintf(stderr,
+ "duplicate: %ld {%s}\n", cnt, data.data);
+ else
+ (void)fprintf(stderr,
+ "duplicate: %ld {%s}\n", cnt, key.data);
+ exit(1);
+ case RET_SUCCESS:
+ break;
+ }
+ }
+ (void)fclose(fp);
+}
+
+void
+next(db, argv)
+ DB *db;
+ char **argv;
+{
+ DBT data, key;
+ int status;
+
+ status = (*db->seq)(db, &key, &data, R_NEXT);
+
+ switch (status) {
+ case RET_ERROR:
+ perror("next/seq");
+ break;
+ case RET_SPECIAL:
+ (void)printf("no more keys\n");
+ break;
+ case RET_SUCCESS:
+ keydata(&key, &data);
+ break;
+ }
+}
+
+void
+previous(db, argv)
+ DB *db;
+ char **argv;
+{
+ DBT data, key;
+ int status;
+
+ status = (*db->seq)(db, &key, &data, R_PREV);
+
+ switch (status) {
+ case RET_ERROR:
+ perror("previous/seq");
+ break;
+ case RET_SPECIAL:
+ (void)printf("no more keys\n");
+ break;
+ case RET_SUCCESS:
+ keydata(&key, &data);
+ break;
+ }
+}
+
+void
+show(db, argv)
+ DB *db;
+ char **argv;
+{
+ BTREE *t;
+ PAGE *h;
+ pgno_t pg;
+
+ pg = atoi(argv[1]);
+ t = db->internal;
+ if ((h = mpool_get(t->bt_mp, pg, 0)) == NULL) {
+ (void)printf("getpage of %ld failed\n", pg);
+ return;
+ }
+ if (pg == 0)
+ __bt_dmpage(h);
+ else
+ __bt_dpage(h);
+ mpool_put(t->bt_mp, h, 0);
+}
+
+void
+bstat(db, argv)
+ DB *db;
+ char **argv;
+{
+ (void)printf("BTREE\n");
+ __bt_stat(db);
+}
+
+void
+mstat(db, argv)
+ DB *db;
+ char **argv;
+{
+ (void)printf("MPOOL\n");
+ mpool_stat(((BTREE *)db->internal)->bt_mp);
+}
+
+void
+keydata(key, data)
+ DBT *key, *data;
+{
+ if (!recno && key->size > 0)
+ (void)printf("%s/", key->data);
+ if (data->size > 0)
+ (void)printf("%s", data->data);
+ (void)printf("\n");
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr,
+ "usage: %s [-bdlu] [-c cache] [-i file] [-p page] [file]\n",
+ progname);
+ exit (1);
+}
diff --git a/lib/libc/db/test/dbtest.c b/lib/libc/db/test/dbtest.c
new file mode 100644
index 0000000..7de3a5c
--- /dev/null
+++ b/lib/libc/db/test/dbtest.c
@@ -0,0 +1,738 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1992, 1993, 1994\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)dbtest.c 8.17 (Berkeley) 9/1/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <db.h>
+
+enum S { COMMAND, COMPARE, GET, PUT, REMOVE, SEQ, SEQFLAG, KEY, DATA };
+
+void compare(DBT *, DBT *);
+DBTYPE dbtype(char *);
+void dump(DB *, int);
+void err(const char *, ...) __printflike(1, 2);
+void get(DB *, DBT *);
+void getdata(DB *, DBT *, DBT *);
+void put(DB *, DBT *, DBT *);
+void rem(DB *, DBT *);
+char *sflags(int);
+void synk(DB *);
+void *rfile(char *, size_t *);
+void seq(DB *, DBT *);
+u_int setflags(char *);
+void *setinfo(DBTYPE, char *);
+void usage(void);
+void *xmalloc(char *, size_t);
+
+DBTYPE type; /* Database type. */
+void *infop; /* Iflags. */
+u_long lineno; /* Current line in test script. */
+u_int flags; /* Current DB flags. */
+int ofd = STDOUT_FILENO; /* Standard output fd. */
+
+DB *XXdbp; /* Global for gdb. */
+int XXlineno; /* Fast breakpoint for gdb. */
+
+int
+main(argc, argv)
+ int argc;
+ char *argv[];
+{
+ extern int optind;
+ extern char *optarg;
+ enum S command, state;
+ DB *dbp;
+ DBT data, key, keydata;
+ size_t len;
+ int ch, oflags, sflag;
+ char *fname, *infoarg, *p, *t, buf[8 * 1024];
+
+ infoarg = NULL;
+ fname = NULL;
+ oflags = O_CREAT | O_RDWR;
+ sflag = 0;
+ while ((ch = getopt(argc, argv, "f:i:lo:s")) != -1)
+ switch (ch) {
+ case 'f':
+ fname = optarg;
+ break;
+ case 'i':
+ infoarg = optarg;
+ break;
+ case 'l':
+ oflags |= DB_LOCK;
+ break;
+ case 'o':
+ if ((ofd = open(optarg,
+ O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
+ err("%s: %s", optarg, strerror(errno));
+ break;
+ case 's':
+ sflag = 1;
+ break;
+ case '?':
+ default:
+ usage();
+ }
+ argc -= optind;
+ argv += optind;
+
+ if (argc != 2)
+ usage();
+
+ /* Set the type. */
+ type = dbtype(*argv++);
+
+ /* Open the descriptor file. */
+ if (strcmp(*argv, "-") && freopen(*argv, "r", stdin) == NULL)
+ err("%s: %s", *argv, strerror(errno));
+
+ /* Set up the db structure as necessary. */
+ if (infoarg == NULL)
+ infop = NULL;
+ else
+ for (p = strtok(infoarg, ",\t "); p != NULL;
+ p = strtok(0, ",\t "))
+ if (*p != '\0')
+ infop = setinfo(type, p);
+
+ /*
+ * Open the DB. Delete any preexisting copy, you almost never
+ * want it around, and it often screws up tests.
+ */
+ if (fname == NULL) {
+ p = getenv("TMPDIR");
+ if (p == NULL)
+ p = "/var/tmp";
+ (void)snprintf(buf, sizeof(buf), "%s/__dbtest", p);
+ fname = buf;
+ (void)unlink(buf);
+ } else if (!sflag)
+ (void)unlink(fname);
+
+ if ((dbp = dbopen(fname,
+ oflags, S_IRUSR | S_IWUSR, type, infop)) == NULL)
+ err("dbopen: %s", strerror(errno));
+ XXdbp = dbp;
+
+ state = COMMAND;
+ for (lineno = 1;
+ (p = fgets(buf, sizeof(buf), stdin)) != NULL; ++lineno) {
+ /* Delete the newline, displaying the key/data is easier. */
+ if (ofd == STDOUT_FILENO && (t = strchr(p, '\n')) != NULL)
+ *t = '\0';
+ if ((len = strlen(buf)) == 0 || isspace(*p) || *p == '#')
+ continue;
+
+ /* Convenient gdb break point. */
+ if (XXlineno == lineno)
+ XXlineno = 1;
+ switch (*p) {
+ case 'c': /* compare */
+ if (state != COMMAND)
+ err("line %lu: not expecting command", lineno);
+ state = KEY;
+ command = COMPARE;
+ break;
+ case 'e': /* echo */
+ if (state != COMMAND)
+ err("line %lu: not expecting command", lineno);
+ /* Don't display the newline, if CR at EOL. */
+ if (p[len - 2] == '\r')
+ --len;
+ if (write(ofd, p + 1, len - 1) != len - 1 ||
+ write(ofd, "\n", 1) != 1)
+ err("write: %s", strerror(errno));
+ break;
+ case 'g': /* get */
+ if (state != COMMAND)
+ err("line %lu: not expecting command", lineno);
+ state = KEY;
+ command = GET;
+ break;
+ case 'p': /* put */
+ if (state != COMMAND)
+ err("line %lu: not expecting command", lineno);
+ state = KEY;
+ command = PUT;
+ break;
+ case 'r': /* remove */
+ if (state != COMMAND)
+ err("line %lu: not expecting command", lineno);
+ if (flags == R_CURSOR) {
+ rem(dbp, &key);
+ state = COMMAND;
+ } else {
+ state = KEY;
+ command = REMOVE;
+ }
+ break;
+ case 'S': /* sync */
+ if (state != COMMAND)
+ err("line %lu: not expecting command", lineno);
+ synk(dbp);
+ state = COMMAND;
+ break;
+ case 's': /* seq */
+ if (state != COMMAND)
+ err("line %lu: not expecting command", lineno);
+ if (flags == R_CURSOR) {
+ state = KEY;
+ command = SEQ;
+ } else
+ seq(dbp, &key);
+ break;
+ case 'f':
+ flags = setflags(p + 1);
+ break;
+ case 'D': /* data file */
+ if (state != DATA)
+ err("line %lu: not expecting data", lineno);
+ data.data = rfile(p + 1, &data.size);
+ goto ldata;
+ case 'd': /* data */
+ if (state != DATA)
+ err("line %lu: not expecting data", lineno);
+ data.data = xmalloc(p + 1, len - 1);
+ data.size = len - 1;
+ldata: switch (command) {
+ case COMPARE:
+ compare(&keydata, &data);
+ break;
+ case PUT:
+ put(dbp, &key, &data);
+ break;
+ default:
+ err("line %lu: command doesn't take data",
+ lineno);
+ }
+ if (type != DB_RECNO)
+ free(key.data);
+ free(data.data);
+ state = COMMAND;
+ break;
+ case 'K': /* key file */
+ if (state != KEY)
+ err("line %lu: not expecting a key", lineno);
+ if (type == DB_RECNO)
+ err("line %lu: 'K' not available for recno",
+ lineno);
+ key.data = rfile(p + 1, &key.size);
+ goto lkey;
+ case 'k': /* key */
+ if (state != KEY)
+ err("line %lu: not expecting a key", lineno);
+ if (type == DB_RECNO) {
+ static recno_t recno;
+ recno = atoi(p + 1);
+ key.data = &recno;
+ key.size = sizeof(recno);
+ } else {
+ key.data = xmalloc(p + 1, len - 1);
+ key.size = len - 1;
+ }
+lkey: switch (command) {
+ case COMPARE:
+ getdata(dbp, &key, &keydata);
+ state = DATA;
+ break;
+ case GET:
+ get(dbp, &key);
+ if (type != DB_RECNO)
+ free(key.data);
+ state = COMMAND;
+ break;
+ case PUT:
+ state = DATA;
+ break;
+ case REMOVE:
+ rem(dbp, &key);
+ if ((type != DB_RECNO) && (flags != R_CURSOR))
+ free(key.data);
+ state = COMMAND;
+ break;
+ case SEQ:
+ seq(dbp, &key);
+ if ((type != DB_RECNO) && (flags != R_CURSOR))
+ free(key.data);
+ state = COMMAND;
+ break;
+ default:
+ err("line %lu: command doesn't take a key",
+ lineno);
+ }
+ break;
+ case 'o':
+ dump(dbp, p[1] == 'r');
+ break;
+ default:
+ err("line %lu: %s: unknown command character",
+ lineno, p);
+ }
+ }
+#ifdef STATISTICS
+ /*
+ * -l must be used (DB_LOCK must be set) for this to be
+ * used, otherwise a page will be locked and it will fail.
+ */
+ if (type == DB_BTREE && oflags & DB_LOCK)
+ __bt_stat(dbp);
+#endif
+ if (dbp->close(dbp))
+ err("db->close: %s", strerror(errno));
+ (void)close(ofd);
+ exit(0);
+}
+
+#define NOOVERWRITE "put failed, would overwrite key\n"
+
+void
+compare(db1, db2)
+ DBT *db1, *db2;
+{
+ size_t len;
+ u_char *p1, *p2;
+
+ if (db1->size != db2->size)
+ printf("compare failed: key->data len %lu != data len %lu\n",
+ db1->size, db2->size);
+
+ len = MIN(db1->size, db2->size);
+ for (p1 = db1->data, p2 = db2->data; len--;)
+ if (*p1++ != *p2++) {
+ printf("compare failed at offset %d\n",
+ p1 - (u_char *)db1->data);
+ break;
+ }
+}
+
+void
+get(dbp, kp)
+ DB *dbp;
+ DBT *kp;
+{
+ DBT data;
+
+ switch (dbp->get(dbp, kp, &data, flags)) {
+ case 0:
+ (void)write(ofd, data.data, data.size);
+ if (ofd == STDOUT_FILENO)
+ (void)write(ofd, "\n", 1);
+ break;
+ case -1:
+ err("line %lu: get: %s", lineno, strerror(errno));
+ /* NOTREACHED */
+ case 1:
+#define NOSUCHKEY "get failed, no such key\n"
+ if (ofd != STDOUT_FILENO)
+ (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+ else
+ (void)fprintf(stderr, "%d: %.*s: %s",
+ lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+#undef NOSUCHKEY
+ break;
+ }
+}
+
+void
+getdata(dbp, kp, dp)
+ DB *dbp;
+ DBT *kp, *dp;
+{
+ switch (dbp->get(dbp, kp, dp, flags)) {
+ case 0:
+ return;
+ case -1:
+ err("line %lu: getdata: %s", lineno, strerror(errno));
+ /* NOTREACHED */
+ case 1:
+ err("line %lu: getdata failed, no such key", lineno);
+ /* NOTREACHED */
+ }
+}
+
+void
+put(dbp, kp, dp)
+ DB *dbp;
+ DBT *kp, *dp;
+{
+ switch (dbp->put(dbp, kp, dp, flags)) {
+ case 0:
+ break;
+ case -1:
+ err("line %lu: put: %s", lineno, strerror(errno));
+ /* NOTREACHED */
+ case 1:
+ (void)write(ofd, NOOVERWRITE, sizeof(NOOVERWRITE) - 1);
+ break;
+ }
+}
+
+void
+rem(dbp, kp)
+ DB *dbp;
+ DBT *kp;
+{
+ switch (dbp->del(dbp, kp, flags)) {
+ case 0:
+ break;
+ case -1:
+ err("line %lu: rem: %s", lineno, strerror(errno));
+ /* NOTREACHED */
+ case 1:
+#define NOSUCHKEY "rem failed, no such key\n"
+ if (ofd != STDOUT_FILENO)
+ (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+ else if (flags != R_CURSOR)
+ (void)fprintf(stderr, "%d: %.*s: %s",
+ lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+ else
+ (void)fprintf(stderr,
+ "%d: rem of cursor failed\n", lineno);
+#undef NOSUCHKEY
+ break;
+ }
+}
+
+void
+synk(dbp)
+ DB *dbp;
+{
+ switch (dbp->sync(dbp, flags)) {
+ case 0:
+ break;
+ case -1:
+ err("line %lu: synk: %s", lineno, strerror(errno));
+ /* NOTREACHED */
+ }
+}
+
+void
+seq(dbp, kp)
+ DB *dbp;
+ DBT *kp;
+{
+ DBT data;
+
+ switch (dbp->seq(dbp, kp, &data, flags)) {
+ case 0:
+ (void)write(ofd, data.data, data.size);
+ if (ofd == STDOUT_FILENO)
+ (void)write(ofd, "\n", 1);
+ break;
+ case -1:
+ err("line %lu: seq: %s", lineno, strerror(errno));
+ /* NOTREACHED */
+ case 1:
+#define NOSUCHKEY "seq failed, no such key\n"
+ if (ofd != STDOUT_FILENO)
+ (void)write(ofd, NOSUCHKEY, sizeof(NOSUCHKEY) - 1);
+ else if (flags == R_CURSOR)
+ (void)fprintf(stderr, "%d: %.*s: %s",
+ lineno, MIN(kp->size, 20), kp->data, NOSUCHKEY);
+ else
+ (void)fprintf(stderr,
+ "%d: seq (%s) failed\n", lineno, sflags(flags));
+#undef NOSUCHKEY
+ break;
+ }
+}
+
+void
+dump(dbp, rev)
+ DB *dbp;
+ int rev;
+{
+ DBT key, data;
+ int flags, nflags;
+
+ if (rev) {
+ flags = R_LAST;
+ nflags = R_PREV;
+ } else {
+ flags = R_FIRST;
+ nflags = R_NEXT;
+ }
+ for (;; flags = nflags)
+ switch (dbp->seq(dbp, &key, &data, flags)) {
+ case 0:
+ (void)write(ofd, data.data, data.size);
+ if (ofd == STDOUT_FILENO)
+ (void)write(ofd, "\n", 1);
+ break;
+ case 1:
+ goto done;
+ case -1:
+ err("line %lu: (dump) seq: %s",
+ lineno, strerror(errno));
+ /* NOTREACHED */
+ }
+done: return;
+}
+
+u_int
+setflags(s)
+ char *s;
+{
+ char *p, *index();
+
+ for (; isspace(*s); ++s);
+ if (*s == '\n' || *s == '\0')
+ return (0);
+ if ((p = index(s, '\n')) != NULL)
+ *p = '\0';
+ if (!strcmp(s, "R_CURSOR")) return (R_CURSOR);
+ if (!strcmp(s, "R_FIRST")) return (R_FIRST);
+ if (!strcmp(s, "R_IAFTER")) return (R_IAFTER);
+ if (!strcmp(s, "R_IBEFORE")) return (R_IBEFORE);
+ if (!strcmp(s, "R_LAST")) return (R_LAST);
+ if (!strcmp(s, "R_NEXT")) return (R_NEXT);
+ if (!strcmp(s, "R_NOOVERWRITE")) return (R_NOOVERWRITE);
+ if (!strcmp(s, "R_PREV")) return (R_PREV);
+ if (!strcmp(s, "R_SETCURSOR")) return (R_SETCURSOR);
+
+ err("line %lu: %s: unknown flag", lineno, s);
+ /* NOTREACHED */
+}
+
+char *
+sflags(flags)
+ int flags;
+{
+ switch (flags) {
+ case R_CURSOR: return ("R_CURSOR");
+ case R_FIRST: return ("R_FIRST");
+ case R_IAFTER: return ("R_IAFTER");
+ case R_IBEFORE: return ("R_IBEFORE");
+ case R_LAST: return ("R_LAST");
+ case R_NEXT: return ("R_NEXT");
+ case R_NOOVERWRITE: return ("R_NOOVERWRITE");
+ case R_PREV: return ("R_PREV");
+ case R_SETCURSOR: return ("R_SETCURSOR");
+ }
+
+ return ("UNKNOWN!");
+}
+
+DBTYPE
+dbtype(s)
+ char *s;
+{
+ if (!strcmp(s, "btree"))
+ return (DB_BTREE);
+ if (!strcmp(s, "hash"))
+ return (DB_HASH);
+ if (!strcmp(s, "recno"))
+ return (DB_RECNO);
+ err("%s: unknown type (use btree, hash or recno)", s);
+ /* NOTREACHED */
+}
+
+void *
+setinfo(type, s)
+ DBTYPE type;
+ char *s;
+{
+ static BTREEINFO ib;
+ static HASHINFO ih;
+ static RECNOINFO rh;
+ char *eq, *index();
+
+ if ((eq = index(s, '=')) == NULL)
+ err("%s: illegal structure set statement", s);
+ *eq++ = '\0';
+ if (!isdigit(*eq))
+ err("%s: structure set statement must be a number", s);
+
+ switch (type) {
+ case DB_BTREE:
+ if (!strcmp("flags", s)) {
+ ib.flags = atoi(eq);
+ return (&ib);
+ }
+ if (!strcmp("cachesize", s)) {
+ ib.cachesize = atoi(eq);
+ return (&ib);
+ }
+ if (!strcmp("maxkeypage", s)) {
+ ib.maxkeypage = atoi(eq);
+ return (&ib);
+ }
+ if (!strcmp("minkeypage", s)) {
+ ib.minkeypage = atoi(eq);
+ return (&ib);
+ }
+ if (!strcmp("lorder", s)) {
+ ib.lorder = atoi(eq);
+ return (&ib);
+ }
+ if (!strcmp("psize", s)) {
+ ib.psize = atoi(eq);
+ return (&ib);
+ }
+ break;
+ case DB_HASH:
+ if (!strcmp("bsize", s)) {
+ ih.bsize = atoi(eq);
+ return (&ih);
+ }
+ if (!strcmp("ffactor", s)) {
+ ih.ffactor = atoi(eq);
+ return (&ih);
+ }
+ if (!strcmp("nelem", s)) {
+ ih.nelem = atoi(eq);
+ return (&ih);
+ }
+ if (!strcmp("cachesize", s)) {
+ ih.cachesize = atoi(eq);
+ return (&ih);
+ }
+ if (!strcmp("lorder", s)) {
+ ih.lorder = atoi(eq);
+ return (&ih);
+ }
+ break;
+ case DB_RECNO:
+ if (!strcmp("flags", s)) {
+ rh.flags = atoi(eq);
+ return (&rh);
+ }
+ if (!strcmp("cachesize", s)) {
+ rh.cachesize = atoi(eq);
+ return (&rh);
+ }
+ if (!strcmp("lorder", s)) {
+ rh.lorder = atoi(eq);
+ return (&rh);
+ }
+ if (!strcmp("reclen", s)) {
+ rh.reclen = atoi(eq);
+ return (&rh);
+ }
+ if (!strcmp("bval", s)) {
+ rh.bval = atoi(eq);
+ return (&rh);
+ }
+ if (!strcmp("psize", s)) {
+ rh.psize = atoi(eq);
+ return (&rh);
+ }
+ break;
+ }
+ err("%s: unknown structure value", s);
+ /* NOTREACHED */
+}
+
+void *
+rfile(name, lenp)
+ char *name;
+ size_t *lenp;
+{
+ struct stat sb;
+ void *p;
+ int fd;
+ char *np, *index();
+
+ for (; isspace(*name); ++name);
+ if ((np = index(name, '\n')) != NULL)
+ *np = '\0';
+ if ((fd = open(name, O_RDONLY, 0)) < 0 ||
+ fstat(fd, &sb))
+ err("%s: %s\n", name, strerror(errno));
+#ifdef NOT_PORTABLE
+ if (sb.st_size > (off_t)SIZE_T_MAX)
+ err("%s: %s\n", name, strerror(E2BIG));
+#endif
+ if ((p = (void *)malloc((u_int)sb.st_size)) == NULL)
+ err("%s", strerror(errno));
+ (void)read(fd, p, (int)sb.st_size);
+ *lenp = sb.st_size;
+ (void)close(fd);
+ return (p);
+}
+
+void *
+xmalloc(text, len)
+ char *text;
+ size_t len;
+{
+ void *p;
+
+ if ((p = (void *)malloc(len)) == NULL)
+ err("%s", strerror(errno));
+ memmove(p, text, len);
+ return (p);
+}
+
+void
+usage()
+{
+ (void)fprintf(stderr,
+ "usage: dbtest [-l] [-f file] [-i info] [-o file] type script\n");
+ exit(1);
+}
+
+#include <stdarg.h>
+
+void
+err(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ (void)fprintf(stderr, "dbtest: ");
+ (void)vfprintf(stderr, fmt, ap);
+ va_end(ap);
+ (void)fprintf(stderr, "\n");
+ exit(1);
+ /* NOTREACHED */
+}
diff --git a/lib/libc/db/test/hash.tests/driver2.c b/lib/libc/db/test/hash.tests/driver2.c
new file mode 100644
index 0000000..1c5a130
--- /dev/null
+++ b/lib/libc/db/test/hash.tests/driver2.c
@@ -0,0 +1,112 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)driver2.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Test driver, to try to tackle the large ugly-split problem.
+ */
+
+#include <sys/file.h>
+#include <stdio.h>
+#include "ndbm.h"
+
+int my_hash(key, len)
+ char *key;
+ int len;
+{
+ return(17); /* So I'm cruel... */
+}
+
+main(argc, argv)
+ int argc;
+{
+ DB *db;
+ DBT key, content;
+ char keybuf[2049];
+ char contentbuf[2049];
+ char buf[256];
+ int i;
+ HASHINFO info;
+
+ info.bsize = 1024;
+ info.ffactor = 5;
+ info.nelem = 1;
+ info.cachesize = NULL;
+#ifdef HASH_ID_PROGRAM_SPECIFIED
+ info.hash_id = HASH_ID_PROGRAM_SPECIFIED;
+ info.hash_func = my_hash;
+#else
+ info.hash = my_hash;
+#endif
+ info.lorder = 0;
+ if (!(db = dbopen("bigtest", O_RDWR | O_CREAT, 0644, DB_HASH, &info))) {
+ sprintf(buf, "dbopen: failed on file bigtest");
+ perror(buf);
+ exit(1);
+ }
+ srandom(17);
+ key.data = keybuf;
+ content.data = contentbuf;
+ bzero(keybuf, sizeof(keybuf));
+ bzero(contentbuf, sizeof(contentbuf));
+ for (i=1; i <= 500; i++) {
+ key.size = 128 + (random()&1023);
+ content.size = 128 + (random()&1023);
+/* printf("%d: Key size %d, data size %d\n", i, key.size,
+ content.size); */
+ sprintf(keybuf, "Key #%d", i);
+ sprintf(contentbuf, "Contents #%d", i);
+ if ((db->put)(db, &key, &content, R_NOOVERWRITE)) {
+ sprintf(buf, "dbm_store #%d", i);
+ perror(buf);
+ }
+ }
+ if ((db->close)(db)) {
+ perror("closing hash file");
+ exit(1);
+ }
+ exit(0);
+}
+
+
+
diff --git a/lib/libc/db/test/hash.tests/makedb.sh b/lib/libc/db/test/hash.tests/makedb.sh
new file mode 100644
index 0000000..f28e281
--- /dev/null
+++ b/lib/libc/db/test/hash.tests/makedb.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+#
+# @(#)makedb.sh 8.1 (Berkeley) 6/4/93
+
+awk '{i++; print $0; print i;}' /usr/share/dict/words > WORDS
+ls /bin /usr/bin /usr/ucb /etc | egrep '^(...|....|.....|......)$' | \
+sort | uniq | \
+awk '{
+ printf "%s\n", $0
+ for (i = 0; i < 1000; i++)
+ printf "%s+", $0
+ printf "\n"
+}' > LONG.DATA
diff --git a/lib/libc/db/test/hash.tests/tcreat3.c b/lib/libc/db/test/hash.tests/tcreat3.c
new file mode 100644
index 0000000..6ba3c07
--- /dev/null
+++ b/lib/libc/db/test/hash.tests/tcreat3.c
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tcreat3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <db.h>
+
+#define INITIAL 25000
+#define MAXWORDS 25000 /* # of elements in search table */
+
+char wp1[8192];
+char wp2[8192];
+main(argc, argv)
+char **argv;
+{
+ DBT item, key;
+ DB *dbp;
+ HASHINFO ctl;
+ FILE *fp;
+ int trash;
+
+ int i = 0;
+
+ argv++;
+ ctl.hash = NULL;
+ ctl.bsize = atoi(*argv++);
+ ctl.ffactor = atoi(*argv++);
+ ctl.nelem = atoi(*argv++);
+ ctl.lorder = 0;
+ if (!(dbp = dbopen( "hashtest",
+ O_CREAT|O_TRUNC|O_RDWR, 0600, DB_HASH, &ctl))){
+ /* create table */
+ fprintf(stderr, "cannot create: hash table (size %d)\n",
+ INITIAL);
+ exit(1);
+ }
+
+ key.data = wp1;
+ item.data = wp2;
+ while ( fgets(wp1, 8192, stdin) &&
+ fgets(wp2, 8192, stdin) &&
+ i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+ key.size = strlen(wp1);
+ item.size = strlen(wp2);
+
+/*
+ * enter key/data pair into the table
+ */
+ if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) {
+ fprintf(stderr, "cannot enter: key %s\n",
+ item.data);
+ exit(1);
+ }
+ }
+
+ (dbp->close)(dbp);
+ exit(0);
+}
diff --git a/lib/libc/db/test/hash.tests/tdel.c b/lib/libc/db/test/hash.tests/tdel.c
new file mode 100644
index 0000000..1d7e424
--- /dev/null
+++ b/lib/libc/db/test/hash.tests/tdel.c
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tdel.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <db.h>
+#include <stdio.h>
+
+#define INITIAL 25000
+#define MAXWORDS 25000 /* # of elements in search table */
+
+/* Usage: thash pagesize fillfactor file */
+char wp1[8192];
+char wp2[8192];
+main(argc, argv)
+char **argv;
+{
+ DBT item, key;
+ DB *dbp;
+ HASHINFO ctl;
+ FILE *fp;
+ int stat;
+
+ int i = 0;
+
+ argv++;
+ ctl.nelem = INITIAL;
+ ctl.hash = NULL;
+ ctl.bsize = atoi(*argv++);
+ ctl.ffactor = atoi(*argv++);
+ ctl.cachesize = 1024 * 1024; /* 1 MEG */
+ ctl.lorder = 0;
+ argc -= 2;
+ if (!(dbp = dbopen( NULL, O_CREAT|O_RDWR, 0400, DB_HASH, &ctl))) {
+ /* create table */
+ fprintf(stderr, "cannot create: hash table size %d)\n",
+ INITIAL);
+ exit(1);
+ }
+
+ key.data = wp1;
+ item.data = wp2;
+ while ( fgets(wp1, 8192, stdin) &&
+ fgets(wp2, 8192, stdin) &&
+ i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+ key.size = strlen(wp1);
+ item.size = strlen(wp2);
+
+/*
+ * enter key/data pair into the table
+ */
+ if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) {
+ fprintf(stderr, "cannot enter: key %s\n",
+ item.data);
+ exit(1);
+ }
+ }
+
+ if ( --argc ) {
+ fp = fopen ( argv[0], "r");
+ i = 0;
+ while ( fgets(wp1, 8192, fp) &&
+ fgets(wp2, 8192, fp) &&
+ i++ < MAXWORDS) {
+ key.size = strlen(wp1);
+ stat = (dbp->del)(dbp, &key, 0);
+ if (stat) {
+ fprintf ( stderr, "Error retrieving %s\n", key.data );
+ exit(1);
+ }
+ }
+ fclose(fp);
+ }
+ (dbp->close)(dbp);
+ exit(0);
+}
diff --git a/lib/libc/db/test/hash.tests/testit b/lib/libc/db/test/hash.tests/testit
new file mode 100644
index 0000000..039457a
--- /dev/null
+++ b/lib/libc/db/test/hash.tests/testit
@@ -0,0 +1,147 @@
+#!/bin/csh -f
+#
+# @(#)testit 8.1 (Berkeley) 6/4/93
+#
+
+echo ""
+echo "PAGE FILL "
+set name=WORDS
+ set i = 256
+ foreach j ( 11 14 21 )
+ thash4 $i $j 25000 65536 $name < $name
+ end
+ set i = 512
+ foreach j ( 21 28 43 )
+ thash4 $i $j 25000 65536 $name < $name
+ end
+ set i = 1024
+ foreach j ( 43 57 85 )
+ thash4 $i $j 25000 65536 $name < $name
+ end
+ set i = 2048
+ foreach j ( 85 114 171 )
+ thash4 $i $j 25000 65536 $name < $name
+ end
+ set i = 4096
+ foreach j ( 171 228 341 )
+ thash4 $i $j 25000 65536 $name < $name
+ end
+ set i = 8192
+ foreach j ( 341 455 683 )
+ thash4 $i $j 25000 65536 $name < $name
+ end
+ echo "PAGE FILL "
+ set i = 256
+ foreach j ( 11 14 21 )
+ echo "$i"_"$j"
+ tcreat3 $i $j 25000 $name < $name
+ tread2 65536 < $name
+ tverify $name < $name
+ tseq > /dev/null
+ tdel $i $j $name < $name
+ end
+ set i = 512
+ foreach j ( 21 28 43 )
+ echo "$i"_"$j"
+ tcreat3 $i $j 25000 $name < $name
+ tread2 65536 < $name
+ tverify $name < $name
+ tseq > /dev/null
+ tdel $i $j $name < $name
+ end
+ set i = 1024
+ foreach j ( 43 57 85 )
+ echo "$i"_"$j"
+ tcreat3 $i $j 25000 $name < $name
+ tread2 65536 < $name
+ tverify $name < $name
+ tseq > /dev/null
+ tdel $i $j $name < $name
+ end
+ set i = 2048
+ foreach j ( 85 114 171 )
+ echo "$i"_"$j"
+ tcreat3 $i $j 25000 $name < $name
+ tread2 65536 < $name
+ tverify $name < $name
+ tseq > /dev/null
+ tdel $i $j $name < $name
+ end
+ set i = 4096
+ foreach j ( 171 228 341 )
+ echo "$i"_"$j"
+ tcreat3 $i $j 25000 $name < $name
+ tread2 65536 < $name
+ tverify $name < $name
+ tseq > /dev/null
+ tdel $i $j $name < $name
+ end
+ set i = 8192
+ foreach j ( 341 455 683 )
+ echo "$i"_"$j"
+ tcreat3 $i $j 25000 $name < $name
+ tread2 65536 < $name
+ tverify $name < $name
+ tseq > /dev/null
+ tdel $i $j $name < $name
+ end
+set name=LONG.DATA
+ set i = 1024
+ foreach j ( 1 2 4 )
+ echo thash4 $i $j 600 65536 $name
+ thash4 $i $j 600 65536 $name < $name
+ end
+
+ set i = 2048
+ foreach j ( 1 2 4 )
+ echo thash4 $i $j 600 65536 $name
+ thash4 $i $j 600 65536 $name < $name
+ end
+ set i = 4096
+ foreach j ( 1 2 4 )
+ echo thash4 $i $j 600 65536 $name
+ thash4 $i $j 600 65536 $name < $name
+ end
+ set i = 8192
+ foreach j ( 2 4 8 )
+ echo thash4 $i $j 600 65536 $name
+ thash4 $i $j 600 65536 $name < $name
+ end
+ echo "PAGE FILL "
+ set i = 1024
+ foreach j ( 1 2 4 )
+ echo "$i"_"$j"
+ tcreat3 $i $j 600 $name < $name
+ tread2 65536 < $name
+ tverify $name < $name
+ tseq > /dev/null
+ tdel $i $j $name < $name
+ end
+ set i = 2048
+ foreach j ( 1 2 4 )
+ echo "$i"_"$j"
+ tcreat3 $i $j 600 $name < $name
+ tread2 65536 < $name
+ tverify $name < $name
+ tseq > /dev/null
+ tdel $i $j $name < $name
+ end
+ set i = 4096
+ foreach j ( 1 2 4 )
+ echo "$i"_"$j"
+ tcreat3 $i $j 600 $name < $name
+ tread2 65536 < $name
+ tverify $name < $name
+ tseq > /dev/null
+ tdel $i $j $name < $name
+ end
+ set i = 8192
+ foreach j ( 2 4 8 )
+ echo "$i"_"$j"
+ tcreat3 $i $j 600 $name < $name
+ tread2 65536 < $name
+ tverify $name < $name
+ tseq > /dev/null
+ tdel $i $j $name < $name
+ end
+driver2
diff --git a/lib/libc/db/test/hash.tests/thash4.c b/lib/libc/db/test/hash.tests/thash4.c
new file mode 100644
index 0000000..02f6832
--- /dev/null
+++ b/lib/libc/db/test/hash.tests/thash4.c
@@ -0,0 +1,130 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)thash4.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <sys/timeb.h>
+#include <stdio.h>
+#include <errno.h>
+#include <db.h>
+
+#define INITIAL 25000
+#define MAXWORDS 25000 /* # of elements in search table */
+
+/* Usage: thash pagesize fillfactor file */
+char wp1[8192];
+char wp2[8192];
+main(argc, argv)
+char **argv;
+{
+ DBT item, key, res;
+ DB *dbp;
+ HASHINFO ctl;
+ FILE *fp;
+ int stat;
+ time_t t;
+
+ int i = 0;
+
+ argv++;
+ ctl.hash = NULL;
+ ctl.bsize = atoi(*argv++);
+ ctl.ffactor = atoi(*argv++);
+ ctl.nelem = atoi(*argv++);
+ ctl.cachesize = atoi(*argv++);
+ ctl.lorder = 0;
+ if (!(dbp = dbopen( NULL, O_CREAT|O_RDWR, 0400, DB_HASH, &ctl))) {
+ /* create table */
+ fprintf(stderr, "cannot create: hash table size %d)\n",
+ INITIAL);
+ fprintf(stderr, "\terrno: %d\n", errno);
+ exit(1);
+ }
+
+ key.data = wp1;
+ item.data = wp2;
+ while ( fgets(wp1, 8192, stdin) &&
+ fgets(wp2, 8192, stdin) &&
+ i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+ key.size = strlen(wp1);
+ item.size = strlen(wp2);
+
+/*
+ * enter key/data pair into the table
+ */
+ if ((dbp->put)(dbp, &key, &item, R_NOOVERWRITE) != NULL) {
+ fprintf(stderr, "cannot enter: key %s\n",
+ item.data);
+ fprintf(stderr, "\terrno: %d\n", errno);
+ exit(1);
+ }
+ }
+
+ if ( --argc ) {
+ fp = fopen ( argv[0], "r");
+ i = 0;
+ while ( fgets(wp1, 256, fp) &&
+ fgets(wp2, 8192, fp) &&
+ i++ < MAXWORDS) {
+
+ key.size = strlen(wp1);
+ stat = (dbp->get)(dbp, &key, &res, 0);
+ if (stat < 0 ) {
+ fprintf ( stderr, "Error retrieving %s\n", key.data );
+ fprintf(stderr, "\terrno: %d\n", errno);
+ exit(1);
+ } else if ( stat > 0 ) {
+ fprintf ( stderr, "%s not found\n", key.data );
+ fprintf(stderr, "\terrno: %d\n", errno);
+ exit(1);
+ }
+ }
+ fclose(fp);
+ }
+ dbp->close(dbp);
+ exit(0);
+}
diff --git a/lib/libc/db/test/hash.tests/tread2.c b/lib/libc/db/test/hash.tests/tread2.c
new file mode 100644
index 0000000..fdcaab3
--- /dev/null
+++ b/lib/libc/db/test/hash.tests/tread2.c
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tread2.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <db.h>
+
+#define INITIAL 25000
+#define MAXWORDS 25000 /* # of elements in search table */
+
+typedef struct { /* info to be stored */
+ int num, siz;
+} info;
+
+char wp1[8192];
+char wp2[8192];
+main(argc, argv)
+char **argv;
+{
+ DBT item, key, res;
+ DB *dbp;
+ HASHINFO ctl;
+ int stat;
+
+ int i = 0;
+
+ ctl.nelem = INITIAL;
+ ctl.hash = NULL;
+ ctl.bsize = 64;
+ ctl.ffactor = 1;
+ ctl.cachesize = atoi(*argv++);
+ ctl.lorder = 0;
+ if (!(dbp = dbopen( "hashtest", O_RDONLY, 0400, DB_HASH, &ctl))) {
+ /* create table */
+ fprintf(stderr, "cannot open: hash table\n" );
+ exit(1);
+ }
+
+ key.data = wp1;
+ item.data = wp2;
+ while ( fgets(wp1, 8192, stdin) &&
+ fgets(wp2, 8192, stdin) &&
+ i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+ key.size = strlen(wp1);
+ item.size = strlen(wp2);
+
+ stat = (dbp->get)(dbp, &key, &res,0);
+ if (stat < 0) {
+ fprintf ( stderr, "Error retrieving %s\n", key.data );
+ exit(1);
+ } else if ( stat > 0 ) {
+ fprintf ( stderr, "%s not found\n", key.data );
+ exit(1);
+ }
+ }
+ (dbp->close)(dbp);
+ exit(0);
+}
diff --git a/lib/libc/db/test/hash.tests/tseq.c b/lib/libc/db/test/hash.tests/tseq.c
new file mode 100644
index 0000000..3aac7d5
--- /dev/null
+++ b/lib/libc/db/test/hash.tests/tseq.c
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tseq.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <db.h>
+
+#define INITIAL 25000
+#define MAXWORDS 25000 /* # of elements in search table */
+
+
+char wp[8192];
+char cp[8192];
+main(argc, argv)
+char **argv;
+{
+ DBT item, key, res;
+ DB *dbp;
+ FILE *fp;
+ int stat;
+
+ if (!(dbp = dbopen( "hashtest", O_RDONLY, 0400, DB_HASH, NULL))) {
+ /* create table */
+ fprintf(stderr, "cannot open: hash table\n" );
+ exit(1);
+ }
+
+/*
+* put info in structure, and structure in the item
+*/
+ for ( stat = (dbp->seq) (dbp, &res, &item, 1 );
+ stat == 0;
+ stat = (dbp->seq) (dbp, &res, &item, 0 ) ) {
+
+ bcopy ( res.data, wp, res.size );
+ wp[res.size] = 0;
+ bcopy ( item.data, cp, item.size );
+ cp[item.size] = 0;
+
+ printf ( "%s %s\n", wp, cp );
+ }
+ (dbp->close)(dbp);
+ exit(0);
+}
diff --git a/lib/libc/db/test/hash.tests/tverify.c b/lib/libc/db/test/hash.tests/tverify.c
new file mode 100644
index 0000000..fb8ee33
--- /dev/null
+++ b/lib/libc/db/test/hash.tests/tverify.c
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Margo Seltzer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1991, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tverify.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <db.h>
+
+#define INITIAL 25000
+#define MAXWORDS 25000 /* # of elements in search table */
+
+typedef struct { /* info to be stored */
+ int num, siz;
+} info;
+
+char wp1[8192];
+char wp2[8192];
+main(argc, argv)
+char **argv;
+{
+ DBT key, res;
+ DB *dbp;
+ HASHINFO ctl;
+ int trash;
+ int stat;
+
+ int i = 0;
+
+ ctl.nelem = INITIAL;
+ ctl.hash = NULL;
+ ctl.bsize = 64;
+ ctl.ffactor = 1;
+ ctl.cachesize = 1024 * 1024; /* 1 MEG */
+ ctl.lorder = 0;
+ if (!(dbp = dbopen( "hashtest", O_RDONLY, 0400, DB_HASH, &ctl))) {
+ /* create table */
+ fprintf(stderr, "cannot open: hash table\n" );
+ exit(1);
+ }
+
+ key.data = wp1;
+ while ( fgets(wp1, 8192, stdin) &&
+ fgets(wp2, 8192, stdin) &&
+ i++ < MAXWORDS) {
+/*
+* put info in structure, and structure in the item
+*/
+ key.size = strlen(wp1);
+
+ stat = (dbp->get)(dbp, &key, &res,0);
+ if (stat < 0) {
+ fprintf ( stderr, "Error retrieving %s\n", key.data );
+ exit(1);
+ } else if ( stat > 0 ) {
+ fprintf ( stderr, "%s not found\n", key.data );
+ exit(1);
+ }
+ if ( memcmp ( res.data, wp2, res.size ) ) {
+ fprintf ( stderr, "data for %s is incorrect. Data was %s. Should have been %s\n", key.data, res.data, wp2 );
+ }
+ }
+ (dbp->close)(dbp);
+ exit(0);
+}
diff --git a/lib/libc/db/test/run.test b/lib/libc/db/test/run.test
new file mode 100644
index 0000000..52b74c3
--- /dev/null
+++ b/lib/libc/db/test/run.test
@@ -0,0 +1,705 @@
+#!/bin/sh -
+#
+# @(#)run.test 8.10 (Berkeley) 7/26/94
+#
+
+# db regression tests
+main()
+{
+
+ PROG=./dbtest
+ TMP1=t1
+ TMP2=t2
+ TMP3=t3
+
+ if [ -f /usr/share/dict/words ]; then
+ DICT=/usr/share/dict/words
+ elif [ -f /usr/dict/words ]; then
+ DICT=/usr/dict/words
+ else
+ echo 'run.test: no dictionary'
+ exit 1
+ fi
+
+ if [ $# -eq 0 ]; then
+ for t in 1 2 3 4 5 6 7 8 9 10 11 12 13 20; do
+ test$t
+ done
+ else
+ while [ $# -gt 0 ]
+ do case "$1" in
+ test*)
+ $1;;
+ [0-9]*)
+ test$1;;
+ btree)
+ for t in 1 2 3 7 8 9 10 12 13; do
+ test$t
+ done;;
+ hash)
+ for t in 1 2 3 8 13 20; do
+ test$t
+ done;;
+ recno)
+ for t in 1 2 3 4 5 6 7 10 11; do
+ test$t
+ done;;
+ *)
+ echo "run.test: unknown test $1"
+ echo "usage: run.test test# | type"
+ exit 1
+ esac
+ shift
+ done
+ fi
+ rm -f $TMP1 $TMP2 $TMP3
+ exit 0
+}
+
+# Take the first hundred entries in the dictionary, and make them
+# be key/data pairs.
+test1()
+{
+ echo "Test 1: btree, hash: small key, small data pairs"
+ sed 200q $DICT > $TMP1
+ for type in btree hash; do
+ rm -f $TMP2 $TMP3
+ for i in `sed 200q $DICT`; do
+ echo p
+ echo k$i
+ echo d$i
+ echo g
+ echo k$i
+ done > $TMP2
+ $PROG -o $TMP3 $type $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test1: type $type: failed"
+ exit 1
+ fi
+ done
+ echo "Test 1: recno: small key, small data pairs"
+ rm -f $TMP2 $TMP3
+ sed 200q $DICT |
+ awk '{
+ ++i;
+ printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
+ }' > $TMP2
+ $PROG -o $TMP3 recno $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test1: type recno: failed"
+ exit 1
+ fi
+}
+
+# Take the first 200 entries in the dictionary, and give them
+# each a medium size data entry.
+test2()
+{
+ echo "Test 2: btree, hash: small key, medium data pairs"
+ mdata=abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz
+ echo $mdata |
+ awk '{ for (i = 1; i < 201; ++i) print $0 }' > $TMP1
+ for type in hash btree; do
+ rm -f $TMP2 $TMP3
+ for i in `sed 200q $DICT`; do
+ echo p
+ echo k$i
+ echo d$mdata
+ echo g
+ echo k$i
+ done > $TMP2
+ $PROG -o $TMP3 $type $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test2: type $type: failed"
+ exit 1
+ fi
+ done
+ echo "Test 2: recno: small key, medium data pairs"
+ rm -f $TMP2 $TMP3
+ echo $mdata |
+ awk '{ for (i = 1; i < 201; ++i)
+ printf("p\nk%d\nd%s\ng\nk%d\n", i, $0, i);
+ }' > $TMP2
+ $PROG -o $TMP3 recno $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test2: type recno: failed"
+ exit 1
+ fi
+}
+
+# Insert the programs in /bin with their paths as their keys.
+test3()
+{
+ echo "Test 3: hash: small key, big data pairs"
+ rm -f $TMP1
+ (find /bin -type f -print | xargs cat) > $TMP1
+ for type in hash; do
+ rm -f $TMP2 $TMP3
+ for i in `find /bin -type f -print`; do
+ echo p
+ echo k$i
+ echo D$i
+ echo g
+ echo k$i
+ done > $TMP2
+ $PROG -o $TMP3 $type $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test3: $type: failed"
+ exit 1
+ fi
+ done
+ echo "Test 3: btree: small key, big data pairs"
+ for psize in 512 16384 65536; do
+ echo " page size $psize"
+ for type in btree; do
+ rm -f $TMP2 $TMP3
+ for i in `find /bin -type f -print`; do
+ echo p
+ echo k$i
+ echo D$i
+ echo g
+ echo k$i
+ done > $TMP2
+ $PROG -i psize=$psize -o $TMP3 $type $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test3: $type: page size $psize: failed"
+ exit 1
+ fi
+ done
+ done
+ echo "Test 3: recno: big data pairs"
+ rm -f $TMP2 $TMP3
+ find /bin -type f -print |
+ awk '{
+ ++i;
+ printf("p\nk%d\nD%s\ng\nk%d\n", i, $0, i);
+ }' > $TMP2
+ for psize in 512 16384 65536; do
+ echo " page size $psize"
+ $PROG -i psize=$psize -o $TMP3 recno $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test3: recno: page size $psize: failed"
+ exit 1
+ fi
+ done
+}
+
+# Do random recno entries.
+test4()
+{
+ echo "Test 4: recno: random entries"
+ echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+ awk '{
+ for (i = 37; i <= 37 + 88 * 17; i += 17) {
+ if (i % 41)
+ s = substr($0, 1, i % 41);
+ else
+ s = substr($0, 1);
+ printf("input key %d: %s\n", i, s);
+ }
+ for (i = 1; i <= 15; ++i) {
+ if (i % 41)
+ s = substr($0, 1, i % 41);
+ else
+ s = substr($0, 1);
+ printf("input key %d: %s\n", i, s);
+ }
+ for (i = 19234; i <= 19234 + 61 * 27; i += 27) {
+ if (i % 41)
+ s = substr($0, 1, i % 41);
+ else
+ s = substr($0, 1);
+ printf("input key %d: %s\n", i, s);
+ }
+ exit
+ }' > $TMP1
+ rm -f $TMP2 $TMP3
+ cat $TMP1 |
+ awk 'BEGIN {
+ i = 37;
+ incr = 17;
+ }
+ {
+ printf("p\nk%d\nd%s\n", i, $0);
+ if (i == 19234 + 61 * 27)
+ exit;
+ if (i == 37 + 88 * 17) {
+ i = 1;
+ incr = 1;
+ } else if (i == 15) {
+ i = 19234;
+ incr = 27;
+ } else
+ i += incr;
+ }
+ END {
+ for (i = 37; i <= 37 + 88 * 17; i += 17)
+ printf("g\nk%d\n", i);
+ for (i = 1; i <= 15; ++i)
+ printf("g\nk%d\n", i);
+ for (i = 19234; i <= 19234 + 61 * 27; i += 27)
+ printf("g\nk%d\n", i);
+ }' > $TMP2
+ $PROG -o $TMP3 recno $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test4: type recno: failed"
+ exit 1
+ fi
+}
+
+# Do reverse order recno entries.
+test5()
+{
+ echo "Test 5: recno: reverse order entries"
+ echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+ awk ' {
+ for (i = 1500; i; --i) {
+ if (i % 34)
+ s = substr($0, 1, i % 34);
+ else
+ s = substr($0, 1);
+ printf("input key %d: %s\n", i, s);
+ }
+ exit;
+ }' > $TMP1
+ rm -f $TMP2 $TMP3
+ cat $TMP1 |
+ awk 'BEGIN {
+ i = 1500;
+ }
+ {
+ printf("p\nk%d\nd%s\n", i, $0);
+ --i;
+ }
+ END {
+ for (i = 1500; i; --i)
+ printf("g\nk%d\n", i);
+ }' > $TMP2
+ $PROG -o $TMP3 recno $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test5: type recno: failed"
+ exit 1
+ fi
+}
+
+# Do alternating order recno entries.
+test6()
+{
+ echo "Test 6: recno: alternating order entries"
+ echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+ awk ' {
+ for (i = 1; i < 1200; i += 2) {
+ if (i % 34)
+ s = substr($0, 1, i % 34);
+ else
+ s = substr($0, 1);
+ printf("input key %d: %s\n", i, s);
+ }
+ for (i = 2; i < 1200; i += 2) {
+ if (i % 34)
+ s = substr($0, 1, i % 34);
+ else
+ s = substr($0, 1);
+ printf("input key %d: %s\n", i, s);
+ }
+ exit;
+ }' > $TMP1
+ rm -f $TMP2 $TMP3
+ cat $TMP1 |
+ awk 'BEGIN {
+ i = 1;
+ even = 0;
+ }
+ {
+ printf("p\nk%d\nd%s\n", i, $0);
+ i += 2;
+ if (i >= 1200) {
+ if (even == 1)
+ exit;
+ even = 1;
+ i = 2;
+ }
+ }
+ END {
+ for (i = 1; i < 1200; ++i)
+ printf("g\nk%d\n", i);
+ }' > $TMP2
+ $PROG -o $TMP3 recno $TMP2
+ sort -o $TMP1 $TMP1
+ sort -o $TMP3 $TMP3
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test6: type recno: failed"
+ exit 1
+ fi
+}
+
+# Delete cursor record
+test7()
+{
+ echo "Test 7: btree, recno: delete cursor record"
+ echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+ awk '{
+ for (i = 1; i <= 120; ++i)
+ printf("%05d: input key %d: %s\n", i, i, $0);
+ printf("%05d: input key %d: %s\n", 120, 120, $0);
+ printf("seq failed, no such key\n");
+ printf("%05d: input key %d: %s\n", 1, 1, $0);
+ printf("%05d: input key %d: %s\n", 2, 2, $0);
+ exit;
+ }' > $TMP1
+ rm -f $TMP2 $TMP3
+
+ for type in btree recno; do
+ cat $TMP1 |
+ awk '{
+ if (i == 120)
+ exit;
+ printf("p\nk%d\nd%s\n", ++i, $0);
+ }
+ END {
+ printf("fR_NEXT\n");
+ for (i = 1; i <= 120; ++i)
+ printf("s\n");
+ printf("fR_CURSOR\ns\nk120\n");
+ printf("r\n");
+ printf("fR_NEXT\ns\n");
+ printf("fR_CURSOR\ns\nk1\n");
+ printf("r\n");
+ printf("fR_FIRST\ns\n");
+ }' > $TMP2
+ $PROG -o $TMP3 recno $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test7: type $type: failed"
+ exit 1
+ fi
+ done
+}
+
+# Make sure that overflow pages are reused.
+test8()
+{
+ echo "Test 8: btree, hash: repeated small key, big data pairs"
+ rm -f $TMP1
+ echo "" |
+ awk 'BEGIN {
+ for (i = 1; i <= 10; ++i) {
+ printf("p\nkkey1\nD/bin/sh\n");
+ printf("p\nkkey2\nD/bin/csh\n");
+ if (i % 8 == 0) {
+ printf("c\nkkey2\nD/bin/csh\n");
+ printf("c\nkkey1\nD/bin/sh\n");
+ printf("e\t%d of 10 (comparison)\n", i);
+ } else
+ printf("e\t%d of 10 \n", i);
+ printf("r\nkkey1\nr\nkkey2\n");
+ }
+ }' > $TMP1
+ $PROG btree $TMP1
+# $PROG hash $TMP1
+ # No explicit test for success.
+}
+
+# Test btree duplicate keys
+test9()
+{
+ echo "Test 9: btree: duplicate keys"
+ echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+ awk '{
+ for (i = 1; i <= 543; ++i)
+ printf("%05d: input key %d: %s\n", i, i, $0);
+ exit;
+ }' > $TMP1
+ rm -f $TMP2 $TMP3
+
+ for type in btree; do
+ cat $TMP1 |
+ awk '{
+ if (i++ % 2)
+ printf("p\nkduplicatekey\nd%s\n", $0);
+ else
+ printf("p\nkunique%dkey\nd%s\n", i, $0);
+ }
+ END {
+ printf("o\n");
+ }' > $TMP2
+ $PROG -iflags=1 -o $TMP3 $type $TMP2
+ sort -o $TMP3 $TMP3
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test9: type $type: failed"
+ exit 1
+ fi
+ done
+}
+
+# Test use of cursor flags without initialization
+test10()
+{
+ echo "Test 10: btree, recno: test cursor flag use"
+ echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+ awk '{
+ for (i = 1; i <= 20; ++i)
+ printf("%05d: input key %d: %s\n", i, i, $0);
+ exit;
+ }' > $TMP1
+ rm -f $TMP2 $TMP3
+
+ # Test that R_CURSOR doesn't succeed before cursor initialized
+ for type in btree recno; do
+ cat $TMP1 |
+ awk '{
+ if (i == 10)
+ exit;
+ printf("p\nk%d\nd%s\n", ++i, $0);
+ }
+ END {
+ printf("fR_CURSOR\nr\n");
+ printf("eR_CURSOR SHOULD HAVE FAILED\n");
+ }' > $TMP2
+ $PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
+ if [ -s $TMP3 ] ; then
+ echo "Test 10: delete: R_CURSOR SHOULD HAVE FAILED"
+ exit 1
+ fi
+ done
+ for type in btree recno; do
+ cat $TMP1 |
+ awk '{
+ if (i == 10)
+ exit;
+ printf("p\nk%d\nd%s\n", ++i, $0);
+ }
+ END {
+ printf("fR_CURSOR\np\nk1\ndsome data\n");
+ printf("eR_CURSOR SHOULD HAVE FAILED\n");
+ }' > $TMP2
+ $PROG -o $TMP3 $type $TMP2 > /dev/null 2>&1
+ if [ -s $TMP3 ] ; then
+ echo "Test 10: put: R_CURSOR SHOULD HAVE FAILED"
+ exit 1
+ fi
+ done
+}
+
+# Test insert in reverse order.
+test11()
+{
+ echo "Test 11: recno: reverse order insert"
+ echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+ awk '{
+ for (i = 1; i <= 779; ++i)
+ printf("%05d: input key %d: %s\n", i, i, $0);
+ exit;
+ }' > $TMP1
+ rm -f $TMP2 $TMP3
+
+ for type in recno; do
+ cat $TMP1 |
+ awk '{
+ if (i == 0) {
+ i = 1;
+ printf("p\nk1\nd%s\n", $0);
+ printf("%s\n", "fR_IBEFORE");
+ } else
+ printf("p\nk1\nd%s\n", $0);
+ }
+ END {
+ printf("or\n");
+ }' > $TMP2
+ $PROG -o $TMP3 $type $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test11: type $type: failed"
+ exit 1
+ fi
+ done
+}
+
+# Take the first 20000 entries in the dictionary, reverse them, and give
+# them each a small size data entry. Use a small page size to make sure
+# the btree split code gets hammered.
+test12()
+{
+ echo "Test 12: btree: lots of keys, small page size"
+ mdata=abcdefghijklmnopqrstuvwxy
+ echo $mdata |
+ awk '{ for (i = 1; i < 20001; ++i) print $0 }' > $TMP1
+ for type in btree; do
+ rm -f $TMP2 $TMP3
+ for i in `sed 20000q $DICT | rev`; do
+ echo p
+ echo k$i
+ echo d$mdata
+ echo g
+ echo k$i
+ done > $TMP2
+ $PROG -i psize=512 -o $TMP3 $type $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test12: type $type: failed"
+ exit 1
+ fi
+ done
+}
+
+# Test different byte orders.
+test13()
+{
+ echo "Test 13: btree, hash: differing byte orders"
+ sed 50q $DICT > $TMP1
+ for order in 1234 4321; do
+ for type in btree hash; do
+ rm -f byte.file $TMP2 $TMP3
+ for i in `sed 50q $DICT`; do
+ echo p
+ echo k$i
+ echo d$i
+ echo g
+ echo k$i
+ done > $TMP2
+ $PROG -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test13: $type/$order put failed"
+ exit 1
+ fi
+ for i in `sed 50q $DICT`; do
+ echo g
+ echo k$i
+ done > $TMP2
+ $PROG -s \
+ -ilorder=$order -f byte.file -o $TMP3 $type $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test13: $type/$order get failed"
+ exit 1
+ fi
+ done
+ done
+ rm -f byte.file
+}
+
+# Try a variety of bucketsizes and fill factors for hashing
+test20()
+{
+ echo\
+ "Test 20: hash: bucketsize, fill factor; nelem 25000 cachesize 65536"
+ echo "abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg" |
+ awk '{
+ for (i = 1; i <= 10000; ++i) {
+ if (i % 34)
+ s = substr($0, 1, i % 34);
+ else
+ s = substr($0, 1);
+ printf("%s\n", s);
+ }
+ exit;
+ }' > $TMP1
+ sed 10000q $DICT |
+ awk 'BEGIN {
+ ds="abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg abcdefg"
+ }
+ {
+ if (++i % 34)
+ s = substr(ds, 1, i % 34);
+ else
+ s = substr(ds, 1);
+ printf("p\nk%s\nd%s\n", $0, s);
+ }' > $TMP2
+ sed 10000q $DICT |
+ awk '{
+ ++i;
+ printf("g\nk%s\n", $0);
+ }' >> $TMP2
+ bsize=256
+ for ffactor in 11 14 21; do
+ echo " bucketsize $bsize, fill factor $ffactor"
+ $PROG -o$TMP3 \
+ -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+ hash $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+ exit 1
+ fi
+ done
+ bsize=512
+ for ffactor in 21 28 43; do
+ echo " bucketsize $bsize, fill factor $ffactor"
+ $PROG -o$TMP3 \
+ -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+ hash $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+ exit 1
+ fi
+ done
+ bsize=1024
+ for ffactor in 43 57 85; do
+ echo " bucketsize $bsize, fill factor $ffactor"
+ $PROG -o$TMP3 \
+ -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+ hash $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+ exit 1
+ fi
+ done
+ bsize=2048
+ for ffactor in 85 114 171; do
+ echo " bucketsize $bsize, fill factor $ffactor"
+ $PROG -o$TMP3 \
+ -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+ hash $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+ exit 1
+ fi
+ done
+ bsize=4096
+ for ffactor in 171 228 341; do
+ echo " bucketsize $bsize, fill factor $ffactor"
+ $PROG -o$TMP3 \
+ -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+ hash $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+ exit 1
+ fi
+ done
+ bsize=8192
+ for ffactor in 341 455 683; do
+ echo " bucketsize $bsize, fill factor $ffactor"
+ $PROG -o$TMP3 \
+ -ibsize=$bsize,ffactor=$ffactor,nelem=25000,cachesize=65536\
+ hash $TMP2
+ if (cmp -s $TMP1 $TMP3) ; then :
+ else
+ echo "test20: type hash:\
+bsize=$bsize ffactor=$ffactor nelem=25000 cachesize=65536 failed"
+ exit 1
+ fi
+ done
+}
+
+main $*
diff --git a/lib/libc/gdtoa/Makefile.inc b/lib/libc/gdtoa/Makefile.inc
new file mode 100644
index 0000000..0d6832f
--- /dev/null
+++ b/lib/libc/gdtoa/Makefile.inc
@@ -0,0 +1,20 @@
+# $FreeBSD$
+
+# netlib gdtoa sources
+.PATH: ${.CURDIR}/gdtoa
+
+MISRCS+=_hdtoa.c _hldtoa.c _ldtoa.c glue.c
+GDTOASRCS+=dmisc.c dtoa.c gdtoa.c gethex.c gmisc.c \
+ hd_init.c hexnan.c misc.c smisc.c \
+ strtod.c strtodg.c strtof.c strtord.c sum.c ulp.c
+
+SYM_MAPS+=${.CURDIR}/gdtoa/Symbol.map
+
+CFLAGS+=-I${.CURDIR}/../../contrib/gdtoa
+
+.for src in ${GDTOASRCS}
+MISRCS+=gdtoa_${src}
+CLEANFILES+=gdtoa_${src}
+gdtoa_${src}:
+ ln -sf ${.CURDIR}/../../contrib/gdtoa/${src} ${.TARGET}
+.endfor
diff --git a/lib/libc/gdtoa/Symbol.map b/lib/libc/gdtoa/Symbol.map
new file mode 100644
index 0000000..4483e9a
--- /dev/null
+++ b/lib/libc/gdtoa/Symbol.map
@@ -0,0 +1,19 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ /*
+ * Standard functions from contrib/gdtoa
+ */
+ strtod;
+ strtof;
+
+ /* FreeBSD additions */
+ strtold;
+};
+
+FBSDprivate_1.0 {
+ /* used in libm */
+ __hexnan_D2A;
+};
diff --git a/lib/libc/gdtoa/_hdtoa.c b/lib/libc/gdtoa/_hdtoa.c
new file mode 100644
index 0000000..6f8ccac
--- /dev/null
+++ b/lib/libc/gdtoa/_hdtoa.c
@@ -0,0 +1,144 @@
+/*-
+ * Copyright (c) 2004-2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+
+#include "../stdio/floatio.h"
+#include "fpmath.h"
+#include "gdtoaimp.h"
+
+/* Strings values used by dtoa() */
+#define INFSTR "Infinity"
+#define NANSTR "NaN"
+
+#define DBL_ADJ (DBL_MAX_EXP - 2)
+#define SIGFIGS ((DBL_MANT_DIG + 3) / 4 + 1)
+
+static const float one[] = { 1.0f, -1.0f };
+
+/*
+ * This procedure converts a double-precision number in IEEE format
+ * into a string of hexadecimal digits and an exponent of 2. Its
+ * behavior is bug-for-bug compatible with dtoa() in mode 2, with the
+ * following exceptions:
+ *
+ * - An ndigits < 0 causes it to use as many digits as necessary to
+ * represent the number exactly.
+ * - The additional xdigs argument should point to either the string
+ * "0123456789ABCDEF" or the string "0123456789abcdef", depending on
+ * which case is desired.
+ * - This routine does not repeat dtoa's mistake of setting decpt
+ * to 9999 in the case of an infinity or NaN. INT_MAX is used
+ * for this purpose instead.
+ *
+ * Note that the C99 standard does not specify what the leading digit
+ * should be for non-zero numbers. For instance, 0x1.3p3 is the same
+ * as 0x2.6p2 is the same as 0x4.cp3. This implementation always makes
+ * the leading digit a 1. This ensures that the exponent printed is the
+ * actual base-2 exponent, i.e., ilogb(d).
+ *
+ * Inputs: d, xdigs, ndigits
+ * Outputs: decpt, sign, rve
+ */
+char *
+__hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign,
+ char **rve)
+{
+ union IEEEd2bits u;
+ char *s, *s0;
+ int bufsize;
+ uint32_t manh, manl;
+
+ u.d = d;
+ *sign = u.bits.sign;
+
+ switch (fpclassify(d)) {
+ case FP_NORMAL:
+ *decpt = u.bits.exp - DBL_ADJ;
+ break;
+ case FP_ZERO:
+ *decpt = 1;
+ return (nrv_alloc("0", rve, 1));
+ case FP_SUBNORMAL:
+ u.d *= 0x1p514;
+ *decpt = u.bits.exp - (514 + DBL_ADJ);
+ break;
+ case FP_INFINITE:
+ *decpt = INT_MAX;
+ return (nrv_alloc(INFSTR, rve, sizeof(INFSTR) - 1));
+ default: /* FP_NAN or unrecognized */
+ *decpt = INT_MAX;
+ return (nrv_alloc(NANSTR, rve, sizeof(NANSTR) - 1));
+ }
+
+ /* FP_NORMAL or FP_SUBNORMAL */
+
+ if (ndigits == 0) /* dtoa() compatibility */
+ ndigits = 1;
+
+ /*
+ * If ndigits < 0, we are expected to auto-size, so we allocate
+ * enough space for all the digits.
+ */
+ bufsize = (ndigits > 0) ? ndigits : SIGFIGS;
+ s0 = rv_alloc(bufsize);
+
+ /* Round to the desired number of digits. */
+ if (SIGFIGS > ndigits && ndigits > 0) {
+ float redux = one[u.bits.sign];
+ int offset = 4 * ndigits + DBL_MAX_EXP - 4 - DBL_MANT_DIG;
+ u.bits.exp = offset;
+ u.d += redux;
+ u.d -= redux;
+ *decpt += u.bits.exp - offset;
+ }
+
+ manh = u.bits.manh;
+ manl = u.bits.manl;
+ *s0 = '1';
+ for (s = s0 + 1; s < s0 + bufsize; s++) {
+ *s = xdigs[(manh >> (DBL_MANH_SIZE - 4)) & 0xf];
+ manh = (manh << 4) | (manl >> (DBL_MANL_SIZE - 4));
+ manl <<= 4;
+ }
+
+ /* If ndigits < 0, we are expected to auto-size the precision. */
+ if (ndigits < 0) {
+ for (ndigits = SIGFIGS; s0[ndigits - 1] == '0'; ndigits--)
+ ;
+ }
+
+ s = s0 + ndigits;
+ *s = '\0';
+ if (rve != NULL)
+ *rve = s;
+ return (s0);
+}
diff --git a/lib/libc/gdtoa/_hldtoa.c b/lib/libc/gdtoa/_hldtoa.c
new file mode 100644
index 0000000..97394ea
--- /dev/null
+++ b/lib/libc/gdtoa/_hldtoa.c
@@ -0,0 +1,177 @@
+/*-
+ * Copyright (c) 2004-2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <float.h>
+#include <limits.h>
+#include <math.h>
+#include <stdint.h>
+
+#ifdef __i386__
+#include <ieeefp.h>
+#endif
+
+#include "../stdio/floatio.h"
+#include "fpmath.h"
+#include "gdtoaimp.h"
+
+#if (LDBL_MANT_DIG > DBL_MANT_DIG)
+
+/* Strings values used by dtoa() */
+#define INFSTR "Infinity"
+#define NANSTR "NaN"
+
+#ifdef LDBL_IMPLICIT_NBIT
+#define MANH_SIZE LDBL_MANH_SIZE
+#else
+#define MANH_SIZE (LDBL_MANH_SIZE - 1)
+#endif
+
+#if MANH_SIZE > 32
+typedef uint64_t manh_t;
+#else
+typedef uint32_t manh_t;
+#endif
+
+#if LDBL_MANL_SIZE > 32
+typedef uint64_t manl_t;
+#else
+typedef uint32_t manl_t;
+#endif
+
+#define LDBL_ADJ (LDBL_MAX_EXP - 2)
+#define SIGFIGS ((LDBL_MANT_DIG + 3) / 4 + 1)
+
+static const float one[] = { 1.0f, -1.0f };
+
+/*
+ * This is the long double version of __hdtoa().
+ */
+char *
+__hldtoa(long double e, const char *xdigs, int ndigits, int *decpt, int *sign,
+ char **rve)
+{
+ union IEEEl2bits u;
+ char *s, *s0;
+ manh_t manh;
+ manl_t manl;
+ int bufsize;
+#ifdef __i386__
+ fp_prec_t oldprec;
+#endif
+
+ u.e = e;
+ *sign = u.bits.sign;
+
+ switch (fpclassify(e)) {
+ case FP_NORMAL:
+ *decpt = u.bits.exp - LDBL_ADJ;
+ break;
+ case FP_ZERO:
+ *decpt = 1;
+ return (nrv_alloc("0", rve, 1));
+ case FP_SUBNORMAL:
+#ifdef __i386__
+ oldprec = fpsetprec(FP_PE);
+#endif
+ u.e *= 0x1p514L;
+ *decpt = u.bits.exp - (514 + LDBL_ADJ);
+#ifdef __i386__
+ fpsetprec(oldprec);
+#endif
+ break;
+ case FP_INFINITE:
+ *decpt = INT_MAX;
+ return (nrv_alloc(INFSTR, rve, sizeof(INFSTR) - 1));
+ default: /* FP_NAN or unrecognized */
+ *decpt = INT_MAX;
+ return (nrv_alloc(NANSTR, rve, sizeof(NANSTR) - 1));
+ }
+
+ /* FP_NORMAL or FP_SUBNORMAL */
+
+ if (ndigits == 0) /* dtoa() compatibility */
+ ndigits = 1;
+
+ /*
+ * If ndigits < 0, we are expected to auto-size, so we allocate
+ * enough space for all the digits.
+ */
+ bufsize = (ndigits > 0) ? ndigits : SIGFIGS;
+ s0 = rv_alloc(bufsize);
+
+ /* Round to the desired number of digits. */
+ if (SIGFIGS > ndigits && ndigits > 0) {
+ float redux = one[u.bits.sign];
+ int offset = 4 * ndigits + LDBL_MAX_EXP - 4 - LDBL_MANT_DIG;
+#ifdef __i386__
+ oldprec = fpsetprec(FP_PE);
+#endif
+ u.bits.exp = offset;
+ u.e += redux;
+ u.e -= redux;
+ *decpt += u.bits.exp - offset;
+#ifdef __i386__
+ fpsetprec(oldprec);
+#endif
+ }
+
+ mask_nbit_l(u);
+ manh = u.bits.manh;
+ manl = u.bits.manl;
+ *s0 = '1';
+ for (s = s0 + 1; s < s0 + bufsize; s++) {
+ *s = xdigs[(manh >> (MANH_SIZE - 4)) & 0xf];
+ manh = (manh << 4) | (manl >> (LDBL_MANL_SIZE - 4));
+ manl <<= 4;
+ }
+
+ /* If ndigits < 0, we are expected to auto-size the precision. */
+ if (ndigits < 0) {
+ for (ndigits = SIGFIGS; s0[ndigits - 1] == '0'; ndigits--)
+ ;
+ }
+
+ s = s0 + ndigits;
+ *s = '\0';
+ if (rve != NULL)
+ *rve = s;
+ return (s0);
+}
+
+#else /* (LDBL_MANT_DIG == DBL_MANT_DIG) */
+
+char *
+__hldtoa(long double e, const char *xdigs, int ndigits, int *decpt, int *sign,
+ char **rve)
+{
+
+ return (__hdtoa((double)e, xdigs, ndigits, decpt, sign, rve));
+}
+
+#endif /* (LDBL_MANT_DIG == DBL_MANT_DIG) */
diff --git a/lib/libc/gdtoa/_ldtoa.c b/lib/libc/gdtoa/_ldtoa.c
new file mode 100644
index 0000000..60c6b22
--- /dev/null
+++ b/lib/libc/gdtoa/_ldtoa.c
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <float.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <math.h>
+#include <stdlib.h>
+#include "fpmath.h"
+#include "gdtoaimp.h"
+
+/*
+ * ldtoa() is a wrapper for gdtoa() that makes it smell like dtoa(),
+ * except that the floating point argument is passed by reference.
+ * When dtoa() is passed a NaN or infinity, it sets expt to 9999.
+ * However, a long double could have a valid exponent of 9999, so we
+ * use INT_MAX in ldtoa() instead.
+ */
+char *
+__ldtoa(long double *ld, int mode, int ndigits, int *decpt, int *sign,
+ char **rve)
+{
+ FPI fpi = {
+ LDBL_MANT_DIG, /* nbits */
+ LDBL_MIN_EXP - LDBL_MANT_DIG, /* emin */
+ LDBL_MAX_EXP - LDBL_MANT_DIG, /* emax */
+ FLT_ROUNDS, /* rounding */
+#ifdef Sudden_Underflow /* unused, but correct anyway */
+ 1
+#else
+ 0
+#endif
+ };
+ int be, kind;
+ char *ret;
+ union IEEEl2bits u;
+ uint32_t bits[(LDBL_MANT_DIG + 31) / 32];
+ void *vbits = bits;
+
+ u.e = *ld;
+
+ /*
+ * gdtoa doesn't know anything about the sign of the number, so
+ * if the number is negative, we need to swap rounding modes of
+ * 2 (upwards) and 3 (downwards).
+ */
+ *sign = u.bits.sign;
+ fpi.rounding ^= (fpi.rounding >> 1) & u.bits.sign;
+
+ be = u.bits.exp - (LDBL_MAX_EXP - 1) - (LDBL_MANT_DIG - 1);
+ LDBL_TO_ARRAY32(u, bits);
+
+ switch (fpclassify(u.e)) {
+ case FP_NORMAL:
+ kind = STRTOG_Normal;
+#ifdef LDBL_IMPLICIT_NBIT
+ bits[LDBL_MANT_DIG / 32] |= 1 << ((LDBL_MANT_DIG - 1) % 32);
+#endif /* LDBL_IMPLICIT_NBIT */
+ break;
+ case FP_ZERO:
+ kind = STRTOG_Zero;
+ break;
+ case FP_SUBNORMAL:
+ kind = STRTOG_Denormal;
+ be++;
+ break;
+ case FP_INFINITE:
+ kind = STRTOG_Infinite;
+ break;
+ case FP_NAN:
+ kind = STRTOG_NaN;
+ break;
+ default:
+ abort();
+ }
+
+ ret = gdtoa(&fpi, be, vbits, &kind, mode, ndigits, decpt, rve);
+ if (*decpt == -32768)
+ *decpt = INT_MAX;
+ return ret;
+}
diff --git a/lib/libc/gdtoa/glue.c b/lib/libc/gdtoa/glue.c
new file mode 100644
index 0000000..39e491a
--- /dev/null
+++ b/lib/libc/gdtoa/glue.c
@@ -0,0 +1,13 @@
+/*
+ * Machine-independent glue to integrate David Gay's gdtoa
+ * package into libc.
+ *
+ * $FreeBSD$
+ */
+
+#include <pthread.h>
+
+pthread_mutex_t __gdtoa_locks[] = {
+ PTHREAD_MUTEX_INITIALIZER,
+ PTHREAD_MUTEX_INITIALIZER
+};
diff --git a/lib/libc/gdtoa/machdep_ldisQ.c b/lib/libc/gdtoa/machdep_ldisQ.c
new file mode 100644
index 0000000..7b5c7af
--- /dev/null
+++ b/lib/libc/gdtoa/machdep_ldisQ.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Machine-dependent glue to integrate David Gay's gdtoa
+ * package into libc for architectures where a long double
+ * uses quad precision, such as sparc64.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <float.h>
+
+#include "gdtoaimp.h"
+
+long double
+strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale)
+{
+ long double result;
+
+ strtorQ_l(s, sp, FLT_ROUNDS, &result, locale);
+ return result;
+}
diff --git a/lib/libc/gdtoa/machdep_ldisd.c b/lib/libc/gdtoa/machdep_ldisd.c
new file mode 100644
index 0000000..d5c7329
--- /dev/null
+++ b/lib/libc/gdtoa/machdep_ldisd.c
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Machine-dependent glue to integrate David Gay's gdtoa
+ * package into libc for architectures where a long double
+ * is the same as a double, such as the Alpha.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "gdtoaimp.h"
+#undef strtold_l
+
+long double
+strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale)
+{
+
+ return strtod_l(s, sp, locale);
+}
diff --git a/lib/libc/gdtoa/machdep_ldisx.c b/lib/libc/gdtoa/machdep_ldisx.c
new file mode 100644
index 0000000..b8e2a05
--- /dev/null
+++ b/lib/libc/gdtoa/machdep_ldisx.c
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Machine-dependent glue to integrate David Gay's gdtoa
+ * package into libc for architectures where a long double
+ * is an IEEE extended precision number.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <float.h>
+
+#include "gdtoaimp.h"
+
+long double
+strtold_l(const char * __restrict s, char ** __restrict sp, locale_t locale)
+{
+ long double result;
+ FIX_LOCALE(locale);
+
+ strtorx_l(s, sp, FLT_ROUNDS, &result, locale);
+ return result;
+}
diff --git a/lib/libc/gen/Makefile.inc b/lib/libc/gen/Makefile.inc
new file mode 100644
index 0000000..0362ce0
--- /dev/null
+++ b/lib/libc/gen/Makefile.inc
@@ -0,0 +1,193 @@
+# @(#)Makefile.inc 8.6 (Berkeley) 5/4/95
+# $FreeBSD$
+
+# machine-independent gen sources
+.PATH: ${.CURDIR}/${LIBC_ARCH}/gen ${.CURDIR}/gen
+
+SRCS+= __getosreldate.c __xuname.c \
+ _once_stub.c _pthread_stubs.c _rand48.c _spinlock_stub.c \
+ _thread_init.c \
+ alarm.c arc4random.c assert.c aux.c basename.c check_utility_compat.c \
+ clock.c closedir.c confstr.c \
+ crypt.c ctermid.c daemon.c devname.c dirname.c disklabel.c \
+ dlfcn.c drand48.c elf_utils.c erand48.c err.c errlst.c errno.c \
+ exec.c fdevname.c feature_present.c fmtcheck.c fmtmsg.c fnmatch.c \
+ fpclassify.c frexp.c fstab.c ftok.c fts.c fts-compat.c ftw.c \
+ getbootfile.c getbsize.c \
+ getcap.c getcwd.c getdomainname.c getgrent.c getgrouplist.c \
+ gethostname.c getloadavg.c getlogin.c getmntinfo.c getnetgrent.c \
+ getosreldate.c getpagesize.c getpagesizes.c \
+ getpeereid.c getprogname.c getpwent.c getttyent.c \
+ getusershell.c getutxent.c getvfsbyname.c glob.c \
+ initgroups.c isatty.c isinf.c isnan.c jrand48.c lcong48.c \
+ libc_dlopen.c \
+ lockf.c lrand48.c mrand48.c nftw.c nice.c \
+ nlist.c nrand48.c opendir.c \
+ pause.c pmadvise.c popen.c posix_spawn.c \
+ psignal.c pututxline.c pw_scan.c pwcache.c \
+ raise.c readdir.c readpassphrase.c rewinddir.c \
+ scandir.c seed48.c seekdir.c semctl.c \
+ setdomainname.c sethostname.c setjmperr.c setmode.c \
+ setproctitle.c setprogname.c siginterrupt.c siglist.c signal.c \
+ sigsetops.c sleep.c srand48.c statvfs.c stringlist.c strtofflags.c \
+ sysconf.c sysctl.c sysctlbyname.c sysctlnametomib.c \
+ syslog.c telldir.c termios.c time.c times.c timezone.c tls.c \
+ ttyname.c ttyslot.c ualarm.c ulimit.c uname.c unvis.c \
+ usleep.c utime.c utxdb.c valloc.c vis.c wait.c wait3.c waitpid.c \
+ wordexp.c
+
+MISRCS+=modf.c
+
+CANCELPOINTS_SRCS=sem.c sem_new.c
+.for src in ${CANCELPOINTS_SRCS}
+SRCS+=cancelpoints_${src}
+CLEANFILES+=cancelpoints_${src}
+cancelpoints_${src}:
+ ln -sf ${.CURDIR}/gen/${src} ${.TARGET}
+.endfor
+
+SYM_MAPS+=${.CURDIR}/gen/Symbol.map
+
+# machine-dependent gen sources
+.sinclude "${.CURDIR}/${LIBC_ARCH}/gen/Makefile.inc"
+
+MAN+= alarm.3 arc4random.3 \
+ basename.3 check_utility_compat.3 clock.3 \
+ confstr.3 ctermid.3 daemon.3 devname.3 directory.3 dirname.3 \
+ dl_iterate_phdr.3 dladdr.3 dlinfo.3 dllockinit.3 dlopen.3 \
+ err.3 exec.3 \
+ feature_present.3 fmtcheck.3 fmtmsg.3 fnmatch.3 fpclassify.3 frexp.3 \
+ ftok.3 fts.3 ftw.3 \
+ getbootfile.3 getbsize.3 getcap.3 getcontext.3 getcwd.3 \
+ getdiskbyname.3 getdomainname.3 getfsent.3 \
+ getgrent.3 getgrouplist.3 gethostname.3 getloadavg.3 \
+ getmntinfo.3 getnetgrent.3 getosreldate.3 getpagesize.3 \
+ getpagesizes.3 getpass.3 getpeereid.3 getprogname.3 getpwent.3 \
+ getttyent.3 getusershell.3 getutxent.3 getvfsbyname.3 \
+ glob.3 initgroups.3 isgreater.3 ldexp.3 lockf.3 makecontext.3 \
+ modf.3 \
+ nice.3 nlist.3 pause.3 popen.3 \
+ posix_spawn.3 posix_spawn_file_actions_addopen.3 \
+ posix_spawn_file_actions_init.3 posix_spawnattr_getflags.3 \
+ posix_spawnattr_getpgroup.3 posix_spawnattr_getschedparam.3 \
+ posix_spawnattr_getschedpolicy.3 posix_spawnattr_init.3 \
+ posix_spawnattr_getsigdefault.3 posix_spawnattr_getsigmask.3 \
+ psignal.3 pwcache.3 \
+ raise.3 rand48.3 readpassphrase.3 rfork_thread.3 \
+ scandir.3 sem_destroy.3 sem_getvalue.3 sem_init.3 \
+ sem_open.3 sem_post.3 sem_timedwait.3 sem_wait.3 \
+ setjmp.3 setmode.3 setproctitle.3 \
+ siginterrupt.3 signal.3 sigsetops.3 sleep.3 \
+ statvfs.3 stringlist.3 \
+ strtofflags.3 sysconf.3 sysctl.3 syslog.3 tcgetpgrp.3 tcgetsid.3 \
+ tcsendbreak.3 tcsetattr.3 tcsetpgrp.3 tcsetsid.3 time.3 times.3 \
+ timezone.3 ttyname.3 tzset.3 ualarm.3 ucontext.3 ulimit.3 uname.3 \
+ unvis.3 usleep.3 utime.3 valloc.3 vis.3 wordexp.3
+
+MLINKS+=arc4random.3 arc4random_addrandom.3 arc4random.3 arc4random_stir.3 \
+ arc4random.3 arc4random_buf.3 arc4random.3 arc4random_uniform.3
+MLINKS+=basename.3 basename_r.3
+MLINKS+=ctermid.3 ctermid_r.3
+MLINKS+=devname.3 devname_r.3
+MLINKS+=devname.3 fdevname.3
+MLINKS+=devname.3 fdevname_r.3
+MLINKS+=directory.3 closedir.3 directory.3 dirfd.3 directory.3 opendir.3 \
+ directory.3 fdopendir.3 \
+ directory.3 readdir.3 directory.3 readdir_r.3 directory.3 rewinddir.3 \
+ directory.3 seekdir.3 directory.3 telldir.3
+MLINKS+=dlopen.3 fdlopen.3 dlopen.3 dlclose.3 dlopen.3 dlerror.3 \
+ dlopen.3 dlfunc.3 dlopen.3 dlsym.3
+MLINKS+=err.3 err_set_exit.3 err.3 err_set_file.3 err.3 errc.3 err.3 errx.3 \
+ err.3 verr.3 err.3 verrc.3 err.3 verrx.3 err.3 vwarn.3 err.3 vwarnc.3 \
+ err.3 vwarnx.3 err.3 warnc.3 err.3 warn.3 err.3 warnx.3
+MLINKS+=exec.3 execl.3 exec.3 execle.3 exec.3 execlp.3 exec.3 exect.3 \
+ exec.3 execv.3 exec.3 execvP.3 exec.3 execvp.3
+MLINKS+=fpclassify.3 finite.3 fpclassify.3 finitef.3 \
+ fpclassify.3 isfinite.3 fpclassify.3 isinf.3 fpclassify.3 isnan.3 \
+ fpclassify.3 isnormal.3
+MLINKS+=frexp.3 frexpf.3 frexp.3 frexpl.3
+MLINKS+=fts.3 fts_children.3 fts.3 fts_close.3 fts.3 fts_open.3 \
+ fts.3 fts_read.3 fts.3 fts_set.3 fts.3 fts_set_clientptr.3 \
+ fts.3 fts_get_clientptr.3 fts.3 fts_get_stream.3
+MLINKS+=ftw.3 nftw.3
+MLINKS+=getcap.3 cgetcap.3 getcap.3 cgetclose.3 getcap.3 cgetent.3 \
+ getcap.3 cgetfirst.3 getcap.3 cgetmatch.3 getcap.3 cgetnext.3 \
+ getcap.3 cgetnum.3 getcap.3 cgetset.3 getcap.3 cgetstr.3 \
+ getcap.3 cgetustr.3
+MLINKS+=getcwd.3 getwd.3
+MLINKS+=getcontext.3 setcontext.3
+MLINKS+=getdomainname.3 setdomainname.3
+MLINKS+=getfsent.3 endfsent.3 getfsent.3 getfsfile.3 getfsent.3 getfsspec.3 \
+ getfsent.3 getfstype.3 getfsent.3 setfsent.3 \
+ getfsent.3 setfstab.3 getfsent.3 getfstab.3
+MLINKS+=getgrent.3 endgrent.3 getgrent.3 getgrgid.3 getgrent.3 getgrnam.3 \
+ getgrent.3 setgrent.3 getgrent.3 setgroupent.3 \
+ getgrent.3 getgrent_r.3 getgrent.3 getgrnam_r.3 getgrent.3 getgrgid_r.3
+MLINKS+=gethostname.3 sethostname.3
+MLINKS+=getnetgrent.3 endnetgrent.3 getnetgrent.3 innetgr.3 \
+ getnetgrent.3 setnetgrent.3
+MLINKS+=getprogname.3 setprogname.3
+MLINKS+=getpwent.3 endpwent.3 getpwent.3 getpwnam.3 getpwent.3 getpwuid.3 \
+ getpwent.3 setpassent.3 getpwent.3 setpwent.3 getpwent.3 setpwfile.3 \
+ getpwent.3 getpwent_r.3 getpwent.3 getpwnam_r.3 \
+ getpwent.3 getpwuid_r.3
+MLINKS+=getttyent.3 endttyent.3 getttyent.3 getttynam.3 \
+ getttyent.3 isdialuptty.3 getttyent.3 isnettty.3 \
+ getttyent.3 setttyent.3
+MLINKS+=getusershell.3 endusershell.3 getusershell.3 setusershell.3
+MLINKS+=getutxent.3 endutxent.3 getutxent.3 getutxid.3 \
+ getutxent.3 getutxline.3 getutxent.3 getutxuser.3 \
+ getutxent.3 pututxline.3 getutxent.3 setutxdb.3 \
+ getutxent.3 setutxent.3 getutxent.3 utmpx.3
+MLINKS+=glob.3 globfree.3
+MLINKS+=isgreater.3 isgreaterequal.3 isgreater.3 isless.3 \
+ isgreater.3 islessequal.3 isgreater.3 islessgreater.3 \
+ isgreater.3 isunordered.3
+MLINKS+=ldexp.3 ldexpf.3 ldexp.3 ldexpl.3
+MLINKS+=makecontext.3 swapcontext.3
+MLINKS+=modf.3 modff.3 modf.3 modfl.3
+MLINKS+=popen.3 pclose.3
+MLINKS+=posix_spawn.3 posix_spawnp.3 \
+ posix_spawn_file_actions_addopen.3 posix_spawn_file_actions_addclose.3 \
+ posix_spawn_file_actions_addopen.3 posix_spawn_file_actions_adddup2.3 \
+ posix_spawn_file_actions_init.3 posix_spawn_file_actions_destroy.3 \
+ posix_spawnattr_getflags.3 posix_spawnattr_setflags.3 \
+ posix_spawnattr_getpgroup.3 posix_spawnattr_setpgroup.3 \
+ posix_spawnattr_getschedparam.3 posix_spawnattr_setschedparam.3 \
+ posix_spawnattr_getschedpolicy.3 posix_spawnattr_setschedpolicy.3 \
+ posix_spawnattr_getsigdefault.3 posix_spawnattr_setsigdefault.3 \
+ posix_spawnattr_getsigmask.3 posix_spawnattr_setsigmask.3 \
+ posix_spawnattr_init.3 posix_spawnattr_destroy.3
+MLINKS+=psignal.3 strsignal.3 psignal.3 sys_siglist.3 psignal.3 sys_signame.3
+MLINKS+=pwcache.3 group_from_gid.3 pwcache.3 user_from_uid.3
+MLINKS+=rand48.3 _rand48.3 rand48.3 drand48.3 rand48.3 erand48.3 \
+ rand48.3 jrand48.3 rand48.3 lcong48.3 rand48.3 lrand48.3 \
+ rand48.3 mrand48.3 rand48.3 nrand48.3 rand48.3 seed48.3 \
+ rand48.3 srand48.3
+MLINKS+=scandir.3 alphasort.3
+MLINKS+=sem_open.3 sem_close.3 sem_open.3 sem_unlink.3
+MLINKS+=sem_wait.3 sem_trywait.3
+MLINKS+=setjmp.3 _longjmp.3 setjmp.3 _setjmp.3 setjmp.3 longjmp.3 \
+ setjmp.3 longjmperr.3 setjmp.3 longjmperror.3 \
+ setjmp.3 siglongjmp.3 setjmp.3 sigsetjmp.3
+MLINKS+=setmode.3 getmode.3
+MLINKS+=sigsetops.3 sigaddset.3 sigsetops.3 sigdelset.3 \
+ sigsetops.3 sigemptyset.3 sigsetops.3 sigfillset.3 \
+ sigsetops.3 sigismember.3
+MLINKS+=statvfs.3 fstatvfs.3
+MLINKS+=stringlist.3 sl_add.3 stringlist.3 sl_find.3 \
+ stringlist.3 sl_free.3 stringlist.3 sl_init.3
+MLINKS+=strtofflags.3 fflagstostr.3
+MLINKS+=sysctl.3 sysctlbyname.3 sysctl.3 sysctlnametomib.3
+MLINKS+=syslog.3 closelog.3 syslog.3 openlog.3 syslog.3 setlogmask.3 \
+ syslog.3 vsyslog.3
+MLINKS+=tcsendbreak.3 tcdrain.3 tcsendbreak.3 tcflow.3 tcsendbreak.3 tcflush.3
+MLINKS+=tcsetattr.3 cfgetispeed.3 tcsetattr.3 cfgetospeed.3 \
+ tcsetattr.3 cfmakeraw.3 tcsetattr.3 cfmakesane.3 \
+ tcsetattr.3 cfsetispeed.3 tcsetattr.3 cfsetospeed.3 \
+ tcsetattr.3 cfsetspeed.3 tcsetattr.3 tcgetattr.3
+MLINKS+=ttyname.3 isatty.3 ttyname.3 ttyname_r.3
+MLINKS+=tzset.3 tzsetwall.3
+MLINKS+=unvis.3 strunvis.3 unvis.3 strunvisx.3
+MLINKS+=vis.3 strvis.3 vis.3 strvisx.3
+MLINKS+=wordexp.3 wordfree.3
diff --git a/lib/libc/gen/Symbol.map b/lib/libc/gen/Symbol.map
new file mode 100644
index 0000000..d794c0a
--- /dev/null
+++ b/lib/libc/gen/Symbol.map
@@ -0,0 +1,513 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ __xuname;
+ pthread_atfork;
+ pthread_attr_destroy;
+ pthread_attr_getdetachstate;
+ pthread_attr_getguardsize;
+ pthread_attr_getinheritsched;
+ pthread_attr_getschedparam;
+ pthread_attr_getschedpolicy;
+ pthread_attr_getscope;
+ pthread_attr_getstackaddr;
+ pthread_attr_getstacksize;
+ pthread_attr_init;
+ pthread_attr_setdetachstate;
+ pthread_attr_setguardsize;
+ pthread_attr_setinheritsched;
+ pthread_attr_setschedparam;
+ pthread_attr_setschedpolicy;
+ pthread_attr_setscope;
+ pthread_attr_setstackaddr;
+ pthread_attr_setstacksize;
+ pthread_cancel;
+ pthread_cleanup_pop;
+ pthread_cleanup_push;
+ pthread_cond_broadcast;
+ pthread_cond_destroy;
+ pthread_cond_init;
+ pthread_cond_signal;
+ pthread_cond_timedwait;
+ pthread_cond_wait;
+ pthread_detach;
+ pthread_equal;
+ pthread_exit;
+ pthread_getspecific;
+ pthread_join;
+ pthread_key_create;
+ pthread_key_delete;
+ pthread_kill;
+ pthread_main_np;
+ pthread_mutex_destroy;
+ pthread_mutex_init;
+ pthread_mutex_lock;
+ pthread_mutex_trylock;
+ pthread_mutex_unlock;
+ pthread_mutexattr_destroy;
+ pthread_mutexattr_init;
+ pthread_mutexattr_settype;
+ pthread_once;
+ pthread_rwlock_destroy;
+ pthread_rwlock_init;
+ pthread_rwlock_rdlock;
+ pthread_rwlock_tryrdlock;
+ pthread_rwlock_trywrlock;
+ pthread_rwlock_unlock;
+ pthread_rwlock_wrlock;
+ pthread_self;
+ pthread_setcancelstate;
+ pthread_setcanceltype;
+ pthread_setspecific;
+ pthread_sigmask;
+ pthread_testcancel;
+ alarm;
+ arc4random;
+ arc4random_addrandom;
+ arc4random_stir;
+ __assert;
+ basename;
+ check_utility_compat;
+ clock;
+ closedir;
+ confstr;
+ encrypt;
+ des_setkey;
+ des_cipher;
+ setkey;
+ ctermid;
+ ctermid_r;
+ daemon;
+ devname;
+ devname_r;
+ dirname;
+ getdiskbyname;
+ dladdr;
+ dlclose;
+ dlerror;
+ dlfunc;
+ dllockinit;
+ dlopen;
+ dlsym;
+ dlvsym;
+ dlinfo;
+ dl_iterate_phdr;
+ drand48;
+ erand48;
+ err_set_file;
+ err_set_exit;
+ err;
+ verr;
+ errc;
+ verrc;
+ errx;
+ verrx;
+ warn;
+ vwarn;
+ warnc;
+ vwarnc;
+ warnx;
+ vwarnx;
+ sys_errlist;
+ sys_nerr;
+ errno;
+ execl;
+ execle;
+ execlp;
+ execv;
+ execvp;
+ execvP;
+ fmtcheck;
+ fmtmsg;
+ fnmatch;
+ __fpclassifyf;
+ __fpclassifyd;
+ __fpclassifyl;
+ frexp;
+ setfstab;
+ getfstab;
+ getfsent;
+ getfsspec;
+ getfsfile;
+ setfsent;
+ endfsent;
+ ftok;
+ ftw;
+ glob;
+ globfree;
+ getbootfile;
+ getbsize;
+ cgetset;
+ cgetcap;
+ cgetent;
+ cgetmatch;
+ cgetfirst;
+ cgetclose;
+ cgetnext;
+ cgetstr;
+ cgetustr;
+ cgetnum;
+ getcwd;
+ getdomainname;
+ setgrent;
+ setgroupent;
+ endgrent;
+ getgrent_r;
+ getgrnam_r;
+ getgrgid_r;
+ getgrnam;
+ getgrgid;
+ getgrent;
+ /*
+ * Why are __gr_parse_entry() and __gr_match_entry() not static in
+ * gen/getgrent.c?
+ */
+ getgrouplist;
+ gethostname;
+ getloadavg;
+ getlogin;
+ getlogin_r;
+ getmntinfo;
+ setnetgrent;
+ getnetgrent;
+ endnetgrent;
+ innetgr;
+ getosreldate;
+ getpagesize;
+ getpeereid;
+ _getprogname;
+ getprogname;
+ setpwent;
+ setpassent;
+ endpwent;
+ getpwent_r;
+ getpwnam_r;
+ getpwuid_r;
+ getpwnam;
+ getpwuid;
+ getpwent;
+ getttynam;
+ getttyent;
+ setttyent;
+ endttyent;
+ isdialuptty;
+ isnettty;
+ getusershell;
+ endusershell;
+ setusershell;
+ getvfsbyname;
+ __isnan;
+ isnan;
+ __isnanf;
+ isnanf;
+ __isinf;
+ isinf;
+ __isinff;
+ __isinfl;
+ isatty;
+ initgroups;
+ jrand48;
+ lcong48;
+ ldexp;
+ lockf;
+ lrand48;
+ modf;
+ mrand48;
+ nftw;
+ nice;
+ nlist;
+ nrand48;
+ opendir;
+ pause;
+ posix_madvise;
+ popen;
+ pclose;
+ psignal;
+ raise;
+ readdir;
+ readdir_r;
+ readpassphrase;
+ getpass;
+ rewinddir;
+ scandir;
+ alphasort;
+ seed48;
+ seekdir;
+ user_from_uid;
+ group_from_gid;
+ setdomainname;
+ sethostname;
+ longjmperror;
+ getmode;
+ setmode;
+ setproctitle;
+ setprogname;
+ siginterrupt;
+ sys_signame;
+ sys_siglist;
+ sys_nsig;
+ signal;
+ sigaddset;
+ sigdelset;
+ sigemptyset;
+ sigfillset;
+ sigismember;
+ sleep;
+ srand48;
+ fstatvfs;
+ statvfs;
+ sl_init;
+ sl_add;
+ sl_free;
+ sl_find;
+ fflagstostr;
+ strtofflags;
+ sysconf;
+ sysctl;
+ sysctlbyname;
+ sysctlnametomib;
+ syslog;
+ vsyslog;
+ openlog;
+ closelog;
+ setlogmask;
+ ttyname_r;
+ ttyname;
+ timezone;
+ times;
+ time;
+ telldir;
+ tcgetattr;
+ tcsetattr;
+ tcsetpgrp;
+ tcgetpgrp;
+ cfgetospeed;
+ cfgetispeed;
+ cfsetospeed;
+ cfsetispeed;
+ cfsetspeed;
+ cfmakeraw;
+ tcsendbreak;
+ _init_tls;
+ __tls_get_addr;
+ tcdrain;
+ tcflush;
+ tcflow;
+ ualarm;
+ ulimit;
+ uname;
+ unvis;
+ strunvis;
+ strunvisx;
+ usleep;
+ utime;
+ valloc;
+ vis;
+ strvis;
+ strvisx;
+ wait;
+ wait3;
+ waitpid;
+ wordexp;
+ wordfree;
+};
+
+FBSD_1.1 {
+ arc4random_buf;
+ arc4random_uniform;
+ fdevname;
+ fdevname_r;
+ fdopendir;
+ feature_present;
+ fts_children;
+ fts_close;
+ fts_get_clientptr;
+ fts_get_stream;
+ fts_open;
+ fts_read;
+ fts_set;
+ fts_set_clientptr;
+ posix_spawn;
+ posix_spawn_file_actions_addclose;
+ posix_spawn_file_actions_adddup2;
+ posix_spawn_file_actions_addopen;
+ posix_spawn_file_actions_destroy;
+ posix_spawn_file_actions_init;
+ posix_spawnattr_destroy;
+ posix_spawnattr_getflags;
+ posix_spawnattr_getpgroup;
+ posix_spawnattr_getschedparam;
+ posix_spawnattr_getschedpolicy;
+ posix_spawnattr_getsigdefault;
+ posix_spawnattr_getsigmask;
+ posix_spawnattr_init;
+ posix_spawnattr_setflags;
+ posix_spawnattr_setpgroup;
+ posix_spawnattr_setschedparam;
+ posix_spawnattr_setschedpolicy;
+ posix_spawnattr_setsigdefault;
+ posix_spawnattr_setsigmask;
+ posix_spawnp;
+ semctl;
+ tcgetsid;
+ tcsetsid;
+ __pthread_cleanup_pop_imp;
+ __pthread_cleanup_push_imp;
+};
+
+FBSD_1.2 {
+ basename_r;
+ cfmakesane;
+ endutxent;
+ getpagesizes;
+ getutxent;
+ getutxid;
+ getutxline;
+ getutxuser;
+ pututxline;
+ sem_close;
+ sem_destroy;
+ sem_getvalue;
+ sem_init;
+ sem_open;
+ sem_post;
+ sem_timedwait;
+ sem_trywait;
+ sem_unlink;
+ sem_wait;
+ setutxdb;
+ setutxent;
+};
+
+FBSD_1.3 {
+ fdlopen;
+ __FreeBSD_libc_enter_restricted_mode;
+ getcontextx;
+};
+
+FBSDprivate_1.0 {
+ /* needed by thread libraries */
+ __thr_jtable;
+
+ _pthread_atfork;
+ _pthread_attr_destroy;
+ _pthread_attr_getdetachstate;
+ _pthread_attr_getguardsize;
+ _pthread_attr_getinheritsched;
+ _pthread_attr_getschedparam;
+ _pthread_attr_getschedpolicy;
+ _pthread_attr_getscope;
+ _pthread_attr_getstackaddr;
+ _pthread_attr_getstacksize;
+ _pthread_attr_init;
+ _pthread_attr_setdetachstate;
+ _pthread_attr_setguardsize;
+ _pthread_attr_setinheritsched;
+ _pthread_attr_setschedparam;
+ _pthread_attr_setschedpolicy;
+ _pthread_attr_setscope;
+ _pthread_attr_setstackaddr;
+ _pthread_attr_setstacksize;
+ _pthread_cancel;
+ _pthread_cancel_enter;
+ _pthread_cancel_leave;
+ _pthread_cleanup_pop;
+ _pthread_cleanup_push;
+ _pthread_cond_broadcast;
+ _pthread_cond_destroy;
+ _pthread_cond_init;
+ _pthread_cond_signal;
+ _pthread_cond_timedwait;
+ _pthread_cond_wait;
+ _pthread_detach;
+ _pthread_equal;
+ _pthread_exit;
+ _pthread_getspecific;
+ _pthread_join;
+ _pthread_key_create;
+ _pthread_key_delete;
+ _pthread_kill;
+ _pthread_main_np;
+ _pthread_mutex_destroy;
+ _pthread_mutex_init_calloc_cb;
+ _pthread_mutex_init;
+ _pthread_mutex_lock;
+ _pthread_mutex_trylock;
+ _pthread_mutex_unlock;
+ _pthread_mutexattr_destroy;
+ _pthread_mutexattr_init;
+ _pthread_mutexattr_settype;
+ _pthread_once;
+ _pthread_rwlock_destroy;
+ _pthread_rwlock_init;
+ _pthread_rwlock_rdlock;
+ _pthread_rwlock_tryrdlock;
+ _pthread_rwlock_trywrlock;
+ _pthread_rwlock_unlock;
+ _pthread_rwlock_wrlock;
+ _pthread_self;
+ _pthread_setcancelstate;
+ _pthread_setcanceltype;
+ _pthread_setspecific;
+ _pthread_sigmask;
+ _pthread_testcancel;
+ _spinlock;
+ _spinlock_debug;
+ _spinunlock;
+ _rtld_addr_phdr;
+ _rtld_atfork_pre;
+ _rtld_atfork_post;
+ _rtld_error; /* for private use */
+ _rtld_get_stack_prot;
+ _rtld_thread_init; /* for private use */
+ __elf_phdr_match_addr;
+ _err;
+ _warn;
+ __fmtcheck;
+ /* __pw_match_entry; */
+ /* __pw_parse_entry; */
+ __fdnlist; /* used by libkvm */
+ /* __aout_fdnlist; */
+ /* __elf_is_okay__; */
+ /* __elf_fdnlist; */
+ __opendir2;
+ __pause;
+ _pause;
+ __pw_scan; /* Used by (at least) libutil */
+ __raise;
+ _raise;
+ __sleep;
+ _sleep;
+ _rtld_allocate_tls;
+ _rtld_free_tls;
+#if defined(i386)
+ ___libc_tls_get_addr; /* x86 only */
+#endif
+ __libc_tls_get_addr;
+ __tcdrain;
+ _tcdrain;
+ __usleep;
+ _usleep;
+ __wait;
+ _wait;
+ __waitpid;
+ _waitpid;
+
+ _libc_sem_init_compat;
+ _libc_sem_destroy_compat;
+ _libc_sem_open_compat;
+ _libc_sem_close_compat;
+ _libc_sem_unlink_compat;
+ _libc_sem_wait_compat;
+ _libc_sem_trywait_compat;
+ _libc_sem_timedwait_compat;
+ _libc_sem_post_compat;
+ _libc_sem_getvalue_compat;
+
+ __elf_aux_vector;
+ __pthread_map_stacks_exec;
+ __fillcontextx;
+ __getcontextx_size;
+};
diff --git a/lib/libc/gen/__getosreldate.c b/lib/libc/gen/__getosreldate.c
new file mode 100644
index 0000000..980f9ef
--- /dev/null
+++ b/lib/libc/gen/__getosreldate.c
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 2007 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <errno.h>
+#include <link.h>
+#include "libc_private.h"
+
+int __getosreldate(void);
+
+/*
+ * This is private to libc. It is intended for wrapping syscall stubs in order
+ * to avoid having to put SIGSYS signal handlers in place to test for presence
+ * of new syscalls. This caches the result in order to be as quick as possible.
+ *
+ * Use getosreldate(3) for public use as it respects the $OSVERSION environment
+ * variable.
+ */
+
+int
+__getosreldate(void)
+{
+ static int osreldate;
+ size_t len;
+ int oid[2];
+ int error, osrel;
+
+ if (osreldate != 0)
+ return (osreldate);
+
+ error = _elf_aux_info(AT_OSRELDATE, &osreldate, sizeof(osreldate));
+ if (error == 0 && osreldate != 0)
+ return (osreldate);
+
+ oid[0] = CTL_KERN;
+ oid[1] = KERN_OSRELDATE;
+ osrel = 0;
+ len = sizeof(osrel);
+ error = sysctl(oid, 2, &osrel, &len, NULL, 0);
+ if (error == 0 && osrel > 0 && len == sizeof(osrel))
+ osreldate = osrel;
+ return (osreldate);
+}
diff --git a/lib/libc/gen/__xuname.c b/lib/libc/gen/__xuname.c
new file mode 100644
index 0000000..6f7d92a
--- /dev/null
+++ b/lib/libc/gen/__xuname.c
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/*static char sccsid[] = "From: @(#)uname.c 8.1 (Berkeley) 1/4/94";*/
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/utsname.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+int
+__xuname(int namesize, void *namebuf)
+{
+ int mib[2], rval;
+ size_t len;
+ char *p, *q;
+ int oerrno;
+
+ rval = 0;
+ q = (char *)namebuf;
+
+ mib[0] = CTL_KERN;
+
+ if ((p = getenv("UNAME_s")))
+ strlcpy(q, p, namesize);
+ else {
+ mib[1] = KERN_OSTYPE;
+ len = namesize;
+ oerrno = errno;
+ if (sysctl(mib, 2, q, &len, NULL, 0) == -1) {
+ if (errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ q[namesize - 1] = '\0';
+ }
+ q += namesize;
+
+ mib[1] = KERN_HOSTNAME;
+ len = namesize;
+ oerrno = errno;
+ if (sysctl(mib, 2, q, &len, NULL, 0) == -1) {
+ if (errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ q[namesize - 1] = '\0';
+ q += namesize;
+
+ if ((p = getenv("UNAME_r")))
+ strlcpy(q, p, namesize);
+ else {
+ mib[1] = KERN_OSRELEASE;
+ len = namesize;
+ oerrno = errno;
+ if (sysctl(mib, 2, q, &len, NULL, 0) == -1) {
+ if (errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ q[namesize - 1] = '\0';
+ }
+ q += namesize;
+
+ if ((p = getenv("UNAME_v")))
+ strlcpy(q, p, namesize);
+ else {
+
+ /*
+ * The version may have newlines in it, turn them into
+ * spaces.
+ */
+ mib[1] = KERN_VERSION;
+ len = namesize;
+ oerrno = errno;
+ if (sysctl(mib, 2, q, &len, NULL, 0) == -1) {
+ if (errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ q[namesize - 1] = '\0';
+ for (p = q; len--; ++p) {
+ if (*p == '\n' || *p == '\t') {
+ if (len > 1)
+ *p = ' ';
+ else
+ *p = '\0';
+ }
+ }
+ }
+ q += namesize;
+
+ if ((p = getenv("UNAME_m")))
+ strlcpy(q, p, namesize);
+ else {
+ mib[0] = CTL_HW;
+ mib[1] = HW_MACHINE;
+ len = namesize;
+ oerrno = errno;
+ if (sysctl(mib, 2, q, &len, NULL, 0) == -1) {
+ if (errno == ENOMEM)
+ errno = oerrno;
+ else
+ rval = -1;
+ }
+ q[namesize - 1] = '\0';
+ }
+
+ return (rval);
+}
diff --git a/lib/libc/gen/_once_stub.c b/lib/libc/gen/_once_stub.c
new file mode 100644
index 0000000..d2acc29
--- /dev/null
+++ b/lib/libc/gen/_once_stub.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 2009 Advanced Computing Technologies LLC
+ * Written by: John H. Baldwin <jhb@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <pthread.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+/* This implements pthread_once() for the single-threaded case. */
+static int
+_libc_once(pthread_once_t *once_control, void (*init_routine)(void))
+{
+
+ if (once_control->state == PTHREAD_DONE_INIT)
+ return (0);
+ init_routine();
+ once_control->state = PTHREAD_DONE_INIT;
+ return (0);
+}
+
+/*
+ * This is the internal interface provided to libc. It will use
+ * pthread_once() from the threading library in a multi-threaded
+ * process and _libc_once() for a single-threaded library. Because
+ * _libc_once() uses the same ABI for the values in the pthread_once_t
+ * structure as the threading library, it is safe for a process to
+ * switch from _libc_once() to pthread_once() when threading is
+ * enabled.
+ */
+int
+_once(pthread_once_t *once_control, void (*init_routine)(void))
+{
+
+ if (__isthreaded)
+ return (_pthread_once(once_control, init_routine));
+ return (_libc_once(once_control, init_routine));
+}
diff --git a/lib/libc/gen/_pthread_stubs.c b/lib/libc/gen/_pthread_stubs.c
new file mode 100644
index 0000000..bd35bd2
--- /dev/null
+++ b/lib/libc/gen/_pthread_stubs.c
@@ -0,0 +1,319 @@
+/*
+ * Copyright (c) 2001 Daniel Eischen <deischen@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <signal.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "libc_private.h"
+
+/*
+ * Weak symbols: All libc internal usage of these functions should
+ * use the weak symbol versions (_pthread_XXX). If libpthread is
+ * linked, it will override these functions with (non-weak) routines.
+ * The _pthread_XXX functions are provided solely for internal libc
+ * usage to avoid unwanted cancellation points and to differentiate
+ * between application locks and libc locks (threads holding the
+ * latter can't be allowed to exit/terminate).
+ */
+
+/* Define a null pthread structure just to satisfy _pthread_self. */
+struct pthread {
+};
+
+static struct pthread main_thread;
+
+static int stub_main(void);
+static void *stub_null(void);
+static struct pthread *stub_self(void);
+static int stub_zero(void);
+static int stub_fail(void);
+static int stub_true(void);
+static void stub_exit(void);
+
+#define PJT_DUAL_ENTRY(entry) \
+ (pthread_func_t)entry, (pthread_func_t)entry
+
+pthread_func_entry_t __thr_jtable[PJT_MAX] = {
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATFORK */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_DESTROY */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_GETDETACHSTATE */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_GETGUARDSIZE */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_GETINHERITSCHED */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_GETSCHEDPARAM */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_GETSCHEDPOLICY */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_GETSCOPE */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_GETSTACKADDR */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_GETSTACKSIZE */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_INIT */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_SETDETACHSTATE */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_SETGUARDSIZE */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_SETINHERITSCHED */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_SETSCHEDPARAM */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_SETSCHEDPOLICY */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_SETSCOPE */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_SETSTACKADDR */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_ATTR_SETSTACKSIZE */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_CANCEL */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_CLEANUP_POP */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_CLEANUP_PUSH */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_COND_BROADCAST */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_COND_DESTROY */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_COND_INIT */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_COND_SIGNAL */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_COND_TIMEDWAIT */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_COND_WAIT */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_DETACH */
+ {PJT_DUAL_ENTRY(stub_true)}, /* PJT_EQUAL */
+ {PJT_DUAL_ENTRY(stub_exit)}, /* PJT_EXIT */
+ {PJT_DUAL_ENTRY(stub_null)}, /* PJT_GETSPECIFIC */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_JOIN */
+ {PJT_DUAL_ENTRY(stub_fail)}, /* PJT_KEY_CREATE */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_KEY_DELETE */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_KILL */
+ {PJT_DUAL_ENTRY(stub_main)}, /* PJT_MAIN_NP */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEXATTR_DESTROY */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEXATTR_INIT */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEXATTR_SETTYPE */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEX_DESTROY */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEX_INIT */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEX_LOCK */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEX_TRYLOCK */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_MUTEX_UNLOCK */
+ {PJT_DUAL_ENTRY(stub_fail)}, /* PJT_ONCE */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_DESTROY */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_INIT */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_RDLOCK */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_TRYRDLOCK */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_TRYWRLOCK */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_UNLOCK */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_RWLOCK_WRLOCK */
+ {PJT_DUAL_ENTRY(stub_self)}, /* PJT_SELF */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_SETCANCELSTATE */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_SETCANCELTYPE */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_SETSPECIFIC */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_SIGMASK */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_TESTCANCEL */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_CLEANUP_POP_IMP */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_CLEANUP_PUSH_IMP */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_CANCEL_ENTER */
+ {PJT_DUAL_ENTRY(stub_zero)}, /* PJT_CANCEL_LEAVE */
+};
+
+/*
+ * Weak aliases for exported (pthread_*) and internal (_pthread_*) routines.
+ */
+#define WEAK_REF(sym, alias) __weak_reference(sym, alias)
+
+#define FUNC_TYPE(name) __CONCAT(name, _func_t)
+#define FUNC_INT(name) __CONCAT(name, _int)
+#define FUNC_EXP(name) __CONCAT(name, _exp)
+
+#define STUB_FUNC(name, idx, ret) \
+ static ret FUNC_EXP(name)(void) __used; \
+ static ret FUNC_INT(name)(void) __used; \
+ WEAK_REF(FUNC_EXP(name), name); \
+ WEAK_REF(FUNC_INT(name), __CONCAT(_, name)); \
+ typedef ret (*FUNC_TYPE(name))(void); \
+ static ret FUNC_EXP(name)(void) \
+ { \
+ FUNC_TYPE(name) func; \
+ func = (FUNC_TYPE(name))__thr_jtable[idx][0]; \
+ return (func()); \
+ } \
+ static ret FUNC_INT(name)(void) \
+ { \
+ FUNC_TYPE(name) func; \
+ func = (FUNC_TYPE(name))__thr_jtable[idx][1]; \
+ return (func()); \
+ }
+
+#define STUB_FUNC1(name, idx, ret, p0_type) \
+ static ret FUNC_EXP(name)(p0_type) __used; \
+ static ret FUNC_INT(name)(p0_type) __used; \
+ WEAK_REF(FUNC_EXP(name), name); \
+ WEAK_REF(FUNC_INT(name), __CONCAT(_, name)); \
+ typedef ret (*FUNC_TYPE(name))(p0_type); \
+ static ret FUNC_EXP(name)(p0_type p0) \
+ { \
+ FUNC_TYPE(name) func; \
+ func = (FUNC_TYPE(name))__thr_jtable[idx][0]; \
+ return (func(p0)); \
+ } \
+ static ret FUNC_INT(name)(p0_type p0) \
+ { \
+ FUNC_TYPE(name) func; \
+ func = (FUNC_TYPE(name))__thr_jtable[idx][1]; \
+ return (func(p0)); \
+ }
+
+#define STUB_FUNC2(name, idx, ret, p0_type, p1_type) \
+ static ret FUNC_EXP(name)(p0_type, p1_type) __used; \
+ static ret FUNC_INT(name)(p0_type, p1_type) __used; \
+ WEAK_REF(FUNC_EXP(name), name); \
+ WEAK_REF(FUNC_INT(name), __CONCAT(_, name)); \
+ typedef ret (*FUNC_TYPE(name))(p0_type, p1_type); \
+ static ret FUNC_EXP(name)(p0_type p0, p1_type p1) \
+ { \
+ FUNC_TYPE(name) func; \
+ func = (FUNC_TYPE(name))__thr_jtable[idx][0]; \
+ return (func(p0, p1)); \
+ } \
+ static ret FUNC_INT(name)(p0_type p0, p1_type p1) \
+ { \
+ FUNC_TYPE(name) func; \
+ func = (FUNC_TYPE(name))__thr_jtable[idx][1]; \
+ return (func(p0, p1)); \
+ }
+
+#define STUB_FUNC3(name, idx, ret, p0_type, p1_type, p2_type) \
+ static ret FUNC_EXP(name)(p0_type, p1_type, p2_type) __used; \
+ static ret FUNC_INT(name)(p0_type, p1_type, p2_type) __used; \
+ WEAK_REF(FUNC_EXP(name), name); \
+ WEAK_REF(FUNC_INT(name), __CONCAT(_, name)); \
+ typedef ret (*FUNC_TYPE(name))(p0_type, p1_type, p2_type); \
+ static ret FUNC_EXP(name)(p0_type p0, p1_type p1, p2_type p2) \
+ { \
+ FUNC_TYPE(name) func; \
+ func = (FUNC_TYPE(name))__thr_jtable[idx][0]; \
+ return (func(p0, p1, p2)); \
+ } \
+ static ret FUNC_INT(name)(p0_type p0, p1_type p1, p2_type p2) \
+ { \
+ FUNC_TYPE(name) func; \
+ func = (FUNC_TYPE(name))__thr_jtable[idx][1]; \
+ return (func(p0, p1, p2)); \
+ }
+
+STUB_FUNC1(pthread_cond_broadcast, PJT_COND_BROADCAST, int, void *)
+STUB_FUNC1(pthread_cond_destroy, PJT_COND_DESTROY, int, void *)
+STUB_FUNC2(pthread_cond_init, PJT_COND_INIT, int, void *, void *)
+STUB_FUNC1(pthread_cond_signal, PJT_COND_SIGNAL, int, void *)
+STUB_FUNC2(pthread_cond_wait, PJT_COND_WAIT, int, void *, void *)
+STUB_FUNC1(pthread_getspecific, PJT_GETSPECIFIC, void *, pthread_key_t)
+STUB_FUNC2(pthread_key_create, PJT_KEY_CREATE, int, void *, void *)
+STUB_FUNC1(pthread_key_delete, PJT_KEY_DELETE, int, pthread_key_t)
+STUB_FUNC(pthread_main_np, PJT_MAIN_NP, int)
+STUB_FUNC1(pthread_mutex_destroy, PJT_MUTEX_DESTROY, int, void *)
+STUB_FUNC2(pthread_mutex_init, PJT_MUTEX_INIT, int, void *, void *)
+STUB_FUNC1(pthread_mutex_lock, PJT_MUTEX_LOCK, int, void *)
+STUB_FUNC1(pthread_mutex_trylock, PJT_MUTEX_TRYLOCK, int, void *)
+STUB_FUNC1(pthread_mutex_unlock, PJT_MUTEX_UNLOCK, int, void *)
+STUB_FUNC1(pthread_mutexattr_destroy, PJT_MUTEXATTR_DESTROY, int, void *)
+STUB_FUNC1(pthread_mutexattr_init, PJT_MUTEXATTR_INIT, int, void *)
+STUB_FUNC2(pthread_mutexattr_settype, PJT_MUTEXATTR_SETTYPE, int, void *, int)
+STUB_FUNC2(pthread_once, PJT_ONCE, int, void *, void *)
+STUB_FUNC1(pthread_rwlock_destroy, PJT_RWLOCK_DESTROY, int, void *)
+STUB_FUNC2(pthread_rwlock_init, PJT_RWLOCK_INIT, int, void *, void *)
+STUB_FUNC1(pthread_rwlock_rdlock, PJT_RWLOCK_RDLOCK, int, void *)
+STUB_FUNC1(pthread_rwlock_tryrdlock, PJT_RWLOCK_TRYRDLOCK, int, void *)
+STUB_FUNC1(pthread_rwlock_trywrlock, PJT_RWLOCK_TRYWRLOCK, int, void *)
+STUB_FUNC1(pthread_rwlock_unlock, PJT_RWLOCK_UNLOCK, int, void *)
+STUB_FUNC1(pthread_rwlock_wrlock, PJT_RWLOCK_WRLOCK, int, void *)
+STUB_FUNC(pthread_self, PJT_SELF, pthread_t)
+STUB_FUNC2(pthread_setspecific, PJT_SETSPECIFIC, int, pthread_key_t, void *)
+STUB_FUNC3(pthread_sigmask, PJT_SIGMASK, int, int, void *, void *)
+STUB_FUNC3(pthread_atfork, PJT_ATFORK, int, void *, void *, void*)
+STUB_FUNC1(pthread_attr_destroy, PJT_ATTR_DESTROY, int, void *);
+STUB_FUNC2(pthread_attr_getdetachstate, PJT_ATTR_GETDETACHSTATE, int, void *, void *)
+STUB_FUNC2(pthread_attr_getguardsize, PJT_ATTR_GETGUARDSIZE, int, void *, void *)
+STUB_FUNC2(pthread_attr_getstackaddr, PJT_ATTR_GETSTACKADDR, int, void *, void *)
+STUB_FUNC2(pthread_attr_getstacksize, PJT_ATTR_GETSTACKSIZE, int, void *, void *)
+STUB_FUNC2(pthread_attr_getinheritsched, PJT_ATTR_GETINHERITSCHED, int, void *, void *)
+STUB_FUNC2(pthread_attr_getschedparam, PJT_ATTR_GETSCHEDPARAM, int, void *, void *)
+STUB_FUNC2(pthread_attr_getschedpolicy, PJT_ATTR_GETSCHEDPOLICY, int, void *, void *)
+STUB_FUNC2(pthread_attr_getscope, PJT_ATTR_GETSCOPE, int, void *, void *)
+STUB_FUNC1(pthread_attr_init, PJT_ATTR_INIT, int, void *)
+STUB_FUNC2(pthread_attr_setdetachstate, PJT_ATTR_SETDETACHSTATE, int, void *, int)
+STUB_FUNC2(pthread_attr_setguardsize, PJT_ATTR_SETGUARDSIZE, int, void *, size_t)
+STUB_FUNC2(pthread_attr_setstackaddr, PJT_ATTR_SETSTACKADDR, int, void *, void *)
+STUB_FUNC2(pthread_attr_setstacksize, PJT_ATTR_SETSTACKSIZE, int, void *, size_t)
+STUB_FUNC2(pthread_attr_setinheritsched, PJT_ATTR_SETINHERITSCHED, int, void *, int)
+STUB_FUNC2(pthread_attr_setschedparam, PJT_ATTR_SETSCHEDPARAM, int, void *, void *)
+STUB_FUNC2(pthread_attr_setschedpolicy, PJT_ATTR_SETSCHEDPOLICY, int, void *, int)
+STUB_FUNC2(pthread_attr_setscope, PJT_ATTR_SETSCOPE, int, void *, int)
+STUB_FUNC1(pthread_cancel, PJT_CANCEL, int, void *)
+STUB_FUNC1(pthread_cleanup_pop, PJT_CLEANUP_POP, int, int)
+STUB_FUNC2(pthread_cleanup_push, PJT_CLEANUP_PUSH, void, void *, void *)
+STUB_FUNC3(pthread_cond_timedwait, PJT_COND_TIMEDWAIT, int, void *, void *, void *)
+STUB_FUNC1(pthread_detach, PJT_DETACH, int, void *)
+STUB_FUNC2(pthread_equal, PJT_EQUAL, int, void *, void *)
+STUB_FUNC1(pthread_exit, PJT_EXIT, void, void *)
+STUB_FUNC2(pthread_join, PJT_JOIN, int, void *, void *)
+STUB_FUNC2(pthread_kill, PJT_KILL, int, void *, int)
+STUB_FUNC2(pthread_setcancelstate, PJT_SETCANCELSTATE, int, int, void *)
+STUB_FUNC2(pthread_setcanceltype, PJT_SETCANCELTYPE, int, int, void *)
+STUB_FUNC(pthread_testcancel, PJT_TESTCANCEL, void)
+STUB_FUNC1(__pthread_cleanup_pop_imp, PJT_CLEANUP_POP_IMP, int, int)
+STUB_FUNC2(__pthread_cleanup_push_imp, PJT_CLEANUP_PUSH_IMP, void, void*, void *);
+STUB_FUNC1(_pthread_cancel_enter, PJT_CANCEL_ENTER, int, int)
+STUB_FUNC1(_pthread_cancel_leave, PJT_CANCEL_LEAVE, int, int)
+
+static int
+stub_zero(void)
+{
+ return (0);
+}
+
+static void *
+stub_null(void)
+{
+ return (NULL);
+}
+
+static struct pthread *
+stub_self(void)
+{
+ return (&main_thread);
+}
+
+static int
+stub_fail(void)
+{
+ return (ENOSYS);
+}
+
+static int
+stub_main(void)
+{
+ return (-1);
+}
+
+static int
+stub_true(void)
+{
+ return (1);
+}
+
+static void
+stub_exit(void)
+{
+ exit(0);
+}
diff --git a/lib/libc/gen/_rand48.c b/lib/libc/gen/_rand48.c
new file mode 100644
index 0000000..279bbc3
--- /dev/null
+++ b/lib/libc/gen/_rand48.c
@@ -0,0 +1,49 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "rand48.h"
+
+unsigned short _rand48_seed[3] = {
+ RAND48_SEED_0,
+ RAND48_SEED_1,
+ RAND48_SEED_2
+};
+unsigned short _rand48_mult[3] = {
+ RAND48_MULT_0,
+ RAND48_MULT_1,
+ RAND48_MULT_2
+};
+unsigned short _rand48_add = RAND48_ADD;
+
+void
+_dorand48(unsigned short xseed[3])
+{
+ unsigned long accu;
+ unsigned short temp[2];
+
+ accu = (unsigned long) _rand48_mult[0] * (unsigned long) xseed[0] +
+ (unsigned long) _rand48_add;
+ temp[0] = (unsigned short) accu; /* lower 16 bits */
+ accu >>= sizeof(unsigned short) * 8;
+ accu += (unsigned long) _rand48_mult[0] * (unsigned long) xseed[1] +
+ (unsigned long) _rand48_mult[1] * (unsigned long) xseed[0];
+ temp[1] = (unsigned short) accu; /* middle 16 bits */
+ accu >>= sizeof(unsigned short) * 8;
+ accu += _rand48_mult[0] * xseed[2] + _rand48_mult[1] * xseed[1] + _rand48_mult[2] * xseed[0];
+ xseed[0] = temp[0];
+ xseed[1] = temp[1];
+ xseed[2] = (unsigned short) accu;
+}
diff --git a/lib/libc/gen/_spinlock_stub.c b/lib/libc/gen/_spinlock_stub.c
new file mode 100644
index 0000000..47bbfeb
--- /dev/null
+++ b/lib/libc/gen/_spinlock_stub.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+
+#include "spinlock.h"
+
+long _atomic_lock_stub(volatile long *);
+void _spinlock_stub(spinlock_t *);
+void _spinunlock_stub(spinlock_t *);
+void _spinlock_debug_stub(spinlock_t *, char *, int);
+
+/*
+ * Declare weak definitions in case the application is not linked
+ * with libpthread.
+ */
+__weak_reference(_atomic_lock_stub, _atomic_lock);
+__weak_reference(_spinlock_stub, _spinlock);
+__weak_reference(_spinunlock_stub, _spinunlock);
+__weak_reference(_spinlock_debug_stub, _spinlock_debug);
+
+/*
+ * This function is a stub for the _atomic_lock function in libpthread.
+ */
+long
+_atomic_lock_stub(volatile long *lck __unused)
+{
+ return (0L);
+}
+
+
+/*
+ * This function is a stub for the spinlock function in libpthread.
+ */
+void
+_spinlock_stub(spinlock_t *lck __unused)
+{
+}
+
+/*
+ * This function is a stub for the spinunlock function in libpthread.
+ */
+void
+_spinunlock_stub(spinlock_t *lck __unused)
+{
+}
+
+/*
+ * This function is a stub for the debug spinlock function in libpthread.
+ */
+void
+_spinlock_debug_stub(spinlock_t *lck __unused, char *fname __unused, int lineno __unused)
+{
+}
diff --git a/lib/libc/gen/_thread_init.c b/lib/libc/gen/_thread_init.c
new file mode 100644
index 0000000..c0b6ade
--- /dev/null
+++ b/lib/libc/gen/_thread_init.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2001 Daniel Eischen <deischen@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS''
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+void _thread_init_stub(void);
+
+__weak_reference(_thread_init_stub, _thread_init);
+__weak_reference(_thread_autoinit_dummy_decl_stub,
+ _thread_autoinit_dummy_decl);
+
+int _thread_autoinit_dummy_decl_stub = 0;
+
+void
+_thread_init_stub(void)
+{
+ /* This is just a stub; there is nothing to do. */
+}
diff --git a/lib/libc/gen/alarm.3 b/lib/libc/gen/alarm.3
new file mode 100644
index 0000000..92817b8
--- /dev/null
+++ b/lib/libc/gen/alarm.3
@@ -0,0 +1,93 @@
+.\" Copyright (c) 1980, 1991, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)alarm.3 8.2 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd April 19, 1994
+.Dt ALARM 3
+.Os
+.Sh NAME
+.Nm alarm
+.Nd set signal timer alarm
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft unsigned int
+.Fn alarm "unsigned int seconds"
+.Sh DESCRIPTION
+.Bf -symbolic
+This interface is made obsolete by
+.Xr setitimer 2 .
+.Ef
+.Pp
+The
+.Fn alarm
+function sets a timer to deliver the signal
+.Dv SIGALRM
+to the calling process after the specified number of
+.Fa seconds .
+If an alarm has already been set with
+.Fn alarm
+but has not been delivered, another call to
+.Fn alarm
+will supersede the prior call.
+The request
+.Fn alarm "0"
+voids the current
+alarm and the signal SIGALRM will not be delivered.
+.Pp
+Due to
+.Xr setitimer 2
+restriction the maximum number of
+.Fa seconds
+allowed is 100000000.
+.Sh RETURN VALUES
+The return value of
+.Fn alarm
+is the amount of time left on the timer from a previous call to
+.Fn alarm .
+If no alarm is currently set, the return value is 0.
+.Sh SEE ALSO
+.Xr setitimer 2 ,
+.Xr sigaction 2 ,
+.Xr sigsuspend 2 ,
+.Xr signal 3 ,
+.Xr sleep 3 ,
+.Xr ualarm 3 ,
+.Xr usleep 3
+.\" .Sh STANDARDS
+.\" The
+.\" .Fn alarm
+.\" function conforms to
+.\" .St -p1003.1-90 .
+.Sh HISTORY
+An
+.Fn alarm
+function appeared in
+.At v7 .
diff --git a/lib/libc/gen/alarm.c b/lib/libc/gen/alarm.c
new file mode 100644
index 0000000..318be4c
--- /dev/null
+++ b/lib/libc/gen/alarm.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)alarm.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Backwards compatible alarm.
+ */
+#include <sys/time.h>
+#include <unistd.h>
+
+unsigned int
+alarm(secs)
+ unsigned int secs;
+{
+ struct itimerval it, oitv;
+ struct itimerval *itp = &it;
+
+ timerclear(&itp->it_interval);
+ itp->it_value.tv_sec = secs;
+ itp->it_value.tv_usec = 0;
+ if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
+ return (-1);
+ if (oitv.it_value.tv_usec)
+ oitv.it_value.tv_sec++;
+ return (oitv.it_value.tv_sec);
+}
diff --git a/lib/libc/gen/arc4random.3 b/lib/libc/gen/arc4random.3
new file mode 100644
index 0000000..e1124c6
--- /dev/null
+++ b/lib/libc/gen/arc4random.3
@@ -0,0 +1,127 @@
+.\" $OpenBSD: arc4random.3,v 1.2 1997/04/27 22:40:25 angelos Exp $
+.\" Copyright 1997 Niels Provos <provos@physnet.uni-hamburg.de>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Niels Provos.
+.\" 4. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" Manual page, using -mandoc macros
+.\" $FreeBSD$
+.\"
+.Dd April 15, 1997
+.Dt ARC4RANDOM 3
+.Os
+.Sh NAME
+.Nm arc4random ,
+.Nm arc4random_buf ,
+.Nm arc4random_uniform ,
+.Nm arc4random_stir ,
+.Nm arc4random_addrandom
+.Nd arc4 random number generator
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft uint32_t
+.Fn arc4random "void"
+.Ft void
+.Fn arc4random_buf "void *buf" "size_t nbytes"
+.Ft uint32_t
+.Fn arc4random_uniform "uint32_t upper_bound"
+.Ft void
+.Fn arc4random_stir "void"
+.Ft void
+.Fn arc4random_addrandom "unsigned char *dat" "int datlen"
+.Sh DESCRIPTION
+The
+.Fn arc4random
+function uses the key stream generator employed by the
+arc4 cipher, which uses 8*8 8 bit S-Boxes.
+The S-Boxes
+can be in about
+.if t 2\u\s71700\s10\d
+.if n (2**1700)
+states.
+The
+.Fn arc4random
+function returns pseudo-random numbers in the range of 0 to
+.if t 2\u\s731\s10\d\(mi1,
+.if n (2**32)\(mi1,
+and therefore has twice the range of
+.Xr rand 3
+and
+.Xr random 3 .
+.Pp
+.Fn arc4random_buf
+function fills the region
+.Fa buf
+of length
+.Fa nbytes
+with ARC4-derived random data.
+.Pp
+.Fn arc4random_uniform
+will return a uniformly distributed random number less than
+.Fa upper_bound .
+.Fn arc4random_uniform
+is recommended over constructions like
+.Dq Li arc4random() % upper_bound
+as it avoids "modulo bias" when the upper bound is not a power of two.
+.Pp
+The
+.Fn arc4random_stir
+function reads data from
+.Pa /dev/urandom
+and uses it to permute the S-Boxes via
+.Fn arc4random_addrandom .
+.Pp
+There is no need to call
+.Fn arc4random_stir
+before using
+.Fn arc4random
+functions family, since
+they automatically initialize themselves.
+.Sh EXAMPLES
+The following produces a drop-in replacement for the traditional
+.Fn rand
+and
+.Fn random
+functions using
+.Fn arc4random :
+.Pp
+.Dl "#define foo4random() (arc4random() % ((unsigned)RAND_MAX + 1))"
+.Sh SEE ALSO
+.Xr rand 3 ,
+.Xr random 3 ,
+.Xr srandomdev 3
+.Sh HISTORY
+.Pa RC4
+has been designed by RSA Data Security, Inc.
+It was posted anonymously
+to the USENET and was confirmed to be equivalent by several sources who
+had access to the original cipher.
+Since
+.Pa RC4
+used to be a trade secret, the cipher is now referred to as
+.Pa ARC4 .
diff --git a/lib/libc/gen/arc4random.c b/lib/libc/gen/arc4random.c
new file mode 100644
index 0000000..a2b235f
--- /dev/null
+++ b/lib/libc/gen/arc4random.c
@@ -0,0 +1,295 @@
+/* $OpenBSD: arc4random.c,v 1.22 2010/12/22 08:23:42 otto Exp $ */
+
+/*
+ * Copyright (c) 1996, David Mazieres <dm@uun.org>
+ * Copyright (c) 2008, Damien Miller <djm@openbsd.org>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * Arc4 random number generator for OpenBSD.
+ *
+ * This code is derived from section 17.1 of Applied Cryptography,
+ * second edition, which describes a stream cipher allegedly
+ * compatible with RSA Labs "RC4" cipher (the actual description of
+ * which is a trade secret). The same algorithm is used as a stream
+ * cipher called "arcfour" in Tatu Ylonen's ssh package.
+ *
+ * RC4 is a registered trademark of RSA Laboratories.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <pthread.h>
+
+#include "libc_private.h"
+#include "un-namespace.h"
+
+#ifdef __GNUC__
+#define inline __inline
+#else /* !__GNUC__ */
+#define inline
+#endif /* !__GNUC__ */
+
+struct arc4_stream {
+ u_int8_t i;
+ u_int8_t j;
+ u_int8_t s[256];
+};
+
+static pthread_mutex_t arc4random_mtx = PTHREAD_MUTEX_INITIALIZER;
+
+#define RANDOMDEV "/dev/random"
+#define KEYSIZE 128
+#define _ARC4_LOCK() \
+ do { \
+ if (__isthreaded) \
+ _pthread_mutex_lock(&arc4random_mtx); \
+ } while (0)
+
+#define _ARC4_UNLOCK() \
+ do { \
+ if (__isthreaded) \
+ _pthread_mutex_unlock(&arc4random_mtx); \
+ } while (0)
+
+static int rs_initialized;
+static struct arc4_stream rs;
+static pid_t arc4_stir_pid;
+static int arc4_count;
+
+static inline u_int8_t arc4_getbyte(void);
+static void arc4_stir(void);
+
+static inline void
+arc4_init(void)
+{
+ int n;
+
+ for (n = 0; n < 256; n++)
+ rs.s[n] = n;
+ rs.i = 0;
+ rs.j = 0;
+}
+
+static inline void
+arc4_addrandom(u_char *dat, int datlen)
+{
+ int n;
+ u_int8_t si;
+
+ rs.i--;
+ for (n = 0; n < 256; n++) {
+ rs.i = (rs.i + 1);
+ si = rs.s[rs.i];
+ rs.j = (rs.j + si + dat[n % datlen]);
+ rs.s[rs.i] = rs.s[rs.j];
+ rs.s[rs.j] = si;
+ }
+ rs.j = rs.i;
+}
+
+static void
+arc4_stir(void)
+{
+ int done, fd, i;
+ struct {
+ struct timeval tv;
+ pid_t pid;
+ u_char rnd[KEYSIZE];
+ } rdat;
+
+ if (!rs_initialized) {
+ arc4_init();
+ rs_initialized = 1;
+ }
+ fd = _open(RANDOMDEV, O_RDONLY, 0);
+ done = 0;
+ if (fd >= 0) {
+ if (_read(fd, &rdat, KEYSIZE) == KEYSIZE)
+ done = 1;
+ (void)_close(fd);
+ }
+ if (!done) {
+ (void)gettimeofday(&rdat.tv, NULL);
+ rdat.pid = getpid();
+ /* We'll just take whatever was on the stack too... */
+ }
+
+ arc4_addrandom((u_char *)&rdat, KEYSIZE);
+
+ /*
+ * Discard early keystream, as per recommendations in:
+ * "(Not So) Random Shuffles of RC4" by Ilya Mironov.
+ */
+ for (i = 0; i < 1024; i++)
+ (void)arc4_getbyte();
+ arc4_count = 1600000;
+}
+
+static void
+arc4_stir_if_needed(void)
+{
+ pid_t pid = getpid();
+
+ if (arc4_count <= 0 || !rs_initialized || arc4_stir_pid != pid)
+ {
+ arc4_stir_pid = pid;
+ arc4_stir();
+ }
+}
+
+static inline u_int8_t
+arc4_getbyte(void)
+{
+ u_int8_t si, sj;
+
+ rs.i = (rs.i + 1);
+ si = rs.s[rs.i];
+ rs.j = (rs.j + si);
+ sj = rs.s[rs.j];
+ rs.s[rs.i] = sj;
+ rs.s[rs.j] = si;
+ return (rs.s[(si + sj) & 0xff]);
+}
+
+static inline u_int32_t
+arc4_getword(void)
+{
+ u_int32_t val;
+ val = arc4_getbyte() << 24;
+ val |= arc4_getbyte() << 16;
+ val |= arc4_getbyte() << 8;
+ val |= arc4_getbyte();
+ return val;
+}
+
+void
+arc4random_stir(void)
+{
+ _ARC4_LOCK();
+ arc4_stir();
+ _ARC4_UNLOCK();
+}
+
+void
+arc4random_addrandom(u_char *dat, int datlen)
+{
+ _ARC4_LOCK();
+ if (!rs_initialized)
+ arc4_stir();
+ arc4_addrandom(dat, datlen);
+ _ARC4_UNLOCK();
+}
+
+u_int32_t
+arc4random(void)
+{
+ u_int32_t val;
+ _ARC4_LOCK();
+ arc4_count -= 4;
+ arc4_stir_if_needed();
+ val = arc4_getword();
+ _ARC4_UNLOCK();
+ return val;
+}
+
+void
+arc4random_buf(void *_buf, size_t n)
+{
+ u_char *buf = (u_char *)_buf;
+ _ARC4_LOCK();
+ arc4_stir_if_needed();
+ while (n--) {
+ if (--arc4_count <= 0)
+ arc4_stir();
+ buf[n] = arc4_getbyte();
+ }
+ _ARC4_UNLOCK();
+}
+
+/*
+ * Calculate a uniformly distributed random number less than upper_bound
+ * avoiding "modulo bias".
+ *
+ * Uniformity is achieved by generating new random numbers until the one
+ * returned is outside the range [0, 2**32 % upper_bound). This
+ * guarantees the selected random number will be inside
+ * [2**32 % upper_bound, 2**32) which maps back to [0, upper_bound)
+ * after reduction modulo upper_bound.
+ */
+u_int32_t
+arc4random_uniform(u_int32_t upper_bound)
+{
+ u_int32_t r, min;
+
+ if (upper_bound < 2)
+ return 0;
+
+#if (ULONG_MAX > 0xffffffffUL)
+ min = 0x100000000UL % upper_bound;
+#else
+ /* Calculate (2**32 % upper_bound) avoiding 64-bit math */
+ if (upper_bound > 0x80000000)
+ min = 1 + ~upper_bound; /* 2**32 - upper_bound */
+ else {
+ /* (2**32 - (x * 2)) % x == 2**32 % x when x <= 2**31 */
+ min = ((0xffffffff - (upper_bound * 2)) + 1) % upper_bound;
+ }
+#endif
+
+ /*
+ * This could theoretically loop forever but each retry has
+ * p > 0.5 (worst case, usually far better) of selecting a
+ * number inside the range we need, so it should rarely need
+ * to re-roll.
+ */
+ for (;;) {
+ r = arc4random();
+ if (r >= min)
+ break;
+ }
+
+ return r % upper_bound;
+}
+
+#if 0
+/*-------- Test code for i386 --------*/
+#include <stdio.h>
+#include <machine/pctr.h>
+int
+main(int argc, char **argv)
+{
+ const int iter = 1000000;
+ int i;
+ pctrval v;
+
+ v = rdtsc();
+ for (i = 0; i < iter; i++)
+ arc4random();
+ v = rdtsc() - v;
+ v /= iter;
+
+ printf("%qd cycles\n", v);
+}
+#endif
diff --git a/lib/libc/gen/assert.c b/lib/libc/gen/assert.c
new file mode 100644
index 0000000..73e199c
--- /dev/null
+++ b/lib/libc/gen/assert.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)assert.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+void
+__assert(func, file, line, failedexpr)
+ const char *func, *file;
+ int line;
+ const char *failedexpr;
+{
+ if (func == NULL)
+ (void)fprintf(stderr,
+ "Assertion failed: (%s), file %s, line %d.\n", failedexpr,
+ file, line);
+ else
+ (void)fprintf(stderr,
+ "Assertion failed: (%s), function %s, file %s, line %d.\n",
+ failedexpr, func, file, line);
+ abort();
+ /* NOTREACHED */
+}
diff --git a/lib/libc/gen/aux.c b/lib/libc/gen/aux.c
new file mode 100644
index 0000000..4bf8643
--- /dev/null
+++ b/lib/libc/gen/aux.c
@@ -0,0 +1,171 @@
+/*-
+ * Copyright 2010, 2012 Konstantin Belousov <kib@FreeBSD.ORG>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <elf.h>
+#include <errno.h>
+#include <link.h>
+#include <pthread.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+extern char **environ;
+extern int _DYNAMIC;
+#pragma weak _DYNAMIC
+
+void *__elf_aux_vector;
+static pthread_once_t aux_vector_once = PTHREAD_ONCE_INIT;
+
+static void
+init_aux_vector_once(void)
+{
+ Elf_Addr *sp;
+
+ sp = (Elf_Addr *)environ;
+ while (*sp++ != 0)
+ ;
+ __elf_aux_vector = (Elf_Auxinfo *)sp;
+}
+
+void
+__init_elf_aux_vector(void)
+{
+
+ if (&_DYNAMIC != NULL)
+ return;
+ _once(&aux_vector_once, init_aux_vector_once);
+}
+
+static pthread_once_t aux_once = PTHREAD_ONCE_INIT;
+static int pagesize, osreldate, canary_len, ncpus, pagesizes_len;
+static char *canary, *pagesizes;
+
+static void
+init_aux(void)
+{
+ Elf_Auxinfo *aux;
+
+ for (aux = __elf_aux_vector; aux->a_type != AT_NULL; aux++) {
+ switch (aux->a_type) {
+ case AT_CANARY:
+ canary = (char *)(aux->a_un.a_ptr);
+ break;
+
+ case AT_CANARYLEN:
+ canary_len = aux->a_un.a_val;
+ break;
+
+ case AT_PAGESIZES:
+ pagesizes = (char *)(aux->a_un.a_ptr);
+ break;
+
+ case AT_PAGESIZESLEN:
+ pagesizes_len = aux->a_un.a_val;
+ break;
+
+ case AT_PAGESZ:
+ pagesize = aux->a_un.a_val;
+ break;
+
+ case AT_OSRELDATE:
+ osreldate = aux->a_un.a_val;
+ break;
+
+ case AT_NCPUS:
+ ncpus = aux->a_un.a_val;
+ break;
+ }
+ }
+}
+
+int
+_elf_aux_info(int aux, void *buf, int buflen)
+{
+ int res;
+
+ __init_elf_aux_vector();
+ if (__elf_aux_vector == NULL)
+ return (ENOSYS);
+ _once(&aux_once, init_aux);
+
+ switch (aux) {
+ case AT_CANARY:
+ if (canary != NULL && canary_len >= buflen) {
+ memcpy(buf, canary, buflen);
+ memset(canary, 0, canary_len);
+ canary = NULL;
+ res = 0;
+ } else
+ res = ENOENT;
+ break;
+ case AT_PAGESIZES:
+ if (pagesizes != NULL && pagesizes_len >= buflen) {
+ memcpy(buf, pagesizes, buflen);
+ res = 0;
+ } else
+ res = ENOENT;
+ break;
+
+ case AT_PAGESZ:
+ if (buflen == sizeof(int)) {
+ if (pagesize != 0) {
+ *(int *)buf = pagesize;
+ res = 0;
+ } else
+ res = ENOENT;
+ } else
+ res = EINVAL;
+ break;
+ case AT_OSRELDATE:
+ if (buflen == sizeof(int)) {
+ if (osreldate != 0) {
+ *(int *)buf = osreldate;
+ res = 0;
+ } else
+ res = ENOENT;
+ } else
+ res = EINVAL;
+ break;
+ case AT_NCPUS:
+ if (buflen == sizeof(int)) {
+ if (ncpus != 0) {
+ *(int *)buf = ncpus;
+ res = 0;
+ } else
+ res = ENOENT;
+ } else
+ res = EINVAL;
+ break;
+ default:
+ res = ENOENT;
+ break;
+ }
+ return (res);
+}
diff --git a/lib/libc/gen/basename.3 b/lib/libc/gen/basename.3
new file mode 100644
index 0000000..bcdd99e
--- /dev/null
+++ b/lib/libc/gen/basename.3
@@ -0,0 +1,113 @@
+.\" $OpenBSD: basename.3,v 1.20 2007/05/31 19:19:28 jmc Exp $
+.\"
+.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 31, 2010
+.Dt BASENAME 3
+.Os
+.Sh NAME
+.Nm basename
+.Nd extract the base portion of a pathname
+.Sh SYNOPSIS
+.In libgen.h
+.Ft char *
+.Fn basename "const char *path"
+.Ft char *
+.Fn basename_r "const char *path" "char *bname"
+.Sh DESCRIPTION
+The
+.Fn basename
+function returns the last component from the pathname pointed to by
+.Fa path ,
+deleting any trailing
+.Sq \&/
+characters.
+If
+.Fa path
+consists entirely of
+.Sq \&/
+characters, a pointer to the string
+.Qq \&/
+is returned.
+If
+.Fa path
+is a null pointer or the empty string, a pointer to the string
+.Qq \&.
+is returned.
+.Pp
+The
+.Fn basename_r
+variation accepts a buffer of at least
+.Dv MAXPATHLEN
+bytes in which to store the resulting component.
+.Sh IMPLEMENTATION NOTES
+The
+.Fn basename
+function
+returns a pointer to internal storage space allocated on the first call
+that will be overwritten
+by subsequent calls.
+.Fn basename_r
+is therefore preferred for threaded applications.
+.Sh RETURN VALUES
+On successful completion,
+.Fn basename
+and
+.Fn basename_r
+return pointers to the last component of
+.Fa path .
+.Pp
+If they fail, a null pointer is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+The following error codes may be set in
+.Va errno :
+.Bl -tag -width Er
+.It Bq Er ENAMETOOLONG
+The path component to be returned was larger than
+.Dv MAXPATHLEN .
+.El
+.Sh SEE ALSO
+.Xr basename 1 ,
+.Xr dirname 1 ,
+.Xr dirname 3
+.Sh STANDARDS
+The
+.Fn basename
+function conforms to
+.St -xpg4.2 .
+.Sh HISTORY
+The
+.Fn basename
+function first appeared in
+.Ox 2.2
+and
+.Fx 4.2 .
+.Sh AUTHORS
+.An Todd C. Miller
+.Sh CAVEATS
+.Fn basename
+returns a pointer to internal static storage space that will be overwritten
+by subsequent calls.
+.Pp
+Other vendor implementations of
+.Fn basename
+may modify the contents of the string passed to
+.Fn basename ;
+this should be taken into account when writing code which calls this function
+if portability is desired.
diff --git a/lib/libc/gen/basename.c b/lib/libc/gen/basename.c
new file mode 100644
index 0000000..f2bfe5f
--- /dev/null
+++ b/lib/libc/gen/basename.c
@@ -0,0 +1,79 @@
+/* $OpenBSD: basename.c,v 1.14 2005/08/08 08:05:33 espie Exp $ */
+
+/*
+ * Copyright (c) 1997, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+char *
+basename_r(const char *path, char *bname)
+{
+ const char *endp, *startp;
+ size_t len;
+
+ /* Empty or NULL string gets treated as "." */
+ if (path == NULL || *path == '\0') {
+ bname[0] = '.';
+ bname[1] = '\0';
+ return (bname);
+ }
+
+ /* Strip any trailing slashes */
+ endp = path + strlen(path) - 1;
+ while (endp > path && *endp == '/')
+ endp--;
+
+ /* All slashes becomes "/" */
+ if (endp == path && *endp == '/') {
+ bname[0] = '/';
+ bname[1] = '\0';
+ return (bname);
+ }
+
+ /* Find the start of the base */
+ startp = endp;
+ while (startp > path && *(startp - 1) != '/')
+ startp--;
+
+ len = endp - startp + 1;
+ if (len >= MAXPATHLEN) {
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ memcpy(bname, startp, len);
+ bname[len] = '\0';
+ return (bname);
+}
+
+char *
+basename(const char *path)
+{
+ static char *bname = NULL;
+
+ if (bname == NULL) {
+ bname = (char *)malloc(MAXPATHLEN);
+ if (bname == NULL)
+ return (NULL);
+ }
+ return (basename_r(path, bname));
+}
diff --git a/lib/libc/gen/check_utility_compat.3 b/lib/libc/gen/check_utility_compat.3
new file mode 100644
index 0000000..57638e5
--- /dev/null
+++ b/lib/libc/gen/check_utility_compat.3
@@ -0,0 +1,89 @@
+.\"
+.\" Copyright 2002 Massachusetts Institute of Technology
+.\"
+.\" Permission to use, copy, modify, and distribute this software and
+.\" its documentation for any purpose and without fee is hereby
+.\" granted, provided that both the above copyright notice and this
+.\" permission notice appear in all copies, that both the above
+.\" copyright notice and this permission notice appear in all
+.\" supporting documentation, and that the name of M.I.T. not be used
+.\" in advertising or publicity pertaining to distribution of the
+.\" software without specific, written prior permission. M.I.T. makes
+.\" no representations about the suitability of this software for any
+.\" purpose. It is provided "as is" without express or implied
+.\" warranty.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+.\" ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+.\" SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 27, 2002
+.Dt CHECK_UTILITY_COMPAT 3
+.Os
+.Sh NAME
+.Nm check_utility_compat
+.Nd "determine whether a utility should be compatible"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn check_utility_compat "const char *utility"
+.Sh DESCRIPTION
+The
+.Fn check_utility_compat
+function checks whether
+.Fa utility
+should behave in a traditional
+.Pq Fx 4.7 Ns -compatible
+manner, or in accordance with
+.St -p1003.1-2001 .
+The configuration is given as a comma-separated list of utility names;
+if the list is present but empty, all supported utilities assume their
+most compatible mode.
+The
+.Fn check_utility_compat
+function first checks for an environment variable named
+.Ev _COMPAT_FreeBSD_4 .
+If that environment variable does not exist, then
+.Fn check_utility_compat
+will attempt to read the contents of a symbolic link named
+.Pa /etc/compat-FreeBSD-4-util .
+If no configuration is found, compatibility mode is disabled.
+.Sh RETURN VALUES
+The
+.Fn check_utility_compat
+function returns zero if
+.Fa utility
+should implement strict
+.St -p1003.1-2001
+behavior, and nonzero otherwise.
+.Sh FILES
+.Bl -tag -width ".Pa /etc/compat-FreeBSD-4-util"
+.It Pa /etc/compat-FreeBSD-4-util
+If present, a symbolic link whose expansion gives system-wide default settings
+for the
+.Fn check_utility_compat
+function.
+.El
+.Sh ERRORS
+No errors are detected.
+.Sh HISTORY
+The
+.Fn check_utility_compat
+function first appeared in
+.Fx 5.0 .
+.Sh AUTHORS
+This manual page was written by
+.An Garrett Wollman Aq wollman@FreeBSD.org .
diff --git a/lib/libc/gen/check_utility_compat.c b/lib/libc/gen/check_utility_compat.c
new file mode 100644
index 0000000..0ccdec1
--- /dev/null
+++ b/lib/libc/gen/check_utility_compat.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright 2002 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * I din't use "namespace.h" here because none of the relevant utilities
+ * are threaded, so I'm not concerned about cancellation points or other
+ * niceties.
+ */
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef LINE_MAX
+#define LINE_MAX _POSIX2_LINE_MAX
+#endif
+
+#define _PATH_UTIL_COMPAT "/etc/compat-FreeBSD-4-util"
+#define _ENV_UTIL_COMPAT "_COMPAT_FreeBSD_4"
+
+int
+check_utility_compat(const char *utility)
+{
+ char buf[LINE_MAX];
+ char *p, *bp;
+ int len;
+
+ if ((p = getenv(_ENV_UTIL_COMPAT)) != NULL) {
+ strlcpy(buf, p, sizeof buf);
+ } else {
+ if ((len = readlink(_PATH_UTIL_COMPAT, buf, sizeof buf)) < 0)
+ return 0;
+ if (len > sizeof buf)
+ len = sizeof buf;
+ buf[len] = '\0';
+ }
+ if (buf[0] == '\0')
+ return 1;
+
+ bp = buf;
+ while ((p = strsep(&bp, ",")) != NULL) {
+ if (strcmp(p, utility) == 0)
+ return 1;
+ }
+ return 0;
+}
diff --git a/lib/libc/gen/clock.3 b/lib/libc/gen/clock.3
new file mode 100644
index 0000000..6a585e5
--- /dev/null
+++ b/lib/libc/gen/clock.3
@@ -0,0 +1,76 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)clock.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt CLOCK 3
+.Os
+.Sh NAME
+.Nm clock
+.Nd determine processor time used
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In time.h
+.Ft clock_t
+.Fn clock void
+.Sh DESCRIPTION
+The
+.Fn clock
+function
+determines the amount of processor time used since the invocation of the
+calling process, measured in
+.Dv CLOCKS_PER_SEC Ns s
+of a second.
+.Sh RETURN VALUES
+The
+.Fn clock
+function returns the amount of time used unless an error occurs, in which
+case the return value is \-1.
+.Sh SEE ALSO
+.Xr getrusage 2 ,
+.Xr clocks 7
+.Sh STANDARDS
+The
+.Fn clock
+function conforms to
+.St -isoC .
+However,
+.St -susv2
+requires
+.Dv CLOCKS_PER_SEC
+to be defined as one million.
+.Fx
+does not conform to this requirement;
+changing the value would introduce binary incompatibility
+and one million is still inadequate on modern processors.
diff --git a/lib/libc/gen/clock.c b/lib/libc/gen/clock.c
new file mode 100644
index 0000000..b405cda
--- /dev/null
+++ b/lib/libc/gen/clock.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)clock.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+/*
+ * Convert usec to clock ticks; could do (usec * CLOCKS_PER_SEC) / 1000000,
+ * but this would overflow if we switch to nanosec.
+ */
+#define CONVTCK(r) ((r).tv_sec * CLOCKS_PER_SEC \
+ + (r).tv_usec / (1000000 / CLOCKS_PER_SEC))
+
+clock_t
+clock()
+{
+ struct rusage ru;
+
+ if (getrusage(RUSAGE_SELF, &ru))
+ return ((clock_t) -1);
+ return((clock_t)((CONVTCK(ru.ru_utime) + CONVTCK(ru.ru_stime))));
+}
diff --git a/lib/libc/gen/closedir.c b/lib/libc/gen/closedir.c
new file mode 100644
index 0000000..5db351b
--- /dev/null
+++ b/lib/libc/gen/closedir.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1983, 1993
+ * Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)closedir.c 8.1 (Berkeley) 6/10/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <dirent.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+#include "telldir.h"
+
+/*
+ * close a directory.
+ */
+int
+closedir(DIR *dirp)
+{
+ int fd;
+
+ if (__isthreaded)
+ _pthread_mutex_lock(&dirp->dd_lock);
+ fd = dirp->dd_fd;
+ dirp->dd_fd = -1;
+ dirp->dd_loc = 0;
+ free((void *)dirp->dd_buf);
+ _reclaim_telldir(dirp);
+ if (__isthreaded) {
+ _pthread_mutex_unlock(&dirp->dd_lock);
+ _pthread_mutex_destroy(&dirp->dd_lock);
+ }
+ free((void *)dirp);
+ return(_close(fd));
+}
diff --git a/lib/libc/gen/confstr.3 b/lib/libc/gen/confstr.3
new file mode 100644
index 0000000..9ca4250
--- /dev/null
+++ b/lib/libc/gen/confstr.3
@@ -0,0 +1,129 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)confstr.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd December 3, 2006
+.Dt CONFSTR 3
+.Os
+.Sh NAME
+.Nm confstr
+.Nd get string-valued configurable variables
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft size_t
+.Fn confstr "int name" "char *buf" "size_t len"
+.Sh DESCRIPTION
+This interface is specified by
+.St -p1003.1-2001 .
+A more flexible (but non-portable) interface is provided by
+.Xr sysctl 3 .
+.Pp
+The
+.Fn confstr
+function provides a method for applications to get configuration
+defined string values.
+Shell programmers needing access to these parameters should use the
+.Xr getconf 1
+utility.
+.Pp
+The
+.Fa name
+argument specifies the system variable to be queried.
+Symbolic constants for each name value are found in the include file
+.In unistd.h .
+The
+.Fa len
+argument specifies the size of the buffer referenced by the
+argument
+.Fa buf .
+If
+.Fa len
+is non-zero,
+.Fa buf
+is a non-null pointer, and
+.Fa name
+has a value, up to
+.Fa len
+\- 1 bytes of the value are copied into the buffer
+.Fa buf .
+The copied value is always null terminated.
+.Pp
+The available values are as follows:
+.Bl -tag -width 6n
+.It Li _CS_PATH
+Return a value for the
+.Ev PATH
+environment variable that finds all the standard utilities.
+.El
+.Sh RETURN VALUES
+If the call to
+.Fn confstr
+is not successful, 0 is returned and
+.Va errno
+is set appropriately.
+Otherwise, if the variable does not have a configuration defined value,
+0 is returned and
+.Va errno
+is not modified.
+Otherwise, the buffer size needed to hold the entire configuration-defined
+value is returned.
+If this size is greater than the argument
+.Fa len ,
+the string in
+.Fa buf
+was truncated.
+.Sh ERRORS
+The
+.Fn confstr
+function may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr malloc 3
+and
+.Xr sysctl 3 .
+.Pp
+In addition, the following errors may be reported:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value of the
+.Fa name
+argument is invalid.
+.El
+.Sh SEE ALSO
+.Xr getconf 1 ,
+.Xr pathconf 2 ,
+.Xr sysconf 3 ,
+.Xr sysctl 3
+.Sh HISTORY
+The
+.Fn confstr
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/confstr.c b/lib/libc/gen/confstr.c
new file mode 100644
index 0000000..2f9a061
--- /dev/null
+++ b/lib/libc/gen/confstr.c
@@ -0,0 +1,121 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)confstr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <string.h>
+#include <unistd.h>
+
+
+size_t
+confstr(int name, char *buf, size_t len)
+{
+ const char *p;
+ const char UPE[] = "unsupported programming environment";
+
+ switch (name) {
+ case _CS_PATH:
+ p = _PATH_STDPATH;
+ goto docopy;
+
+ /*
+ * POSIX/SUS ``Programming Environments'' stuff
+ *
+ * We don't support more than one programming environment
+ * on any platform (yet), so we just return the empty
+ * string for the environment we are compiled for,
+ * and the string "unsupported programming environment"
+ * for anything else. (The Standard says that if these
+ * values are used on a system which does not support
+ * this environment -- determined via sysconf() -- then
+ * the value we return is unspecified. So, we return
+ * something which will cause obvious breakage.)
+ */
+ case _CS_POSIX_V6_ILP32_OFF32_CFLAGS:
+ case _CS_POSIX_V6_ILP32_OFF32_LDFLAGS:
+ case _CS_POSIX_V6_ILP32_OFF32_LIBS:
+ case _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS:
+ case _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS:
+ case _CS_POSIX_V6_LPBIG_OFFBIG_LIBS:
+ /*
+ * These two environments are never supported.
+ */
+ p = UPE;
+ goto docopy;
+
+ case _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS:
+ case _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS:
+ case _CS_POSIX_V6_ILP32_OFFBIG_LIBS:
+ if (sizeof(long) * CHAR_BIT == 32 &&
+ sizeof(off_t) > sizeof(long))
+ p = "";
+ else
+ p = UPE;
+ goto docopy;
+
+ case _CS_POSIX_V6_LP64_OFF64_CFLAGS:
+ case _CS_POSIX_V6_LP64_OFF64_LDFLAGS:
+ case _CS_POSIX_V6_LP64_OFF64_LIBS:
+ if (sizeof(long) * CHAR_BIT >= 64 &&
+ sizeof(void *) * CHAR_BIT >= 64 &&
+ sizeof(int) * CHAR_BIT >= 32 &&
+ sizeof(off_t) >= sizeof(long))
+ p = "";
+ else
+ p = UPE;
+ goto docopy;
+
+ case _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS:
+ /* XXX - should have more complete coverage */
+ if (sizeof(long) * CHAR_BIT >= 64)
+ p = "_POSIX_V6_LP64_OFF64";
+ else
+ p = "_POSIX_V6_ILP32_OFFBIG";
+ goto docopy;
+
+docopy:
+ if (len != 0 && buf != NULL)
+ strlcpy(buf, p, len);
+ return (strlen(p) + 1);
+
+ default:
+ errno = EINVAL;
+ return (0);
+ }
+ /* NOTREACHED */
+}
diff --git a/lib/libc/gen/crypt.c b/lib/libc/gen/crypt.c
new file mode 100644
index 0000000..ab1a799
--- /dev/null
+++ b/lib/libc/gen/crypt.c
@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Tom Truscott.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+/* from static char sccsid[] = "@(#)crypt.c 5.11 (Berkeley) 6/25/91"; */
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+ * UNIX password, and DES, encryption.
+ *
+ * since this is non-exportable, this is just a dummy. if you want real
+ * encryption, make sure you've got libcrypt.a around.
+ */
+
+__warn_references(des_setkey,
+ "WARNING! des_setkey(3) not present in the system!");
+
+/* ARGSUSED */
+int
+des_setkey(const char *key __unused)
+{
+ fprintf(stderr, "WARNING! des_setkey(3) not present in the system!\n");
+ return (0);
+}
+
+__warn_references(des_cipher,
+ "WARNING! des_cipher(3) not present in the system!");
+
+/* ARGSUSED */
+int
+des_cipher(const char *in, char *out, long salt __unused, int num_iter __unused)
+{
+ fprintf(stderr, "WARNING! des_cipher(3) not present in the system!\n");
+ bcopy(in, out, 8);
+ return (0);
+}
+
+__warn_references(setkey,
+ "WARNING! setkey(3) not present in the system!");
+
+/* ARGSUSED */
+int
+setkey(const char *key __unused)
+{
+ fprintf(stderr, "WARNING! setkey(3) not present in the system!\n");
+ return (0);
+}
+
+__warn_references(encrypt,
+ "WARNING! encrypt(3) not present in the system!");
+
+/* ARGSUSED */
+int
+encrypt(char *block __unused, int flag __unused)
+{
+ fprintf(stderr, "WARNING! encrypt(3) not present in the system!\n");
+ return (0);
+}
diff --git a/lib/libc/gen/ctermid.3 b/lib/libc/gen/ctermid.3
new file mode 100644
index 0000000..d737e5e
--- /dev/null
+++ b/lib/libc/gen/ctermid.3
@@ -0,0 +1,108 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)ctermid.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd October 1, 2011
+.Dt CTERMID 3
+.Os
+.Sh NAME
+.Nm ctermid
+.Nd generate terminal pathname
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft char *
+.Fn ctermid "char *buf"
+.Ft char *
+.Fn ctermid_r "char *buf"
+.Sh DESCRIPTION
+The
+.Fn ctermid
+function generates a string, that, when used as a pathname, refers to
+the current controlling terminal of the calling process.
+.Pp
+If
+.Fa buf
+is the
+.Dv NULL
+pointer, a pointer to a static area is returned.
+Otherwise, the pathname is copied into the memory referenced by
+.Fa buf .
+The argument
+.Fa buf
+is assumed to be at least
+.Dv L_ctermid
+(as defined in the include
+file
+.In stdio.h )
+bytes long.
+.Pp
+The
+.Fn ctermid_r
+function
+provides the same functionality as
+.Fn ctermid
+except that if
+.Fa buf
+is a
+.Dv NULL
+pointer,
+.Dv NULL
+is returned.
+.Pp
+If no suitable lookup of the controlling terminal name can be performed,
+this implementation returns
+.Ql /dev/tty .
+.Sh RETURN VALUES
+Upon successful completion, a
+.Pf non- Dv NULL
+pointer is returned.
+Otherwise, a
+.Dv NULL
+pointer is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+The current implementation detects no error conditions.
+.Sh SEE ALSO
+.Xr ttyname 3
+.Sh STANDARDS
+The
+.Fn ctermid
+function conforms to
+.St -p1003.1-88 .
+.Sh BUGS
+By default the
+.Fn ctermid
+function
+writes all information to an internal static object.
+Subsequent calls to
+.Fn ctermid
+will modify the same object.
diff --git a/lib/libc/gen/ctermid.c b/lib/libc/gen/ctermid.c
new file mode 100644
index 0000000..8af1cb2
--- /dev/null
+++ b/lib/libc/gen/ctermid.c
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 2011 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/sysctl.h>
+
+#include <errno.h>
+#include <paths.h>
+#include <stdio.h>
+#include <string.h>
+
+#define LEN_PATH_DEV (sizeof(_PATH_DEV) - 1)
+
+char *
+ctermid(char *s)
+{
+ static char def[sizeof(_PATH_DEV) + SPECNAMELEN];
+ struct stat sb;
+ size_t dlen;
+ int sverrno;
+
+ if (s == NULL) {
+ s = def;
+ dlen = sizeof(def) - LEN_PATH_DEV;
+ } else
+ dlen = L_ctermid - LEN_PATH_DEV;
+ strcpy(s, _PATH_TTY);
+
+ /* Attempt to perform a lookup of the actual TTY pathname. */
+ sverrno = errno;
+ if (stat(_PATH_TTY, &sb) == 0 && S_ISCHR(sb.st_mode))
+ (void)sysctlbyname("kern.devname", s + LEN_PATH_DEV,
+ &dlen, &sb.st_rdev, sizeof(sb.st_rdev));
+ errno = sverrno;
+ return (s);
+}
+
+char *
+ctermid_r(char *s)
+{
+
+ return (s != NULL ? ctermid(s) : NULL);
+}
diff --git a/lib/libc/gen/daemon.3 b/lib/libc/gen/daemon.3
new file mode 100644
index 0000000..34db966
--- /dev/null
+++ b/lib/libc/gen/daemon.3
@@ -0,0 +1,112 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)daemon.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd June 9, 1993
+.Dt DAEMON 3
+.Os
+.Sh NAME
+.Nm daemon
+.Nd run in the background
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fn daemon "int nochdir" "int noclose"
+.Sh DESCRIPTION
+The
+.Fn daemon
+function is for programs wishing to detach themselves from the
+controlling terminal and run in the background as system daemons.
+.Pp
+Unless the argument
+.Fa nochdir
+is non-zero,
+.Fn daemon
+changes the current working directory to the root
+.Pq Pa / .
+.Pp
+Unless the argument
+.Fa noclose
+is non-zero,
+.Fn daemon
+will redirect standard input, standard output, and standard error to
+.Pa /dev/null .
+.Sh RETURN VALUES
+.Rv -std daemon
+.Sh ERRORS
+The
+.Fn daemon
+function may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr fork 2
+and
+.Xr setsid 2 .
+.Sh SEE ALSO
+.Xr fork 2 ,
+.Xr setsid 2 ,
+.Xr sigaction 2
+.Sh HISTORY
+The
+.Fn daemon
+function first appeared in
+.Bx 4.4 .
+.Sh CAVEATS
+Unless the
+.Fa noclose
+argument is non-zero,
+.Fn daemon
+will close the first three file descriptors and redirect them to
+.Pa /dev/null .
+Normally, these correspond to standard input, standard output, and
+standard error.
+However, if any of those file descriptors refer to something else, they
+will still be closed, resulting in incorrect behavior of the calling program.
+This can happen if any of standard input, standard output, or standard
+error have been closed before the program was run.
+Programs using
+.Fn daemon
+should therefore either call
+.Fn daemon
+before opening any files or sockets, or verify that any file
+descriptors obtained have values greater than 2.
+.Pp
+The
+.Fn daemon
+function temporarily ignores
+.Dv SIGHUP
+while calling
+.Xr setsid 2
+to prevent a parent session group leader's calls to
+.Xr fork 2
+and then
+.Xr _exit 2
+from prematurely terminating the child process.
diff --git a/lib/libc/gen/daemon.c b/lib/libc/gen/daemon.c
new file mode 100644
index 0000000..b359a87
--- /dev/null
+++ b/lib/libc/gen/daemon.c
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)daemon.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+int
+daemon(nochdir, noclose)
+ int nochdir, noclose;
+{
+ struct sigaction osa, sa;
+ int fd;
+ pid_t newgrp;
+ int oerrno;
+ int osa_ok;
+
+ /* A SIGHUP may be thrown when the parent exits below. */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_handler = SIG_IGN;
+ sa.sa_flags = 0;
+ osa_ok = _sigaction(SIGHUP, &sa, &osa);
+
+ switch (fork()) {
+ case -1:
+ return (-1);
+ case 0:
+ break;
+ default:
+ /*
+ * A fine point: _exit(0), not exit(0), to avoid triggering
+ * atexit(3) processing
+ */
+ _exit(0);
+ }
+
+ newgrp = setsid();
+ oerrno = errno;
+ if (osa_ok != -1)
+ _sigaction(SIGHUP, &osa, NULL);
+
+ if (newgrp == -1) {
+ errno = oerrno;
+ return (-1);
+ }
+
+ if (!nochdir)
+ (void)chdir("/");
+
+ if (!noclose && (fd = _open(_PATH_DEVNULL, O_RDWR, 0)) != -1) {
+ (void)_dup2(fd, STDIN_FILENO);
+ (void)_dup2(fd, STDOUT_FILENO);
+ (void)_dup2(fd, STDERR_FILENO);
+ if (fd > 2)
+ (void)_close(fd);
+ }
+ return (0);
+}
diff --git a/lib/libc/gen/devname.3 b/lib/libc/gen/devname.3
new file mode 100644
index 0000000..7ff31c7
--- /dev/null
+++ b/lib/libc/gen/devname.3
@@ -0,0 +1,115 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)devname.3 8.2 (Berkeley) 4/29/95
+.\" $FreeBSD$
+.\"
+.Dd February 22, 2005
+.Dt DEVNAME 3
+.Os
+.Sh NAME
+.Nm devname
+.Nd "get device name"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/stat.h
+.In stdlib.h
+.Ft char *
+.Fn devname "dev_t dev" "mode_t type"
+.Ft char *
+.Fn devname_r "dev_t dev" "mode_t type" "char *buf" "int len"
+.Ft char *
+.Fn fdevname "int fd"
+.Ft char *
+.Fn fdevname_r "int fd" "char *buf" "int len"
+.Sh DESCRIPTION
+The
+.Fn devname
+function returns a pointer to the name of the block or character
+device in
+.Pa /dev
+with a device number of
+.Fa dev ,
+and a file type matching the one encoded in
+.Fa type
+which must be one of
+.Dv S_IFBLK
+or
+.Dv S_IFCHR .
+To find the right name,
+.Fn devname
+asks the kernel via the
+.Va kern.devname
+sysctl.
+If it is unable to come up with a suitable name,
+it will format the information encapsulated in
+.Fa dev
+and
+.Fa type
+in a human-readable format.
+.Pp
+The
+.Fn fdevname
+and
+.Fn fdevname_r
+function obtains the device name directly from a file descriptor
+pointing to a character device.
+If it is unable to come up with a suitable name, these functions will
+return a NULL pointer.
+.Pp
+.Fn devname
+and
+.Fn fdevname
+return the name stored in a static buffer which will be overwritten
+on subsequent calls.
+.Fn devname_r
+and
+.Fn fdevname_r
+take a buffer and length as argument to avoid this problem.
+.Sh EXAMPLES
+.Bd -literal -compact
+int fd;
+struct stat buf;
+char *name;
+
+ fd = open("/dev/tun");
+ fstat(fd, &buf);
+ printf("devname is /dev/%s\en", devname(buf.st_rdev, S_IFCHR));
+ printf("fdevname is /dev/%s\en", fdevname(fd));
+.Ed
+.Sh SEE ALSO
+.Xr stat 2
+.Sh HISTORY
+The
+.Fn devname
+function appeared in
+.Bx 4.4 .
+The
+.Fn fdevname
+function appeared in
+.Fx 8.0 .
diff --git a/lib/libc/gen/devname.c b/lib/libc/gen/devname.c
new file mode 100644
index 0000000..da0b923
--- /dev/null
+++ b/lib/libc/gen/devname.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)devname.c 8.2 (Berkeley) 4/29/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#include <stdio.h>
+#include <stdint.h>
+#include <string.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+
+char *
+devname_r(dev_t dev, mode_t type, char *buf, int len)
+{
+ int i;
+ size_t j;
+
+ if (dev == NODEV || !(S_ISCHR(type) || S_ISBLK(dev))) {
+ strlcpy(buf, "#NODEV", len);
+ return (buf);
+ }
+
+ if (S_ISCHR(type)) {
+ j = len;
+ i = sysctlbyname("kern.devname", buf, &j, &dev, sizeof (dev));
+ if (i == 0)
+ return (buf);
+ }
+
+ /* Finally just format it */
+ snprintf(buf, len, "#%c:%#jx",
+ S_ISCHR(type) ? 'C' : 'B', (uintmax_t)dev);
+ return (buf);
+}
+
+char *
+devname(dev_t dev, mode_t type)
+{
+ static char buf[SPECNAMELEN + 1];
+
+ return (devname_r(dev, type, buf, sizeof(buf)));
+}
diff --git a/lib/libc/gen/directory.3 b/lib/libc/gen/directory.3
new file mode 100644
index 0000000..1c568fc
--- /dev/null
+++ b/lib/libc/gen/directory.3
@@ -0,0 +1,247 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)directory.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd April 16, 2008
+.Dt DIRECTORY 3
+.Os
+.Sh NAME
+.Nm opendir ,
+.Nm fdopendir ,
+.Nm readdir ,
+.Nm readdir_r ,
+.Nm telldir ,
+.Nm seekdir ,
+.Nm rewinddir ,
+.Nm closedir ,
+.Nm dirfd
+.Nd directory operations
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In dirent.h
+.Ft DIR *
+.Fn opendir "const char *filename"
+.Ft DIR *
+.Fn fdopendir "int fd"
+.Ft struct dirent *
+.Fn readdir "DIR *dirp"
+.Ft int
+.Fn readdir_r "DIR *dirp" "struct dirent *entry" "struct dirent **result"
+.Ft long
+.Fn telldir "DIR *dirp"
+.Ft void
+.Fn seekdir "DIR *dirp" "long loc"
+.Ft void
+.Fn rewinddir "DIR *dirp"
+.Ft int
+.Fn closedir "DIR *dirp"
+.Ft int
+.Fn dirfd "DIR *dirp"
+.Sh DESCRIPTION
+The
+.Fn opendir
+function
+opens the directory named by
+.Fa filename ,
+associates a
+.Em directory stream
+with it
+and
+returns a pointer to be used to identify the
+.Em directory stream
+in subsequent operations.
+The pointer
+.Dv NULL
+is returned if
+.Fa filename
+cannot be accessed, or if it cannot
+.Xr malloc 3
+enough memory to hold the whole thing.
+.Pp
+The
+.Fn fdopendir
+function is equivalent to the
+.Fn opendir
+function except that the directory is specified by a file descriptor
+.Fa fd
+rather than by a name.
+The file offset associated with the file descriptor at the time of the call
+determines which entries are returned.
+.Pp
+Upon successful return from
+.Fn fdopendir ,
+the file descriptor is under the control of the system,
+and if any attempt is made to close the file descriptor,
+or to modify the state of the associated description other than by means
+of
+.Fn closedir ,
+.Fn readdir ,
+.Fn readdir_r ,
+or
+.Fn rewinddir ,
+the behavior is undefined.
+Upon calling
+.Fn closedir
+the file descriptor is closed.
+The
+.Dv FD_CLOEXEC
+flag is set on the file descriptor by a successful call to
+.Fn fdopendir .
+.Pp
+The
+.Fn readdir
+function
+returns a pointer to the next directory entry.
+It returns
+.Dv NULL
+upon reaching the end of the directory or on error.
+In the event of an error,
+.Va errno
+may be set to any of the values documented for the
+.Xr getdirentries 2
+system call.
+.Pp
+The
+.Fn readdir_r
+function
+provides the same functionality as
+.Fn readdir ,
+but the caller must provide a directory
+.Fa entry
+buffer to store the results in.
+If the read succeeds,
+.Fa result
+is pointed at the
+.Fa entry ;
+upon reaching the end of the directory
+.Fa result
+is set to
+.Dv NULL .
+The
+.Fn readdir_r
+function
+returns 0 on success or an error number to indicate failure.
+.Pp
+The
+.Fn telldir
+function
+returns the current location associated with the named
+.Em directory stream .
+Values returned by
+.Fn telldir
+are good only for the lifetime of the
+.Dv DIR
+pointer,
+.Fa dirp ,
+from which they are derived.
+If the directory is closed and then
+reopened, prior values returned by
+.Fn telldir
+will no longer be valid.
+.Pp
+The
+.Fn seekdir
+function
+sets the position of the next
+.Fn readdir
+operation on the
+.Em directory stream .
+The new position reverts to the one associated with the
+.Em directory stream
+when the
+.Fn telldir
+operation was performed.
+.Pp
+The
+.Fn rewinddir
+function
+resets the position of the named
+.Em directory stream
+to the beginning of the directory.
+.Pp
+The
+.Fn closedir
+function
+closes the named
+.Em directory stream
+and frees the structure associated with the
+.Fa dirp
+pointer,
+returning 0 on success.
+On failure, \-1 is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Pp
+The
+.Fn dirfd
+function
+returns the integer file descriptor associated with the named
+.Em directory stream ,
+see
+.Xr open 2 .
+.Pp
+Sample code which searches a directory for entry ``name'' is:
+.Bd -literal -offset indent
+dirp = opendir(".");
+if (dirp == NULL)
+ return (ERROR);
+len = strlen(name);
+while ((dp = readdir(dirp)) != NULL) {
+ if (dp->d_namlen == len && strcmp(dp->d_name, name) == 0) {
+ (void)closedir(dirp);
+ return (FOUND);
+ }
+}
+(void)closedir(dirp);
+return (NOT_FOUND);
+.Ed
+.Sh SEE ALSO
+.Xr close 2 ,
+.Xr lseek 2 ,
+.Xr open 2 ,
+.Xr read 2 ,
+.Xr dir 5
+.Sh HISTORY
+The
+.Fn opendir ,
+.Fn readdir ,
+.Fn telldir ,
+.Fn seekdir ,
+.Fn rewinddir ,
+.Fn closedir ,
+and
+.Fn dirfd
+functions appeared in
+.Bx 4.2 .
+The
+.Fn fdopendir
+function appeared in
+.Fx 8.0 .
diff --git a/lib/libc/gen/dirname.3 b/lib/libc/gen/dirname.3
new file mode 100644
index 0000000..ba5cce3
--- /dev/null
+++ b/lib/libc/gen/dirname.3
@@ -0,0 +1,99 @@
+.\" $OpenBSD: dirname.3,v 1.17 2007/05/31 19:19:28 jmc Exp $
+.\"
+.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 12, 2006
+.Dt DIRNAME 3
+.Os
+.Sh NAME
+.Nm dirname
+.Nd extract the directory part of a pathname
+.Sh SYNOPSIS
+.In libgen.h
+.Ft char *
+.Fn dirname "const char *path"
+.Sh DESCRIPTION
+The
+.Fn dirname
+function is the converse of
+.Xr basename 3 ;
+it returns a pointer to the parent directory of the pathname pointed to by
+.Fa path .
+Any trailing
+.Sq \&/
+characters are not counted as part of the directory
+name.
+If
+.Fa path
+is a null pointer, the empty string, or contains no
+.Sq \&/
+characters,
+.Fn dirname
+returns a pointer to the string
+.Qq \&. ,
+signifying the current directory.
+.Sh IMPLEMENTATION NOTES
+The
+.Fn dirname
+function
+returns a pointer to internal storage space allocated on the first call
+that will be overwritten
+by subsequent calls.
+.Pp
+Other vendor implementations of
+.Fn dirname
+may modify the contents of the string passed to
+.Fn dirname ;
+this should be taken into account when writing code which calls this function
+if portability is desired.
+.Sh RETURN VALUES
+On successful completion,
+.Fn dirname
+returns a pointer to the parent directory of
+.Fa path .
+.Pp
+If
+.Fn dirname
+fails, a null pointer is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+The following error codes may be set in
+.Va errno :
+.Bl -tag -width Er
+.It Bq Er ENAMETOOLONG
+The path component to be returned was larger than
+.Dv MAXPATHLEN .
+.El
+.Sh SEE ALSO
+.Xr basename 1 ,
+.Xr dirname 1 ,
+.Xr basename 3
+.Sh STANDARDS
+The
+.Fn dirname
+function conforms to
+.St -xpg4.2 .
+.Sh HISTORY
+The
+.Fn dirname
+function first appeared in
+.Ox 2.2
+and
+.Fx 4.2 .
+.Sh AUTHORS
+.An "Todd C. Miller"
diff --git a/lib/libc/gen/dirname.c b/lib/libc/gen/dirname.c
new file mode 100644
index 0000000..5a94c1a
--- /dev/null
+++ b/lib/libc/gen/dirname.c
@@ -0,0 +1,77 @@
+/* $OpenBSD: dirname.c,v 1.13 2005/08/08 08:05:33 espie Exp $ */
+
+/*
+ * Copyright (c) 1997, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <libgen.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/param.h>
+
+char *
+dirname(const char *path)
+{
+ static char *dname = NULL;
+ size_t len;
+ const char *endp;
+
+ if (dname == NULL) {
+ dname = (char *)malloc(MAXPATHLEN);
+ if (dname == NULL)
+ return(NULL);
+ }
+
+ /* Empty or NULL string gets treated as "." */
+ if (path == NULL || *path == '\0') {
+ dname[0] = '.';
+ dname[1] = '\0';
+ return (dname);
+ }
+
+ /* Strip any trailing slashes */
+ endp = path + strlen(path) - 1;
+ while (endp > path && *endp == '/')
+ endp--;
+
+ /* Find the start of the dir */
+ while (endp > path && *endp != '/')
+ endp--;
+
+ /* Either the dir is "/" or there are no slashes */
+ if (endp == path) {
+ dname[0] = *endp == '/' ? '/' : '.';
+ dname[1] = '\0';
+ return (dname);
+ } else {
+ /* Move forward past the separating slashes */
+ do {
+ endp--;
+ } while (endp > path && *endp == '/');
+ }
+
+ len = endp - path + 1;
+ if (len >= MAXPATHLEN) {
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ memcpy(dname, path, len);
+ dname[len] = '\0';
+ return (dname);
+}
diff --git a/lib/libc/gen/disklabel.c b/lib/libc/gen/disklabel.c
new file mode 100644
index 0000000..bd15a47
--- /dev/null
+++ b/lib/libc/gen/disklabel.c
@@ -0,0 +1,159 @@
+/*
+ * Copyright (c) 1983, 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)disklabel.c 8.2 (Berkeley) 5/3/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#define DKTYPENAMES
+#define FSTYPENAMES
+#include <sys/disklabel.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+static int
+gettype(char *t, const char **names)
+{
+ const char **nm;
+
+ for (nm = names; *nm; nm++)
+ if (strcasecmp(t, *nm) == 0)
+ return (nm - names);
+ if (isdigit((unsigned char)*t))
+ return (atoi(t));
+ return (0);
+}
+
+struct disklabel *
+getdiskbyname(const char *name)
+{
+ static struct disklabel disk;
+ struct disklabel *dp = &disk;
+ struct partition *pp;
+ char *buf;
+ char *db_array[2] = { _PATH_DISKTAB, 0 };
+ char *cp, *cq; /* can't be register */
+ char p, max, psize[3], pbsize[3],
+ pfsize[3], poffset[3], ptype[3];
+ u_int32_t *dx;
+
+ if (cgetent(&buf, db_array, (char *) name) < 0)
+ return NULL;
+
+ bzero((char *)&disk, sizeof(disk));
+ /*
+ * typename
+ */
+ cq = dp->d_typename;
+ cp = buf;
+ while (cq < dp->d_typename + sizeof(dp->d_typename) - 1 &&
+ (*cq = *cp) && *cq != '|' && *cq != ':')
+ cq++, cp++;
+ *cq = '\0';
+
+ if (cgetstr(buf, "ty", &cq) > 0 && strcmp(cq, "removable") == 0)
+ dp->d_flags |= D_REMOVABLE;
+ else if (cq && strcmp(cq, "simulated") == 0)
+ dp->d_flags |= D_RAMDISK;
+ if (cgetcap(buf, "sf", ':') != NULL)
+ dp->d_flags |= D_BADSECT;
+
+#define getnumdflt(field, dname, dflt) \
+ { long f; (field) = (cgetnum(buf, dname, &f) == -1) ? (dflt) : f; }
+
+ getnumdflt(dp->d_secsize, "se", DEV_BSIZE);
+ getnumdflt(dp->d_ntracks, "nt", 0);
+ getnumdflt(dp->d_nsectors, "ns", 0);
+ getnumdflt(dp->d_ncylinders, "nc", 0);
+
+ if (cgetstr(buf, "dt", &cq) > 0)
+ dp->d_type = gettype(cq, dktypenames);
+ else
+ getnumdflt(dp->d_type, "dt", 0);
+ getnumdflt(dp->d_secpercyl, "sc", dp->d_nsectors * dp->d_ntracks);
+ getnumdflt(dp->d_secperunit, "su", dp->d_secpercyl * dp->d_ncylinders);
+ getnumdflt(dp->d_rpm, "rm", 3600);
+ getnumdflt(dp->d_interleave, "il", 1);
+ getnumdflt(dp->d_trackskew, "sk", 0);
+ getnumdflt(dp->d_cylskew, "cs", 0);
+ getnumdflt(dp->d_headswitch, "hs", 0);
+ getnumdflt(dp->d_trkseek, "ts", 0);
+ getnumdflt(dp->d_bbsize, "bs", BBSIZE);
+ getnumdflt(dp->d_sbsize, "sb", 0);
+ strcpy(psize, "px");
+ strcpy(pbsize, "bx");
+ strcpy(pfsize, "fx");
+ strcpy(poffset, "ox");
+ strcpy(ptype, "tx");
+ max = 'a' - 1;
+ pp = &dp->d_partitions[0];
+ for (p = 'a'; p < 'a' + MAXPARTITIONS; p++, pp++) {
+ long l;
+ psize[1] = pbsize[1] = pfsize[1] = poffset[1] = ptype[1] = p;
+ if (cgetnum(buf, psize, &l) == -1)
+ pp->p_size = 0;
+ else {
+ pp->p_size = l;
+ cgetnum(buf, poffset, &l);
+ pp->p_offset = l;
+ getnumdflt(pp->p_fsize, pfsize, 0);
+ if (pp->p_fsize) {
+ long bsize;
+
+ if (cgetnum(buf, pbsize, &bsize) == 0)
+ pp->p_frag = bsize / pp->p_fsize;
+ else
+ pp->p_frag = 8;
+ }
+ getnumdflt(pp->p_fstype, ptype, 0);
+ if (pp->p_fstype == 0 && cgetstr(buf, ptype, &cq) > 0)
+ pp->p_fstype = gettype(cq, fstypenames);
+ max = p;
+ }
+ }
+ dp->d_npartitions = max + 1 - 'a';
+ (void)strcpy(psize, "dx");
+ dx = dp->d_drivedata;
+ for (p = '0'; p < '0' + NDDATA; p++, dx++) {
+ psize[1] = p;
+ getnumdflt(*dx, psize, 0);
+ }
+ dp->d_magic = DISKMAGIC;
+ dp->d_magic2 = DISKMAGIC;
+ free(buf);
+ return (dp);
+}
diff --git a/lib/libc/gen/dl_iterate_phdr.3 b/lib/libc/gen/dl_iterate_phdr.3
new file mode 100644
index 0000000..f148ab1
--- /dev/null
+++ b/lib/libc/gen/dl_iterate_phdr.3
@@ -0,0 +1,115 @@
+.\" Copyright (c) 2005 Mark Kettenis
+.\" Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $OpenBSD: dl_iterate_phdr.3,v 1.3 2007/05/31 19:19:48 jmc Exp $
+.\" $FreeBSD$
+.Dd February 15, 2012
+.Dt DL_ITERATE_PHDR 3
+.Os
+.Sh NAME
+.Nm dl_iterate_phdr
+.Nd iterate over program headers
+.Sh LIBRARY
+For the dynamically linked binaries, the service is provided by
+.Xr ld-elf.so.1 1
+dynamic linker.
+Statically linked programs use an implementation of
+.Fn dl_iterate_phdr
+from libc.
+.Sh SYNOPSIS
+.Fd #include <link.h>
+.Ft int
+.Fn dl_iterate_phdr "int (*callback)(struct dl_phdr_info *, size_t, void *)" "void *data"
+.Sh DESCRIPTION
+The
+.Fn dl_iterate_phdr
+function iterates over all ELF objects loaded into a process's
+address space, calling
+.Fa callback
+for each object, passing it information about the object's
+program headers and the
+.Fa data
+argument.
+The iteration is aborted when all objects are passed, or when the next
+.Fa callback
+call returns non-zero value.
+The information about the program headers is passed in a structure
+that is defined as:
+.Bd -literal
+struct dl_phdr_info {
+ Elf_Addr dlpi_addr;
+ const char *dlpi_name;
+ const Elf_Phdr *dlpi_phdr;
+ Elf_Half dlpi_phnum;
+ unsigned long long int dlpi_adds;
+ unsigned long long int dlpi_subs;
+ size_t dlpi_tls_modid;
+ void *dlpi_tls_data;
+};
+.Ed
+.Pp
+The members of
+.Li struct dl_phdr_info
+have the following meaning:
+.Bl -tag -width dlpi_tls_modid
+.It Fa dlpi_addr
+The base address at which the object is mapped into the address
+space of the calling process.
+.It Fa dlpi_name
+The name of the ELF object.
+.It Fa dlpi_phdr
+A pointer to the object's program headers.
+.It Fa dlpi_phnum
+The number of program headers in the object.
+.It Fa dlpi_adds
+The counter of the object loads performed by the dynamic linker.
+.It Fa dlpi_subs
+The counter of the object unloads performed by the dynamic linker.
+.It Fa dlpi_tls_modid
+The TLS index of the object.
+.It Fa dlpi_tls_data
+A pointer to the initialization data for the object TLS segment.
+.El
+.Pp
+Future versions of
+.Fx
+might add more members to this structure.
+To make it possible for programs to check whether any new members have
+been added, the size of the structure is passed as an second argument to
+.Fa callback .
+.Pp
+The third argument to callback is the
+.Fa data
+value passed to the call to
+.Fn dl_iterate_phdr ,
+allowing the
+.Fa callback
+to have a context.
+.Sh RETURN VALUES
+The
+.Fn dl_iterate_phdr
+returns the value returned by the last
+.Fa callback
+call executed.
+.Sh SEE ALSO
+.Xr ld 1 ,
+.Xr ld-elf.so.1 1 ,
+.Xr dlopen 3 ,
+.Xr elf 5
+.Sh HISTORY
+The
+.Nm
+function first appeared in
+.Fx 7.0 .
diff --git a/lib/libc/gen/dladdr.3 b/lib/libc/gen/dladdr.3
new file mode 100644
index 0000000..6566279
--- /dev/null
+++ b/lib/libc/gen/dladdr.3
@@ -0,0 +1,133 @@
+.\"
+.\" Copyright (c) 1998 John D. Polstra
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 5, 1998
+.Dt DLADDR 3
+.Os
+.Sh NAME
+.Nm dladdr
+.Nd find the shared object containing a given address
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In dlfcn.h
+.Ft int
+.Fn dladdr "const void *addr" "Dl_info *info"
+.Sh DESCRIPTION
+The
+.Fn dladdr
+function
+queries the dynamic linker for information about the shared object
+containing the address
+.Fa addr .
+The information is returned in the structure specified by
+.Fa info .
+The structure contains at least the following members:
+.Bl -tag -width "XXXconst char *dli_fname"
+.It Li "const char *dli_fname"
+The pathname of the shared object containing the address.
+.It Li "void *dli_fbase"
+The base address at which the shared object is mapped into the
+address space of the calling process.
+.It Li "const char *dli_sname"
+The name of the nearest run-time symbol with a value less than or
+equal to
+.Fa addr .
+When possible, the symbol name is returned as it would appear in C
+source code.
+.Pp
+If no symbol with a suitable value is found, both this field and
+.Va dli_saddr
+are set to
+.Dv NULL .
+.It Li "void *dli_saddr"
+The value of the symbol returned in
+.Li dli_sname .
+.El
+.Pp
+The
+.Fn dladdr
+function
+is available only in dynamically linked programs.
+.Sh ERRORS
+If a mapped shared object containing
+.Fa addr
+cannot be found,
+.Fn dladdr
+returns 0.
+In that case, a message detailing the failure can be retrieved by
+calling
+.Fn dlerror .
+.Pp
+On success, a non-zero value is returned.
+.Sh SEE ALSO
+.Xr rtld 1 ,
+.Xr dlopen 3
+.Sh HISTORY
+The
+.Fn dladdr
+function first appeared in the Solaris operating system.
+.Sh BUGS
+This implementation is bug-compatible with the Solaris
+implementation.
+In particular, the following bugs are present:
+.Bl -bullet
+.It
+If
+.Fa addr
+lies in the main executable rather than in a shared library, the
+pathname returned in
+.Va dli_fname
+may not be correct.
+The pathname is taken directly from
+.Va argv[0]
+of the calling process.
+When executing a program specified by its
+full pathname, most shells set
+.Va argv[0]
+to the pathname.
+But this is not required of shells or guaranteed
+by the operating system.
+.It
+If
+.Fa addr
+is of the form
+.Va &func ,
+where
+.Va func
+is a global function, its value may be an unpleasant surprise.
+In
+dynamically linked programs, the address of a global function is
+considered to point to its program linkage table entry, rather than to
+the entry point of the function itself.
+This causes most global
+functions to appear to be defined within the main executable, rather
+than in the shared libraries where the actual code resides.
+.It
+Returning 0 as an indication of failure goes against long-standing
+Unix tradition.
+.El
diff --git a/lib/libc/gen/dlfcn.c b/lib/libc/gen/dlfcn.c
new file mode 100644
index 0000000..ad24bb4
--- /dev/null
+++ b/lib/libc/gen/dlfcn.c
@@ -0,0 +1,235 @@
+/*-
+ * Copyright (c) 1998 John D. Polstra
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Linkage to services provided by the dynamic linker.
+ */
+#include <sys/mman.h>
+#include <dlfcn.h>
+#include <link.h>
+#include <stddef.h>
+#include "namespace.h"
+#include <pthread.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+static char sorry[] = "Service unavailable";
+
+/*
+ * For ELF, the dynamic linker directly resolves references to its
+ * services to functions inside the dynamic linker itself. These
+ * weak-symbol stubs are necessary so that "ld" won't complain about
+ * undefined symbols. The stubs are executed only when the program is
+ * linked statically, or when a given service isn't implemented in the
+ * dynamic linker. They must return an error if called, and they must
+ * be weak symbols so that the dynamic linker can override them.
+ */
+
+#pragma weak _rtld_error
+void
+_rtld_error(const char *fmt, ...)
+{
+}
+
+#pragma weak dladdr
+int
+dladdr(const void *addr, Dl_info *dlip)
+{
+ _rtld_error(sorry);
+ return 0;
+}
+
+#pragma weak dlclose
+int
+dlclose(void *handle)
+{
+ _rtld_error(sorry);
+ return -1;
+}
+
+#pragma weak dlerror
+char *
+dlerror(void)
+{
+ return sorry;
+}
+
+#pragma weak dllockinit
+void
+dllockinit(void *context,
+ void *(*lock_create)(void *context),
+ void (*rlock_acquire)(void *lock),
+ void (*wlock_acquire)(void *lock),
+ void (*lock_release)(void *lock),
+ void (*lock_destroy)(void *lock),
+ void (*context_destroy)(void *context))
+{
+ if (context_destroy != NULL)
+ context_destroy(context);
+}
+
+#pragma weak dlopen
+void *
+dlopen(const char *name, int mode)
+{
+ _rtld_error(sorry);
+ return NULL;
+}
+
+#pragma weak dlsym
+void *
+dlsym(void * __restrict handle, const char * __restrict name)
+{
+ _rtld_error(sorry);
+ return NULL;
+}
+
+#pragma weak dlfunc
+dlfunc_t
+dlfunc(void * __restrict handle, const char * __restrict name)
+{
+ _rtld_error(sorry);
+ return NULL;
+}
+
+#pragma weak dlvsym
+void *
+dlvsym(void * __restrict handle, const char * __restrict name,
+ const char * __restrict version)
+{
+ _rtld_error(sorry);
+ return NULL;
+}
+
+#pragma weak dlinfo
+int
+dlinfo(void * __restrict handle, int request, void * __restrict p)
+{
+ _rtld_error(sorry);
+ return 0;
+}
+
+#pragma weak _rtld_thread_init
+void
+_rtld_thread_init(void * li)
+{
+ _rtld_error(sorry);
+}
+
+static pthread_once_t dl_phdr_info_once = PTHREAD_ONCE_INIT;
+static struct dl_phdr_info phdr_info;
+
+static void
+dl_init_phdr_info(void)
+{
+ Elf_Auxinfo *auxp;
+ size_t phent;
+ unsigned int i;
+
+ phent = 0;
+ for (auxp = __elf_aux_vector; auxp->a_type != AT_NULL; auxp++) {
+ switch (auxp->a_type) {
+ case AT_BASE:
+ phdr_info.dlpi_addr = (Elf_Addr)auxp->a_un.a_ptr;
+ break;
+ case AT_EXECPATH:
+ phdr_info.dlpi_name = (const char *)auxp->a_un.a_ptr;
+ break;
+ case AT_PHDR:
+ phdr_info.dlpi_phdr =
+ (const Elf_Phdr *)auxp->a_un.a_ptr;
+ break;
+ case AT_PHENT:
+ phent = auxp->a_un.a_val;
+ break;
+ case AT_PHNUM:
+ phdr_info.dlpi_phnum = (Elf_Half)auxp->a_un.a_val;
+ break;
+ }
+ }
+ for (i = 0; i < phdr_info.dlpi_phnum; i++) {
+ if (phdr_info.dlpi_phdr[i].p_type == PT_TLS) {
+ phdr_info.dlpi_tls_modid = 1;
+ phdr_info.dlpi_tls_data =
+ (void*)phdr_info.dlpi_phdr[i].p_vaddr;
+ }
+ }
+ phdr_info.dlpi_adds = 1;
+}
+
+#pragma weak dl_iterate_phdr
+int
+dl_iterate_phdr(int (*callback)(struct dl_phdr_info *, size_t, void *),
+ void *data)
+{
+
+ __init_elf_aux_vector();
+ if (__elf_aux_vector == NULL)
+ return (1);
+ _once(&dl_phdr_info_once, dl_init_phdr_info);
+ return (callback(&phdr_info, sizeof(phdr_info), data));
+}
+
+#pragma weak fdlopen
+void *
+fdlopen(int fd, int mode)
+{
+
+ _rtld_error(sorry);
+ return NULL;
+}
+
+#pragma weak _rtld_atfork_pre
+void
+_rtld_atfork_pre(int *locks)
+{
+}
+
+#pragma weak _rtld_atfork_post
+void
+_rtld_atfork_post(int *locks)
+{
+}
+
+#pragma weak _rtld_addr_phdr
+int
+_rtld_addr_phdr(const void *addr, struct dl_phdr_info *phdr_info)
+{
+
+ return (0);
+}
+
+#pragma weak _rtld_get_stack_prot
+int
+_rtld_get_stack_prot(void)
+{
+
+ return (PROT_EXEC | PROT_READ | PROT_WRITE);
+}
+
diff --git a/lib/libc/gen/dlinfo.3 b/lib/libc/gen/dlinfo.3
new file mode 100644
index 0000000..d00f074
--- /dev/null
+++ b/lib/libc/gen/dlinfo.3
@@ -0,0 +1,282 @@
+.\"
+.\" Copyright (c) 2003 Alexey Zelkin <phantom@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 14, 2003
+.Dt DLINFO 3
+.Os
+.Sh NAME
+.Nm dlinfo
+.Nd information about dynamically loaded object
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In link.h
+.In dlfcn.h
+.Ft int
+.Fn dlinfo "void * restrict handle" "int request" "void * restrict p"
+.Sh DESCRIPTION
+The
+.Fn dlinfo
+function provides information about dynamically loaded object.
+The action taken by
+.Fn dlinfo
+and exact meaning and type of
+.Fa p
+argument depend on value of the
+.Fa request
+argument provided by caller.
+.Pp
+The
+.Fa handle
+argument is either the value returned from the
+.Xr dlopen 3
+function call or special handle
+.Dv RTLD_SELF .
+If
+.Fa handle
+is the value returned from
+.Xr dlopen 3 ,
+the information returned by the
+.Fn dlinfo
+function pertains to the specified object.
+If handle is the special handle
+.Dv RTLD_SELF ,
+the information returned pertains to the caller itself.
+.Pp
+Possible values for the
+.Fa request
+argument are:
+.Bl -tag -width indent
+.It Dv RTLD_DI_LINKMAP
+Retrieve the
+.Vt Link_map
+.Pq Vt "struct link_map"
+structure pointer for the specified
+.Fa handle .
+On successful return, the
+.Fa p
+argument is filled with the pointer to the
+.Vt Link_map
+structure
+.Pq Fa "Link_map **p"
+describing a shared object specified by the
+.Fa handle
+argument.
+The
+.Vt Link_map
+structures are maintained as a doubly linked list by
+.Xr ld.so 1 ,
+in the same order as
+.Xr dlopen 3
+and
+.Xr dlclose 3
+are called.
+See
+.Sx EXAMPLES ,
+example 1.
+.Pp
+The
+.Vt Link_map
+structure is defined in
+.In link.h
+and has the following members:
+.Bd -literal -offset indent
+caddr_t l_addr; /* Base Address of library */
+const char *l_name; /* Absolute Path to Library */
+const void *l_ld; /* Pointer to .dynamic in memory */
+struct link_map *l_next, /* linked list of mapped libs */
+ *l_prev;
+.Ed
+.Bl -tag -width ".Va l_addr"
+.It Va l_addr
+The base address of the object loaded into memory.
+.It Va l_name
+The full name of the loaded shared object.
+.It Va l_ld
+The address of the dynamic linking information segment
+.Pq Dv PT_DYNAMIC
+loaded into memory.
+.It Va l_next
+The next
+.Vt Link_map
+structure on the link-map list.
+.It Va l_prev
+The previous
+.Vt Link_map
+structure on the link-map list.
+.El
+.It Dv RTLD_DI_SERINFO
+Retrieve the library search paths associated with the given
+.Fa handle
+argument.
+The
+.Fa p
+argument should point to
+.Vt Dl_serinfo
+structure buffer
+.Pq Fa "Dl_serinfo *p" .
+The
+.Vt Dl_serinfo
+structure must be initialized first with the
+.Dv RTLD_DI_SERINFOSIZE
+request.
+.Pp
+The returned
+.Vt Dl_serinfo
+structure contains
+.Va dls_cnt
+.Vt Dl_serpath
+entries.
+Each entry's
+.Va dlp_name
+field points to the search path.
+The corresponding
+.Va dlp_info
+field contains one of more flags indicating the origin of the path (see the
+.Dv LA_SER_*
+flags defined in the
+.In link.h
+header file).
+See
+.Sx EXAMPLES ,
+example 2, for a usage example.
+.It Dv RTLD_DI_SERINFOSIZE
+Initialize a
+.Vt Dl_serinfo
+structure for use in a
+.Dv RTLD_DI_SERINFO
+request.
+Both the
+.Va dls_cnt
+and
+.Va dls_size
+fields are returned to indicate the number of search paths applicable
+to the handle, and the total size of a
+.Vt Dl_serinfo
+buffer required to hold
+.Va dls_cnt
+.Vt Dl_serpath
+entries and the associated search path strings.
+See
+.Sx EXAMPLES ,
+example 2, for a usage example.
+.It Va RTLD_DI_ORIGIN
+Retrieve the origin of the dynamic object associated with the handle.
+On successful return,
+.Fa p
+argument is filled with the
+.Vt char
+pointer
+.Pq Fa "char *p" .
+.El
+.Sh RETURN VALUES
+The
+.Fn dlinfo
+function returns 0 on success, or \-1 if an error occurred.
+Whenever an error has been detected, a message detailing it can
+be retrieved via a call to
+.Xr dlerror 3 .
+.Sh EXAMPLES
+Example 1: Using
+.Fn dlinfo
+to retrieve
+.Vt Link_map
+structure.
+.Pp
+The following example shows how dynamic library can detect the list
+of shared libraries loaded after caller's one.
+For simplicity, error checking has been omitted.
+.Bd -literal -offset indent
+Link_map *map;
+
+dlinfo(RTLD_SELF, RTLD_DI_LINKMAP, &map);
+
+while (map != NULL) {
+ printf("%p: %s\\n", map->l_addr, map->l_name);
+ map = map->l_next;
+}
+.Ed
+.Pp
+Example 2: Using
+.Fn dlinfo
+to retrieve the library search paths.
+.Pp
+The following example shows how a dynamic object can inspect the library
+search paths that would be used to locate a simple filename with
+.Xr dlopen 3 .
+For simplicity, error checking has been omitted.
+.Bd -literal -offset indent
+Dl_serinfo _info, *info = &_info;
+Dl_serpath *path;
+unsigned int cnt;
+
+/* determine search path count and required buffer size */
+dlinfo(RTLD_SELF, RTLD_DI_SERINFOSIZE, (void *)info);
+
+/* allocate new buffer and initialize */
+info = malloc(_info.dls_size);
+info->dls_size = _info.dls_size;
+info->dls_cnt = _info.dls_cnt;
+
+/* obtain sarch path information */
+dlinfo(RTLD_SELF, RTLD_DI_SERINFO, (void *)info);
+
+path = &info->dls_serpath[0];
+
+for (cnt = 1; cnt <= info->dls_cnt; cnt++, path++) {
+ (void) printf("%2d: %s\\n", cnt, path->dls_name);
+}
+.Ed
+.Sh SEE ALSO
+.Xr rtld 1 ,
+.Xr dladdr 3 ,
+.Xr dlopen 3 ,
+.Xr dlsym 3
+.Sh HISTORY
+The
+.Fn dlinfo
+function first appeared in the Solaris operating system.
+In
+.Fx ,
+it first appeared in
+.Fx 4.8 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Fx
+implementation of the
+.Fn dlinfo
+function was originally written by
+.An Alexey Zelkin
+.Aq phantom@FreeBSD.org
+and later extended and improved by
+.An Alexander Kabaev
+.Aq kan@FreeBSD.org .
+.Pp
+The manual page for this function was written by
+.An Alexey Zelkin
+.Aq phantom@FreeBSD.org .
diff --git a/lib/libc/gen/dllockinit.3 b/lib/libc/gen/dllockinit.3
new file mode 100644
index 0000000..be3e2ca
--- /dev/null
+++ b/lib/libc/gen/dllockinit.3
@@ -0,0 +1,127 @@
+.\"
+.\" Copyright (c) 1999, 2000 John D. Polstra
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 5, 2000
+.Dt DLLOCKINIT 3
+.Os
+.Sh NAME
+.Nm dllockinit
+.Nd register thread locking methods with the dynamic linker
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In dlfcn.h
+.Ft void
+.Fn dllockinit "void *context" "void *(*lock_create)(void *context)" "void (*rlock_acquire)(void *lock)" "void (*wlock_acquire)(void *lock)" "void (*lock_release)(void *lock)" "void (*lock_destroy)(void *lock)" "void (*context_destroy)(void *context)"
+.Sh DESCRIPTION
+.Bf Sy
+Due to enhancements in the dynamic linker, this interface is no longer
+needed.
+It is deprecated and will be removed from future releases.
+In current releases it still exists, but only as a stub which does nothing.
+.Ef
+.Pp
+Threads packages can call
+.Fn dllockinit
+at initialization time to register locking functions for the dynamic
+linker to use.
+This enables the dynamic linker to prevent multiple
+threads from entering its critical sections simultaneously.
+.Pp
+The
+.Fa context
+argument specifies an opaque context for creating locks.
+The
+dynamic linker will pass it to the
+.Fa lock_create
+function when creating the locks it needs.
+When the dynamic linker
+is permanently finished using the locking functions (e.g., if the
+program makes a subsequent call to
+.Fn dllockinit
+to register new locking functions) it will call
+.Fa context_destroy
+to destroy the context.
+.Pp
+The
+.Fa lock_create
+argument specifies a function for creating a read/write lock.
+It
+must return a pointer to the new lock.
+.Pp
+The
+.Fa rlock_acquire
+and
+.Fa wlock_acquire
+arguments specify functions which lock a lock for reading or
+writing, respectively.
+The
+.Fa lock_release
+argument specifies a function which unlocks a lock.
+Each of these
+functions is passed a pointer to the lock.
+.Pp
+The
+.Fa lock_destroy
+argument specifies a function to destroy a lock.
+It may be
+.Dv NULL
+if locks do not need to be destroyed.
+The
+.Fa context_destroy
+argument specifies a function to destroy the context.
+It may be
+.Dv NULL
+if the context does not need to be destroyed.
+.Pp
+Until
+.Fn dllockinit
+is called, the dynamic linker protects its critical sections using
+a default locking mechanism which works by blocking the
+.Dv SIGVTALRM ,
+.Dv SIGPROF ,
+and
+.Dv SIGALRM
+signals.
+This is sufficient for many application level threads
+packages, which typically use one of these signals to implement
+preemption.
+An application which has registered its own locking
+methods with
+.Fn dllockinit
+can restore the default locking by calling
+.Fn dllockinit
+with all arguments
+.Dv NULL .
+.Sh SEE ALSO
+.Xr rtld 1 ,
+.Xr signal 3
+.Sh HISTORY
+The
+.Fn dllockinit
+function first appeared in
+.Fx 4.0 .
diff --git a/lib/libc/gen/dlopen.3 b/lib/libc/gen/dlopen.3
new file mode 100644
index 0000000..089e631
--- /dev/null
+++ b/lib/libc/gen/dlopen.3
@@ -0,0 +1,408 @@
+.\" This source code is a product of Sun Microsystems, Inc. and is provided
+.\" for unrestricted use provided that this legend is included on all tape
+.\" media and as a part of the software program in whole or part. Users
+.\" may copy or modify this source code without charge, but are not authorized
+.\" to license or distribute it to anyone else except as part of a product or
+.\" program developed by the user.
+.\"
+.\" THIS PROGRAM CONTAINS SOURCE CODE COPYRIGHTED BY SUN MICROSYSTEMS, INC.
+.\" SUN MICROSYSTEMS, INC., MAKES NO REPRESENTATIONS ABOUT THE SUITABLITY
+.\" OF SUCH SOURCE CODE FOR ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT
+.\" EXPRESS OR IMPLIED WARRANTY OF ANY KIND. SUN MICROSYSTEMS, INC. DISCLAIMS
+.\" ALL WARRANTIES WITH REGARD TO SUCH SOURCE CODE, INCLUDING ALL IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN
+.\" NO EVENT SHALL SUN MICROSYSTEMS, INC. BE LIABLE FOR ANY SPECIAL, INDIRECT,
+.\" INCIDENTAL, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
+.\" FROM USE OF SUCH SOURCE CODE, REGARDLESS OF THE THEORY OF LIABILITY.
+.\"
+.\" This source code is provided with no support and without any obligation on
+.\" the part of Sun Microsystems, Inc. to assist in its use, correction,
+.\" modification or enhancement.
+.\"
+.\" SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+.\" INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS
+.\" SOURCE CODE OR ANY PART THEREOF.
+.\"
+.\" Sun Microsystems, Inc.
+.\" 2550 Garcia Avenue
+.\" Mountain View, California 94043
+.\"
+.\" Copyright (c) 1991 Sun Microsystems, Inc.
+.\"
+.\" @(#) dlopen.3 1.6 90/01/31 SMI
+.\" $FreeBSD$
+.\"
+.Dd December 21, 2011
+.Dt DLOPEN 3
+.Os
+.Sh NAME
+.Nm dlopen ,
+.Nm fdlopen ,
+.Nm dlsym ,
+.Nm dlfunc ,
+.Nm dlerror ,
+.Nm dlclose
+.Nd programmatic interface to the dynamic linker
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In dlfcn.h
+.Ft void *
+.Fn dlopen "const char *path" "int mode"
+.Ft void *
+.Fn fdlopen "int fd" "int mode"
+.Ft void *
+.Fn dlsym "void * restrict handle" "const char * restrict symbol"
+.Ft dlfunc_t
+.Fn dlfunc "void * restrict handle" "const char * restrict symbol"
+.Ft char *
+.Fn dlerror "void"
+.Ft int
+.Fn dlclose "void *handle"
+.Sh DESCRIPTION
+These functions provide a simple programmatic interface to the services of the
+dynamic linker.
+Operations are provided to add new shared objects to a
+program's address space, to obtain the address bindings of symbols
+defined by such
+objects, and to remove such objects when their use is no longer required.
+.Pp
+The
+.Fn dlopen
+function
+provides access to the shared object in
+.Fa path ,
+returning a descriptor that can be used for later
+references to the object in calls to
+.Fn dlsym
+and
+.Fn dlclose .
+If
+.Fa path
+was not in the address space prior to the call to
+.Fn dlopen ,
+it is placed in the address space.
+When an object is first loaded into the address space in this way, its
+function
+.Fn _init ,
+if any, is called by the dynamic linker.
+If
+.Fa path
+has already been placed in the address space in a previous call to
+.Fn dlopen ,
+it is not added a second time, although a reference count of
+.Fn dlopen
+operations on
+.Fa path
+is maintained.
+A null pointer supplied for
+.Fa path
+is interpreted as a reference to the main
+executable of the process.
+The
+.Fa mode
+argument
+controls the way in which external function references from the
+loaded object are bound to their referents.
+It must contain one of the following values, possibly ORed with
+additional flags which will be described subsequently:
+.Bl -tag -width RTLD_LAZYX
+.It Dv RTLD_LAZY
+Each external function reference is resolved when the function is first
+called.
+.It Dv RTLD_NOW
+All external function references are bound immediately by
+.Fn dlopen .
+.El
+.Pp
+.Dv RTLD_LAZY
+is normally preferred, for reasons of efficiency.
+However,
+.Dv RTLD_NOW
+is useful to ensure that any undefined symbols are discovered during the
+call to
+.Fn dlopen .
+.Pp
+One of the following flags may be ORed into the
+.Fa mode
+argument:
+.Bl -tag -width RTLD_NODELETE
+.It Dv RTLD_GLOBAL
+Symbols from this shared object and its directed acyclic graph (DAG)
+of needed objects will be available for resolving undefined references
+from all other shared objects.
+.It Dv RTLD_LOCAL
+Symbols in this shared object and its DAG of needed objects will be
+available for resolving undefined references only from other objects
+in the same DAG.
+This is the default, but it may be specified
+explicitly with this flag.
+.It Dv RTLD_TRACE
+When set, causes dynamic linker to exit after loading all objects
+needed by this shared object and printing a summary which includes
+the absolute pathnames of all objects, to standard output.
+With this flag
+.Fn dlopen
+will return to the caller only in the case of error.
+.It Dv RTLD_NODELETE
+Prevents unload of the loaded object on
+.Fn dlclose .
+The same behaviour may be requested by
+.Fl "z nodelete"
+option of the static linker
+.Xr ld 1 .
+.It Dv RTLD_NOLOAD
+Only return valid handle for the object if it is already loaded in
+the process address space, otherwise
+.Dv NULL
+is returned.
+Other mode flags may be specified, which will be applied for promotion
+for the found object.
+.El
+.Pp
+If
+.Fn dlopen
+fails, it returns a null pointer, and sets an error condition which may
+be interrogated with
+.Fn dlerror .
+.Pp
+The
+.Fn fdlopen
+function is similar to
+.Fn dlopen ,
+but it takes the file descriptor argument
+.Fa fd ,
+which is used for the file operations needed to load an object
+into the address space.
+The file descriptor
+.Fa fd
+is not closed by the function regardless a result of execution,
+but a duplicate of the file descriptor is.
+This may be important if a
+.Xr lockf 3
+lock is held on the passed descriptor.
+The
+.Fa fd
+argument -1 is interpreted as a reference to the main
+executable of the process, similar to
+.Va NULL
+value for the
+.Fa name
+argument to
+.Fn dlopen .
+The
+.Fn fdlopen
+function can be used by the code that needs to perform
+additional checks on the loaded objects, to prevent races with
+symlinking or renames.
+.Pp
+The
+.Fn dlsym
+function
+returns the address binding of the symbol described in the null-terminated
+character string
+.Fa symbol ,
+as it occurs in the shared object identified by
+.Fa handle .
+The symbols exported by objects added to the address space by
+.Fn dlopen
+can be accessed only through calls to
+.Fn dlsym .
+Such symbols do not supersede any definition of those symbols already present
+in the address space when the object is loaded, nor are they available to
+satisfy normal dynamic linking references.
+.Pp
+If
+.Fn dlsym
+is called with the special
+.Fa handle
+.Dv NULL ,
+it is interpreted as a reference to the executable or shared object
+from which the call
+is being made.
+Thus a shared object can reference its own symbols.
+.Pp
+If
+.Fn dlsym
+is called with the special
+.Fa handle
+.Dv RTLD_DEFAULT ,
+the search for the symbol follows the algorithm used for resolving
+undefined symbols when objects are loaded.
+The objects searched are
+as follows, in the given order:
+.Bl -enum
+.It
+The referencing object itself (or the object from which the call to
+.Fn dlsym
+is made), if that object was linked using the
+.Fl Wsymbolic
+option to
+.Xr ld 1 .
+.It
+All objects loaded at program start-up.
+.It
+All objects loaded via
+.Fn dlopen
+with the
+.Dv RTLD_GLOBAL
+flag set in the
+.Fa mode
+argument.
+.It
+All objects loaded via
+.Fn dlopen
+which are in needed-object DAGs that also contain the referencing object.
+.El
+.Pp
+If
+.Fn dlsym
+is called with the special
+.Fa handle
+.Dv RTLD_NEXT ,
+then the search for the symbol is limited to the shared objects
+which were loaded after the one issuing the call to
+.Fn dlsym .
+Thus, if the function is called from the main program, all
+the shared libraries are searched.
+If it is called from a shared library, all subsequent shared
+libraries are searched.
+.Dv RTLD_NEXT
+is useful for implementing wrappers around library functions.
+For example, a wrapper function
+.Fn getpid
+could access the
+.Dq real
+.Fn getpid
+with
+.Li dlsym(RTLD_NEXT, \&"getpid\&") .
+(Actually, the
+.Fn dlfunc
+interface, below, should be used, since
+.Fn getpid
+is a function and not a data object.)
+.Pp
+If
+.Fn dlsym
+is called with the special
+.Fa handle
+.Dv RTLD_SELF ,
+then the search for the symbol is limited to the shared object
+issuing the call to
+.Fn dlsym
+and those shared objects which were loaded after it.
+.Pp
+The
+.Fn dlsym
+function
+returns a null pointer if the symbol cannot be found, and sets an error
+condition which may be queried with
+.Fn dlerror .
+.Pp
+The
+.Fn dlfunc
+function
+implements all of the behavior of
+.Fn dlsym ,
+but has a return type which can be cast to a function pointer without
+triggering compiler diagnostics.
+(The
+.Fn dlsym
+function
+returns a data pointer; in the C standard, conversions between
+data and function pointer types are undefined.
+Some compilers and
+.Xr lint 1
+utilities warn about such casts.)
+The precise return type of
+.Fn dlfunc
+is unspecified; applications must cast it to an appropriate function pointer
+type.
+.Pp
+The
+.Fn dlerror
+function
+returns a null-terminated character string describing the last error that
+occurred during a call to
+.Fn dlopen ,
+.Fn dladdr ,
+.Fn dlinfo ,
+.Fn dlsym ,
+.Fn dlfunc ,
+or
+.Fn dlclose .
+If no such error has occurred,
+.Fn dlerror
+returns a null pointer.
+At each call to
+.Fn dlerror ,
+the error indication is reset.
+Thus in the case of two calls
+to
+.Fn dlerror ,
+where the second call follows the first immediately, the second call
+will always return a null pointer.
+.Pp
+The
+.Fn dlclose
+function
+deletes a reference to the shared object referenced by
+.Fa handle .
+If the reference count drops to 0, the object is removed from the
+address space, and
+.Fa handle
+is rendered invalid.
+Just before removing a shared object in this way, the dynamic linker
+calls the object's
+.Fn _fini
+function, if such a function is defined by the object.
+If
+.Fn dlclose
+is successful, it returns a value of 0.
+Otherwise it returns -1, and sets an error condition that can be
+interrogated with
+.Fn dlerror .
+.Pp
+The object-intrinsic functions
+.Fn _init
+and
+.Fn _fini
+are called with no arguments, and are not expected to return values.
+.Sh NOTES
+ELF executables need to be linked
+using the
+.Fl export-dynamic
+option to
+.Xr ld 1
+for symbols defined in the executable to become visible to
+.Fn dlsym .
+.Pp
+In previous implementations, it was necessary to prepend an underscore
+to all external symbols in order to gain symbol
+compatibility with object code compiled from the C language.
+This is
+still the case when using the (obsolete)
+.Fl aout
+option to the C language compiler.
+.Sh ERRORS
+The
+.Fn dlopen ,
+.Fn fdlopen ,
+.Fn dlsym ,
+and
+.Fn dlfunc
+functions
+return a null pointer in the event of errors.
+The
+.Fn dlclose
+function
+returns 0 on success, or -1 if an error occurred.
+Whenever an error has been detected, a message detailing it can be
+retrieved via a call to
+.Fn dlerror .
+.Sh SEE ALSO
+.Xr ld 1 ,
+.Xr rtld 1 ,
+.Xr dladdr 3 ,
+.Xr dlinfo 3 ,
+.Xr link 5
diff --git a/lib/libc/gen/drand48.c b/lib/libc/gen/drand48.c
new file mode 100644
index 0000000..672b5ee
--- /dev/null
+++ b/lib/libc/gen/drand48.c
@@ -0,0 +1,25 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "rand48.h"
+
+extern unsigned short _rand48_seed[3];
+
+double
+drand48(void)
+{
+ return erand48(_rand48_seed);
+}
diff --git a/lib/libc/gen/elf_utils.c b/lib/libc/gen/elf_utils.c
new file mode 100644
index 0000000..7bd7511
--- /dev/null
+++ b/lib/libc/gen/elf_utils.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 2010 Konstantin Belousov <kib@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
+#include <link.h>
+#include <stddef.h>
+
+int
+__elf_phdr_match_addr(struct dl_phdr_info *phdr_info, void *addr)
+{
+ const Elf_Phdr *ph;
+ int i;
+
+ for (i = 0; i < phdr_info->dlpi_phnum; i++) {
+ ph = &phdr_info->dlpi_phdr[i];
+ if (ph->p_type != PT_LOAD || (ph->p_flags & PF_X) == 0)
+ continue;
+ if (phdr_info->dlpi_addr + ph->p_vaddr <= (uintptr_t)addr &&
+ (uintptr_t)addr + sizeof(addr) < phdr_info->dlpi_addr +
+ ph->p_vaddr + ph->p_memsz)
+ break;
+ }
+ return (i != phdr_info->dlpi_phnum);
+}
+
+#pragma weak __pthread_map_stacks_exec
+void
+__pthread_map_stacks_exec(void)
+{
+ int mib[2];
+ struct rlimit rlim;
+ u_long usrstack;
+ size_t len;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_USRSTACK;
+ len = sizeof(usrstack);
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), &usrstack, &len, NULL, 0)
+ == -1)
+ return;
+ if (getrlimit(RLIMIT_STACK, &rlim) == -1)
+ return;
+ mprotect((void *)(uintptr_t)(usrstack - rlim.rlim_cur),
+ rlim.rlim_cur, _rtld_get_stack_prot());
+}
+
diff --git a/lib/libc/gen/erand48.c b/lib/libc/gen/erand48.c
new file mode 100644
index 0000000..cdb3ec8
--- /dev/null
+++ b/lib/libc/gen/erand48.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "rand48.h"
+
+double
+erand48(unsigned short xseed[3])
+{
+ _dorand48(xseed);
+ return ldexp((double) xseed[0], -48) +
+ ldexp((double) xseed[1], -32) +
+ ldexp((double) xseed[2], -16);
+}
diff --git a/lib/libc/gen/err.3 b/lib/libc/gen/err.3
new file mode 100644
index 0000000..f9fcdaf
--- /dev/null
+++ b/lib/libc/gen/err.3
@@ -0,0 +1,243 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)err.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd March 29, 2012
+.Dt ERR 3
+.Os
+.Sh NAME
+.Nm err ,
+.Nm verr ,
+.Nm errc ,
+.Nm verrc ,
+.Nm errx ,
+.Nm verrx ,
+.Nm warn ,
+.Nm vwarn ,
+.Nm warnc ,
+.Nm vwarnc ,
+.Nm warnx ,
+.Nm vwarnx ,
+.Nm err_set_exit ,
+.Nm err_set_file
+.Nd formatted error messages
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In err.h
+.Ft void
+.Fn err "int eval" "const char *fmt" "..."
+.Ft void
+.Fn err_set_exit "void (*exitf)(int)"
+.Ft void
+.Fn err_set_file "void *vfp"
+.Ft void
+.Fn errc "int eval" "int code" "const char *fmt" "..."
+.Ft void
+.Fn errx "int eval" "const char *fmt" "..."
+.Ft void
+.Fn warn "const char *fmt" "..."
+.Ft void
+.Fn warnc "int code" "const char *fmt" "..."
+.Ft void
+.Fn warnx "const char *fmt" "..."
+.In stdarg.h
+.Ft void
+.Fn verr "int eval" "const char *fmt" "va_list args"
+.Ft void
+.Fn verrc "int eval" "int code" "const char *fmt" "va_list args"
+.Ft void
+.Fn verrx "int eval" "const char *fmt" "va_list args"
+.Ft void
+.Fn vwarn "const char *fmt" "va_list args"
+.Ft void
+.Fn vwarnc "int code" "const char *fmt" "va_list args"
+.Ft void
+.Fn vwarnx "const char *fmt" "va_list args"
+.Sh DESCRIPTION
+The
+.Fn err
+and
+.Fn warn
+family of functions display a formatted error message on the standard
+error output, or on another file specified using the
+.Fn err_set_file
+function.
+In all cases, the last component of the program name, a colon character,
+and a space are output.
+If the
+.Fa fmt
+argument is not NULL, the
+.Xr printf 3 Ns
+-like formatted error message is output.
+The output is terminated by a newline character.
+.Pp
+The
+.Fn err ,
+.Fn errc ,
+.Fn verr ,
+.Fn verrc ,
+.Fn warn ,
+.Fn warnc ,
+.Fn vwarn ,
+and
+.Fn vwarnc
+functions append an error message obtained from
+.Xr strerror 3
+based on a supplied error code value or the global variable
+.Va errno ,
+preceded by another colon and space unless the
+.Fa fmt
+argument is
+.Dv NULL .
+.Pp
+In the case of the
+.Fn errc ,
+.Fn verrc ,
+.Fn warnc ,
+and
+.Fn vwarnc
+functions,
+the
+.Fa code
+argument is used to look up the error message.
+.Pp
+The
+.Fn err ,
+.Fn verr ,
+.Fn warn ,
+and
+.Fn vwarn
+functions use the global variable
+.Va errno
+to look up the error message.
+.Pp
+The
+.Fn errx
+and
+.Fn warnx
+functions do not append an error message.
+.Pp
+The
+.Fn err ,
+.Fn verr ,
+.Fn errc ,
+.Fn verrc ,
+.Fn errx ,
+and
+.Fn verrx
+functions do not return, but exit with the value of the argument
+.Fa eval .
+It is recommended that the standard values defined in
+.Xr sysexits 3
+be used for the value of
+.Fa eval .
+The
+.Fn err_set_exit
+function can be used to specify a function which is called before
+.Xr exit 3
+to perform any necessary cleanup; passing a null function pointer for
+.Va exitf
+resets the hook to do nothing.
+The
+.Fn err_set_file
+function sets the output stream used by the other functions.
+Its
+.Fa vfp
+argument must be either a pointer to an open stream
+(possibly already converted to void *)
+or a null pointer
+(in which case the output stream is set to standard error).
+.Sh EXAMPLES
+Display the current errno information string and exit:
+.Bd -literal -offset indent
+if ((p = malloc(size)) == NULL)
+ err(EX_OSERR, NULL);
+if ((fd = open(file_name, O_RDONLY, 0)) == -1)
+ err(EX_NOINPUT, "%s", file_name);
+.Ed
+.Pp
+Display an error message and exit:
+.Bd -literal -offset indent
+if (tm.tm_hour < START_TIME)
+ errx(EX_DATAERR, "too early, wait until %s",
+ start_time_string);
+.Ed
+.Pp
+Warn of an error:
+.Bd -literal -offset indent
+if ((fd = open(raw_device, O_RDONLY, 0)) == -1)
+ warnx("%s: %s: trying the block device",
+ raw_device, strerror(errno));
+if ((fd = open(block_device, O_RDONLY, 0)) == -1)
+ err(EX_OSFILE, "%s", block_device);
+.Ed
+.Pp
+Warn of an error without using the global variable
+.Va errno :
+.Bd -literal -offset indent
+error = my_function(); /* returns a value from <errno.h> */
+if (error != 0)
+ warnc(error, "my_function");
+.Ed
+.Sh SEE ALSO
+.Xr exit 3 ,
+.Xr fmtmsg 3 ,
+.Xr printf 3 ,
+.Xr strerror 3 ,
+.Xr sysexits 3
+.Sh STANDARDS
+The
+.Fn err
+and
+.Fn warn
+families of functions are BSD extensions.
+As such they should not be used in truly portable code.
+Use
+.Fn strerror
+or similar functions instead.
+.Sh HISTORY
+The
+.Fn err
+and
+.Fn warn
+functions first appeared in
+.Bx 4.4 .
+The
+.Fn err_set_exit
+and
+.Fn err_set_file
+functions first appeared in
+.Fx 2.1 .
+The
+.Fn errc
+and
+.Fn warnc
+functions first appeared in
+.Fx 3.0 .
diff --git a/lib/libc/gen/err.c b/lib/libc/gen/err.c
new file mode 100644
index 0000000..0ba584c
--- /dev/null
+++ b/lib/libc/gen/err.c
@@ -0,0 +1,195 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)err.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <err.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+static FILE *err_file; /* file to use for error output */
+static void (*err_exit)(int);
+
+/*
+ * This is declared to take a `void *' so that the caller is not required
+ * to include <stdio.h> first. However, it is really a `FILE *', and the
+ * manual page documents it as such.
+ */
+void
+err_set_file(void *fp)
+{
+ if (fp)
+ err_file = fp;
+ else
+ err_file = stderr;
+}
+
+void
+err_set_exit(void (*ef)(int))
+{
+ err_exit = ef;
+}
+
+__weak_reference(_err, err);
+
+void
+_err(int eval, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrc(eval, errno, fmt, ap);
+ va_end(ap);
+}
+
+void
+verr(eval, fmt, ap)
+ int eval;
+ const char *fmt;
+ va_list ap;
+{
+ verrc(eval, errno, fmt, ap);
+}
+
+void
+errc(int eval, int code, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrc(eval, code, fmt, ap);
+ va_end(ap);
+}
+
+void
+verrc(int eval, int code, const char *fmt, va_list ap)
+{
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", _getprogname());
+ if (fmt != NULL) {
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, ": ");
+ }
+ fprintf(err_file, "%s\n", strerror(code));
+ if (err_exit)
+ err_exit(eval);
+ exit(eval);
+}
+
+void
+errx(int eval, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ verrx(eval, fmt, ap);
+ va_end(ap);
+}
+
+void
+verrx(int eval, const char *fmt, va_list ap)
+{
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", _getprogname());
+ if (fmt != NULL)
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, "\n");
+ if (err_exit)
+ err_exit(eval);
+ exit(eval);
+}
+
+__weak_reference(_warn, warn);
+
+void
+_warn(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnc(errno, fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarn(const char *fmt, va_list ap)
+{
+ vwarnc(errno, fmt, ap);
+}
+
+void
+warnc(int code, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnc(code, fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarnc(int code, const char *fmt, va_list ap)
+{
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", _getprogname());
+ if (fmt != NULL) {
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, ": ");
+ }
+ fprintf(err_file, "%s\n", strerror(code));
+}
+
+void
+warnx(const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ vwarnx(fmt, ap);
+ va_end(ap);
+}
+
+void
+vwarnx(const char *fmt, va_list ap)
+{
+ if (err_file == 0)
+ err_set_file((FILE *)0);
+ fprintf(err_file, "%s: ", _getprogname());
+ if (fmt != NULL)
+ vfprintf(err_file, fmt, ap);
+ fprintf(err_file, "\n");
+}
diff --git a/lib/libc/gen/errlst.c b/lib/libc/gen/errlst.c
new file mode 100644
index 0000000..d817823
--- /dev/null
+++ b/lib/libc/gen/errlst.c
@@ -0,0 +1,156 @@
+/*
+ * Copyright (c) 1982, 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)errlst.c 8.2 (Berkeley) 11/16/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+
+const char *const sys_errlist[] = {
+ "No error: 0", /* 0 - ENOERROR */
+ "Operation not permitted", /* 1 - EPERM */
+ "No such file or directory", /* 2 - ENOENT */
+ "No such process", /* 3 - ESRCH */
+ "Interrupted system call", /* 4 - EINTR */
+ "Input/output error", /* 5 - EIO */
+ "Device not configured", /* 6 - ENXIO */
+ "Argument list too long", /* 7 - E2BIG */
+ "Exec format error", /* 8 - ENOEXEC */
+ "Bad file descriptor", /* 9 - EBADF */
+ "No child processes", /* 10 - ECHILD */
+ "Resource deadlock avoided", /* 11 - EDEADLK */
+ "Cannot allocate memory", /* 12 - ENOMEM */
+ "Permission denied", /* 13 - EACCES */
+ "Bad address", /* 14 - EFAULT */
+ "Block device required", /* 15 - ENOTBLK */
+ "Device busy", /* 16 - EBUSY */
+ "File exists", /* 17 - EEXIST */
+ "Cross-device link", /* 18 - EXDEV */
+ "Operation not supported by device", /* 19 - ENODEV */
+ "Not a directory", /* 20 - ENOTDIR */
+ "Is a directory", /* 21 - EISDIR */
+ "Invalid argument", /* 22 - EINVAL */
+ "Too many open files in system", /* 23 - ENFILE */
+ "Too many open files", /* 24 - EMFILE */
+ "Inappropriate ioctl for device", /* 25 - ENOTTY */
+ "Text file busy", /* 26 - ETXTBSY */
+ "File too large", /* 27 - EFBIG */
+ "No space left on device", /* 28 - ENOSPC */
+ "Illegal seek", /* 29 - ESPIPE */
+ "Read-only file system", /* 30 - EROFS */
+ "Too many links", /* 31 - EMLINK */
+ "Broken pipe", /* 32 - EPIPE */
+
+/* math software */
+ "Numerical argument out of domain", /* 33 - EDOM */
+ "Result too large", /* 34 - ERANGE */
+
+/* non-blocking and interrupt i/o */
+ "Resource temporarily unavailable", /* 35 - EAGAIN */
+ /* 35 - EWOULDBLOCK */
+ "Operation now in progress", /* 36 - EINPROGRESS */
+ "Operation already in progress", /* 37 - EALREADY */
+
+/* ipc/network software -- argument errors */
+ "Socket operation on non-socket", /* 38 - ENOTSOCK */
+ "Destination address required", /* 39 - EDESTADDRREQ */
+ "Message too long", /* 40 - EMSGSIZE */
+ "Protocol wrong type for socket", /* 41 - EPROTOTYPE */
+ "Protocol not available", /* 42 - ENOPROTOOPT */
+ "Protocol not supported", /* 43 - EPROTONOSUPPORT */
+ "Socket type not supported", /* 44 - ESOCKTNOSUPPORT */
+ "Operation not supported", /* 45 - EOPNOTSUPP */
+ "Protocol family not supported", /* 46 - EPFNOSUPPORT */
+ /* 47 - EAFNOSUPPORT */
+ "Address family not supported by protocol family",
+ "Address already in use", /* 48 - EADDRINUSE */
+ "Can't assign requested address", /* 49 - EADDRNOTAVAIL */
+
+/* ipc/network software -- operational errors */
+ "Network is down", /* 50 - ENETDOWN */
+ "Network is unreachable", /* 51 - ENETUNREACH */
+ "Network dropped connection on reset", /* 52 - ENETRESET */
+ "Software caused connection abort", /* 53 - ECONNABORTED */
+ "Connection reset by peer", /* 54 - ECONNRESET */
+ "No buffer space available", /* 55 - ENOBUFS */
+ "Socket is already connected", /* 56 - EISCONN */
+ "Socket is not connected", /* 57 - ENOTCONN */
+ "Can't send after socket shutdown", /* 58 - ESHUTDOWN */
+ "Too many references: can't splice", /* 59 - ETOOMANYREFS */
+ "Operation timed out", /* 60 - ETIMEDOUT */
+ "Connection refused", /* 61 - ECONNREFUSED */
+
+ "Too many levels of symbolic links", /* 62 - ELOOP */
+ "File name too long", /* 63 - ENAMETOOLONG */
+
+/* should be rearranged */
+ "Host is down", /* 64 - EHOSTDOWN */
+ "No route to host", /* 65 - EHOSTUNREACH */
+ "Directory not empty", /* 66 - ENOTEMPTY */
+
+/* quotas & mush */
+ "Too many processes", /* 67 - EPROCLIM */
+ "Too many users", /* 68 - EUSERS */
+ "Disc quota exceeded", /* 69 - EDQUOT */
+
+/* Network File System */
+ "Stale NFS file handle", /* 70 - ESTALE */
+ "Too many levels of remote in path", /* 71 - EREMOTE */
+ "RPC struct is bad", /* 72 - EBADRPC */
+ "RPC version wrong", /* 73 - ERPCMISMATCH */
+ "RPC prog. not avail", /* 74 - EPROGUNAVAIL */
+ "Program version wrong", /* 75 - EPROGMISMATCH */
+ "Bad procedure for program", /* 76 - EPROCUNAVAIL */
+
+ "No locks available", /* 77 - ENOLCK */
+ "Function not implemented", /* 78 - ENOSYS */
+ "Inappropriate file type or format", /* 79 - EFTYPE */
+ "Authentication error", /* 80 - EAUTH */
+ "Need authenticator", /* 81 - ENEEDAUTH */
+ "Identifier removed", /* 82 - EIDRM */
+ "No message of desired type", /* 83 - ENOMSG */
+ "Value too large to be stored in data type", /* 84 - EOVERFLOW */
+ "Operation canceled", /* 85 - ECANCELED */
+ "Illegal byte sequence", /* 86 - EILSEQ */
+ "Attribute not found", /* 87 - ENOATTR */
+
+/* General */
+ "Programming error", /* 88 - EDOOFUS */
+
+ "Bad message", /* 89 - EBADMSG */
+ "Multihop attempted", /* 90 - EMULTIHOP */
+ "Link has been severed", /* 91 - ENOLINK */
+ "Protocol error", /* 92 - EPROTO */
+ "Capabilities insufficient", /* 93 - ENOTCAPABLE */
+ "Not permitted in capability mode", /* 94 - ECAPMODE */
+};
+const int sys_nerr = sizeof(sys_errlist) / sizeof(sys_errlist[0]);
diff --git a/lib/libc/gen/errno.c b/lib/libc/gen/errno.c
new file mode 100644
index 0000000..02e0351
--- /dev/null
+++ b/lib/libc/gen/errno.c
@@ -0,0 +1,30 @@
+/*-
+ * Copyright (c) 2002 Peter Wemm <peter@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+int errno;
diff --git a/lib/libc/gen/exec.3 b/lib/libc/gen/exec.3
new file mode 100644
index 0000000..daeccd1
--- /dev/null
+++ b/lib/libc/gen/exec.3
@@ -0,0 +1,321 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)exec.3 8.3 (Berkeley) 1/24/94
+.\" $FreeBSD$
+.\"
+.Dd January 24, 1994
+.Dt EXEC 3
+.Os
+.Sh NAME
+.Nm execl ,
+.Nm execlp ,
+.Nm execle ,
+.Nm exect ,
+.Nm execv ,
+.Nm execvp ,
+.Nm execvP
+.Nd execute a file
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Vt extern char **environ ;
+.Ft int
+.Fn execl "const char *path" "const char *arg" ... /* "(char *)0" */
+.Ft int
+.Fn execlp "const char *file" "const char *arg" ... /* "(char *)0" */
+.Ft int
+.Fo execle
+.Fa "const char *path" "const char *arg" ...
+.Fa /*
+.Bk -words
+.Fa "(char *)0" "char *const envp[]" */
+.Ek
+.Fc
+.Ft int
+.Fn exect "const char *path" "char *const argv[]" "char *const envp[]"
+.Ft int
+.Fn execv "const char *path" "char *const argv[]"
+.Ft int
+.Fn execvp "const char *file" "char *const argv[]"
+.Ft int
+.Fn execvP "const char *file" "const char *search_path" "char *const argv[]"
+.Sh DESCRIPTION
+The
+.Nm exec
+family of functions replaces the current process image with a
+new process image.
+The functions described in this manual page are front-ends for the function
+.Xr execve 2 .
+(See the manual page for
+.Xr execve 2
+for detailed information about the replacement of the current process.)
+.Pp
+The initial argument for these functions is the pathname of a file which
+is to be executed.
+.Pp
+The
+.Fa "const char *arg"
+and subsequent ellipses in the
+.Fn execl ,
+.Fn execlp ,
+and
+.Fn execle
+functions can be thought of as
+.Em arg0 ,
+.Em arg1 ,
+\&...,
+.Em argn .
+Together they describe a list of one or more pointers to null-terminated
+strings that represent the argument list available to the executed program.
+The first argument, by convention, should point to the file name associated
+with the file being executed.
+The list of arguments
+.Em must
+be terminated by a
+.Dv NULL
+pointer.
+.Pp
+The
+.Fn exect ,
+.Fn execv ,
+.Fn execvp ,
+and
+.Fn execvP
+functions provide an array of pointers to null-terminated strings that
+represent the argument list available to the new program.
+The first argument, by convention, should point to the file name associated
+with the file being executed.
+The array of pointers
+.Sy must
+be terminated by a
+.Dv NULL
+pointer.
+.Pp
+The
+.Fn execle
+and
+.Fn exect
+functions also specify the environment of the executed process by following
+the
+.Dv NULL
+pointer that terminates the list of arguments in the argument list
+or the pointer to the argv array with an additional argument.
+This additional argument is an array of pointers to null-terminated strings
+and
+.Em must
+be terminated by a
+.Dv NULL
+pointer.
+The other functions take the environment for the new process image from the
+external variable
+.Va environ
+in the current process.
+.Pp
+Some of these functions have special semantics.
+.Pp
+The functions
+.Fn execlp ,
+.Fn execvp ,
+and
+.Fn execvP
+will duplicate the actions of the shell in searching for an executable file
+if the specified file name does not contain a slash
+.Dq Li /
+character.
+For
+.Fn execlp
+and
+.Fn execvp ,
+search path is the path specified in the environment by
+.Dq Ev PATH
+variable.
+If this variable is not specified,
+the default path is set according to the
+.Dv _PATH_DEFPATH
+definition in
+.In paths.h ,
+which is set to
+.Dq Ev /usr/bin:/bin .
+For
+.Fn execvP ,
+the search path is specified as an argument to the function.
+In addition, certain errors are treated specially.
+.Pp
+If an error is ambiguous (for simplicity, we shall consider all
+errors except
+.Er ENOEXEC
+as being ambiguous here, although only the critical error
+.Er EACCES
+is really ambiguous),
+then these functions will act as if they stat the file to determine
+whether the file exists and has suitable execute permissions.
+If it does, they will return immediately with the global variable
+.Va errno
+restored to the value set by
+.Fn execve .
+Otherwise, the search will be continued.
+If the search completes without performing a successful
+.Fn execve
+or terminating due to an error,
+these functions will return with the global variable
+.Va errno
+set to
+.Er EACCES
+or
+.Er ENOENT
+according to whether at least one file with suitable execute permissions
+was found.
+.Pp
+If the header of a file is not recognized (the attempted
+.Fn execve
+returned
+.Er ENOEXEC ) ,
+these functions will execute the shell with the path of
+the file as its first argument.
+(If this attempt fails, no further searching is done.)
+.Pp
+The function
+.Fn exect
+executes a file with the program tracing facilities enabled (see
+.Xr ptrace 2 ) .
+.Sh RETURN VALUES
+If any of the
+.Fn exec
+functions returns, an error will have occurred.
+The return value is \-1, and the global variable
+.Va errno
+will be set to indicate the error.
+.Sh FILES
+.Bl -tag -width /bin/sh -compact
+.It Pa /bin/sh
+The shell.
+.El
+.Sh COMPATIBILITY
+Historically, the default path for the
+.Fn execlp
+and
+.Fn execvp
+functions was
+.Dq Pa :/bin:/usr/bin .
+This was changed to place the current directory last to enhance system
+security.
+.Pp
+The behavior of
+.Fn execlp
+and
+.Fn execvp
+when errors occur while attempting to execute the file is not quite historic
+practice, and has not traditionally been documented and is not specified
+by the
+.Tn POSIX
+standard.
+.Pp
+Traditionally, the functions
+.Fn execlp
+and
+.Fn execvp
+ignored all errors except for the ones described above and
+.Er ETXTBSY ,
+upon which they retried after sleeping for several seconds, and
+.Er ENOMEM
+and
+.Er E2BIG ,
+upon which they returned.
+They now return for
+.Er ETXTBSY ,
+and determine existence and executability more carefully.
+In particular,
+.Er EACCES
+for inaccessible directories in the path prefix is no longer
+confused with
+.Er EACCES
+for files with unsuitable execute permissions.
+In
+.Bx 4.4 ,
+they returned upon all errors except
+.Er EACCES ,
+.Er ENOENT ,
+.Er ENOEXEC
+and
+.Er ETXTBSY .
+This was inferior to the traditional error handling,
+since it breaks the ignoring of errors for path prefixes
+and only improves the handling of the unusual ambiguous error
+.Er EFAULT
+and the unusual error
+.Er EIO .
+The behaviour was changed to match the behaviour of
+.Xr sh 1 .
+.Sh ERRORS
+The
+.Fn execl ,
+.Fn execle ,
+.Fn execlp ,
+.Fn execvp
+and
+.Fn execvP
+functions
+may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr execve 2
+and
+.Xr malloc 3 .
+.Pp
+The
+.Fn exect
+and
+.Fn execv
+functions
+may fail and set
+.Va errno
+for any of the errors specified for the library function
+.Xr execve 2 .
+.Sh SEE ALSO
+.Xr sh 1 ,
+.Xr execve 2 ,
+.Xr fork 2 ,
+.Xr ktrace 2 ,
+.Xr ptrace 2 ,
+.Xr environ 7
+.Sh STANDARDS
+The
+.Fn execl ,
+.Fn execv ,
+.Fn execle ,
+.Fn execlp
+and
+.Fn execvp
+functions
+conform to
+.St -p1003.1-88 .
+The
+.Fn execvP
+function first appeared in
+.Fx 5.2 .
diff --git a/lib/libc/gen/exec.c b/lib/libc/gen/exec.c
new file mode 100644
index 0000000..4998ee8
--- /dev/null
+++ b/lib/libc/gen/exec.c
@@ -0,0 +1,284 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)exec.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdio.h>
+#include <paths.h>
+
+#include <stdarg.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+extern char **environ;
+
+int
+execl(const char *name, const char *arg, ...)
+{
+ va_list ap;
+ const char **argv;
+ int n;
+
+ va_start(ap, arg);
+ n = 1;
+ while (va_arg(ap, char *) != NULL)
+ n++;
+ va_end(ap);
+ argv = alloca((n + 1) * sizeof(*argv));
+ if (argv == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ va_start(ap, arg);
+ n = 1;
+ argv[0] = arg;
+ while ((argv[n] = va_arg(ap, char *)) != NULL)
+ n++;
+ va_end(ap);
+ return (_execve(name, __DECONST(char **, argv), environ));
+}
+
+int
+execle(const char *name, const char *arg, ...)
+{
+ va_list ap;
+ const char **argv;
+ char **envp;
+ int n;
+
+ va_start(ap, arg);
+ n = 1;
+ while (va_arg(ap, char *) != NULL)
+ n++;
+ va_end(ap);
+ argv = alloca((n + 1) * sizeof(*argv));
+ if (argv == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ va_start(ap, arg);
+ n = 1;
+ argv[0] = arg;
+ while ((argv[n] = va_arg(ap, char *)) != NULL)
+ n++;
+ envp = va_arg(ap, char **);
+ va_end(ap);
+ return (_execve(name, __DECONST(char **, argv), envp));
+}
+
+int
+execlp(const char *name, const char *arg, ...)
+{
+ va_list ap;
+ const char **argv;
+ int n;
+
+ va_start(ap, arg);
+ n = 1;
+ while (va_arg(ap, char *) != NULL)
+ n++;
+ va_end(ap);
+ argv = alloca((n + 1) * sizeof(*argv));
+ if (argv == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ va_start(ap, arg);
+ n = 1;
+ argv[0] = arg;
+ while ((argv[n] = va_arg(ap, char *)) != NULL)
+ n++;
+ va_end(ap);
+ return (execvp(name, __DECONST(char **, argv)));
+}
+
+int
+execv(name, argv)
+ const char *name;
+ char * const *argv;
+{
+ (void)_execve(name, argv, environ);
+ return (-1);
+}
+
+int
+execvp(const char *name, char * const *argv)
+{
+ return (_execvpe(name, argv, environ));
+}
+
+static int
+execvPe(const char *name, const char *path, char * const *argv,
+ char * const *envp)
+{
+ const char **memp;
+ size_t cnt, lp, ln;
+ int eacces, save_errno;
+ char *cur, buf[MAXPATHLEN];
+ const char *p, *bp;
+ struct stat sb;
+
+ eacces = 0;
+
+ /* If it's an absolute or relative path name, it's easy. */
+ if (strchr(name, '/')) {
+ bp = name;
+ cur = NULL;
+ goto retry;
+ }
+ bp = buf;
+
+ /* If it's an empty path name, fail in the usual POSIX way. */
+ if (*name == '\0') {
+ errno = ENOENT;
+ return (-1);
+ }
+
+ cur = alloca(strlen(path) + 1);
+ if (cur == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ strcpy(cur, path);
+ while ((p = strsep(&cur, ":")) != NULL) {
+ /*
+ * It's a SHELL path -- double, leading and trailing colons
+ * mean the current directory.
+ */
+ if (*p == '\0') {
+ p = ".";
+ lp = 1;
+ } else
+ lp = strlen(p);
+ ln = strlen(name);
+
+ /*
+ * If the path is too long complain. This is a possible
+ * security issue; given a way to make the path too long
+ * the user may execute the wrong program.
+ */
+ if (lp + ln + 2 > sizeof(buf)) {
+ (void)_write(STDERR_FILENO, "execvP: ", 8);
+ (void)_write(STDERR_FILENO, p, lp);
+ (void)_write(STDERR_FILENO, ": path too long\n",
+ 16);
+ continue;
+ }
+ bcopy(p, buf, lp);
+ buf[lp] = '/';
+ bcopy(name, buf + lp + 1, ln);
+ buf[lp + ln + 1] = '\0';
+
+retry: (void)_execve(bp, argv, envp);
+ switch (errno) {
+ case E2BIG:
+ goto done;
+ case ELOOP:
+ case ENAMETOOLONG:
+ case ENOENT:
+ break;
+ case ENOEXEC:
+ for (cnt = 0; argv[cnt]; ++cnt)
+ ;
+ memp = alloca((cnt + 2) * sizeof(char *));
+ if (memp == NULL) {
+ /* errno = ENOMEM; XXX override ENOEXEC? */
+ goto done;
+ }
+ memp[0] = "sh";
+ memp[1] = bp;
+ bcopy(argv + 1, memp + 2, cnt * sizeof(char *));
+ (void)_execve(_PATH_BSHELL,
+ __DECONST(char **, memp), envp);
+ goto done;
+ case ENOMEM:
+ goto done;
+ case ENOTDIR:
+ break;
+ case ETXTBSY:
+ /*
+ * We used to retry here, but sh(1) doesn't.
+ */
+ goto done;
+ default:
+ /*
+ * EACCES may be for an inaccessible directory or
+ * a non-executable file. Call stat() to decide
+ * which. This also handles ambiguities for EFAULT
+ * and EIO, and undocumented errors like ESTALE.
+ * We hope that the race for a stat() is unimportant.
+ */
+ save_errno = errno;
+ if (stat(bp, &sb) != 0)
+ break;
+ if (save_errno == EACCES) {
+ eacces = 1;
+ continue;
+ }
+ errno = save_errno;
+ goto done;
+ }
+ }
+ if (eacces)
+ errno = EACCES;
+ else
+ errno = ENOENT;
+done:
+ return (-1);
+}
+
+int
+execvP(const char *name, const char *path, char * const argv[])
+{
+ return execvPe(name, path, argv, environ);
+}
+
+int
+_execvpe(const char *name, char * const argv[], char * const envp[])
+{
+ const char *path;
+
+ /* Get the path we're searching. */
+ if ((path = getenv("PATH")) == NULL)
+ path = _PATH_DEFPATH;
+
+ return (execvPe(name, path, argv, envp));
+}
diff --git a/lib/libc/gen/fdevname.c b/lib/libc/gen/fdevname.c
new file mode 100644
index 0000000..d60da70
--- /dev/null
+++ b/lib/libc/gen/fdevname.c
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2009 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+
+char *
+fdevname_r(int fd, char *buf, int len)
+{
+ struct fiodgname_arg fgn;
+
+ fgn.buf = buf;
+ fgn.len = len;
+
+ if (_ioctl(fd, FIODGNAME, &fgn) == -1)
+ return (NULL);
+ return (buf);
+}
+
+char *
+fdevname(int fd)
+{
+ static char buf[SPECNAMELEN + 1];
+
+ return (fdevname_r(fd, buf, sizeof(buf)));
+}
diff --git a/lib/libc/gen/feature_present.3 b/lib/libc/gen/feature_present.3
new file mode 100644
index 0000000..3a702d4
--- /dev/null
+++ b/lib/libc/gen/feature_present.3
@@ -0,0 +1,72 @@
+.\" Copyright (c) 2008 Yahoo!, Inc.
+.\" All rights reserved.
+.\" Written by: John Baldwin <jhb@FreeBSD.org>
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the author nor the names of any co-contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 8, 2008
+.Dt FEATURE_PRESENT 3
+.Os
+.Sh NAME
+.Nm feature_present
+.Nd query presence of a kernel feature
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn feature_present "const char *feature"
+.Sh DESCRIPTION
+The
+.Fn feature_present
+function provides a method for an application to determine if a specific
+kernel feature is present in the currently running kernel.
+The
+.Fa feature
+argument specifies the name of the feature to check.
+The
+.Fn feature_present
+function will return 1 if the specified feature is present,
+otherwise it will return 0.
+If the
+.Fn feature_present
+function is not able to determine the presence of
+.Fa feature
+due to an internal error it will return 0.
+.Sh RETURN VALUES
+If
+.Fa feature
+is present then 1 is returned;
+otherwise 0 is returned.
+.Sh SEE ALSO
+.Xr sysconf 3 ,
+.Xr sysctl 3
+.Sh HISTORY
+The
+.Fn feature_present
+function first appeared in
+.Fx 8.0 .
diff --git a/lib/libc/gen/feature_present.c b/lib/libc/gen/feature_present.c
new file mode 100644
index 0000000..7a2c282
--- /dev/null
+++ b/lib/libc/gen/feature_present.c
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 2008 Yahoo!, Inc.
+ * All rights reserved.
+ * Written by: John Baldwin <jhb@FreeBSD.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+/*
+ * Returns true if the named feature is present in the currently
+ * running kernel. A feature's presence is indicated by an integer
+ * sysctl node called kern.feature.<feature> that is non-zero.
+ */
+int
+feature_present(const char *feature)
+{
+ char *mib;
+ size_t len;
+ int i;
+
+ if (asprintf(&mib, "kern.features.%s", feature) < 0)
+ return (0);
+ len = sizeof(i);
+ if (sysctlbyname(mib, &i, &len, NULL, 0) < 0) {
+ free(mib);
+ return (0);
+ }
+ free(mib);
+ if (len != sizeof(i))
+ return (0);
+ return (i != 0);
+}
diff --git a/lib/libc/gen/fmtcheck.3 b/lib/libc/gen/fmtcheck.3
new file mode 100644
index 0000000..0bd4299
--- /dev/null
+++ b/lib/libc/gen/fmtcheck.3
@@ -0,0 +1,108 @@
+.\" Copyright (c) 2000 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This file was contributed to The NetBSD Foundation by Allen Briggs.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.Dd October 16, 2002
+.Dt FMTCHECK 3
+.Os
+.Sh NAME
+.Nm fmtcheck
+.Nd sanitizes user-supplied
+.Xr printf 3 Ns -style
+format string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft const char *
+.Fn fmtcheck "const char *fmt_suspect" "const char *fmt_default"
+.Sh DESCRIPTION
+The
+.Fn fmtcheck
+scans
+.Fa fmt_suspect
+and
+.Fa fmt_default
+to determine if
+.Fa fmt_suspect
+will consume the same argument types as
+.Fa fmt_default
+and to ensure that
+.Fa fmt_suspect
+is a valid format string.
+.Pp
+The
+.Xr printf 3
+family of functions cannot verify the types of arguments that they are
+passed at run-time.
+In some cases, like
+.Xr catgets 3 ,
+it is useful or necessary to use a user-supplied format string with no
+guarantee that the format string matches the specified arguments.
+.Pp
+The
+.Fn fmtcheck
+was designed to be used in these cases, as in:
+.Bd -literal -offset indent
+printf(fmtcheck(user_format, standard_format), arg1, arg2);
+.Ed
+.Pp
+In the check, field widths, fillers, precisions, etc.\& are ignored (unless
+the field width or precision is an asterisk
+.Ql *
+instead of a digit string).
+Also, any text other than the format specifiers
+is completely ignored.
+.Sh RETURN VALUES
+If
+.Fa fmt_suspect
+is a valid format and consumes the same argument types as
+.Fa fmt_default ,
+then the
+.Fn fmtcheck
+will return
+.Fa fmt_suspect .
+Otherwise, it will return
+.Fa fmt_default .
+.Sh SEE ALSO
+.Xr printf 3
+.Sh BUGS
+The
+.Fn fmtcheck
+function does not recognize positional parameters.
+.Sh SECURITY CONSIDERATIONS
+Note that the formats may be quite different as long as they accept the
+same arguments.
+For example,
+.Qq Li "%p %o %30s %#llx %-10.*e %n"
+is compatible with
+.Qq Li "This number %lu %d%% and string %s has %qd numbers and %.*g floats (%n)" .
+However,
+.Qq Li %o
+is not equivalent to
+.Qq Li %lx
+because
+the first requires an integer and the second requires a long.
diff --git a/lib/libc/gen/fmtcheck.c b/lib/libc/gen/fmtcheck.c
new file mode 100644
index 0000000..5b3f2c4
--- /dev/null
+++ b/lib/libc/gen/fmtcheck.c
@@ -0,0 +1,325 @@
+/* $NetBSD: fmtcheck.c,v 1.8 2008/04/28 20:22:59 martin Exp $ */
+
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code was contributed to The NetBSD Foundation by Allen Briggs.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+__weak_reference(__fmtcheck, fmtcheck);
+
+enum __e_fmtcheck_types {
+ FMTCHECK_START,
+ FMTCHECK_SHORT,
+ FMTCHECK_INT,
+ FMTCHECK_WINTT,
+ FMTCHECK_LONG,
+ FMTCHECK_QUAD,
+ FMTCHECK_INTMAXT,
+ FMTCHECK_PTRDIFFT,
+ FMTCHECK_SIZET,
+ FMTCHECK_CHARPOINTER,
+ FMTCHECK_SHORTPOINTER,
+ FMTCHECK_INTPOINTER,
+ FMTCHECK_LONGPOINTER,
+ FMTCHECK_QUADPOINTER,
+ FMTCHECK_INTMAXTPOINTER,
+ FMTCHECK_PTRDIFFTPOINTER,
+ FMTCHECK_SIZETPOINTER,
+#ifndef NO_FLOATING_POINT
+ FMTCHECK_DOUBLE,
+ FMTCHECK_LONGDOUBLE,
+#endif
+ FMTCHECK_STRING,
+ FMTCHECK_WSTRING,
+ FMTCHECK_WIDTH,
+ FMTCHECK_PRECISION,
+ FMTCHECK_DONE,
+ FMTCHECK_UNKNOWN
+};
+typedef enum __e_fmtcheck_types EFT;
+
+enum e_modifier {
+ MOD_NONE,
+ MOD_CHAR,
+ MOD_SHORT,
+ MOD_LONG,
+ MOD_QUAD,
+ MOD_INTMAXT,
+ MOD_LONGDOUBLE,
+ MOD_PTRDIFFT,
+ MOD_SIZET,
+};
+
+#define RETURN(pf,f,r) do { \
+ *(pf) = (f); \
+ return r; \
+ } /*NOTREACHED*/ /*CONSTCOND*/ while (0)
+
+static EFT
+get_next_format_from_precision(const char **pf)
+{
+ enum e_modifier modifier;
+ const char *f;
+
+ f = *pf;
+ switch (*f) {
+ case 'h':
+ f++;
+ if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
+ if (*f == 'h') {
+ f++;
+ modifier = MOD_CHAR;
+ } else {
+ modifier = MOD_SHORT;
+ }
+ break;
+ case 'j':
+ f++;
+ modifier = MOD_INTMAXT;
+ break;
+ case 'l':
+ f++;
+ if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
+ if (*f == 'l') {
+ f++;
+ modifier = MOD_QUAD;
+ } else {
+ modifier = MOD_LONG;
+ }
+ break;
+ case 'q':
+ f++;
+ modifier = MOD_QUAD;
+ break;
+ case 't':
+ f++;
+ modifier = MOD_PTRDIFFT;
+ break;
+ case 'z':
+ f++;
+ modifier = MOD_SIZET;
+ break;
+ case 'L':
+ f++;
+ modifier = MOD_LONGDOUBLE;
+ break;
+ default:
+ modifier = MOD_NONE;
+ break;
+ }
+ if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
+ if (strchr("diouxX", *f)) {
+ switch (modifier) {
+ case MOD_LONG:
+ RETURN(pf,f,FMTCHECK_LONG);
+ case MOD_QUAD:
+ RETURN(pf,f,FMTCHECK_QUAD);
+ case MOD_INTMAXT:
+ RETURN(pf,f,FMTCHECK_INTMAXT);
+ case MOD_PTRDIFFT:
+ RETURN(pf,f,FMTCHECK_PTRDIFFT);
+ case MOD_SIZET:
+ RETURN(pf,f,FMTCHECK_SIZET);
+ case MOD_CHAR:
+ case MOD_SHORT:
+ case MOD_NONE:
+ RETURN(pf,f,FMTCHECK_INT);
+ default:
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ }
+ }
+ if (*f == 'n') {
+ switch (modifier) {
+ case MOD_CHAR:
+ RETURN(pf,f,FMTCHECK_CHARPOINTER);
+ case MOD_SHORT:
+ RETURN(pf,f,FMTCHECK_SHORTPOINTER);
+ case MOD_LONG:
+ RETURN(pf,f,FMTCHECK_LONGPOINTER);
+ case MOD_QUAD:
+ RETURN(pf,f,FMTCHECK_QUADPOINTER);
+ case MOD_INTMAXT:
+ RETURN(pf,f,FMTCHECK_INTMAXTPOINTER);
+ case MOD_PTRDIFFT:
+ RETURN(pf,f,FMTCHECK_PTRDIFFTPOINTER);
+ case MOD_SIZET:
+ RETURN(pf,f,FMTCHECK_SIZETPOINTER);
+ case MOD_NONE:
+ RETURN(pf,f,FMTCHECK_INTPOINTER);
+ default:
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ }
+ }
+ if (strchr("DOU", *f)) {
+ if (modifier != MOD_NONE)
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ RETURN(pf,f,FMTCHECK_LONG);
+ }
+#ifndef NO_FLOATING_POINT
+ if (strchr("aAeEfFgG", *f)) {
+ switch (modifier) {
+ case MOD_LONGDOUBLE:
+ RETURN(pf,f,FMTCHECK_LONGDOUBLE);
+ case MOD_LONG:
+ case MOD_NONE:
+ RETURN(pf,f,FMTCHECK_DOUBLE);
+ default:
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ }
+ }
+#endif
+ if (*f == 'c') {
+ switch (modifier) {
+ case MOD_LONG:
+ RETURN(pf,f,FMTCHECK_WINTT);
+ case MOD_NONE:
+ RETURN(pf,f,FMTCHECK_INT);
+ default:
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ }
+ }
+ if (*f == 'C') {
+ if (modifier != MOD_NONE)
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ RETURN(pf,f,FMTCHECK_WINTT);
+ }
+ if (*f == 's') {
+ switch (modifier) {
+ case MOD_LONG:
+ RETURN(pf,f,FMTCHECK_WSTRING);
+ case MOD_NONE:
+ RETURN(pf,f,FMTCHECK_STRING);
+ default:
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ }
+ }
+ if (*f == 'S') {
+ if (modifier != MOD_NONE)
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ RETURN(pf,f,FMTCHECK_WSTRING);
+ }
+ if (*f == 'p') {
+ if (modifier != MOD_NONE)
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ RETURN(pf,f,FMTCHECK_LONG);
+ }
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ /*NOTREACHED*/
+}
+
+static EFT
+get_next_format_from_width(const char **pf)
+{
+ const char *f;
+
+ f = *pf;
+ if (*f == '.') {
+ f++;
+ if (*f == '*') {
+ RETURN(pf,f,FMTCHECK_PRECISION);
+ }
+ /* eat any precision (empty is allowed) */
+ while (isdigit(*f)) f++;
+ if (!*f) RETURN(pf,f,FMTCHECK_UNKNOWN);
+ }
+ RETURN(pf,f,get_next_format_from_precision(pf));
+ /*NOTREACHED*/
+}
+
+static EFT
+get_next_format(const char **pf, EFT eft)
+{
+ int infmt;
+ const char *f;
+
+ if (eft == FMTCHECK_WIDTH) {
+ (*pf)++;
+ return get_next_format_from_width(pf);
+ } else if (eft == FMTCHECK_PRECISION) {
+ (*pf)++;
+ return get_next_format_from_precision(pf);
+ }
+
+ f = *pf;
+ infmt = 0;
+ while (!infmt) {
+ f = strchr(f, '%');
+ if (f == NULL)
+ RETURN(pf,f,FMTCHECK_DONE);
+ f++;
+ if (!*f)
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ if (*f != '%')
+ infmt = 1;
+ else
+ f++;
+ }
+
+ /* Eat any of the flags */
+ while (*f && (strchr("#'0- +", *f)))
+ f++;
+
+ if (*f == '*') {
+ RETURN(pf,f,FMTCHECK_WIDTH);
+ }
+ /* eat any width */
+ while (isdigit(*f)) f++;
+ if (!*f) {
+ RETURN(pf,f,FMTCHECK_UNKNOWN);
+ }
+
+ RETURN(pf,f,get_next_format_from_width(pf));
+ /*NOTREACHED*/
+}
+
+const char *
+__fmtcheck(const char *f1, const char *f2)
+{
+ const char *f1p, *f2p;
+ EFT f1t, f2t;
+
+ if (!f1) return f2;
+
+ f1p = f1;
+ f1t = FMTCHECK_START;
+ f2p = f2;
+ f2t = FMTCHECK_START;
+ while ((f1t = get_next_format(&f1p, f1t)) != FMTCHECK_DONE) {
+ if (f1t == FMTCHECK_UNKNOWN)
+ return f2;
+ f2t = get_next_format(&f2p, f2t);
+ if (f1t != f2t)
+ return f2;
+ }
+ return f1;
+}
diff --git a/lib/libc/gen/fmtmsg.3 b/lib/libc/gen/fmtmsg.3
new file mode 100644
index 0000000..7995d7b
--- /dev/null
+++ b/lib/libc/gen/fmtmsg.3
@@ -0,0 +1,260 @@
+.\"
+.\" Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 5, 2002
+.Dt FMTMSG 3
+.Os
+.Sh NAME
+.Nm fmtmsg
+.Nd display a detailed diagnostic message
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In fmtmsg.h
+.Ft int
+.Fo fmtmsg
+.Fa "long classification" "const char *label" "int severity"
+.Fa "const char *text" "const char *action" "const char *tag"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn fmtmsg
+function displays a detailed diagnostic message, based on
+the supplied arguments, to
+.Dv stderr
+and/or the system console.
+.Pp
+The
+.Fa classification
+argument is the bitwise inclusive
+.Tn OR
+of zero or one of the manifest constants from
+each of the classification groups below.
+The Output classification group is an exception since both
+.Dv MM_PRINT
+and
+.Dv MM_CONSOLE
+may be specified.
+.Bl -tag -width indent
+.It Output
+.Bl -tag -width ".Dv MM_CONSOLE"
+.It Dv MM_PRINT
+Output should take place on
+.Dv stderr .
+.It Dv MM_CONSOLE
+Output should take place on the system console.
+.El
+.It "Source of Condition (Major)"
+.Bl -tag -width ".Dv MM_CONSOLE"
+.It Dv MM_HARD
+The source of the condition is hardware related.
+.It Dv MM_SOFT
+The source of the condition is software related.
+.It Dv MM_FIRM
+The source of the condition is firmware related.
+.El
+.It "Source of Condition (Minor)"
+.Bl -tag -width ".Dv MM_CONSOLE"
+.It Dv MM_APPL
+The condition was detected at the application level.
+.It Dv MM_UTIL
+The condition was detected at the utility level.
+.It Dv MM_OPSYS
+The condition was detected at the operating system level.
+.El
+.It Status
+.Bl -tag -width ".Dv MM_CONSOLE"
+.It Dv MM_RECOVER
+The application can recover from the condition.
+.It Dv MM_NRECOV
+The application is unable to recover from the condition.
+.El
+.El
+.Pp
+Alternatively, the
+.Dv MM_NULLMC
+manifest constant may be used to specify no classification.
+.Pp
+The
+.Fa label
+argument indicates the source of the message.
+It is made up of two fields separated by a colon
+.Pq Ql \&: .
+The first field can be up to 10 bytes,
+and the second field can be up to 14 bytes.
+The
+.Dv MM_NULLLBL
+manifest constant may be used to specify no label.
+.Pp
+The
+.Fa severity
+argument identifies the importance of the condition.
+One of the following manifest constants should be used for this argument.
+.Bl -tag -offset indent -width ".Dv MM_WARNING"
+.It Dv MM_HALT
+The application has confronted a serious fault and is halting.
+.It Dv MM_ERROR
+The application has detected a fault.
+.It Dv MM_WARNING
+The application has detected an unusual condition,
+that could be indicative of a problem.
+.It Dv MM_INFO
+The application is providing information about a non-error condition.
+.It Dv MM_NOSEV
+No severity level supplied.
+.El
+.Pp
+The
+.Fa text
+argument details the error condition that caused the message.
+There is no limit on the size of this character string.
+The
+.Dv MM_NULLTXT
+manifest constant may be used to specify no text.
+.Pp
+The
+.Fa action
+argument details how the error-recovery process should begin.
+Upon output,
+.Fn fmtmsg
+will prefix
+.Qq Li "TO FIX:"
+to the beginning of the
+.Fa action
+argument.
+The
+.Dv MM_NULLACT
+manifest constant may be used to specify no action.
+.Pp
+The
+.Fa tag
+argument should reference online documentation for the message.
+This usually includes the
+.Fa label
+and a unique identifying number.
+An example tag is
+.Qq Li BSD:ls:168 .
+The
+.Dv MM_NULLTAG
+manifest constant may be used to specify no tag.
+.Sh RETURN VALUES
+The
+.Fn fmtmsg
+function returns
+.Dv MM_OK
+upon success,
+.Dv MM_NOMSG
+to indicate output to
+.Dv stderr
+failed,
+.Dv MM_NOCON
+to indicate output to the system console failed, or
+.Dv MM_NOTOK
+to indicate output to
+.Dv stderr
+and the system console failed.
+.Sh ENVIRONMENT
+The
+.Ev MSGVERB
+(message verbosity)
+environment variable specifies which arguments to
+.Fn fmtmsg
+will be output to
+.Dv stderr ,
+and in which order.
+.Ev MSGVERB
+should be a colon
+.Pq Ql \&:
+separated list of identifiers.
+Valid identifiers include:
+.Li label , severity , text , action ,
+and
+.Li tag .
+If invalid identifiers are specified or incorrectly separated,
+the default message verbosity and ordering will be used.
+The default ordering is equivalent to a
+.Ev MSGVERB
+with a value of
+.Qq Li label:severity:text:action:tag .
+.Sh EXAMPLES
+The code:
+.Bd -literal -offset indent
+fmtmsg(MM_UTIL | MM_PRINT, "BSD:ls", MM_ERROR,
+ "illegal option -- z", "refer to manual", "BSD:ls:001");
+.Ed
+.Pp
+will output:
+.Bd -literal -offset indent
+BSD:ls: ERROR: illegal option -- z
+TO FIX: refer to manual BSD:ls:001
+.Ed
+.Pp
+to
+.Dv stderr .
+.Pp
+The same code, with
+.Ev MSGVERB
+set to
+.Qq Li "text:severity:action:tag" ,
+produces:
+.Bd -literal -offset indent
+illegal option -- z: ERROR
+TO FIX: refer to manual BSD:ls:001
+.Ed
+.Sh SEE ALSO
+.Xr err 3 ,
+.Xr exit 3 ,
+.Xr strerror 3
+.Sh STANDARDS
+The
+.Fn fmtmsg
+function conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn fmtmsg
+function first appeared in
+.Fx 5.0 .
+.Sh BUGS
+Specifying
+.Dv MM_NULLMC
+for the
+.Fa classification
+argument makes little sense, since without an output specified,
+.Fn fmtmsg
+is unable to do anything useful.
+.Pp
+In order for
+.Fn fmtmsg
+to output to the system console, the effective
+user must have appropriate permission to write to
+.Pa /dev/console .
+This means that on most systems
+.Fn fmtmsg
+will return
+.Dv MM_NOCON
+unless the effective user is root.
diff --git a/lib/libc/gen/fmtmsg.c b/lib/libc/gen/fmtmsg.c
new file mode 100644
index 0000000..c6ecbd5
--- /dev/null
+++ b/lib/libc/gen/fmtmsg.c
@@ -0,0 +1,220 @@
+/*-
+ * Copyright (c) 2002 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <fmtmsg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+/* Default value for MSGVERB. */
+#define DFLT_MSGVERB "label:severity:text:action:tag"
+
+/* Maximum valid size for a MSGVERB. */
+#define MAX_MSGVERB sizeof(DFLT_MSGVERB)
+
+static char *printfmt(char *, long, const char *, int, const char *,
+ const char *, const char *);
+static char *nextcomp(const char *);
+static const char
+ *sevinfo(int);
+static int validmsgverb(const char *);
+
+int
+fmtmsg(long class, const char *label, int sev, const char *text,
+ const char *action, const char *tag)
+{
+ FILE *fp;
+ char *env, *msgverb, *output;
+
+ if (class & MM_PRINT) {
+ if ((env = getenv("MSGVERB")) != NULL && *env != '\0' &&
+ strlen(env) <= strlen(DFLT_MSGVERB)) {
+ if ((msgverb = strdup(env)) == NULL)
+ return (MM_NOTOK);
+ else if (validmsgverb(msgverb) == 0) {
+ free(msgverb);
+ goto def;
+ }
+ } else {
+def:
+ if ((msgverb = strdup(DFLT_MSGVERB)) == NULL)
+ return (MM_NOTOK);
+ }
+ output = printfmt(msgverb, class, label, sev, text, action,
+ tag);
+ if (output == NULL) {
+ free(msgverb);
+ return (MM_NOTOK);
+ }
+ if (*output != '\0')
+ fprintf(stderr, "%s", output);
+ free(msgverb);
+ free(output);
+ }
+ if (class & MM_CONSOLE) {
+ output = printfmt(DFLT_MSGVERB, class, label, sev, text,
+ action, tag);
+ if (output == NULL)
+ return (MM_NOCON);
+ if (*output != '\0') {
+ if ((fp = fopen("/dev/console", "a")) == NULL) {
+ free(output);
+ return (MM_NOCON);
+ }
+ fprintf(fp, "%s", output);
+ fclose(fp);
+ }
+ free(output);
+ }
+ return (MM_OK);
+}
+
+#define INSERT_COLON \
+ if (*output != '\0') \
+ strlcat(output, ": ", size)
+#define INSERT_NEWLINE \
+ if (*output != '\0') \
+ strlcat(output, "\n", size)
+#define INSERT_SPACE \
+ if (*output != '\0') \
+ strlcat(output, " ", size)
+
+/*
+ * Returns NULL on memory allocation failure, otherwise returns a pointer to
+ * a newly malloc()'d output buffer.
+ */
+static char *
+printfmt(char *msgverb, long class, const char *label, int sev,
+ const char *text, const char *act, const char *tag)
+{
+ size_t size;
+ char *comp, *output;
+ const char *sevname;
+
+ size = 32;
+ if (label != MM_NULLLBL)
+ size += strlen(label);
+ if ((sevname = sevinfo(sev)) != NULL)
+ size += strlen(sevname);
+ if (text != MM_NULLTXT)
+ size += strlen(text);
+ if (act != MM_NULLACT)
+ size += strlen(act);
+ if (tag != MM_NULLTAG)
+ size += strlen(tag);
+
+ if ((output = malloc(size)) == NULL)
+ return (NULL);
+ *output = '\0';
+ while ((comp = nextcomp(msgverb)) != NULL) {
+ if (strcmp(comp, "label") == 0 && label != MM_NULLLBL) {
+ INSERT_COLON;
+ strlcat(output, label, size);
+ } else if (strcmp(comp, "severity") == 0 && sevname != NULL) {
+ INSERT_COLON;
+ strlcat(output, sevinfo(sev), size);
+ } else if (strcmp(comp, "text") == 0 && text != MM_NULLTXT) {
+ INSERT_COLON;
+ strlcat(output, text, size);
+ } else if (strcmp(comp, "action") == 0 && act != MM_NULLACT) {
+ INSERT_NEWLINE;
+ strlcat(output, "TO FIX: ", size);
+ strlcat(output, act, size);
+ } else if (strcmp(comp, "tag") == 0 && tag != MM_NULLTAG) {
+ INSERT_SPACE;
+ strlcat(output, tag, size);
+ }
+ }
+ INSERT_NEWLINE;
+ return (output);
+}
+
+/*
+ * Returns a component of a colon delimited string. NULL is returned to
+ * indicate that there are no remaining components. This function must be
+ * called until it returns NULL in order for the local state to be cleared.
+ */
+static char *
+nextcomp(const char *msgverb)
+{
+ static char lmsgverb[MAX_MSGVERB], *state;
+ char *retval;
+
+ if (*lmsgverb == '\0') {
+ strlcpy(lmsgverb, msgverb, sizeof(lmsgverb));
+ retval = strtok_r(lmsgverb, ":", &state);
+ } else {
+ retval = strtok_r(NULL, ":", &state);
+ }
+ if (retval == NULL)
+ *lmsgverb = '\0';
+ return (retval);
+}
+
+static const char *
+sevinfo(int sev)
+{
+
+ switch (sev) {
+ case MM_HALT:
+ return ("HALT");
+ case MM_ERROR:
+ return ("ERROR");
+ case MM_WARNING:
+ return ("WARNING");
+ case MM_INFO:
+ return ("INFO");
+ default:
+ return (NULL);
+ }
+}
+
+/*
+ * Returns 1 if the msgverb list is valid, otherwise 0.
+ */
+static int
+validmsgverb(const char *msgverb)
+{
+ const char *validlist = "label\0severity\0text\0action\0tag\0";
+ char *msgcomp;
+ size_t len1, len2;
+ const char *p;
+ int equality;
+
+ equality = 0;
+ while ((msgcomp = nextcomp(msgverb)) != NULL) {
+ equality--;
+ len1 = strlen(msgcomp);
+ for (p = validlist; (len2 = strlen(p)) != 0; p += len2 + 1) {
+ if (len1 == len2 && memcmp(msgcomp, p, len1) == 0)
+ equality++;
+ }
+ }
+ return (!equality);
+}
diff --git a/lib/libc/gen/fnmatch.3 b/lib/libc/gen/fnmatch.3
new file mode 100644
index 0000000..489b2a8
--- /dev/null
+++ b/lib/libc/gen/fnmatch.3
@@ -0,0 +1,151 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Guido van Rossum.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fnmatch.3 8.3 (Berkeley) 4/28/95
+.\" $FreeBSD$
+.\"
+.Dd July 18, 2004
+.Dt FNMATCH 3
+.Os
+.Sh NAME
+.Nm fnmatch
+.Nd test whether a filename or pathname matches a shell-style pattern
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In fnmatch.h
+.Ft int
+.Fn fnmatch "const char *pattern" "const char *string" "int flags"
+.Sh DESCRIPTION
+The
+.Fn fnmatch
+function
+matches patterns according to the rules used by the shell.
+It checks the string specified by the
+.Fa string
+argument to see if it matches the pattern specified by the
+.Fa pattern
+argument.
+.Pp
+The
+.Fa flags
+argument modifies the interpretation of
+.Fa pattern
+and
+.Fa string .
+The value of
+.Fa flags
+is the bitwise inclusive
+.Tn OR
+of any of the following
+constants, which are defined in the include file
+.In fnmatch.h .
+.Bl -tag -width FNM_PATHNAME
+.It Dv FNM_NOESCAPE
+Normally, every occurrence of a backslash
+.Pq Ql \e
+followed by a character in
+.Fa pattern
+is replaced by that character.
+This is done to negate any special meaning for the character.
+If the
+.Dv FNM_NOESCAPE
+flag is set, a backslash character is treated as an ordinary character.
+.It Dv FNM_PATHNAME
+Slash characters in
+.Fa string
+must be explicitly matched by slashes in
+.Fa pattern .
+If this flag is not set, then slashes are treated as regular characters.
+.It Dv FNM_PERIOD
+Leading periods in
+.Fa string
+must be explicitly matched by periods in
+.Fa pattern .
+If this flag is not set, then leading periods are treated as regular
+characters.
+The definition of
+.Dq leading
+is related to the specification of
+.Dv FNM_PATHNAME .
+A period is always
+.Dq leading
+if it is the first character in
+.Fa string .
+Additionally, if
+.Dv FNM_PATHNAME
+is set,
+a period is
+leading
+if it immediately follows a slash.
+.It Dv FNM_LEADING_DIR
+Ignore
+.Dq Li /*
+rest after successful
+.Fa pattern
+matching.
+.It Dv FNM_CASEFOLD
+Ignore case distinctions in both the
+.Fa pattern
+and the
+.Fa string .
+.El
+.Sh RETURN VALUES
+The
+.Fn fnmatch
+function returns zero if
+.Fa string
+matches the pattern specified by
+.Fa pattern ,
+otherwise, it returns the value
+.Dv FNM_NOMATCH .
+.Sh SEE ALSO
+.Xr sh 1 ,
+.Xr glob 3 ,
+.Xr regex 3
+.Sh STANDARDS
+The current implementation of the
+.Fn fnmatch
+function
+.Em does not
+conform to
+.St -p1003.2 .
+Collating symbol expressions, equivalence class expressions and
+character class expressions are not supported.
+.Sh HISTORY
+The
+.Fn fnmatch
+function first appeared in
+.Bx 4.4 .
+.Sh BUGS
+The pattern
+.Ql *
+matches the empty string, even if
+.Dv FNM_PATHNAME
+is specified.
diff --git a/lib/libc/gen/fnmatch.c b/lib/libc/gen/fnmatch.c
new file mode 100644
index 0000000..c38aafc
--- /dev/null
+++ b/lib/libc/gen/fnmatch.c
@@ -0,0 +1,298 @@
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6.
+ * Compares a filename or pathname to a pattern.
+ */
+
+/*
+ * Some notes on multibyte character support:
+ * 1. Patterns with illegal byte sequences match nothing.
+ * 2. Illegal byte sequences in the "string" argument are handled by treating
+ * them as single-byte characters with a value of the first byte of the
+ * sequence cast to wchar_t.
+ * 3. Multibyte conversion state objects (mbstate_t) are passed around and
+ * used for most, but not all, conversions. Further work will be required
+ * to support state-dependent encodings.
+ */
+
+#include <fnmatch.h>
+#include <limits.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "collate.h"
+
+#define EOS '\0'
+
+#define RANGE_MATCH 1
+#define RANGE_NOMATCH 0
+#define RANGE_ERROR (-1)
+
+static int rangematch(const char *, wchar_t, int, char **, mbstate_t *);
+static int fnmatch1(const char *, const char *, const char *, int, mbstate_t,
+ mbstate_t);
+
+int
+fnmatch(pattern, string, flags)
+ const char *pattern, *string;
+ int flags;
+{
+ static const mbstate_t initial;
+
+ return (fnmatch1(pattern, string, string, flags, initial, initial));
+}
+
+static int
+fnmatch1(pattern, string, stringstart, flags, patmbs, strmbs)
+ const char *pattern, *string, *stringstart;
+ int flags;
+ mbstate_t patmbs, strmbs;
+{
+ char *newp;
+ char c;
+ wchar_t pc, sc;
+ size_t pclen, sclen;
+
+ for (;;) {
+ pclen = mbrtowc(&pc, pattern, MB_LEN_MAX, &patmbs);
+ if (pclen == (size_t)-1 || pclen == (size_t)-2)
+ return (FNM_NOMATCH);
+ pattern += pclen;
+ sclen = mbrtowc(&sc, string, MB_LEN_MAX, &strmbs);
+ if (sclen == (size_t)-1 || sclen == (size_t)-2) {
+ sc = (unsigned char)*string;
+ sclen = 1;
+ memset(&strmbs, 0, sizeof(strmbs));
+ }
+ switch (pc) {
+ case EOS:
+ if ((flags & FNM_LEADING_DIR) && sc == '/')
+ return (0);
+ return (sc == EOS ? 0 : FNM_NOMATCH);
+ case '?':
+ if (sc == EOS)
+ return (FNM_NOMATCH);
+ if (sc == '/' && (flags & FNM_PATHNAME))
+ return (FNM_NOMATCH);
+ if (sc == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+ return (FNM_NOMATCH);
+ string += sclen;
+ break;
+ case '*':
+ c = *pattern;
+ /* Collapse multiple stars. */
+ while (c == '*')
+ c = *++pattern;
+
+ if (sc == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+ return (FNM_NOMATCH);
+
+ /* Optimize for pattern with * at end or before /. */
+ if (c == EOS)
+ if (flags & FNM_PATHNAME)
+ return ((flags & FNM_LEADING_DIR) ||
+ strchr(string, '/') == NULL ?
+ 0 : FNM_NOMATCH);
+ else
+ return (0);
+ else if (c == '/' && flags & FNM_PATHNAME) {
+ if ((string = strchr(string, '/')) == NULL)
+ return (FNM_NOMATCH);
+ break;
+ }
+
+ /* General case, use recursion. */
+ while (sc != EOS) {
+ if (!fnmatch1(pattern, string, stringstart,
+ flags, patmbs, strmbs))
+ return (0);
+ sclen = mbrtowc(&sc, string, MB_LEN_MAX,
+ &strmbs);
+ if (sclen == (size_t)-1 ||
+ sclen == (size_t)-2) {
+ sc = (unsigned char)*string;
+ sclen = 1;
+ memset(&strmbs, 0, sizeof(strmbs));
+ }
+ if (sc == '/' && flags & FNM_PATHNAME)
+ break;
+ string += sclen;
+ }
+ return (FNM_NOMATCH);
+ case '[':
+ if (sc == EOS)
+ return (FNM_NOMATCH);
+ if (sc == '/' && (flags & FNM_PATHNAME))
+ return (FNM_NOMATCH);
+ if (sc == '.' && (flags & FNM_PERIOD) &&
+ (string == stringstart ||
+ ((flags & FNM_PATHNAME) && *(string - 1) == '/')))
+ return (FNM_NOMATCH);
+
+ switch (rangematch(pattern, sc, flags, &newp,
+ &patmbs)) {
+ case RANGE_ERROR:
+ goto norm;
+ case RANGE_MATCH:
+ pattern = newp;
+ break;
+ case RANGE_NOMATCH:
+ return (FNM_NOMATCH);
+ }
+ string += sclen;
+ break;
+ case '\\':
+ if (!(flags & FNM_NOESCAPE)) {
+ pclen = mbrtowc(&pc, pattern, MB_LEN_MAX,
+ &patmbs);
+ if (pclen == (size_t)-1 || pclen == (size_t)-2)
+ return (FNM_NOMATCH);
+ if (pclen == 0)
+ pc = '\\';
+ pattern += pclen;
+ }
+ /* FALLTHROUGH */
+ default:
+ norm:
+ if (pc == sc)
+ ;
+ else if ((flags & FNM_CASEFOLD) &&
+ (towlower(pc) == towlower(sc)))
+ ;
+ else
+ return (FNM_NOMATCH);
+ string += sclen;
+ break;
+ }
+ }
+ /* NOTREACHED */
+}
+
+static int
+rangematch(pattern, test, flags, newp, patmbs)
+ const char *pattern;
+ wchar_t test;
+ int flags;
+ char **newp;
+ mbstate_t *patmbs;
+{
+ int negate, ok;
+ wchar_t c, c2;
+ size_t pclen;
+ const char *origpat;
+ struct xlocale_collate *table =
+ (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE];
+
+ /*
+ * A bracket expression starting with an unquoted circumflex
+ * character produces unspecified results (IEEE 1003.2-1992,
+ * 3.13.2). This implementation treats it like '!', for
+ * consistency with the regular expression syntax.
+ * J.T. Conklin (conklin@ngai.kaleida.com)
+ */
+ if ( (negate = (*pattern == '!' || *pattern == '^')) )
+ ++pattern;
+
+ if (flags & FNM_CASEFOLD)
+ test = towlower(test);
+
+ /*
+ * A right bracket shall lose its special meaning and represent
+ * itself in a bracket expression if it occurs first in the list.
+ * -- POSIX.2 2.8.3.2
+ */
+ ok = 0;
+ origpat = pattern;
+ for (;;) {
+ if (*pattern == ']' && pattern > origpat) {
+ pattern++;
+ break;
+ } else if (*pattern == '\0') {
+ return (RANGE_ERROR);
+ } else if (*pattern == '/' && (flags & FNM_PATHNAME)) {
+ return (RANGE_NOMATCH);
+ } else if (*pattern == '\\' && !(flags & FNM_NOESCAPE))
+ pattern++;
+ pclen = mbrtowc(&c, pattern, MB_LEN_MAX, patmbs);
+ if (pclen == (size_t)-1 || pclen == (size_t)-2)
+ return (RANGE_NOMATCH);
+ pattern += pclen;
+
+ if (flags & FNM_CASEFOLD)
+ c = towlower(c);
+
+ if (*pattern == '-' && *(pattern + 1) != EOS &&
+ *(pattern + 1) != ']') {
+ if (*++pattern == '\\' && !(flags & FNM_NOESCAPE))
+ if (*pattern != EOS)
+ pattern++;
+ pclen = mbrtowc(&c2, pattern, MB_LEN_MAX, patmbs);
+ if (pclen == (size_t)-1 || pclen == (size_t)-2)
+ return (RANGE_NOMATCH);
+ pattern += pclen;
+ if (c2 == EOS)
+ return (RANGE_ERROR);
+
+ if (flags & FNM_CASEFOLD)
+ c2 = towlower(c2);
+
+ if (table->__collate_load_error ?
+ c <= test && test <= c2 :
+ __collate_range_cmp(table, c, test) <= 0
+ && __collate_range_cmp(table, test, c2) <= 0
+ )
+ ok = 1;
+ } else if (c == test)
+ ok = 1;
+ }
+
+ *newp = (char *)pattern;
+ return (ok == negate ? RANGE_NOMATCH : RANGE_MATCH);
+}
diff --git a/lib/libc/gen/fpclassify.3 b/lib/libc/gen/fpclassify.3
new file mode 100644
index 0000000..a547eeb
--- /dev/null
+++ b/lib/libc/gen/fpclassify.3
@@ -0,0 +1,133 @@
+.\" Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 26, 2005
+.Dt FPCLASSIFY 3
+.Os
+.Sh NAME
+.Nm fpclassify , isfinite , isinf , isnan , isnormal
+.Nd "classify a floating-point number"
+.Sh LIBRARY
+.Lb libm
+.Sh SYNOPSIS
+.In math.h
+.Ft int
+.Fn fpclassify "real-floating x"
+.Ft int
+.Fn isfinite "real-floating x"
+.Ft int
+.Fn isinf "real-floating x"
+.Ft int
+.Fn isnan "real-floating x"
+.Ft int
+.Fn isnormal "real-floating x"
+.Sh DESCRIPTION
+The
+.Fn fpclassify
+macro takes an argument of
+.Fa x
+and returns one of the following manifest constants.
+.Bl -tag -width ".Dv FP_SUBNORMAL"
+.It Dv FP_INFINITE
+Indicates that
+.Fa x
+is an infinite number.
+.It Dv FP_NAN
+Indicates that
+.Fa x
+is not a number (NaN).
+.It Dv FP_NORMAL
+Indicates that
+.Fa x
+is a normalized number.
+.It Dv FP_SUBNORMAL
+Indicates that
+.Fa x
+is a denormalized number.
+.It Dv FP_ZERO
+Indicates that
+.Fa x
+is zero (0 or \-0).
+.El
+.Pp
+The
+.Fn isfinite
+macro returns a non-zero value if and only if its argument has
+a finite (zero, subnormal, or normal) value.
+The
+.Fn isinf ,
+.Fn isnan ,
+and
+.Fn isnormal
+macros return non-zero if and only if
+.Fa x
+is an infinity, NaN,
+or a non-zero normalized number, respectively.
+.Pp
+The symbol
+.Fn isnanf
+is provided as an alias to
+.Fn isnan
+for compatibility, and its use is deprecated.
+Similarly,
+.Fn finite
+and
+.Fn finitef
+are deprecated versions of
+.Fn isfinite .
+.Sh SEE ALSO
+.Xr isgreater 3 ,
+.Xr math 3 ,
+.Xr signbit 3
+.Sh STANDARDS
+The
+.Fn fpclassify ,
+.Fn isfinite ,
+.Fn isinf ,
+.Fn isnan ,
+and
+.Fn isnormal
+macros conform to
+.St -isoC-99 .
+.Sh HISTORY
+The
+.Fn fpclassify ,
+.Fn isfinite ,
+.Fn isinf ,
+.Fn isnan ,
+and
+.Fn isnormal
+macros were added in
+.Fx 5.1 .
+.Bx 3
+introduced
+.Fn isinf
+and
+.Fn isnan
+functions, which accepted
+.Vt double
+arguments; these have been superseded by the macros
+described above.
diff --git a/lib/libc/gen/fpclassify.c b/lib/libc/gen/fpclassify.c
new file mode 100644
index 0000000..754a1df
--- /dev/null
+++ b/lib/libc/gen/fpclassify.c
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/endian.h>
+
+#include <math.h>
+#include <stdint.h>
+
+#include "fpmath.h"
+
+int
+__fpclassifyf(float f)
+{
+ union IEEEf2bits u;
+
+ u.f = f;
+ if (u.bits.exp == 0) {
+ if (u.bits.man == 0)
+ return (FP_ZERO);
+ return (FP_SUBNORMAL);
+ }
+ if (u.bits.exp == 255) {
+ if (u.bits.man == 0)
+ return (FP_INFINITE);
+ return (FP_NAN);
+ }
+ return (FP_NORMAL);
+}
+
+int
+__fpclassifyd(double d)
+{
+ union IEEEd2bits u;
+
+ u.d = d;
+ if (u.bits.exp == 0) {
+ if ((u.bits.manl | u.bits.manh) == 0)
+ return (FP_ZERO);
+ return (FP_SUBNORMAL);
+ }
+ if (u.bits.exp == 2047) {
+ if ((u.bits.manl | u.bits.manh) == 0)
+ return (FP_INFINITE);
+ return (FP_NAN);
+ }
+ return (FP_NORMAL);
+}
+
+int
+__fpclassifyl(long double e)
+{
+ union IEEEl2bits u;
+
+ u.e = e;
+ if (u.bits.exp == 0) {
+ if ((u.bits.manl | u.bits.manh) == 0)
+ return (FP_ZERO);
+ return (FP_SUBNORMAL);
+ }
+ mask_nbit_l(u); /* Mask normalization bit if applicable. */
+ if (u.bits.exp == 32767) {
+ if ((u.bits.manl | u.bits.manh) == 0)
+ return (FP_INFINITE);
+ return (FP_NAN);
+ }
+ return (FP_NORMAL);
+}
diff --git a/lib/libc/gen/frexp.3 b/lib/libc/gen/frexp.3
new file mode 100644
index 0000000..ba33d3d
--- /dev/null
+++ b/lib/libc/gen/frexp.3
@@ -0,0 +1,94 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)frexp.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd March 4, 2005
+.Dt FREXP 3
+.Os
+.Sh NAME
+.Nm frexp ,
+.Nm frexpf ,
+.Nm frexpl
+.Nd convert floating-point number to fractional and integral components
+.Sh LIBRARY
+.Lb libm
+.Sh SYNOPSIS
+.In math.h
+.Ft double
+.Fn frexp "double value" "int *exp"
+.Ft float
+.Fn frexpf "float value" "int *exp"
+.Ft long double
+.Fn frexpl "long double value" "int *exp"
+.Sh DESCRIPTION
+The
+.Fn frexp ,
+.Fn frexpf
+and
+.Fn frexpl
+functions break a floating-point number into a normalized
+fraction and an integral power of 2.
+They store the integer in the
+.Vt int
+object pointed to by
+.Fa exp .
+.Sh RETURN VALUES
+These functions return the value
+.Va x ,
+such that
+.Va x
+is a
+.Vt double
+with magnitude in the interval
+.Eo [ 1/2 , 1 Ec )
+or zero, and
+.Fa value
+equals
+.Va x
+times 2 raised to the power
+.Fa *exp .
+If
+.Fa value
+is zero, both parts of the result are zero.
+.Sh SEE ALSO
+.Xr ldexp 3 ,
+.Xr math 3 ,
+.Xr modf 3
+.Sh STANDARDS
+The
+.Fn frexp ,
+.Fn frexpf ,
+and
+.Fn frexpl
+functions conform to
+.St -isoC-99 .
diff --git a/lib/libc/gen/frexp.c b/lib/libc/gen/frexp.c
new file mode 100644
index 0000000..53483da
--- /dev/null
+++ b/lib/libc/gen/frexp.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <math.h>
+
+#include "fpmath.h"
+
+double
+frexp(double d, int *ex)
+{
+ union IEEEd2bits u;
+
+ u.d = d;
+ switch (u.bits.exp) {
+ case 0: /* 0 or subnormal */
+ if ((u.bits.manl | u.bits.manh) == 0) {
+ *ex = 0;
+ } else {
+ u.d *= 0x1.0p514;
+ *ex = u.bits.exp - 1536;
+ u.bits.exp = 1022;
+ }
+ break;
+ case 2047: /* infinity or NaN; value of *ex is unspecified */
+ break;
+ default: /* normal */
+ *ex = u.bits.exp - 1022;
+ u.bits.exp = 1022;
+ break;
+ }
+ return (u.d);
+}
diff --git a/lib/libc/gen/fstab.c b/lib/libc/gen/fstab.c
new file mode 100644
index 0000000..b2c28ad
--- /dev/null
+++ b/lib/libc/gen/fstab.c
@@ -0,0 +1,294 @@
+/*
+ * Copyright (c) 1980, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fstab.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fstab.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+static FILE *_fs_fp;
+static struct fstab _fs_fstab;
+static int LineNo = 0;
+static char *path_fstab;
+static char fstab_path[PATH_MAX];
+static int fsp_set = 0;
+
+static void error(int);
+static void fixfsfile(void);
+static int fstabscan(void);
+
+void
+setfstab(const char *file)
+{
+
+ if (file == NULL) {
+ path_fstab = _PATH_FSTAB;
+ } else {
+ strncpy(fstab_path, file, PATH_MAX);
+ fstab_path[PATH_MAX - 1] = '\0';
+ path_fstab = fstab_path;
+ }
+ fsp_set = 1;
+
+ return;
+}
+
+const char *
+getfstab (void)
+{
+
+ if (fsp_set)
+ return (path_fstab);
+ else
+ return (_PATH_FSTAB);
+}
+
+static void
+fixfsfile()
+{
+ static char buf[sizeof(_PATH_DEV) + MNAMELEN];
+ struct stat sb;
+ struct statfs sf;
+
+ if (_fs_fstab.fs_file != NULL && strcmp(_fs_fstab.fs_file, "/") != 0)
+ return;
+ if (statfs("/", &sf) != 0)
+ return;
+ if (sf.f_mntfromname[0] == '/')
+ buf[0] = '\0';
+ else
+ strcpy(buf, _PATH_DEV);
+ strcat(buf, sf.f_mntfromname);
+ if (stat(buf, &sb) != 0 ||
+ (!S_ISBLK(sb.st_mode) && !S_ISCHR(sb.st_mode)))
+ return;
+ _fs_fstab.fs_spec = buf;
+}
+
+static int
+fstabscan()
+{
+ char *cp, *p;
+#define MAXLINELENGTH 1024
+ static char line[MAXLINELENGTH];
+ char subline[MAXLINELENGTH];
+ int typexx;
+
+ for (;;) {
+
+ if (!(p = fgets(line, sizeof(line), _fs_fp)))
+ return(0);
+/* OLD_STYLE_FSTAB */
+ ++LineNo;
+ if (*line == '#' || *line == '\n')
+ continue;
+ if (!strpbrk(p, " \t")) {
+ _fs_fstab.fs_spec = strsep(&p, ":\n");
+ _fs_fstab.fs_file = strsep(&p, ":\n");
+ fixfsfile();
+ _fs_fstab.fs_type = strsep(&p, ":\n");
+ if (_fs_fstab.fs_type) {
+ if (!strcmp(_fs_fstab.fs_type, FSTAB_XX))
+ continue;
+ _fs_fstab.fs_mntops = _fs_fstab.fs_type;
+ _fs_fstab.fs_vfstype =
+ strcmp(_fs_fstab.fs_type, FSTAB_SW) ?
+ "ufs" : "swap";
+ if ((cp = strsep(&p, ":\n")) != NULL) {
+ _fs_fstab.fs_freq = atoi(cp);
+ if ((cp = strsep(&p, ":\n")) != NULL) {
+ _fs_fstab.fs_passno = atoi(cp);
+ return(1);
+ }
+ }
+ }
+ goto bad;
+ }
+/* OLD_STYLE_FSTAB */
+ while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
+ ;
+ _fs_fstab.fs_spec = cp;
+ if (!_fs_fstab.fs_spec || *_fs_fstab.fs_spec == '#')
+ continue;
+ while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
+ ;
+ _fs_fstab.fs_file = cp;
+ fixfsfile();
+ while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
+ ;
+ _fs_fstab.fs_vfstype = cp;
+ while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
+ ;
+ _fs_fstab.fs_mntops = cp;
+ if (_fs_fstab.fs_mntops == NULL)
+ goto bad;
+ _fs_fstab.fs_freq = 0;
+ _fs_fstab.fs_passno = 0;
+ while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
+ ;
+ if (cp != NULL) {
+ _fs_fstab.fs_freq = atoi(cp);
+ while ((cp = strsep(&p, " \t\n")) != NULL && *cp == '\0')
+ ;
+ if (cp != NULL)
+ _fs_fstab.fs_passno = atoi(cp);
+ }
+ strcpy(subline, _fs_fstab.fs_mntops);
+ p = subline;
+ for (typexx = 0, cp = strsep(&p, ","); cp;
+ cp = strsep(&p, ",")) {
+ if (strlen(cp) != 2)
+ continue;
+ if (!strcmp(cp, FSTAB_RW)) {
+ _fs_fstab.fs_type = FSTAB_RW;
+ break;
+ }
+ if (!strcmp(cp, FSTAB_RQ)) {
+ _fs_fstab.fs_type = FSTAB_RQ;
+ break;
+ }
+ if (!strcmp(cp, FSTAB_RO)) {
+ _fs_fstab.fs_type = FSTAB_RO;
+ break;
+ }
+ if (!strcmp(cp, FSTAB_SW)) {
+ _fs_fstab.fs_type = FSTAB_SW;
+ break;
+ }
+ if (!strcmp(cp, FSTAB_XX)) {
+ _fs_fstab.fs_type = FSTAB_XX;
+ typexx++;
+ break;
+ }
+ }
+ if (typexx)
+ continue;
+ if (cp != NULL)
+ return(1);
+
+bad: /* no way to distinguish between EOF and syntax error */
+ error(EFTYPE);
+ }
+ /* NOTREACHED */
+}
+
+struct fstab *
+getfsent()
+{
+ if ((!_fs_fp && !setfsent()) || !fstabscan())
+ return((struct fstab *)NULL);
+ return(&_fs_fstab);
+}
+
+struct fstab *
+getfsspec(name)
+ const char *name;
+{
+ if (setfsent())
+ while (fstabscan())
+ if (!strcmp(_fs_fstab.fs_spec, name))
+ return(&_fs_fstab);
+ return((struct fstab *)NULL);
+}
+
+struct fstab *
+getfsfile(name)
+ const char *name;
+{
+ if (setfsent())
+ while (fstabscan())
+ if (!strcmp(_fs_fstab.fs_file, name))
+ return(&_fs_fstab);
+ return((struct fstab *)NULL);
+}
+
+int
+setfsent()
+{
+ if (_fs_fp) {
+ rewind(_fs_fp);
+ LineNo = 0;
+ return(1);
+ }
+ if (fsp_set == 0) {
+ if (issetugid())
+ setfstab(NULL);
+ else
+ setfstab(getenv("PATH_FSTAB"));
+ }
+ if ((_fs_fp = fopen(path_fstab, "r")) != NULL) {
+ LineNo = 0;
+ return(1);
+ }
+ error(errno);
+ return(0);
+}
+
+void
+endfsent()
+{
+ if (_fs_fp) {
+ (void)fclose(_fs_fp);
+ _fs_fp = NULL;
+ }
+
+ fsp_set = 0;
+}
+
+static void
+error(err)
+ int err;
+{
+ char *p;
+ char num[30];
+
+ (void)_write(STDERR_FILENO, "fstab: ", 7);
+ (void)_write(STDERR_FILENO, path_fstab, strlen(path_fstab));
+ (void)_write(STDERR_FILENO, ":", 1);
+ sprintf(num, "%d: ", LineNo);
+ (void)_write(STDERR_FILENO, num, strlen(num));
+ p = strerror(err);
+ (void)_write(STDERR_FILENO, p, strlen(p));
+ (void)_write(STDERR_FILENO, "\n", 1);
+}
diff --git a/lib/libc/gen/ftok.3 b/lib/libc/gen/ftok.3
new file mode 100644
index 0000000..996b2da
--- /dev/null
+++ b/lib/libc/gen/ftok.3
@@ -0,0 +1,83 @@
+.\" Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.Dd July 9, 2009
+.Dt FTOK 3
+.Os
+.Sh NAME
+.Nm ftok
+.Nd create IPC identifier from path name
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/ipc.h
+.Ft key_t
+.Fn ftok "const char *path" "int id"
+.Sh DESCRIPTION
+The
+.Fn ftok
+function attempts to create a unique key suitable for use with the
+.Xr msgget 2 ,
+.Xr semget 2
+and
+.Xr shmget 2
+functions given the
+.Fa path
+of an existing file and a user-selectable
+.Fa id .
+.Pp
+The specified
+.Fa path
+must specify an existing file that is accessible to the calling process
+or the call will fail.
+Also, note that links to files will return the
+same key, given the same
+.Fa id .
+.Sh RETURN VALUES
+The
+.Fn ftok
+function will return -1 if
+.Fa path
+does not exist or if it cannot be accessed by the calling process.
+.Sh SEE ALSO
+.Xr semget 2 ,
+.Xr shmget 2 ,
+.Xr msgget 2
+.Sh HISTORY
+The
+.Fn ftok
+function originates with System V and is typically used by programs
+that use the System V IPC routines.
+.Sh AUTHORS
+.An Thorsten Lockert Aq tholo@sigmasoft.com
+.Sh BUGS
+The returned key is computed based on the device minor number and inode of the
+specified
+.Fa path
+in combination with the lower 8 bits of the given
+.Fa id .
+Thus it is quite possible for the routine to return duplicate keys.
diff --git a/lib/libc/gen/ftok.c b/lib/libc/gen/ftok.c
new file mode 100644
index 0000000..4269e37
--- /dev/null
+++ b/lib/libc/gen/ftok.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1994 SigmaSoft, Th. Lockert <tholo@sigmasoft.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ipc.h>
+
+key_t
+ftok(path, id)
+ const char *path;
+ int id;
+{
+ struct stat st;
+
+ if (stat(path, &st) < 0)
+ return (key_t)-1;
+
+ return (key_t) (id << 24 | (st.st_dev & 0xff) << 16 | (st.st_ino & 0xffff));
+}
diff --git a/lib/libc/gen/fts-compat.c b/lib/libc/gen/fts-compat.c
new file mode 100644
index 0000000..a6ddde4
--- /dev/null
+++ b/lib/libc/gen/fts-compat.c
@@ -0,0 +1,1242 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $OpenBSD: fts.c,v 1.22 1999/10/03 19:22:22 millert Exp $
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
+#endif /* LIBC_SCCS and not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "fts-compat.h"
+#include "un-namespace.h"
+
+FTSENT *__fts_children_44bsd(FTS *, int);
+int __fts_close_44bsd(FTS *);
+void *__fts_get_clientptr_44bsd(FTS *);
+FTS *__fts_get_stream_44bsd(FTSENT *);
+FTS *__fts_open_44bsd(char * const *, int,
+ int (*)(const FTSENT * const *, const FTSENT * const *));
+FTSENT *__fts_read_44bsd(FTS *);
+int __fts_set_44bsd(FTS *, FTSENT *, int);
+void __fts_set_clientptr_44bsd(FTS *, void *);
+
+static FTSENT *fts_alloc(FTS *, char *, int);
+static FTSENT *fts_build(FTS *, int);
+static void fts_lfree(FTSENT *);
+static void fts_load(FTS *, FTSENT *);
+static size_t fts_maxarglen(char * const *);
+static void fts_padjust(FTS *, FTSENT *);
+static int fts_palloc(FTS *, size_t);
+static FTSENT *fts_sort(FTS *, FTSENT *, int);
+static u_short fts_stat(FTS *, FTSENT *, int);
+static int fts_safe_changedir(FTS *, FTSENT *, int, char *);
+static int fts_ufslinks(FTS *, const FTSENT *);
+
+#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
+
+#define CLR(opt) (sp->fts_options &= ~(opt))
+#define ISSET(opt) (sp->fts_options & (opt))
+#define SET(opt) (sp->fts_options |= (opt))
+
+#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd))
+
+/* fts_build flags */
+#define BCHILD 1 /* fts_children */
+#define BNAMES 2 /* fts_children, names only */
+#define BREAD 3 /* fts_read */
+
+/*
+ * Internal representation of an FTS, including extra implementation
+ * details. The FTS returned from fts_open points to this structure's
+ * ftsp_fts member (and can be cast to an _fts_private as required)
+ */
+struct _fts_private {
+ FTS ftsp_fts;
+ struct statfs ftsp_statfs;
+ dev_t ftsp_dev;
+ int ftsp_linksreliable;
+};
+
+/*
+ * The "FTS_NOSTAT" option can avoid a lot of calls to stat(2) if it
+ * knows that a directory could not possibly have subdirectories. This
+ * is decided by looking at the link count: a subdirectory would
+ * increment its parent's link count by virtue of its own ".." entry.
+ * This assumption only holds for UFS-like filesystems that implement
+ * links and directories this way, so we must punt for others.
+ */
+
+static const char *ufslike_filesystems[] = {
+ "ufs",
+ "zfs",
+ "nfs",
+ "nfs4",
+ "ext2fs",
+ 0
+};
+
+FTS *
+__fts_open_44bsd(argv, options, compar)
+ char * const *argv;
+ int options;
+ int (*compar)(const FTSENT * const *, const FTSENT * const *);
+{
+ struct _fts_private *priv;
+ FTS *sp;
+ FTSENT *p, *root;
+ int nitems;
+ FTSENT *parent, *tmp;
+ int len;
+
+ /* Options check. */
+ if (options & ~FTS_OPTIONMASK) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Allocate/initialize the stream. */
+ if ((priv = malloc(sizeof(*priv))) == NULL)
+ return (NULL);
+ memset(priv, 0, sizeof(*priv));
+ sp = &priv->ftsp_fts;
+ sp->fts_compar = compar;
+ sp->fts_options = options;
+
+ /* Shush, GCC. */
+ tmp = NULL;
+
+ /* Logical walks turn on NOCHDIR; symbolic links are too hard. */
+ if (ISSET(FTS_LOGICAL))
+ SET(FTS_NOCHDIR);
+
+ /*
+ * Start out with 1K of path space, and enough, in any case,
+ * to hold the user's paths.
+ */
+ if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
+ goto mem1;
+
+ /* Allocate/initialize root's parent. */
+ if ((parent = fts_alloc(sp, "", 0)) == NULL)
+ goto mem2;
+ parent->fts_level = FTS_ROOTPARENTLEVEL;
+
+ /* Allocate/initialize root(s). */
+ for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
+ /* Don't allow zero-length paths. */
+ if ((len = strlen(*argv)) == 0) {
+ errno = ENOENT;
+ goto mem3;
+ }
+
+ p = fts_alloc(sp, *argv, len);
+ p->fts_level = FTS_ROOTLEVEL;
+ p->fts_parent = parent;
+ p->fts_accpath = p->fts_name;
+ p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
+
+ /* Command-line "." and ".." are real directories. */
+ if (p->fts_info == FTS_DOT)
+ p->fts_info = FTS_D;
+
+ /*
+ * If comparison routine supplied, traverse in sorted
+ * order; otherwise traverse in the order specified.
+ */
+ if (compar) {
+ p->fts_link = root;
+ root = p;
+ } else {
+ p->fts_link = NULL;
+ if (root == NULL)
+ tmp = root = p;
+ else {
+ tmp->fts_link = p;
+ tmp = p;
+ }
+ }
+ }
+ if (compar && nitems > 1)
+ root = fts_sort(sp, root, nitems);
+
+ /*
+ * Allocate a dummy pointer and make fts_read think that we've just
+ * finished the node before the root(s); set p->fts_info to FTS_INIT
+ * so that everything about the "current" node is ignored.
+ */
+ if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
+ goto mem3;
+ sp->fts_cur->fts_link = root;
+ sp->fts_cur->fts_info = FTS_INIT;
+
+ /*
+ * If using chdir(2), grab a file descriptor pointing to dot to ensure
+ * that we can get back here; this could be avoided for some paths,
+ * but almost certainly not worth the effort. Slashes, symbolic links,
+ * and ".." are all fairly nasty problems. Note, if we can't get the
+ * descriptor we run anyway, just more slowly.
+ */
+ if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = _open(".", O_RDONLY, 0)) < 0)
+ SET(FTS_NOCHDIR);
+
+ return (sp);
+
+mem3: fts_lfree(root);
+ free(parent);
+mem2: free(sp->fts_path);
+mem1: free(sp);
+ return (NULL);
+}
+
+static void
+fts_load(sp, p)
+ FTS *sp;
+ FTSENT *p;
+{
+ int len;
+ char *cp;
+
+ /*
+ * Load the stream structure for the next traversal. Since we don't
+ * actually enter the directory until after the preorder visit, set
+ * the fts_accpath field specially so the chdir gets done to the right
+ * place and the user can access the first node. From fts_open it's
+ * known that the path will fit.
+ */
+ len = p->fts_pathlen = p->fts_namelen;
+ memmove(sp->fts_path, p->fts_name, len + 1);
+ if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
+ len = strlen(++cp);
+ memmove(p->fts_name, cp, len + 1);
+ p->fts_namelen = len;
+ }
+ p->fts_accpath = p->fts_path = sp->fts_path;
+ sp->fts_dev = p->fts_dev;
+}
+
+int
+__fts_close_44bsd(sp)
+ FTS *sp;
+{
+ FTSENT *freep, *p;
+ int saved_errno;
+
+ /*
+ * This still works if we haven't read anything -- the dummy structure
+ * points to the root list, so we step through to the end of the root
+ * list which has a valid parent pointer.
+ */
+ if (sp->fts_cur) {
+ for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
+ freep = p;
+ p = p->fts_link != NULL ? p->fts_link : p->fts_parent;
+ free(freep);
+ }
+ free(p);
+ }
+
+ /* Free up child linked list, sort array, path buffer. */
+ if (sp->fts_child)
+ fts_lfree(sp->fts_child);
+ if (sp->fts_array)
+ free(sp->fts_array);
+ free(sp->fts_path);
+
+ /* Return to original directory, save errno if necessary. */
+ if (!ISSET(FTS_NOCHDIR)) {
+ saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
+ (void)_close(sp->fts_rfd);
+
+ /* Set errno and return. */
+ if (saved_errno != 0) {
+ /* Free up the stream pointer. */
+ free(sp);
+ errno = saved_errno;
+ return (-1);
+ }
+ }
+
+ /* Free up the stream pointer. */
+ free(sp);
+ return (0);
+}
+
+/*
+ * Special case of "/" at the end of the path so that slashes aren't
+ * appended which would cause paths to be written as "....//foo".
+ */
+#define NAPPEND(p) \
+ (p->fts_path[p->fts_pathlen - 1] == '/' \
+ ? p->fts_pathlen - 1 : p->fts_pathlen)
+
+FTSENT *
+__fts_read_44bsd(sp)
+ FTS *sp;
+{
+ FTSENT *p, *tmp;
+ int instr;
+ char *t;
+ int saved_errno;
+
+ /* If finished or unrecoverable error, return NULL. */
+ if (sp->fts_cur == NULL || ISSET(FTS_STOP))
+ return (NULL);
+
+ /* Set current node pointer. */
+ p = sp->fts_cur;
+
+ /* Save and zero out user instructions. */
+ instr = p->fts_instr;
+ p->fts_instr = FTS_NOINSTR;
+
+ /* Any type of file may be re-visited; re-stat and re-turn. */
+ if (instr == FTS_AGAIN) {
+ p->fts_info = fts_stat(sp, p, 0);
+ return (p);
+ }
+
+ /*
+ * Following a symlink -- SLNONE test allows application to see
+ * SLNONE and recover. If indirecting through a symlink, have
+ * keep a pointer to current location. If unable to get that
+ * pointer, follow fails.
+ */
+ if (instr == FTS_FOLLOW &&
+ (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
+ p->fts_info = fts_stat(sp, p, 1);
+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+ if ((p->fts_symfd = _open(".", O_RDONLY, 0)) < 0) {
+ p->fts_errno = errno;
+ p->fts_info = FTS_ERR;
+ } else
+ p->fts_flags |= FTS_SYMFOLLOW;
+ }
+ return (p);
+ }
+
+ /* Directory in pre-order. */
+ if (p->fts_info == FTS_D) {
+ /* If skipped or crossed mount point, do post-order visit. */
+ if (instr == FTS_SKIP ||
+ (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
+ if (p->fts_flags & FTS_SYMFOLLOW)
+ (void)_close(p->fts_symfd);
+ if (sp->fts_child) {
+ fts_lfree(sp->fts_child);
+ sp->fts_child = NULL;
+ }
+ p->fts_info = FTS_DP;
+ return (p);
+ }
+
+ /* Rebuild if only read the names and now traversing. */
+ if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {
+ CLR(FTS_NAMEONLY);
+ fts_lfree(sp->fts_child);
+ sp->fts_child = NULL;
+ }
+
+ /*
+ * Cd to the subdirectory.
+ *
+ * If have already read and now fail to chdir, whack the list
+ * to make the names come out right, and set the parent errno
+ * so the application will eventually get an error condition.
+ * Set the FTS_DONTCHDIR flag so that when we logically change
+ * directories back to the parent we don't do a chdir.
+ *
+ * If haven't read do so. If the read fails, fts_build sets
+ * FTS_STOP or the fts_info field of the node.
+ */
+ if (sp->fts_child != NULL) {
+ if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
+ p->fts_errno = errno;
+ p->fts_flags |= FTS_DONTCHDIR;
+ for (p = sp->fts_child; p != NULL;
+ p = p->fts_link)
+ p->fts_accpath =
+ p->fts_parent->fts_accpath;
+ }
+ } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
+ if (ISSET(FTS_STOP))
+ return (NULL);
+ return (p);
+ }
+ p = sp->fts_child;
+ sp->fts_child = NULL;
+ goto name;
+ }
+
+ /* Move to the next node on this level. */
+next: tmp = p;
+ if ((p = p->fts_link) != NULL) {
+ free(tmp);
+
+ /*
+ * If reached the top, return to the original directory (or
+ * the root of the tree), and load the paths for the next root.
+ */
+ if (p->fts_level == FTS_ROOTLEVEL) {
+ if (FCHDIR(sp, sp->fts_rfd)) {
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ fts_load(sp, p);
+ return (sp->fts_cur = p);
+ }
+
+ /*
+ * User may have called fts_set on the node. If skipped,
+ * ignore. If followed, get a file descriptor so we can
+ * get back if necessary.
+ */
+ if (p->fts_instr == FTS_SKIP)
+ goto next;
+ if (p->fts_instr == FTS_FOLLOW) {
+ p->fts_info = fts_stat(sp, p, 1);
+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+ if ((p->fts_symfd =
+ _open(".", O_RDONLY, 0)) < 0) {
+ p->fts_errno = errno;
+ p->fts_info = FTS_ERR;
+ } else
+ p->fts_flags |= FTS_SYMFOLLOW;
+ }
+ p->fts_instr = FTS_NOINSTR;
+ }
+
+name: t = sp->fts_path + NAPPEND(p->fts_parent);
+ *t++ = '/';
+ memmove(t, p->fts_name, p->fts_namelen + 1);
+ return (sp->fts_cur = p);
+ }
+
+ /* Move up to the parent node. */
+ p = tmp->fts_parent;
+ free(tmp);
+
+ if (p->fts_level == FTS_ROOTPARENTLEVEL) {
+ /*
+ * Done; free everything up and set errno to 0 so the user
+ * can distinguish between error and EOF.
+ */
+ free(p);
+ errno = 0;
+ return (sp->fts_cur = NULL);
+ }
+
+ /* NUL terminate the pathname. */
+ sp->fts_path[p->fts_pathlen] = '\0';
+
+ /*
+ * Return to the parent directory. If at a root node or came through
+ * a symlink, go back through the file descriptor. Otherwise, cd up
+ * one directory.
+ */
+ if (p->fts_level == FTS_ROOTLEVEL) {
+ if (FCHDIR(sp, sp->fts_rfd)) {
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ } else if (p->fts_flags & FTS_SYMFOLLOW) {
+ if (FCHDIR(sp, p->fts_symfd)) {
+ saved_errno = errno;
+ (void)_close(p->fts_symfd);
+ errno = saved_errno;
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ (void)_close(p->fts_symfd);
+ } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
+ fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
+ return (sp->fts_cur = p);
+}
+
+/*
+ * Fts_set takes the stream as an argument although it's not used in this
+ * implementation; it would be necessary if anyone wanted to add global
+ * semantics to fts using fts_set. An error return is allowed for similar
+ * reasons.
+ */
+/* ARGSUSED */
+int
+__fts_set_44bsd(sp, p, instr)
+ FTS *sp;
+ FTSENT *p;
+ int instr;
+{
+ if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
+ instr != FTS_NOINSTR && instr != FTS_SKIP) {
+ errno = EINVAL;
+ return (1);
+ }
+ p->fts_instr = instr;
+ return (0);
+}
+
+FTSENT *
+__fts_children_44bsd(sp, instr)
+ FTS *sp;
+ int instr;
+{
+ FTSENT *p;
+ int fd;
+
+ if (instr != 0 && instr != FTS_NAMEONLY) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Set current node pointer. */
+ p = sp->fts_cur;
+
+ /*
+ * Errno set to 0 so user can distinguish empty directory from
+ * an error.
+ */
+ errno = 0;
+
+ /* Fatal errors stop here. */
+ if (ISSET(FTS_STOP))
+ return (NULL);
+
+ /* Return logical hierarchy of user's arguments. */
+ if (p->fts_info == FTS_INIT)
+ return (p->fts_link);
+
+ /*
+ * If not a directory being visited in pre-order, stop here. Could
+ * allow FTS_DNR, assuming the user has fixed the problem, but the
+ * same effect is available with FTS_AGAIN.
+ */
+ if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
+ return (NULL);
+
+ /* Free up any previous child list. */
+ if (sp->fts_child != NULL)
+ fts_lfree(sp->fts_child);
+
+ if (instr == FTS_NAMEONLY) {
+ SET(FTS_NAMEONLY);
+ instr = BNAMES;
+ } else
+ instr = BCHILD;
+
+ /*
+ * If using chdir on a relative path and called BEFORE fts_read does
+ * its chdir to the root of a traversal, we can lose -- we need to
+ * chdir into the subdirectory, and we don't know where the current
+ * directory is, so we can't get back so that the upcoming chdir by
+ * fts_read will work.
+ */
+ if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
+ ISSET(FTS_NOCHDIR))
+ return (sp->fts_child = fts_build(sp, instr));
+
+ if ((fd = _open(".", O_RDONLY, 0)) < 0)
+ return (NULL);
+ sp->fts_child = fts_build(sp, instr);
+ if (fchdir(fd))
+ return (NULL);
+ (void)_close(fd);
+ return (sp->fts_child);
+}
+
+#ifndef fts_get_clientptr
+#error "fts_get_clientptr not defined"
+#endif
+
+void *
+(__fts_get_clientptr_44bsd)(FTS *sp)
+{
+
+ return (fts_get_clientptr(sp));
+}
+
+#ifndef fts_get_stream
+#error "fts_get_stream not defined"
+#endif
+
+FTS *
+(__fts_get_stream_44bsd)(FTSENT *p)
+{
+ return (fts_get_stream(p));
+}
+
+void
+__fts_set_clientptr_44bsd(FTS *sp, void *clientptr)
+{
+
+ sp->fts_clientptr = clientptr;
+}
+
+/*
+ * This is the tricky part -- do not casually change *anything* in here. The
+ * idea is to build the linked list of entries that are used by fts_children
+ * and fts_read. There are lots of special cases.
+ *
+ * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is
+ * set and it's a physical walk (so that symbolic links can't be directories),
+ * we can do things quickly. First, if it's a 4.4BSD file system, the type
+ * of the file is in the directory entry. Otherwise, we assume that the number
+ * of subdirectories in a node is equal to the number of links to the parent.
+ * The former skips all stat calls. The latter skips stat calls in any leaf
+ * directories and for any files after the subdirectories in the directory have
+ * been found, cutting the stat calls by about 2/3.
+ */
+static FTSENT *
+fts_build(sp, type)
+ FTS *sp;
+ int type;
+{
+ struct dirent *dp;
+ FTSENT *p, *head;
+ int nitems;
+ FTSENT *cur, *tail;
+ DIR *dirp;
+ void *oldaddr;
+ size_t dnamlen;
+ int cderrno, descend, len, level, maxlen, nlinks, oflag, saved_errno,
+ nostat, doadjust;
+ char *cp;
+
+ /* Set current node pointer. */
+ cur = sp->fts_cur;
+
+ /*
+ * Open the directory for reading. If this fails, we're done.
+ * If being called from fts_read, set the fts_info field.
+ */
+#ifdef FTS_WHITEOUT
+ if (ISSET(FTS_WHITEOUT))
+ oflag = DTF_NODUP | DTF_REWIND;
+ else
+ oflag = DTF_HIDEW | DTF_NODUP | DTF_REWIND;
+#else
+#define __opendir2(path, flag) opendir(path)
+#endif
+ if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
+ if (type == BREAD) {
+ cur->fts_info = FTS_DNR;
+ cur->fts_errno = errno;
+ }
+ return (NULL);
+ }
+
+ /*
+ * Nlinks is the number of possible entries of type directory in the
+ * directory if we're cheating on stat calls, 0 if we're not doing
+ * any stat calls at all, -1 if we're doing stats on everything.
+ */
+ if (type == BNAMES) {
+ nlinks = 0;
+ /* Be quiet about nostat, GCC. */
+ nostat = 0;
+ } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
+ if (fts_ufslinks(sp, cur))
+ nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
+ else
+ nlinks = -1;
+ nostat = 1;
+ } else {
+ nlinks = -1;
+ nostat = 0;
+ }
+
+#ifdef notdef
+ (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
+ (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
+ ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
+#endif
+ /*
+ * If we're going to need to stat anything or we want to descend
+ * and stay in the directory, chdir. If this fails we keep going,
+ * but set a flag so we don't chdir after the post-order visit.
+ * We won't be able to stat anything, but we can still return the
+ * names themselves. Note, that since fts_read won't be able to
+ * chdir into the directory, it will have to return different path
+ * names than before, i.e. "a/b" instead of "b". Since the node
+ * has already been visited in pre-order, have to wait until the
+ * post-order visit to return the error. There is a special case
+ * here, if there was nothing to stat then it's not an error to
+ * not be able to stat. This is all fairly nasty. If a program
+ * needed sorted entries or stat information, they had better be
+ * checking FTS_NS on the returned nodes.
+ */
+ cderrno = 0;
+ if (nlinks || type == BREAD) {
+ if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
+ if (nlinks && type == BREAD)
+ cur->fts_errno = errno;
+ cur->fts_flags |= FTS_DONTCHDIR;
+ descend = 0;
+ cderrno = errno;
+ } else
+ descend = 1;
+ } else
+ descend = 0;
+
+ /*
+ * Figure out the max file name length that can be stored in the
+ * current path -- the inner loop allocates more path as necessary.
+ * We really wouldn't have to do the maxlen calculations here, we
+ * could do them in fts_read before returning the path, but it's a
+ * lot easier here since the length is part of the dirent structure.
+ *
+ * If not changing directories set a pointer so that can just append
+ * each new name into the path.
+ */
+ len = NAPPEND(cur);
+ if (ISSET(FTS_NOCHDIR)) {
+ cp = sp->fts_path + len;
+ *cp++ = '/';
+ } else {
+ /* GCC, you're too verbose. */
+ cp = NULL;
+ }
+ len++;
+ maxlen = sp->fts_pathlen - len;
+
+ level = cur->fts_level + 1;
+
+ /* Read the directory, attaching each entry to the `link' pointer. */
+ doadjust = 0;
+ for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) {
+ dnamlen = dp->d_namlen;
+ if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+ continue;
+
+ if ((p = fts_alloc(sp, dp->d_name, (int)dnamlen)) == NULL)
+ goto mem1;
+ if (dnamlen >= maxlen) { /* include space for NUL */
+ oldaddr = sp->fts_path;
+ if (fts_palloc(sp, dnamlen + len + 1)) {
+ /*
+ * No more memory for path or structures. Save
+ * errno, free up the current structure and the
+ * structures already allocated.
+ */
+mem1: saved_errno = errno;
+ if (p)
+ free(p);
+ fts_lfree(head);
+ (void)closedir(dirp);
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ errno = saved_errno;
+ return (NULL);
+ }
+ /* Did realloc() change the pointer? */
+ if (oldaddr != sp->fts_path) {
+ doadjust = 1;
+ if (ISSET(FTS_NOCHDIR))
+ cp = sp->fts_path + len;
+ }
+ maxlen = sp->fts_pathlen - len;
+ }
+
+ if (len + dnamlen >= USHRT_MAX) {
+ /*
+ * In an FTSENT, fts_pathlen is a u_short so it is
+ * possible to wraparound here. If we do, free up
+ * the current structure and the structures already
+ * allocated, then error out with ENAMETOOLONG.
+ */
+ free(p);
+ fts_lfree(head);
+ (void)closedir(dirp);
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ p->fts_level = level;
+ p->fts_parent = sp->fts_cur;
+ p->fts_pathlen = len + dnamlen;
+
+#ifdef FTS_WHITEOUT
+ if (dp->d_type == DT_WHT)
+ p->fts_flags |= FTS_ISW;
+#endif
+
+ if (cderrno) {
+ if (nlinks) {
+ p->fts_info = FTS_NS;
+ p->fts_errno = cderrno;
+ } else
+ p->fts_info = FTS_NSOK;
+ p->fts_accpath = cur->fts_accpath;
+ } else if (nlinks == 0
+#ifdef DT_DIR
+ || (nostat &&
+ dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
+#endif
+ ) {
+ p->fts_accpath =
+ ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
+ p->fts_info = FTS_NSOK;
+ } else {
+ /* Build a file name for fts_stat to stat. */
+ if (ISSET(FTS_NOCHDIR)) {
+ p->fts_accpath = p->fts_path;
+ memmove(cp, p->fts_name, p->fts_namelen + 1);
+ } else
+ p->fts_accpath = p->fts_name;
+ /* Stat it. */
+ p->fts_info = fts_stat(sp, p, 0);
+
+ /* Decrement link count if applicable. */
+ if (nlinks > 0 && (p->fts_info == FTS_D ||
+ p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
+ --nlinks;
+ }
+
+ /* We walk in directory order so "ls -f" doesn't get upset. */
+ p->fts_link = NULL;
+ if (head == NULL)
+ head = tail = p;
+ else {
+ tail->fts_link = p;
+ tail = p;
+ }
+ ++nitems;
+ }
+ if (dirp)
+ (void)closedir(dirp);
+
+ /*
+ * If realloc() changed the address of the path, adjust the
+ * addresses for the rest of the tree and the dir list.
+ */
+ if (doadjust)
+ fts_padjust(sp, head);
+
+ /*
+ * If not changing directories, reset the path back to original
+ * state.
+ */
+ if (ISSET(FTS_NOCHDIR)) {
+ if (len == sp->fts_pathlen || nitems == 0)
+ --cp;
+ *cp = '\0';
+ }
+
+ /*
+ * If descended after called from fts_children or after called from
+ * fts_read and nothing found, get back. At the root level we use
+ * the saved fd; if one of fts_open()'s arguments is a relative path
+ * to an empty directory, we wind up here with no other way back. If
+ * can't get back, we're done.
+ */
+ if (descend && (type == BCHILD || !nitems) &&
+ (cur->fts_level == FTS_ROOTLEVEL ?
+ FCHDIR(sp, sp->fts_rfd) :
+ fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ return (NULL);
+ }
+
+ /* If didn't find anything, return NULL. */
+ if (!nitems) {
+ if (type == BREAD)
+ cur->fts_info = FTS_DP;
+ return (NULL);
+ }
+
+ /* Sort the entries. */
+ if (sp->fts_compar && nitems > 1)
+ head = fts_sort(sp, head, nitems);
+ return (head);
+}
+
+static u_short
+fts_stat(sp, p, follow)
+ FTS *sp;
+ FTSENT *p;
+ int follow;
+{
+ FTSENT *t;
+ dev_t dev;
+ ino_t ino;
+ struct stat *sbp, sb;
+ int saved_errno;
+
+ /* If user needs stat info, stat buffer already allocated. */
+ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
+
+#ifdef FTS_WHITEOUT
+ /* Check for whiteout. */
+ if (p->fts_flags & FTS_ISW) {
+ if (sbp != &sb) {
+ memset(sbp, '\0', sizeof(*sbp));
+ sbp->st_mode = S_IFWHT;
+ }
+ return (FTS_W);
+ }
+#endif
+
+ /*
+ * If doing a logical walk, or application requested FTS_FOLLOW, do
+ * a stat(2). If that fails, check for a non-existent symlink. If
+ * fail, set the errno from the stat call.
+ */
+ if (ISSET(FTS_LOGICAL) || follow) {
+ if (stat(p->fts_accpath, sbp)) {
+ saved_errno = errno;
+ if (!lstat(p->fts_accpath, sbp)) {
+ errno = 0;
+ return (FTS_SLNONE);
+ }
+ p->fts_errno = saved_errno;
+ goto err;
+ }
+ } else if (lstat(p->fts_accpath, sbp)) {
+ p->fts_errno = errno;
+err: memset(sbp, 0, sizeof(struct stat));
+ return (FTS_NS);
+ }
+
+ if (S_ISDIR(sbp->st_mode)) {
+ /*
+ * Set the device/inode. Used to find cycles and check for
+ * crossing mount points. Also remember the link count, used
+ * in fts_build to limit the number of stat calls. It is
+ * understood that these fields are only referenced if fts_info
+ * is set to FTS_D.
+ */
+ dev = p->fts_dev = sbp->st_dev;
+ ino = p->fts_ino = sbp->st_ino;
+ p->fts_nlink = sbp->st_nlink;
+
+ if (ISDOT(p->fts_name))
+ return (FTS_DOT);
+
+ /*
+ * Cycle detection is done by brute force when the directory
+ * is first encountered. If the tree gets deep enough or the
+ * number of symbolic links to directories is high enough,
+ * something faster might be worthwhile.
+ */
+ for (t = p->fts_parent;
+ t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
+ if (ino == t->fts_ino && dev == t->fts_dev) {
+ p->fts_cycle = t;
+ return (FTS_DC);
+ }
+ return (FTS_D);
+ }
+ if (S_ISLNK(sbp->st_mode))
+ return (FTS_SL);
+ if (S_ISREG(sbp->st_mode))
+ return (FTS_F);
+ return (FTS_DEFAULT);
+}
+
+/*
+ * The comparison function takes pointers to pointers to FTSENT structures.
+ * Qsort wants a comparison function that takes pointers to void.
+ * (Both with appropriate levels of const-poisoning, of course!)
+ * Use a trampoline function to deal with the difference.
+ */
+static int
+fts_compar(const void *a, const void *b)
+{
+ FTS *parent;
+
+ parent = (*(const FTSENT * const *)a)->fts_fts;
+ return (*parent->fts_compar)(a, b);
+}
+
+static FTSENT *
+fts_sort(sp, head, nitems)
+ FTS *sp;
+ FTSENT *head;
+ int nitems;
+{
+ FTSENT **ap, *p;
+
+ /*
+ * Construct an array of pointers to the structures and call qsort(3).
+ * Reassemble the array in the order returned by qsort. If unable to
+ * sort for memory reasons, return the directory entries in their
+ * current order. Allocate enough space for the current needs plus
+ * 40 so don't realloc one entry at a time.
+ */
+ if (nitems > sp->fts_nitems) {
+ sp->fts_nitems = nitems + 40;
+ if ((sp->fts_array = reallocf(sp->fts_array,
+ sp->fts_nitems * sizeof(FTSENT *))) == NULL) {
+ sp->fts_nitems = 0;
+ return (head);
+ }
+ }
+ for (ap = sp->fts_array, p = head; p; p = p->fts_link)
+ *ap++ = p;
+ qsort(sp->fts_array, nitems, sizeof(FTSENT *), fts_compar);
+ for (head = *(ap = sp->fts_array); --nitems; ++ap)
+ ap[0]->fts_link = ap[1];
+ ap[0]->fts_link = NULL;
+ return (head);
+}
+
+static FTSENT *
+fts_alloc(sp, name, namelen)
+ FTS *sp;
+ char *name;
+ int namelen;
+{
+ FTSENT *p;
+ size_t len;
+
+ struct ftsent_withstat {
+ FTSENT ent;
+ struct stat statbuf;
+ };
+
+ /*
+ * The file name is a variable length array and no stat structure is
+ * necessary if the user has set the nostat bit. Allocate the FTSENT
+ * structure, the file name and the stat structure in one chunk, but
+ * be careful that the stat structure is reasonably aligned.
+ */
+ if (ISSET(FTS_NOSTAT))
+ len = sizeof(FTSENT) + namelen + 1;
+ else
+ len = sizeof(struct ftsent_withstat) + namelen + 1;
+
+ if ((p = malloc(len)) == NULL)
+ return (NULL);
+
+ if (ISSET(FTS_NOSTAT)) {
+ p->fts_name = (char *)(p + 1);
+ p->fts_statp = NULL;
+ } else {
+ p->fts_name = (char *)((struct ftsent_withstat *)p + 1);
+ p->fts_statp = &((struct ftsent_withstat *)p)->statbuf;
+ }
+
+ /* Copy the name and guarantee NUL termination. */
+ memcpy(p->fts_name, name, namelen);
+ p->fts_name[namelen] = '\0';
+ p->fts_namelen = namelen;
+ p->fts_path = sp->fts_path;
+ p->fts_errno = 0;
+ p->fts_flags = 0;
+ p->fts_instr = FTS_NOINSTR;
+ p->fts_number = 0;
+ p->fts_pointer = NULL;
+ p->fts_fts = sp;
+ return (p);
+}
+
+static void
+fts_lfree(head)
+ FTSENT *head;
+{
+ FTSENT *p;
+
+ /* Free a linked list of structures. */
+ while ((p = head)) {
+ head = head->fts_link;
+ free(p);
+ }
+}
+
+/*
+ * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
+ * Most systems will allow creation of paths much longer than MAXPATHLEN, even
+ * though the kernel won't resolve them. Add the size (not just what's needed)
+ * plus 256 bytes so don't realloc the path 2 bytes at a time.
+ */
+static int
+fts_palloc(sp, more)
+ FTS *sp;
+ size_t more;
+{
+
+ sp->fts_pathlen += more + 256;
+ /*
+ * Check for possible wraparound. In an FTS, fts_pathlen is
+ * a signed int but in an FTSENT it is an unsigned short.
+ * We limit fts_pathlen to USHRT_MAX to be safe in both cases.
+ */
+ if (sp->fts_pathlen < 0 || sp->fts_pathlen >= USHRT_MAX) {
+ if (sp->fts_path)
+ free(sp->fts_path);
+ sp->fts_path = NULL;
+ errno = ENAMETOOLONG;
+ return (1);
+ }
+ sp->fts_path = reallocf(sp->fts_path, sp->fts_pathlen);
+ return (sp->fts_path == NULL);
+}
+
+/*
+ * When the path is realloc'd, have to fix all of the pointers in structures
+ * already returned.
+ */
+static void
+fts_padjust(sp, head)
+ FTS *sp;
+ FTSENT *head;
+{
+ FTSENT *p;
+ char *addr = sp->fts_path;
+
+#define ADJUST(p) do { \
+ if ((p)->fts_accpath != (p)->fts_name) { \
+ (p)->fts_accpath = \
+ (char *)addr + ((p)->fts_accpath - (p)->fts_path); \
+ } \
+ (p)->fts_path = addr; \
+} while (0)
+ /* Adjust the current set of children. */
+ for (p = sp->fts_child; p; p = p->fts_link)
+ ADJUST(p);
+
+ /* Adjust the rest of the tree, including the current level. */
+ for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
+ ADJUST(p);
+ p = p->fts_link ? p->fts_link : p->fts_parent;
+ }
+}
+
+static size_t
+fts_maxarglen(argv)
+ char * const *argv;
+{
+ size_t len, max;
+
+ for (max = 0; *argv; ++argv)
+ if ((len = strlen(*argv)) > max)
+ max = len;
+ return (max + 1);
+}
+
+/*
+ * Change to dir specified by fd or p->fts_accpath without getting
+ * tricked by someone changing the world out from underneath us.
+ * Assumes p->fts_dev and p->fts_ino are filled in.
+ */
+static int
+fts_safe_changedir(sp, p, fd, path)
+ FTS *sp;
+ FTSENT *p;
+ int fd;
+ char *path;
+{
+ int ret, oerrno, newfd;
+ struct stat sb;
+
+ newfd = fd;
+ if (ISSET(FTS_NOCHDIR))
+ return (0);
+ if (fd < 0 && (newfd = _open(path, O_RDONLY, 0)) < 0)
+ return (-1);
+ if (_fstat(newfd, &sb)) {
+ ret = -1;
+ goto bail;
+ }
+ if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) {
+ errno = ENOENT; /* disinformation */
+ ret = -1;
+ goto bail;
+ }
+ ret = fchdir(newfd);
+bail:
+ oerrno = errno;
+ if (fd < 0)
+ (void)_close(newfd);
+ errno = oerrno;
+ return (ret);
+}
+
+/*
+ * Check if the filesystem for "ent" has UFS-style links.
+ */
+static int
+fts_ufslinks(FTS *sp, const FTSENT *ent)
+{
+ struct _fts_private *priv;
+ const char **cpp;
+
+ priv = (struct _fts_private *)sp;
+ /*
+ * If this node's device is different from the previous, grab
+ * the filesystem information, and decide on the reliability
+ * of the link information from this filesystem for stat(2)
+ * avoidance.
+ */
+ if (priv->ftsp_dev != ent->fts_dev) {
+ if (statfs(ent->fts_path, &priv->ftsp_statfs) != -1) {
+ priv->ftsp_dev = ent->fts_dev;
+ priv->ftsp_linksreliable = 0;
+ for (cpp = ufslike_filesystems; *cpp; cpp++) {
+ if (strcmp(priv->ftsp_statfs.f_fstypename,
+ *cpp) == 0) {
+ priv->ftsp_linksreliable = 1;
+ break;
+ }
+ }
+ } else {
+ priv->ftsp_linksreliable = 0;
+ }
+ }
+ return (priv->ftsp_linksreliable);
+}
+
+__sym_compat(fts_open, __fts_open_44bsd, FBSD_1.0);
+__sym_compat(fts_close, __fts_close_44bsd, FBSD_1.0);
+__sym_compat(fts_read, __fts_read_44bsd, FBSD_1.0);
+__sym_compat(fts_set, __fts_set_44bsd, FBSD_1.0);
+__sym_compat(fts_children, __fts_children_44bsd, FBSD_1.0);
+__sym_compat(fts_get_clientptr, __fts_get_clientptr_44bsd, FBSD_1.0);
+__sym_compat(fts_get_stream, __fts_get_stream_44bsd, FBSD_1.0);
+__sym_compat(fts_set_clientptr, __fts_set_clientptr_44bsd, FBSD_1.0);
diff --git a/lib/libc/gen/fts-compat.h b/lib/libc/gen/fts-compat.h
new file mode 100644
index 0000000..dfdd53b
--- /dev/null
+++ b/lib/libc/gen/fts-compat.h
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fts.h 8.3 (Berkeley) 8/14/94
+ * $FreeBSD$
+ */
+
+#ifndef _FTS_H_
+#define _FTS_H_
+
+typedef struct {
+ struct _ftsent *fts_cur; /* current node */
+ struct _ftsent *fts_child; /* linked list of children */
+ struct _ftsent **fts_array; /* sort array */
+ dev_t fts_dev; /* starting device # */
+ char *fts_path; /* path for this descent */
+ int fts_rfd; /* fd for root */
+ int fts_pathlen; /* sizeof(path) */
+ int fts_nitems; /* elements in the sort array */
+ int (*fts_compar) /* compare function */
+ (const struct _ftsent * const *, const struct _ftsent * const *);
+
+#define FTS_COMFOLLOW 0x001 /* follow command line symlinks */
+#define FTS_LOGICAL 0x002 /* logical walk */
+#define FTS_NOCHDIR 0x004 /* don't change directories */
+#define FTS_NOSTAT 0x008 /* don't get stat info */
+#define FTS_PHYSICAL 0x010 /* physical walk */
+#define FTS_SEEDOT 0x020 /* return dot and dot-dot */
+#define FTS_XDEV 0x040 /* don't cross devices */
+#define FTS_WHITEOUT 0x080 /* return whiteout information */
+#define FTS_OPTIONMASK 0x0ff /* valid user option mask */
+
+#define FTS_NAMEONLY 0x100 /* (private) child names only */
+#define FTS_STOP 0x200 /* (private) unrecoverable error */
+ int fts_options; /* fts_open options, global flags */
+ void *fts_clientptr; /* thunk for sort function */
+} FTS;
+
+typedef struct _ftsent {
+ struct _ftsent *fts_cycle; /* cycle node */
+ struct _ftsent *fts_parent; /* parent directory */
+ struct _ftsent *fts_link; /* next file in directory */
+ union {
+ struct {
+ long __fts_number; /* local numeric value */
+ void *__fts_pointer; /* local address value */
+ } __struct_ftsent;
+ int64_t __fts_bignum;
+ } __union_ftsent;
+#define fts_number __union_ftsent.__struct_ftsent.__fts_number
+#define fts_pointer __union_ftsent.__struct_ftsent.__fts_pointer
+#define fts_bignum __union_ftsent.__fts_bignum
+ char *fts_accpath; /* access path */
+ char *fts_path; /* root path */
+ int fts_errno; /* errno for this node */
+ int fts_symfd; /* fd for symlink */
+ u_short fts_pathlen; /* strlen(fts_path) */
+ u_short fts_namelen; /* strlen(fts_name) */
+
+ ino_t fts_ino; /* inode */
+ dev_t fts_dev; /* device */
+ nlink_t fts_nlink; /* link count */
+
+#define FTS_ROOTPARENTLEVEL -1
+#define FTS_ROOTLEVEL 0
+ short fts_level; /* depth (-1 to N) */
+
+#define FTS_D 1 /* preorder directory */
+#define FTS_DC 2 /* directory that causes cycles */
+#define FTS_DEFAULT 3 /* none of the above */
+#define FTS_DNR 4 /* unreadable directory */
+#define FTS_DOT 5 /* dot or dot-dot */
+#define FTS_DP 6 /* postorder directory */
+#define FTS_ERR 7 /* error; errno is set */
+#define FTS_F 8 /* regular file */
+#define FTS_INIT 9 /* initialized only */
+#define FTS_NS 10 /* stat(2) failed */
+#define FTS_NSOK 11 /* no stat(2) requested */
+#define FTS_SL 12 /* symbolic link */
+#define FTS_SLNONE 13 /* symbolic link without target */
+#define FTS_W 14 /* whiteout object */
+ u_short fts_info; /* user flags for FTSENT structure */
+
+#define FTS_DONTCHDIR 0x01 /* don't chdir .. to the parent */
+#define FTS_SYMFOLLOW 0x02 /* followed a symlink to get here */
+#define FTS_ISW 0x04 /* this is a whiteout object */
+ u_short fts_flags; /* private flags for FTSENT structure */
+
+#define FTS_AGAIN 1 /* read node again */
+#define FTS_FOLLOW 2 /* follow symbolic link */
+#define FTS_NOINSTR 3 /* no instructions */
+#define FTS_SKIP 4 /* discard node */
+ u_short fts_instr; /* fts_set() instructions */
+
+ struct stat *fts_statp; /* stat(2) information */
+ char *fts_name; /* file name */
+ FTS *fts_fts; /* back pointer to main FTS */
+} FTSENT;
+
+#define fts_get_clientptr(fts) ((fts)->fts_clientptr)
+#define fts_get_stream(ftsent) ((ftsent)->fts_fts)
+
+#endif /* !_FTS_H_ */
diff --git a/lib/libc/gen/fts.3 b/lib/libc/gen/fts.3
new file mode 100644
index 0000000..35e4d45
--- /dev/null
+++ b/lib/libc/gen/fts.3
@@ -0,0 +1,813 @@
+.\" Copyright (c) 1989, 1991, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fts.3 8.5 (Berkeley) 4/16/94
+.\" $FreeBSD$
+.\"
+.Dd March 18, 2012
+.Dt FTS 3
+.Os
+.Sh NAME
+.Nm fts
+.Nd traverse a file hierarchy
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/stat.h
+.In fts.h
+.Ft FTS *
+.Fn fts_open "char * const *path_argv" "int options" "int (*compar)(const FTSENT * const *, const FTSENT * const *)"
+.Ft FTSENT *
+.Fn fts_read "FTS *ftsp"
+.Ft FTSENT *
+.Fn fts_children "FTS *ftsp" "int options"
+.Ft int
+.Fn fts_set "FTS *ftsp" "FTSENT *f" "int options"
+.Ft void
+.Fn fts_set_clientptr "FTS *ftsp" "void *clientdata"
+.Ft void *
+.Fn fts_get_clientptr "FTS *ftsp"
+.Ft FTS *
+.Fn fts_get_stream "FTSENT *f"
+.Ft int
+.Fn fts_close "FTS *ftsp"
+.Sh DESCRIPTION
+The
+.Nm
+functions are provided for traversing
+.Ux
+file hierarchies.
+A simple overview is that the
+.Fn fts_open
+function returns a
+.Dq handle
+on a file hierarchy, which is then supplied to
+the other
+.Nm
+functions.
+The function
+.Fn fts_read
+returns a pointer to a structure describing one of the files in the file
+hierarchy.
+The function
+.Fn fts_children
+returns a pointer to a linked list of structures, each of which describes
+one of the files contained in a directory in the hierarchy.
+In general, directories are visited two distinguishable times; in pre-order
+(before any of their descendants are visited) and in post-order (after all
+of their descendants have been visited).
+Files are visited once.
+It is possible to walk the hierarchy
+.Dq logically
+(ignoring symbolic links)
+or physically (visiting symbolic links), order the walk of the hierarchy or
+prune and/or re-visit portions of the hierarchy.
+.Pp
+Two structures are defined (and typedef'd) in the include file
+.In fts.h .
+The first is
+.Vt FTS ,
+the structure that represents the file hierarchy itself.
+The second is
+.Vt FTSENT ,
+the structure that represents a file in the file
+hierarchy.
+Normally, an
+.Vt FTSENT
+structure is returned for every file in the file
+hierarchy.
+In this manual page,
+.Dq file
+and
+.Dq Vt FTSENT No structure
+are generally
+interchangeable.
+.Pp
+The
+.Vt FTS
+structure contains space for a single pointer, which may be used to
+store application data or per-hierarchy state.
+The
+.Fn fts_set_clientptr
+and
+.Fn fts_get_clientptr
+functions may be used to set and retrieve this pointer.
+This is likely to be useful only when accessed from the sort
+comparison function, which can determine the original
+.Vt FTS
+stream of its arguments using the
+.Fn fts_get_stream
+function.
+The two
+.Li get
+functions are also available as macros of the same name.
+.Pp
+The
+.Vt FTSENT
+structure contains at least the following fields, which are
+described in greater detail below:
+.Bd -literal
+typedef struct _ftsent {
+ int fts_info; /* status for FTSENT structure */
+ char *fts_accpath; /* access path */
+ char *fts_path; /* root path */
+ size_t fts_pathlen; /* strlen(fts_path) */
+ char *fts_name; /* file name */
+ size_t fts_namelen; /* strlen(fts_name) */
+ long fts_level; /* depth (\-1 to N) */
+ int fts_errno; /* file errno */
+ long long fts_number; /* local numeric value */
+ void *fts_pointer; /* local address value */
+ struct ftsent *fts_parent; /* parent directory */
+ struct ftsent *fts_link; /* next file structure */
+ struct ftsent *fts_cycle; /* cycle structure */
+ struct stat *fts_statp; /* stat(2) information */
+} FTSENT;
+.Ed
+.Pp
+These fields are defined as follows:
+.Bl -tag -width "fts_namelen"
+.It Fa fts_info
+One of the following values describing the returned
+.Vt FTSENT
+structure and
+the file it represents.
+With the exception of directories without errors
+.Pq Dv FTS_D ,
+all of these
+entries are terminal, that is, they will not be revisited, nor will any
+of their descendants be visited.
+.Bl -tag -width FTS_DEFAULT
+.It Dv FTS_D
+A directory being visited in pre-order.
+.It Dv FTS_DC
+A directory that causes a cycle in the tree.
+(The
+.Fa fts_cycle
+field of the
+.Vt FTSENT
+structure will be filled in as well.)
+.It Dv FTS_DEFAULT
+Any
+.Vt FTSENT
+structure that represents a file type not explicitly described
+by one of the other
+.Fa fts_info
+values.
+.It Dv FTS_DNR
+A directory which cannot be read.
+This is an error return, and the
+.Fa fts_errno
+field will be set to indicate what caused the error.
+.It Dv FTS_DOT
+A file named
+.Ql .\&
+or
+.Ql ..\&
+which was not specified as a file name to
+.Fn fts_open
+(see
+.Dv FTS_SEEDOT ) .
+.It Dv FTS_DP
+A directory being visited in post-order.
+The contents of the
+.Vt FTSENT
+structure will be unchanged from when
+the directory was visited in pre-order, except for the
+.Fa fts_info
+field.
+.It Dv FTS_ERR
+This is an error return, and the
+.Fa fts_errno
+field will be set to indicate what caused the error.
+.It Dv FTS_F
+A regular file.
+.It Dv FTS_NS
+A file for which no
+.Xr stat 2
+information was available.
+The contents of the
+.Fa fts_statp
+field are undefined.
+This is an error return, and the
+.Fa fts_errno
+field will be set to indicate what caused the error.
+.It Dv FTS_NSOK
+A file for which no
+.Xr stat 2
+information was requested.
+The contents of the
+.Fa fts_statp
+field are undefined.
+.It Dv FTS_SL
+A symbolic link.
+.It Dv FTS_SLNONE
+A symbolic link with a non-existent target.
+The contents of the
+.Fa fts_statp
+field reference the file characteristic information for the symbolic link
+itself.
+.El
+.It Fa fts_accpath
+A path for accessing the file from the current directory.
+.It Fa fts_path
+The path for the file relative to the root of the traversal.
+This path contains the path specified to
+.Fn fts_open
+as a prefix.
+.It Fa fts_pathlen
+The length of the string referenced by
+.Fa fts_path .
+.It Fa fts_name
+The name of the file.
+.It Fa fts_namelen
+The length of the string referenced by
+.Fa fts_name .
+.It Fa fts_level
+The depth of the traversal, numbered from \-1 to N, where this file
+was found.
+The
+.Vt FTSENT
+structure representing the parent of the starting point (or root)
+of the traversal is numbered
+.Dv FTS_ROOTPARENTLEVEL
+(\-1), and the
+.Vt FTSENT
+structure for the root
+itself is numbered
+.Dv FTS_ROOTLEVEL
+(0).
+.It Fa fts_errno
+Upon return of a
+.Vt FTSENT
+structure from the
+.Fn fts_children
+or
+.Fn fts_read
+functions, with its
+.Fa fts_info
+field set to
+.Dv FTS_DNR ,
+.Dv FTS_ERR
+or
+.Dv FTS_NS ,
+the
+.Fa fts_errno
+field contains the value of the external variable
+.Va errno
+specifying the cause of the error.
+Otherwise, the contents of the
+.Fa fts_errno
+field are undefined.
+.It Fa fts_number
+This field is provided for the use of the application program and is
+not modified by the
+.Nm
+functions.
+It is initialized to 0.
+.It Fa fts_pointer
+This field is provided for the use of the application program and is
+not modified by the
+.Nm
+functions.
+It is initialized to
+.Dv NULL .
+.It Fa fts_parent
+A pointer to the
+.Vt FTSENT
+structure referencing the file in the hierarchy
+immediately above the current file, i.e., the directory of which this
+file is a member.
+A parent structure for the initial entry point is provided as well,
+however, only the
+.Fa fts_level ,
+.Fa fts_bignum ,
+.Fa fts_number
+and
+.Fa fts_pointer
+fields are guaranteed to be initialized.
+.It Fa fts_link
+Upon return from the
+.Fn fts_children
+function, the
+.Fa fts_link
+field points to the next structure in the NULL-terminated linked list of
+directory members.
+Otherwise, the contents of the
+.Fa fts_link
+field are undefined.
+.It Fa fts_cycle
+If a directory causes a cycle in the hierarchy (see
+.Dv FTS_DC ) ,
+either because
+of a hard link between two directories, or a symbolic link pointing to a
+directory, the
+.Fa fts_cycle
+field of the structure will point to the
+.Vt FTSENT
+structure in the hierarchy that references the same file as the current
+.Vt FTSENT
+structure.
+Otherwise, the contents of the
+.Fa fts_cycle
+field are undefined.
+.It Fa fts_statp
+A pointer to
+.Xr stat 2
+information for the file.
+.El
+.Pp
+A single buffer is used for all of the paths of all of the files in the
+file hierarchy.
+Therefore, the
+.Fa fts_path
+and
+.Fa fts_accpath
+fields are guaranteed to be
+.Dv NUL Ns -terminated
+.Em only
+for the file most recently returned by
+.Fn fts_read .
+To use these fields to reference any files represented by other
+.Vt FTSENT
+structures will require that the path buffer be modified using the
+information contained in that
+.Vt FTSENT
+structure's
+.Fa fts_pathlen
+field.
+Any such modifications should be undone before further calls to
+.Fn fts_read
+are attempted.
+The
+.Fa fts_name
+field is always
+.Dv NUL Ns -terminated .
+.Pp
+Note that the use of
+.Fa fts_bignum
+is mutually exclusive with the use of
+.Fa fts_number
+or
+.Fa fts_pointer .
+.Sh FTS_OPEN
+The
+.Fn fts_open
+function takes a pointer to an array of character pointers naming one
+or more paths which make up a logical file hierarchy to be traversed.
+The array must be terminated by a
+.Dv NULL
+pointer.
+.Pp
+There are
+a number of options, at least one of which (either
+.Dv FTS_LOGICAL
+or
+.Dv FTS_PHYSICAL )
+must be specified.
+The options are selected by
+.Em or Ns 'ing
+the following values:
+.Bl -tag -width "FTS_PHYSICAL"
+.It Dv FTS_COMFOLLOW
+This option causes any symbolic link specified as a root path to be
+followed immediately whether or not
+.Dv FTS_LOGICAL
+is also specified.
+.It Dv FTS_LOGICAL
+This option causes the
+.Nm
+routines to return
+.Vt FTSENT
+structures for the targets of symbolic links
+instead of the symbolic links themselves.
+If this option is set, the only symbolic links for which
+.Vt FTSENT
+structures
+are returned to the application are those referencing non-existent files.
+Either
+.Dv FTS_LOGICAL
+or
+.Dv FTS_PHYSICAL
+.Em must
+be provided to the
+.Fn fts_open
+function.
+.It Dv FTS_NOCHDIR
+To allow descending to arbitrary depths
+(independent of
+.Brq Dv PATH_MAX )
+and improve performance, the
+.Nm
+functions change directories as they walk the file hierarchy.
+This has the side-effect that an application cannot rely on being
+in any particular directory during the traversal.
+The
+.Dv FTS_NOCHDIR
+option turns off this feature, and the
+.Nm
+functions will not change the current directory.
+Note that applications should not themselves change their current directory
+and try to access files unless
+.Dv FTS_NOCHDIR
+is specified and absolute
+pathnames were provided as arguments to
+.Fn fts_open .
+.It Dv FTS_NOSTAT
+By default, returned
+.Vt FTSENT
+structures reference file characteristic information (the
+.Fa statp
+field) for each file visited.
+This option relaxes that requirement as a performance optimization,
+allowing the
+.Nm
+functions to set the
+.Fa fts_info
+field to
+.Dv FTS_NSOK
+and leave the contents of the
+.Fa statp
+field undefined.
+.It Dv FTS_PHYSICAL
+This option causes the
+.Nm
+routines to return
+.Vt FTSENT
+structures for symbolic links themselves instead
+of the target files they point to.
+If this option is set,
+.Vt FTSENT
+structures for all symbolic links in the
+hierarchy are returned to the application.
+Either
+.Dv FTS_LOGICAL
+or
+.Dv FTS_PHYSICAL
+.Em must
+be provided to the
+.Fn fts_open
+function.
+.It Dv FTS_SEEDOT
+By default, unless they are specified as path arguments to
+.Fn fts_open ,
+any files named
+.Ql .\&
+or
+.Ql ..\&
+encountered in the file hierarchy are ignored.
+This option causes the
+.Nm
+routines to return
+.Vt FTSENT
+structures for them.
+.It Dv FTS_XDEV
+This option prevents
+.Nm
+from descending into directories that have a different device number
+than the file from which the descent began.
+.El
+.Pp
+The argument
+.Fn compar
+specifies a user-defined function which may be used to order the traversal
+of the hierarchy.
+It
+takes two pointers to pointers to
+.Vt FTSENT
+structures as arguments and
+should return a negative value, zero, or a positive value to indicate
+if the file referenced by its first argument comes before, in any order
+with respect to, or after, the file referenced by its second argument.
+The
+.Fa fts_accpath ,
+.Fa fts_path
+and
+.Fa fts_pathlen
+fields of the
+.Vt FTSENT
+structures may
+.Em never
+be used in this comparison.
+If the
+.Fa fts_info
+field is set to
+.Dv FTS_NS
+or
+.Dv FTS_NSOK ,
+the
+.Fa fts_statp
+field may not either.
+If the
+.Fn compar
+argument is
+.Dv NULL ,
+the directory traversal order is in the order listed in
+.Fa path_argv
+for the root paths, and in the order listed in the directory for
+everything else.
+.Sh FTS_READ
+The
+.Fn fts_read
+function returns a pointer to an
+.Vt FTSENT
+structure describing a file in
+the hierarchy.
+Directories (that are readable and do not cause cycles) are visited at
+least twice, once in pre-order and once in post-order.
+All other files are visited at least once.
+(Hard links between directories that do not cause cycles or symbolic
+links to symbolic links may cause files to be visited more than once,
+or directories more than twice.)
+.Pp
+If all the members of the hierarchy have been returned,
+.Fn fts_read
+returns
+.Dv NULL
+and sets the external variable
+.Va errno
+to 0.
+If an error unrelated to a file in the hierarchy occurs,
+.Fn fts_read
+returns
+.Dv NULL
+and sets
+.Va errno
+appropriately.
+If an error related to a returned file occurs, a pointer to an
+.Vt FTSENT
+structure is returned, and
+.Va errno
+may or may not have been set (see
+.Fa fts_info ) .
+.Pp
+The
+.Vt FTSENT
+structures returned by
+.Fn fts_read
+may be overwritten after a call to
+.Fn fts_close
+on the same file hierarchy stream, or, after a call to
+.Fn fts_read
+on the same file hierarchy stream unless they represent a file of type
+directory, in which case they will not be overwritten until after a call to
+.Fn fts_read
+after the
+.Vt FTSENT
+structure has been returned by the function
+.Fn fts_read
+in post-order.
+.Sh FTS_CHILDREN
+The
+.Fn fts_children
+function returns a pointer to an
+.Vt FTSENT
+structure describing the first entry in a NULL-terminated linked list of
+the files in the directory represented by the
+.Vt FTSENT
+structure most recently returned by
+.Fn fts_read .
+The list is linked through the
+.Fa fts_link
+field of the
+.Vt FTSENT
+structure, and is ordered by the user-specified comparison function, if any.
+Repeated calls to
+.Fn fts_children
+will recreate this linked list.
+.Pp
+As a special case, if
+.Fn fts_read
+has not yet been called for a hierarchy,
+.Fn fts_children
+will return a pointer to the files in the logical directory specified to
+.Fn fts_open ,
+i.e., the arguments specified to
+.Fn fts_open .
+Otherwise, if the
+.Vt FTSENT
+structure most recently returned by
+.Fn fts_read
+is not a directory being visited in pre-order,
+or the directory does not contain any files,
+.Fn fts_children
+returns
+.Dv NULL
+and sets
+.Va errno
+to zero.
+If an error occurs,
+.Fn fts_children
+returns
+.Dv NULL
+and sets
+.Va errno
+appropriately.
+.Pp
+The
+.Vt FTSENT
+structures returned by
+.Fn fts_children
+may be overwritten after a call to
+.Fn fts_children ,
+.Fn fts_close
+or
+.Fn fts_read
+on the same file hierarchy stream.
+.Pp
+.Em Option
+may be set to the following value:
+.Bl -tag -width FTS_NAMEONLY
+.It Dv FTS_NAMEONLY
+Only the names of the files are needed.
+The contents of all the fields in the returned linked list of structures
+are undefined with the exception of the
+.Fa fts_name
+and
+.Fa fts_namelen
+fields.
+.El
+.Sh FTS_SET
+The function
+.Fn fts_set
+allows the user application to determine further processing for the
+file
+.Fa f
+of the stream
+.Fa ftsp .
+The
+.Fn fts_set
+function
+returns 0 on success, and \-1 if an error occurs.
+.Em Option
+must be set to one of the following values:
+.Bl -tag -width FTS_PHYSICAL
+.It Dv FTS_AGAIN
+Re-visit the file; any file type may be re-visited.
+The next call to
+.Fn fts_read
+will return the referenced file.
+The
+.Fa fts_stat
+and
+.Fa fts_info
+fields of the structure will be reinitialized at that time,
+but no other fields will have been changed.
+This option is meaningful only for the most recently returned
+file from
+.Fn fts_read .
+Normal use is for post-order directory visits, where it causes the
+directory to be re-visited (in both pre and post-order) as well as all
+of its descendants.
+.It Dv FTS_FOLLOW
+The referenced file must be a symbolic link.
+If the referenced file is the one most recently returned by
+.Fn fts_read ,
+the next call to
+.Fn fts_read
+returns the file with the
+.Fa fts_info
+and
+.Fa fts_statp
+fields reinitialized to reflect the target of the symbolic link instead
+of the symbolic link itself.
+If the file is one of those most recently returned by
+.Fn fts_children ,
+the
+.Fa fts_info
+and
+.Fa fts_statp
+fields of the structure, when returned by
+.Fn fts_read ,
+will reflect the target of the symbolic link instead of the symbolic link
+itself.
+In either case, if the target of the symbolic link does not exist the
+fields of the returned structure will be unchanged and the
+.Fa fts_info
+field will be set to
+.Dv FTS_SLNONE .
+.Pp
+If the target of the link is a directory, the pre-order return, followed
+by the return of all of its descendants, followed by a post-order return,
+is done.
+.It Dv FTS_SKIP
+No descendants of this file are visited.
+The file may be one of those most recently returned by either
+.Fn fts_children
+or
+.Fn fts_read .
+.El
+.Sh FTS_CLOSE
+The
+.Fn fts_close
+function closes a file hierarchy stream
+.Fa ftsp
+and restores the current directory to the directory from which
+.Fn fts_open
+was called to open
+.Fa ftsp .
+The
+.Fn fts_close
+function
+returns 0 on success, and \-1 if an error occurs.
+.Sh ERRORS
+The function
+.Fn fts_open
+may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr open 2
+and
+.Xr malloc 3 .
+.Pp
+The function
+.Fn fts_close
+may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr chdir 2
+and
+.Xr close 2 .
+.Pp
+The functions
+.Fn fts_read
+and
+.Fn fts_children
+may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr chdir 2 ,
+.Xr malloc 3 ,
+.Xr opendir 3 ,
+.Xr readdir 3
+and
+.Xr stat 2 .
+.Pp
+In addition,
+.Fn fts_children ,
+.Fn fts_open
+and
+.Fn fts_set
+may fail and set
+.Va errno
+as follows:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The options were invalid, or the list were empty.
+.El
+.Sh SEE ALSO
+.Xr find 1 ,
+.Xr chdir 2 ,
+.Xr stat 2 ,
+.Xr ftw 3 ,
+.Xr qsort 3
+.Sh HISTORY
+The
+.Nm
+interface was first introduced in
+.Bx 4.4 .
+The
+.Fn fts_get_clientptr ,
+.Fn fts_get_stream ,
+and
+.Fn fts_set_clientptr
+functions were introduced in
+.Fx 5.0 ,
+principally to provide for alternative interfaces to the
+.Nm
+functionality using different data structures.
+.Sh BUGS
+The
+.Fn fts_open
+function will automatically set the
+.Dv FTS_NOCHDIR
+option if the
+.Dv FTS_LOGICAL
+option is provided, or if it cannot
+.Xr open 2
+the current directory.
diff --git a/lib/libc/gen/fts.c b/lib/libc/gen/fts.c
new file mode 100644
index 0000000..1344464
--- /dev/null
+++ b/lib/libc/gen/fts.c
@@ -0,0 +1,1171 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $OpenBSD: fts.c,v 1.22 1999/10/03 19:22:22 millert Exp $
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fts.c 8.6 (Berkeley) 8/14/94";
+#endif /* LIBC_SCCS and not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+static FTSENT *fts_alloc(FTS *, char *, size_t);
+static FTSENT *fts_build(FTS *, int);
+static void fts_lfree(FTSENT *);
+static void fts_load(FTS *, FTSENT *);
+static size_t fts_maxarglen(char * const *);
+static void fts_padjust(FTS *, FTSENT *);
+static int fts_palloc(FTS *, size_t);
+static FTSENT *fts_sort(FTS *, FTSENT *, size_t);
+static int fts_stat(FTS *, FTSENT *, int);
+static int fts_safe_changedir(FTS *, FTSENT *, int, char *);
+static int fts_ufslinks(FTS *, const FTSENT *);
+
+#define ISDOT(a) (a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
+
+#define CLR(opt) (sp->fts_options &= ~(opt))
+#define ISSET(opt) (sp->fts_options & (opt))
+#define SET(opt) (sp->fts_options |= (opt))
+
+#define FCHDIR(sp, fd) (!ISSET(FTS_NOCHDIR) && fchdir(fd))
+
+/* fts_build flags */
+#define BCHILD 1 /* fts_children */
+#define BNAMES 2 /* fts_children, names only */
+#define BREAD 3 /* fts_read */
+
+/*
+ * Internal representation of an FTS, including extra implementation
+ * details. The FTS returned from fts_open points to this structure's
+ * ftsp_fts member (and can be cast to an _fts_private as required)
+ */
+struct _fts_private {
+ FTS ftsp_fts;
+ struct statfs ftsp_statfs;
+ dev_t ftsp_dev;
+ int ftsp_linksreliable;
+};
+
+/*
+ * The "FTS_NOSTAT" option can avoid a lot of calls to stat(2) if it
+ * knows that a directory could not possibly have subdirectories. This
+ * is decided by looking at the link count: a subdirectory would
+ * increment its parent's link count by virtue of its own ".." entry.
+ * This assumption only holds for UFS-like filesystems that implement
+ * links and directories this way, so we must punt for others.
+ */
+
+static const char *ufslike_filesystems[] = {
+ "ufs",
+ "zfs",
+ "nfs",
+ "nfs4",
+ "ext2fs",
+ 0
+};
+
+FTS *
+fts_open(argv, options, compar)
+ char * const *argv;
+ int options;
+ int (*compar)(const FTSENT * const *, const FTSENT * const *);
+{
+ struct _fts_private *priv;
+ FTS *sp;
+ FTSENT *p, *root;
+ FTSENT *parent, *tmp;
+ size_t len, nitems;
+
+ /* Options check. */
+ if (options & ~FTS_OPTIONMASK) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* fts_open() requires at least one path */
+ if (*argv == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Allocate/initialize the stream. */
+ if ((priv = malloc(sizeof(*priv))) == NULL)
+ return (NULL);
+ memset(priv, 0, sizeof(*priv));
+ sp = &priv->ftsp_fts;
+ sp->fts_compar = compar;
+ sp->fts_options = options;
+
+ /* Shush, GCC. */
+ tmp = NULL;
+
+ /* Logical walks turn on NOCHDIR; symbolic links are too hard. */
+ if (ISSET(FTS_LOGICAL))
+ SET(FTS_NOCHDIR);
+
+ /*
+ * Start out with 1K of path space, and enough, in any case,
+ * to hold the user's paths.
+ */
+ if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
+ goto mem1;
+
+ /* Allocate/initialize root's parent. */
+ if ((parent = fts_alloc(sp, "", 0)) == NULL)
+ goto mem2;
+ parent->fts_level = FTS_ROOTPARENTLEVEL;
+
+ /* Allocate/initialize root(s). */
+ for (root = NULL, nitems = 0; *argv != NULL; ++argv, ++nitems) {
+ /* Don't allow zero-length paths. */
+ if ((len = strlen(*argv)) == 0) {
+ errno = ENOENT;
+ goto mem3;
+ }
+
+ p = fts_alloc(sp, *argv, len);
+ p->fts_level = FTS_ROOTLEVEL;
+ p->fts_parent = parent;
+ p->fts_accpath = p->fts_name;
+ p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
+
+ /* Command-line "." and ".." are real directories. */
+ if (p->fts_info == FTS_DOT)
+ p->fts_info = FTS_D;
+
+ /*
+ * If comparison routine supplied, traverse in sorted
+ * order; otherwise traverse in the order specified.
+ */
+ if (compar) {
+ p->fts_link = root;
+ root = p;
+ } else {
+ p->fts_link = NULL;
+ if (root == NULL)
+ tmp = root = p;
+ else {
+ tmp->fts_link = p;
+ tmp = p;
+ }
+ }
+ }
+ if (compar && nitems > 1)
+ root = fts_sort(sp, root, nitems);
+
+ /*
+ * Allocate a dummy pointer and make fts_read think that we've just
+ * finished the node before the root(s); set p->fts_info to FTS_INIT
+ * so that everything about the "current" node is ignored.
+ */
+ if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
+ goto mem3;
+ sp->fts_cur->fts_link = root;
+ sp->fts_cur->fts_info = FTS_INIT;
+
+ /*
+ * If using chdir(2), grab a file descriptor pointing to dot to ensure
+ * that we can get back here; this could be avoided for some paths,
+ * but almost certainly not worth the effort. Slashes, symbolic links,
+ * and ".." are all fairly nasty problems. Note, if we can't get the
+ * descriptor we run anyway, just more slowly.
+ */
+ if (!ISSET(FTS_NOCHDIR) && (sp->fts_rfd = _open(".", O_RDONLY, 0)) < 0)
+ SET(FTS_NOCHDIR);
+
+ return (sp);
+
+mem3: fts_lfree(root);
+ free(parent);
+mem2: free(sp->fts_path);
+mem1: free(sp);
+ return (NULL);
+}
+
+static void
+fts_load(FTS *sp, FTSENT *p)
+{
+ size_t len;
+ char *cp;
+
+ /*
+ * Load the stream structure for the next traversal. Since we don't
+ * actually enter the directory until after the preorder visit, set
+ * the fts_accpath field specially so the chdir gets done to the right
+ * place and the user can access the first node. From fts_open it's
+ * known that the path will fit.
+ */
+ len = p->fts_pathlen = p->fts_namelen;
+ memmove(sp->fts_path, p->fts_name, len + 1);
+ if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
+ len = strlen(++cp);
+ memmove(p->fts_name, cp, len + 1);
+ p->fts_namelen = len;
+ }
+ p->fts_accpath = p->fts_path = sp->fts_path;
+ sp->fts_dev = p->fts_dev;
+}
+
+int
+fts_close(FTS *sp)
+{
+ FTSENT *freep, *p;
+ int saved_errno;
+
+ /*
+ * This still works if we haven't read anything -- the dummy structure
+ * points to the root list, so we step through to the end of the root
+ * list which has a valid parent pointer.
+ */
+ if (sp->fts_cur) {
+ for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
+ freep = p;
+ p = p->fts_link != NULL ? p->fts_link : p->fts_parent;
+ free(freep);
+ }
+ free(p);
+ }
+
+ /* Free up child linked list, sort array, path buffer. */
+ if (sp->fts_child)
+ fts_lfree(sp->fts_child);
+ if (sp->fts_array)
+ free(sp->fts_array);
+ free(sp->fts_path);
+
+ /* Return to original directory, save errno if necessary. */
+ if (!ISSET(FTS_NOCHDIR)) {
+ saved_errno = fchdir(sp->fts_rfd) ? errno : 0;
+ (void)_close(sp->fts_rfd);
+
+ /* Set errno and return. */
+ if (saved_errno != 0) {
+ /* Free up the stream pointer. */
+ free(sp);
+ errno = saved_errno;
+ return (-1);
+ }
+ }
+
+ /* Free up the stream pointer. */
+ free(sp);
+ return (0);
+}
+
+/*
+ * Special case of "/" at the end of the path so that slashes aren't
+ * appended which would cause paths to be written as "....//foo".
+ */
+#define NAPPEND(p) \
+ (p->fts_path[p->fts_pathlen - 1] == '/' \
+ ? p->fts_pathlen - 1 : p->fts_pathlen)
+
+FTSENT *
+fts_read(FTS *sp)
+{
+ FTSENT *p, *tmp;
+ int instr;
+ char *t;
+ int saved_errno;
+
+ /* If finished or unrecoverable error, return NULL. */
+ if (sp->fts_cur == NULL || ISSET(FTS_STOP))
+ return (NULL);
+
+ /* Set current node pointer. */
+ p = sp->fts_cur;
+
+ /* Save and zero out user instructions. */
+ instr = p->fts_instr;
+ p->fts_instr = FTS_NOINSTR;
+
+ /* Any type of file may be re-visited; re-stat and re-turn. */
+ if (instr == FTS_AGAIN) {
+ p->fts_info = fts_stat(sp, p, 0);
+ return (p);
+ }
+
+ /*
+ * Following a symlink -- SLNONE test allows application to see
+ * SLNONE and recover. If indirecting through a symlink, have
+ * keep a pointer to current location. If unable to get that
+ * pointer, follow fails.
+ */
+ if (instr == FTS_FOLLOW &&
+ (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
+ p->fts_info = fts_stat(sp, p, 1);
+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+ if ((p->fts_symfd = _open(".", O_RDONLY, 0)) < 0) {
+ p->fts_errno = errno;
+ p->fts_info = FTS_ERR;
+ } else
+ p->fts_flags |= FTS_SYMFOLLOW;
+ }
+ return (p);
+ }
+
+ /* Directory in pre-order. */
+ if (p->fts_info == FTS_D) {
+ /* If skipped or crossed mount point, do post-order visit. */
+ if (instr == FTS_SKIP ||
+ (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
+ if (p->fts_flags & FTS_SYMFOLLOW)
+ (void)_close(p->fts_symfd);
+ if (sp->fts_child) {
+ fts_lfree(sp->fts_child);
+ sp->fts_child = NULL;
+ }
+ p->fts_info = FTS_DP;
+ return (p);
+ }
+
+ /* Rebuild if only read the names and now traversing. */
+ if (sp->fts_child != NULL && ISSET(FTS_NAMEONLY)) {
+ CLR(FTS_NAMEONLY);
+ fts_lfree(sp->fts_child);
+ sp->fts_child = NULL;
+ }
+
+ /*
+ * Cd to the subdirectory.
+ *
+ * If have already read and now fail to chdir, whack the list
+ * to make the names come out right, and set the parent errno
+ * so the application will eventually get an error condition.
+ * Set the FTS_DONTCHDIR flag so that when we logically change
+ * directories back to the parent we don't do a chdir.
+ *
+ * If haven't read do so. If the read fails, fts_build sets
+ * FTS_STOP or the fts_info field of the node.
+ */
+ if (sp->fts_child != NULL) {
+ if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
+ p->fts_errno = errno;
+ p->fts_flags |= FTS_DONTCHDIR;
+ for (p = sp->fts_child; p != NULL;
+ p = p->fts_link)
+ p->fts_accpath =
+ p->fts_parent->fts_accpath;
+ }
+ } else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
+ if (ISSET(FTS_STOP))
+ return (NULL);
+ return (p);
+ }
+ p = sp->fts_child;
+ sp->fts_child = NULL;
+ goto name;
+ }
+
+ /* Move to the next node on this level. */
+next: tmp = p;
+ if ((p = p->fts_link) != NULL) {
+ free(tmp);
+
+ /*
+ * If reached the top, return to the original directory (or
+ * the root of the tree), and load the paths for the next root.
+ */
+ if (p->fts_level == FTS_ROOTLEVEL) {
+ if (FCHDIR(sp, sp->fts_rfd)) {
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ fts_load(sp, p);
+ return (sp->fts_cur = p);
+ }
+
+ /*
+ * User may have called fts_set on the node. If skipped,
+ * ignore. If followed, get a file descriptor so we can
+ * get back if necessary.
+ */
+ if (p->fts_instr == FTS_SKIP)
+ goto next;
+ if (p->fts_instr == FTS_FOLLOW) {
+ p->fts_info = fts_stat(sp, p, 1);
+ if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+ if ((p->fts_symfd =
+ _open(".", O_RDONLY, 0)) < 0) {
+ p->fts_errno = errno;
+ p->fts_info = FTS_ERR;
+ } else
+ p->fts_flags |= FTS_SYMFOLLOW;
+ }
+ p->fts_instr = FTS_NOINSTR;
+ }
+
+name: t = sp->fts_path + NAPPEND(p->fts_parent);
+ *t++ = '/';
+ memmove(t, p->fts_name, p->fts_namelen + 1);
+ return (sp->fts_cur = p);
+ }
+
+ /* Move up to the parent node. */
+ p = tmp->fts_parent;
+ free(tmp);
+
+ if (p->fts_level == FTS_ROOTPARENTLEVEL) {
+ /*
+ * Done; free everything up and set errno to 0 so the user
+ * can distinguish between error and EOF.
+ */
+ free(p);
+ errno = 0;
+ return (sp->fts_cur = NULL);
+ }
+
+ /* NUL terminate the pathname. */
+ sp->fts_path[p->fts_pathlen] = '\0';
+
+ /*
+ * Return to the parent directory. If at a root node or came through
+ * a symlink, go back through the file descriptor. Otherwise, cd up
+ * one directory.
+ */
+ if (p->fts_level == FTS_ROOTLEVEL) {
+ if (FCHDIR(sp, sp->fts_rfd)) {
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ } else if (p->fts_flags & FTS_SYMFOLLOW) {
+ if (FCHDIR(sp, p->fts_symfd)) {
+ saved_errno = errno;
+ (void)_close(p->fts_symfd);
+ errno = saved_errno;
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ (void)_close(p->fts_symfd);
+ } else if (!(p->fts_flags & FTS_DONTCHDIR) &&
+ fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
+ SET(FTS_STOP);
+ return (NULL);
+ }
+ p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
+ return (sp->fts_cur = p);
+}
+
+/*
+ * Fts_set takes the stream as an argument although it's not used in this
+ * implementation; it would be necessary if anyone wanted to add global
+ * semantics to fts using fts_set. An error return is allowed for similar
+ * reasons.
+ */
+/* ARGSUSED */
+int
+fts_set(FTS *sp, FTSENT *p, int instr)
+{
+ if (instr != 0 && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
+ instr != FTS_NOINSTR && instr != FTS_SKIP) {
+ errno = EINVAL;
+ return (1);
+ }
+ p->fts_instr = instr;
+ return (0);
+}
+
+FTSENT *
+fts_children(FTS *sp, int instr)
+{
+ FTSENT *p;
+ int fd;
+
+ if (instr != 0 && instr != FTS_NAMEONLY) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Set current node pointer. */
+ p = sp->fts_cur;
+
+ /*
+ * Errno set to 0 so user can distinguish empty directory from
+ * an error.
+ */
+ errno = 0;
+
+ /* Fatal errors stop here. */
+ if (ISSET(FTS_STOP))
+ return (NULL);
+
+ /* Return logical hierarchy of user's arguments. */
+ if (p->fts_info == FTS_INIT)
+ return (p->fts_link);
+
+ /*
+ * If not a directory being visited in pre-order, stop here. Could
+ * allow FTS_DNR, assuming the user has fixed the problem, but the
+ * same effect is available with FTS_AGAIN.
+ */
+ if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
+ return (NULL);
+
+ /* Free up any previous child list. */
+ if (sp->fts_child != NULL)
+ fts_lfree(sp->fts_child);
+
+ if (instr == FTS_NAMEONLY) {
+ SET(FTS_NAMEONLY);
+ instr = BNAMES;
+ } else
+ instr = BCHILD;
+
+ /*
+ * If using chdir on a relative path and called BEFORE fts_read does
+ * its chdir to the root of a traversal, we can lose -- we need to
+ * chdir into the subdirectory, and we don't know where the current
+ * directory is, so we can't get back so that the upcoming chdir by
+ * fts_read will work.
+ */
+ if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
+ ISSET(FTS_NOCHDIR))
+ return (sp->fts_child = fts_build(sp, instr));
+
+ if ((fd = _open(".", O_RDONLY, 0)) < 0)
+ return (NULL);
+ sp->fts_child = fts_build(sp, instr);
+ if (fchdir(fd)) {
+ (void)_close(fd);
+ return (NULL);
+ }
+ (void)_close(fd);
+ return (sp->fts_child);
+}
+
+#ifndef fts_get_clientptr
+#error "fts_get_clientptr not defined"
+#endif
+
+void *
+(fts_get_clientptr)(FTS *sp)
+{
+
+ return (fts_get_clientptr(sp));
+}
+
+#ifndef fts_get_stream
+#error "fts_get_stream not defined"
+#endif
+
+FTS *
+(fts_get_stream)(FTSENT *p)
+{
+ return (fts_get_stream(p));
+}
+
+void
+fts_set_clientptr(FTS *sp, void *clientptr)
+{
+
+ sp->fts_clientptr = clientptr;
+}
+
+/*
+ * This is the tricky part -- do not casually change *anything* in here. The
+ * idea is to build the linked list of entries that are used by fts_children
+ * and fts_read. There are lots of special cases.
+ *
+ * The real slowdown in walking the tree is the stat calls. If FTS_NOSTAT is
+ * set and it's a physical walk (so that symbolic links can't be directories),
+ * we can do things quickly. First, if it's a 4.4BSD file system, the type
+ * of the file is in the directory entry. Otherwise, we assume that the number
+ * of subdirectories in a node is equal to the number of links to the parent.
+ * The former skips all stat calls. The latter skips stat calls in any leaf
+ * directories and for any files after the subdirectories in the directory have
+ * been found, cutting the stat calls by about 2/3.
+ */
+static FTSENT *
+fts_build(FTS *sp, int type)
+{
+ struct dirent *dp;
+ FTSENT *p, *head;
+ FTSENT *cur, *tail;
+ DIR *dirp;
+ void *oldaddr;
+ char *cp;
+ int cderrno, descend, oflag, saved_errno, nostat, doadjust;
+ long level;
+ long nlinks; /* has to be signed because -1 is a magic value */
+ size_t dnamlen, len, maxlen, nitems;
+
+ /* Set current node pointer. */
+ cur = sp->fts_cur;
+
+ /*
+ * Open the directory for reading. If this fails, we're done.
+ * If being called from fts_read, set the fts_info field.
+ */
+#ifdef FTS_WHITEOUT
+ if (ISSET(FTS_WHITEOUT))
+ oflag = DTF_NODUP | DTF_REWIND;
+ else
+ oflag = DTF_HIDEW | DTF_NODUP | DTF_REWIND;
+#else
+#define __opendir2(path, flag) opendir(path)
+#endif
+ if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
+ if (type == BREAD) {
+ cur->fts_info = FTS_DNR;
+ cur->fts_errno = errno;
+ }
+ return (NULL);
+ }
+
+ /*
+ * Nlinks is the number of possible entries of type directory in the
+ * directory if we're cheating on stat calls, 0 if we're not doing
+ * any stat calls at all, -1 if we're doing stats on everything.
+ */
+ if (type == BNAMES) {
+ nlinks = 0;
+ /* Be quiet about nostat, GCC. */
+ nostat = 0;
+ } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
+ if (fts_ufslinks(sp, cur))
+ nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
+ else
+ nlinks = -1;
+ nostat = 1;
+ } else {
+ nlinks = -1;
+ nostat = 0;
+ }
+
+#ifdef notdef
+ (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
+ (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
+ ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
+#endif
+ /*
+ * If we're going to need to stat anything or we want to descend
+ * and stay in the directory, chdir. If this fails we keep going,
+ * but set a flag so we don't chdir after the post-order visit.
+ * We won't be able to stat anything, but we can still return the
+ * names themselves. Note, that since fts_read won't be able to
+ * chdir into the directory, it will have to return different path
+ * names than before, i.e. "a/b" instead of "b". Since the node
+ * has already been visited in pre-order, have to wait until the
+ * post-order visit to return the error. There is a special case
+ * here, if there was nothing to stat then it's not an error to
+ * not be able to stat. This is all fairly nasty. If a program
+ * needed sorted entries or stat information, they had better be
+ * checking FTS_NS on the returned nodes.
+ */
+ cderrno = 0;
+ if (nlinks || type == BREAD) {
+ if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
+ if (nlinks && type == BREAD)
+ cur->fts_errno = errno;
+ cur->fts_flags |= FTS_DONTCHDIR;
+ descend = 0;
+ cderrno = errno;
+ } else
+ descend = 1;
+ } else
+ descend = 0;
+
+ /*
+ * Figure out the max file name length that can be stored in the
+ * current path -- the inner loop allocates more path as necessary.
+ * We really wouldn't have to do the maxlen calculations here, we
+ * could do them in fts_read before returning the path, but it's a
+ * lot easier here since the length is part of the dirent structure.
+ *
+ * If not changing directories set a pointer so that can just append
+ * each new name into the path.
+ */
+ len = NAPPEND(cur);
+ if (ISSET(FTS_NOCHDIR)) {
+ cp = sp->fts_path + len;
+ *cp++ = '/';
+ } else {
+ /* GCC, you're too verbose. */
+ cp = NULL;
+ }
+ len++;
+ maxlen = sp->fts_pathlen - len;
+
+ level = cur->fts_level + 1;
+
+ /* Read the directory, attaching each entry to the `link' pointer. */
+ doadjust = 0;
+ for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) {
+ dnamlen = dp->d_namlen;
+ if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+ continue;
+
+ if ((p = fts_alloc(sp, dp->d_name, dnamlen)) == NULL)
+ goto mem1;
+ if (dnamlen >= maxlen) { /* include space for NUL */
+ oldaddr = sp->fts_path;
+ if (fts_palloc(sp, dnamlen + len + 1)) {
+ /*
+ * No more memory for path or structures. Save
+ * errno, free up the current structure and the
+ * structures already allocated.
+ */
+mem1: saved_errno = errno;
+ if (p)
+ free(p);
+ fts_lfree(head);
+ (void)closedir(dirp);
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ errno = saved_errno;
+ return (NULL);
+ }
+ /* Did realloc() change the pointer? */
+ if (oldaddr != sp->fts_path) {
+ doadjust = 1;
+ if (ISSET(FTS_NOCHDIR))
+ cp = sp->fts_path + len;
+ }
+ maxlen = sp->fts_pathlen - len;
+ }
+
+ p->fts_level = level;
+ p->fts_parent = sp->fts_cur;
+ p->fts_pathlen = len + dnamlen;
+
+#ifdef FTS_WHITEOUT
+ if (dp->d_type == DT_WHT)
+ p->fts_flags |= FTS_ISW;
+#endif
+
+ if (cderrno) {
+ if (nlinks) {
+ p->fts_info = FTS_NS;
+ p->fts_errno = cderrno;
+ } else
+ p->fts_info = FTS_NSOK;
+ p->fts_accpath = cur->fts_accpath;
+ } else if (nlinks == 0
+#ifdef DT_DIR
+ || (nostat &&
+ dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
+#endif
+ ) {
+ p->fts_accpath =
+ ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
+ p->fts_info = FTS_NSOK;
+ } else {
+ /* Build a file name for fts_stat to stat. */
+ if (ISSET(FTS_NOCHDIR)) {
+ p->fts_accpath = p->fts_path;
+ memmove(cp, p->fts_name, p->fts_namelen + 1);
+ } else
+ p->fts_accpath = p->fts_name;
+ /* Stat it. */
+ p->fts_info = fts_stat(sp, p, 0);
+
+ /* Decrement link count if applicable. */
+ if (nlinks > 0 && (p->fts_info == FTS_D ||
+ p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
+ --nlinks;
+ }
+
+ /* We walk in directory order so "ls -f" doesn't get upset. */
+ p->fts_link = NULL;
+ if (head == NULL)
+ head = tail = p;
+ else {
+ tail->fts_link = p;
+ tail = p;
+ }
+ ++nitems;
+ }
+ if (dirp)
+ (void)closedir(dirp);
+
+ /*
+ * If realloc() changed the address of the path, adjust the
+ * addresses for the rest of the tree and the dir list.
+ */
+ if (doadjust)
+ fts_padjust(sp, head);
+
+ /*
+ * If not changing directories, reset the path back to original
+ * state.
+ */
+ if (ISSET(FTS_NOCHDIR))
+ sp->fts_path[cur->fts_pathlen] = '\0';
+
+ /*
+ * If descended after called from fts_children or after called from
+ * fts_read and nothing found, get back. At the root level we use
+ * the saved fd; if one of fts_open()'s arguments is a relative path
+ * to an empty directory, we wind up here with no other way back. If
+ * can't get back, we're done.
+ */
+ if (descend && (type == BCHILD || !nitems) &&
+ (cur->fts_level == FTS_ROOTLEVEL ?
+ FCHDIR(sp, sp->fts_rfd) :
+ fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
+ cur->fts_info = FTS_ERR;
+ SET(FTS_STOP);
+ return (NULL);
+ }
+
+ /* If didn't find anything, return NULL. */
+ if (!nitems) {
+ if (type == BREAD)
+ cur->fts_info = FTS_DP;
+ return (NULL);
+ }
+
+ /* Sort the entries. */
+ if (sp->fts_compar && nitems > 1)
+ head = fts_sort(sp, head, nitems);
+ return (head);
+}
+
+static int
+fts_stat(FTS *sp, FTSENT *p, int follow)
+{
+ FTSENT *t;
+ dev_t dev;
+ ino_t ino;
+ struct stat *sbp, sb;
+ int saved_errno;
+
+ /* If user needs stat info, stat buffer already allocated. */
+ sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
+
+#ifdef FTS_WHITEOUT
+ /* Check for whiteout. */
+ if (p->fts_flags & FTS_ISW) {
+ if (sbp != &sb) {
+ memset(sbp, '\0', sizeof(*sbp));
+ sbp->st_mode = S_IFWHT;
+ }
+ return (FTS_W);
+ }
+#endif
+
+ /*
+ * If doing a logical walk, or application requested FTS_FOLLOW, do
+ * a stat(2). If that fails, check for a non-existent symlink. If
+ * fail, set the errno from the stat call.
+ */
+ if (ISSET(FTS_LOGICAL) || follow) {
+ if (stat(p->fts_accpath, sbp)) {
+ saved_errno = errno;
+ if (!lstat(p->fts_accpath, sbp)) {
+ errno = 0;
+ return (FTS_SLNONE);
+ }
+ p->fts_errno = saved_errno;
+ goto err;
+ }
+ } else if (lstat(p->fts_accpath, sbp)) {
+ p->fts_errno = errno;
+err: memset(sbp, 0, sizeof(struct stat));
+ return (FTS_NS);
+ }
+
+ if (S_ISDIR(sbp->st_mode)) {
+ /*
+ * Set the device/inode. Used to find cycles and check for
+ * crossing mount points. Also remember the link count, used
+ * in fts_build to limit the number of stat calls. It is
+ * understood that these fields are only referenced if fts_info
+ * is set to FTS_D.
+ */
+ dev = p->fts_dev = sbp->st_dev;
+ ino = p->fts_ino = sbp->st_ino;
+ p->fts_nlink = sbp->st_nlink;
+
+ if (ISDOT(p->fts_name))
+ return (FTS_DOT);
+
+ /*
+ * Cycle detection is done by brute force when the directory
+ * is first encountered. If the tree gets deep enough or the
+ * number of symbolic links to directories is high enough,
+ * something faster might be worthwhile.
+ */
+ for (t = p->fts_parent;
+ t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
+ if (ino == t->fts_ino && dev == t->fts_dev) {
+ p->fts_cycle = t;
+ return (FTS_DC);
+ }
+ return (FTS_D);
+ }
+ if (S_ISLNK(sbp->st_mode))
+ return (FTS_SL);
+ if (S_ISREG(sbp->st_mode))
+ return (FTS_F);
+ return (FTS_DEFAULT);
+}
+
+/*
+ * The comparison function takes pointers to pointers to FTSENT structures.
+ * Qsort wants a comparison function that takes pointers to void.
+ * (Both with appropriate levels of const-poisoning, of course!)
+ * Use a trampoline function to deal with the difference.
+ */
+static int
+fts_compar(const void *a, const void *b)
+{
+ FTS *parent;
+
+ parent = (*(const FTSENT * const *)a)->fts_fts;
+ return (*parent->fts_compar)(a, b);
+}
+
+static FTSENT *
+fts_sort(FTS *sp, FTSENT *head, size_t nitems)
+{
+ FTSENT **ap, *p;
+
+ /*
+ * Construct an array of pointers to the structures and call qsort(3).
+ * Reassemble the array in the order returned by qsort. If unable to
+ * sort for memory reasons, return the directory entries in their
+ * current order. Allocate enough space for the current needs plus
+ * 40 so don't realloc one entry at a time.
+ */
+ if (nitems > sp->fts_nitems) {
+ sp->fts_nitems = nitems + 40;
+ if ((sp->fts_array = reallocf(sp->fts_array,
+ sp->fts_nitems * sizeof(FTSENT *))) == NULL) {
+ sp->fts_nitems = 0;
+ return (head);
+ }
+ }
+ for (ap = sp->fts_array, p = head; p; p = p->fts_link)
+ *ap++ = p;
+ qsort(sp->fts_array, nitems, sizeof(FTSENT *), fts_compar);
+ for (head = *(ap = sp->fts_array); --nitems; ++ap)
+ ap[0]->fts_link = ap[1];
+ ap[0]->fts_link = NULL;
+ return (head);
+}
+
+static FTSENT *
+fts_alloc(FTS *sp, char *name, size_t namelen)
+{
+ FTSENT *p;
+ size_t len;
+
+ struct ftsent_withstat {
+ FTSENT ent;
+ struct stat statbuf;
+ };
+
+ /*
+ * The file name is a variable length array and no stat structure is
+ * necessary if the user has set the nostat bit. Allocate the FTSENT
+ * structure, the file name and the stat structure in one chunk, but
+ * be careful that the stat structure is reasonably aligned.
+ */
+ if (ISSET(FTS_NOSTAT))
+ len = sizeof(FTSENT) + namelen + 1;
+ else
+ len = sizeof(struct ftsent_withstat) + namelen + 1;
+
+ if ((p = malloc(len)) == NULL)
+ return (NULL);
+
+ if (ISSET(FTS_NOSTAT)) {
+ p->fts_name = (char *)(p + 1);
+ p->fts_statp = NULL;
+ } else {
+ p->fts_name = (char *)((struct ftsent_withstat *)p + 1);
+ p->fts_statp = &((struct ftsent_withstat *)p)->statbuf;
+ }
+
+ /* Copy the name and guarantee NUL termination. */
+ memcpy(p->fts_name, name, namelen);
+ p->fts_name[namelen] = '\0';
+ p->fts_namelen = namelen;
+ p->fts_path = sp->fts_path;
+ p->fts_errno = 0;
+ p->fts_flags = 0;
+ p->fts_instr = FTS_NOINSTR;
+ p->fts_number = 0;
+ p->fts_pointer = NULL;
+ p->fts_fts = sp;
+ return (p);
+}
+
+static void
+fts_lfree(FTSENT *head)
+{
+ FTSENT *p;
+
+ /* Free a linked list of structures. */
+ while ((p = head)) {
+ head = head->fts_link;
+ free(p);
+ }
+}
+
+/*
+ * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
+ * Most systems will allow creation of paths much longer than MAXPATHLEN, even
+ * though the kernel won't resolve them. Add the size (not just what's needed)
+ * plus 256 bytes so don't realloc the path 2 bytes at a time.
+ */
+static int
+fts_palloc(FTS *sp, size_t more)
+{
+
+ sp->fts_pathlen += more + 256;
+ sp->fts_path = reallocf(sp->fts_path, sp->fts_pathlen);
+ return (sp->fts_path == NULL);
+}
+
+/*
+ * When the path is realloc'd, have to fix all of the pointers in structures
+ * already returned.
+ */
+static void
+fts_padjust(FTS *sp, FTSENT *head)
+{
+ FTSENT *p;
+ char *addr = sp->fts_path;
+
+#define ADJUST(p) do { \
+ if ((p)->fts_accpath != (p)->fts_name) { \
+ (p)->fts_accpath = \
+ (char *)addr + ((p)->fts_accpath - (p)->fts_path); \
+ } \
+ (p)->fts_path = addr; \
+} while (0)
+ /* Adjust the current set of children. */
+ for (p = sp->fts_child; p; p = p->fts_link)
+ ADJUST(p);
+
+ /* Adjust the rest of the tree, including the current level. */
+ for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
+ ADJUST(p);
+ p = p->fts_link ? p->fts_link : p->fts_parent;
+ }
+}
+
+static size_t
+fts_maxarglen(argv)
+ char * const *argv;
+{
+ size_t len, max;
+
+ for (max = 0; *argv; ++argv)
+ if ((len = strlen(*argv)) > max)
+ max = len;
+ return (max + 1);
+}
+
+/*
+ * Change to dir specified by fd or p->fts_accpath without getting
+ * tricked by someone changing the world out from underneath us.
+ * Assumes p->fts_dev and p->fts_ino are filled in.
+ */
+static int
+fts_safe_changedir(FTS *sp, FTSENT *p, int fd, char *path)
+{
+ int ret, oerrno, newfd;
+ struct stat sb;
+
+ newfd = fd;
+ if (ISSET(FTS_NOCHDIR))
+ return (0);
+ if (fd < 0 && (newfd = _open(path, O_RDONLY, 0)) < 0)
+ return (-1);
+ if (_fstat(newfd, &sb)) {
+ ret = -1;
+ goto bail;
+ }
+ if (p->fts_dev != sb.st_dev || p->fts_ino != sb.st_ino) {
+ errno = ENOENT; /* disinformation */
+ ret = -1;
+ goto bail;
+ }
+ ret = fchdir(newfd);
+bail:
+ oerrno = errno;
+ if (fd < 0)
+ (void)_close(newfd);
+ errno = oerrno;
+ return (ret);
+}
+
+/*
+ * Check if the filesystem for "ent" has UFS-style links.
+ */
+static int
+fts_ufslinks(FTS *sp, const FTSENT *ent)
+{
+ struct _fts_private *priv;
+ const char **cpp;
+
+ priv = (struct _fts_private *)sp;
+ /*
+ * If this node's device is different from the previous, grab
+ * the filesystem information, and decide on the reliability
+ * of the link information from this filesystem for stat(2)
+ * avoidance.
+ */
+ if (priv->ftsp_dev != ent->fts_dev) {
+ if (statfs(ent->fts_path, &priv->ftsp_statfs) != -1) {
+ priv->ftsp_dev = ent->fts_dev;
+ priv->ftsp_linksreliable = 0;
+ for (cpp = ufslike_filesystems; *cpp; cpp++) {
+ if (strcmp(priv->ftsp_statfs.f_fstypename,
+ *cpp) == 0) {
+ priv->ftsp_linksreliable = 1;
+ break;
+ }
+ }
+ } else {
+ priv->ftsp_linksreliable = 0;
+ }
+ }
+ return (priv->ftsp_linksreliable);
+}
diff --git a/lib/libc/gen/ftw.3 b/lib/libc/gen/ftw.3
new file mode 100644
index 0000000..ba8859b
--- /dev/null
+++ b/lib/libc/gen/ftw.3
@@ -0,0 +1,216 @@
+.\" $OpenBSD: ftw.3,v 1.5 2004/01/25 14:48:32 jmc Exp $
+.\"
+.\" Copyright (c) 2003 Todd C. Miller <Todd.Miller@courtesan.com>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 5, 2004
+.Dt FTW 3
+.Os
+.Sh NAME
+.Nm ftw , nftw
+.Nd traverse (walk) a file tree
+.Sh SYNOPSIS
+.In ftw.h
+.Ft int
+.Fo ftw
+.Fa "const char *path"
+.Fa "int \*[lp]*fn\*[rp]\*[lp]const char *, const struct stat *, int\*[rp]"
+.Fa "int maxfds"
+.Fc
+.Ft int
+.Fo nftw
+.Fa "const char *path"
+.Fa "int \*[lp]*fn\*[rp]\*[lp]const char *, const struct stat *, int, struct FTW *\*[rp]"
+.Fa "int maxfds"
+.Fa "int flags"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn ftw
+and
+.Fn nftw
+functions traverse (walk) the directory hierarchy rooted in
+.Fa path .
+For each object in the hierarchy, these functions call the function
+pointed to by
+.Fa fn .
+The
+.Fn ftw
+function passes this function a pointer to a
+.Dv NUL Ns
+-terminated string containing
+the name of the object, a pointer to a
+.Vt stat
+structure corresponding to the
+object, and an integer flag.
+The
+.Fn nftw
+function passes the aforementioned arguments plus a pointer to a
+.Vt FTW
+structure as defined by
+.In ftw.h
+(shown below):
+.Bd -literal
+struct FTW {
+ int base; /* offset of basename into pathname */
+ int level; /* directory depth relative to starting point */
+};
+.Ed
+.Pp
+Possible values for the flag passed to
+.Fa fn
+are:
+.Bl -tag -width ".Dv FTW_DNR"
+.It Dv FTW_F
+A regular file.
+.It Dv FTW_D
+A directory being visited in pre-order.
+.It Dv FTW_DNR
+A directory which cannot be read.
+The directory will not be descended into.
+.It Dv FTW_DP
+A directory being visited in post-order
+.Fn ( nftw
+only).
+.It Dv FTW_NS
+A file for which no
+.Xr stat 2
+information was available.
+The contents of the
+.Vt stat
+structure are undefined.
+.It Dv FTW_SL
+A symbolic link.
+.It Dv FTW_SLN
+A symbolic link with a non-existent target
+.Fn ( nftw
+only).
+.El
+.Pp
+The
+.Fn ftw
+function traverses the tree in pre-order.
+That is, it processes the directory before the directory's contents.
+.Pp
+The
+.Fa maxfds
+argument specifies the maximum number of file descriptors
+to keep open while traversing the tree.
+It has no effect in this implementation.
+.Pp
+The
+.Fn nftw
+function has an additional
+.Fa flags
+argument with the following possible values:
+.Bl -tag -width ".Dv FTW_MOUNT"
+.It Dv FTW_PHYS
+Physical walk, do not follow symbolic links.
+.It Dv FTW_MOUNT
+The walk will not cross a mount point.
+.It FTW_DEPTH
+Process directories in post-order.
+Contents of a directory are visited before the directory itself.
+By default,
+.Fn nftw
+traverses the tree in pre-order.
+.It FTW_CHDIR
+Change to a directory before reading it.
+By default,
+.Fn nftw
+will change its starting directory.
+The current working directory will be restored to its original value before
+.Fn nftw
+returns.
+.El
+.Sh RETURN VALUES
+If the tree was traversed successfully, the
+.Fn ftw
+and
+.Fn nftw
+functions return 0.
+If the function pointed to by
+.Fa fn
+returns a non-zero value,
+.Fn ftw
+and
+.Fn nftw
+will stop processing the tree and return the value from
+.Fa fn .
+Both functions return \-1 if an error is detected.
+.Sh ERRORS
+The
+.Fn ftw
+and
+.Fn nftw
+functions may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr close 2 ,
+.Xr open 2 ,
+.Xr stat 2 ,
+.Xr malloc 3 ,
+.Xr opendir 3
+and
+.Xr readdir 3 .
+If the
+.Dv FTW_CHDIR
+flag is set, the
+.Fn nftw
+function may fail and set
+.Va errno
+for any of the errors specified for
+.Xr chdir 2 .
+In addition, either function may fail and set
+.Va errno
+as follows:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa maxfds
+argument is less than 1.
+.El
+.Sh SEE ALSO
+.Xr chdir 2 ,
+.Xr close 2 ,
+.Xr open 2 ,
+.Xr stat 2 ,
+.Xr fts 3 ,
+.Xr malloc 3 ,
+.Xr opendir 3 ,
+.Xr readdir 3
+.Sh STANDARDS
+The
+.Fn ftw
+and
+.Fn nftw
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+These functions first appeared in
+.At V.3 .
+Their first
+.Fx
+appearance was in
+.Fx 5.3 .
+.Sh BUGS
+The
+.Fa maxfds
+argument is currently ignored.
diff --git a/lib/libc/gen/ftw.c b/lib/libc/gen/ftw.c
new file mode 100644
index 0000000..bfaf121
--- /dev/null
+++ b/lib/libc/gen/ftw.c
@@ -0,0 +1,92 @@
+/* $OpenBSD: ftw.c,v 1.5 2005/08/08 08:05:34 espie Exp $ */
+
+/*
+ * Copyright (c) 2003, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fts.h>
+#include <ftw.h>
+#include <limits.h>
+
+int
+ftw(const char *path, int (*fn)(const char *, const struct stat *, int),
+ int nfds)
+{
+ char * const paths[2] = { (char *)path, NULL };
+ FTSENT *cur;
+ FTS *ftsp;
+ int error = 0, fnflag, sverrno;
+
+ /* XXX - nfds is currently unused */
+ if (nfds < 1 || nfds > OPEN_MAX) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ftsp = fts_open(paths, FTS_LOGICAL | FTS_COMFOLLOW | FTS_NOCHDIR, NULL);
+ if (ftsp == NULL)
+ return (-1);
+ while ((cur = fts_read(ftsp)) != NULL) {
+ switch (cur->fts_info) {
+ case FTS_D:
+ fnflag = FTW_D;
+ break;
+ case FTS_DNR:
+ fnflag = FTW_DNR;
+ break;
+ case FTS_DP:
+ /* we only visit in preorder */
+ continue;
+ case FTS_F:
+ case FTS_DEFAULT:
+ fnflag = FTW_F;
+ break;
+ case FTS_NS:
+ case FTS_NSOK:
+ case FTS_SLNONE:
+ fnflag = FTW_NS;
+ break;
+ case FTS_SL:
+ fnflag = FTW_SL;
+ break;
+ case FTS_DC:
+ errno = ELOOP;
+ /* FALLTHROUGH */
+ default:
+ error = -1;
+ goto done;
+ }
+ error = fn(cur->fts_path, cur->fts_statp, fnflag);
+ if (error != 0)
+ break;
+ }
+done:
+ sverrno = errno;
+ if (fts_close(ftsp) != 0 && error == 0)
+ error = -1;
+ else
+ errno = sverrno;
+ return (error);
+}
diff --git a/lib/libc/gen/getbootfile.3 b/lib/libc/gen/getbootfile.3
new file mode 100644
index 0000000..5130c64
--- /dev/null
+++ b/lib/libc/gen/getbootfile.3
@@ -0,0 +1,69 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)gethostname.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd September 23, 1994
+.Dt GETBOOTFILE 3
+.Os
+.Sh NAME
+.Nm getbootfile
+.Nd get kernel boot file name
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In paths.h
+.Ft const char *
+.Fn getbootfile void
+.Sh DESCRIPTION
+The
+.Fn getbootfile
+function retrieves the full pathname of the file from which the
+current kernel was loaded, and returns a static pointer to the name.
+A read/write interface to this information is available via the
+.Xr sysctl 3
+MIB variable
+.Dq Li kern.bootfile .
+.Sh RETURN VALUES
+If the call succeeds a string giving the pathname is returned.
+If it
+fails, a null pointer is returned and an error code is
+placed in the global location
+.Va errno .
+.Sh SEE ALSO
+.Xr sysctl 3
+.Sh HISTORY
+The
+.Fn getbootfile
+function appeared in
+.Fx 2.0 .
+.Sh BUGS
+If the boot blocks have not been modified to pass this information into
+the kernel at boot time, the static string
+.Dq Pa /boot/kernel/kernel
+is returned instead of the real boot file.
diff --git a/lib/libc/gen/getbootfile.c b/lib/libc/gen/getbootfile.c
new file mode 100644
index 0000000..aa23247
--- /dev/null
+++ b/lib/libc/gen/getbootfile.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "From: @(#)gethostname.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <paths.h>
+
+const char *
+getbootfile(void)
+{
+ static char name[MAXPATHLEN];
+ size_t size = sizeof name;
+ int mib[2];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_BOOTFILE;
+ if (sysctl(mib, 2, name, &size, NULL, 0) == -1)
+ return ("/boot/kernel/kernel");
+ return (name);
+}
diff --git a/lib/libc/gen/getbsize.3 b/lib/libc/gen/getbsize.3
new file mode 100644
index 0000000..1407051
--- /dev/null
+++ b/lib/libc/gen/getbsize.3
@@ -0,0 +1,78 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getbsize.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt GETBSIZE 3
+.Os
+.Sh NAME
+.Nm getbsize
+.Nd get user block size
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft char *
+.Fn getbsize "int *headerlenp" "long *blocksizep"
+.Sh DESCRIPTION
+The
+.Fn getbsize
+function determines the user's preferred block size based on the value of the
+.Dq BLOCKSIZE
+environment variable; see
+.Xr environ 7
+for details on its use and format.
+.Pp
+The
+.Fn getbsize
+function returns a pointer to a null-terminated string describing
+the block size, something like
+.Dq 1K-blocks .
+The memory referenced by
+.Fa headerlenp
+is filled in with the length of the string (not including the
+terminating null).
+The memory referenced by
+.Fa blocksizep
+is filled in with block size, in bytes.
+.Pp
+If the user's block size is unreasonable, a warning message is
+written to standard error and the returned information reflects
+a block size of 512 bytes.
+.Sh SEE ALSO
+.Xr df 1 ,
+.Xr du 1 ,
+.Xr ls 1 ,
+.Xr systat 1 ,
+.Xr environ 7
+.Sh HISTORY
+The
+.Fn getbsize
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/getbsize.c b/lib/libc/gen/getbsize.c
new file mode 100644
index 0000000..7e88e3f
--- /dev/null
+++ b/lib/libc/gen/getbsize.c
@@ -0,0 +1,106 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getbsize.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *
+getbsize(headerlenp, blocksizep)
+ int *headerlenp;
+ long *blocksizep;
+{
+ static char header[20];
+ long n, max, mul, blocksize;
+ char *ep, *p;
+ const char *form;
+
+#define KB (1024L)
+#define MB (1024L * 1024L)
+#define GB (1024L * 1024L * 1024L)
+#define MAXB GB /* No tera, peta, nor exa. */
+ form = "";
+ if ((p = getenv("BLOCKSIZE")) != NULL && *p != '\0') {
+ if ((n = strtol(p, &ep, 10)) < 0)
+ goto underflow;
+ if (n == 0)
+ n = 1;
+ if (*ep && ep[1])
+ goto fmterr;
+ switch (*ep) {
+ case 'G': case 'g':
+ form = "G";
+ max = MAXB / GB;
+ mul = GB;
+ break;
+ case 'K': case 'k':
+ form = "K";
+ max = MAXB / KB;
+ mul = KB;
+ break;
+ case 'M': case 'm':
+ form = "M";
+ max = MAXB / MB;
+ mul = MB;
+ break;
+ case '\0':
+ max = MAXB;
+ mul = 1;
+ break;
+ default:
+fmterr: warnx("%s: unknown blocksize", p);
+ n = 512;
+ max = MAXB;
+ mul = 1;
+ break;
+ }
+ if (n > max) {
+ warnx("maximum blocksize is %ldG", MAXB / GB);
+ n = max;
+ }
+ if ((blocksize = n * mul) < 512) {
+underflow: warnx("minimum blocksize is 512");
+ form = "";
+ blocksize = n = 512;
+ }
+ } else
+ blocksize = n = 512;
+
+ (void)snprintf(header, sizeof(header), "%ld%s-blocks", n, form);
+ *headerlenp = strlen(header);
+ *blocksizep = blocksize;
+ return (header);
+}
diff --git a/lib/libc/gen/getcap.3 b/lib/libc/gen/getcap.3
new file mode 100644
index 0000000..73826ae
--- /dev/null
+++ b/lib/libc/gen/getcap.3
@@ -0,0 +1,568 @@
+.\" Copyright (c) 1992, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Casey Leedom of Lawrence Livermore National Laboratory.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getcap.3 8.4 (Berkeley) 5/13/94
+.\" $FreeBSD$
+.\"
+.Dd March 22, 2002
+.Dt GETCAP 3
+.Os
+.Sh NAME
+.Nm cgetent ,
+.Nm cgetset ,
+.Nm cgetmatch ,
+.Nm cgetcap ,
+.Nm cgetnum ,
+.Nm cgetstr ,
+.Nm cgetustr ,
+.Nm cgetfirst ,
+.Nm cgetnext ,
+.Nm cgetclose
+.Nd capability database access routines
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fn cgetent "char **buf" "char **db_array" "const char *name"
+.Ft int
+.Fn cgetset "const char *ent"
+.Ft int
+.Fn cgetmatch "const char *buf" "const char *name"
+.Ft char *
+.Fn cgetcap "char *buf" "const char *cap" "int type"
+.Ft int
+.Fn cgetnum "char *buf" "const char *cap" "long *num"
+.Ft int
+.Fn cgetstr "char *buf" "const char *cap" "char **str"
+.Ft int
+.Fn cgetustr "char *buf" "const char *cap" "char **str"
+.Ft int
+.Fn cgetfirst "char **buf" "char **db_array"
+.Ft int
+.Fn cgetnext "char **buf" "char **db_array"
+.Ft int
+.Fn cgetclose "void"
+.Sh DESCRIPTION
+The
+.Fn cgetent
+function extracts the capability
+.Fa name
+from the database specified by the
+.Dv NULL
+terminated file array
+.Fa db_array
+and returns a pointer to a
+.Xr malloc 3 Ns \&'d
+copy of it in
+.Fa buf .
+The
+.Fn cgetent
+function will first look for files ending in
+.Pa .db
+(see
+.Xr cap_mkdb 1 )
+before accessing the ASCII file.
+The
+.Fa buf
+argument
+must be retained through all subsequent calls to
+.Fn cgetmatch ,
+.Fn cgetcap ,
+.Fn cgetnum ,
+.Fn cgetstr ,
+and
+.Fn cgetustr ,
+but may then be
+.Xr free 3 Ns \&'d .
+On success 0 is returned, 1 if the returned
+record contains an unresolved
+.Ic tc
+expansion,
+\-1 if the requested record could not be found,
+\-2 if a system error was encountered (could not open/read a file, etc.) also
+setting
+.Va errno ,
+and \-3 if a potential reference loop is detected (see
+.Ic tc=
+comments below).
+.Pp
+The
+.Fn cgetset
+function enables the addition of a character buffer containing a single capability
+record entry
+to the capability database.
+Conceptually, the entry is added as the first ``file'' in the database, and
+is therefore searched first on the call to
+.Fn cgetent .
+The entry is passed in
+.Fa ent .
+If
+.Fa ent
+is
+.Dv NULL ,
+the current entry is removed from the database.
+A call to
+.Fn cgetset
+must precede the database traversal.
+It must be called before the
+.Fn cgetent
+call.
+If a sequential access is being performed (see below), it must be called
+before the first sequential access call
+.Fn ( cgetfirst
+or
+.Fn cgetnext ) ,
+or be directly preceded by a
+.Fn cgetclose
+call.
+On success 0 is returned and \-1 on failure.
+.Pp
+The
+.Fn cgetmatch
+function will return 0 if
+.Fa name
+is one of the names of the capability record
+.Fa buf ,
+\-1 if
+not.
+.Pp
+The
+.Fn cgetcap
+function searches the capability record
+.Fa buf
+for the capability
+.Fa cap
+with type
+.Fa type .
+A
+.Fa type
+is specified using any single character.
+If a colon (`:') is used, an
+untyped capability will be searched for (see below for explanation of
+types).
+A pointer to the value of
+.Fa cap
+in
+.Fa buf
+is returned on success,
+.Dv NULL
+if the requested capability could not be
+found.
+The end of the capability value is signaled by a `:' or
+.Tn ASCII
+.Dv NUL
+(see below for capability database syntax).
+.Pp
+The
+.Fn cgetnum
+function retrieves the value of the numeric capability
+.Fa cap
+from the capability record pointed to by
+.Fa buf .
+The numeric value is returned in the
+.Ft long
+pointed to by
+.Fa num .
+0 is returned on success, \-1 if the requested numeric capability could not
+be found.
+.Pp
+The
+.Fn cgetstr
+function retrieves the value of the string capability
+.Fa cap
+from the capability record pointed to by
+.Fa buf .
+A pointer to a decoded,
+.Dv NUL
+terminated,
+.Xr malloc 3 Ns \&'d
+copy of the string is returned in the
+.Ft char *
+pointed to by
+.Fa str .
+The number of characters in the decoded string not including the trailing
+.Dv NUL
+is returned on success, \-1 if the requested string capability could not
+be found, \-2 if a system error was encountered (storage allocation
+failure).
+.Pp
+The
+.Fn cgetustr
+function is identical to
+.Fn cgetstr
+except that it does not expand special characters, but rather returns each
+character of the capability string literally.
+.Pp
+The
+.Fn cgetfirst
+and
+.Fn cgetnext
+functions comprise a function group that provides for sequential
+access of the
+.Dv NULL
+pointer terminated array of file names,
+.Fa db_array .
+The
+.Fn cgetfirst
+function returns the first record in the database and resets the access
+to the first record.
+The
+.Fn cgetnext
+function returns the next record in the database with respect to the
+record returned by the previous
+.Fn cgetfirst
+or
+.Fn cgetnext
+call.
+If there is no such previous call, the first record in the database is
+returned.
+Each record is returned in a
+.Xr malloc 3 Ns \&'d
+copy pointed to by
+.Fa buf .
+.Ic Tc
+expansion is done (see
+.Ic tc=
+comments below).
+Upon completion of the database 0 is returned, 1 is returned upon successful
+return of record with possibly more remaining (we have not reached the end of
+the database yet), 2 is returned if the record contains an unresolved
+.Ic tc
+expansion, \-1 is returned if a system error occurred, and \-2
+is returned if a potential reference loop is detected (see
+.Ic tc=
+comments below).
+Upon completion of database (0 return) the database is closed.
+.Pp
+The
+.Fn cgetclose
+function closes the sequential access and frees any memory and file descriptors
+being used.
+Note that it does not erase the buffer pushed by a call to
+.Fn cgetset .
+.Sh CAPABILITY DATABASE SYNTAX
+Capability databases are normally
+.Tn ASCII
+and may be edited with standard
+text editors.
+Blank lines and lines beginning with a `#' are comments
+and are ignored.
+Lines ending with a `\|\e' indicate that the next line
+is a continuation of the current line; the `\|\e' and following newline
+are ignored.
+Long lines are usually continued onto several physical
+lines by ending each line except the last with a `\|\e'.
+.Pp
+Capability databases consist of a series of records, one per logical
+line.
+Each record contains a variable number of `:'-separated fields
+(capabilities).
+Empty fields consisting entirely of white space
+characters (spaces and tabs) are ignored.
+.Pp
+The first capability of each record specifies its names, separated by `|'
+characters.
+These names are used to reference records in the database.
+By convention, the last name is usually a comment and is not intended as
+a lookup tag.
+For example, the
+.Em vt100
+record from the
+.Xr termcap 5
+database begins:
+.Pp
+.Dl "d0\||\|vt100\||\|vt100-am\||\|vt100am\||\|dec vt100:"
+.Pp
+giving four names that can be used to access the record.
+.Pp
+The remaining non-empty capabilities describe a set of (name, value)
+bindings, consisting of a names optionally followed by a typed value:
+.Pp
+.Bl -tag -width "nameTvalue" -compact
+.It name
+typeless [boolean] capability
+.Em name No "is present [true]"
+.It name Ns Em \&T Ns value
+capability
+.Pq Em name , \&T
+has value
+.Em value
+.It name@
+no capability
+.Em name No exists
+.It name Ns Em T Ns \&@
+capability
+.Pq Em name , T
+does not exist
+.El
+.Pp
+Names consist of one or more characters.
+Names may contain any character
+except `:', but it is usually best to restrict them to the printable
+characters and avoid use of graphics like `#', `=', `%', `@', etc.
+Types
+are single characters used to separate capability names from their
+associated typed values.
+Types may be any character except a `:'.
+Typically, graphics like `#', `=', `%', etc.\& are used.
+Values may be any
+number of characters and may contain any character except `:'.
+.Sh CAPABILITY DATABASE SEMANTICS
+Capability records describe a set of (name, value) bindings.
+Names may
+have multiple values bound to them.
+Different values for a name are
+distinguished by their
+.Fa types .
+The
+.Fn cgetcap
+function will return a pointer to a value of a name given the capability
+name and the type of the value.
+.Pp
+The types `#' and `=' are conventionally used to denote numeric and
+string typed values, but no restriction on those types is enforced.
+The
+functions
+.Fn cgetnum
+and
+.Fn cgetstr
+can be used to implement the traditional syntax and semantics of `#'
+and `='.
+Typeless capabilities are typically used to denote boolean objects with
+presence or absence indicating truth and false values respectively.
+This interpretation is conveniently represented by:
+.Pp
+.Dl "(getcap(buf, name, ':') != NULL)"
+.Pp
+A special capability,
+.Ic tc= name ,
+is used to indicate that the record specified by
+.Fa name
+should be substituted for the
+.Ic tc
+capability.
+.Ic Tc
+capabilities may interpolate records which also contain
+.Ic tc
+capabilities and more than one
+.Ic tc
+capability may be used in a record.
+A
+.Ic tc
+expansion scope (i.e., where the argument is searched for) contains the
+file in which the
+.Ic tc
+is declared and all subsequent files in the file array.
+.Pp
+When a database is searched for a capability record, the first matching
+record in the search is returned.
+When a record is scanned for a
+capability, the first matching capability is returned; the capability
+.Ic :nameT@:
+will hide any following definition of a value of type
+.Em T
+for
+.Fa name ;
+and the capability
+.Ic :name@:
+will prevent any following values of
+.Fa name
+from being seen.
+.Pp
+These features combined with
+.Ic tc
+capabilities can be used to generate variations of other databases and
+records by either adding new capabilities, overriding definitions with new
+definitions, or hiding following definitions via `@' capabilities.
+.Sh EXAMPLES
+.Bd -unfilled -offset indent
+example\||\|an example of binding multiple values to names:\e
+ :foo%bar:foo^blah:foo@:\e
+ :abc%xyz:abc^frap:abc$@:\e
+ :tc=more:
+.Ed
+.Pp
+The capability foo has two values bound to it (bar of type `%' and blah of
+type `^') and any other value bindings are hidden.
+The capability abc
+also has two values bound but only a value of type `$' is prevented from
+being defined in the capability record more.
+.Bd -unfilled -offset indent
+file1:
+ new\||\|new_record\||\|a modification of "old":\e
+ :fript=bar:who-cares@:tc=old:blah:tc=extensions:
+file2:
+ old\||\|old_record\||\|an old database record:\e
+ :fript=foo:who-cares:glork#200:
+.Ed
+.Pp
+The records are extracted by calling
+.Fn cgetent
+with file1 preceding file2.
+In the capability record new in file1, fript=bar overrides the definition
+of fript=foo interpolated from the capability record old in file2,
+who-cares@ prevents the definition of any who-cares definitions in old
+from being seen, glork#200 is inherited from old, and blah and anything
+defined by the record extensions is added to those definitions in old.
+Note that the position of the fript=bar and who-cares@ definitions before
+tc=old is important here.
+If they were after, the definitions in old
+would take precedence.
+.Sh CGETNUM AND CGETSTR SYNTAX AND SEMANTICS
+Two types are predefined by
+.Fn cgetnum
+and
+.Fn cgetstr :
+.Pp
+.Bl -tag -width "nameXnumber" -compact
+.It Em name Ns \&# Ns Em number
+numeric capability
+.Em name
+has value
+.Em number
+.It Em name Ns = Ns Em string
+string capability
+.Em name
+has value
+.Em string
+.It Em name Ns \&#@
+the numeric capability
+.Em name
+does not exist
+.It Em name Ns \&=@
+the string capability
+.Em name
+does not exist
+.El
+.Pp
+Numeric capability values may be given in one of three numeric bases.
+If the number starts with either
+.Ql 0x
+or
+.Ql 0X
+it is interpreted as a hexadecimal number (both upper and lower case a-f
+may be used to denote the extended hexadecimal digits).
+Otherwise, if the number starts with a
+.Ql 0
+it is interpreted as an octal number.
+Otherwise the number is interpreted as a decimal number.
+.Pp
+String capability values may contain any character.
+Non-printable
+.Dv ASCII
+codes, new lines, and colons may be conveniently represented by the use
+of escape sequences:
+.Bl -column "\e\|X,X\e\|X" "(ASCII octal nnn)"
+^X ('X' & 037) control-X
+\e\|b, \e\|B (ASCII 010) backspace
+\e\|t, \e\|T (ASCII 011) tab
+\e\|n, \e\|N (ASCII 012) line feed (newline)
+\e\|f, \e\|F (ASCII 014) form feed
+\e\|r, \e\|R (ASCII 015) carriage return
+\e\|e, \e\|E (ASCII 027) escape
+\e\|c, \e\|C (:) colon
+\e\|\e (\e\|) back slash
+\e\|^ (^) caret
+\e\|nnn (ASCII octal nnn)
+.El
+.Pp
+A `\|\e' may be followed by up to three octal digits directly specifies
+the numeric code for a character.
+The use of
+.Tn ASCII
+.Dv NUL Ns s ,
+while easily
+encoded, causes all sorts of problems and must be used with care since
+.Dv NUL Ns s
+are typically used to denote the end of strings; many applications
+use `\e\|200' to represent a
+.Dv NUL .
+.Sh DIAGNOSTICS
+The
+.Fn cgetent ,
+.Fn cgetset ,
+.Fn cgetmatch ,
+.Fn cgetnum ,
+.Fn cgetstr ,
+.Fn cgetustr ,
+.Fn cgetfirst ,
+and
+.Fn cgetnext
+functions
+return a value greater than or equal to 0 on success and a value less
+than 0 on failure.
+The
+.Fn cgetcap
+function returns a character pointer on success and a
+.Dv NULL
+on failure.
+.Pp
+The
+.Fn cgetent ,
+and
+.Fn cgetset
+functions may fail and set
+.Va errno
+for any of the errors specified for the library functions:
+.Xr fopen 3 ,
+.Xr fclose 3 ,
+.Xr open 2 ,
+and
+.Xr close 2 .
+.Pp
+The
+.Fn cgetent ,
+.Fn cgetset ,
+.Fn cgetstr ,
+and
+.Fn cgetustr
+functions
+may fail and set
+.Va errno
+as follows:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+No memory to allocate.
+.El
+.Sh SEE ALSO
+.Xr cap_mkdb 1 ,
+.Xr malloc 3
+.Sh BUGS
+Colons (`:') cannot be used in names, types, or values.
+.Pp
+There are no checks for
+.Ic tc Ns = Ns Ic name
+loops in
+.Fn cgetent .
+.Pp
+The buffer added to the database by a call to
+.Fn cgetset
+is not unique to the database but is rather prepended to any database used.
diff --git a/lib/libc/gen/getcap.c b/lib/libc/gen/getcap.c
new file mode 100644
index 0000000..2700d3d
--- /dev/null
+++ b/lib/libc/gen/getcap.c
@@ -0,0 +1,1055 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Casey Leedom of Lawrence Livermore National Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getcap.c 8.3 (Berkeley) 3/25/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <db.h>
+
+#define BFRAG 1024
+#define BSIZE 1024
+#define ESC ('[' & 037) /* ASCII ESC */
+#define MAX_RECURSION 32 /* maximum getent recursion */
+#define SFRAG 100 /* cgetstr mallocs in SFRAG chunks */
+
+#define RECOK (char)0
+#define TCERR (char)1
+#define SHADOW (char)2
+
+static size_t topreclen; /* toprec length */
+static char *toprec; /* Additional record specified by cgetset() */
+static int gottoprec; /* Flag indicating retrieval of toprecord */
+
+static int cdbget(DB *, char **, const char *);
+static int getent(char **, u_int *, char **, int, const char *, int, char *);
+static int nfcmp(char *, char *);
+
+/*
+ * Cgetset() allows the addition of a user specified buffer to be added
+ * to the database array, in effect "pushing" the buffer on top of the
+ * virtual database. 0 is returned on success, -1 on failure.
+ */
+int
+cgetset(const char *ent)
+{
+ if (ent == NULL) {
+ if (toprec)
+ free(toprec);
+ toprec = NULL;
+ topreclen = 0;
+ return (0);
+ }
+ topreclen = strlen(ent);
+ if ((toprec = malloc (topreclen + 1)) == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ gottoprec = 0;
+ (void)strcpy(toprec, ent);
+ return (0);
+}
+
+/*
+ * Cgetcap searches the capability record buf for the capability cap with
+ * type `type'. A pointer to the value of cap is returned on success, NULL
+ * if the requested capability couldn't be found.
+ *
+ * Specifying a type of ':' means that nothing should follow cap (:cap:).
+ * In this case a pointer to the terminating ':' or NUL will be returned if
+ * cap is found.
+ *
+ * If (cap, '@') or (cap, terminator, '@') is found before (cap, terminator)
+ * return NULL.
+ */
+char *
+cgetcap(char *buf, const char *cap, int type)
+{
+ char *bp;
+ const char *cp;
+
+ bp = buf;
+ for (;;) {
+ /*
+ * Skip past the current capability field - it's either the
+ * name field if this is the first time through the loop, or
+ * the remainder of a field whose name failed to match cap.
+ */
+ for (;;)
+ if (*bp == '\0')
+ return (NULL);
+ else
+ if (*bp++ == ':')
+ break;
+
+ /*
+ * Try to match (cap, type) in buf.
+ */
+ for (cp = cap; *cp == *bp && *bp != '\0'; cp++, bp++)
+ continue;
+ if (*cp != '\0')
+ continue;
+ if (*bp == '@')
+ return (NULL);
+ if (type == ':') {
+ if (*bp != '\0' && *bp != ':')
+ continue;
+ return(bp);
+ }
+ if (*bp != type)
+ continue;
+ bp++;
+ return (*bp == '@' ? NULL : bp);
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * Cgetent extracts the capability record name from the NULL terminated file
+ * array db_array and returns a pointer to a malloc'd copy of it in buf.
+ * Buf must be retained through all subsequent calls to cgetcap, cgetnum,
+ * cgetflag, and cgetstr, but may then be free'd. 0 is returned on success,
+ * -1 if the requested record couldn't be found, -2 if a system error was
+ * encountered (couldn't open/read a file, etc.), and -3 if a potential
+ * reference loop is detected.
+ */
+int
+cgetent(char **buf, char **db_array, const char *name)
+{
+ u_int dummy;
+
+ return (getent(buf, &dummy, db_array, -1, name, 0, NULL));
+}
+
+/*
+ * Getent implements the functions of cgetent. If fd is non-negative,
+ * *db_array has already been opened and fd is the open file descriptor. We
+ * do this to save time and avoid using up file descriptors for tc=
+ * recursions.
+ *
+ * Getent returns the same success/failure codes as cgetent. On success, a
+ * pointer to a malloc'ed capability record with all tc= capabilities fully
+ * expanded and its length (not including trailing ASCII NUL) are left in
+ * *cap and *len.
+ *
+ * Basic algorithm:
+ * + Allocate memory incrementally as needed in chunks of size BFRAG
+ * for capability buffer.
+ * + Recurse for each tc=name and interpolate result. Stop when all
+ * names interpolated, a name can't be found, or depth exceeds
+ * MAX_RECURSION.
+ */
+static int
+getent(char **cap, u_int *len, char **db_array, int fd, const char *name,
+ int depth, char *nfield)
+{
+ DB *capdbp;
+ char *r_end, *rp, **db_p;
+ int myfd, eof, foundit, retval;
+ char *record, *cbuf;
+ int tc_not_resolved;
+ char pbuf[_POSIX_PATH_MAX];
+
+ /*
+ * Return with ``loop detected'' error if we've recursed more than
+ * MAX_RECURSION times.
+ */
+ if (depth > MAX_RECURSION)
+ return (-3);
+
+ /*
+ * Check if we have a top record from cgetset().
+ */
+ if (depth == 0 && toprec != NULL && cgetmatch(toprec, name) == 0) {
+ if ((record = malloc (topreclen + BFRAG)) == NULL) {
+ errno = ENOMEM;
+ return (-2);
+ }
+ (void)strcpy(record, toprec);
+ myfd = 0;
+ db_p = db_array;
+ rp = record + topreclen + 1;
+ r_end = rp + BFRAG;
+ goto tc_exp;
+ }
+ /*
+ * Allocate first chunk of memory.
+ */
+ if ((record = malloc(BFRAG)) == NULL) {
+ errno = ENOMEM;
+ return (-2);
+ }
+ r_end = record + BFRAG;
+ foundit = 0;
+ /*
+ * Loop through database array until finding the record.
+ */
+
+ for (db_p = db_array; *db_p != NULL; db_p++) {
+ eof = 0;
+
+ /*
+ * Open database if not already open.
+ */
+
+ if (fd >= 0) {
+ (void)lseek(fd, (off_t)0, SEEK_SET);
+ myfd = 0;
+ } else {
+ (void)snprintf(pbuf, sizeof(pbuf), "%s.db", *db_p);
+ if ((capdbp = dbopen(pbuf, O_RDONLY, 0, DB_HASH, 0))
+ != NULL) {
+ free(record);
+ retval = cdbget(capdbp, &record, name);
+ if (retval < 0) {
+ /* no record available */
+ (void)capdbp->close(capdbp);
+ return (retval);
+ }
+ /* save the data; close frees it */
+ cbuf = strdup(record);
+ if (capdbp->close(capdbp) < 0) {
+ free(cbuf);
+ return (-2);
+ }
+ if (cbuf == NULL) {
+ errno = ENOMEM;
+ return (-2);
+ }
+ *len = strlen(cbuf);
+ *cap = cbuf;
+ return (retval);
+ } else {
+ fd = _open(*db_p, O_RDONLY, 0);
+ if (fd < 0)
+ continue;
+ myfd = 1;
+ }
+ }
+ /*
+ * Find the requested capability record ...
+ */
+ {
+ char buf[BUFSIZ];
+ char *b_end, *bp;
+ int c;
+
+ /*
+ * Loop invariants:
+ * There is always room for one more character in record.
+ * R_end always points just past end of record.
+ * Rp always points just past last character in record.
+ * B_end always points just past last character in buf.
+ * Bp always points at next character in buf.
+ */
+ b_end = buf;
+ bp = buf;
+ for (;;) {
+
+ /*
+ * Read in a line implementing (\, newline)
+ * line continuation.
+ */
+ rp = record;
+ for (;;) {
+ if (bp >= b_end) {
+ int n;
+
+ n = _read(fd, buf, sizeof(buf));
+ if (n <= 0) {
+ if (myfd)
+ (void)_close(fd);
+ if (n < 0) {
+ free(record);
+ return (-2);
+ } else {
+ fd = -1;
+ eof = 1;
+ break;
+ }
+ }
+ b_end = buf+n;
+ bp = buf;
+ }
+
+ c = *bp++;
+ if (c == '\n') {
+ if (rp > record && *(rp-1) == '\\') {
+ rp--;
+ continue;
+ } else
+ break;
+ }
+ *rp++ = c;
+
+ /*
+ * Enforce loop invariant: if no room
+ * left in record buffer, try to get
+ * some more.
+ */
+ if (rp >= r_end) {
+ u_int pos;
+ size_t newsize;
+
+ pos = rp - record;
+ newsize = r_end - record + BFRAG;
+ record = reallocf(record, newsize);
+ if (record == NULL) {
+ errno = ENOMEM;
+ if (myfd)
+ (void)_close(fd);
+ return (-2);
+ }
+ r_end = record + newsize;
+ rp = record + pos;
+ }
+ }
+ /* loop invariant let's us do this */
+ *rp++ = '\0';
+
+ /*
+ * If encountered eof check next file.
+ */
+ if (eof)
+ break;
+
+ /*
+ * Toss blank lines and comments.
+ */
+ if (*record == '\0' || *record == '#')
+ continue;
+
+ /*
+ * See if this is the record we want ...
+ */
+ if (cgetmatch(record, name) == 0) {
+ if (nfield == NULL || !nfcmp(nfield, record)) {
+ foundit = 1;
+ break; /* found it! */
+ }
+ }
+ }
+ }
+ if (foundit)
+ break;
+ }
+
+ if (!foundit) {
+ free(record);
+ return (-1);
+ }
+
+ /*
+ * Got the capability record, but now we have to expand all tc=name
+ * references in it ...
+ */
+tc_exp: {
+ char *newicap, *s;
+ int newilen;
+ u_int ilen;
+ int diff, iret, tclen;
+ char *icap, *scan, *tc, *tcstart, *tcend;
+
+ /*
+ * Loop invariants:
+ * There is room for one more character in record.
+ * R_end points just past end of record.
+ * Rp points just past last character in record.
+ * Scan points at remainder of record that needs to be
+ * scanned for tc=name constructs.
+ */
+ scan = record;
+ tc_not_resolved = 0;
+ for (;;) {
+ if ((tc = cgetcap(scan, "tc", '=')) == NULL)
+ break;
+
+ /*
+ * Find end of tc=name and stomp on the trailing `:'
+ * (if present) so we can use it to call ourselves.
+ */
+ s = tc;
+ for (;;)
+ if (*s == '\0')
+ break;
+ else
+ if (*s++ == ':') {
+ *(s - 1) = '\0';
+ break;
+ }
+ tcstart = tc - 3;
+ tclen = s - tcstart;
+ tcend = s;
+
+ iret = getent(&icap, &ilen, db_p, fd, tc, depth+1,
+ NULL);
+ newicap = icap; /* Put into a register. */
+ newilen = ilen;
+ if (iret != 0) {
+ /* an error */
+ if (iret < -1) {
+ if (myfd)
+ (void)_close(fd);
+ free(record);
+ return (iret);
+ }
+ if (iret == 1)
+ tc_not_resolved = 1;
+ /* couldn't resolve tc */
+ if (iret == -1) {
+ *(s - 1) = ':';
+ scan = s - 1;
+ tc_not_resolved = 1;
+ continue;
+
+ }
+ }
+ /* not interested in name field of tc'ed record */
+ s = newicap;
+ for (;;)
+ if (*s == '\0')
+ break;
+ else
+ if (*s++ == ':')
+ break;
+ newilen -= s - newicap;
+ newicap = s;
+
+ /* make sure interpolated record is `:'-terminated */
+ s += newilen;
+ if (*(s-1) != ':') {
+ *s = ':'; /* overwrite NUL with : */
+ newilen++;
+ }
+
+ /*
+ * Make sure there's enough room to insert the
+ * new record.
+ */
+ diff = newilen - tclen;
+ if (diff >= r_end - rp) {
+ u_int pos, tcpos, tcposend;
+ size_t newsize;
+
+ pos = rp - record;
+ newsize = r_end - record + diff + BFRAG;
+ tcpos = tcstart - record;
+ tcposend = tcend - record;
+ record = reallocf(record, newsize);
+ if (record == NULL) {
+ errno = ENOMEM;
+ if (myfd)
+ (void)_close(fd);
+ free(icap);
+ return (-2);
+ }
+ r_end = record + newsize;
+ rp = record + pos;
+ tcstart = record + tcpos;
+ tcend = record + tcposend;
+ }
+
+ /*
+ * Insert tc'ed record into our record.
+ */
+ s = tcstart + newilen;
+ bcopy(tcend, s, rp - tcend);
+ bcopy(newicap, tcstart, newilen);
+ rp += diff;
+ free(icap);
+
+ /*
+ * Start scan on `:' so next cgetcap works properly
+ * (cgetcap always skips first field).
+ */
+ scan = s-1;
+ }
+
+ }
+ /*
+ * Close file (if we opened it), give back any extra memory, and
+ * return capability, length and success.
+ */
+ if (myfd)
+ (void)_close(fd);
+ *len = rp - record - 1; /* don't count NUL */
+ if (r_end > rp)
+ if ((record =
+ reallocf(record, (size_t)(rp - record))) == NULL) {
+ errno = ENOMEM;
+ return (-2);
+ }
+
+ *cap = record;
+ if (tc_not_resolved)
+ return (1);
+ return (0);
+}
+
+static int
+cdbget(DB *capdbp, char **bp, const char *name)
+{
+ DBT key, data;
+ char *namebuf;
+
+ namebuf = strdup(name);
+ if (namebuf == NULL)
+ return (-2);
+ key.data = namebuf;
+ key.size = strlen(namebuf);
+
+ for (;;) {
+ /* Get the reference. */
+ switch(capdbp->get(capdbp, &key, &data, 0)) {
+ case -1:
+ free(namebuf);
+ return (-2);
+ case 1:
+ free(namebuf);
+ return (-1);
+ }
+
+ /* If not an index to another record, leave. */
+ if (((char *)data.data)[0] != SHADOW)
+ break;
+
+ key.data = (char *)data.data + 1;
+ key.size = data.size - 1;
+ }
+
+ *bp = (char *)data.data + 1;
+ free(namebuf);
+ return (((char *)(data.data))[0] == TCERR ? 1 : 0);
+}
+
+/*
+ * Cgetmatch will return 0 if name is one of the names of the capability
+ * record buf, -1 if not.
+ */
+int
+cgetmatch(const char *buf, const char *name)
+{
+ const char *np, *bp;
+
+ if (name == NULL || *name == '\0')
+ return -1;
+
+ /*
+ * Start search at beginning of record.
+ */
+ bp = buf;
+ for (;;) {
+ /*
+ * Try to match a record name.
+ */
+ np = name;
+ for (;;)
+ if (*np == '\0')
+ if (*bp == '|' || *bp == ':' || *bp == '\0')
+ return (0);
+ else
+ break;
+ else
+ if (*bp++ != *np++)
+ break;
+
+ /*
+ * Match failed, skip to next name in record.
+ */
+ bp--; /* a '|' or ':' may have stopped the match */
+ for (;;)
+ if (*bp == '\0' || *bp == ':')
+ return (-1); /* match failed totally */
+ else
+ if (*bp++ == '|')
+ break; /* found next name */
+ }
+}
+
+
+
+
+
+int
+cgetfirst(char **buf, char **db_array)
+{
+ (void)cgetclose();
+ return (cgetnext(buf, db_array));
+}
+
+static FILE *pfp;
+static int slash;
+static char **dbp;
+
+int
+cgetclose(void)
+{
+ if (pfp != NULL) {
+ (void)fclose(pfp);
+ pfp = NULL;
+ }
+ dbp = NULL;
+ gottoprec = 0;
+ slash = 0;
+ return(0);
+}
+
+/*
+ * Cgetnext() gets either the first or next entry in the logical database
+ * specified by db_array. It returns 0 upon completion of the database, 1
+ * upon returning an entry with more remaining, and -1 if an error occurs.
+ */
+int
+cgetnext(char **bp, char **db_array)
+{
+ size_t len;
+ int done, hadreaderr, savederrno, status;
+ char *cp, *line, *rp, *np, buf[BSIZE], nbuf[BSIZE];
+ u_int dummy;
+
+ if (dbp == NULL)
+ dbp = db_array;
+
+ if (pfp == NULL && (pfp = fopen(*dbp, "r")) == NULL) {
+ (void)cgetclose();
+ return (-1);
+ }
+ for (;;) {
+ if (toprec && !gottoprec) {
+ gottoprec = 1;
+ line = toprec;
+ } else {
+ line = fgetln(pfp, &len);
+ if (line == NULL && pfp) {
+ hadreaderr = ferror(pfp);
+ if (hadreaderr)
+ savederrno = errno;
+ fclose(pfp);
+ pfp = NULL;
+ if (hadreaderr) {
+ cgetclose();
+ errno = savederrno;
+ return (-1);
+ } else {
+ if (*++dbp == NULL) {
+ (void)cgetclose();
+ return (0);
+ } else if ((pfp =
+ fopen(*dbp, "r")) == NULL) {
+ (void)cgetclose();
+ return (-1);
+ } else
+ continue;
+ }
+ } else
+ line[len - 1] = '\0';
+ if (len == 1) {
+ slash = 0;
+ continue;
+ }
+ if (isspace((unsigned char)*line) ||
+ *line == ':' || *line == '#' || slash) {
+ if (line[len - 2] == '\\')
+ slash = 1;
+ else
+ slash = 0;
+ continue;
+ }
+ if (line[len - 2] == '\\')
+ slash = 1;
+ else
+ slash = 0;
+ }
+
+
+ /*
+ * Line points to a name line.
+ */
+ done = 0;
+ np = nbuf;
+ for (;;) {
+ for (cp = line; *cp != '\0'; cp++) {
+ if (*cp == ':') {
+ *np++ = ':';
+ done = 1;
+ break;
+ }
+ if (*cp == '\\')
+ break;
+ *np++ = *cp;
+ }
+ if (done) {
+ *np = '\0';
+ break;
+ } else { /* name field extends beyond the line */
+ line = fgetln(pfp, &len);
+ if (line == NULL && pfp) {
+ /* Name extends beyond the EOF! */
+ hadreaderr = ferror(pfp);
+ if (hadreaderr)
+ savederrno = errno;
+ fclose(pfp);
+ pfp = NULL;
+ if (hadreaderr) {
+ cgetclose();
+ errno = savederrno;
+ return (-1);
+ } else {
+ cgetclose();
+ return (-1);
+ }
+ } else
+ line[len - 1] = '\0';
+ }
+ }
+ rp = buf;
+ for(cp = nbuf; *cp != '\0'; cp++)
+ if (*cp == '|' || *cp == ':')
+ break;
+ else
+ *rp++ = *cp;
+
+ *rp = '\0';
+ /*
+ * XXX
+ * Last argument of getent here should be nbuf if we want true
+ * sequential access in the case of duplicates.
+ * With NULL, getent will return the first entry found
+ * rather than the duplicate entry record. This is a
+ * matter of semantics that should be resolved.
+ */
+ status = getent(bp, &dummy, db_array, -1, buf, 0, NULL);
+ if (status == -2 || status == -3)
+ (void)cgetclose();
+
+ return (status + 1);
+ }
+ /* NOTREACHED */
+}
+
+/*
+ * Cgetstr retrieves the value of the string capability cap from the
+ * capability record pointed to by buf. A pointer to a decoded, NUL
+ * terminated, malloc'd copy of the string is returned in the char *
+ * pointed to by str. The length of the string not including the trailing
+ * NUL is returned on success, -1 if the requested string capability
+ * couldn't be found, -2 if a system error was encountered (storage
+ * allocation failure).
+ */
+int
+cgetstr(char *buf, const char *cap, char **str)
+{
+ u_int m_room;
+ char *bp, *mp;
+ int len;
+ char *mem;
+
+ /*
+ * Find string capability cap
+ */
+ bp = cgetcap(buf, cap, '=');
+ if (bp == NULL)
+ return (-1);
+
+ /*
+ * Conversion / storage allocation loop ... Allocate memory in
+ * chunks SFRAG in size.
+ */
+ if ((mem = malloc(SFRAG)) == NULL) {
+ errno = ENOMEM;
+ return (-2); /* couldn't even allocate the first fragment */
+ }
+ m_room = SFRAG;
+ mp = mem;
+
+ while (*bp != ':' && *bp != '\0') {
+ /*
+ * Loop invariants:
+ * There is always room for one more character in mem.
+ * Mp always points just past last character in mem.
+ * Bp always points at next character in buf.
+ */
+ if (*bp == '^') {
+ bp++;
+ if (*bp == ':' || *bp == '\0')
+ break; /* drop unfinished escape */
+ if (*bp == '?') {
+ *mp++ = '\177';
+ bp++;
+ } else
+ *mp++ = *bp++ & 037;
+ } else if (*bp == '\\') {
+ bp++;
+ if (*bp == ':' || *bp == '\0')
+ break; /* drop unfinished escape */
+ if ('0' <= *bp && *bp <= '7') {
+ int n, i;
+
+ n = 0;
+ i = 3; /* maximum of three octal digits */
+ do {
+ n = n * 8 + (*bp++ - '0');
+ } while (--i && '0' <= *bp && *bp <= '7');
+ *mp++ = n;
+ }
+ else switch (*bp++) {
+ case 'b': case 'B':
+ *mp++ = '\b';
+ break;
+ case 't': case 'T':
+ *mp++ = '\t';
+ break;
+ case 'n': case 'N':
+ *mp++ = '\n';
+ break;
+ case 'f': case 'F':
+ *mp++ = '\f';
+ break;
+ case 'r': case 'R':
+ *mp++ = '\r';
+ break;
+ case 'e': case 'E':
+ *mp++ = ESC;
+ break;
+ case 'c': case 'C':
+ *mp++ = ':';
+ break;
+ default:
+ /*
+ * Catches '\', '^', and
+ * everything else.
+ */
+ *mp++ = *(bp-1);
+ break;
+ }
+ } else
+ *mp++ = *bp++;
+ m_room--;
+
+ /*
+ * Enforce loop invariant: if no room left in current
+ * buffer, try to get some more.
+ */
+ if (m_room == 0) {
+ size_t size = mp - mem;
+
+ if ((mem = reallocf(mem, size + SFRAG)) == NULL)
+ return (-2);
+ m_room = SFRAG;
+ mp = mem + size;
+ }
+ }
+ *mp++ = '\0'; /* loop invariant let's us do this */
+ m_room--;
+ len = mp - mem - 1;
+
+ /*
+ * Give back any extra memory and return value and success.
+ */
+ if (m_room != 0)
+ if ((mem = reallocf(mem, (size_t)(mp - mem))) == NULL)
+ return (-2);
+ *str = mem;
+ return (len);
+}
+
+/*
+ * Cgetustr retrieves the value of the string capability cap from the
+ * capability record pointed to by buf. The difference between cgetustr()
+ * and cgetstr() is that cgetustr does not decode escapes but rather treats
+ * all characters literally. A pointer to a NUL terminated malloc'd
+ * copy of the string is returned in the char pointed to by str. The
+ * length of the string not including the trailing NUL is returned on success,
+ * -1 if the requested string capability couldn't be found, -2 if a system
+ * error was encountered (storage allocation failure).
+ */
+int
+cgetustr(char *buf, const char *cap, char **str)
+{
+ u_int m_room;
+ char *bp, *mp;
+ int len;
+ char *mem;
+
+ /*
+ * Find string capability cap
+ */
+ if ((bp = cgetcap(buf, cap, '=')) == NULL)
+ return (-1);
+
+ /*
+ * Conversion / storage allocation loop ... Allocate memory in
+ * chunks SFRAG in size.
+ */
+ if ((mem = malloc(SFRAG)) == NULL) {
+ errno = ENOMEM;
+ return (-2); /* couldn't even allocate the first fragment */
+ }
+ m_room = SFRAG;
+ mp = mem;
+
+ while (*bp != ':' && *bp != '\0') {
+ /*
+ * Loop invariants:
+ * There is always room for one more character in mem.
+ * Mp always points just past last character in mem.
+ * Bp always points at next character in buf.
+ */
+ *mp++ = *bp++;
+ m_room--;
+
+ /*
+ * Enforce loop invariant: if no room left in current
+ * buffer, try to get some more.
+ */
+ if (m_room == 0) {
+ size_t size = mp - mem;
+
+ if ((mem = reallocf(mem, size + SFRAG)) == NULL)
+ return (-2);
+ m_room = SFRAG;
+ mp = mem + size;
+ }
+ }
+ *mp++ = '\0'; /* loop invariant let's us do this */
+ m_room--;
+ len = mp - mem - 1;
+
+ /*
+ * Give back any extra memory and return value and success.
+ */
+ if (m_room != 0)
+ if ((mem = reallocf(mem, (size_t)(mp - mem))) == NULL)
+ return (-2);
+ *str = mem;
+ return (len);
+}
+
+/*
+ * Cgetnum retrieves the value of the numeric capability cap from the
+ * capability record pointed to by buf. The numeric value is returned in
+ * the long pointed to by num. 0 is returned on success, -1 if the requested
+ * numeric capability couldn't be found.
+ */
+int
+cgetnum(char *buf, const char *cap, long *num)
+{
+ long n;
+ int base, digit;
+ char *bp;
+
+ /*
+ * Find numeric capability cap
+ */
+ bp = cgetcap(buf, cap, '#');
+ if (bp == NULL)
+ return (-1);
+
+ /*
+ * Look at value and determine numeric base:
+ * 0x... or 0X... hexadecimal,
+ * else 0... octal,
+ * else decimal.
+ */
+ if (*bp == '0') {
+ bp++;
+ if (*bp == 'x' || *bp == 'X') {
+ bp++;
+ base = 16;
+ } else
+ base = 8;
+ } else
+ base = 10;
+
+ /*
+ * Conversion loop ...
+ */
+ n = 0;
+ for (;;) {
+ if ('0' <= *bp && *bp <= '9')
+ digit = *bp - '0';
+ else if ('a' <= *bp && *bp <= 'f')
+ digit = 10 + *bp - 'a';
+ else if ('A' <= *bp && *bp <= 'F')
+ digit = 10 + *bp - 'A';
+ else
+ break;
+
+ if (digit >= base)
+ break;
+
+ n = n * base + digit;
+ bp++;
+ }
+
+ /*
+ * Return value and success.
+ */
+ *num = n;
+ return (0);
+}
+
+
+/*
+ * Compare name field of record.
+ */
+static int
+nfcmp(char *nf, char *rec)
+{
+ char *cp, tmp;
+ int ret;
+
+ for (cp = rec; *cp != ':'; cp++)
+ ;
+
+ tmp = *(cp + 1);
+ *(cp + 1) = '\0';
+ ret = strcmp(nf, rec);
+ *(cp + 1) = tmp;
+
+ return (ret);
+}
diff --git a/lib/libc/gen/getcontext.3 b/lib/libc/gen/getcontext.3
new file mode 100644
index 0000000..5b801fd
--- /dev/null
+++ b/lib/libc/gen/getcontext.3
@@ -0,0 +1,148 @@
+.\" Copyright (c) 2002 Packet Design, LLC.
+.\" All rights reserved.
+.\"
+.\" Subject to the following obligations and disclaimer of warranty,
+.\" use and redistribution of this software, in source or object code
+.\" forms, with or without modifications are expressly permitted by
+.\" Packet Design; provided, however, that:
+.\"
+.\" (i) Any and all reproductions of the source or object code
+.\" must include the copyright notice above and the following
+.\" disclaimer of warranties; and
+.\" (ii) No rights are granted, in any manner or form, to use
+.\" Packet Design trademarks, including the mark "PACKET DESIGN"
+.\" on advertising, endorsements, or otherwise except as such
+.\" appears in the above copyright notice or in the software.
+.\"
+.\" THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
+.\" TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
+.\" REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
+.\" THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
+.\" OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
+.\" OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
+.\" OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
+.\" RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
+.\" LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
+.\" OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
+.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
+.\" DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
+.\" USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
+.\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+.\" THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
+.\" THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 26, 2011
+.Dt GETCONTEXT 3
+.Os
+.Sh NAME
+.Nm getcontext , getcontextx , setcontext
+.Nd get and set user thread context
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ucontext.h
+.Ft int
+.Fn getcontext "ucontext_t *ucp"
+.Ft int
+.Fn setcontext "const ucontext_t *ucp"
+.Sh DESCRIPTION
+The
+.Fn getcontext
+function
+saves the current thread's execution context in the structure pointed to by
+.Fa ucp .
+This saved context may then later be restored by calling
+.Fn setcontext .
+.Pp
+The
+.Fn getcontextx
+function saves the current execution context in the newly allocated structure
+.Vt ucontext_t ,
+which is returned on success.
+If architecture defines additional CPU states that can be stored in extended
+blocks referenced from the
+.Vt ucontext_t ,
+the memory for them may be allocated and their context also stored.
+Memory returned by
+.Fn getcontextx
+function shall be freed using
+.Fn free 3 .
+.Pp
+The
+.Fn setcontext
+function
+makes a previously saved thread context the current thread context, i.e.,
+the current context is lost and
+.Fn setcontext
+does not return.
+Instead, execution continues in the context specified by
+.Fa ucp ,
+which must have been previously initialized by a call to
+.Fn getcontext ,
+.Xr makecontext 3 ,
+or by being passed as an argument to a signal handler (see
+.Xr sigaction 2 ) .
+.Pp
+If
+.Fa ucp
+was initialized by
+.Fn getcontext ,
+then execution continues as if the original
+.Fn getcontext
+call had just returned (again).
+.Pp
+If
+.Fa ucp
+was initialized by
+.Xr makecontext 3 ,
+execution continues with the invocation of the function specified to
+.Xr makecontext 3 .
+When that function returns,
+.Fa "ucp->uc_link"
+determines what happens next:
+if
+.Fa "ucp->uc_link"
+is
+.Dv NULL ,
+the process exits;
+otherwise,
+.Fn setcontext "ucp->uc_link"
+is implicitly invoked.
+.Pp
+If
+.Fa ucp
+was initialized by the invocation of a signal handler, execution continues
+at the point the thread was interrupted by the signal.
+.Sh RETURN VALUES
+If successful,
+.Fn getcontext
+returns zero and
+.Fn setcontext
+does not return; otherwise \-1 is returned.
+The
+.Fn getcontextx
+returns pointer to the allocated and initialized context on success, and
+.Va NULL
+on failure.
+.Sh ERRORS
+No errors are defined for
+.Fn getcontext
+or
+.Fn setcontext .
+The
+.Fn getcontextx
+may return the following errors in
+.Va errno :
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+No memory was available to allocate for the context or some extended state.
+.El
+.Sh SEE ALSO
+.Xr sigaction 2 ,
+.Xr sigaltstack 2 ,
+.Xr makecontext 3 ,
+.Xr ucontext 3
diff --git a/lib/libc/gen/getcwd.3 b/lib/libc/gen/getcwd.3
new file mode 100644
index 0000000..88291c3
--- /dev/null
+++ b/lib/libc/gen/getcwd.3
@@ -0,0 +1,162 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getcwd.3 8.2 (Berkeley) 12/11/93
+.\" $FreeBSD$
+.\"
+.Dd April 17, 2010
+.Dt GETCWD 3
+.Os
+.Sh NAME
+.Nm getcwd ,
+.Nm getwd
+.Nd get working directory pathname
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft char *
+.Fn getcwd "char *buf" "size_t size"
+.Ft char *
+.Fn getwd "char *buf"
+.Sh DESCRIPTION
+The
+.Fn getcwd
+function copies the absolute pathname of the current working directory
+into the memory referenced by
+.Fa buf
+and returns a pointer to
+.Fa buf .
+The
+.Fa size
+argument is the size, in bytes, of the array referenced by
+.Fa buf .
+.Pp
+If
+.Fa buf
+is
+.Dv NULL ,
+space is allocated as necessary to store the pathname.
+This space may later be
+.Xr free 3 Ns 'd .
+.Pp
+The function
+.Fn getwd
+is a compatibility routine which calls
+.Fn getcwd
+with its
+.Fa buf
+argument and a size of
+.Dv MAXPATHLEN
+(as defined in the include
+file
+.In sys/param.h ) .
+Obviously,
+.Fa buf
+should be at least
+.Dv MAXPATHLEN
+bytes in length.
+.Pp
+These routines have traditionally been used by programs to save the
+name of a working directory for the purpose of returning to it.
+A much faster and less error-prone method of accomplishing this is to
+open the current directory
+.Pq Ql .\&
+and use the
+.Xr fchdir 2
+function to return.
+.Sh RETURN VALUES
+Upon successful completion, a pointer to the pathname is returned.
+Otherwise a
+.Dv NULL
+pointer is returned and the global variable
+.Va errno
+is set to indicate the error.
+In addition,
+.Fn getwd
+copies the error message associated with
+.Va errno
+into the memory referenced by
+.Fa buf .
+.Sh ERRORS
+The
+.Fn getcwd
+function
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa size
+argument is zero.
+.It Bq Er ENOENT
+A component of the pathname no longer exists.
+.It Bq Er ENOMEM
+Insufficient memory is available.
+.It Bq Er ERANGE
+The
+.Fa size
+argument is greater than zero but smaller than the length of the pathname
+plus 1.
+.El
+.Pp
+The
+.Fn getcwd
+function
+may fail if:
+.Bl -tag -width Er
+.It Bq Er EACCES
+Read or search permission was denied for a component of the pathname.
+This is only checked in limited cases, depending on implementation details.
+.El
+.Sh SEE ALSO
+.Xr chdir 2 ,
+.Xr fchdir 2 ,
+.Xr malloc 3 ,
+.Xr strerror 3
+.Sh STANDARDS
+The
+.Fn getcwd
+function
+conforms to
+.St -p1003.1-90 .
+The ability to specify a
+.Dv NULL
+pointer and have
+.Fn getcwd
+allocate memory as necessary is an extension.
+.Sh HISTORY
+The
+.Fn getwd
+function appeared in
+.Bx 4.0 .
+.Sh BUGS
+The
+.Fn getwd
+function
+does not do sufficient error checking and is not able to return very
+long, but valid, paths.
+It is provided for compatibility.
diff --git a/lib/libc/gen/getcwd.c b/lib/libc/gen/getcwd.c
new file mode 100644
index 0000000..c886dde
--- /dev/null
+++ b/lib/libc/gen/getcwd.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 1989, 1991, 1993, 1995
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getcwd.c 8.5 (Berkeley) 2/7/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#define ISDOT(dp) \
+ (dp->d_name[0] == '.' && (dp->d_name[1] == '\0' || \
+ (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
+
+extern int __getcwd(char *, size_t);
+
+char *
+getcwd(pt, size)
+ char *pt;
+ size_t size;
+{
+ struct dirent *dp;
+ DIR *dir = NULL;
+ dev_t dev;
+ ino_t ino;
+ int first;
+ char *bpt;
+ struct stat s;
+ dev_t root_dev;
+ ino_t root_ino;
+ size_t ptsize;
+ int save_errno;
+ char *ept, c;
+ int fd;
+
+ /*
+ * If no buffer specified by the user, allocate one as necessary.
+ * If a buffer is specified, the size has to be non-zero. The path
+ * is built from the end of the buffer backwards.
+ */
+ if (pt) {
+ ptsize = 0;
+ if (!size) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ if (size == 1) {
+ errno = ERANGE;
+ return (NULL);
+ }
+ ept = pt + size;
+ } else {
+ if ((pt = malloc(ptsize = PATH_MAX)) == NULL)
+ return (NULL);
+ ept = pt + ptsize;
+ }
+ if (__getcwd(pt, ept - pt) == 0) {
+ if (*pt != '/') {
+ bpt = pt;
+ ept = pt + strlen(pt) - 1;
+ while (bpt < ept) {
+ c = *bpt;
+ *bpt++ = *ept;
+ *ept-- = c;
+ }
+ }
+ return (pt);
+ }
+ bpt = ept - 1;
+ *bpt = '\0';
+
+ /* Save root values, so know when to stop. */
+ if (stat("/", &s))
+ goto err;
+ root_dev = s.st_dev;
+ root_ino = s.st_ino;
+
+ errno = 0; /* XXX readdir has no error return. */
+
+ for (first = 1;; first = 0) {
+ /* Stat the current level. */
+ if (dir != NULL ? _fstat(dirfd(dir), &s) : lstat(".", &s))
+ goto err;
+
+ /* Save current node values. */
+ ino = s.st_ino;
+ dev = s.st_dev;
+
+ /* Check for reaching root. */
+ if (root_dev == dev && root_ino == ino) {
+ *--bpt = '/';
+ /*
+ * It's unclear that it's a requirement to copy the
+ * path to the beginning of the buffer, but it's always
+ * been that way and stuff would probably break.
+ */
+ bcopy(bpt, pt, ept - bpt);
+ if (dir)
+ (void) closedir(dir);
+ return (pt);
+ }
+
+ /* Open and stat parent directory. */
+ fd = _openat(dir != NULL ? dirfd(dir) : AT_FDCWD,
+ "..", O_RDONLY);
+ if (fd == -1)
+ goto err;
+ if (dir)
+ (void) closedir(dir);
+ if (!(dir = fdopendir(fd)) || _fstat(dirfd(dir), &s)) {
+ _close(fd);
+ goto err;
+ }
+
+ /*
+ * If it's a mount point, have to stat each element because
+ * the inode number in the directory is for the entry in the
+ * parent directory, not the inode number of the mounted file.
+ */
+ save_errno = 0;
+ if (s.st_dev == dev) {
+ for (;;) {
+ if (!(dp = readdir(dir)))
+ goto notfound;
+ if (dp->d_fileno == ino)
+ break;
+ }
+ } else
+ for (;;) {
+ if (!(dp = readdir(dir)))
+ goto notfound;
+ if (ISDOT(dp))
+ continue;
+
+ /* Save the first error for later. */
+ if (fstatat(dirfd(dir), dp->d_name, &s,
+ AT_SYMLINK_NOFOLLOW)) {
+ if (!save_errno)
+ save_errno = errno;
+ errno = 0;
+ continue;
+ }
+ if (s.st_dev == dev && s.st_ino == ino)
+ break;
+ }
+
+ /*
+ * Check for length of the current name, preceding slash,
+ * leading slash.
+ */
+ while (bpt - pt < dp->d_namlen + (first ? 1 : 2)) {
+ size_t len, off;
+
+ if (!ptsize) {
+ errno = ERANGE;
+ goto err;
+ }
+ off = bpt - pt;
+ len = ept - bpt;
+ if ((pt = reallocf(pt, ptsize *= 2)) == NULL)
+ goto err;
+ bpt = pt + off;
+ ept = pt + ptsize;
+ bcopy(bpt, ept - len, len);
+ bpt = ept - len;
+ }
+ if (!first)
+ *--bpt = '/';
+ bpt -= dp->d_namlen;
+ bcopy(dp->d_name, bpt, dp->d_namlen);
+ }
+
+notfound:
+ /*
+ * If readdir set errno, use it, not any saved error; otherwise,
+ * didn't find the current directory in its parent directory, set
+ * errno to ENOENT.
+ */
+ if (!errno)
+ errno = save_errno ? save_errno : ENOENT;
+ /* FALLTHROUGH */
+err:
+ save_errno = errno;
+
+ if (ptsize)
+ free(pt);
+ if (dir)
+ (void) closedir(dir);
+
+ errno = save_errno;
+ return (NULL);
+}
diff --git a/lib/libc/gen/getdiskbyname.3 b/lib/libc/gen/getdiskbyname.3
new file mode 100644
index 0000000..4406096
--- /dev/null
+++ b/lib/libc/gen/getdiskbyname.3
@@ -0,0 +1,63 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getdiskbyname.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt GETDISKBYNAME 3
+.Os
+.Sh NAME
+.Nm getdiskbyname
+.Nd get generic disk description by its name
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/disklabel.h
+.Ft struct disklabel *
+.Fn getdiskbyname "const char *name"
+.Sh DESCRIPTION
+The
+.Fn getdiskbyname
+function
+takes a disk name (e.g.\&
+.Ql rm03 )
+and returns a prototype disk label
+describing its geometry information and the standard
+disk partition tables.
+All information is obtained from
+the
+.Xr disktab 5
+file.
+.Sh SEE ALSO
+.Xr disktab 5 ,
+.Xr disklabel 8
+.Sh HISTORY
+The
+.Fn getdiskbyname
+function appeared in
+.Bx 4.3 .
diff --git a/lib/libc/gen/getdomainname.3 b/lib/libc/gen/getdomainname.3
new file mode 100644
index 0000000..480c746
--- /dev/null
+++ b/lib/libc/gen/getdomainname.3
@@ -0,0 +1,100 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)gethostname.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd May 6, 1994
+.Dt GETDOMAINNAME 3
+.Os
+.Sh NAME
+.Nm getdomainname ,
+.Nm setdomainname
+.Nd get/set the NIS domain name of current host
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn getdomainname "char *name" "int namelen"
+.Ft int
+.Fn setdomainname "const char *name" "int namelen"
+.Sh DESCRIPTION
+The
+.Fn getdomainname
+function
+returns the standard NIS domain name for the current host, as
+previously set by
+.Fn setdomainname .
+The
+.Fa namelen
+argument
+specifies the size of the
+.Fa name
+array.
+The returned name is null-terminated unless insufficient
+space is provided.
+.Pp
+The
+.Fn setdomainname
+function
+sets the NIS domain name of the host machine to be
+.Fa name ,
+which has length
+.Fa namelen .
+This call is restricted to the super-user and
+is normally used only when the system is bootstrapped.
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+The following errors may be returned by these calls:
+.Bl -tag -width Er
+.It Bq Er EFAULT
+The
+.Fa name
+or
+.Fa namelen
+argument gave an
+invalid address.
+.It Bq Er EPERM
+The caller tried to set the hostname and was not the super-user.
+.El
+.Sh SEE ALSO
+.Xr gethostid 3 ,
+.Xr gethostname 3 ,
+.Xr sysctl 3
+.Sh HISTORY
+The
+.Fn getdomainname
+function appeared in
+.Bx 4.2 .
+.Sh BUGS
+Domain names are limited to
+.Dv MAXHOSTNAMELEN
+(from
+.In sys/param.h )
+characters, currently 256.
diff --git a/lib/libc/gen/getdomainname.c b/lib/libc/gen/getdomainname.c
new file mode 100644
index 0000000..21eb66d
--- /dev/null
+++ b/lib/libc/gen/getdomainname.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostname.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <unistd.h>
+
+int
+getdomainname(name, namelen)
+ char *name;
+ int namelen;
+{
+ int mib[2];
+ size_t size;
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_NISDOMAINNAME;
+ size = namelen;
+ if (sysctl(mib, 2, name, &size, NULL, 0) == -1)
+ return (-1);
+ return (0);
+}
diff --git a/lib/libc/gen/getfsent.3 b/lib/libc/gen/getfsent.3
new file mode 100644
index 0000000..306db64
--- /dev/null
+++ b/lib/libc/gen/getfsent.3
@@ -0,0 +1,185 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getfsent.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd April 7, 2003
+.Dt GETFSENT 3
+.Os
+.Sh NAME
+.Nm getfsent ,
+.Nm getfsspec ,
+.Nm getfsfile ,
+.Nm setfsent ,
+.Nm endfsent
+.Nd get file system descriptor file entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In fstab.h
+.Ft "struct fstab *"
+.Fn getfsent void
+.Ft "struct fstab *"
+.Fn getfsspec "const char *spec"
+.Ft "struct fstab *"
+.Fn getfsfile "const char *file"
+.Ft int
+.Fn setfsent void
+.Ft void
+.Fn endfsent void
+.Ft void
+.Fn setfstab "const char *file"
+.Ft "const char *"
+.Fn getfstab void
+.Sh DESCRIPTION
+The
+.Fn getfsent ,
+.Fn getfsspec ,
+and
+.Fn getfsfile
+functions
+each return a pointer to an object with the following structure
+containing the broken-out fields of a line in the file system
+description file,
+.In fstab.h .
+.Bd -literal -offset indent
+struct fstab {
+ char *fs_spec; /* block special device name */
+ char *fs_file; /* file system path prefix */
+ char *fs_vfstype; /* File system type, ufs, nfs */
+ char *fs_mntops; /* Mount options ala -o */
+ char *fs_type; /* FSTAB_* from fs_mntops */
+ int fs_freq; /* dump frequency, in days */
+ int fs_passno; /* pass number on parallel fsck */
+};
+.Ed
+.Pp
+The fields have meanings described in
+.Xr fstab 5 .
+.Pp
+The
+.Fn setfsent
+function
+opens the file (closing any previously opened file) or rewinds it
+if it is already open.
+.Pp
+The
+.Fn endfsent
+function
+closes the file.
+.Pp
+The
+.Fn setfstab
+function sets the file to be used by subsequent operations.
+The value set by
+.Fn setfstab
+does not persist across calls to
+.Fn endfsent .
+.Pp
+The
+.Fn getfstab
+function returns the name of the file that will be used.
+.Pp
+The
+.Fn getfsspec
+and
+.Fn getfsfile
+functions
+search the entire file (opening it if necessary) for a matching special
+file name or file system file name.
+.Pp
+For programs wishing to read the entire database,
+.Fn getfsent
+reads the next entry (opening the file if necessary).
+.Pp
+All entries in the file with a type field equivalent to
+.Dv FSTAB_XX
+are ignored.
+.Sh RETURN VALUES
+The
+.Fn getfsent ,
+.Fn getfsspec ,
+and
+.Fn getfsfile
+functions
+return a
+.Dv NULL
+pointer on
+.Dv EOF
+or error.
+The
+.Fn setfsent
+function
+returns 0 on failure, 1 on success.
+The
+.Fn endfsent
+function
+returns nothing.
+.Sh ENVIRONMENT
+.Bl -tag -width ".Ev PATH_FSTAB"
+.It Ev PATH_FSTAB
+If the environment variable
+.Ev PATH_FSTAB
+is set, all operations are performed against the specified file.
+.Ev PATH_FSTAB
+will not be honored if the process environment or memory address space is
+considered
+.Dq tainted .
+(See
+.Xr issetugid 2
+for more information.)
+.El
+.Sh FILES
+.Bl -tag -width /etc/fstab -compact
+.It Pa /etc/fstab
+.El
+.Sh SEE ALSO
+.Xr fstab 5
+.Sh HISTORY
+The
+.Fn getfsent
+function appeared in
+.Bx 4.0 ;
+the
+.Fn endfsent ,
+.Fn getfsfile ,
+.Fn getfsspec ,
+and
+.Fn setfsent
+functions appeared in
+.Bx 4.3 ;
+the
+.Fn setfstab
+and
+.Fn getfstab
+functions appeared in
+.Fx 5.1 .
+.Sh BUGS
+These functions use static data storage;
+if the data is needed for future use, it should be
+copied before any subsequent calls overwrite it.
diff --git a/lib/libc/gen/getgrent.3 b/lib/libc/gen/getgrent.3
new file mode 100644
index 0000000..da2ed8c
--- /dev/null
+++ b/lib/libc/gen/getgrent.3
@@ -0,0 +1,287 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)getgrent.3 8.2 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd April 16, 2003
+.Dt GETGRENT 3
+.Os
+.Sh NAME
+.Nm getgrent ,
+.Nm getgrent_r ,
+.Nm getgrnam ,
+.Nm getgrnam_r ,
+.Nm getgrgid ,
+.Nm getgrgid_r ,
+.Nm setgroupent ,
+.Nm setgrent ,
+.Nm endgrent
+.Nd group database operations
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In grp.h
+.Ft struct group *
+.Fn getgrent void
+.Ft int
+.Fn getgrent_r "struct group *grp" "char *buffer" "size_t bufsize" "struct group **result"
+.Ft struct group *
+.Fn getgrnam "const char *name"
+.Ft int
+.Fn getgrnam_r "const char *name" "struct group *grp" "char *buffer" "size_t bufsize" "struct group **result"
+.Ft struct group *
+.Fn getgrgid "gid_t gid"
+.Ft int
+.Fn getgrgid_r "gid_t gid" "struct group *grp" "char *buffer" "size_t bufsize" "struct group **result"
+.Ft int
+.Fn setgroupent "int stayopen"
+.Ft int
+.Fn setgrent void
+.Ft void
+.Fn endgrent void
+.Sh DESCRIPTION
+These functions operate on the group database file
+.Pa /etc/group
+which is described
+in
+.Xr group 5 .
+Each line of the database is defined by the structure
+.Vt group
+found in the include
+file
+.In grp.h :
+.Bd -literal -offset indent
+struct group {
+ char *gr_name; /* group name */
+ char *gr_passwd; /* group password */
+ gid_t gr_gid; /* group id */
+ char **gr_mem; /* group members */
+};
+.Ed
+.Pp
+The functions
+.Fn getgrnam
+and
+.Fn getgrgid
+search the group database for the given group name pointed to by
+.Fa name
+or the group id pointed to by
+.Fa gid ,
+respectively, returning the first one encountered.
+Identical group
+names or group gids may result in undefined behavior.
+.Pp
+The
+.Fn getgrent
+function
+sequentially reads the group database and is intended for programs
+that wish to step through the complete list of groups.
+.Pp
+The functions
+.Fn getgrent_r ,
+.Fn getgrnam_r ,
+and
+.Fn getgrgid_r
+are thread-safe versions of
+.Fn getgrent ,
+.Fn getgrnam ,
+and
+.Fn getgrgid ,
+respectively.
+The caller must provide storage for the results of the search in
+the
+.Fa grp ,
+.Fa buffer ,
+.Fa bufsize ,
+and
+.Fa result
+arguments.
+When these functions are successful, the
+.Fa grp
+argument will be filled-in, and a pointer to that argument will be
+stored in
+.Fa result .
+If an entry is not found or an error occurs,
+.Fa result
+will be set to
+.Dv NULL .
+.Pp
+These functions will open the group file for reading, if necessary.
+.Pp
+The
+.Fn setgroupent
+function
+opens the file, or rewinds it if it is already open.
+If
+.Fa stayopen
+is non-zero, file descriptors are left open, significantly speeding
+functions subsequent calls.
+This functionality is unnecessary for
+.Fn getgrent
+as it does not close its file descriptors by default.
+It should also
+be noted that it is dangerous for long-running programs to use this
+functionality as the group file may be updated.
+.Pp
+The
+.Fn setgrent
+function
+is identical to
+.Fn setgroupent
+with an argument of zero.
+.Pp
+The
+.Fn endgrent
+function
+closes any open files.
+.Sh RETURN VALUES
+The functions
+.Fn getgrent ,
+.Fn getgrnam ,
+and
+.Fn getgrgid ,
+return a pointer to a group structure on success or
+.Dv NULL
+if the entry is not found or if an error occurs.
+If an error does occur,
+.Va errno
+will be set.
+Note that programs must explicitly set
+.Va errno
+to zero before calling any of these functions if they need to
+distinguish between a non-existent entry and an error.
+The functions
+.Fn getgrent_r ,
+.Fn getgrnam_r ,
+and
+.Fn getgrgid_r
+return 0 if no error occurred, or an error number to indicate failure.
+It is not an error if a matching entry is not found.
+(Thus, if
+.Fa result
+is set to
+.Dv NULL
+and the return value is 0, no matching entry exists.)
+.Pp
+The functions
+.Fn setgroupent
+and
+.Fn setgrent
+return the value 1 if successful, otherwise the value
+0 is returned.
+The functions
+.Fn endgrent
+and
+.Fn setgrfile
+have no return value.
+.Sh FILES
+.Bl -tag -width /etc/group -compact
+.It Pa /etc/group
+group database file
+.El
+.Sh COMPATIBILITY
+The historic function
+.Fn setgrfile ,
+which allowed the specification of alternate password databases, has
+been deprecated and is no longer available.
+.Sh SEE ALSO
+.Xr getpwent 3 ,
+.Xr group 5 ,
+.Xr nsswitch.conf 5 ,
+.Xr yp 8
+.Sh STANDARDS
+The
+.Fn getgrent ,
+.Fn getgrnam ,
+.Fn getgrnam_r ,
+.Fn getgrgid ,
+.Fn getgrgid_r
+and
+.Fn endgrent
+functions conform to
+.St -p1003.1-96 .
+The
+.Fn setgrent
+function differs from that standard in that its return type is
+.Vt int
+rather than
+.Vt void .
+.Sh HISTORY
+The functions
+.Fn endgrent ,
+.Fn getgrent ,
+.Fn getgrnam ,
+.Fn getgrgid ,
+and
+.Fn setgrent
+appeared in
+.At v7 .
+The functions
+.Fn setgrfile
+and
+.Fn setgroupent
+appeared in
+.Bx 4.3 Reno .
+The functions
+.Fn getgrent_r ,
+.Fn getgrnam_r ,
+and
+.Fn getgrgid_r
+appeared in
+.Fx 5.1 .
+.Sh BUGS
+The functions
+.Fn getgrent ,
+.Fn getgrnam ,
+.Fn getgrgid ,
+.Fn setgroupent
+and
+.Fn setgrent
+leave their results in an internal static object and return
+a pointer to that object.
+Subsequent calls to
+the same function
+will modify the same object.
+.Pp
+The functions
+.Fn getgrent ,
+.Fn getgrent_r ,
+.Fn endgrent ,
+.Fn setgroupent ,
+and
+.Fn setgrent
+are fairly useless in a networked environment and should be
+avoided, if possible.
+The
+.Fn getgrent
+and
+.Fn getgrent_r
+functions
+make no attempt to suppress duplicate information if multiple
+sources are specified in
+.Xr nsswitch.conf 5 .
diff --git a/lib/libc/gen/getgrent.c b/lib/libc/gen/getgrent.c
new file mode 100644
index 0000000..18f64a8
--- /dev/null
+++ b/lib/libc/gen/getgrent.c
@@ -0,0 +1,1554 @@
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#ifdef HESIOD
+#include <hesiod.h>
+#endif
+#include <grp.h>
+#include <nsswitch.h>
+#include <pthread.h>
+#include <pthread_np.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "nss_tls.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+
+enum constants {
+ GRP_STORAGE_INITIAL = 1 << 10, /* 1 KByte */
+ GRP_STORAGE_MAX = 1 << 20, /* 1 MByte */
+ SETGRENT = 1,
+ ENDGRENT = 2,
+ HESIOD_NAME_MAX = 256,
+};
+
+static const ns_src defaultsrc[] = {
+ { NSSRC_COMPAT, NS_SUCCESS },
+ { NULL, 0 }
+};
+
+int __gr_match_entry(const char *, size_t, enum nss_lookup_type,
+ const char *, gid_t);
+int __gr_parse_entry(char *, size_t, struct group *, char *, size_t,
+ int *);
+
+static int is_comment_line(const char *, size_t);
+
+union key {
+ const char *name;
+ gid_t gid;
+};
+static struct group *getgr(int (*)(union key, struct group *, char *, size_t,
+ struct group **), union key);
+static int wrap_getgrnam_r(union key, struct group *, char *, size_t,
+ struct group **);
+static int wrap_getgrgid_r(union key, struct group *, char *, size_t,
+ struct group **);
+static int wrap_getgrent_r(union key, struct group *, char *, size_t,
+ struct group **);
+
+struct files_state {
+ FILE *fp;
+ int stayopen;
+};
+static void files_endstate(void *);
+NSS_TLS_HANDLING(files);
+static int files_setgrent(void *, void *, va_list);
+static int files_group(void *, void *, va_list);
+
+
+#ifdef HESIOD
+struct dns_state {
+ long counter;
+};
+static void dns_endstate(void *);
+NSS_TLS_HANDLING(dns);
+static int dns_setgrent(void *, void *, va_list);
+static int dns_group(void *, void *, va_list);
+#endif
+
+
+#ifdef YP
+struct nis_state {
+ char domain[MAXHOSTNAMELEN];
+ int done;
+ char *key;
+ int keylen;
+};
+static void nis_endstate(void *);
+NSS_TLS_HANDLING(nis);
+static int nis_setgrent(void *, void *, va_list);
+static int nis_group(void *, void *, va_list);
+#endif
+
+struct compat_state {
+ FILE *fp;
+ int stayopen;
+ char *name;
+ enum _compat {
+ COMPAT_MODE_OFF = 0,
+ COMPAT_MODE_ALL,
+ COMPAT_MODE_NAME
+ } compat;
+};
+static void compat_endstate(void *);
+NSS_TLS_HANDLING(compat);
+static int compat_setgrent(void *, void *, va_list);
+static int compat_group(void *, void *, va_list);
+
+static int gr_addgid(gid_t, gid_t *, int, int *);
+static int getgroupmembership_fallback(void *, void *, va_list);
+
+#ifdef NS_CACHING
+static int grp_id_func(char *, size_t *, va_list, void *);
+static int grp_marshal_func(char *, size_t *, void *, va_list, void *);
+static int grp_unmarshal_func(char *, size_t, void *, va_list, void *);
+
+static int
+grp_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
+{
+ char *name;
+ gid_t gid;
+
+ size_t desired_size, size;
+ int res = NS_UNAVAIL;
+ enum nss_lookup_type lookup_type;
+
+
+ lookup_type = (enum nss_lookup_type)cache_mdata;
+ switch (lookup_type) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ size = strlen(name);
+ desired_size = sizeof(enum nss_lookup_type) + size + 1;
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
+
+ res = NS_SUCCESS;
+ break;
+ case nss_lt_id:
+ gid = va_arg(ap, gid_t);
+ desired_size = sizeof(enum nss_lookup_type) + sizeof(gid_t);
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), &gid,
+ sizeof(gid_t));
+
+ res = NS_SUCCESS;
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+fin:
+ *buffer_size = desired_size;
+ return (res);
+}
+
+static int
+grp_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ gid_t gid;
+ struct group *grp;
+ char *orig_buf;
+ size_t orig_buf_size;
+
+ struct group new_grp;
+ size_t desired_size, size, mem_size;
+ char *p, **mem;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ gid = va_arg(ap, gid_t);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ grp = va_arg(ap, struct group *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+
+ desired_size = _ALIGNBYTES + sizeof(struct group) + sizeof(char *);
+
+ if (grp->gr_name != NULL)
+ desired_size += strlen(grp->gr_name) + 1;
+ if (grp->gr_passwd != NULL)
+ desired_size += strlen(grp->gr_passwd) + 1;
+
+ if (grp->gr_mem != NULL) {
+ mem_size = 0;
+ for (mem = grp->gr_mem; *mem; ++mem) {
+ desired_size += strlen(*mem) + 1;
+ ++mem_size;
+ }
+
+ desired_size += _ALIGNBYTES + (mem_size + 1) * sizeof(char *);
+ }
+
+ if (desired_size > *buffer_size) {
+ /* this assignment is here for future use */
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ memcpy(&new_grp, grp, sizeof(struct group));
+ memset(buffer, 0, desired_size);
+
+ *buffer_size = desired_size;
+ p = buffer + sizeof(struct group) + sizeof(char *);
+ memcpy(buffer + sizeof(struct group), &p, sizeof(char *));
+ p = (char *)_ALIGN(p);
+
+ if (new_grp.gr_name != NULL) {
+ size = strlen(new_grp.gr_name);
+ memcpy(p, new_grp.gr_name, size);
+ new_grp.gr_name = p;
+ p += size + 1;
+ }
+
+ if (new_grp.gr_passwd != NULL) {
+ size = strlen(new_grp.gr_passwd);
+ memcpy(p, new_grp.gr_passwd, size);
+ new_grp.gr_passwd = p;
+ p += size + 1;
+ }
+
+ if (new_grp.gr_mem != NULL) {
+ p = (char *)_ALIGN(p);
+ memcpy(p, new_grp.gr_mem, sizeof(char *) * mem_size);
+ new_grp.gr_mem = (char **)p;
+ p += sizeof(char *) * (mem_size + 1);
+
+ for (mem = new_grp.gr_mem; *mem; ++mem) {
+ size = strlen(*mem);
+ memcpy(p, *mem, size);
+ *mem = p;
+ p += size + 1;
+ }
+ }
+
+ memcpy(buffer, &new_grp, sizeof(struct group));
+ return (NS_SUCCESS);
+}
+
+static int
+grp_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ gid_t gid;
+ struct group *grp;
+ char *orig_buf;
+ size_t orig_buf_size;
+ int *ret_errno;
+
+ char *p;
+ char **mem;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ gid = va_arg(ap, gid_t);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ grp = va_arg(ap, struct group *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+ ret_errno = va_arg(ap, int *);
+
+ if (orig_buf_size <
+ buffer_size - sizeof(struct group) - sizeof(char *)) {
+ *ret_errno = ERANGE;
+ return (NS_RETURN);
+ }
+
+ memcpy(grp, buffer, sizeof(struct group));
+ memcpy(&p, buffer + sizeof(struct group), sizeof(char *));
+
+ orig_buf = (char *)_ALIGN(orig_buf);
+ memcpy(orig_buf, buffer + sizeof(struct group) + sizeof(char *) +
+ _ALIGN(p) - (size_t)p,
+ buffer_size - sizeof(struct group) - sizeof(char *) -
+ _ALIGN(p) + (size_t)p);
+ p = (char *)_ALIGN(p);
+
+ NS_APPLY_OFFSET(grp->gr_name, orig_buf, p, char *);
+ NS_APPLY_OFFSET(grp->gr_passwd, orig_buf, p, char *);
+ if (grp->gr_mem != NULL) {
+ NS_APPLY_OFFSET(grp->gr_mem, orig_buf, p, char **);
+
+ for (mem = grp->gr_mem; *mem; ++mem)
+ NS_APPLY_OFFSET(*mem, orig_buf, p, char *);
+ }
+
+ if (retval != NULL)
+ *((struct group **)retval) = grp;
+
+ return (NS_SUCCESS);
+}
+
+NSS_MP_CACHE_HANDLING(group);
+#endif /* NS_CACHING */
+
+#ifdef NS_CACHING
+static const nss_cache_info setgrent_cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ group, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+
+static const ns_dtab setgrent_dtab[] = {
+ { NSSRC_FILES, files_setgrent, (void *)SETGRENT },
+#ifdef HESIOD
+ { NSSRC_DNS, dns_setgrent, (void *)SETGRENT },
+#endif
+#ifdef YP
+ { NSSRC_NIS, nis_setgrent, (void *)SETGRENT },
+#endif
+ { NSSRC_COMPAT, compat_setgrent, (void *)SETGRENT },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&setgrent_cache_info)
+#endif
+ { NULL, NULL, NULL }
+};
+
+#ifdef NS_CACHING
+static const nss_cache_info endgrent_cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ group, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+
+static const ns_dtab endgrent_dtab[] = {
+ { NSSRC_FILES, files_setgrent, (void *)ENDGRENT },
+#ifdef HESIOD
+ { NSSRC_DNS, dns_setgrent, (void *)ENDGRENT },
+#endif
+#ifdef YP
+ { NSSRC_NIS, nis_setgrent, (void *)ENDGRENT },
+#endif
+ { NSSRC_COMPAT, compat_setgrent, (void *)ENDGRENT },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&endgrent_cache_info)
+#endif
+ { NULL, NULL, NULL }
+};
+
+#ifdef NS_CACHING
+static const nss_cache_info getgrent_r_cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ group, (void *)nss_lt_all,
+ grp_marshal_func, grp_unmarshal_func);
+#endif
+
+static const ns_dtab getgrent_r_dtab[] = {
+ { NSSRC_FILES, files_group, (void *)nss_lt_all },
+#ifdef HESIOD
+ { NSSRC_DNS, dns_group, (void *)nss_lt_all },
+#endif
+#ifdef YP
+ { NSSRC_NIS, nis_group, (void *)nss_lt_all },
+#endif
+ { NSSRC_COMPAT, compat_group, (void *)nss_lt_all },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&getgrent_r_cache_info)
+#endif
+ { NULL, NULL, NULL }
+};
+
+static int
+gr_addgid(gid_t gid, gid_t *groups, int maxgrp, int *grpcnt)
+{
+ int ret, dupc;
+
+ for (dupc = 0; dupc < MIN(maxgrp, *grpcnt); dupc++) {
+ if (groups[dupc] == gid)
+ return 1;
+ }
+
+ ret = 1;
+ if (*grpcnt < maxgrp)
+ groups[*grpcnt] = gid;
+ else
+ ret = 0;
+
+ (*grpcnt)++;
+
+ return ret;
+}
+
+static int
+getgroupmembership_fallback(void *retval, void *mdata, va_list ap)
+{
+ const ns_src src[] = {
+ { mdata, NS_SUCCESS },
+ { NULL, 0}
+ };
+ struct group grp;
+ struct group *grp_p;
+ char *buf;
+ size_t bufsize;
+ const char *uname;
+ gid_t *groups;
+ gid_t agroup;
+ int maxgrp, *grpcnt;
+ int i, rv, ret_errno;
+
+ /*
+ * As this is a fallback method, only provided src
+ * list will be respected during methods search.
+ */
+ assert(src[0].name != NULL);
+
+ uname = va_arg(ap, const char *);
+ agroup = va_arg(ap, gid_t);
+ groups = va_arg(ap, gid_t *);
+ maxgrp = va_arg(ap, int);
+ grpcnt = va_arg(ap, int *);
+
+ rv = NS_UNAVAIL;
+
+ buf = malloc(GRP_STORAGE_INITIAL);
+ if (buf == NULL)
+ goto out;
+
+ bufsize = GRP_STORAGE_INITIAL;
+
+ gr_addgid(agroup, groups, maxgrp, grpcnt);
+
+ _nsdispatch(NULL, setgrent_dtab, NSDB_GROUP, "setgrent", src, 0);
+ for (;;) {
+ do {
+ ret_errno = 0;
+ grp_p = NULL;
+ rv = _nsdispatch(&grp_p, getgrent_r_dtab, NSDB_GROUP,
+ "getgrent_r", src, &grp, buf, bufsize, &ret_errno);
+
+ if (grp_p == NULL && ret_errno == ERANGE) {
+ free(buf);
+ if ((bufsize << 1) > GRP_STORAGE_MAX) {
+ buf = NULL;
+ errno = ERANGE;
+ goto out;
+ }
+
+ bufsize <<= 1;
+ buf = malloc(bufsize);
+ if (buf == NULL) {
+ goto out;
+ }
+ }
+ } while (grp_p == NULL && ret_errno == ERANGE);
+
+ if (ret_errno != 0) {
+ errno = ret_errno;
+ goto out;
+ }
+
+ if (grp_p == NULL)
+ break;
+
+ for (i = 0; grp.gr_mem[i]; i++) {
+ if (strcmp(grp.gr_mem[i], uname) == 0)
+ gr_addgid(grp.gr_gid, groups, maxgrp, grpcnt);
+ }
+ }
+
+ _nsdispatch(NULL, endgrent_dtab, NSDB_GROUP, "endgrent", src);
+out:
+ free(buf);
+ return (rv);
+}
+
+/* XXX IEEE Std 1003.1, 2003 specifies `void setgrent(void)' */
+int
+setgrent(void)
+{
+ (void)_nsdispatch(NULL, setgrent_dtab, NSDB_GROUP, "setgrent", defaultsrc, 0);
+ return (1);
+}
+
+
+int
+setgroupent(int stayopen)
+{
+ (void)_nsdispatch(NULL, setgrent_dtab, NSDB_GROUP, "setgrent", defaultsrc,
+ stayopen);
+ return (1);
+}
+
+
+void
+endgrent(void)
+{
+ (void)_nsdispatch(NULL, endgrent_dtab, NSDB_GROUP, "endgrent", defaultsrc);
+}
+
+
+int
+getgrent_r(struct group *grp, char *buffer, size_t bufsize,
+ struct group **result)
+{
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = _nsdispatch(result, getgrent_r_dtab, NSDB_GROUP, "getgrent_r", defaultsrc,
+ grp, buffer, bufsize, &ret_errno);
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+
+int
+getgrnam_r(const char *name, struct group *grp, char *buffer, size_t bufsize,
+ struct group **result)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ group, (void *)nss_lt_name,
+ grp_id_func, grp_marshal_func, grp_unmarshal_func);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_group, (void *)nss_lt_name },
+#ifdef HESIOD
+ { NSSRC_DNS, dns_group, (void *)nss_lt_name },
+#endif
+#ifdef YP
+ { NSSRC_NIS, nis_group, (void *)nss_lt_name },
+#endif
+ { NSSRC_COMPAT, compat_group, (void *)nss_lt_name },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = _nsdispatch(result, dtab, NSDB_GROUP, "getgrnam_r", defaultsrc,
+ name, grp, buffer, bufsize, &ret_errno);
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+
+int
+getgrgid_r(gid_t gid, struct group *grp, char *buffer, size_t bufsize,
+ struct group **result)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ group, (void *)nss_lt_id,
+ grp_id_func, grp_marshal_func, grp_unmarshal_func);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_group, (void *)nss_lt_id },
+#ifdef HESIOD
+ { NSSRC_DNS, dns_group, (void *)nss_lt_id },
+#endif
+#ifdef YP
+ { NSSRC_NIS, nis_group, (void *)nss_lt_id },
+#endif
+ { NSSRC_COMPAT, compat_group, (void *)nss_lt_id },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = _nsdispatch(result, dtab, NSDB_GROUP, "getgrgid_r", defaultsrc,
+ gid, grp, buffer, bufsize, &ret_errno);
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+
+
+int
+__getgroupmembership(const char *uname, gid_t agroup, gid_t *groups,
+ int maxgrp, int *grpcnt)
+{
+ static const ns_dtab dtab[] = {
+ NS_FALLBACK_CB(getgroupmembership_fallback)
+ { NULL, NULL, NULL }
+ };
+ int rv;
+
+ assert(uname != NULL);
+ /* groups may be NULL if just sizing when invoked with maxgrp = 0 */
+ assert(grpcnt != NULL);
+
+ *grpcnt = 0;
+ rv = _nsdispatch(NULL, dtab, NSDB_GROUP, "getgroupmembership",
+ defaultsrc, uname, agroup, groups, maxgrp, grpcnt);
+
+ /* too many groups found? */
+ return (*grpcnt > maxgrp ? -1 : 0);
+}
+
+
+static struct group grp;
+static char *grp_storage;
+static size_t grp_storage_size;
+
+static struct group *
+getgr(int (*fn)(union key, struct group *, char *, size_t, struct group **),
+ union key key)
+{
+ int rv;
+ struct group *res;
+
+ if (grp_storage == NULL) {
+ grp_storage = malloc(GRP_STORAGE_INITIAL);
+ if (grp_storage == NULL)
+ return (NULL);
+ grp_storage_size = GRP_STORAGE_INITIAL;
+ }
+ do {
+ rv = fn(key, &grp, grp_storage, grp_storage_size, &res);
+ if (res == NULL && rv == ERANGE) {
+ free(grp_storage);
+ if ((grp_storage_size << 1) > GRP_STORAGE_MAX) {
+ grp_storage = NULL;
+ errno = ERANGE;
+ return (NULL);
+ }
+ grp_storage_size <<= 1;
+ grp_storage = malloc(grp_storage_size);
+ if (grp_storage == NULL)
+ return (NULL);
+ }
+ } while (res == NULL && rv == ERANGE);
+ if (rv != 0)
+ errno = rv;
+ return (res);
+}
+
+
+static int
+wrap_getgrnam_r(union key key, struct group *grp, char *buffer, size_t bufsize,
+ struct group **res)
+{
+ return (getgrnam_r(key.name, grp, buffer, bufsize, res));
+}
+
+
+static int
+wrap_getgrgid_r(union key key, struct group *grp, char *buffer, size_t bufsize,
+ struct group **res)
+{
+ return (getgrgid_r(key.gid, grp, buffer, bufsize, res));
+}
+
+
+static int
+wrap_getgrent_r(union key key __unused, struct group *grp, char *buffer,
+ size_t bufsize, struct group **res)
+{
+ return (getgrent_r(grp, buffer, bufsize, res));
+}
+
+
+struct group *
+getgrnam(const char *name)
+{
+ union key key;
+
+ key.name = name;
+ return (getgr(wrap_getgrnam_r, key));
+}
+
+
+struct group *
+getgrgid(gid_t gid)
+{
+ union key key;
+
+ key.gid = gid;
+ return (getgr(wrap_getgrgid_r, key));
+}
+
+
+struct group *
+getgrent(void)
+{
+ union key key;
+
+ key.gid = 0; /* not used */
+ return (getgr(wrap_getgrent_r, key));
+}
+
+
+static int
+is_comment_line(const char *s, size_t n)
+{
+ const char *eom;
+
+ eom = &s[n];
+
+ for (; s < eom; s++)
+ if (*s == '#' || !isspace((unsigned char)*s))
+ break;
+ return (*s == '#' || s == eom);
+}
+
+
+/*
+ * files backend
+ */
+static void
+files_endstate(void *p)
+{
+
+ if (p == NULL)
+ return;
+ if (((struct files_state *)p)->fp != NULL)
+ fclose(((struct files_state *)p)->fp);
+ free(p);
+}
+
+
+static int
+files_setgrent(void *retval, void *mdata, va_list ap)
+{
+ struct files_state *st;
+ int rv, stayopen;
+
+ rv = files_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+ switch ((enum constants)mdata) {
+ case SETGRENT:
+ stayopen = va_arg(ap, int);
+ if (st->fp != NULL)
+ rewind(st->fp);
+ else if (stayopen)
+ st->fp = fopen(_PATH_GROUP, "r");
+ break;
+ case ENDGRENT:
+ if (st->fp != NULL) {
+ fclose(st->fp);
+ st->fp = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+ return (NS_UNAVAIL);
+}
+
+
+static int
+files_group(void *retval, void *mdata, va_list ap)
+{
+ struct files_state *st;
+ enum nss_lookup_type how;
+ const char *name, *line;
+ struct group *grp;
+ gid_t gid;
+ char *buffer;
+ size_t bufsize, linesize;
+ off_t pos;
+ int rv, stayopen, *errnop;
+
+ name = NULL;
+ gid = (gid_t)-1;
+ how = (enum nss_lookup_type)mdata;
+ switch (how) {
+ case nss_lt_name:
+ name = va_arg(ap, const char *);
+ break;
+ case nss_lt_id:
+ gid = va_arg(ap, gid_t);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ return (NS_NOTFOUND);
+ }
+ grp = va_arg(ap, struct group *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ *errnop = files_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+ if (st->fp == NULL &&
+ ((st->fp = fopen(_PATH_GROUP, "r")) == NULL)) {
+ *errnop = errno;
+ return (NS_UNAVAIL);
+ }
+ if (how == nss_lt_all)
+ stayopen = 1;
+ else {
+ rewind(st->fp);
+ stayopen = st->stayopen;
+ }
+ rv = NS_NOTFOUND;
+ pos = ftello(st->fp);
+ while ((line = fgetln(st->fp, &linesize)) != NULL) {
+ if (line[linesize-1] == '\n')
+ linesize--;
+ rv = __gr_match_entry(line, linesize, how, name, gid);
+ if (rv != NS_SUCCESS)
+ continue;
+ /* We need room at least for the line, a string NUL
+ * terminator, alignment padding, and one (char *)
+ * pointer for the member list terminator.
+ */
+ if (bufsize <= linesize + _ALIGNBYTES + sizeof(char *)) {
+ *errnop = ERANGE;
+ rv = NS_RETURN;
+ break;
+ }
+ memcpy(buffer, line, linesize);
+ buffer[linesize] = '\0';
+ rv = __gr_parse_entry(buffer, linesize, grp,
+ &buffer[linesize + 1], bufsize - linesize - 1, errnop);
+ if (rv & NS_TERMINATE)
+ break;
+ pos = ftello(st->fp);
+ }
+ if (!stayopen && st->fp != NULL) {
+ fclose(st->fp);
+ st->fp = NULL;
+ }
+ if (rv == NS_SUCCESS && retval != NULL)
+ *(struct group **)retval = grp;
+ else if (rv == NS_RETURN && *errnop == ERANGE && st->fp != NULL)
+ fseeko(st->fp, pos, SEEK_SET);
+ return (rv);
+}
+
+
+#ifdef HESIOD
+/*
+ * dns backend
+ */
+static void
+dns_endstate(void *p)
+{
+
+ free(p);
+}
+
+
+static int
+dns_setgrent(void *retval, void *cb_data, va_list ap)
+{
+ struct dns_state *st;
+ int rv;
+
+ rv = dns_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+ st->counter = 0;
+ return (NS_UNAVAIL);
+}
+
+
+static int
+dns_group(void *retval, void *mdata, va_list ap)
+{
+ char buf[HESIOD_NAME_MAX];
+ struct dns_state *st;
+ struct group *grp;
+ const char *name, *label;
+ void *ctx;
+ char *buffer, **hes;
+ size_t bufsize, adjsize, linesize;
+ gid_t gid;
+ enum nss_lookup_type how;
+ int rv, *errnop;
+
+ ctx = NULL;
+ hes = NULL;
+ name = NULL;
+ gid = (gid_t)-1;
+ how = (enum nss_lookup_type)mdata;
+ switch (how) {
+ case nss_lt_name:
+ name = va_arg(ap, const char *);
+ break;
+ case nss_lt_id:
+ gid = va_arg(ap, gid_t);
+ break;
+ case nss_lt_all:
+ break;
+ }
+ grp = va_arg(ap, struct group *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ *errnop = dns_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+ if (hesiod_init(&ctx) != 0) {
+ *errnop = errno;
+ rv = NS_UNAVAIL;
+ goto fin;
+ }
+ do {
+ rv = NS_NOTFOUND;
+ switch (how) {
+ case nss_lt_name:
+ label = name;
+ break;
+ case nss_lt_id:
+ if (snprintf(buf, sizeof(buf), "%lu",
+ (unsigned long)gid) >= sizeof(buf))
+ goto fin;
+ label = buf;
+ break;
+ case nss_lt_all:
+ if (st->counter < 0)
+ goto fin;
+ if (snprintf(buf, sizeof(buf), "group-%ld",
+ st->counter++) >= sizeof(buf))
+ goto fin;
+ label = buf;
+ break;
+ }
+ hes = hesiod_resolve(ctx, label,
+ how == nss_lt_id ? "gid" : "group");
+ if ((how == nss_lt_id && hes == NULL &&
+ (hes = hesiod_resolve(ctx, buf, "group")) == NULL) ||
+ hes == NULL) {
+ if (how == nss_lt_all)
+ st->counter = -1;
+ if (errno != ENOENT)
+ *errnop = errno;
+ goto fin;
+ }
+ rv = __gr_match_entry(hes[0], strlen(hes[0]), how, name, gid);
+ if (rv != NS_SUCCESS) {
+ hesiod_free_list(ctx, hes);
+ hes = NULL;
+ continue;
+ }
+ /* We need room at least for the line, a string NUL
+ * terminator, alignment padding, and one (char *)
+ * pointer for the member list terminator.
+ */
+ adjsize = bufsize - _ALIGNBYTES - sizeof(char *);
+ linesize = strlcpy(buffer, hes[0], adjsize);
+ if (linesize >= adjsize) {
+ *errnop = ERANGE;
+ rv = NS_RETURN;
+ goto fin;
+ }
+ hesiod_free_list(ctx, hes);
+ hes = NULL;
+ rv = __gr_parse_entry(buffer, linesize, grp,
+ &buffer[linesize + 1], bufsize - linesize - 1, errnop);
+ } while (how == nss_lt_all && !(rv & NS_TERMINATE));
+fin:
+ if (hes != NULL)
+ hesiod_free_list(ctx, hes);
+ if (ctx != NULL)
+ hesiod_end(ctx);
+ if (rv == NS_SUCCESS && retval != NULL)
+ *(struct group **)retval = grp;
+ return (rv);
+}
+#endif /* HESIOD */
+
+
+#ifdef YP
+/*
+ * nis backend
+ */
+static void
+nis_endstate(void *p)
+{
+
+ if (p == NULL)
+ return;
+ free(((struct nis_state *)p)->key);
+ free(p);
+}
+
+
+static int
+nis_setgrent(void *retval, void *cb_data, va_list ap)
+{
+ struct nis_state *st;
+ int rv;
+
+ rv = nis_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+ st->done = 0;
+ free(st->key);
+ st->key = NULL;
+ return (NS_UNAVAIL);
+}
+
+
+static int
+nis_group(void *retval, void *mdata, va_list ap)
+{
+ char *map;
+ struct nis_state *st;
+ struct group *grp;
+ const char *name;
+ char *buffer, *key, *result;
+ size_t bufsize;
+ gid_t gid;
+ enum nss_lookup_type how;
+ int *errnop, keylen, resultlen, rv;
+
+ name = NULL;
+ gid = (gid_t)-1;
+ how = (enum nss_lookup_type)mdata;
+ switch (how) {
+ case nss_lt_name:
+ name = va_arg(ap, const char *);
+ map = "group.byname";
+ break;
+ case nss_lt_id:
+ gid = va_arg(ap, gid_t);
+ map = "group.bygid";
+ break;
+ case nss_lt_all:
+ map = "group.byname";
+ break;
+ }
+ grp = va_arg(ap, struct group *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ *errnop = nis_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+ if (st->domain[0] == '\0') {
+ if (getdomainname(st->domain, sizeof(st->domain)) != 0) {
+ *errnop = errno;
+ return (NS_UNAVAIL);
+ }
+ }
+ result = NULL;
+ do {
+ rv = NS_NOTFOUND;
+ switch (how) {
+ case nss_lt_name:
+ if (strlcpy(buffer, name, bufsize) >= bufsize)
+ goto erange;
+ break;
+ case nss_lt_id:
+ if (snprintf(buffer, bufsize, "%lu",
+ (unsigned long)gid) >= bufsize)
+ goto erange;
+ break;
+ case nss_lt_all:
+ if (st->done)
+ goto fin;
+ break;
+ }
+ result = NULL;
+ if (how == nss_lt_all) {
+ if (st->key == NULL)
+ rv = yp_first(st->domain, map, &st->key,
+ &st->keylen, &result, &resultlen);
+ else {
+ key = st->key;
+ keylen = st->keylen;
+ st->key = NULL;
+ rv = yp_next(st->domain, map, key, keylen,
+ &st->key, &st->keylen, &result,
+ &resultlen);
+ free(key);
+ }
+ if (rv != 0) {
+ free(result);
+ free(st->key);
+ st->key = NULL;
+ if (rv == YPERR_NOMORE) {
+ st->done = 1;
+ rv = NS_NOTFOUND;
+ } else
+ rv = NS_UNAVAIL;
+ goto fin;
+ }
+ } else {
+ rv = yp_match(st->domain, map, buffer, strlen(buffer),
+ &result, &resultlen);
+ if (rv == YPERR_KEY) {
+ rv = NS_NOTFOUND;
+ continue;
+ } else if (rv != 0) {
+ free(result);
+ rv = NS_UNAVAIL;
+ continue;
+ }
+ }
+ /* We need room at least for the line, a string NUL
+ * terminator, alignment padding, and one (char *)
+ * pointer for the member list terminator.
+ */
+ if (resultlen >= bufsize - _ALIGNBYTES - sizeof(char *))
+ goto erange;
+ memcpy(buffer, result, resultlen);
+ buffer[resultlen] = '\0';
+ free(result);
+ rv = __gr_match_entry(buffer, resultlen, how, name, gid);
+ if (rv == NS_SUCCESS)
+ rv = __gr_parse_entry(buffer, resultlen, grp,
+ &buffer[resultlen+1], bufsize - resultlen - 1,
+ errnop);
+ } while (how == nss_lt_all && !(rv & NS_TERMINATE));
+fin:
+ if (rv == NS_SUCCESS && retval != NULL)
+ *(struct group **)retval = grp;
+ return (rv);
+erange:
+ *errnop = ERANGE;
+ return (NS_RETURN);
+}
+#endif /* YP */
+
+
+
+/*
+ * compat backend
+ */
+static void
+compat_endstate(void *p)
+{
+ struct compat_state *st;
+
+ if (p == NULL)
+ return;
+ st = (struct compat_state *)p;
+ free(st->name);
+ if (st->fp != NULL)
+ fclose(st->fp);
+ free(p);
+}
+
+
+static int
+compat_setgrent(void *retval, void *mdata, va_list ap)
+{
+ static const ns_src compatsrc[] = {
+#ifdef YP
+ { NSSRC_NIS, NS_SUCCESS },
+#endif
+ { NULL, 0 }
+ };
+ ns_dtab dtab[] = {
+#ifdef HESIOD
+ { NSSRC_DNS, dns_setgrent, NULL },
+#endif
+#ifdef YP
+ { NSSRC_NIS, nis_setgrent, NULL },
+#endif
+ { NULL, NULL, NULL }
+ };
+ struct compat_state *st;
+ int rv, stayopen;
+
+#define set_setent(x, y) do { \
+ int i; \
+ \
+ for (i = 0; i < (sizeof(x)/sizeof(x[0])) - 1; i++) \
+ x[i].mdata = (void *)y; \
+} while (0)
+
+ rv = compat_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+ switch ((enum constants)mdata) {
+ case SETGRENT:
+ stayopen = va_arg(ap, int);
+ if (st->fp != NULL)
+ rewind(st->fp);
+ else if (stayopen)
+ st->fp = fopen(_PATH_GROUP, "r");
+ set_setent(dtab, mdata);
+ (void)_nsdispatch(NULL, dtab, NSDB_GROUP_COMPAT, "setgrent",
+ compatsrc, 0);
+ break;
+ case ENDGRENT:
+ if (st->fp != NULL) {
+ fclose(st->fp);
+ st->fp = NULL;
+ }
+ set_setent(dtab, mdata);
+ (void)_nsdispatch(NULL, dtab, NSDB_GROUP_COMPAT, "endgrent",
+ compatsrc, 0);
+ break;
+ default:
+ break;
+ }
+ st->compat = COMPAT_MODE_OFF;
+ free(st->name);
+ st->name = NULL;
+ return (NS_UNAVAIL);
+#undef set_setent
+}
+
+
+static int
+compat_group(void *retval, void *mdata, va_list ap)
+{
+ static const ns_src compatsrc[] = {
+#ifdef YP
+ { NSSRC_NIS, NS_SUCCESS },
+#endif
+ { NULL, 0 }
+ };
+ ns_dtab dtab[] = {
+#ifdef YP
+ { NSSRC_NIS, nis_group, NULL },
+#endif
+#ifdef HESIOD
+ { NSSRC_DNS, dns_group, NULL },
+#endif
+ { NULL, NULL, NULL }
+ };
+ struct compat_state *st;
+ enum nss_lookup_type how;
+ const char *name, *line;
+ struct group *grp;
+ gid_t gid;
+ char *buffer, *p;
+ void *discard;
+ size_t bufsize, linesize;
+ off_t pos;
+ int rv, stayopen, *errnop;
+
+#define set_lookup_type(x, y) do { \
+ int i; \
+ \
+ for (i = 0; i < (sizeof(x)/sizeof(x[0])) - 1; i++) \
+ x[i].mdata = (void *)y; \
+} while (0)
+
+ name = NULL;
+ gid = (gid_t)-1;
+ how = (enum nss_lookup_type)mdata;
+ switch (how) {
+ case nss_lt_name:
+ name = va_arg(ap, const char *);
+ break;
+ case nss_lt_id:
+ gid = va_arg(ap, gid_t);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ return (NS_NOTFOUND);
+ }
+ grp = va_arg(ap, struct group *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ *errnop = compat_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+ if (st->fp == NULL &&
+ ((st->fp = fopen(_PATH_GROUP, "r")) == NULL)) {
+ *errnop = errno;
+ rv = NS_UNAVAIL;
+ goto fin;
+ }
+ if (how == nss_lt_all)
+ stayopen = 1;
+ else {
+ rewind(st->fp);
+ stayopen = st->stayopen;
+ }
+docompat:
+ switch (st->compat) {
+ case COMPAT_MODE_ALL:
+ set_lookup_type(dtab, how);
+ switch (how) {
+ case nss_lt_all:
+ rv = _nsdispatch(&discard, dtab, NSDB_GROUP_COMPAT,
+ "getgrent_r", compatsrc, grp, buffer, bufsize,
+ errnop);
+ break;
+ case nss_lt_id:
+ rv = _nsdispatch(&discard, dtab, NSDB_GROUP_COMPAT,
+ "getgrgid_r", compatsrc, gid, grp, buffer, bufsize,
+ errnop);
+ break;
+ case nss_lt_name:
+ rv = _nsdispatch(&discard, dtab, NSDB_GROUP_COMPAT,
+ "getgrnam_r", compatsrc, name, grp, buffer,
+ bufsize, errnop);
+ break;
+ }
+ if (rv & NS_TERMINATE)
+ goto fin;
+ st->compat = COMPAT_MODE_OFF;
+ break;
+ case COMPAT_MODE_NAME:
+ set_lookup_type(dtab, nss_lt_name);
+ rv = _nsdispatch(&discard, dtab, NSDB_GROUP_COMPAT,
+ "getgrnam_r", compatsrc, st->name, grp, buffer, bufsize,
+ errnop);
+ switch (rv) {
+ case NS_SUCCESS:
+ switch (how) {
+ case nss_lt_name:
+ if (strcmp(name, grp->gr_name) != 0)
+ rv = NS_NOTFOUND;
+ break;
+ case nss_lt_id:
+ if (gid != grp->gr_gid)
+ rv = NS_NOTFOUND;
+ break;
+ default:
+ break;
+ }
+ break;
+ case NS_RETURN:
+ goto fin;
+ default:
+ break;
+ }
+ free(st->name);
+ st->name = NULL;
+ st->compat = COMPAT_MODE_OFF;
+ if (rv == NS_SUCCESS)
+ goto fin;
+ break;
+ default:
+ break;
+ }
+ rv = NS_NOTFOUND;
+ pos = ftello(st->fp);
+ while ((line = fgetln(st->fp, &linesize)) != NULL) {
+ if (line[linesize-1] == '\n')
+ linesize--;
+ if (linesize > 2 && line[0] == '+') {
+ p = memchr(&line[1], ':', linesize);
+ if (p == NULL || p == &line[1])
+ st->compat = COMPAT_MODE_ALL;
+ else {
+ st->name = malloc(p - line);
+ if (st->name == NULL) {
+ syslog(LOG_ERR,
+ "getgrent memory allocation failure");
+ *errnop = ENOMEM;
+ rv = NS_UNAVAIL;
+ break;
+ }
+ memcpy(st->name, &line[1], p - line - 1);
+ st->name[p - line - 1] = '\0';
+ st->compat = COMPAT_MODE_NAME;
+ }
+ goto docompat;
+ }
+ rv = __gr_match_entry(line, linesize, how, name, gid);
+ if (rv != NS_SUCCESS)
+ continue;
+ /* We need room at least for the line, a string NUL
+ * terminator, alignment padding, and one (char *)
+ * pointer for the member list terminator.
+ */
+ if (bufsize <= linesize + _ALIGNBYTES + sizeof(char *)) {
+ *errnop = ERANGE;
+ rv = NS_RETURN;
+ break;
+ }
+ memcpy(buffer, line, linesize);
+ buffer[linesize] = '\0';
+ rv = __gr_parse_entry(buffer, linesize, grp,
+ &buffer[linesize + 1], bufsize - linesize - 1, errnop);
+ if (rv & NS_TERMINATE)
+ break;
+ pos = ftello(st->fp);
+ }
+fin:
+ if (!stayopen && st->fp != NULL) {
+ fclose(st->fp);
+ st->fp = NULL;
+ }
+ if (rv == NS_SUCCESS && retval != NULL)
+ *(struct group **)retval = grp;
+ else if (rv == NS_RETURN && *errnop == ERANGE && st->fp != NULL)
+ fseeko(st->fp, pos, SEEK_SET);
+ return (rv);
+#undef set_lookup_type
+}
+
+
+/*
+ * common group line matching and parsing
+ */
+int
+__gr_match_entry(const char *line, size_t linesize, enum nss_lookup_type how,
+ const char *name, gid_t gid)
+{
+ size_t namesize;
+ const char *p, *eol;
+ char *q;
+ unsigned long n;
+ int i, needed;
+
+ if (linesize == 0 || is_comment_line(line, linesize))
+ return (NS_NOTFOUND);
+ switch (how) {
+ case nss_lt_name: needed = 1; break;
+ case nss_lt_id: needed = 2; break;
+ default: needed = 2; break;
+ }
+ eol = &line[linesize];
+ for (p = line, i = 0; i < needed && p < eol; p++)
+ if (*p == ':')
+ i++;
+ if (i < needed)
+ return (NS_NOTFOUND);
+ switch (how) {
+ case nss_lt_name:
+ namesize = strlen(name);
+ if (namesize + 1 == (size_t)(p - line) &&
+ memcmp(line, name, namesize) == 0)
+ return (NS_SUCCESS);
+ break;
+ case nss_lt_id:
+ n = strtoul(p, &q, 10);
+ if (q < eol && *q == ':' && gid == (gid_t)n)
+ return (NS_SUCCESS);
+ break;
+ case nss_lt_all:
+ return (NS_SUCCESS);
+ default:
+ break;
+ }
+ return (NS_NOTFOUND);
+}
+
+
+int
+__gr_parse_entry(char *line, size_t linesize, struct group *grp, char *membuf,
+ size_t membufsize, int *errnop)
+{
+ char *s_gid, *s_mem, *p, **members;
+ unsigned long n;
+ int maxmembers;
+
+ memset(grp, 0, sizeof(*grp));
+ members = (char **)_ALIGN(membuf);
+ membufsize -= (char *)members - membuf;
+ maxmembers = membufsize / sizeof(*members);
+ if (maxmembers <= 0 ||
+ (grp->gr_name = strsep(&line, ":")) == NULL ||
+ grp->gr_name[0] == '\0' ||
+ (grp->gr_passwd = strsep(&line, ":")) == NULL ||
+ (s_gid = strsep(&line, ":")) == NULL ||
+ s_gid[0] == '\0')
+ return (NS_NOTFOUND);
+ s_mem = line;
+ n = strtoul(s_gid, &s_gid, 10);
+ if (s_gid[0] != '\0')
+ return (NS_NOTFOUND);
+ grp->gr_gid = (gid_t)n;
+ grp->gr_mem = members;
+ while (maxmembers > 1 && s_mem != NULL) {
+ p = strsep(&s_mem, ",");
+ if (p != NULL && *p != '\0') {
+ *members++ = p;
+ maxmembers--;
+ }
+ }
+ *members = NULL;
+ if (s_mem == NULL)
+ return (NS_SUCCESS);
+ else {
+ *errnop = ERANGE;
+ return (NS_RETURN);
+ }
+}
+
+
diff --git a/lib/libc/gen/getgrouplist.3 b/lib/libc/gen/getgrouplist.3
new file mode 100644
index 0000000..44d95f5
--- /dev/null
+++ b/lib/libc/gen/getgrouplist.3
@@ -0,0 +1,92 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getgrouplist.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd February 20, 2012
+.Dt GETGROUPLIST 3
+.Os
+.Sh NAME
+.Nm getgrouplist
+.Nd calculate group access list
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn getgrouplist "const char *name" "gid_t basegid" "gid_t *groups" "int *ngroups"
+.Sh DESCRIPTION
+The
+.Fn getgrouplist
+function reads through the group file and calculates
+the group access list for the user specified in
+.Fa name .
+The
+.Fa basegid
+is automatically included in the groups list.
+Typically this value is given as
+the group number from the password file.
+.Pp
+The resulting group list is returned in the array pointed to by
+.Fa groups .
+The caller specifies the size of the
+.Fa groups
+array in the integer pointed to by
+.Fa ngroups ;
+the actual number of groups found is returned in
+.Fa ngroups .
+.Sh RETURN VALUES
+The
+.Fn getgrouplist
+function
+returns 0 on success and \-1 if the size of the group list is too small to
+hold all the user's groups.
+Here, the group array will be filled with as many groups as will fit.
+.Sh FILES
+.Bl -tag -width /etc/group -compact
+.It Pa /etc/group
+group membership list
+.El
+.Sh SEE ALSO
+.Xr setgroups 2 ,
+.Xr initgroups 3
+.Sh HISTORY
+The
+.Fn getgrouplist
+function first appeared in
+.Bx 4.4 .
+.Sh BUGS
+The
+.Fn getgrouplist
+function
+uses the routines based on
+.Xr getgrent 3 .
+If the invoking program uses any of these routines,
+the group structure will
+be overwritten in the call to
+.Fn getgrouplist .
diff --git a/lib/libc/gen/getgrouplist.c b/lib/libc/gen/getgrouplist.c
new file mode 100644
index 0000000..9eb55f9
--- /dev/null
+++ b/lib/libc/gen/getgrouplist.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getgrouplist.c 8.2 (Berkeley) 12/8/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * get credential
+ */
+#include <sys/types.h>
+
+#include <grp.h>
+#include <string.h>
+#include <unistd.h>
+
+extern int __getgroupmembership(const char *, gid_t, gid_t *, int, int *);
+
+int
+getgrouplist(const char *uname, gid_t agroup, gid_t *groups, int *grpcnt)
+{
+ return __getgroupmembership(uname, agroup, groups, *grpcnt, grpcnt);
+}
+
diff --git a/lib/libc/gen/gethostname.3 b/lib/libc/gen/gethostname.3
new file mode 100644
index 0000000..00853ef
--- /dev/null
+++ b/lib/libc/gen/gethostname.3
@@ -0,0 +1,131 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)gethostname.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd August 18, 2003
+.Dt GETHOSTNAME 3
+.Os
+.Sh NAME
+.Nm gethostname ,
+.Nm sethostname
+.Nd get/set name of current host
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn gethostname "char *name" "size_t namelen"
+.Ft int
+.Fn sethostname "const char *name" "int namelen"
+.Sh DESCRIPTION
+The
+.Fn gethostname
+function
+returns the standard host name for the current processor, as
+previously set by
+.Fn sethostname .
+The
+.Fa namelen
+argument
+specifies the size of the
+.Fa name
+array.
+The returned name is null-terminated unless insufficient space is provided.
+.Pp
+The
+.Fn sethostname
+function
+sets the name of the host machine to be
+.Fa name ,
+which has length
+.Fa namelen .
+This call is restricted to the super-user and
+is normally used only when the system is bootstrapped.
+.Pp
+Host names are limited to
+.Brq Dv HOST_NAME_MAX
+characters, not including the trailing null, currently 255.
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+The following errors may be returned by these calls:
+.Bl -tag -width Er
+.It Bq Er EFAULT
+The
+.Fa name
+or
+.Fa namelen
+argument gave an
+invalid address.
+.It Bq Er ENAMETOOLONG
+The current host name is longer than
+.Fa namelen .
+(For
+.Fn gethostname
+only.)
+.It Bq Er EPERM
+The caller tried to set the host name and was not the super-user.
+.El
+.Sh SEE ALSO
+.Xr sysconf 3 ,
+.Xr sysctl 3
+.Sh STANDARDS
+The
+.Fn gethostname
+function conforms to
+.St -p1003.1-2001 .
+Callers should be aware that
+.Brq Dv HOST_NAME_MAX
+may be variable or infinite, but is guaranteed to be no less than
+.Brq Dv _POSIX_HOST_NAME_MAX .
+On older systems, this limit was defined in the non-standard header
+.In sys/param.h
+as
+.Dv MAXHOSTNAMELEN ,
+and counted the terminating null.
+The
+.Fn sethostname
+function and the error returns for
+.Fn gethostname
+are not standardized.
+.Sh HISTORY
+The
+.Fn gethostname
+function appeared in
+.Bx 4.2 .
+The
+.Fa namelen
+argument to
+.Fn gethostname
+was changed to
+.Vt size_t
+in
+.Fx 5.2
+for alignment with
+.St -p1003.1-2001 .
diff --git a/lib/libc/gen/gethostname.c b/lib/libc/gen/gethostname.c
new file mode 100644
index 0000000..c83805e
--- /dev/null
+++ b/lib/libc/gen/gethostname.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostname.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+int
+gethostname(name, namelen)
+ char *name;
+ size_t namelen;
+{
+ int mib[2];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_HOSTNAME;
+ if (sysctl(mib, 2, name, &namelen, NULL, 0) == -1) {
+ if (errno == ENOMEM)
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+ return (0);
+}
diff --git a/lib/libc/gen/getloadavg.3 b/lib/libc/gen/getloadavg.3
new file mode 100644
index 0000000..5a77ecb
--- /dev/null
+++ b/lib/libc/gen/getloadavg.3
@@ -0,0 +1,65 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getloadavg.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt GETLOADAVG 3
+.Os
+.Sh NAME
+.Nm getloadavg
+.Nd get system load averages
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fn getloadavg "double loadavg[]" "int nelem"
+.Sh DESCRIPTION
+The
+.Fn getloadavg
+function returns the number of processes in the system run queue
+averaged over various periods of time.
+Up to
+.Fa nelem
+samples are retrieved and assigned to successive elements of
+.Fa loadavg Ns Bq .
+The system imposes a maximum of 3 samples, representing averages
+over the last 1, 5, and 15 minutes, respectively.
+.Sh DIAGNOSTICS
+If the load average was unobtainable, \-1 is returned; otherwise,
+the number of samples actually retrieved is returned.
+.Sh SEE ALSO
+.Xr uptime 1 ,
+.Xr kvm_getloadavg 3 ,
+.Xr sysctl 3
+.Sh HISTORY
+The
+.Fn getloadavg
+function appeared in
+.Bx 4.3 Reno .
diff --git a/lib/libc/gen/getloadavg.c b/lib/libc/gen/getloadavg.c
new file mode 100644
index 0000000..127d3e8
--- /dev/null
+++ b/lib/libc/gen/getloadavg.c
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getloadavg.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <sys/sysctl.h>
+#include <vm/vm_param.h>
+
+#include <stdlib.h>
+
+/*
+ * getloadavg() -- Get system load averages.
+ *
+ * Put `nelem' samples into `loadavg' array.
+ * Return number of samples retrieved, or -1 on error.
+ */
+int
+getloadavg(loadavg, nelem)
+ double loadavg[];
+ int nelem;
+{
+ struct loadavg loadinfo;
+ int i, mib[2];
+ size_t size;
+
+ mib[0] = CTL_VM;
+ mib[1] = VM_LOADAVG;
+ size = sizeof(loadinfo);
+ if (sysctl(mib, 2, &loadinfo, &size, NULL, 0) < 0)
+ return (-1);
+
+ nelem = MIN(nelem, sizeof(loadinfo.ldavg) / sizeof(fixpt_t));
+ for (i = 0; i < nelem; i++)
+ loadavg[i] = (double) loadinfo.ldavg[i] / loadinfo.fscale;
+ return (nelem);
+}
diff --git a/lib/libc/gen/getlogin.c b/lib/libc/gen/getlogin.c
new file mode 100644
index 0000000..569cf42
--- /dev/null
+++ b/lib/libc/gen/getlogin.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getlogin.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <errno.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "namespace.h"
+#include <pthread.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+#define THREAD_LOCK() if (__isthreaded) _pthread_mutex_lock(&logname_mutex)
+#define THREAD_UNLOCK() if (__isthreaded) _pthread_mutex_unlock(&logname_mutex)
+
+extern int _getlogin(char *, int);
+
+int _logname_valid; /* known to setlogin() */
+static pthread_mutex_t logname_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+static char *
+getlogin_basic(int *status)
+{
+ static char logname[MAXLOGNAME];
+
+ if (_logname_valid == 0) {
+ if (_getlogin(logname, sizeof(logname)) < 0) {
+ *status = errno;
+ return (NULL);
+ }
+ _logname_valid = 1;
+ }
+ *status = 0;
+ return (*logname ? logname : NULL);
+}
+
+char *
+getlogin(void)
+{
+ char *result;
+ int status;
+
+ THREAD_LOCK();
+ result = getlogin_basic(&status);
+ THREAD_UNLOCK();
+ return (result);
+}
+
+int
+getlogin_r(char *logname, int namelen)
+{
+ char *result;
+ int len;
+ int status;
+
+ THREAD_LOCK();
+ result = getlogin_basic(&status);
+ if (status == 0) {
+ if ((len = strlen(result) + 1) > namelen)
+ status = ERANGE;
+ else
+ strncpy(logname, result, len);
+ }
+ THREAD_UNLOCK();
+ return (status);
+}
diff --git a/lib/libc/gen/getmntinfo.3 b/lib/libc/gen/getmntinfo.3
new file mode 100644
index 0000000..dc83e37
--- /dev/null
+++ b/lib/libc/gen/getmntinfo.3
@@ -0,0 +1,109 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getmntinfo.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd June 9, 1993
+.Dt GETMNTINFO 3
+.Os
+.Sh NAME
+.Nm getmntinfo
+.Nd get information about mounted file systems
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/ucred.h
+.In sys/mount.h
+.Ft int
+.Fn getmntinfo "struct statfs **mntbufp" "int flags"
+.Sh DESCRIPTION
+The
+.Fn getmntinfo
+function
+returns an array of
+.Fn statfs
+structures describing each currently mounted file system (see
+.Xr statfs 2 ) .
+.Pp
+The
+.Fn getmntinfo
+function
+passes its
+.Fa flags
+argument transparently to
+.Xr getfsstat 2 .
+.Sh RETURN VALUES
+On successful completion,
+.Fn getmntinfo
+returns a count of the number of elements in the array.
+The pointer to the array is stored into
+.Fa mntbufp .
+.Pp
+If an error occurs, zero is returned and the external variable
+.Va errno
+is set to indicate the error.
+Although the pointer
+.Fa mntbufp
+will be unmodified, any information previously returned by
+.Fn getmntinfo
+will be lost.
+.Sh ERRORS
+The
+.Fn getmntinfo
+function
+may fail and set errno for any of the errors specified for the library
+routines
+.Xr getfsstat 2
+or
+.Xr malloc 3 .
+.Sh SEE ALSO
+.Xr getfsstat 2 ,
+.Xr mount 2 ,
+.Xr statfs 2 ,
+.Xr mount 8
+.Sh HISTORY
+The
+.Fn getmntinfo
+function first appeared in
+.Bx 4.4 .
+.Sh BUGS
+The
+.Fn getmntinfo
+function writes the array of structures to an internal static object
+and returns
+a pointer to that object.
+Subsequent calls to
+.Fn getmntinfo
+will modify the same object.
+.Pp
+The memory allocated by
+.Fn getmntinfo
+cannot be
+.Xr free 3 Ns 'd
+by the application.
diff --git a/lib/libc/gen/getmntinfo.c b/lib/libc/gen/getmntinfo.c
new file mode 100644
index 0000000..2b532f6
--- /dev/null
+++ b/lib/libc/gen/getmntinfo.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getmntinfo.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/ucred.h>
+#include <sys/mount.h>
+#include <stdlib.h>
+
+/*
+ * Return information about mounted filesystems.
+ */
+int
+getmntinfo(mntbufp, flags)
+ struct statfs **mntbufp;
+ int flags;
+{
+ static struct statfs *mntbuf;
+ static int mntsize;
+ static long bufsize;
+
+ if (mntsize <= 0 && (mntsize = getfsstat(0, 0, MNT_NOWAIT)) < 0)
+ return (0);
+ if (bufsize > 0 && (mntsize = getfsstat(mntbuf, bufsize, flags)) < 0)
+ return (0);
+ while (bufsize <= mntsize * sizeof(struct statfs)) {
+ if (mntbuf)
+ free(mntbuf);
+ bufsize = (mntsize + 1) * sizeof(struct statfs);
+ if ((mntbuf = (struct statfs *)malloc(bufsize)) == 0)
+ return (0);
+ if ((mntsize = getfsstat(mntbuf, bufsize, flags)) < 0)
+ return (0);
+ }
+ *mntbufp = mntbuf;
+ return (mntsize);
+}
diff --git a/lib/libc/gen/getnetgrent.3 b/lib/libc/gen/getnetgrent.3
new file mode 100644
index 0000000..4cc2a21
--- /dev/null
+++ b/lib/libc/gen/getnetgrent.3
@@ -0,0 +1,131 @@
+.\" Copyright (c) 1992, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getnetgrent.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt GETNETGRENT 3
+.Os
+.Sh NAME
+.Nm getnetgrent ,
+.Nm innetgr ,
+.Nm setnetgrent ,
+.Nm endnetgrent
+.Nd netgroup database operations
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In netdb.h
+.Ft int
+.Fn getnetgrent "char **host" "char **user" "char **domain"
+.Ft int
+.Fn innetgr "const char *netgroup" "const char *host" "const char *user" "const char *domain"
+.Ft void
+.Fn setnetgrent "const char *netgroup"
+.Ft void
+.Fn endnetgrent void
+.Sh DESCRIPTION
+These functions operate on the netgroup database file
+.Pa /etc/netgroup
+which is described
+in
+.Xr netgroup 5 .
+The database defines a set of netgroups, each made up of one or more triples:
+.Bd -literal -offset indent
+(host, user, domain)
+.Ed
+that defines a combination of host, user and domain.
+Any of the three fields may be specified as ``wildcards'' that match any
+string.
+.Pp
+The function
+.Fn getnetgrent
+sets the three pointer arguments to the strings of the next member of the
+current netgroup.
+If any of the string pointers are
+.Sy (char *)0
+that field is considered a wildcard.
+.Pp
+The functions
+.Fn setnetgrent
+and
+.Fn endnetgrent
+set the current netgroup and terminate the current netgroup respectively.
+If
+.Fn setnetgrent
+is called with a different netgroup than the previous call, an implicit
+.Fn endnetgrent
+is implied.
+The
+.Fn setnetgrent
+function
+also sets the offset to the first member of the netgroup.
+.Pp
+The function
+.Fn innetgr
+searches for a match of all fields within the specified group.
+If any of the
+.Sy host ,
+.Sy user ,
+or
+.Sy domain
+arguments are
+.Sy (char *)0
+those fields will match any string value in the netgroup member.
+.Sh RETURN VALUES
+The function
+.Fn getnetgrent
+returns 0 for ``no more netgroup members'' and 1 otherwise.
+The function
+.Fn innetgr
+returns 1 for a successful match and 0 otherwise.
+The functions
+.Fn setnetgrent
+and
+.Fn endnetgrent
+have no return value.
+.Sh FILES
+.Bl -tag -width /etc/netgroup -compact
+.It Pa /etc/netgroup
+netgroup database file
+.El
+.Sh COMPATIBILITY
+The netgroup members have three string fields to maintain compatibility
+with other vendor implementations, however it is not obvious what use the
+.Sy domain
+string has within
+.Bx .
+.Sh SEE ALSO
+.Xr netgroup 5
+.Sh BUGS
+The function
+.Fn getnetgrent
+returns pointers to dynamically allocated data areas that are freed when
+the function
+.Fn endnetgrent
+is called.
diff --git a/lib/libc/gen/getnetgrent.c b/lib/libc/gen/getnetgrent.c
new file mode 100644
index 0000000..ca75d9b
--- /dev/null
+++ b/lib/libc/gen/getnetgrent.c
@@ -0,0 +1,638 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Rick Macklem at The University of Guelph.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetgrent.c 8.2 (Berkeley) 4/27/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifdef YP
+/*
+ * Notes:
+ * We want to be able to use NIS netgroups properly while retaining
+ * the ability to use a local /etc/netgroup file. Unfortunately, you
+ * can't really do both at the same time - at least, not efficiently.
+ * NetBSD deals with this problem by creating a netgroup database
+ * using Berkeley DB (just like the password database) that allows
+ * for lookups using netgroup, netgroup.byuser or netgroup.byhost
+ * searches. This is a neat idea, but I don't have time to implement
+ * something like that now. (I think ultimately it would be nice
+ * if we DB-fied the group and netgroup stuff all in one shot, but
+ * for now I'm satisfied just to have something that works well
+ * without requiring massive code changes.)
+ *
+ * Therefore, to still permit the use of the local file and maintain
+ * optimum NIS performance, we allow for the following conditions:
+ *
+ * - If /etc/netgroup does not exist and NIS is turned on, we use
+ * NIS netgroups only.
+ *
+ * - If /etc/netgroup exists but is empty, we use NIS netgroups
+ * only.
+ *
+ * - If /etc/netgroup exists and contains _only_ a '+', we use
+ * NIS netgroups only.
+ *
+ * - If /etc/netgroup exists, contains locally defined netgroups
+ * and a '+', we use a mixture of NIS and the local entries.
+ * This method should return the same NIS data as just using
+ * NIS alone, but it will be slower if the NIS netgroup database
+ * is large (innetgr() in particular will suffer since extra
+ * processing has to be done in order to determine memberships
+ * using just the raw netgroup data).
+ *
+ * - If /etc/netgroup exists and contains only locally defined
+ * netgroup entries, we use just those local entries and ignore
+ * NIS (this is the original, pre-NIS behavior).
+ */
+
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <sys/errno.h>
+static char *_netgr_yp_domain;
+int _use_only_yp;
+static int _netgr_yp_enabled;
+static int _yp_innetgr;
+#endif
+
+#ifndef _PATH_NETGROUP
+#define _PATH_NETGROUP "/etc/netgroup"
+#endif
+
+/*
+ * Static Variables and functions used by setnetgrent(), getnetgrent() and
+ * endnetgrent().
+ * There are two linked lists:
+ * - linelist is just used by setnetgrent() to parse the net group file via.
+ * parse_netgrp()
+ * - netgrp is the list of entries for the current netgroup
+ */
+struct linelist {
+ struct linelist *l_next; /* Chain ptr. */
+ int l_parsed; /* Flag for cycles */
+ char *l_groupname; /* Name of netgroup */
+ char *l_line; /* Netgroup entrie(s) to be parsed */
+};
+
+struct netgrp {
+ struct netgrp *ng_next; /* Chain ptr */
+ char *ng_str[3]; /* Field pointers, see below */
+};
+#define NG_HOST 0 /* Host name */
+#define NG_USER 1 /* User name */
+#define NG_DOM 2 /* and Domain name */
+
+static struct linelist *linehead = (struct linelist *)0;
+static struct netgrp *nextgrp = (struct netgrp *)0;
+static struct {
+ struct netgrp *gr;
+ char *grname;
+} grouphead = {
+ (struct netgrp *)0,
+ (char *)0,
+};
+static FILE *netf = (FILE *)0;
+
+static int parse_netgrp(const char *);
+static struct linelist *read_for_group(const char *);
+void setnetgrent(const char *);
+void endnetgrent(void);
+int getnetgrent(char **, char **, char **);
+int innetgr(const char *, const char *, const char *, const char *);
+
+#define LINSIZ 1024 /* Length of netgroup file line */
+
+/*
+ * setnetgrent()
+ * Parse the netgroup file looking for the netgroup and build the list
+ * of netgrp structures. Let parse_netgrp() and read_for_group() do
+ * most of the work.
+ */
+void
+setnetgrent(const char *group)
+{
+#ifdef YP
+ struct stat _yp_statp;
+ char _yp_plus;
+#endif
+
+ /* Sanity check */
+
+ if (group == NULL || !strlen(group))
+ return;
+
+ if (grouphead.gr == (struct netgrp *)0 ||
+ strcmp(group, grouphead.grname)) {
+ endnetgrent();
+#ifdef YP
+ /* Presumed guilty until proven innocent. */
+ _use_only_yp = 0;
+ /*
+ * If /etc/netgroup doesn't exist or is empty,
+ * use NIS exclusively.
+ */
+ if (((stat(_PATH_NETGROUP, &_yp_statp) < 0) &&
+ errno == ENOENT) || _yp_statp.st_size == 0)
+ _use_only_yp = _netgr_yp_enabled = 1;
+ if ((netf = fopen(_PATH_NETGROUP,"r")) != NULL ||_use_only_yp){
+ /*
+ * Icky: grab the first character of the netgroup file
+ * and turn on NIS if it's a '+'. rewind the stream
+ * afterwards so we don't goof up read_for_group() later.
+ */
+ if (netf) {
+ fscanf(netf, "%c", &_yp_plus);
+ rewind(netf);
+ if (_yp_plus == '+')
+ _use_only_yp = _netgr_yp_enabled = 1;
+ }
+ /*
+ * If we were called specifically for an innetgr()
+ * lookup and we're in NIS-only mode, short-circuit
+ * parse_netgroup() and cut directly to the chase.
+ */
+ if (_use_only_yp && _yp_innetgr) {
+ /* dohw! */
+ if (netf != NULL)
+ fclose(netf);
+ return;
+ }
+#else
+ if ((netf = fopen(_PATH_NETGROUP, "r"))) {
+#endif
+ if (parse_netgrp(group))
+ endnetgrent();
+ else {
+ grouphead.grname = (char *)
+ malloc(strlen(group) + 1);
+ strcpy(grouphead.grname, group);
+ }
+ if (netf)
+ fclose(netf);
+ }
+ }
+ nextgrp = grouphead.gr;
+}
+
+/*
+ * Get the next netgroup off the list.
+ */
+int
+getnetgrent(char **hostp, char **userp, char **domp)
+{
+#ifdef YP
+ _yp_innetgr = 0;
+#endif
+
+ if (nextgrp) {
+ *hostp = nextgrp->ng_str[NG_HOST];
+ *userp = nextgrp->ng_str[NG_USER];
+ *domp = nextgrp->ng_str[NG_DOM];
+ nextgrp = nextgrp->ng_next;
+ return (1);
+ }
+ return (0);
+}
+
+/*
+ * endnetgrent() - cleanup
+ */
+void
+endnetgrent(void)
+{
+ struct linelist *lp, *olp;
+ struct netgrp *gp, *ogp;
+
+ lp = linehead;
+ while (lp) {
+ olp = lp;
+ lp = lp->l_next;
+ free(olp->l_groupname);
+ free(olp->l_line);
+ free((char *)olp);
+ }
+ linehead = (struct linelist *)0;
+ if (grouphead.grname) {
+ free(grouphead.grname);
+ grouphead.grname = (char *)0;
+ }
+ gp = grouphead.gr;
+ while (gp) {
+ ogp = gp;
+ gp = gp->ng_next;
+ if (ogp->ng_str[NG_HOST])
+ free(ogp->ng_str[NG_HOST]);
+ if (ogp->ng_str[NG_USER])
+ free(ogp->ng_str[NG_USER]);
+ if (ogp->ng_str[NG_DOM])
+ free(ogp->ng_str[NG_DOM]);
+ free((char *)ogp);
+ }
+ grouphead.gr = (struct netgrp *)0;
+ nextgrp = (struct netgrp *)0;
+#ifdef YP
+ _netgr_yp_enabled = 0;
+#endif
+}
+
+#ifdef YP
+static int
+_listmatch(const char *list, const char *group, int len)
+{
+ const char *ptr = list;
+ const char *cptr;
+ int glen = strlen(group);
+
+ /* skip possible leading whitespace */
+ while(isspace((unsigned char)*ptr))
+ ptr++;
+
+ while (ptr < list + len) {
+ cptr = ptr;
+ while(*ptr != ',' && *ptr != '\0' && !isspace((unsigned char)*ptr))
+ ptr++;
+ if (strncmp(cptr, group, glen) == 0 && glen == (ptr - cptr))
+ return(1);
+ while(*ptr == ',' || isspace((unsigned char)*ptr))
+ ptr++;
+ }
+
+ return(0);
+}
+
+static int
+_revnetgr_lookup(char* lookupdom, char* map, const char* str,
+ const char* dom, const char* group)
+{
+ int y, rv, rot;
+ char key[MAXHOSTNAMELEN];
+ char *result;
+ int resultlen;
+
+ for (rot = 0; ; rot++) {
+ switch (rot) {
+ case(0): snprintf(key, MAXHOSTNAMELEN, "%s.%s",
+ str, dom?dom:lookupdom);
+ break;
+ case(1): snprintf(key, MAXHOSTNAMELEN, "%s.*",
+ str);
+ break;
+ case(2): snprintf(key, MAXHOSTNAMELEN, "*.%s",
+ dom?dom:lookupdom);
+ break;
+ case(3): snprintf(key, MAXHOSTNAMELEN, "*.*");
+ break;
+ default: return(0);
+ }
+ y = yp_match(lookupdom, map, key, strlen(key), &result,
+ &resultlen);
+ if (y == 0) {
+ rv = _listmatch(result, group, resultlen);
+ free(result);
+ if (rv) return(1);
+ } else if (y != YPERR_KEY) {
+ /*
+ * If we get an error other than 'no
+ * such key in map' then something is
+ * wrong and we should stop the search.
+ */
+ return(-1);
+ }
+ }
+}
+#endif
+
+/*
+ * Search for a match in a netgroup.
+ */
+int
+innetgr(const char *group, const char *host, const char *user, const char *dom)
+{
+ char *hst, *usr, *dm;
+ /* Sanity check */
+
+ if (group == NULL || !strlen(group))
+ return (0);
+
+#ifdef YP
+ _yp_innetgr = 1;
+#endif
+ setnetgrent(group);
+#ifdef YP
+ _yp_innetgr = 0;
+ /*
+ * If we're in NIS-only mode, do the search using
+ * NIS 'reverse netgroup' lookups.
+ *
+ * What happens with 'reverse netgroup' lookups:
+ *
+ * 1) try 'reverse netgroup' lookup
+ * 1.a) if host is specified and user is null:
+ * look in netgroup.byhost
+ * (try host.domain, host.*, *.domain or *.*)
+ * if found, return yes
+ * 1.b) if user is specified and host is null:
+ * look in netgroup.byuser
+ * (try host.domain, host.*, *.domain or *.*)
+ * if found, return yes
+ * 1.c) if both host and user are specified,
+ * don't do 'reverse netgroup' lookup. It won't work.
+ * 1.d) if neither host ane user are specified (why?!?)
+ * don't do 'reverse netgroup' lookup either.
+ * 2) if domain is specified and 'reverse lookup' is done:
+ * 'reverse lookup' was authoritative. bye bye.
+ * 3) otherwise, too bad, try it the slow way.
+ */
+ if (_use_only_yp && (host == NULL) != (user == NULL)) {
+ int ret;
+ if(yp_get_default_domain(&_netgr_yp_domain))
+ return(0);
+ ret = _revnetgr_lookup(_netgr_yp_domain,
+ host?"netgroup.byhost":"netgroup.byuser",
+ host?host:user, dom, group);
+ if (ret == 1)
+ return(1);
+ else if (ret == 0 && dom != NULL)
+ return(0);
+ }
+
+ setnetgrent(group);
+#endif /* YP */
+
+ while (getnetgrent(&hst, &usr, &dm))
+ if ((host == NULL || hst == NULL || !strcmp(host, hst)) &&
+ (user == NULL || usr == NULL || !strcmp(user, usr)) &&
+ ( dom == NULL || dm == NULL || !strcmp(dom, dm))) {
+ endnetgrent();
+ return (1);
+ }
+ endnetgrent();
+ return (0);
+}
+
+/*
+ * Parse the netgroup file setting up the linked lists.
+ */
+static int
+parse_netgrp(const char *group)
+{
+ char *spos, *epos;
+ int len, strpos;
+#ifdef DEBUG
+ int fields;
+#endif
+ char *pos, *gpos;
+ struct netgrp *grp;
+ struct linelist *lp = linehead;
+
+ /*
+ * First, see if the line has already been read in.
+ */
+ while (lp) {
+ if (!strcmp(group, lp->l_groupname))
+ break;
+ lp = lp->l_next;
+ }
+ if (lp == (struct linelist *)0 &&
+ (lp = read_for_group(group)) == (struct linelist *)0)
+ return (1);
+ if (lp->l_parsed) {
+#ifdef DEBUG
+ /*
+ * This error message is largely superflous since the
+ * code handles the error condition sucessfully, and
+ * spewing it out from inside libc can actually hose
+ * certain programs.
+ */
+ fprintf(stderr, "Cycle in netgroup %s\n", lp->l_groupname);
+#endif
+ return (1);
+ } else
+ lp->l_parsed = 1;
+ pos = lp->l_line;
+ /* Watch for null pointer dereferences, dammit! */
+ while (pos != NULL && *pos != '\0') {
+ if (*pos == '(') {
+ grp = (struct netgrp *)malloc(sizeof (struct netgrp));
+ bzero((char *)grp, sizeof (struct netgrp));
+ grp->ng_next = grouphead.gr;
+ grouphead.gr = grp;
+ pos++;
+ gpos = strsep(&pos, ")");
+#ifdef DEBUG
+ fields = 0;
+#endif
+ for (strpos = 0; strpos < 3; strpos++) {
+ if ((spos = strsep(&gpos, ","))) {
+#ifdef DEBUG
+ fields++;
+#endif
+ while (*spos == ' ' || *spos == '\t')
+ spos++;
+ if ((epos = strpbrk(spos, " \t"))) {
+ *epos = '\0';
+ len = epos - spos;
+ } else
+ len = strlen(spos);
+ if (len > 0) {
+ grp->ng_str[strpos] = (char *)
+ malloc(len + 1);
+ bcopy(spos, grp->ng_str[strpos],
+ len + 1);
+ }
+ } else {
+ /*
+ * All other systems I've tested
+ * return NULL for empty netgroup
+ * fields. It's up to user programs
+ * to handle the NULLs appropriately.
+ */
+ grp->ng_str[strpos] = NULL;
+ }
+ }
+#ifdef DEBUG
+ /*
+ * Note: on other platforms, malformed netgroup
+ * entries are not normally flagged. While we
+ * can catch bad entries and report them, we should
+ * stay silent by default for compatibility's sake.
+ */
+ if (fields < 3)
+ fprintf(stderr, "Bad entry (%s%s%s%s%s) in netgroup \"%s\"\n",
+ grp->ng_str[NG_HOST] == NULL ? "" : grp->ng_str[NG_HOST],
+ grp->ng_str[NG_USER] == NULL ? "" : ",",
+ grp->ng_str[NG_USER] == NULL ? "" : grp->ng_str[NG_USER],
+ grp->ng_str[NG_DOM] == NULL ? "" : ",",
+ grp->ng_str[NG_DOM] == NULL ? "" : grp->ng_str[NG_DOM],
+ lp->l_groupname);
+#endif
+ } else {
+ spos = strsep(&pos, ", \t");
+ if (parse_netgrp(spos))
+ continue;
+ }
+ if (pos == NULL)
+ break;
+ while (*pos == ' ' || *pos == ',' || *pos == '\t')
+ pos++;
+ }
+ return (0);
+}
+
+/*
+ * Read the netgroup file and save lines until the line for the netgroup
+ * is found. Return 1 if eof is encountered.
+ */
+static struct linelist *
+read_for_group(const char *group)
+{
+ char *pos, *spos, *linep, *olinep;
+ int len, olen;
+ int cont;
+ struct linelist *lp;
+ char line[LINSIZ + 2];
+#ifdef YP
+ char *result;
+ int resultlen;
+
+ while (_netgr_yp_enabled || fgets(line, LINSIZ, netf) != NULL) {
+ if (_netgr_yp_enabled) {
+ if(!_netgr_yp_domain)
+ if(yp_get_default_domain(&_netgr_yp_domain))
+ continue;
+ if (yp_match(_netgr_yp_domain, "netgroup", group,
+ strlen(group), &result, &resultlen)) {
+ free(result);
+ if (_use_only_yp)
+ return ((struct linelist *)0);
+ else {
+ _netgr_yp_enabled = 0;
+ continue;
+ }
+ }
+ snprintf(line, LINSIZ, "%s %s", group, result);
+ free(result);
+ }
+#else
+ while (fgets(line, LINSIZ, netf) != NULL) {
+#endif
+ pos = (char *)&line;
+#ifdef YP
+ if (*pos == '+') {
+ _netgr_yp_enabled = 1;
+ continue;
+ }
+#endif
+ if (*pos == '#')
+ continue;
+ while (*pos == ' ' || *pos == '\t')
+ pos++;
+ spos = pos;
+ while (*pos != ' ' && *pos != '\t' && *pos != '\n' &&
+ *pos != '\0')
+ pos++;
+ len = pos - spos;
+ while (*pos == ' ' || *pos == '\t')
+ pos++;
+ if (*pos != '\n' && *pos != '\0') {
+ lp = (struct linelist *)malloc(sizeof (*lp));
+ lp->l_parsed = 0;
+ lp->l_groupname = (char *)malloc(len + 1);
+ bcopy(spos, lp->l_groupname, len);
+ *(lp->l_groupname + len) = '\0';
+ len = strlen(pos);
+ olen = 0;
+
+ /*
+ * Loop around handling line continuations.
+ */
+ do {
+ if (*(pos + len - 1) == '\n')
+ len--;
+ if (*(pos + len - 1) == '\\') {
+ len--;
+ cont = 1;
+ } else
+ cont = 0;
+ if (len > 0) {
+ linep = (char *)malloc(olen + len + 1);
+ if (olen > 0) {
+ bcopy(olinep, linep, olen);
+ free(olinep);
+ }
+ bcopy(pos, linep + olen, len);
+ olen += len;
+ *(linep + olen) = '\0';
+ olinep = linep;
+ }
+ if (cont) {
+ if (fgets(line, LINSIZ, netf)) {
+ pos = line;
+ len = strlen(pos);
+ } else
+ cont = 0;
+ }
+ } while (cont);
+ lp->l_line = linep;
+ lp->l_next = linehead;
+ linehead = lp;
+
+ /*
+ * If this is the one we wanted, we are done.
+ */
+ if (!strcmp(lp->l_groupname, group))
+ return (lp);
+ }
+ }
+#ifdef YP
+ /*
+ * Yucky. The recursive nature of this whole mess might require
+ * us to make more than one pass through the netgroup file.
+ * This might be best left outside the #ifdef YP, but YP is
+ * defined by default anyway, so I'll leave it like this
+ * until I know better.
+ */
+ rewind(netf);
+#endif
+ return ((struct linelist *)0);
+}
diff --git a/lib/libc/gen/getosreldate.3 b/lib/libc/gen/getosreldate.3
new file mode 100644
index 0000000..95f63b5
--- /dev/null
+++ b/lib/libc/gen/getosreldate.3
@@ -0,0 +1,86 @@
+.\" Copyright (c) 2002 The FreeBSD Project.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 30, 2008
+.Dt GETOSRELDATE 3
+.Os
+.Sh NAME
+.Nm getosreldate
+.Nd get the value of
+.Dv __FreeBSD_version
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn getosreldate void
+.Sh DESCRIPTION
+The
+.Fn getosreldate
+function returns an integer showing the version of the
+currently running
+.Fx
+kernel.
+Definitions of the values can be found in
+.%B "The Porter's Handbook"
+which is usually installed at
+.Pa /usr/share/doc/en_US.ISO8859-1/books/porters-handbook/ .
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn getosreldate
+returns the value requested;
+otherwise the value \-1 is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ENVIRONMENT
+.Bl -tag -width ".Ev OSVERSION"
+.It Ev OSVERSION
+If the environment variable
+.Ev OSVERSION
+is set, it will override the
+.Fn getosreldate
+return value.
+.El
+.Sh EXAMPLES
+An example can be found in
+.Pa /usr/share/examples/FreeBSD_version .
+.Sh ERRORS
+The
+.Fn getosreldate
+function may fail and set
+.Va errno
+for any of the errors specified for the library function
+.Xr sysctl 3 .
+.Sh SEE ALSO
+.Rs
+.%B "The Porter's Handbook"
+.%O /usr/share/doc/en_US.ISO8859-1/books/porters\-handbook/
+.Re
+.Sh HISTORY
+The
+.Fn getosreldate
+function appeared in
+.Fx 2.0 .
diff --git a/lib/libc/gen/getosreldate.c b/lib/libc/gen/getosreldate.c
new file mode 100644
index 0000000..b4bf545
--- /dev/null
+++ b/lib/libc/gen/getosreldate.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostid.c 8.1 (Berkeley) 6/2/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+getosreldate(void)
+{
+ int mib[2];
+ size_t size;
+ int value;
+ char *temp;
+
+ if ((temp = getenv("OSVERSION"))) {
+ value = atoi(temp);
+ return (value);
+ }
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_OSRELDATE;
+ size = sizeof value;
+ if (sysctl(mib, 2, &value, &size, NULL, 0) == -1)
+ return (-1);
+ return (value);
+}
diff --git a/lib/libc/gen/getpagesize.3 b/lib/libc/gen/getpagesize.3
new file mode 100644
index 0000000..8369a85
--- /dev/null
+++ b/lib/libc/gen/getpagesize.3
@@ -0,0 +1,61 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getpagesize.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt GETPAGESIZE 3
+.Os
+.Sh NAME
+.Nm getpagesize
+.Nd get system page size
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn getpagesize void
+.Sh DESCRIPTION
+The
+.Fn getpagesize
+function
+returns the number of bytes in a page.
+Page granularity is the granularity of many of the memory
+management calls.
+.Pp
+The page size is a system
+page size and may not be the same as the underlying
+hardware page size.
+.Sh SEE ALSO
+.Xr pagesize 1 ,
+.Xr sbrk 2
+.Sh HISTORY
+The
+.Fn getpagesize
+function appeared in
+.Bx 4.2 .
diff --git a/lib/libc/gen/getpagesize.c b/lib/libc/gen/getpagesize.c
new file mode 100644
index 0000000..f4b8128
--- /dev/null
+++ b/lib/libc/gen/getpagesize.c
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getpagesize.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <errno.h>
+#include <link.h>
+#include <unistd.h>
+
+#include "libc_private.h"
+
+/*
+ * This is unlikely to change over the running time of any
+ * program, so we cache the result to save some syscalls.
+ *
+ * NB: This function may be called from malloc(3) at initialization
+ * NB: so must not result in a malloc(3) related call!
+ */
+
+int
+getpagesize()
+{
+ int mib[2];
+ static int value;
+ size_t size;
+ int error;
+
+ if (value != 0)
+ return (value);
+
+ error = _elf_aux_info(AT_PAGESZ, &value, sizeof(value));
+ if (error == 0 && value != 0)
+ return (value);
+
+ mib[0] = CTL_HW;
+ mib[1] = HW_PAGESIZE;
+ size = sizeof value;
+ if (sysctl(mib, 2, &value, &size, NULL, 0) == -1)
+ return (-1);
+
+ return (value);
+}
diff --git a/lib/libc/gen/getpagesizes.3 b/lib/libc/gen/getpagesizes.3
new file mode 100644
index 0000000..854e2f7
--- /dev/null
+++ b/lib/libc/gen/getpagesizes.3
@@ -0,0 +1,99 @@
+.\" Copyright (c) 2009 Alan L. Cox <alc@cs.rice.edu>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 21, 2009
+.Dt GETPAGESIZES 3
+.Os
+.Sh NAME
+.Nm getpagesizes
+.Nd "get system page sizes"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/mman.h
+.Ft int
+.Fn getpagesizes "size_t pagesize[]" "int nelem"
+.Sh DESCRIPTION
+The
+.Fn getpagesizes
+function retrieves page size information from the system.
+When it is called with
+.Fa pagesize
+specified as
+.Dv NULL
+and
+.Fa nelem
+specified as 0, it returns the number of distinct page sizes that are
+supported by the system.
+Otherwise, it assigns up to
+.Fa nelem
+of the system-supported page sizes to consecutive elements of the
+array referenced by
+.Fa pagesize .
+These page sizes are expressed in bytes.
+In this case,
+.Fn getpagesizes
+returns the number of such page sizes that it assigned to the array.
+.Sh RETURN VALUES
+If successful, the
+.Fn getpagesizes
+function returns either the number of page sizes that are supported by
+the system or the number of supported page sizes that it assigned to
+the array referenced by
+.Fa pagesize .
+Otherwise, it returns the value\~\-1 and sets
+.Va errno
+to indicate the error.
+.Sh ERRORS
+The
+.Fn getpagesizes
+function will succeed unless:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa pagesize
+argument is
+.Dv NULL
+and the
+.Fa nelem
+argument is non-zero.
+.It Bq Er EINVAL
+The
+.Fa nelem
+argument is less than zero.
+.El
+.Sh SEE ALSO
+.Xr getpagesize 3
+.Sh HISTORY
+The
+.Fn getpagesizes
+function first appeared in Solaris 9.
+This manual page was written in conjunction with a new but compatible
+implementation that was first released in
+.Fx 7.3 .
+.Sh AUTHORS
+This manual page was written by
+.An Alan L. Cox Aq alc@cs.rice.edu .
diff --git a/lib/libc/gen/getpagesizes.c b/lib/libc/gen/getpagesizes.c
new file mode 100644
index 0000000..534fe9e
--- /dev/null
+++ b/lib/libc/gen/getpagesizes.c
@@ -0,0 +1,85 @@
+/*-
+ * Copyright (c) 2009 Alan L. Cox <alc@cs.rice.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/sysctl.h>
+
+#include <errno.h>
+#include <link.h>
+
+#include "libc_private.h"
+
+/*
+ * Retrieves page size information from the system. Specifically, returns the
+ * number of distinct page sizes that are supported by the system, if
+ * "pagesize" is NULL and "nelem" is 0. Otherwise, assigns up to "nelem" of
+ * the system-supported page sizes to consecutive elements of the array
+ * referenced by "pagesize", and returns the number of such page sizes that it
+ * assigned to the array. These page sizes are expressed in bytes.
+ *
+ * The implementation of this function does not directly or indirectly call
+ * malloc(3) or any other dynamic memory allocator that may itself call this
+ * function.
+ */
+int
+getpagesizes(size_t pagesize[], int nelem)
+{
+ static u_long ps[MAXPAGESIZES];
+ static int nops;
+ size_t size;
+ int error, i;
+
+ if (nelem < 0 || (nelem > 0 && pagesize == NULL)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ /* Cache the result of the sysctl(2). */
+ if (nops == 0) {
+ error = _elf_aux_info(AT_PAGESIZES, ps, sizeof(ps));
+ size = sizeof(ps);
+ if (error != 0 || ps[0] == 0) {
+ if (sysctlbyname("hw.pagesizes", ps, &size, NULL, 0)
+ == -1)
+ return (-1);
+ }
+ /* Count the number of page sizes that are supported. */
+ nops = size / sizeof(ps[0]);
+ while (nops > 0 && ps[nops - 1] == 0)
+ nops--;
+ }
+ if (pagesize == NULL)
+ return (nops);
+ /* Return up to "nelem" page sizes from the cached result. */
+ if (nelem > nops)
+ nelem = nops;
+ for (i = 0; i < nelem; i++)
+ pagesize[i] = ps[i];
+ return (nelem);
+}
diff --git a/lib/libc/gen/getpass.3 b/lib/libc/gen/getpass.3
new file mode 100644
index 0000000..85dcdce
--- /dev/null
+++ b/lib/libc/gen/getpass.3
@@ -0,0 +1,93 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getpass.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt GETPASS 3
+.Os
+.Sh NAME
+.Nm getpass
+.Nd get a password
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In pwd.h
+.In unistd.h
+.Ft char *
+.Fn getpass "const char *prompt"
+.Sh DESCRIPTION
+The
+.Fn getpass
+function displays a prompt to, and reads in a password from,
+.Pa /dev/tty .
+If this file is not accessible,
+.Fn getpass
+displays the prompt on the standard error output and reads from the standard
+input.
+.Pp
+The password may be up to _PASSWORD_LEN (currently 128)
+characters in length.
+Any additional
+characters and the terminating newline character are discarded.
+.Pp
+The
+.Fn getpass
+function turns off character echoing while reading the password.
+.Sh RETURN VALUES
+The
+.Fn getpass
+function returns a pointer to the null terminated password.
+.Sh FILES
+.Bl -tag -width /dev/tty -compact
+.It Pa /dev/tty
+.El
+.Sh SEE ALSO
+.Xr crypt 3 ,
+.Xr readpassphrase 3
+.Sh HISTORY
+A
+.Fn getpass
+function appeared in
+.At v7 .
+.Sh BUGS
+The
+.Fn getpass
+function leaves its result in an internal static object and returns
+a pointer to that object.
+Subsequent calls to
+.Fn getpass
+will modify the same object.
+.Pp
+The calling process should zero the password as soon as possible to
+avoid leaving the cleartext password visible in the process's address
+space.
+.Pp
+Upon receipt of a SIGTSTP, the input buffer will be flushed, so any
+partially typed password must be retyped when the process
+continues.
diff --git a/lib/libc/gen/getpeereid.3 b/lib/libc/gen/getpeereid.3
new file mode 100644
index 0000000..12999e5
--- /dev/null
+++ b/lib/libc/gen/getpeereid.3
@@ -0,0 +1,137 @@
+.\"
+.\" Copyright (c) 2001 Dima Dorfman.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 15, 2001
+.Dt GETPEEREID 3
+.Os
+.Sh NAME
+.Nm getpeereid
+.Nd get the effective credentials of a UNIX-domain peer
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In unistd.h
+.Ft int
+.Fn getpeereid "int s" "uid_t *euid" "gid_t *egid"
+.Sh DESCRIPTION
+The
+.Fn getpeereid
+function returns the effective user and group IDs of the
+peer connected to a
+.Ux Ns -domain
+socket.
+The argument
+.Fa s
+must be a
+.Ux Ns -domain
+socket
+.Pq Xr unix 4
+of type
+.Dv SOCK_STREAM
+on which either
+.Xr connect 2
+or
+.Xr listen 2
+have been called.
+The effective used ID is placed in
+.Fa euid ,
+and the effective group ID in
+.Fa egid .
+.Pp
+The credentials returned to the
+.Xr listen 2
+caller are those of its peer at the time it called
+.Xr connect 2 ;
+the credentials returned to the
+.Xr connect 2
+caller are those of its peer at the time it called
+.Xr listen 2 .
+This mechanism is reliable; there is no way for either side to influence
+the credentials returned to its peer except by calling the appropriate
+system call (i.e., either
+.Xr connect 2
+or
+.Xr listen 2 )
+under different effective credentials.
+.Pp
+One common use of this routine is for a
+.Ux Ns -domain
+server
+to verify the credentials of its client.
+Likewise, the client can verify the credentials of the server.
+.Sh IMPLEMENTATION NOTES
+On
+.Fx ,
+.Fn getpeereid
+is implemented in terms of the
+.Dv LOCAL_PEERCRED
+.Xr unix 4
+socket option.
+.Sh RETURN VALUES
+.Rv -std getpeereid
+.Sh ERRORS
+The
+.Fn getpeereid
+function
+fails if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The argument
+.Fa s
+is not a valid descriptor.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is a file, not a socket.
+.It Bq Er ENOTCONN
+The argument
+.Fa s
+does not refer to a socket on which
+.Xr connect 2
+or
+.Xr listen 2
+have been called.
+.It Bq Er EINVAL
+The argument
+.Fa s
+does not refer to a socket of type
+.Dv SOCK_STREAM ,
+or the kernel returned invalid data.
+.El
+.Sh SEE ALSO
+.Xr connect 2 ,
+.Xr getpeername 2 ,
+.Xr getsockname 2 ,
+.Xr getsockopt 2 ,
+.Xr listen 2 ,
+.Xr unix 4
+.Sh HISTORY
+The
+.Fn getpeereid
+function appeared in
+.Fx 4.6 .
diff --git a/lib/libc/gen/getpeereid.c b/lib/libc/gen/getpeereid.c
new file mode 100644
index 0000000..5ecb243
--- /dev/null
+++ b/lib/libc/gen/getpeereid.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2001 Dima Dorfman.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/ucred.h>
+#include <sys/un.h>
+
+#include <errno.h>
+#include <unistd.h>
+
+int
+getpeereid(int s, uid_t *euid, gid_t *egid)
+{
+ struct xucred xuc;
+ socklen_t xuclen;
+ int error;
+
+ xuclen = sizeof(xuc);
+ error = getsockopt(s, 0, LOCAL_PEERCRED, &xuc, &xuclen);
+ if (error != 0)
+ return (error);
+ if (xuc.cr_version != XUCRED_VERSION)
+ return (EINVAL);
+ *euid = xuc.cr_uid;
+ *egid = xuc.cr_gid;
+ return (0);
+}
diff --git a/lib/libc/gen/getprogname.3 b/lib/libc/gen/getprogname.3
new file mode 100644
index 0000000..53d39a6
--- /dev/null
+++ b/lib/libc/gen/getprogname.3
@@ -0,0 +1,94 @@
+.\"
+.\" Copyright (c) 2001 Christopher G. Demetriou
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed for the
+.\" NetBSD Project. See http://www.netbsd.org/ for
+.\" information about NetBSD.
+.\" 4. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd May 1, 2001
+.Dt GETPROGNAME 3
+.Os
+.Sh NAME
+.Nm getprogname ,
+.Nm setprogname
+.Nd get or set the program name
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft const char *
+.Fn getprogname "void"
+.Ft void
+.Fn setprogname "const char *progname"
+.Sh DESCRIPTION
+The
+.Fn getprogname
+and
+.Fn setprogname
+functions manipulate the name of the current program.
+They are used by error-reporting routines to produce
+consistent output.
+.Pp
+The
+.Fn getprogname
+function returns the name of the program.
+If the name has not been set yet, it will return
+.Dv NULL .
+.Pp
+The
+.Fn setprogname
+function sets the name of the program to be the last component of the
+.Fa progname
+argument.
+Since a pointer to the given string is kept as the program name,
+it should not be modified for the rest of the program's lifetime.
+.Pp
+In
+.Fx ,
+the name of the program is set by the start-up code that is run before
+.Fn main ;
+thus,
+running
+.Fn setprogname
+is not necessary.
+Programs that desire maximum portability should still call it;
+on another operating system,
+these functions may be implemented in a portability library.
+Calling
+.Fn setprogname
+allows the aforementioned library to learn the program name without
+modifications to the start-up code.
+.Sh SEE ALSO
+.Xr err 3 ,
+.Xr setproctitle 3
+.Sh HISTORY
+These functions first appeared in
+.Nx 1.6 ,
+and made their way into
+.Fx 4.4 .
diff --git a/lib/libc/gen/getprogname.c b/lib/libc/gen/getprogname.c
new file mode 100644
index 0000000..fd51d13
--- /dev/null
+++ b/lib/libc/gen/getprogname.c
@@ -0,0 +1,17 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdlib.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+__weak_reference(_getprogname, getprogname);
+
+const char *
+_getprogname(void)
+{
+
+ return (__progname);
+}
diff --git a/lib/libc/gen/getpwent.3 b/lib/libc/gen/getpwent.3
new file mode 100644
index 0000000..65092ab
--- /dev/null
+++ b/lib/libc/gen/getpwent.3
@@ -0,0 +1,315 @@
+.\" Copyright (c) 1988, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)getpwent.3 8.2 (Berkeley) 12/11/93
+.\" $FreeBSD$
+.\"
+.Dd April 16, 2003
+.Dt GETPWENT 3
+.Os
+.Sh NAME
+.Nm getpwent ,
+.Nm getpwent_r ,
+.Nm getpwnam ,
+.Nm getpwnam_r ,
+.Nm getpwuid ,
+.Nm getpwuid_r ,
+.Nm setpassent ,
+.Nm setpwent ,
+.Nm endpwent
+.Nd password database operations
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In pwd.h
+.Ft struct passwd *
+.Fn getpwent void
+.Ft int
+.Fn getpwent_r "struct passwd *pwd" "char *buffer" "size_t bufsize" "struct passwd **result"
+.Ft struct passwd *
+.Fn getpwnam "const char *login"
+.Ft int
+.Fn getpwnam_r "const char *name" "struct passwd *pwd" "char *buffer" "size_t bufsize" "struct passwd **result"
+.Ft struct passwd *
+.Fn getpwuid "uid_t uid"
+.Ft int
+.Fn getpwuid_r "uid_t uid" "struct passwd *pwd" "char *buffer" "size_t bufsize" "struct passwd **result"
+.Ft int
+.Fn setpassent "int stayopen"
+.Ft void
+.Fn setpwent void
+.Ft void
+.Fn endpwent void
+.Sh DESCRIPTION
+These functions
+operate on the password database file
+which is described
+in
+.Xr passwd 5 .
+Each entry in the database is defined by the structure
+.Vt passwd
+found in the include
+file
+.In pwd.h :
+.Bd -literal -offset indent
+struct passwd {
+ char *pw_name; /* user name */
+ char *pw_passwd; /* encrypted password */
+ uid_t pw_uid; /* user uid */
+ gid_t pw_gid; /* user gid */
+ time_t pw_change; /* password change time */
+ char *pw_class; /* user access class */
+ char *pw_gecos; /* Honeywell login info */
+ char *pw_dir; /* home directory */
+ char *pw_shell; /* default shell */
+ time_t pw_expire; /* account expiration */
+ int pw_fields; /* internal: fields filled in */
+};
+.Ed
+.Pp
+The functions
+.Fn getpwnam
+and
+.Fn getpwuid
+search the password database for the given login name or user uid,
+respectively, always returning the first one encountered.
+.Pp
+The
+.Fn getpwent
+function
+sequentially reads the password database and is intended for programs
+that wish to process the complete list of users.
+.Pp
+The functions
+.Fn getpwent_r ,
+.Fn getpwnam_r ,
+and
+.Fn getpwuid_r
+are thread-safe versions of
+.Fn getpwent ,
+.Fn getpwnam ,
+and
+.Fn getpwuid ,
+respectively.
+The caller must provide storage for the results of the search in
+the
+.Fa pwd ,
+.Fa buffer ,
+.Fa bufsize ,
+and
+.Fa result
+arguments.
+When these functions are successful, the
+.Fa pwd
+argument will be filled-in, and a pointer to that argument will be
+stored in
+.Fa result .
+If an entry is not found or an error occurs,
+.Fa result
+will be set to
+.Dv NULL .
+.Pp
+The
+.Fn setpassent
+function
+accomplishes two purposes.
+First, it causes
+.Fn getpwent
+to ``rewind'' to the beginning of the database.
+Additionally, if
+.Fa stayopen
+is non-zero, file descriptors are left open, significantly speeding
+up subsequent accesses for all of the routines.
+(This latter functionality is unnecessary for
+.Fn getpwent
+as it does not close its file descriptors by default.)
+.Pp
+It is dangerous for long-running programs to keep the file descriptors
+open as the database will become out of date if it is updated while the
+program is running.
+.Pp
+The
+.Fn setpwent
+function
+is identical to
+.Fn setpassent
+with an argument of zero.
+.Pp
+The
+.Fn endpwent
+function
+closes any open files.
+.Pp
+These routines have been written to ``shadow'' the password file, e.g.\&
+allow only certain programs to have access to the encrypted password.
+If the process which calls them has an effective uid of 0, the encrypted
+password will be returned, otherwise, the password field of the returned
+structure will point to the string
+.Ql * .
+.Sh RETURN VALUES
+The functions
+.Fn getpwent ,
+.Fn getpwnam ,
+and
+.Fn getpwuid
+return a valid pointer to a passwd structure on success
+or
+.Dv NULL
+if the entry is not found or if an error occurs.
+If an error does occur,
+.Va errno
+will be set.
+Note that programs must explicitly set
+.Va errno
+to zero before calling any of these functions if they need to
+distinguish between a non-existent entry and an error.
+The functions
+.Fn getpwent_r ,
+.Fn getpwnam_r ,
+and
+.Fn getpwuid_r
+return 0 if no error occurred, or an error number to indicate failure.
+It is not an error if a matching entry is not found.
+(Thus, if
+.Fa result
+is
+.Dv NULL
+and the return value is 0, no matching entry exists.)
+.Pp
+The
+.Fn setpassent
+function returns 0 on failure and 1 on success.
+The
+.Fn endpwent
+and
+.Fn setpwent
+functions
+have no return value.
+.Sh FILES
+.Bl -tag -width /etc/master.passwd -compact
+.It Pa /etc/pwd.db
+The insecure password database file
+.It Pa /etc/spwd.db
+The secure password database file
+.It Pa /etc/master.passwd
+The current password file
+.It Pa /etc/passwd
+A Version 7 format password file
+.El
+.Sh COMPATIBILITY
+The historic function
+.Xr setpwfile 3 ,
+which allowed the specification of alternate password databases,
+has been deprecated and is no longer available.
+.Sh ERRORS
+These routines may fail for any of the errors specified in
+.Xr open 2 ,
+.Xr dbopen 3 ,
+.Xr socket 2 ,
+and
+.Xr connect 2 ,
+in addition to the following:
+.Bl -tag -width Er
+.It Bq Er ERANGE
+The buffer specified by the
+.Fa buffer
+and
+.Fa bufsize
+arguments was insufficiently sized to store the result.
+The caller should retry with a larger buffer.
+.El
+.Sh SEE ALSO
+.Xr getlogin 2 ,
+.Xr getgrent 3 ,
+.Xr nsswitch.conf 5 ,
+.Xr passwd 5 ,
+.Xr pwd_mkdb 8 ,
+.Xr vipw 8 ,
+.Xr yp 8
+.Sh STANDARDS
+The
+.Fn getpwent ,
+.Fn getpwnam ,
+.Fn getpwnam_r ,
+.Fn getpwuid ,
+.Fn getpwuid_r ,
+.Fn setpwent ,
+and
+.Fn endpwent
+functions conform to
+.St -p1003.1-96 .
+.Sh HISTORY
+The
+.Fn getpwent ,
+.Fn getpwnam ,
+.Fn getpwuid ,
+.Fn setpwent ,
+and
+.Fn endpwent
+functions appeared in
+.At v7 .
+The
+.Fn setpassent
+function appeared in
+.Bx 4.3 Reno .
+The
+.Fn getpwent_r ,
+.Fn getpwnam_r ,
+and
+.Fn getpwuid_r
+functions appeared in
+.Fx 5.1 .
+.Sh BUGS
+The functions
+.Fn getpwent ,
+.Fn getpwnam ,
+and
+.Fn getpwuid ,
+leave their results in an internal static object and return
+a pointer to that object.
+Subsequent calls to
+the same function
+will modify the same object.
+.Pp
+The functions
+.Fn getpwent ,
+.Fn getpwent_r ,
+.Fn endpwent ,
+.Fn setpassent ,
+and
+.Fn setpwent
+are fairly useless in a networked environment and should be
+avoided, if possible.
+The
+.Fn getpwent
+and
+.Fn getpwent_r
+functions
+make no attempt to suppress duplicate information if multiple
+sources are specified in
+.Xr nsswitch.conf 5 .
diff --git a/lib/libc/gen/getpwent.c b/lib/libc/gen/getpwent.c
new file mode 100644
index 0000000..f729cdf
--- /dev/null
+++ b/lib/libc/gen/getpwent.c
@@ -0,0 +1,2009 @@
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <arpa/inet.h>
+#include <errno.h>
+#include <fcntl.h>
+#ifdef HESIOD
+#include <hesiod.h>
+#endif
+#include <netdb.h>
+#include <nsswitch.h>
+#include <pthread.h>
+#include <pthread_np.h>
+#include <pwd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include <db.h>
+#include "libc_private.h"
+#include "pw_scan.h"
+#include "nss_tls.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+
+#ifndef CTASSERT
+#define CTASSERT(x) _CTASSERT(x, __LINE__)
+#define _CTASSERT(x, y) __CTASSERT(x, y)
+#define __CTASSERT(x, y) typedef char __assert_ ## y [(x) ? 1 : -1]
+#endif
+
+/* Counter as stored in /etc/pwd.db */
+typedef int pwkeynum;
+
+CTASSERT(MAXLOGNAME > sizeof(uid_t));
+CTASSERT(MAXLOGNAME > sizeof(pwkeynum));
+
+enum constants {
+ PWD_STORAGE_INITIAL = 1 << 10, /* 1 KByte */
+ PWD_STORAGE_MAX = 1 << 20, /* 1 MByte */
+ SETPWENT = 1,
+ ENDPWENT = 2,
+ HESIOD_NAME_MAX = 256
+};
+
+static const ns_src defaultsrc[] = {
+ { NSSRC_COMPAT, NS_SUCCESS },
+ { NULL, 0 }
+};
+
+int __pw_match_entry(const char *, size_t, enum nss_lookup_type,
+ const char *, uid_t);
+int __pw_parse_entry(char *, size_t, struct passwd *, int, int *errnop);
+
+static void pwd_init(struct passwd *);
+
+union key {
+ const char *name;
+ uid_t uid;
+};
+
+static struct passwd *getpw(int (*fn)(union key, struct passwd *, char *,
+ size_t, struct passwd **), union key);
+static int wrap_getpwnam_r(union key, struct passwd *, char *,
+ size_t, struct passwd **);
+static int wrap_getpwuid_r(union key, struct passwd *, char *, size_t,
+ struct passwd **);
+static int wrap_getpwent_r(union key, struct passwd *, char *, size_t,
+ struct passwd **);
+
+static int pwdb_match_entry_v3(char *, size_t, enum nss_lookup_type,
+ const char *, uid_t);
+static int pwdb_parse_entry_v3(char *, size_t, struct passwd *, int *);
+static int pwdb_match_entry_v4(char *, size_t, enum nss_lookup_type,
+ const char *, uid_t);
+static int pwdb_parse_entry_v4(char *, size_t, struct passwd *, int *);
+
+
+struct {
+ int (*match)(char *, size_t, enum nss_lookup_type, const char *,
+ uid_t);
+ int (*parse)(char *, size_t, struct passwd *, int *);
+} pwdb_versions[] = {
+ { NULL, NULL }, /* version 0 */
+ { NULL, NULL }, /* version 1 */
+ { NULL, NULL }, /* version 2 */
+ { pwdb_match_entry_v3, pwdb_parse_entry_v3 }, /* version 3 */
+ { pwdb_match_entry_v4, pwdb_parse_entry_v4 }, /* version 4 */
+};
+
+
+struct files_state {
+ DB *db;
+ pwkeynum keynum;
+ int stayopen;
+ int version;
+};
+static void files_endstate(void *);
+NSS_TLS_HANDLING(files);
+static DB *pwdbopen(int *);
+static void files_endstate(void *);
+static int files_setpwent(void *, void *, va_list);
+static int files_passwd(void *, void *, va_list);
+
+
+#ifdef HESIOD
+struct dns_state {
+ long counter;
+};
+static void dns_endstate(void *);
+NSS_TLS_HANDLING(dns);
+static int dns_setpwent(void *, void *, va_list);
+static int dns_passwd(void *, void *, va_list);
+#endif
+
+
+#ifdef YP
+struct nis_state {
+ char domain[MAXHOSTNAMELEN];
+ int done;
+ char *key;
+ int keylen;
+};
+static void nis_endstate(void *);
+NSS_TLS_HANDLING(nis);
+static int nis_setpwent(void *, void *, va_list);
+static int nis_passwd(void *, void *, va_list);
+static int nis_map(char *, enum nss_lookup_type, char *, size_t, int *);
+static int nis_adjunct(char *, const char *, char *, size_t);
+#endif
+
+
+struct compat_state {
+ DB *db;
+ pwkeynum keynum;
+ int stayopen;
+ int version;
+ DB *exclude;
+ struct passwd template;
+ char *name;
+ enum _compat {
+ COMPAT_MODE_OFF = 0,
+ COMPAT_MODE_ALL,
+ COMPAT_MODE_NAME,
+ COMPAT_MODE_NETGROUP
+ } compat;
+};
+static void compat_endstate(void *);
+NSS_TLS_HANDLING(compat);
+static int compat_setpwent(void *, void *, va_list);
+static int compat_passwd(void *, void *, va_list);
+static void compat_clear_template(struct passwd *);
+static int compat_set_template(struct passwd *, struct passwd *);
+static int compat_use_template(struct passwd *, struct passwd *, char *,
+ size_t);
+static int compat_redispatch(struct compat_state *, enum nss_lookup_type,
+ enum nss_lookup_type, const char *, const char *, uid_t,
+ struct passwd *, char *, size_t, int *);
+
+#ifdef NS_CACHING
+static int pwd_id_func(char *, size_t *, va_list ap, void *);
+static int pwd_marshal_func(char *, size_t *, void *, va_list, void *);
+static int pwd_unmarshal_func(char *, size_t, void *, va_list, void *);
+
+static int
+pwd_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
+{
+ char *name;
+ uid_t uid;
+ size_t size, desired_size;
+ int res = NS_UNAVAIL;
+ enum nss_lookup_type lookup_type;
+
+ lookup_type = (enum nss_lookup_type)cache_mdata;
+ switch (lookup_type) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ size = strlen(name);
+ desired_size = sizeof(enum nss_lookup_type) + size + 1;
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
+
+ res = NS_SUCCESS;
+ break;
+ case nss_lt_id:
+ uid = va_arg(ap, uid_t);
+ desired_size = sizeof(enum nss_lookup_type) + sizeof(uid_t);
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), &uid,
+ sizeof(uid_t));
+
+ res = NS_SUCCESS;
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+fin:
+ *buffer_size = desired_size;
+ return (res);
+}
+
+static int
+pwd_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ uid_t uid;
+ struct passwd *pwd;
+ char *orig_buf;
+ size_t orig_buf_size;
+
+ struct passwd new_pwd;
+ size_t desired_size, size;
+ char *p;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ uid = va_arg(ap, uid_t);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ pwd = va_arg(ap, struct passwd *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+
+ desired_size = sizeof(struct passwd) + sizeof(char *) +
+ strlen(pwd->pw_name) + 1;
+ if (pwd->pw_passwd != NULL)
+ desired_size += strlen(pwd->pw_passwd) + 1;
+ if (pwd->pw_class != NULL)
+ desired_size += strlen(pwd->pw_class) + 1;
+ if (pwd->pw_gecos != NULL)
+ desired_size += strlen(pwd->pw_gecos) + 1;
+ if (pwd->pw_dir != NULL)
+ desired_size += strlen(pwd->pw_dir) + 1;
+ if (pwd->pw_shell != NULL)
+ desired_size += strlen(pwd->pw_shell) + 1;
+
+ if (*buffer_size < desired_size) {
+ /* this assignment is here for future use */
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ memcpy(&new_pwd, pwd, sizeof(struct passwd));
+ memset(buffer, 0, desired_size);
+
+ *buffer_size = desired_size;
+ p = buffer + sizeof(struct passwd) + sizeof(char *);
+ memcpy(buffer + sizeof(struct passwd), &p, sizeof(char *));
+
+ if (new_pwd.pw_name != NULL) {
+ size = strlen(new_pwd.pw_name);
+ memcpy(p, new_pwd.pw_name, size);
+ new_pwd.pw_name = p;
+ p += size + 1;
+ }
+
+ if (new_pwd.pw_passwd != NULL) {
+ size = strlen(new_pwd.pw_passwd);
+ memcpy(p, new_pwd.pw_passwd, size);
+ new_pwd.pw_passwd = p;
+ p += size + 1;
+ }
+
+ if (new_pwd.pw_class != NULL) {
+ size = strlen(new_pwd.pw_class);
+ memcpy(p, new_pwd.pw_class, size);
+ new_pwd.pw_class = p;
+ p += size + 1;
+ }
+
+ if (new_pwd.pw_gecos != NULL) {
+ size = strlen(new_pwd.pw_gecos);
+ memcpy(p, new_pwd.pw_gecos, size);
+ new_pwd.pw_gecos = p;
+ p += size + 1;
+ }
+
+ if (new_pwd.pw_dir != NULL) {
+ size = strlen(new_pwd.pw_dir);
+ memcpy(p, new_pwd.pw_dir, size);
+ new_pwd.pw_dir = p;
+ p += size + 1;
+ }
+
+ if (new_pwd.pw_shell != NULL) {
+ size = strlen(new_pwd.pw_shell);
+ memcpy(p, new_pwd.pw_shell, size);
+ new_pwd.pw_shell = p;
+ p += size + 1;
+ }
+
+ memcpy(buffer, &new_pwd, sizeof(struct passwd));
+ return (NS_SUCCESS);
+}
+
+static int
+pwd_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ uid_t uid;
+ struct passwd *pwd;
+ char *orig_buf;
+ size_t orig_buf_size;
+ int *ret_errno;
+
+ char *p;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ uid = va_arg(ap, uid_t);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ pwd = va_arg(ap, struct passwd *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+ ret_errno = va_arg(ap, int *);
+
+ if (orig_buf_size <
+ buffer_size - sizeof(struct passwd) - sizeof(char *)) {
+ *ret_errno = ERANGE;
+ return (NS_RETURN);
+ }
+
+ memcpy(pwd, buffer, sizeof(struct passwd));
+ memcpy(&p, buffer + sizeof(struct passwd), sizeof(char *));
+ memcpy(orig_buf, buffer + sizeof(struct passwd) + sizeof(char *),
+ buffer_size - sizeof(struct passwd) - sizeof(char *));
+
+ NS_APPLY_OFFSET(pwd->pw_name, orig_buf, p, char *);
+ NS_APPLY_OFFSET(pwd->pw_passwd, orig_buf, p, char *);
+ NS_APPLY_OFFSET(pwd->pw_class, orig_buf, p, char *);
+ NS_APPLY_OFFSET(pwd->pw_gecos, orig_buf, p, char *);
+ NS_APPLY_OFFSET(pwd->pw_dir, orig_buf, p, char *);
+ NS_APPLY_OFFSET(pwd->pw_shell, orig_buf, p, char *);
+
+ if (retval != NULL)
+ *((struct passwd **)retval) = pwd;
+
+ return (NS_SUCCESS);
+}
+
+NSS_MP_CACHE_HANDLING(passwd);
+#endif /* NS_CACHING */
+
+void
+setpwent(void)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ passwd, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_setpwent, (void *)SETPWENT },
+#ifdef HESIOD
+ { NSSRC_DNS, dns_setpwent, (void *)SETPWENT },
+#endif
+#ifdef YP
+ { NSSRC_NIS, nis_setpwent, (void *)SETPWENT },
+#endif
+ { NSSRC_COMPAT, compat_setpwent, (void *)SETPWENT },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ (void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "setpwent", defaultsrc, 0);
+}
+
+
+int
+setpassent(int stayopen)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ passwd, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_setpwent, (void *)SETPWENT },
+#ifdef HESIOD
+ { NSSRC_DNS, dns_setpwent, (void *)SETPWENT },
+#endif
+#ifdef YP
+ { NSSRC_NIS, nis_setpwent, (void *)SETPWENT },
+#endif
+ { NSSRC_COMPAT, compat_setpwent, (void *)SETPWENT },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ (void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "setpwent", defaultsrc,
+ stayopen);
+ return (1);
+}
+
+
+void
+endpwent(void)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ passwd, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_setpwent, (void *)ENDPWENT },
+#ifdef HESIOD
+ { NSSRC_DNS, dns_setpwent, (void *)ENDPWENT },
+#endif
+#ifdef YP
+ { NSSRC_NIS, nis_setpwent, (void *)ENDPWENT },
+#endif
+ { NSSRC_COMPAT, compat_setpwent, (void *)ENDPWENT },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ (void)_nsdispatch(NULL, dtab, NSDB_PASSWD, "endpwent", defaultsrc);
+}
+
+
+int
+getpwent_r(struct passwd *pwd, char *buffer, size_t bufsize,
+ struct passwd **result)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ passwd, (void *)nss_lt_all,
+ pwd_marshal_func, pwd_unmarshal_func);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_passwd, (void *)nss_lt_all },
+#ifdef HESIOD
+ { NSSRC_DNS, dns_passwd, (void *)nss_lt_all },
+#endif
+#ifdef YP
+ { NSSRC_NIS, nis_passwd, (void *)nss_lt_all },
+#endif
+ { NSSRC_COMPAT, compat_passwd, (void *)nss_lt_all },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ pwd_init(pwd);
+ ret_errno = 0;
+ *result = NULL;
+ rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwent_r", defaultsrc,
+ pwd, buffer, bufsize, &ret_errno);
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+
+int
+getpwnam_r(const char *name, struct passwd *pwd, char *buffer, size_t bufsize,
+ struct passwd **result)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ passwd, (void *)nss_lt_name,
+ pwd_id_func, pwd_marshal_func, pwd_unmarshal_func);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_passwd, (void *)nss_lt_name },
+#ifdef HESIOD
+ { NSSRC_DNS, dns_passwd, (void *)nss_lt_name },
+#endif
+#ifdef YP
+ { NSSRC_NIS, nis_passwd, (void *)nss_lt_name },
+#endif
+ { NSSRC_COMPAT, compat_passwd, (void *)nss_lt_name },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ pwd_init(pwd);
+ ret_errno = 0;
+ *result = NULL;
+ rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwnam_r", defaultsrc,
+ name, pwd, buffer, bufsize, &ret_errno);
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+
+int
+getpwuid_r(uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize,
+ struct passwd **result)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ passwd, (void *)nss_lt_id,
+ pwd_id_func, pwd_marshal_func, pwd_unmarshal_func);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_passwd, (void *)nss_lt_id },
+#ifdef HESIOD
+ { NSSRC_DNS, dns_passwd, (void *)nss_lt_id },
+#endif
+#ifdef YP
+ { NSSRC_NIS, nis_passwd, (void *)nss_lt_id },
+#endif
+ { NSSRC_COMPAT, compat_passwd, (void *)nss_lt_id },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ pwd_init(pwd);
+ ret_errno = 0;
+ *result = NULL;
+ rv = _nsdispatch(result, dtab, NSDB_PASSWD, "getpwuid_r", defaultsrc,
+ uid, pwd, buffer, bufsize, &ret_errno);
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+
+static void
+pwd_init(struct passwd *pwd)
+{
+ static char nul[] = "";
+
+ memset(pwd, 0, sizeof(*pwd));
+ pwd->pw_uid = (uid_t)-1; /* Considered least likely to lead to */
+ pwd->pw_gid = (gid_t)-1; /* a security issue. */
+ pwd->pw_name = nul;
+ pwd->pw_passwd = nul;
+ pwd->pw_class = nul;
+ pwd->pw_gecos = nul;
+ pwd->pw_dir = nul;
+ pwd->pw_shell = nul;
+}
+
+
+static struct passwd pwd;
+static char *pwd_storage;
+static size_t pwd_storage_size;
+
+
+static struct passwd *
+getpw(int (*fn)(union key, struct passwd *, char *, size_t, struct passwd **),
+ union key key)
+{
+ int rv;
+ struct passwd *res;
+
+ if (pwd_storage == NULL) {
+ pwd_storage = malloc(PWD_STORAGE_INITIAL);
+ if (pwd_storage == NULL)
+ return (NULL);
+ pwd_storage_size = PWD_STORAGE_INITIAL;
+ }
+ do {
+ rv = fn(key, &pwd, pwd_storage, pwd_storage_size, &res);
+ if (res == NULL && rv == ERANGE) {
+ free(pwd_storage);
+ if ((pwd_storage_size << 1) > PWD_STORAGE_MAX) {
+ pwd_storage = NULL;
+ errno = ERANGE;
+ return (NULL);
+ }
+ pwd_storage_size <<= 1;
+ pwd_storage = malloc(pwd_storage_size);
+ if (pwd_storage == NULL)
+ return (NULL);
+ }
+ } while (res == NULL && rv == ERANGE);
+ if (rv != 0)
+ errno = rv;
+ return (res);
+}
+
+
+static int
+wrap_getpwnam_r(union key key, struct passwd *pwd, char *buffer,
+ size_t bufsize, struct passwd **res)
+{
+ return (getpwnam_r(key.name, pwd, buffer, bufsize, res));
+}
+
+
+static int
+wrap_getpwuid_r(union key key, struct passwd *pwd, char *buffer,
+ size_t bufsize, struct passwd **res)
+{
+ return (getpwuid_r(key.uid, pwd, buffer, bufsize, res));
+}
+
+
+static int
+wrap_getpwent_r(union key key __unused, struct passwd *pwd, char *buffer,
+ size_t bufsize, struct passwd **res)
+{
+ return (getpwent_r(pwd, buffer, bufsize, res));
+}
+
+
+struct passwd *
+getpwnam(const char *name)
+{
+ union key key;
+
+ key.name = name;
+ return (getpw(wrap_getpwnam_r, key));
+}
+
+
+struct passwd *
+getpwuid(uid_t uid)
+{
+ union key key;
+
+ key.uid = uid;
+ return (getpw(wrap_getpwuid_r, key));
+}
+
+
+struct passwd *
+getpwent(void)
+{
+ union key key;
+
+ key.uid = 0; /* not used */
+ return (getpw(wrap_getpwent_r, key));
+}
+
+
+/*
+ * files backend
+ */
+static DB *
+pwdbopen(int *version)
+{
+ DB *res;
+ DBT key, entry;
+ int rv;
+
+ if (geteuid() != 0 ||
+ (res = dbopen(_PATH_SMP_DB, O_RDONLY, 0, DB_HASH, NULL)) == NULL)
+ res = dbopen(_PATH_MP_DB, O_RDONLY, 0, DB_HASH, NULL);
+ if (res == NULL)
+ return (NULL);
+ key.data = _PWD_VERSION_KEY;
+ key.size = strlen(_PWD_VERSION_KEY);
+ rv = res->get(res, &key, &entry, 0);
+ if (rv == 0)
+ *version = *(unsigned char *)entry.data;
+ else
+ *version = 3;
+ if (*version < 3 ||
+ *version >= sizeof(pwdb_versions)/sizeof(pwdb_versions[0])) {
+ syslog(LOG_CRIT, "Unsupported password database version %d",
+ *version);
+ res->close(res);
+ res = NULL;
+ }
+ return (res);
+}
+
+
+static void
+files_endstate(void *p)
+{
+ DB *db;
+
+ if (p == NULL)
+ return;
+ db = ((struct files_state *)p)->db;
+ if (db != NULL)
+ db->close(db);
+ free(p);
+}
+
+
+static int
+files_setpwent(void *retval, void *mdata, va_list ap)
+{
+ struct files_state *st;
+ int rv, stayopen;
+
+ rv = files_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+ switch ((enum constants)mdata) {
+ case SETPWENT:
+ stayopen = va_arg(ap, int);
+ st->keynum = 0;
+ if (stayopen)
+ st->db = pwdbopen(&st->version);
+ st->stayopen = stayopen;
+ break;
+ case ENDPWENT:
+ if (st->db != NULL) {
+ (void)st->db->close(st->db);
+ st->db = NULL;
+ }
+ break;
+ default:
+ break;
+ }
+ return (NS_UNAVAIL);
+}
+
+
+static int
+files_passwd(void *retval, void *mdata, va_list ap)
+{
+ char keybuf[MAXLOGNAME + 1];
+ DBT key, entry;
+ struct files_state *st;
+ enum nss_lookup_type how;
+ const char *name;
+ struct passwd *pwd;
+ char *buffer;
+ size_t bufsize, namesize;
+ uid_t uid;
+ uint32_t store;
+ int rv, stayopen, *errnop;
+
+ name = NULL;
+ uid = (uid_t)-1;
+ how = (enum nss_lookup_type)mdata;
+ switch (how) {
+ case nss_lt_name:
+ name = va_arg(ap, const char *);
+ keybuf[0] = _PW_KEYBYNAME;
+ break;
+ case nss_lt_id:
+ uid = va_arg(ap, uid_t);
+ keybuf[0] = _PW_KEYBYUID;
+ break;
+ case nss_lt_all:
+ keybuf[0] = _PW_KEYBYNUM;
+ break;
+ default:
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ pwd = va_arg(ap, struct passwd *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ *errnop = files_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+ if (how == nss_lt_all && st->keynum < 0) {
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ if (st->db == NULL &&
+ (st->db = pwdbopen(&st->version)) == NULL) {
+ *errnop = errno;
+ rv = NS_UNAVAIL;
+ goto fin;
+ }
+ if (how == nss_lt_all)
+ stayopen = 1;
+ else
+ stayopen = st->stayopen;
+ key.data = keybuf;
+ do {
+ switch (how) {
+ case nss_lt_name:
+ /* MAXLOGNAME includes NUL byte, but we do not
+ * include the NUL byte in the key.
+ */
+ namesize = strlcpy(&keybuf[1], name, sizeof(keybuf)-1);
+ if (namesize >= sizeof(keybuf)-1) {
+ *errnop = EINVAL;
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ key.size = namesize + 1;
+ break;
+ case nss_lt_id:
+ if (st->version < _PWD_CURRENT_VERSION) {
+ memcpy(&keybuf[1], &uid, sizeof(uid));
+ key.size = sizeof(uid) + 1;
+ } else {
+ store = htonl(uid);
+ memcpy(&keybuf[1], &store, sizeof(store));
+ key.size = sizeof(store) + 1;
+ }
+ break;
+ case nss_lt_all:
+ st->keynum++;
+ if (st->version < _PWD_CURRENT_VERSION) {
+ memcpy(&keybuf[1], &st->keynum,
+ sizeof(st->keynum));
+ key.size = sizeof(st->keynum) + 1;
+ } else {
+ store = htonl(st->keynum);
+ memcpy(&keybuf[1], &store, sizeof(store));
+ key.size = sizeof(store) + 1;
+ }
+ break;
+ }
+ keybuf[0] = _PW_VERSIONED(keybuf[0], st->version);
+ rv = st->db->get(st->db, &key, &entry, 0);
+ if (rv < 0 || rv > 1) { /* should never return > 1 */
+ *errnop = errno;
+ rv = NS_UNAVAIL;
+ goto fin;
+ } else if (rv == 1) {
+ if (how == nss_lt_all)
+ st->keynum = -1;
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ rv = pwdb_versions[st->version].match(entry.data, entry.size,
+ how, name, uid);
+ if (rv != NS_SUCCESS)
+ continue;
+ if (entry.size > bufsize) {
+ *errnop = ERANGE;
+ rv = NS_RETURN;
+ break;
+ }
+ memcpy(buffer, entry.data, entry.size);
+ rv = pwdb_versions[st->version].parse(buffer, entry.size, pwd,
+ errnop);
+ } while (how == nss_lt_all && !(rv & NS_TERMINATE));
+fin:
+ if (!stayopen && st->db != NULL) {
+ (void)st->db->close(st->db);
+ st->db = NULL;
+ }
+ if (rv == NS_SUCCESS) {
+ pwd->pw_fields &= ~_PWF_SOURCE;
+ pwd->pw_fields |= _PWF_FILES;
+ if (retval != NULL)
+ *(struct passwd **)retval = pwd;
+ }
+ return (rv);
+}
+
+
+static int
+pwdb_match_entry_v3(char *entry, size_t entrysize, enum nss_lookup_type how,
+ const char *name, uid_t uid)
+{
+ const char *p, *eom;
+ uid_t uid2;
+
+ eom = &entry[entrysize];
+ for (p = entry; p < eom; p++)
+ if (*p == '\0')
+ break;
+ if (*p != '\0')
+ return (NS_NOTFOUND);
+ if (how == nss_lt_all)
+ return (NS_SUCCESS);
+ if (how == nss_lt_name)
+ return (strcmp(name, entry) == 0 ? NS_SUCCESS : NS_NOTFOUND);
+ for (p++; p < eom; p++)
+ if (*p == '\0')
+ break;
+ if (*p != '\0' || (++p) + sizeof(uid) >= eom)
+ return (NS_NOTFOUND);
+ memcpy(&uid2, p, sizeof(uid2));
+ return (uid == uid2 ? NS_SUCCESS : NS_NOTFOUND);
+}
+
+
+static int
+pwdb_parse_entry_v3(char *buffer, size_t bufsize, struct passwd *pwd,
+ int *errnop)
+{
+ char *p, *eom;
+ int32_t pw_change, pw_expire;
+
+ /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */
+ p = buffer;
+ eom = &buffer[bufsize];
+#define STRING(field) do { \
+ (field) = p; \
+ while (p < eom && *p != '\0') \
+ p++; \
+ if (p >= eom) \
+ return (NS_NOTFOUND); \
+ p++; \
+ } while (0)
+#define SCALAR(field) do { \
+ if (p + sizeof(field) > eom) \
+ return (NS_NOTFOUND); \
+ memcpy(&(field), p, sizeof(field)); \
+ p += sizeof(field); \
+ } while (0)
+ STRING(pwd->pw_name);
+ STRING(pwd->pw_passwd);
+ SCALAR(pwd->pw_uid);
+ SCALAR(pwd->pw_gid);
+ SCALAR(pw_change);
+ STRING(pwd->pw_class);
+ STRING(pwd->pw_gecos);
+ STRING(pwd->pw_dir);
+ STRING(pwd->pw_shell);
+ SCALAR(pw_expire);
+ SCALAR(pwd->pw_fields);
+#undef STRING
+#undef SCALAR
+ pwd->pw_change = pw_change;
+ pwd->pw_expire = pw_expire;
+ return (NS_SUCCESS);
+}
+
+
+static int
+pwdb_match_entry_v4(char *entry, size_t entrysize, enum nss_lookup_type how,
+ const char *name, uid_t uid)
+{
+ const char *p, *eom;
+ uint32_t uid2;
+
+ eom = &entry[entrysize];
+ for (p = entry; p < eom; p++)
+ if (*p == '\0')
+ break;
+ if (*p != '\0')
+ return (NS_NOTFOUND);
+ if (how == nss_lt_all)
+ return (NS_SUCCESS);
+ if (how == nss_lt_name)
+ return (strcmp(name, entry) == 0 ? NS_SUCCESS : NS_NOTFOUND);
+ for (p++; p < eom; p++)
+ if (*p == '\0')
+ break;
+ if (*p != '\0' || (++p) + sizeof(uid) >= eom)
+ return (NS_NOTFOUND);
+ memcpy(&uid2, p, sizeof(uid2));
+ uid2 = ntohl(uid2);
+ return (uid == (uid_t)uid2 ? NS_SUCCESS : NS_NOTFOUND);
+}
+
+
+static int
+pwdb_parse_entry_v4(char *buffer, size_t bufsize, struct passwd *pwd,
+ int *errnop)
+{
+ char *p, *eom;
+ uint32_t n;
+
+ /* THIS CODE MUST MATCH THAT IN pwd_mkdb. */
+ p = buffer;
+ eom = &buffer[bufsize];
+#define STRING(field) do { \
+ (field) = p; \
+ while (p < eom && *p != '\0') \
+ p++; \
+ if (p >= eom) \
+ return (NS_NOTFOUND); \
+ p++; \
+ } while (0)
+#define SCALAR(field) do { \
+ if (p + sizeof(n) > eom) \
+ return (NS_NOTFOUND); \
+ memcpy(&n, p, sizeof(n)); \
+ (field) = ntohl(n); \
+ p += sizeof(n); \
+ } while (0)
+ STRING(pwd->pw_name);
+ STRING(pwd->pw_passwd);
+ SCALAR(pwd->pw_uid);
+ SCALAR(pwd->pw_gid);
+ SCALAR(pwd->pw_change);
+ STRING(pwd->pw_class);
+ STRING(pwd->pw_gecos);
+ STRING(pwd->pw_dir);
+ STRING(pwd->pw_shell);
+ SCALAR(pwd->pw_expire);
+ SCALAR(pwd->pw_fields);
+#undef STRING
+#undef SCALAR
+ return (NS_SUCCESS);
+}
+
+
+#ifdef HESIOD
+/*
+ * dns backend
+ */
+static void
+dns_endstate(void *p)
+{
+ free(p);
+}
+
+
+static int
+dns_setpwent(void *retval, void *mdata, va_list ap)
+{
+ struct dns_state *st;
+ int rv;
+
+ rv = dns_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+ st->counter = 0;
+ return (NS_UNAVAIL);
+}
+
+
+static int
+dns_passwd(void *retval, void *mdata, va_list ap)
+{
+ char buf[HESIOD_NAME_MAX];
+ struct dns_state *st;
+ struct passwd *pwd;
+ const char *name, *label;
+ void *ctx;
+ char *buffer, **hes;
+ size_t bufsize, linesize;
+ uid_t uid;
+ enum nss_lookup_type how;
+ int rv, *errnop;
+
+ ctx = NULL;
+ hes = NULL;
+ name = NULL;
+ uid = (uid_t)-1;
+ how = (enum nss_lookup_type)mdata;
+ switch (how) {
+ case nss_lt_name:
+ name = va_arg(ap, const char *);
+ break;
+ case nss_lt_id:
+ uid = va_arg(ap, uid_t);
+ break;
+ case nss_lt_all:
+ break;
+ }
+ pwd = va_arg(ap, struct passwd *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ *errnop = dns_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+ if (hesiod_init(&ctx) != 0) {
+ *errnop = errno;
+ rv = NS_UNAVAIL;
+ goto fin;
+ }
+ do {
+ rv = NS_NOTFOUND;
+ switch (how) {
+ case nss_lt_name:
+ label = name;
+ break;
+ case nss_lt_id:
+ if (snprintf(buf, sizeof(buf), "%lu",
+ (unsigned long)uid) >= sizeof(buf))
+ goto fin;
+ label = buf;
+ break;
+ case nss_lt_all:
+ if (st->counter < 0)
+ goto fin;
+ if (snprintf(buf, sizeof(buf), "passwd-%ld",
+ st->counter++) >= sizeof(buf))
+ goto fin;
+ label = buf;
+ break;
+ }
+ hes = hesiod_resolve(ctx, label,
+ how == nss_lt_id ? "uid" : "passwd");
+ if (hes == NULL) {
+ if (how == nss_lt_all)
+ st->counter = -1;
+ if (errno != ENOENT)
+ *errnop = errno;
+ goto fin;
+ }
+ rv = __pw_match_entry(hes[0], strlen(hes[0]), how, name, uid);
+ if (rv != NS_SUCCESS) {
+ hesiod_free_list(ctx, hes);
+ hes = NULL;
+ continue;
+ }
+ linesize = strlcpy(buffer, hes[0], bufsize);
+ if (linesize >= bufsize) {
+ *errnop = ERANGE;
+ rv = NS_RETURN;
+ continue;
+ }
+ hesiod_free_list(ctx, hes);
+ hes = NULL;
+ rv = __pw_parse_entry(buffer, bufsize, pwd, 0, errnop);
+ } while (how == nss_lt_all && !(rv & NS_TERMINATE));
+fin:
+ if (hes != NULL)
+ hesiod_free_list(ctx, hes);
+ if (ctx != NULL)
+ hesiod_end(ctx);
+ if (rv == NS_SUCCESS) {
+ pwd->pw_fields &= ~_PWF_SOURCE;
+ pwd->pw_fields |= _PWF_HESIOD;
+ if (retval != NULL)
+ *(struct passwd **)retval = pwd;
+ }
+ return (rv);
+}
+#endif /* HESIOD */
+
+
+#ifdef YP
+/*
+ * nis backend
+ */
+static void
+nis_endstate(void *p)
+{
+ free(((struct nis_state *)p)->key);
+ free(p);
+}
+
+/*
+ * Test for the presence of special FreeBSD-specific master.passwd.by*
+ * maps. We do this using yp_order(). If it fails, then either the server
+ * doesn't have the map, or the YPPROC_ORDER procedure isn't supported by
+ * the server (Sun NIS+ servers in YP compat mode behave this way). If
+ * the master.passwd.by* maps don't exist, then let the lookup routine try
+ * the regular passwd.by* maps instead. If the lookup routine fails, it
+ * can return an error as needed.
+ */
+static int
+nis_map(char *domain, enum nss_lookup_type how, char *buffer, size_t bufsize,
+ int *master)
+{
+ int rv, order;
+
+ *master = 0;
+ if (geteuid() == 0) {
+ if (snprintf(buffer, bufsize, "master.passwd.by%s",
+ (how == nss_lt_id) ? "uid" : "name") >= bufsize)
+ return (NS_UNAVAIL);
+ rv = yp_order(domain, buffer, &order);
+ if (rv == 0) {
+ *master = 1;
+ return (NS_SUCCESS);
+ }
+ }
+
+ if (snprintf(buffer, bufsize, "passwd.by%s",
+ (how == nss_lt_id) ? "uid" : "name") >= bufsize)
+ return (NS_UNAVAIL);
+
+ return (NS_SUCCESS);
+}
+
+
+static int
+nis_adjunct(char *domain, const char *name, char *buffer, size_t bufsize)
+{
+ int rv;
+ char *result, *p, *q, *eor;
+ int resultlen;
+
+ result = NULL;
+ rv = yp_match(domain, "passwd.adjunct.byname", name, strlen(name),
+ &result, &resultlen);
+ if (rv != 0)
+ rv = 1;
+ else {
+ eor = &result[resultlen];
+ p = memchr(result, ':', eor - result);
+ if (p != NULL && ++p < eor &&
+ (q = memchr(p, ':', eor - p)) != NULL) {
+ if (q - p >= bufsize)
+ rv = -1;
+ else {
+ memcpy(buffer, p, q - p);
+ buffer[q - p] ='\0';
+ }
+ } else
+ rv = 1;
+ }
+ free(result);
+ return (rv);
+}
+
+
+static int
+nis_setpwent(void *retval, void *mdata, va_list ap)
+{
+ struct nis_state *st;
+ int rv;
+
+ rv = nis_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+ st->done = 0;
+ free(st->key);
+ st->key = NULL;
+ return (NS_UNAVAIL);
+}
+
+
+static int
+nis_passwd(void *retval, void *mdata, va_list ap)
+{
+ char map[YPMAXMAP];
+ struct nis_state *st;
+ struct passwd *pwd;
+ const char *name;
+ char *buffer, *key, *result;
+ size_t bufsize;
+ uid_t uid;
+ enum nss_lookup_type how;
+ int *errnop, keylen, resultlen, rv, master;
+
+ name = NULL;
+ uid = (uid_t)-1;
+ how = (enum nss_lookup_type)mdata;
+ switch (how) {
+ case nss_lt_name:
+ name = va_arg(ap, const char *);
+ break;
+ case nss_lt_id:
+ uid = va_arg(ap, uid_t);
+ break;
+ case nss_lt_all:
+ break;
+ }
+ pwd = va_arg(ap, struct passwd *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ *errnop = nis_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+ if (st->domain[0] == '\0') {
+ if (getdomainname(st->domain, sizeof(st->domain)) != 0) {
+ *errnop = errno;
+ return (NS_UNAVAIL);
+ }
+ }
+ rv = nis_map(st->domain, how, map, sizeof(map), &master);
+ if (rv != NS_SUCCESS)
+ return (rv);
+ result = NULL;
+ do {
+ rv = NS_NOTFOUND;
+ switch (how) {
+ case nss_lt_name:
+ if (strlcpy(buffer, name, bufsize) >= bufsize)
+ goto erange;
+ break;
+ case nss_lt_id:
+ if (snprintf(buffer, bufsize, "%lu",
+ (unsigned long)uid) >= bufsize)
+ goto erange;
+ break;
+ case nss_lt_all:
+ if (st->done)
+ goto fin;
+ break;
+ }
+ result = NULL;
+ if (how == nss_lt_all) {
+ if (st->key == NULL)
+ rv = yp_first(st->domain, map, &st->key,
+ &st->keylen, &result, &resultlen);
+ else {
+ key = st->key;
+ keylen = st->keylen;
+ st->key = NULL;
+ rv = yp_next(st->domain, map, key, keylen,
+ &st->key, &st->keylen, &result,
+ &resultlen);
+ free(key);
+ }
+ if (rv != 0) {
+ free(result);
+ free(st->key);
+ st->key = NULL;
+ if (rv == YPERR_NOMORE)
+ st->done = 1;
+ else
+ rv = NS_UNAVAIL;
+ goto fin;
+ }
+ } else {
+ rv = yp_match(st->domain, map, buffer, strlen(buffer),
+ &result, &resultlen);
+ if (rv == YPERR_KEY) {
+ rv = NS_NOTFOUND;
+ continue;
+ } else if (rv != 0) {
+ free(result);
+ rv = NS_UNAVAIL;
+ continue;
+ }
+ }
+ if (resultlen >= bufsize)
+ goto erange;
+ memcpy(buffer, result, resultlen);
+ buffer[resultlen] = '\0';
+ free(result);
+ rv = __pw_match_entry(buffer, resultlen, how, name, uid);
+ if (rv == NS_SUCCESS)
+ rv = __pw_parse_entry(buffer, resultlen, pwd, master,
+ errnop);
+ } while (how == nss_lt_all && !(rv & NS_TERMINATE));
+fin:
+ if (rv == NS_SUCCESS) {
+ if (strstr(pwd->pw_passwd, "##") != NULL) {
+ rv = nis_adjunct(st->domain, pwd->pw_name,
+ &buffer[resultlen+1], bufsize-resultlen-1);
+ if (rv < 0)
+ goto erange;
+ else if (rv == 0)
+ pwd->pw_passwd = &buffer[resultlen+1];
+ }
+ pwd->pw_fields &= ~_PWF_SOURCE;
+ pwd->pw_fields |= _PWF_NIS;
+ if (retval != NULL)
+ *(struct passwd **)retval = pwd;
+ rv = NS_SUCCESS;
+ }
+ return (rv);
+erange:
+ *errnop = ERANGE;
+ return (NS_RETURN);
+}
+#endif /* YP */
+
+
+/*
+ * compat backend
+ */
+static void
+compat_clear_template(struct passwd *template)
+{
+
+ free(template->pw_passwd);
+ free(template->pw_gecos);
+ free(template->pw_dir);
+ free(template->pw_shell);
+ memset(template, 0, sizeof(*template));
+}
+
+
+static int
+compat_set_template(struct passwd *src, struct passwd *template)
+{
+
+ compat_clear_template(template);
+#ifdef PW_OVERRIDE_PASSWD
+ if ((src->pw_fields & _PWF_PASSWD) &&
+ (template->pw_passwd = strdup(src->pw_passwd)) == NULL)
+ goto enomem;
+#endif
+ if (src->pw_fields & _PWF_UID)
+ template->pw_uid = src->pw_uid;
+ if (src->pw_fields & _PWF_GID)
+ template->pw_gid = src->pw_gid;
+ if ((src->pw_fields & _PWF_GECOS) &&
+ (template->pw_gecos = strdup(src->pw_gecos)) == NULL)
+ goto enomem;
+ if ((src->pw_fields & _PWF_DIR) &&
+ (template->pw_dir = strdup(src->pw_dir)) == NULL)
+ goto enomem;
+ if ((src->pw_fields & _PWF_SHELL) &&
+ (template->pw_shell = strdup(src->pw_shell)) == NULL)
+ goto enomem;
+ template->pw_fields = src->pw_fields;
+ return (0);
+enomem:
+ syslog(LOG_ERR, "getpwent memory allocation failure");
+ return (-1);
+}
+
+
+static int
+compat_use_template(struct passwd *pwd, struct passwd *template, char *buffer,
+ size_t bufsize)
+{
+ struct passwd hold;
+ char *copy, *p, *q, *eob;
+ size_t n;
+
+ /* We cannot know the layout of the password fields in `buffer',
+ * so we have to copy everything.
+ */
+ if (template->pw_fields == 0) /* nothing to fill-in */
+ return (0);
+ n = 0;
+ n += pwd->pw_name != NULL ? strlen(pwd->pw_name) + 1 : 0;
+ n += pwd->pw_passwd != NULL ? strlen(pwd->pw_passwd) + 1 : 0;
+ n += pwd->pw_class != NULL ? strlen(pwd->pw_class) + 1 : 0;
+ n += pwd->pw_gecos != NULL ? strlen(pwd->pw_gecos) + 1 : 0;
+ n += pwd->pw_dir != NULL ? strlen(pwd->pw_dir) + 1 : 0;
+ n += pwd->pw_shell != NULL ? strlen(pwd->pw_shell) + 1 : 0;
+ copy = malloc(n);
+ if (copy == NULL) {
+ syslog(LOG_ERR, "getpwent memory allocation failure");
+ return (ENOMEM);
+ }
+ p = copy;
+ eob = &copy[n];
+#define COPY(field) do { \
+ if (pwd->field == NULL) \
+ hold.field = NULL; \
+ else { \
+ hold.field = p; \
+ p += strlcpy(p, pwd->field, eob-p) + 1; \
+ } \
+} while (0)
+ COPY(pw_name);
+ COPY(pw_passwd);
+ COPY(pw_class);
+ COPY(pw_gecos);
+ COPY(pw_dir);
+ COPY(pw_shell);
+#undef COPY
+ p = buffer;
+ eob = &buffer[bufsize];
+#define COPY(field, flag) do { \
+ q = (template->pw_fields & flag) ? template->field : hold.field; \
+ if (q == NULL) \
+ pwd->field = NULL; \
+ else { \
+ pwd->field = p; \
+ if ((n = strlcpy(p, q, eob-p)) >= eob-p) { \
+ free(copy); \
+ return (ERANGE); \
+ } \
+ p += n + 1; \
+ } \
+} while (0)
+ COPY(pw_name, 0);
+#ifdef PW_OVERRIDE_PASSWD
+ COPY(pw_passwd, _PWF_PASSWD);
+#else
+ COPY(pw_passwd, 0);
+#endif
+ COPY(pw_class, 0);
+ COPY(pw_gecos, _PWF_GECOS);
+ COPY(pw_dir, _PWF_DIR);
+ COPY(pw_shell, _PWF_SHELL);
+#undef COPY
+#define COPY(field, flag) do { \
+ if (template->pw_fields & flag) \
+ pwd->field = template->field; \
+} while (0)
+ COPY(pw_uid, _PWF_UID);
+ COPY(pw_gid, _PWF_GID);
+#undef COPY
+ free(copy);
+ return (0);
+}
+
+
+static int
+compat_exclude(const char *name, DB **db)
+{
+ DBT key, data;
+
+ if (*db == NULL &&
+ (*db = dbopen(NULL, O_RDWR, 600, DB_HASH, 0)) == NULL)
+ return (errno);
+ key.size = strlen(name);
+ key.data = (char *)name;
+ data.size = 0;
+ data.data = NULL;
+
+ if ((*db)->put(*db, &key, &data, 0) == -1)
+ return (errno);
+ return (0);
+}
+
+
+static int
+compat_is_excluded(const char *name, DB *db)
+{
+ DBT key, data;
+
+ if (db == NULL)
+ return (0);
+ key.size = strlen(name);
+ key.data = (char *)name;
+ return (db->get(db, &key, &data, 0) == 0);
+}
+
+
+static int
+compat_redispatch(struct compat_state *st, enum nss_lookup_type how,
+ enum nss_lookup_type lookup_how, const char *name, const char *lookup_name,
+ uid_t uid, struct passwd *pwd, char *buffer, size_t bufsize, int *errnop)
+{
+ static const ns_src compatsrc[] = {
+#ifdef YP
+ { NSSRC_NIS, NS_SUCCESS },
+#endif
+ { NULL, 0 }
+ };
+ ns_dtab dtab[] = {
+#ifdef YP
+ { NSSRC_NIS, nis_passwd, NULL },
+#endif
+#ifdef HESIOD
+ { NSSRC_DNS, dns_passwd, NULL },
+#endif
+ { NULL, NULL, NULL }
+ };
+ void *discard;
+ int rv, e, i;
+
+ for (i = 0; i < sizeof(dtab)/sizeof(dtab[0]) - 1; i++)
+ dtab[i].mdata = (void *)lookup_how;
+more:
+ pwd_init(pwd);
+ switch (lookup_how) {
+ case nss_lt_all:
+ rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT,
+ "getpwent_r", compatsrc, pwd, buffer, bufsize,
+ errnop);
+ break;
+ case nss_lt_id:
+ rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT,
+ "getpwuid_r", compatsrc, uid, pwd, buffer,
+ bufsize, errnop);
+ break;
+ case nss_lt_name:
+ rv = _nsdispatch(&discard, dtab, NSDB_PASSWD_COMPAT,
+ "getpwnam_r", compatsrc, lookup_name, pwd, buffer,
+ bufsize, errnop);
+ break;
+ default:
+ return (NS_UNAVAIL);
+ }
+ if (rv != NS_SUCCESS)
+ return (rv);
+ if (compat_is_excluded(pwd->pw_name, st->exclude)) {
+ if (how == nss_lt_all)
+ goto more;
+ return (NS_NOTFOUND);
+ }
+ e = compat_use_template(pwd, &st->template, buffer, bufsize);
+ if (e != 0) {
+ *errnop = e;
+ if (e == ERANGE)
+ return (NS_RETURN);
+ else
+ return (NS_UNAVAIL);
+ }
+ switch (how) {
+ case nss_lt_name:
+ if (strcmp(name, pwd->pw_name) != 0)
+ return (NS_NOTFOUND);
+ break;
+ case nss_lt_id:
+ if (uid != pwd->pw_uid)
+ return (NS_NOTFOUND);
+ break;
+ default:
+ break;
+ }
+ return (NS_SUCCESS);
+}
+
+
+static void
+compat_endstate(void *p)
+{
+ struct compat_state *st;
+
+ if (p == NULL)
+ return;
+ st = (struct compat_state *)p;
+ if (st->db != NULL)
+ st->db->close(st->db);
+ if (st->exclude != NULL)
+ st->exclude->close(st->exclude);
+ compat_clear_template(&st->template);
+ free(p);
+}
+
+
+static int
+compat_setpwent(void *retval, void *mdata, va_list ap)
+{
+ static const ns_src compatsrc[] = {
+#ifdef YP
+ { NSSRC_NIS, NS_SUCCESS },
+#endif
+ { NULL, 0 }
+ };
+ ns_dtab dtab[] = {
+#ifdef YP
+ { NSSRC_NIS, nis_setpwent, NULL },
+#endif
+#ifdef HESIOD
+ { NSSRC_DNS, dns_setpwent, NULL },
+#endif
+ { NULL, NULL, NULL }
+ };
+ struct compat_state *st;
+ int rv, stayopen;
+
+#define set_setent(x, y) do { \
+ int i; \
+ \
+ for (i = 0; i < (sizeof(x)/sizeof(x[0])) - 1; i++) \
+ x[i].mdata = (void *)y; \
+} while (0)
+
+ rv = compat_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+ switch ((enum constants)mdata) {
+ case SETPWENT:
+ stayopen = va_arg(ap, int);
+ st->keynum = 0;
+ if (stayopen)
+ st->db = pwdbopen(&st->version);
+ st->stayopen = stayopen;
+ set_setent(dtab, mdata);
+ (void)_nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "setpwent",
+ compatsrc, 0);
+ break;
+ case ENDPWENT:
+ if (st->db != NULL) {
+ (void)st->db->close(st->db);
+ st->db = NULL;
+ }
+ set_setent(dtab, mdata);
+ (void)_nsdispatch(NULL, dtab, NSDB_PASSWD_COMPAT, "endpwent",
+ compatsrc, 0);
+ break;
+ default:
+ break;
+ }
+ return (NS_UNAVAIL);
+#undef set_setent
+}
+
+
+static int
+compat_passwd(void *retval, void *mdata, va_list ap)
+{
+ char keybuf[MAXLOGNAME + 1];
+ DBT key, entry;
+ struct compat_state *st;
+ enum nss_lookup_type how;
+ const char *name;
+ struct passwd *pwd;
+ char *buffer, *pw_name;
+ char *host, *user, *domain;
+ size_t bufsize;
+ uid_t uid;
+ uint32_t store;
+ int rv, from_compat, stayopen, *errnop;
+
+ from_compat = 0;
+ name = NULL;
+ uid = (uid_t)-1;
+ how = (enum nss_lookup_type)mdata;
+ switch (how) {
+ case nss_lt_name:
+ name = va_arg(ap, const char *);
+ break;
+ case nss_lt_id:
+ uid = va_arg(ap, uid_t);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ pwd = va_arg(ap, struct passwd *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ *errnop = compat_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+ if (how == nss_lt_all && st->keynum < 0) {
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ if (st->db == NULL &&
+ (st->db = pwdbopen(&st->version)) == NULL) {
+ *errnop = errno;
+ rv = NS_UNAVAIL;
+ goto fin;
+ }
+ if (how == nss_lt_all) {
+ if (st->keynum < 0) {
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ stayopen = 1;
+ } else {
+ st->keynum = 0;
+ stayopen = st->stayopen;
+ }
+docompat:
+ rv = NS_NOTFOUND;
+ switch (st->compat) {
+ case COMPAT_MODE_ALL:
+ rv = compat_redispatch(st, how, how, name, name, uid, pwd,
+ buffer, bufsize, errnop);
+ if (rv != NS_SUCCESS)
+ st->compat = COMPAT_MODE_OFF;
+ break;
+ case COMPAT_MODE_NETGROUP:
+ /* XXX getnetgrent is not thread-safe. */
+ do {
+ rv = getnetgrent(&host, &user, &domain);
+ if (rv == 0) {
+ endnetgrent();
+ st->compat = COMPAT_MODE_OFF;
+ rv = NS_NOTFOUND;
+ continue;
+ } else if (user == NULL || user[0] == '\0')
+ continue;
+ rv = compat_redispatch(st, how, nss_lt_name, name,
+ user, uid, pwd, buffer, bufsize, errnop);
+ } while (st->compat == COMPAT_MODE_NETGROUP &&
+ !(rv & NS_TERMINATE));
+ break;
+ case COMPAT_MODE_NAME:
+ rv = compat_redispatch(st, how, nss_lt_name, name, st->name,
+ uid, pwd, buffer, bufsize, errnop);
+ free(st->name);
+ st->name = NULL;
+ st->compat = COMPAT_MODE_OFF;
+ break;
+ default:
+ break;
+ }
+ if (rv & NS_TERMINATE) {
+ from_compat = 1;
+ goto fin;
+ }
+ key.data = keybuf;
+ rv = NS_NOTFOUND;
+ while (st->keynum >= 0) {
+ st->keynum++;
+ if (st->version < _PWD_CURRENT_VERSION) {
+ memcpy(&keybuf[1], &st->keynum, sizeof(st->keynum));
+ key.size = sizeof(st->keynum) + 1;
+ } else {
+ store = htonl(st->keynum);
+ memcpy(&keybuf[1], &store, sizeof(store));
+ key.size = sizeof(store) + 1;
+ }
+ keybuf[0] = _PW_VERSIONED(_PW_KEYBYNUM, st->version);
+ rv = st->db->get(st->db, &key, &entry, 0);
+ if (rv < 0 || rv > 1) { /* should never return > 1 */
+ *errnop = errno;
+ rv = NS_UNAVAIL;
+ goto fin;
+ } else if (rv == 1) {
+ st->keynum = -1;
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ pw_name = (char *)entry.data;
+ switch (pw_name[0]) {
+ case '+':
+ switch (pw_name[1]) {
+ case '\0':
+ st->compat = COMPAT_MODE_ALL;
+ break;
+ case '@':
+ setnetgrent(&pw_name[2]);
+ st->compat = COMPAT_MODE_NETGROUP;
+ break;
+ default:
+ st->name = strdup(&pw_name[1]);
+ if (st->name == NULL) {
+ syslog(LOG_ERR,
+ "getpwent memory allocation failure");
+ *errnop = ENOMEM;
+ rv = NS_UNAVAIL;
+ break;
+ }
+ st->compat = COMPAT_MODE_NAME;
+ }
+ if (entry.size > bufsize) {
+ *errnop = ERANGE;
+ rv = NS_RETURN;
+ goto fin;
+ }
+ memcpy(buffer, entry.data, entry.size);
+ rv = pwdb_versions[st->version].parse(buffer,
+ entry.size, pwd, errnop);
+ if (rv != NS_SUCCESS)
+ ;
+ else if (compat_set_template(pwd, &st->template) < 0) {
+ *errnop = ENOMEM;
+ rv = NS_UNAVAIL;
+ goto fin;
+ }
+ goto docompat;
+ case '-':
+ switch (pw_name[1]) {
+ case '\0':
+ /* XXX Maybe syslog warning */
+ continue;
+ case '@':
+ setnetgrent(&pw_name[2]);
+ while (getnetgrent(&host, &user, &domain) !=
+ 0) {
+ if (user != NULL && user[0] != '\0')
+ compat_exclude(user,
+ &st->exclude);
+ }
+ endnetgrent();
+ continue;
+ default:
+ compat_exclude(&pw_name[1], &st->exclude);
+ continue;
+ }
+ break;
+ default:
+ break;
+ }
+ if (compat_is_excluded((char *)entry.data, st->exclude))
+ continue;
+ rv = pwdb_versions[st->version].match(entry.data, entry.size,
+ how, name, uid);
+ if (rv == NS_RETURN)
+ break;
+ else if (rv != NS_SUCCESS)
+ continue;
+ if (entry.size > bufsize) {
+ *errnop = ERANGE;
+ rv = NS_RETURN;
+ break;
+ }
+ memcpy(buffer, entry.data, entry.size);
+ rv = pwdb_versions[st->version].parse(buffer, entry.size, pwd,
+ errnop);
+ if (rv & NS_TERMINATE)
+ break;
+ }
+fin:
+ if (!stayopen && st->db != NULL) {
+ (void)st->db->close(st->db);
+ st->db = NULL;
+ }
+ if (rv == NS_SUCCESS) {
+ if (!from_compat) {
+ pwd->pw_fields &= ~_PWF_SOURCE;
+ pwd->pw_fields |= _PWF_FILES;
+ }
+ if (retval != NULL)
+ *(struct passwd **)retval = pwd;
+ }
+ return (rv);
+}
+
+
+/*
+ * common passwd line matching and parsing
+ */
+int
+__pw_match_entry(const char *entry, size_t entrysize, enum nss_lookup_type how,
+ const char *name, uid_t uid)
+{
+ const char *p, *eom;
+ char *q;
+ size_t len;
+ unsigned long m;
+
+ eom = entry + entrysize;
+ for (p = entry; p < eom; p++)
+ if (*p == ':')
+ break;
+ if (*p != ':')
+ return (NS_NOTFOUND);
+ if (how == nss_lt_all)
+ return (NS_SUCCESS);
+ if (how == nss_lt_name) {
+ len = strlen(name);
+ if (len == (p - entry) && memcmp(name, entry, len) == 0)
+ return (NS_SUCCESS);
+ else
+ return (NS_NOTFOUND);
+ }
+ for (p++; p < eom; p++)
+ if (*p == ':')
+ break;
+ if (*p != ':')
+ return (NS_NOTFOUND);
+ m = strtoul(++p, &q, 10);
+ if (q[0] != ':' || (uid_t)m != uid)
+ return (NS_NOTFOUND);
+ else
+ return (NS_SUCCESS);
+}
+
+
+/* XXX buffer must be NUL-terminated. errnop is not set correctly. */
+int
+__pw_parse_entry(char *buffer, size_t bufsize __unused, struct passwd *pwd,
+ int master, int *errnop __unused)
+{
+
+ if (__pw_scan(buffer, pwd, master ? _PWSCAN_MASTER : 0) == 0)
+ return (NS_NOTFOUND);
+ else
+ return (NS_SUCCESS);
+}
diff --git a/lib/libc/gen/getttyent.3 b/lib/libc/gen/getttyent.3
new file mode 100644
index 0000000..18c3f07
--- /dev/null
+++ b/lib/libc/gen/getttyent.3
@@ -0,0 +1,208 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getttyent.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd November 17, 1996
+.Dt GETTTYENT 3
+.Os
+.Sh NAME
+.Nm getttyent ,
+.Nm getttynam ,
+.Nm setttyent ,
+.Nm endttyent ,
+.Nm isdialuptty ,
+.Nm isnettty
+.Nd
+.Xr ttys 5
+file routines
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ttyent.h
+.Ft struct ttyent *
+.Fn getttyent void
+.Ft struct ttyent *
+.Fn getttynam "const char *name"
+.Ft int
+.Fn setttyent void
+.Ft int
+.Fn endttyent void
+.Ft int
+.Fn isdialuptty "const char *name"
+.Ft int
+.Fn isnettty "const char *name"
+.Sh DESCRIPTION
+The
+.Fn getttyent ,
+and
+.Fn getttynam
+functions
+each return a pointer to an object, with the following structure,
+containing the broken-out fields of a line from the tty description
+file.
+.Bd -literal
+struct ttyent {
+ char *ty_name; /* terminal device name */
+ char *ty_getty; /* command to execute, usually getty */
+ char *ty_type; /* terminal type for termcap */
+#define TTY_ON 0x01 /* enable logins (start ty_getty program) */
+#define TTY_SECURE 0x02 /* allow uid of 0 to login */
+#define TTY_DIALUP 0x04 /* is a dialup tty */
+#define TTY_NETWORK 0x08 /* is a network tty */
+ int ty_status; /* status flags */
+ char *ty_window; /* command to start up window manager */
+ char *ty_comment; /* comment field */
+ char *ty_group; /* tty group name */
+};
+.Ed
+.Pp
+The fields are as follows:
+.Bl -tag -width ty_comment
+.It Fa ty_name
+The name of the character-special file.
+.It Fa ty_getty
+The name of the command invoked by
+.Xr init 8
+to initialize tty line characteristics.
+.It Fa ty_type
+The name of the default terminal type connected to this tty line.
+.It Fa ty_status
+A mask of bit fields which indicate various actions allowed on this
+tty line.
+The possible flags are as follows:
+.Bl -tag -width TTY_NETWORK
+.It Dv TTY_ON
+Enables logins (i.e.,
+.Xr init 8
+will start the command referenced by
+.Fa ty_getty
+on this entry).
+.It Dv TTY_SECURE
+Allow users with a uid of 0 to login on this terminal.
+.It Dv TTY_DIALUP
+Identifies a tty as a dialin line.
+If this flag is set, then
+.Fn isdialuptty
+will return a non-zero value.
+.It Dv TTY_NETWORK
+Identifies a tty used for network connections.
+If this flag is set, then
+.Fn isnettty
+will return a non-zero value.
+.El
+.It Fa ty_window
+The command to execute for a window system associated with the line.
+.It Fa ty_group
+A group name to which the tty belongs.
+If no group is specified in the ttys description file,
+then the tty is placed in an anonymous group called "none".
+.It Fa ty_comment
+Any trailing comment field, with any leading hash marks (``#'') or
+whitespace removed.
+.El
+.Pp
+If any of the fields pointing to character strings are unspecified,
+they are returned as null pointers.
+The field
+.Fa ty_status
+will be zero if no flag values are specified.
+.Pp
+See
+.Xr ttys 5
+for a more complete discussion of the meaning and usage of the
+fields.
+.Pp
+The
+.Fn getttyent
+function
+reads the next line from the ttys file, opening the file if necessary.
+The
+.Fn setttyent
+function
+rewinds the file if open, or opens the file if it is unopened.
+The
+.Fn endttyent
+function
+closes any open files.
+.Pp
+The
+.Fn getttynam
+function
+searches from the beginning of the file until a matching
+.Fa name
+is found
+(or until
+.Dv EOF
+is encountered).
+.Sh RETURN VALUES
+The routines
+.Fn getttyent
+and
+.Fn getttynam
+return a null pointer on
+.Dv EOF
+or error.
+The
+.Fn setttyent
+function
+and
+.Fn endttyent
+return 0 on failure and 1 on success.
+.Pp
+The routines
+.Fn isdialuptty
+and
+.Fn isnettty
+return non-zero if the dialup or network flag is set for the
+tty entry relating to the tty named by the argument, and
+zero otherwise.
+.Sh FILES
+.Bl -tag -width /etc/ttys -compact
+.It Pa /etc/ttys
+.El
+.Sh SEE ALSO
+.Xr login 1 ,
+.Xr gettytab 5 ,
+.Xr termcap 5 ,
+.Xr ttys 5 ,
+.Xr getty 8 ,
+.Xr init 8
+.Sh HISTORY
+The
+.Fn getttyent ,
+.Fn getttynam ,
+.Fn setttyent ,
+and
+.Fn endttyent
+functions appeared in
+.Bx 4.3 .
+.Sh BUGS
+These functions use static data storage;
+if the data is needed for future use, it should be
+copied before any subsequent calls overwrite it.
diff --git a/lib/libc/gen/getttyent.c b/lib/libc/gen/getttyent.c
new file mode 100644
index 0000000..f2fc298
--- /dev/null
+++ b/lib/libc/gen/getttyent.c
@@ -0,0 +1,257 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getttyent.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ttyent.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <string.h>
+
+static char zapchar;
+static FILE *tf;
+static size_t lbsize;
+static char *line;
+
+#define MALLOCCHUNK 100
+
+static char *skip(char *);
+static char *value(char *);
+
+struct ttyent *
+getttynam(const char *tty)
+{
+ struct ttyent *t;
+
+ if (strncmp(tty, "/dev/", 5) == 0)
+ tty += 5;
+ setttyent();
+ while ( (t = getttyent()) )
+ if (!strcmp(tty, t->ty_name))
+ break;
+ endttyent();
+ return (t);
+}
+
+struct ttyent *
+getttyent(void)
+{
+ static struct ttyent tty;
+ char *p;
+ int c;
+ size_t i;
+
+ if (!tf && !setttyent())
+ return (NULL);
+ for (;;) {
+ if (!fgets(p = line, lbsize, tf))
+ return (NULL);
+ /* extend buffer if line was too big, and retry */
+ while (!strchr(p, '\n') && !feof(tf)) {
+ i = strlen(p);
+ lbsize += MALLOCCHUNK;
+ if ((p = realloc(line, lbsize)) == NULL) {
+ (void)endttyent();
+ return (NULL);
+ }
+ line = p;
+ if (!fgets(&line[i], lbsize - i, tf))
+ return (NULL);
+ }
+ while (isspace((unsigned char)*p))
+ ++p;
+ if (*p && *p != '#')
+ break;
+ }
+
+#define scmp(e) !strncmp(p, e, sizeof(e) - 1) && isspace((unsigned char)p[sizeof(e) - 1])
+#define vcmp(e) !strncmp(p, e, sizeof(e) - 1) && p[sizeof(e) - 1] == '='
+
+ zapchar = 0;
+ tty.ty_name = p;
+ tty.ty_status = 0;
+ tty.ty_window = NULL;
+ tty.ty_group = _TTYS_NOGROUP;
+
+ p = skip(p);
+ if (!*(tty.ty_getty = p))
+ tty.ty_getty = tty.ty_type = NULL;
+ else {
+ p = skip(p);
+ if (!*(tty.ty_type = p))
+ tty.ty_type = NULL;
+ else {
+ /* compatibility kludge: handle network/dialup specially */
+ if (scmp(_TTYS_DIALUP))
+ tty.ty_status |= TTY_DIALUP;
+ else if (scmp(_TTYS_NETWORK))
+ tty.ty_status |= TTY_NETWORK;
+ p = skip(p);
+ }
+ }
+
+ for (; *p; p = skip(p)) {
+ if (scmp(_TTYS_OFF))
+ tty.ty_status &= ~TTY_ON;
+ else if (scmp(_TTYS_ON))
+ tty.ty_status |= TTY_ON;
+ else if (scmp(_TTYS_SECURE))
+ tty.ty_status |= TTY_SECURE;
+ else if (scmp(_TTYS_INSECURE))
+ tty.ty_status &= ~TTY_SECURE;
+ else if (scmp(_TTYS_DIALUP))
+ tty.ty_status |= TTY_DIALUP;
+ else if (scmp(_TTYS_NETWORK))
+ tty.ty_status |= TTY_NETWORK;
+ else if (vcmp(_TTYS_WINDOW))
+ tty.ty_window = value(p);
+ else if (vcmp(_TTYS_GROUP))
+ tty.ty_group = value(p);
+ else
+ break;
+ }
+
+ if (zapchar == '#' || *p == '#')
+ while ((c = *++p) == ' ' || c == '\t')
+ ;
+ tty.ty_comment = p;
+ if (*p == 0)
+ tty.ty_comment = 0;
+ if ((p = strchr(p, '\n')))
+ *p = '\0';
+ return (&tty);
+}
+
+#define QUOTED 1
+
+/*
+ * Skip over the current field, removing quotes, and return a pointer to
+ * the next field.
+ */
+static char *
+skip(char *p)
+{
+ char *t;
+ int c, q;
+
+ for (q = 0, t = p; (c = *p) != '\0'; p++) {
+ if (c == '"') {
+ q ^= QUOTED; /* obscure, but nice */
+ continue;
+ }
+ if (q == QUOTED && *p == '\\' && *(p+1) == '"')
+ p++;
+ *t++ = *p;
+ if (q == QUOTED)
+ continue;
+ if (c == '#') {
+ zapchar = c;
+ *p = 0;
+ break;
+ }
+ if (c == '\t' || c == ' ' || c == '\n') {
+ zapchar = c;
+ *p++ = 0;
+ while ((c = *p) == '\t' || c == ' ' || c == '\n')
+ p++;
+ break;
+ }
+ }
+ *--t = '\0';
+ return (p);
+}
+
+static char *
+value(char *p)
+{
+
+ return ((p = strchr(p, '=')) ? ++p : NULL);
+}
+
+int
+setttyent(void)
+{
+
+ if (line == NULL) {
+ if ((line = malloc(MALLOCCHUNK)) == NULL)
+ return (0);
+ lbsize = MALLOCCHUNK;
+ }
+ if (tf) {
+ rewind(tf);
+ return (1);
+ } else if ( (tf = fopen(_PATH_TTYS, "r")) )
+ return (1);
+ return (0);
+}
+
+int
+endttyent(void)
+{
+ int rval;
+
+ /*
+ * NB: Don't free `line' because getttynam()
+ * may still be referencing it
+ */
+ if (tf) {
+ rval = (fclose(tf) != EOF);
+ tf = NULL;
+ return (rval);
+ }
+ return (1);
+}
+
+static int
+isttystat(const char *tty, int flag)
+{
+ struct ttyent *t;
+
+ return ((t = getttynam(tty)) == NULL) ? 0 : !!(t->ty_status & flag);
+}
+
+
+int
+isdialuptty(const char *tty)
+{
+
+ return isttystat(tty, TTY_DIALUP);
+}
+
+int
+isnettty(const char *tty)
+{
+
+ return isttystat(tty, TTY_NETWORK);
+}
diff --git a/lib/libc/gen/getusershell.3 b/lib/libc/gen/getusershell.3
new file mode 100644
index 0000000..1559519
--- /dev/null
+++ b/lib/libc/gen/getusershell.3
@@ -0,0 +1,99 @@
+.\" $NetBSD: getusershell.3,v 1.6 1999/03/22 19:44:42 garbled Exp $
+.\"
+.\" Copyright (c) 1985, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getusershell.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd January 16, 1999
+.Dt GETUSERSHELL 3
+.Os
+.Sh NAME
+.Nm getusershell ,
+.Nm setusershell ,
+.Nm endusershell
+.Nd get valid user shells
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft char *
+.Fn getusershell void
+.Ft void
+.Fn setusershell void
+.Ft void
+.Fn endusershell void
+.Sh DESCRIPTION
+The
+.Fn getusershell
+function
+returns a pointer to a valid user shell as defined by the
+system manager in the shells database as described in
+.Xr shells 5 .
+If the shells database is not available,
+.Fn getusershell
+behaves as if
+.Pa /bin/sh
+and
+.Pa /bin/csh
+were listed.
+.Pp
+The
+.Fn getusershell
+function
+reads the next
+line (opening the file if necessary);
+.Fn setusershell
+rewinds the file;
+.Fn endusershell
+closes it.
+.Sh FILES
+.Bl -tag -width /etc/shells -compact
+.It Pa /etc/shells
+.El
+.Sh DIAGNOSTICS
+The routine
+.Fn getusershell
+returns a null pointer (0) on
+.Dv EOF .
+.Sh SEE ALSO
+.Xr nsswitch.conf 5 ,
+.Xr shells 5
+.Sh HISTORY
+The
+.Fn getusershell
+function appeared in
+.Bx 4.3 .
+.Sh BUGS
+The
+.Fn getusershell
+function leaves its result in an internal static object and returns
+a pointer to that object.
+Subsequent calls to
+.Fn getusershell
+will modify the same object.
diff --git a/lib/libc/gen/getusershell.c b/lib/libc/gen/getusershell.c
new file mode 100644
index 0000000..ce50069
--- /dev/null
+++ b/lib/libc/gen/getusershell.c
@@ -0,0 +1,269 @@
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getusershell.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+/* $NetBSD: getusershell.c,v 1.17 1999/01/25 01:09:34 lukem Exp $ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/file.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <nsswitch.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stringlist.h>
+#include <unistd.h>
+
+#ifdef HESIOD
+#include <hesiod.h>
+#endif
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/ypclnt.h>
+#include <rpcsvc/yp_prot.h>
+#endif
+#include "un-namespace.h"
+
+static const char *const *curshell;
+static StringList *sl;
+
+static const char *const *initshells(void);
+
+/*
+ * Get a list of shells from "shells" nsswitch database
+ */
+char *
+getusershell(void)
+{
+ char *ret;
+
+ if (curshell == NULL)
+ curshell = initshells();
+ /*LINTED*/
+ ret = (char *)*curshell;
+ if (ret != NULL)
+ curshell++;
+ return (ret);
+}
+
+void
+endusershell(void)
+{
+ if (sl) {
+ sl_free(sl, 1);
+ sl = NULL;
+ }
+ curshell = NULL;
+}
+
+void
+setusershell(void)
+{
+
+ curshell = initshells();
+}
+
+
+static int _local_initshells(void *, void *, va_list);
+
+/*ARGSUSED*/
+static int
+_local_initshells(rv, cb_data, ap)
+ void *rv;
+ void *cb_data;
+ va_list ap;
+{
+ char *sp, *cp;
+ FILE *fp;
+ char line[MAXPATHLEN + 2];
+
+ if (sl)
+ sl_free(sl, 1);
+ sl = sl_init();
+
+ if ((fp = fopen(_PATH_SHELLS, "r")) == NULL)
+ return NS_UNAVAIL;
+
+ cp = line;
+ while (fgets(cp, MAXPATHLEN + 1, fp) != NULL) {
+ while (*cp != '#' && *cp != '/' && *cp != '\0')
+ cp++;
+ if (*cp == '#' || *cp == '\0')
+ continue;
+ sp = cp;
+ while (!isspace(*cp) && *cp != '#' && *cp != '\0')
+ cp++;
+ *cp++ = '\0';
+ sl_add(sl, strdup(sp));
+ }
+ (void)fclose(fp);
+ return NS_SUCCESS;
+}
+
+#ifdef HESIOD
+static int _dns_initshells(void *, void *, va_list);
+
+/*ARGSUSED*/
+static int
+_dns_initshells(rv, cb_data, ap)
+ void *rv;
+ void *cb_data;
+ va_list ap;
+{
+ char shellname[] = "shells-XXXXX";
+ int hsindex, hpi, r;
+ char **hp;
+ void *context;
+
+ if (sl)
+ sl_free(sl, 1);
+ sl = sl_init();
+ r = NS_UNAVAIL;
+ if (hesiod_init(&context) == -1)
+ return (r);
+
+ for (hsindex = 0; ; hsindex++) {
+ snprintf(shellname, sizeof(shellname)-1, "shells-%d", hsindex);
+ hp = hesiod_resolve(context, shellname, "shells");
+ if (hp == NULL) {
+ if (errno == ENOENT) {
+ if (hsindex == 0)
+ r = NS_NOTFOUND;
+ else
+ r = NS_SUCCESS;
+ }
+ break;
+ } else {
+ for (hpi = 0; hp[hpi]; hpi++)
+ sl_add(sl, hp[hpi]);
+ free(hp);
+ }
+ }
+ hesiod_end(context);
+ return (r);
+}
+#endif /* HESIOD */
+
+#ifdef YP
+static int _nis_initshells(void *, void *, va_list);
+
+/*ARGSUSED*/
+static int
+_nis_initshells(rv, cb_data, ap)
+ void *rv;
+ void *cb_data;
+ va_list ap;
+{
+ static char *ypdomain;
+ char *key, *data;
+ char *lastkey;
+ int keylen, datalen;
+ int r;
+
+ if (sl)
+ sl_free(sl, 1);
+ sl = sl_init();
+
+ if (ypdomain == NULL) {
+ switch (yp_get_default_domain(&ypdomain)) {
+ case 0:
+ break;
+ case YPERR_RESRC:
+ return NS_TRYAGAIN;
+ default:
+ return NS_UNAVAIL;
+ }
+ }
+
+ /*
+ * `key' and `data' point to strings dynamically allocated by
+ * the yp_... functions.
+ * `data' is directly put into the stringlist of shells.
+ */
+ key = data = NULL;
+ if (yp_first(ypdomain, "shells", &key, &keylen, &data, &datalen))
+ return NS_UNAVAIL;
+ do {
+ data[datalen] = '\0'; /* clear trailing \n */
+ sl_add(sl, data);
+
+ lastkey = key;
+ r = yp_next(ypdomain, "shells", lastkey, keylen,
+ &key, &keylen, &data, &datalen);
+ free(lastkey);
+ } while (r == 0);
+
+ if (r == YPERR_NOMORE) {
+ /*
+ * `data' and `key' ought to be NULL - do not try to free them.
+ */
+ return NS_SUCCESS;
+ }
+
+ return NS_UNAVAIL;
+}
+#endif /* YP */
+
+static const char *const *
+initshells()
+{
+ static const ns_dtab dtab[] = {
+ NS_FILES_CB(_local_initshells, NULL)
+ NS_DNS_CB(_dns_initshells, NULL)
+ NS_NIS_CB(_nis_initshells, NULL)
+ { 0 }
+ };
+ if (sl)
+ sl_free(sl, 1);
+ sl = sl_init();
+
+ if (_nsdispatch(NULL, dtab, NSDB_SHELLS, "initshells", __nsdefaultsrc)
+ != NS_SUCCESS) {
+ if (sl)
+ sl_free(sl, 1);
+ sl = sl_init();
+ /*
+ * Local shells should NOT be added here. They should be
+ * added in /etc/shells.
+ */
+ sl_add(sl, strdup(_PATH_BSHELL));
+ sl_add(sl, strdup(_PATH_CSHELL));
+ }
+ sl_add(sl, NULL);
+
+ return (const char *const *)(sl->sl_str);
+}
diff --git a/lib/libc/gen/getutxent.3 b/lib/libc/gen/getutxent.3
new file mode 100644
index 0000000..2ea0971
--- /dev/null
+++ b/lib/libc/gen/getutxent.3
@@ -0,0 +1,478 @@
+.\" Copyright (c) 2010 Ed Schouten <ed@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 27, 2011
+.Dt GETUTXENT 3
+.Os
+.Sh NAME
+.Nm endutxent ,
+.Nm getutxent ,
+.Nm getutxid ,
+.Nm getutxline ,
+.Nm getutxuser ,
+.Nm pututxline ,
+.Nm setutxdb ,
+.Nm setutxent
+.Nd user accounting database functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In utmpx.h
+.Ft void
+.Fn endutxent "void"
+.Ft struct utmpx *
+.Fn getutxent "void"
+.Ft struct utmpx *
+.Fn getutxid "const struct utmpx *id"
+.Ft struct utmpx *
+.Fn getutxline "const struct utmpx *line"
+.Ft struct utmpx *
+.Fn getutxuser "const char *user"
+.Ft struct utmpx *
+.Fn pututxline "const struct utmpx *utmpx"
+.Ft int
+.Fn setutxdb "int type" "const char *file"
+.Ft void
+.Fn setutxent "void"
+.Sh DESCRIPTION
+These functions operate on the user accounting database which stores
+records of various system activities, such as user login and logouts,
+but also system startups and shutdowns and modifications to the system's
+clock.
+The system stores these records in three databases, each having a
+different purpose:
+.Bl -tag -width indent
+.It Pa /var/run/utx.active
+Log of currently active user login sessions.
+This file is similar to the traditional
+.Pa utmp
+file.
+This file only contains process related entries, such as user login and
+logout records.
+.It Pa /var/log/utx.lastlogin
+Log of last user login entries per user.
+This file is similar to the traditional
+.Pa lastlog
+file.
+This file only contains user login records for users who have at least
+logged in once.
+.It Pa /var/log/utx.log
+Log of all entries, sorted by date of addition.
+This file is similar to the traditional
+.Pa wtmp
+file.
+This file may contain any type of record described below.
+.El
+.Pp
+Each entry in these databases is defined by the structure
+.Vt utmpx
+found in the include file
+.In utmpx.h :
+.Bd -literal -offset indent
+struct utmpx {
+ short ut_type; /* Type of entry. */
+ struct timeval ut_tv; /* Time entry was made. */
+ char ut_id[]; /* Record identifier. */
+ pid_t ut_pid; /* Process ID. */
+ char ut_user[]; /* User login name. */
+ char ut_line[]; /* Device name. */
+ char ut_host[]; /* Remote hostname. */
+};
+.Ed
+.Pp
+The
+.Fa ut_type
+field indicates the type of the log entry, which can have one of the
+following values:
+.Bl -tag -width LOGIN_PROCESS
+.It Dv EMPTY
+No valid user accounting information.
+.It Dv BOOT_TIME
+Identifies time of system boot.
+.It Dv SHUTDOWN_TIME
+Identifies time of system shutdown.
+.It Dv OLD_TIME
+Identifies time when system clock changed.
+.It Dv NEW_TIME
+Identifies time after system clock changed.
+.It Dv USER_PROCESS
+Identifies a process.
+.It Dv INIT_PROCESS
+Identifies a process spawned by the init process.
+.It Dv LOGIN_PROCESS
+Identifies the session leader of a logged-in user.
+.It Dv DEAD_PROCESS
+Identifies a session leader who has exited.
+.El
+.Pp
+Entries of type
+.Dv INIT_PROCESS
+and
+.Dv LOGIN_PROCESS
+are not processed by this implementation.
+.Pp
+Other fields inside the structure are:
+.Bl -tag -width ut_user
+.It Fa ut_tv
+The time the event occurred.
+This field is used for all types of entries, except
+.Dv EMPTY .
+.It Fa ut_id
+An identifier that is used to refer to the entry.
+This identifier can be used to remove or replace a login entry by
+writing a new entry to the database containing the same value for
+.Fa ut_id .
+This field is only applicable to entries of type
+.Dv USER_PROCESS ,
+.Dv INIT_PROCESS ,
+.Dv LOGIN_PROCESS
+and
+.Dv DEAD_PROCESS .
+.It Fa ut_pid
+The process identifier of the session leader of the login session.
+This field is only applicable to entries of type
+.Dv USER_PROCESS ,
+.Dv INIT_PROCESS ,
+.Dv LOGIN_PROCESS
+and
+.Dv DEAD_PROCESS .
+.It Fa ut_user
+The user login name corresponding with the login session.
+This field is only applicable to entries of type
+.Dv USER_PROCESS
+and
+.Dv INIT_PROCESS .
+For
+.Dv INIT_PROCESS
+entries this entry typically contains the name of the login process.
+.It Fa ut_line
+The name of the TTY character device, without the leading
+.Pa /dev/
+prefix, corresponding with the device used to facilitate the user login
+session.
+If no TTY character device is used, this field is left blank.
+This field is only applicable to entries of type
+.Dv USER_PROCESS
+and
+.Dv LOGIN_PROCESS .
+.It Fa ut_host
+The network hostname of the remote system, connecting to perform a user
+login.
+If the user login session is not performed across a network, this field
+is left blank.
+This field is only applicable to entries of type
+.Dv USER_PROCESS .
+.El
+.Pp
+This implementation guarantees all inapplicable fields are discarded.
+The
+.Fa ut_user ,
+.Fa ut_line
+and
+.Fa ut_host
+fields of the structure returned by the library functions are also
+guaranteed to be null-terminated in this implementation.
+.Pp
+The
+.Fn getutxent
+function can be used to read the next entry from the user accounting
+database.
+.Pp
+The
+.Fn getutxid
+function searches for the next entry in the database of which the
+behaviour is based on the
+.Fa ut_type
+field of
+.Fa id .
+If
+.Fa ut_type
+has a value of
+.Dv BOOT_TIME ,
+.Dv SHUTDOWN_TIME ,
+.Dv OLD_TIME
+or
+.Dv NEW_TIME ,
+it will return the next entry whose
+.Fa ut_type
+has an equal value.
+If
+.Fa ut_type
+has a value of
+.Dv USER_PROCESS ,
+.Dv INIT_PROCESS ,
+.Dv LOGIN_PROCESS
+or
+.Dv DEAD_PROCESS ,
+it will return the next entry whose
+.Fa ut_type
+has one of the previously mentioned values and whose
+.Fa ut_id
+is equal.
+.Pp
+The
+.Fn getutxline
+function searches for the next entry in the database whose
+.Fa ut_type
+has a value of
+.Dv USER_PROCESS
+or
+.Dv LOGIN_PROCESS
+and whose
+.Fa ut_line
+is equal to the same field in
+.Fa line .
+.Pp
+The
+.Fn getutxuser
+function searches for the next entry in the database whose
+.Fa ut_type
+has a value of
+.Dv USER_PROCESS
+and whose
+.Fa ut_user
+is equal to
+.Fa user .
+.Pp
+The previously mentioned functions will automatically try to open the
+user accounting database if not already done so.
+The
+.Fn setutxdb
+and
+.Fn setutxent
+functions allow the database to be opened manually, causing the offset
+within the user accounting database to be rewound.
+The
+.Fn endutxent
+function closes the database.
+.Pp
+The
+.Fn setutxent
+database always opens the active sessions database.
+The
+.Fn setutxdb
+function opens the database identified by
+.Fa type ,
+whose value is either
+.Dv UTXDB_ACTIVE ,
+.Dv UTXDB_LASTLOGIN
+or
+.Dv UTXDB_LOG .
+It will open a custom file with filename
+.Fa file
+instead of the system-default if
+.Fa file
+is not null.
+Care must be taken that when using a custom filename,
+.Fa type
+still has to match with the actual format, since each database may use
+its own file format.
+.Pp
+The
+.Fn pututxline
+function writes record
+.Fa utmpx
+to the system-default user accounting databases.
+The value of
+.Fa ut_type
+determines which databases are modified.
+.Pp
+Entries of type
+.Dv SHUTDOWN_TIME ,
+.Dv OLD_TIME
+and
+.Dv NEW_TIME
+will only be written to
+.Pa /var/log/utx.log .
+.Pp
+Entries of type
+.Dv USER_PROCESS
+will also be written to
+.Pa /var/run/utx.active
+and
+.Pa /var/log/utx.lastlogin .
+.Pp
+Entries of type
+.Dv DEAD_PROCESS
+will only be written to
+.Pa /var/log/utx.log
+and
+.Pa /var/run/utx.active
+if a corresponding
+.Dv USER_PROCESS ,
+.Dv INIT_PROCESS
+or
+.Dv LOGIN_PROCESS
+entry whose
+.Fa ut_id
+is equal has been found in the latter.
+.Pp
+In addition, entries of type
+.Dv BOOT_TIME
+and
+.Dv SHUTDOWN_TIME
+will cause all existing entries in
+.Pa /var/run/utx.active
+to be discarded.
+.Pp
+All entries whose type has not been mentioned previously, are discarded
+by this implementation of
+.Fn pututxline .
+This implementation also ignores the value of
+.Fa ut_tv .
+.Sh RETURN VALUES
+The
+.Fn getutxent ,
+.Fn getutxid ,
+.Fn getutxline ,
+and
+.Fn getutxuser
+functions return a pointer to an
+.Vt utmpx
+structure that matches the mentioned constraints on success or
+.Dv NULL
+when reaching the end-of-file or when an error occurs.
+.Pp
+The
+.Fn pututxline
+function returns a pointer to an
+.Vt utmpx
+structure containing a copy of the structure written to disk upon
+success.
+It returns
+.Dv NULL
+when the provided
+.Vt utmpx
+is invalid, or
+.Fa ut_type
+has a value of
+.Dv DEAD_PROCESS
+and an entry with an identifier with a value equal to the field
+.Fa ut_id
+was not found; the global variable
+.Va errno
+is set to indicate the error.
+.Pp
+The
+.Fn setutxdb
+function returns 0 if the user accounting database was opened
+successfully.
+Otherwise, -1 is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+In addition to the error conditions described in
+.Xr open 2 ,
+.Xr fdopen 3 ,
+.Xr fopen 3 ,
+.Xr fseek 3 ,
+the
+.Fn pututxline
+function can generate the following errors:
+.Bl -tag -width Er
+.It Bq Er ESRCH
+The value of
+.Fa ut_type
+is DEAD_PROCESS, and the process entry could not be found.
+.It Bq Er EINVAL
+The value of
+.Fa ut_type
+is not supported by this implementation.
+.El
+In addition to the error conditions described in
+.Xr fopen 3 ,
+the
+.Fn setutxdb
+function can generate the following errors:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa type
+argument contains a value not supported by this implementation.
+.It Bq Er EFTYPE
+The file format is invalid.
+.El
+.Sh SEE ALSO
+.Xr last 1 ,
+.Xr write 1 ,
+.Xr getpid 2 ,
+.Xr gettimeofday 2 ,
+.Xr tty 4 ,
+.Xr ac 8 ,
+.Xr newsyslog 8 ,
+.Xr utx 8
+.Sh STANDARDS
+The
+.Fn endutxent ,
+.Fn getutxent ,
+.Fn getutxid ,
+.Fn getutxline
+and
+.Fn setutxent
+functions are expected to conform to
+.St -p1003.1-2008 .
+.Pp
+The
+.Fn pututxline
+function deviates from the standard by writing its records to multiple
+database files, depending on its
+.Fa ut_type .
+This prevents the need for special utility functions to update the other
+databases, such as the
+.Fn updlastlogx
+and
+.Fn updwtmpx
+functions which are available in other implementations.
+It also tries to replace
+.Dv DEAD_PROCESS
+entries in the active sessions database when storing
+.Dv USER_PROCESS
+entries and no entry with the same value for
+.Fa ut_id
+has been found.
+The standard always requires a new entry to be allocated, which could
+cause an unbounded growth of the database.
+.Pp
+The
+.Fn getutxuser
+and
+.Fn setutxdb
+functions,
+the
+.Fa ut_host
+field of the
+.Vt utmpx
+structure and
+.Dv SHUTDOWN_TIME
+are extensions.
+.Sh HISTORY
+These functions appeared in
+.Fx 9.0 .
+They replaced the
+.In utmp.h
+interface.
+.Sh AUTHORS
+.An Ed Schouten Aq ed@FreeBSD.org
diff --git a/lib/libc/gen/getutxent.c b/lib/libc/gen/getutxent.c
new file mode 100644
index 0000000..a2e938a
--- /dev/null
+++ b/lib/libc/gen/getutxent.c
@@ -0,0 +1,235 @@
+/*-
+ * Copyright (c) 2010 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/endian.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <utmpx.h>
+#include "utxdb.h"
+#include "un-namespace.h"
+
+#ifdef __NO_TLS
+static FILE *uf = NULL;
+static int udb;
+#else
+static _Thread_local FILE *uf = NULL;
+static _Thread_local int udb;
+#endif
+
+int
+setutxdb(int db, const char *file)
+{
+ struct stat sb;
+
+ switch (db) {
+ case UTXDB_ACTIVE:
+ if (file == NULL)
+ file = _PATH_UTX_ACTIVE;
+ break;
+ case UTXDB_LASTLOGIN:
+ if (file == NULL)
+ file = _PATH_UTX_LASTLOGIN;
+ break;
+ case UTXDB_LOG:
+ if (file == NULL)
+ file = _PATH_UTX_LOG;
+ break;
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (uf != NULL)
+ fclose(uf);
+ uf = fopen(file, "r");
+ if (uf == NULL)
+ return (-1);
+
+ if (db != UTXDB_LOG) {
+ /* Safety check: never use broken files. */
+ if (_fstat(fileno(uf), &sb) != -1 &&
+ sb.st_size % sizeof(struct futx) != 0) {
+ fclose(uf);
+ uf = NULL;
+ errno = EFTYPE;
+ return (-1);
+ }
+ /* Prevent reading of partial records. */
+ (void)setvbuf(uf, NULL, _IOFBF,
+ rounddown(BUFSIZ, sizeof(struct futx)));
+ }
+
+ udb = db;
+ return (0);
+}
+
+void
+setutxent(void)
+{
+
+ setutxdb(UTXDB_ACTIVE, NULL);
+}
+
+void
+endutxent(void)
+{
+
+ if (uf != NULL) {
+ fclose(uf);
+ uf = NULL;
+ }
+}
+
+static int
+getfutxent(struct futx *fu)
+{
+
+ if (uf == NULL)
+ setutxent();
+ if (uf == NULL)
+ return (-1);
+
+ if (udb == UTXDB_LOG) {
+ uint16_t len;
+
+ if (fread(&len, sizeof(len), 1, uf) != 1)
+ return (-1);
+ len = be16toh(len);
+ if (len > sizeof *fu) {
+ /* Forward compatibility. */
+ if (fread(fu, sizeof(*fu), 1, uf) != 1)
+ return (-1);
+ fseek(uf, len - sizeof(*fu), SEEK_CUR);
+ } else {
+ /* Partial record. */
+ memset(fu, 0, sizeof(*fu));
+ if (fread(fu, len, 1, uf) != 1)
+ return (-1);
+ }
+ } else {
+ if (fread(fu, sizeof(*fu), 1, uf) != 1)
+ return (-1);
+ }
+ return (0);
+}
+
+struct utmpx *
+getutxent(void)
+{
+ struct futx fu;
+
+ if (getfutxent(&fu) != 0)
+ return (NULL);
+ return (futx_to_utx(&fu));
+}
+
+struct utmpx *
+getutxid(const struct utmpx *id)
+{
+ struct futx fu;
+
+ for (;;) {
+ if (getfutxent(&fu) != 0)
+ return (NULL);
+
+ switch (fu.fu_type) {
+ case USER_PROCESS:
+ case INIT_PROCESS:
+ case LOGIN_PROCESS:
+ case DEAD_PROCESS:
+ switch (id->ut_type) {
+ case USER_PROCESS:
+ case INIT_PROCESS:
+ case LOGIN_PROCESS:
+ case DEAD_PROCESS:
+ if (memcmp(fu.fu_id, id->ut_id,
+ MIN(sizeof(fu.fu_id), sizeof(id->ut_id))) ==
+ 0)
+ goto found;
+ }
+ break;
+ default:
+ if (fu.fu_type == id->ut_type)
+ goto found;
+ break;
+ }
+ }
+
+found:
+ return (futx_to_utx(&fu));
+}
+
+struct utmpx *
+getutxline(const struct utmpx *line)
+{
+ struct futx fu;
+
+ for (;;) {
+ if (getfutxent(&fu) != 0)
+ return (NULL);
+
+ switch (fu.fu_type) {
+ case USER_PROCESS:
+ case LOGIN_PROCESS:
+ if (strncmp(fu.fu_line, line->ut_line,
+ MIN(sizeof(fu.fu_line), sizeof(line->ut_line))) ==
+ 0)
+ goto found;
+ break;
+ }
+ }
+
+found:
+ return (futx_to_utx(&fu));
+}
+
+struct utmpx *
+getutxuser(const char *user)
+{
+ struct futx fu;
+
+ for (;;) {
+ if (getfutxent(&fu) != 0)
+ return (NULL);
+
+ switch (fu.fu_type) {
+ case USER_PROCESS:
+ if (strncmp(fu.fu_user, user, sizeof(fu.fu_user)) == 0)
+ goto found;
+ break;
+ }
+ }
+
+found:
+ return (futx_to_utx(&fu));
+}
diff --git a/lib/libc/gen/getvfsbyname.3 b/lib/libc/gen/getvfsbyname.3
new file mode 100644
index 0000000..f2a5965
--- /dev/null
+++ b/lib/libc/gen/getvfsbyname.3
@@ -0,0 +1,122 @@
+.\" Copyright (c) 1995
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)kvm_getvfsbyname.3 8.3 (Berkeley) 5/4/95
+.\" $FreeBSD$
+.\"
+.Dd April 5, 2007
+.Dt GETVFSBYNAME 3
+.Os
+.Sh NAME
+.Nm getvfsbyname
+.Nd get information about a file system
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/param.h
+.In sys/mount.h
+.Ft int
+.Fn getvfsbyname "const char *name" "struct xvfsconf *vfc"
+.Sh DESCRIPTION
+The
+.Fn getvfsbyname
+function provides access to information about a
+file system module that is configured in the kernel.
+If successful,
+the requested file system
+.Fa xvfsconf
+is returned in the location pointed to by
+.Fa vfc .
+The fields in a
+.Dq Li struct xvfsconf
+are defined as follows:
+.Pp
+.Bl -tag -compact -width vfc_refcount
+.It vfc_name
+the name of the file system
+.It vfc_typenum
+the file system type number assigned by the kernel
+.It vfc_refcount
+the number of active mount points using the file system
+.It vfc_flags
+flag bits, as described below
+.El
+.Pp
+The flags are defined as follows:
+.Pp
+.Bl -tag -width VFCF_DELEGADMIN -compact
+.It Dv VFCF_STATIC
+statically compiled into kernel
+.It Dv VFCF_NETWORK
+may get data over the network
+.It Dv VFCF_READONLY
+writes are not implemented
+.It Dv VFCF_SYNTHETIC
+data does not represent real files
+.It Dv VFCF_LOOPBACK
+aliases some other mounted FS
+.It Dv VFCF_UNICODE
+stores file names as Unicode
+.It Dv VFCF_JAIL
+can be mounted from within a jail if
+.Va security.jail.mount_allowed
+sysctl is set to
+.Dv 1
+.It Dv VFCF_DELEGADMIN
+supports delegated administration if
+.Va vfs.usermount
+sysctl is set to
+.Dv 1
+.El
+.Sh RETURN VALUES
+.Rv -std getvfsbyname
+.Sh ERRORS
+The following errors may be reported:
+.Bl -tag -width Er
+.It Bq Er EFAULT
+The
+.Fa vfc
+argument
+points to an invalid address.
+.It Bq Er ENOENT
+The
+.Fa name
+argument
+specifies a file system that is unknown or not configured in the kernel.
+.El
+.Sh SEE ALSO
+.Xr jail 2 ,
+.Xr mount 2 ,
+.Xr sysctl 3 ,
+.Xr jail 8 ,
+.Xr mount 8 ,
+.Xr sysctl 8
+.Sh HISTORY
+A variant of the
+.Fn getvfsbyname
+function first appeared in
+.Fx 2.0 .
diff --git a/lib/libc/gen/getvfsbyname.c b/lib/libc/gen/getvfsbyname.c
new file mode 100644
index 0000000..0d896bb
--- /dev/null
+++ b/lib/libc/gen/getvfsbyname.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1995
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)kvm_getvfsbyname.c 8.1 (Berkeley) 4/3/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/sysctl.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * Given a filesystem name, determine if it is resident in the kernel,
+ * and if it is resident, return its xvfsconf structure.
+ */
+int
+getvfsbyname(fsname, vfcp)
+ const char *fsname;
+ struct xvfsconf *vfcp;
+{
+ struct xvfsconf *xvfsp;
+ size_t buflen;
+ int cnt, i;
+
+ if (sysctlbyname("vfs.conflist", NULL, &buflen, NULL, 0) < 0)
+ return (-1);
+ xvfsp = malloc(buflen);
+ if (xvfsp == NULL)
+ return (-1);
+ if (sysctlbyname("vfs.conflist", xvfsp, &buflen, NULL, 0) < 0) {
+ free(xvfsp);
+ return (-1);
+ }
+ cnt = buflen / sizeof(struct xvfsconf);
+ for (i = 0; i < cnt; i++) {
+ if (strcmp(fsname, xvfsp[i].vfc_name) == 0) {
+ memcpy(vfcp, xvfsp + i, sizeof(struct xvfsconf));
+ free(xvfsp);
+ return (0);
+ }
+ }
+ free(xvfsp);
+ errno = ENOENT;
+ return (-1);
+}
diff --git a/lib/libc/gen/glob.3 b/lib/libc/gen/glob.3
new file mode 100644
index 0000000..468a73b
--- /dev/null
+++ b/lib/libc/gen/glob.3
@@ -0,0 +1,471 @@
+.\" Copyright (c) 1989, 1991, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Guido van Rossum.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)glob.3 8.3 (Berkeley) 4/16/94
+.\" $FreeBSD$
+.\"
+.Dd December 20, 2011
+.Dt GLOB 3
+.Os
+.Sh NAME
+.Nm glob ,
+.Nm globfree
+.Nd generate pathnames matching a pattern
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In glob.h
+.Ft int
+.Fn glob "const char * restrict pattern" "int flags" "int (*errfunc)(const char *, int)" "glob_t * restrict pglob"
+.Ft void
+.Fn globfree "glob_t *pglob"
+.Sh DESCRIPTION
+The
+.Fn glob
+function
+is a pathname generator that implements the rules for file name pattern
+matching used by the shell.
+.Pp
+The include file
+.In glob.h
+defines the structure type
+.Fa glob_t ,
+which contains at least the following fields:
+.Bd -literal
+typedef struct {
+ size_t gl_pathc; /* count of total paths so far */
+ size_t gl_matchc; /* count of paths matching pattern */
+ size_t gl_offs; /* reserved at beginning of gl_pathv */
+ int gl_flags; /* returned flags */
+ char **gl_pathv; /* list of paths matching pattern */
+} glob_t;
+.Ed
+.Pp
+The argument
+.Fa pattern
+is a pointer to a pathname pattern to be expanded.
+The
+.Fn glob
+argument
+matches all accessible pathnames against the pattern and creates
+a list of the pathnames that match.
+In order to have access to a pathname,
+.Fn glob
+requires search permission on every component of a path except the last
+and read permission on each directory of any filename component of
+.Fa pattern
+that contains any of the special characters
+.Ql * ,
+.Ql ?\&
+or
+.Ql \&[ .
+.Pp
+The
+.Fn glob
+argument
+stores the number of matched pathnames into the
+.Fa gl_pathc
+field, and a pointer to a list of pointers to pathnames into the
+.Fa gl_pathv
+field.
+The first pointer after the last pathname is
+.Dv NULL .
+If the pattern does not match any pathnames, the returned number of
+matched paths is set to zero.
+.Pp
+It is the caller's responsibility to create the structure pointed to by
+.Fa pglob .
+The
+.Fn glob
+function allocates other space as needed, including the memory pointed
+to by
+.Fa gl_pathv .
+.Pp
+The argument
+.Fa flags
+is used to modify the behavior of
+.Fn glob .
+The value of
+.Fa flags
+is the bitwise inclusive
+.Tn OR
+of any of the following
+values defined in
+.In glob.h :
+.Bl -tag -width GLOB_ALTDIRFUNC
+.It Dv GLOB_APPEND
+Append pathnames generated to the ones from a previous call (or calls)
+to
+.Fn glob .
+The value of
+.Fa gl_pathc
+will be the total matches found by this call and the previous call(s).
+The pathnames are appended to, not merged with the pathnames returned by
+the previous call(s).
+Between calls, the caller must not change the setting of the
+.Dv GLOB_DOOFFS
+flag, nor change the value of
+.Fa gl_offs
+when
+.Dv GLOB_DOOFFS
+is set, nor (obviously) call
+.Fn globfree
+for
+.Fa pglob .
+.It Dv GLOB_DOOFFS
+Make use of the
+.Fa gl_offs
+field.
+If this flag is set,
+.Fa gl_offs
+is used to specify how many
+.Dv NULL
+pointers to prepend to the beginning
+of the
+.Fa gl_pathv
+field.
+In other words,
+.Fa gl_pathv
+will point to
+.Fa gl_offs
+.Dv NULL
+pointers,
+followed by
+.Fa gl_pathc
+pathname pointers, followed by a
+.Dv NULL
+pointer.
+.It Dv GLOB_ERR
+Causes
+.Fn glob
+to return when it encounters a directory that it cannot open or read.
+Ordinarily,
+.Fn glob
+continues to find matches.
+.It Dv GLOB_MARK
+Each pathname that is a directory that matches
+.Fa pattern
+has a slash
+appended.
+.It Dv GLOB_NOCHECK
+If
+.Fa pattern
+does not match any pathname, then
+.Fn glob
+returns a list
+consisting of only
+.Fa pattern ,
+with the number of total pathnames set to 1, and the number of matched
+pathnames set to 0.
+The effect of backslash escaping is present in the pattern returned.
+.It Dv GLOB_NOESCAPE
+By default, a backslash
+.Pq Ql \e
+character is used to escape the following character in the pattern,
+avoiding any special interpretation of the character.
+If
+.Dv GLOB_NOESCAPE
+is set, backslash escaping is disabled.
+.It Dv GLOB_NOSORT
+By default, the pathnames are sorted in ascending
+.Tn ASCII
+order;
+this flag prevents that sorting (speeding up
+.Fn glob ) .
+.El
+.Pp
+The following values may also be included in
+.Fa flags ,
+however, they are non-standard extensions to
+.St -p1003.2 .
+.Bl -tag -width GLOB_ALTDIRFUNC
+.It Dv GLOB_ALTDIRFUNC
+The following additional fields in the pglob structure have been
+initialized with alternate functions for glob to use to open, read,
+and close directories and to get stat information on names found
+in those directories.
+.Bd -literal
+void *(*gl_opendir)(const char * name);
+struct dirent *(*gl_readdir)(void *);
+void (*gl_closedir)(void *);
+int (*gl_lstat)(const char *name, struct stat *st);
+int (*gl_stat)(const char *name, struct stat *st);
+.Ed
+.Pp
+This extension is provided to allow programs such as
+.Xr restore 8
+to provide globbing from directories stored on tape.
+.It Dv GLOB_BRACE
+Pre-process the pattern string to expand
+.Ql {pat,pat,...}
+strings like
+.Xr csh 1 .
+The pattern
+.Ql {}
+is left unexpanded for historical reasons (and
+.Xr csh 1
+does the same thing to
+ease typing
+of
+.Xr find 1
+patterns).
+.It Dv GLOB_MAGCHAR
+Set by the
+.Fn glob
+function if the pattern included globbing characters.
+See the description of the usage of the
+.Fa gl_matchc
+structure member for more details.
+.It Dv GLOB_NOMAGIC
+Is the same as
+.Dv GLOB_NOCHECK
+but it only appends the
+.Fa pattern
+if it does not contain any of the special characters ``*'', ``?'' or ``[''.
+.Dv GLOB_NOMAGIC
+is provided to simplify implementing the historic
+.Xr csh 1
+globbing behavior and should probably not be used anywhere else.
+.It Dv GLOB_TILDE
+Expand patterns that start with
+.Ql ~
+to user name home directories.
+.It Dv GLOB_LIMIT
+Limit the total number of returned pathnames to the value provided in
+.Fa gl_matchc
+(default
+.Dv ARG_MAX ) .
+This option should be set for programs
+that can be coerced into a denial of service attack
+via patterns that expand to a very large number of matches,
+such as a long string of
+.Ql */../*/.. .
+.El
+.Pp
+If, during the search, a directory is encountered that cannot be opened
+or read and
+.Fa errfunc
+is
+.Pf non- Dv NULL ,
+.Fn glob
+calls
+.Fa \*(lp*errfunc\*(rp Ns ( Fa path , errno ) .
+This may be unintuitive: a pattern like
+.Ql */Makefile
+will try to
+.Xr stat 2
+.Ql foo/Makefile
+even if
+.Ql foo
+is not a directory, resulting in a
+call to
+.Fa errfunc .
+The error routine can suppress this action by testing for
+.Er ENOENT
+and
+.Er ENOTDIR ;
+however, the
+.Dv GLOB_ERR
+flag will still cause an immediate
+return when this happens.
+.Pp
+If
+.Fa errfunc
+returns non-zero,
+.Fn glob
+stops the scan and returns
+.Dv GLOB_ABORTED
+after setting
+.Fa gl_pathc
+and
+.Fa gl_pathv
+to reflect any paths already matched.
+This also happens if an error is encountered and
+.Dv GLOB_ERR
+is set in
+.Fa flags ,
+regardless of the return value of
+.Fa errfunc ,
+if called.
+If
+.Dv GLOB_ERR
+is not set and either
+.Fa errfunc
+is
+.Dv NULL
+or
+.Fa errfunc
+returns zero, the error is ignored.
+.Pp
+The
+.Fn globfree
+function frees any space associated with
+.Fa pglob
+from a previous call(s) to
+.Fn glob .
+.Sh RETURN VALUES
+On successful completion,
+.Fn glob
+returns zero.
+In addition the fields of
+.Fa pglob
+contain the values described below:
+.Bl -tag -width GLOB_NOCHECK
+.It Fa gl_pathc
+contains the total number of matched pathnames so far.
+This includes other matches from previous invocations of
+.Fn glob
+if
+.Dv GLOB_APPEND
+was specified.
+.It Fa gl_matchc
+contains the number of matched pathnames in the current invocation of
+.Fn glob .
+.It Fa gl_flags
+contains a copy of the
+.Fa flags
+argument with the bit
+.Dv GLOB_MAGCHAR
+set if
+.Fa pattern
+contained any of the special characters ``*'', ``?'' or ``['', cleared
+if not.
+.It Fa gl_pathv
+contains a pointer to a
+.Dv NULL Ns -terminated
+list of matched pathnames.
+However, if
+.Fa gl_pathc
+is zero, the contents of
+.Fa gl_pathv
+are undefined.
+.El
+.Pp
+If
+.Fn glob
+terminates due to an error, it sets errno and returns one of the
+following non-zero constants, which are defined in the include
+file
+.In glob.h :
+.Bl -tag -width GLOB_NOCHECK
+.It Dv GLOB_NOSPACE
+An attempt to allocate memory failed, or if
+.Fa errno
+was 0
+.Dv GLOB_LIMIT
+was specified in the flags and
+.Fa pglob\->gl_matchc
+or more patterns were matched.
+.It Dv GLOB_ABORTED
+The scan was stopped because an error was encountered and either
+.Dv GLOB_ERR
+was set or
+.Fa \*(lp*errfunc\*(rp\*(lp\*(rp
+returned non-zero.
+.It Dv GLOB_NOMATCH
+The pattern did not match a pathname and
+.Dv GLOB_NOCHECK
+was not set.
+.El
+.Pp
+The arguments
+.Fa pglob\->gl_pathc
+and
+.Fa pglob\->gl_pathv
+are still set as specified above.
+.Sh EXAMPLES
+A rough equivalent of
+.Ql "ls -l *.c *.h"
+can be obtained with the
+following code:
+.Bd -literal -offset indent
+glob_t g;
+
+g.gl_offs = 2;
+glob("*.c", GLOB_DOOFFS, NULL, &g);
+glob("*.h", GLOB_DOOFFS | GLOB_APPEND, NULL, &g);
+g.gl_pathv[0] = "ls";
+g.gl_pathv[1] = "-l";
+execvp("ls", g.gl_pathv);
+.Ed
+.Sh SEE ALSO
+.Xr sh 1 ,
+.Xr fnmatch 3 ,
+.Xr regex 3
+.Sh STANDARDS
+The current implementation of the
+.Fn glob
+function
+.Em does not
+conform to
+.St -p1003.2 .
+Collating symbol expressions, equivalence class expressions and
+character class expressions are not supported.
+.Pp
+The flags
+.Dv GLOB_ALTDIRFUNC ,
+.Dv GLOB_BRACE ,
+.Dv GLOB_LIMIT ,
+.Dv GLOB_MAGCHAR ,
+.Dv GLOB_NOMAGIC ,
+and
+.Dv GLOB_TILDE ,
+and the fields
+.Fa gl_matchc
+and
+.Fa gl_flags
+are extensions to the
+.Tn POSIX
+standard and
+should not be used by applications striving for strict
+conformance.
+.Sh HISTORY
+The
+.Fn glob
+and
+.Fn globfree
+functions first appeared in
+.Bx 4.4 .
+.Sh BUGS
+Patterns longer than
+.Dv MAXPATHLEN
+may cause unchecked errors.
+.Pp
+The
+.Fn glob
+argument
+may fail and set errno for any of the errors specified for the
+library routines
+.Xr stat 2 ,
+.Xr closedir 3 ,
+.Xr opendir 3 ,
+.Xr readdir 3 ,
+.Xr malloc 3 ,
+and
+.Xr free 3 .
diff --git a/lib/libc/gen/glob.c b/lib/libc/gen/glob.c
new file mode 100644
index 0000000..211b535
--- /dev/null
+++ b/lib/libc/gen/glob.c
@@ -0,0 +1,918 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Guido van Rossum.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)glob.c 8.3 (Berkeley) 10/13/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * glob(3) -- a superset of the one defined in POSIX 1003.2.
+ *
+ * The [!...] convention to negate a range is supported (SysV, Posix, ksh).
+ *
+ * Optional extra services, controlled by flags not defined by POSIX:
+ *
+ * GLOB_QUOTE:
+ * Escaping convention: \ inhibits any special meaning the following
+ * character might have (except \ at end of string is retained).
+ * GLOB_MAGCHAR:
+ * Set in gl_flags if pattern contained a globbing character.
+ * GLOB_NOMAGIC:
+ * Same as GLOB_NOCHECK, but it will only append pattern if it did
+ * not contain any magic characters. [Used in csh style globbing]
+ * GLOB_ALTDIRFUNC:
+ * Use alternately specified directory access functions.
+ * GLOB_TILDE:
+ * expand ~user/foo to the /home/dir/of/user/foo
+ * GLOB_BRACE:
+ * expand {1,2}{a,b} to 1a 1b 2a 2b
+ * gl_matchc:
+ * Number of matches in the current invocation of glob.
+ */
+
+/*
+ * Some notes on multibyte character support:
+ * 1. Patterns with illegal byte sequences match nothing - even if
+ * GLOB_NOCHECK is specified.
+ * 2. Illegal byte sequences in filenames are handled by treating them as
+ * single-byte characters with a value of the first byte of the sequence
+ * cast to wchar_t.
+ * 3. State-dependent encodings are not currently supported.
+ */
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <dirent.h>
+#include <errno.h>
+#include <glob.h>
+#include <limits.h>
+#include <pwd.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wchar.h>
+
+#include "collate.h"
+
+#define DOLLAR '$'
+#define DOT '.'
+#define EOS '\0'
+#define LBRACKET '['
+#define NOT '!'
+#define QUESTION '?'
+#define QUOTE '\\'
+#define RANGE '-'
+#define RBRACKET ']'
+#define SEP '/'
+#define STAR '*'
+#define TILDE '~'
+#define UNDERSCORE '_'
+#define LBRACE '{'
+#define RBRACE '}'
+#define SLASH '/'
+#define COMMA ','
+
+#ifndef DEBUG
+
+#define M_QUOTE 0x8000000000ULL
+#define M_PROTECT 0x4000000000ULL
+#define M_MASK 0xffffffffffULL
+#define M_CHAR 0x00ffffffffULL
+
+typedef uint_fast64_t Char;
+
+#else
+
+#define M_QUOTE 0x80
+#define M_PROTECT 0x40
+#define M_MASK 0xff
+#define M_CHAR 0x7f
+
+typedef char Char;
+
+#endif
+
+
+#define CHAR(c) ((Char)((c)&M_CHAR))
+#define META(c) ((Char)((c)|M_QUOTE))
+#define M_ALL META('*')
+#define M_END META(']')
+#define M_NOT META('!')
+#define M_ONE META('?')
+#define M_RNG META('-')
+#define M_SET META('[')
+#define ismeta(c) (((c)&M_QUOTE) != 0)
+
+
+static int compare(const void *, const void *);
+static int g_Ctoc(const Char *, char *, size_t);
+static int g_lstat(Char *, struct stat *, glob_t *);
+static DIR *g_opendir(Char *, glob_t *);
+static const Char *g_strchr(const Char *, wchar_t);
+#ifdef notdef
+static Char *g_strcat(Char *, const Char *);
+#endif
+static int g_stat(Char *, struct stat *, glob_t *);
+static int glob0(const Char *, glob_t *, size_t *);
+static int glob1(Char *, glob_t *, size_t *);
+static int glob2(Char *, Char *, Char *, Char *, glob_t *, size_t *);
+static int glob3(Char *, Char *, Char *, Char *, Char *, glob_t *, size_t *);
+static int globextend(const Char *, glob_t *, size_t *);
+static const Char *
+ globtilde(const Char *, Char *, size_t, glob_t *);
+static int globexp1(const Char *, glob_t *, size_t *);
+static int globexp2(const Char *, const Char *, glob_t *, int *, size_t *);
+static int match(Char *, Char *, Char *);
+#ifdef DEBUG
+static void qprintf(const char *, Char *);
+#endif
+
+int
+glob(const char * __restrict pattern, int flags,
+ int (*errfunc)(const char *, int), glob_t * __restrict pglob)
+{
+ const char *patnext;
+ size_t limit;
+ Char *bufnext, *bufend, patbuf[MAXPATHLEN], prot;
+ mbstate_t mbs;
+ wchar_t wc;
+ size_t clen;
+
+ patnext = pattern;
+ if (!(flags & GLOB_APPEND)) {
+ pglob->gl_pathc = 0;
+ pglob->gl_pathv = NULL;
+ if (!(flags & GLOB_DOOFFS))
+ pglob->gl_offs = 0;
+ }
+ if (flags & GLOB_LIMIT) {
+ limit = pglob->gl_matchc;
+ if (limit == 0)
+ limit = ARG_MAX;
+ } else
+ limit = 0;
+ pglob->gl_flags = flags & ~GLOB_MAGCHAR;
+ pglob->gl_errfunc = errfunc;
+ pglob->gl_matchc = 0;
+
+ bufnext = patbuf;
+ bufend = bufnext + MAXPATHLEN - 1;
+ if (flags & GLOB_NOESCAPE) {
+ memset(&mbs, 0, sizeof(mbs));
+ while (bufend - bufnext >= MB_CUR_MAX) {
+ clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs);
+ if (clen == (size_t)-1 || clen == (size_t)-2)
+ return (GLOB_NOMATCH);
+ else if (clen == 0)
+ break;
+ *bufnext++ = wc;
+ patnext += clen;
+ }
+ } else {
+ /* Protect the quoted characters. */
+ memset(&mbs, 0, sizeof(mbs));
+ while (bufend - bufnext >= MB_CUR_MAX) {
+ if (*patnext == QUOTE) {
+ if (*++patnext == EOS) {
+ *bufnext++ = QUOTE | M_PROTECT;
+ continue;
+ }
+ prot = M_PROTECT;
+ } else
+ prot = 0;
+ clen = mbrtowc(&wc, patnext, MB_LEN_MAX, &mbs);
+ if (clen == (size_t)-1 || clen == (size_t)-2)
+ return (GLOB_NOMATCH);
+ else if (clen == 0)
+ break;
+ *bufnext++ = wc | prot;
+ patnext += clen;
+ }
+ }
+ *bufnext = EOS;
+
+ if (flags & GLOB_BRACE)
+ return (globexp1(patbuf, pglob, &limit));
+ else
+ return (glob0(patbuf, pglob, &limit));
+}
+
+/*
+ * Expand recursively a glob {} pattern. When there is no more expansion
+ * invoke the standard globbing routine to glob the rest of the magic
+ * characters
+ */
+static int
+globexp1(const Char *pattern, glob_t *pglob, size_t *limit)
+{
+ const Char* ptr = pattern;
+ int rv;
+
+ /* Protect a single {}, for find(1), like csh */
+ if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)
+ return glob0(pattern, pglob, limit);
+
+ while ((ptr = g_strchr(ptr, LBRACE)) != NULL)
+ if (!globexp2(ptr, pattern, pglob, &rv, limit))
+ return rv;
+
+ return glob0(pattern, pglob, limit);
+}
+
+
+/*
+ * Recursive brace globbing helper. Tries to expand a single brace.
+ * If it succeeds then it invokes globexp1 with the new pattern.
+ * If it fails then it tries to glob the rest of the pattern and returns.
+ */
+static int
+globexp2(const Char *ptr, const Char *pattern, glob_t *pglob, int *rv, size_t *limit)
+{
+ int i;
+ Char *lm, *ls;
+ const Char *pe, *pm, *pm1, *pl;
+ Char patbuf[MAXPATHLEN];
+
+ /* copy part up to the brace */
+ for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++)
+ continue;
+ *lm = EOS;
+ ls = lm;
+
+ /* Find the balanced brace */
+ for (i = 0, pe = ++ptr; *pe; pe++)
+ if (*pe == LBRACKET) {
+ /* Ignore everything between [] */
+ for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++)
+ continue;
+ if (*pe == EOS) {
+ /*
+ * We could not find a matching RBRACKET.
+ * Ignore and just look for RBRACE
+ */
+ pe = pm;
+ }
+ }
+ else if (*pe == LBRACE)
+ i++;
+ else if (*pe == RBRACE) {
+ if (i == 0)
+ break;
+ i--;
+ }
+
+ /* Non matching braces; just glob the pattern */
+ if (i != 0 || *pe == EOS) {
+ *rv = glob0(patbuf, pglob, limit);
+ return (0);
+ }
+
+ for (i = 0, pl = pm = ptr; pm <= pe; pm++)
+ switch (*pm) {
+ case LBRACKET:
+ /* Ignore everything between [] */
+ for (pm1 = pm++; *pm != RBRACKET && *pm != EOS; pm++)
+ continue;
+ if (*pm == EOS) {
+ /*
+ * We could not find a matching RBRACKET.
+ * Ignore and just look for RBRACE
+ */
+ pm = pm1;
+ }
+ break;
+
+ case LBRACE:
+ i++;
+ break;
+
+ case RBRACE:
+ if (i) {
+ i--;
+ break;
+ }
+ /* FALLTHROUGH */
+ case COMMA:
+ if (i && *pm == COMMA)
+ break;
+ else {
+ /* Append the current string */
+ for (lm = ls; (pl < pm); *lm++ = *pl++)
+ continue;
+ /*
+ * Append the rest of the pattern after the
+ * closing brace
+ */
+ for (pl = pe + 1; (*lm++ = *pl++) != EOS;)
+ continue;
+
+ /* Expand the current pattern */
+#ifdef DEBUG
+ qprintf("globexp2:", patbuf);
+#endif
+ *rv = globexp1(patbuf, pglob, limit);
+
+ /* move after the comma, to the next string */
+ pl = pm + 1;
+ }
+ break;
+
+ default:
+ break;
+ }
+ *rv = 0;
+ return (0);
+}
+
+
+
+/*
+ * expand tilde from the passwd file.
+ */
+static const Char *
+globtilde(const Char *pattern, Char *patbuf, size_t patbuf_len, glob_t *pglob)
+{
+ struct passwd *pwd;
+ char *h;
+ const Char *p;
+ Char *b, *eb;
+
+ if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))
+ return (pattern);
+
+ /*
+ * Copy up to the end of the string or /
+ */
+ eb = &patbuf[patbuf_len - 1];
+ for (p = pattern + 1, h = (char *) patbuf;
+ h < (char *)eb && *p && *p != SLASH; *h++ = *p++)
+ continue;
+
+ *h = EOS;
+
+ if (((char *) patbuf)[0] == EOS) {
+ /*
+ * handle a plain ~ or ~/ by expanding $HOME first (iff
+ * we're not running setuid or setgid) and then trying
+ * the password file
+ */
+ if (issetugid() != 0 ||
+ (h = getenv("HOME")) == NULL) {
+ if (((h = getlogin()) != NULL &&
+ (pwd = getpwnam(h)) != NULL) ||
+ (pwd = getpwuid(getuid())) != NULL)
+ h = pwd->pw_dir;
+ else
+ return (pattern);
+ }
+ }
+ else {
+ /*
+ * Expand a ~user
+ */
+ if ((pwd = getpwnam((char*) patbuf)) == NULL)
+ return (pattern);
+ else
+ h = pwd->pw_dir;
+ }
+
+ /* Copy the home directory */
+ for (b = patbuf; b < eb && *h; *b++ = *h++)
+ continue;
+
+ /* Append the rest of the pattern */
+ while (b < eb && (*b++ = *p++) != EOS)
+ continue;
+ *b = EOS;
+
+ return (patbuf);
+}
+
+
+/*
+ * The main glob() routine: compiles the pattern (optionally processing
+ * quotes), calls glob1() to do the real pattern matching, and finally
+ * sorts the list (unless unsorted operation is requested). Returns 0
+ * if things went well, nonzero if errors occurred.
+ */
+static int
+glob0(const Char *pattern, glob_t *pglob, size_t *limit)
+{
+ const Char *qpatnext;
+ int err;
+ size_t oldpathc;
+ Char *bufnext, c, patbuf[MAXPATHLEN];
+
+ qpatnext = globtilde(pattern, patbuf, MAXPATHLEN, pglob);
+ oldpathc = pglob->gl_pathc;
+ bufnext = patbuf;
+
+ /* We don't need to check for buffer overflow any more. */
+ while ((c = *qpatnext++) != EOS) {
+ switch (c) {
+ case LBRACKET:
+ c = *qpatnext;
+ if (c == NOT)
+ ++qpatnext;
+ if (*qpatnext == EOS ||
+ g_strchr(qpatnext+1, RBRACKET) == NULL) {
+ *bufnext++ = LBRACKET;
+ if (c == NOT)
+ --qpatnext;
+ break;
+ }
+ *bufnext++ = M_SET;
+ if (c == NOT)
+ *bufnext++ = M_NOT;
+ c = *qpatnext++;
+ do {
+ *bufnext++ = CHAR(c);
+ if (*qpatnext == RANGE &&
+ (c = qpatnext[1]) != RBRACKET) {
+ *bufnext++ = M_RNG;
+ *bufnext++ = CHAR(c);
+ qpatnext += 2;
+ }
+ } while ((c = *qpatnext++) != RBRACKET);
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_END;
+ break;
+ case QUESTION:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ *bufnext++ = M_ONE;
+ break;
+ case STAR:
+ pglob->gl_flags |= GLOB_MAGCHAR;
+ /* collapse adjacent stars to one,
+ * to avoid exponential behavior
+ */
+ if (bufnext == patbuf || bufnext[-1] != M_ALL)
+ *bufnext++ = M_ALL;
+ break;
+ default:
+ *bufnext++ = CHAR(c);
+ break;
+ }
+ }
+ *bufnext = EOS;
+#ifdef DEBUG
+ qprintf("glob0:", patbuf);
+#endif
+
+ if ((err = glob1(patbuf, pglob, limit)) != 0)
+ return(err);
+
+ /*
+ * If there was no match we are going to append the pattern
+ * if GLOB_NOCHECK was specified or if GLOB_NOMAGIC was specified
+ * and the pattern did not contain any magic characters
+ * GLOB_NOMAGIC is there just for compatibility with csh.
+ */
+ if (pglob->gl_pathc == oldpathc) {
+ if (((pglob->gl_flags & GLOB_NOCHECK) ||
+ ((pglob->gl_flags & GLOB_NOMAGIC) &&
+ !(pglob->gl_flags & GLOB_MAGCHAR))))
+ return (globextend(pattern, pglob, limit));
+ else
+ return (GLOB_NOMATCH);
+ }
+ if (!(pglob->gl_flags & GLOB_NOSORT))
+ qsort(pglob->gl_pathv + pglob->gl_offs + oldpathc,
+ pglob->gl_pathc - oldpathc, sizeof(char *), compare);
+ return (0);
+}
+
+static int
+compare(const void *p, const void *q)
+{
+ return (strcmp(*(char **)p, *(char **)q));
+}
+
+static int
+glob1(Char *pattern, glob_t *pglob, size_t *limit)
+{
+ Char pathbuf[MAXPATHLEN];
+
+ /* A null pathname is invalid -- POSIX 1003.1 sect. 2.4. */
+ if (*pattern == EOS)
+ return (0);
+ return (glob2(pathbuf, pathbuf, pathbuf + MAXPATHLEN - 1,
+ pattern, pglob, limit));
+}
+
+/*
+ * The functions glob2 and glob3 are mutually recursive; there is one level
+ * of recursion for each segment in the pattern that contains one or more
+ * meta characters.
+ */
+static int
+glob2(Char *pathbuf, Char *pathend, Char *pathend_last, Char *pattern,
+ glob_t *pglob, size_t *limit)
+{
+ struct stat sb;
+ Char *p, *q;
+ int anymeta;
+
+ /*
+ * Loop over pattern segments until end of pattern or until
+ * segment with meta character found.
+ */
+ for (anymeta = 0;;) {
+ if (*pattern == EOS) { /* End of pattern? */
+ *pathend = EOS;
+ if (g_lstat(pathbuf, &sb, pglob))
+ return (0);
+
+ if (((pglob->gl_flags & GLOB_MARK) &&
+ pathend[-1] != SEP) && (S_ISDIR(sb.st_mode)
+ || (S_ISLNK(sb.st_mode) &&
+ (g_stat(pathbuf, &sb, pglob) == 0) &&
+ S_ISDIR(sb.st_mode)))) {
+ if (pathend + 1 > pathend_last)
+ return (GLOB_ABORTED);
+ *pathend++ = SEP;
+ *pathend = EOS;
+ }
+ ++pglob->gl_matchc;
+ return (globextend(pathbuf, pglob, limit));
+ }
+
+ /* Find end of next segment, copy tentatively to pathend. */
+ q = pathend;
+ p = pattern;
+ while (*p != EOS && *p != SEP) {
+ if (ismeta(*p))
+ anymeta = 1;
+ if (q + 1 > pathend_last)
+ return (GLOB_ABORTED);
+ *q++ = *p++;
+ }
+
+ if (!anymeta) { /* No expansion, do next segment. */
+ pathend = q;
+ pattern = p;
+ while (*pattern == SEP) {
+ if (pathend + 1 > pathend_last)
+ return (GLOB_ABORTED);
+ *pathend++ = *pattern++;
+ }
+ } else /* Need expansion, recurse. */
+ return (glob3(pathbuf, pathend, pathend_last, pattern,
+ p, pglob, limit));
+ }
+ /* NOTREACHED */
+}
+
+static int
+glob3(Char *pathbuf, Char *pathend, Char *pathend_last,
+ Char *pattern, Char *restpattern,
+ glob_t *pglob, size_t *limit)
+{
+ struct dirent *dp;
+ DIR *dirp;
+ int err;
+ char buf[MAXPATHLEN];
+
+ /*
+ * The readdirfunc declaration can't be prototyped, because it is
+ * assigned, below, to two functions which are prototyped in glob.h
+ * and dirent.h as taking pointers to differently typed opaque
+ * structures.
+ */
+ struct dirent *(*readdirfunc)();
+
+ if (pathend > pathend_last)
+ return (GLOB_ABORTED);
+ *pathend = EOS;
+ errno = 0;
+
+ if ((dirp = g_opendir(pathbuf, pglob)) == NULL) {
+ /* TODO: don't call for ENOENT or ENOTDIR? */
+ if (pglob->gl_errfunc) {
+ if (g_Ctoc(pathbuf, buf, sizeof(buf)))
+ return (GLOB_ABORTED);
+ if (pglob->gl_errfunc(buf, errno) ||
+ pglob->gl_flags & GLOB_ERR)
+ return (GLOB_ABORTED);
+ }
+ return (0);
+ }
+
+ err = 0;
+
+ /* Search directory for matching names. */
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ readdirfunc = pglob->gl_readdir;
+ else
+ readdirfunc = readdir;
+ while ((dp = (*readdirfunc)(dirp))) {
+ char *sc;
+ Char *dc;
+ wchar_t wc;
+ size_t clen;
+ mbstate_t mbs;
+
+ /* Initial DOT must be matched literally. */
+ if (dp->d_name[0] == DOT && *pattern != DOT)
+ continue;
+ memset(&mbs, 0, sizeof(mbs));
+ dc = pathend;
+ sc = dp->d_name;
+ while (dc < pathend_last) {
+ clen = mbrtowc(&wc, sc, MB_LEN_MAX, &mbs);
+ if (clen == (size_t)-1 || clen == (size_t)-2) {
+ wc = *sc;
+ clen = 1;
+ memset(&mbs, 0, sizeof(mbs));
+ }
+ if ((*dc++ = wc) == EOS)
+ break;
+ sc += clen;
+ }
+ if (!match(pathend, pattern, restpattern)) {
+ *pathend = EOS;
+ continue;
+ }
+ err = glob2(pathbuf, --dc, pathend_last, restpattern,
+ pglob, limit);
+ if (err)
+ break;
+ }
+
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ (*pglob->gl_closedir)(dirp);
+ else
+ closedir(dirp);
+ return (err);
+}
+
+
+/*
+ * Extend the gl_pathv member of a glob_t structure to accomodate a new item,
+ * add the new item, and update gl_pathc.
+ *
+ * This assumes the BSD realloc, which only copies the block when its size
+ * crosses a power-of-two boundary; for v7 realloc, this would cause quadratic
+ * behavior.
+ *
+ * Return 0 if new item added, error code if memory couldn't be allocated.
+ *
+ * Invariant of the glob_t structure:
+ * Either gl_pathc is zero and gl_pathv is NULL; or gl_pathc > 0 and
+ * gl_pathv points to (gl_offs + gl_pathc + 1) items.
+ */
+static int
+globextend(const Char *path, glob_t *pglob, size_t *limit)
+{
+ char **pathv;
+ size_t i, newsize, len;
+ char *copy;
+ const Char *p;
+
+ if (*limit && pglob->gl_pathc > *limit) {
+ errno = 0;
+ return (GLOB_NOSPACE);
+ }
+
+ newsize = sizeof(*pathv) * (2 + pglob->gl_pathc + pglob->gl_offs);
+ pathv = pglob->gl_pathv ?
+ realloc((char *)pglob->gl_pathv, newsize) :
+ malloc(newsize);
+ if (pathv == NULL) {
+ if (pglob->gl_pathv) {
+ free(pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ }
+ return (GLOB_NOSPACE);
+ }
+
+ if (pglob->gl_pathv == NULL && pglob->gl_offs > 0) {
+ /* first time around -- clear initial gl_offs items */
+ pathv += pglob->gl_offs;
+ for (i = pglob->gl_offs + 1; --i > 0; )
+ *--pathv = NULL;
+ }
+ pglob->gl_pathv = pathv;
+
+ for (p = path; *p++;)
+ continue;
+ len = MB_CUR_MAX * (size_t)(p - path); /* XXX overallocation */
+ if ((copy = malloc(len)) != NULL) {
+ if (g_Ctoc(path, copy, len)) {
+ free(copy);
+ return (GLOB_NOSPACE);
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc++] = copy;
+ }
+ pathv[pglob->gl_offs + pglob->gl_pathc] = NULL;
+ return (copy == NULL ? GLOB_NOSPACE : 0);
+}
+
+/*
+ * pattern matching function for filenames. Each occurrence of the *
+ * pattern causes a recursion level.
+ */
+static int
+match(Char *name, Char *pat, Char *patend)
+{
+ int ok, negate_range;
+ Char c, k;
+ struct xlocale_collate *table =
+ (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE];
+
+ while (pat < patend) {
+ c = *pat++;
+ switch (c & M_MASK) {
+ case M_ALL:
+ if (pat == patend)
+ return (1);
+ do
+ if (match(name, pat, patend))
+ return (1);
+ while (*name++ != EOS);
+ return (0);
+ case M_ONE:
+ if (*name++ == EOS)
+ return (0);
+ break;
+ case M_SET:
+ ok = 0;
+ if ((k = *name++) == EOS)
+ return (0);
+ if ((negate_range = ((*pat & M_MASK) == M_NOT)) != EOS)
+ ++pat;
+ while (((c = *pat++) & M_MASK) != M_END)
+ if ((*pat & M_MASK) == M_RNG) {
+ if (table->__collate_load_error ?
+ CHAR(c) <= CHAR(k) && CHAR(k) <= CHAR(pat[1]) :
+ __collate_range_cmp(table, CHAR(c), CHAR(k)) <= 0
+ && __collate_range_cmp(table, CHAR(k), CHAR(pat[1])) <= 0
+ )
+ ok = 1;
+ pat += 2;
+ } else if (c == k)
+ ok = 1;
+ if (ok == negate_range)
+ return (0);
+ break;
+ default:
+ if (*name++ != c)
+ return (0);
+ break;
+ }
+ }
+ return (*name == EOS);
+}
+
+/* Free allocated data belonging to a glob_t structure. */
+void
+globfree(glob_t *pglob)
+{
+ size_t i;
+ char **pp;
+
+ if (pglob->gl_pathv != NULL) {
+ pp = pglob->gl_pathv + pglob->gl_offs;
+ for (i = pglob->gl_pathc; i--; ++pp)
+ if (*pp)
+ free(*pp);
+ free(pglob->gl_pathv);
+ pglob->gl_pathv = NULL;
+ }
+}
+
+static DIR *
+g_opendir(Char *str, glob_t *pglob)
+{
+ char buf[MAXPATHLEN];
+
+ if (!*str)
+ strcpy(buf, ".");
+ else {
+ if (g_Ctoc(str, buf, sizeof(buf)))
+ return (NULL);
+ }
+
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return ((*pglob->gl_opendir)(buf));
+
+ return (opendir(buf));
+}
+
+static int
+g_lstat(Char *fn, struct stat *sb, glob_t *pglob)
+{
+ char buf[MAXPATHLEN];
+
+ if (g_Ctoc(fn, buf, sizeof(buf))) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return((*pglob->gl_lstat)(buf, sb));
+ return (lstat(buf, sb));
+}
+
+static int
+g_stat(Char *fn, struct stat *sb, glob_t *pglob)
+{
+ char buf[MAXPATHLEN];
+
+ if (g_Ctoc(fn, buf, sizeof(buf))) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+ if (pglob->gl_flags & GLOB_ALTDIRFUNC)
+ return ((*pglob->gl_stat)(buf, sb));
+ return (stat(buf, sb));
+}
+
+static const Char *
+g_strchr(const Char *str, wchar_t ch)
+{
+
+ do {
+ if (*str == ch)
+ return (str);
+ } while (*str++);
+ return (NULL);
+}
+
+static int
+g_Ctoc(const Char *str, char *buf, size_t len)
+{
+ mbstate_t mbs;
+ size_t clen;
+
+ memset(&mbs, 0, sizeof(mbs));
+ while (len >= MB_CUR_MAX) {
+ clen = wcrtomb(buf, *str, &mbs);
+ if (clen == (size_t)-1)
+ return (1);
+ if (*str == L'\0')
+ return (0);
+ str++;
+ buf += clen;
+ len -= clen;
+ }
+ return (1);
+}
+
+#ifdef DEBUG
+static void
+qprintf(const char *str, Char *s)
+{
+ Char *p;
+
+ (void)printf("%s:\n", str);
+ for (p = s; *p; p++)
+ (void)printf("%c", CHAR(*p));
+ (void)printf("\n");
+ for (p = s; *p; p++)
+ (void)printf("%c", *p & M_PROTECT ? '"' : ' ');
+ (void)printf("\n");
+ for (p = s; *p; p++)
+ (void)printf("%c", ismeta(*p) ? '_' : ' ');
+ (void)printf("\n");
+}
+#endif
diff --git a/lib/libc/gen/initgroups.3 b/lib/libc/gen/initgroups.3
new file mode 100644
index 0000000..3ed3ca7
--- /dev/null
+++ b/lib/libc/gen/initgroups.3
@@ -0,0 +1,93 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)initgroups.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt INITGROUPS 3
+.Os
+.Sh NAME
+.Nm initgroups
+.Nd initialize group access list
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn initgroups "const char *name" "gid_t basegid"
+.Sh DESCRIPTION
+The
+.Fn initgroups
+function
+uses the
+.Xr getgrouplist 3
+function to calculate the group access list for the user
+specified in
+.Fa name .
+This group list is then setup for the current process using
+.Xr setgroups 2 .
+The
+.Fa basegid
+is automatically included in the groups list.
+Typically this value is given as
+the group number from the password file.
+.Sh RETURN VALUES
+.Rv -std initgroups
+.Sh ERRORS
+The
+.Fn initgroups
+function may fail and set
+.Va errno
+for any of the errors specified for the library function
+.Xr setgroups 2 .
+It may also return:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+The
+.Fn initgroups
+function was unable to allocate temporary storage.
+.El
+.Sh SEE ALSO
+.Xr setgroups 2 ,
+.Xr getgrouplist 3
+.Sh HISTORY
+The
+.Fn initgroups
+function appeared in
+.Bx 4.2 .
+.Sh BUGS
+The
+.Fn getgrouplist
+function called by
+.Fn initgroups
+uses the routines based on
+.Xr getgrent 3 .
+If the invoking program uses any of these routines,
+the group structure will
+be overwritten in the call to
+.Fn initgroups .
diff --git a/lib/libc/gen/initgroups.c b/lib/libc/gen/initgroups.c
new file mode 100644
index 0000000..aacaf7e
--- /dev/null
+++ b/lib/libc/gen/initgroups.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)initgroups.c 8.1 (Berkeley) 6/4/93";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include "namespace.h"
+#include <err.h>
+#include "un-namespace.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+int
+initgroups(uname, agroup)
+ const char *uname;
+ gid_t agroup;
+{
+ int ngroups, ret;
+ long ngroups_max;
+ gid_t *groups;
+
+ /*
+ * Provide space for one group more than possible to allow
+ * setgroups to fail and set errno.
+ */
+ ngroups_max = sysconf(_SC_NGROUPS_MAX) + 2;
+ if ((groups = malloc(sizeof(*groups) * ngroups_max)) == NULL)
+ return (ENOMEM);
+
+ ngroups = (int)ngroups_max;
+ getgrouplist(uname, agroup, groups, &ngroups);
+ ret = setgroups(ngroups, groups);
+ free(groups);
+ return (ret);
+}
diff --git a/lib/libc/gen/isatty.c b/lib/libc/gen/isatty.c
new file mode 100644
index 0000000..076b824
--- /dev/null
+++ b/lib/libc/gen/isatty.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)isatty.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <termios.h>
+#include <unistd.h>
+
+int
+isatty(fd)
+ int fd;
+{
+ int retval;
+ struct termios t;
+
+ retval = (tcgetattr(fd, &t) != -1);
+ return(retval);
+}
diff --git a/lib/libc/gen/isgreater.3 b/lib/libc/gen/isgreater.3
new file mode 100644
index 0000000..9a6d85c
--- /dev/null
+++ b/lib/libc/gen/isgreater.3
@@ -0,0 +1,102 @@
+.\" Copyright (c) 2003 David Schultz <das@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 12, 2003
+.Dt ISGREATER 3
+.Os
+.Sh NAME
+.Nm isgreater , isgreaterequal , isless , islessequal ,
+.Nm islessgreater , isunordered
+.Nd "compare two floating-point numbers"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In math.h
+.Ft int
+.Fn isgreater "real-floating x" "real-floating y"
+.Ft int
+.Fn isgreaterequal "real-floating x" "real-floating y"
+.Ft int
+.Fn isless "real-floating x" "real-floating y"
+.Ft int
+.Fn islessequal "real-floating x" "real-floating y"
+.Ft int
+.Fn islessgreater "real-floating x" "real-floating y"
+.Ft int
+.Fn isunordered "real-floating x" "real-floating y"
+.Sh DESCRIPTION
+Each of the macros
+.Fn isgreater ,
+.Fn isgreaterequal ,
+.Fn isless ,
+.Fn islessequal ,
+and
+.Fn islessgreater
+take arguments
+.Fa x
+and
+.Fa y
+and return a non-zero value if and only if its nominal
+relation on
+.Fa x
+and
+.Fa y
+is true.
+These macros always return zero if either
+argument is not a number (NaN), but unlike the corresponding C
+operators, they never raise a floating point exception.
+.Pp
+The
+.Fn isunordered
+macro takes arguments
+.Fa x
+and
+.Fa y
+and returns non-zero if and only if neither
+.Fa x
+nor
+.Fa y
+are NaNs.
+For any pair of floating-point values, one
+of the relationships (less, greater, equal, unordered) holds.
+.Sh SEE ALSO
+.Xr fpclassify 3 ,
+.Xr math 3 ,
+.Xr signbit 3
+.Sh STANDARDS
+The
+.Fn isgreater ,
+.Fn isgreaterequal ,
+.Fn isless ,
+.Fn islessequal ,
+.Fn islessgreater ,
+and
+.Fn isunordered
+macros conform to
+.St -isoC-99 .
+.Sh HISTORY
+The relational macros described above first appeared in
+.Fx 5.1 .
diff --git a/lib/libc/gen/isinf.c b/lib/libc/gen/isinf.c
new file mode 100644
index 0000000..4a4152a
--- /dev/null
+++ b/lib/libc/gen/isinf.c
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <math.h>
+
+#include "fpmath.h"
+
+/*
+ * XXX These routines belong in libm, but they must remain in libc for
+ * binary compat until we can bump libm's major version number.
+ */
+
+__weak_reference(__isinf, isinf);
+
+int
+__isinf(double d)
+{
+ union IEEEd2bits u;
+
+ u.d = d;
+ return (u.bits.exp == 2047 && u.bits.manl == 0 && u.bits.manh == 0);
+}
+
+int
+__isinff(float f)
+{
+ union IEEEf2bits u;
+
+ u.f = f;
+ return (u.bits.exp == 255 && u.bits.man == 0);
+}
+
+int
+__isinfl(long double e)
+{
+ union IEEEl2bits u;
+
+ u.e = e;
+ mask_nbit_l(u);
+#ifndef __alpha__
+ return (u.bits.exp == 32767 && u.bits.manl == 0 && u.bits.manh == 0);
+#else
+ return (u.bits.exp == 2047 && u.bits.manl == 0 && u.bits.manh == 0);
+#endif
+}
diff --git a/lib/libc/gen/isnan.c b/lib/libc/gen/isnan.c
new file mode 100644
index 0000000..ec81362
--- /dev/null
+++ b/lib/libc/gen/isnan.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2004 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <math.h>
+
+#include "fpmath.h"
+
+/*
+ * XXX These routines belong in libm, but they must remain in libc for
+ * binary compat until we can bump libm's major version number.
+ */
+
+__weak_reference(__isnan, isnan);
+__weak_reference(__isnanf, isnanf);
+
+int
+__isnan(double d)
+{
+ union IEEEd2bits u;
+
+ u.d = d;
+ return (u.bits.exp == 2047 && (u.bits.manl != 0 || u.bits.manh != 0));
+}
+
+int
+__isnanf(float f)
+{
+ union IEEEf2bits u;
+
+ u.f = f;
+ return (u.bits.exp == 255 && u.bits.man != 0);
+}
diff --git a/lib/libc/gen/jrand48.c b/lib/libc/gen/jrand48.c
new file mode 100644
index 0000000..1707620
--- /dev/null
+++ b/lib/libc/gen/jrand48.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "rand48.h"
+
+long
+jrand48(unsigned short xseed[3])
+{
+ _dorand48(xseed);
+ return ((long) xseed[2] << 16) + (long) xseed[1];
+}
diff --git a/lib/libc/gen/lcong48.c b/lib/libc/gen/lcong48.c
new file mode 100644
index 0000000..ab0d1f7
--- /dev/null
+++ b/lib/libc/gen/lcong48.c
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "rand48.h"
+
+extern unsigned short _rand48_seed[3];
+extern unsigned short _rand48_mult[3];
+extern unsigned short _rand48_add;
+
+void
+lcong48(unsigned short p[7])
+{
+ _rand48_seed[0] = p[0];
+ _rand48_seed[1] = p[1];
+ _rand48_seed[2] = p[2];
+ _rand48_mult[0] = p[3];
+ _rand48_mult[1] = p[4];
+ _rand48_mult[2] = p[5];
+ _rand48_add = p[6];
+}
diff --git a/lib/libc/gen/ldexp.3 b/lib/libc/gen/ldexp.3
new file mode 100644
index 0000000..e8e4fba
--- /dev/null
+++ b/lib/libc/gen/ldexp.3
@@ -0,0 +1,77 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)ldexp.3 8.2 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd March 4, 2005
+.Dt LDEXP 3
+.Os
+.Sh NAME
+.Nm ldexp ,
+.Nm ldexpf ,
+.Nm ldexpl
+.Nd multiply floating-point number by integral power of 2
+.Sh LIBRARY
+.Lb libm
+.Sh SYNOPSIS
+.In math.h
+.Ft double
+.Fn ldexp "double x" "int exp"
+.Ft float
+.Fn ldexpf "float x" "int exp"
+.Ft long double
+.Fn ldexpl "long double x" "int exp"
+.Sh DESCRIPTION
+The
+.Fn ldexp ,
+.Fn ldexpf ,
+and
+.Fn ldexpl
+functions multiply a floating-point number by an integral
+power of 2.
+.Sh RETURN VALUES
+These functions return the value of
+.Fa x
+times 2 raised to the power
+.Fa exp .
+.Sh SEE ALSO
+.Xr frexp 3 ,
+.Xr math 3 ,
+.Xr modf 3
+.Sh STANDARDS
+The
+.Fn ldexp ,
+.Fn ldexpf ,
+and
+.Fn ldexpl
+functions conform to
+.St -isoC-99 .
diff --git a/lib/libc/gen/ldexp.c b/lib/libc/gen/ldexp.c
new file mode 100644
index 0000000..887f673
--- /dev/null
+++ b/lib/libc/gen/ldexp.c
@@ -0,0 +1,123 @@
+/* @(#)s_scalbn.c 5.1 93/09/24 */
+/* @(#)fdlibm.h 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <machine/endian.h>
+#include <math.h>
+
+/* Bit fiddling routines copied from msun/src/math_private.h,v 1.15 */
+
+#if BYTE_ORDER == BIG_ENDIAN
+
+typedef union
+{
+ double value;
+ struct
+ {
+ u_int32_t msw;
+ u_int32_t lsw;
+ } parts;
+} ieee_double_shape_type;
+
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+typedef union
+{
+ double value;
+ struct
+ {
+ u_int32_t lsw;
+ u_int32_t msw;
+ } parts;
+} ieee_double_shape_type;
+
+#endif
+
+/* Get two 32 bit ints from a double. */
+
+#define EXTRACT_WORDS(ix0,ix1,d) \
+do { \
+ ieee_double_shape_type ew_u; \
+ ew_u.value = (d); \
+ (ix0) = ew_u.parts.msw; \
+ (ix1) = ew_u.parts.lsw; \
+} while (0)
+
+/* Get the more significant 32 bit int from a double. */
+
+#define GET_HIGH_WORD(i,d) \
+do { \
+ ieee_double_shape_type gh_u; \
+ gh_u.value = (d); \
+ (i) = gh_u.parts.msw; \
+} while (0)
+
+/* Set the more significant 32 bits of a double from an int. */
+
+#define SET_HIGH_WORD(d,v) \
+do { \
+ ieee_double_shape_type sh_u; \
+ sh_u.value = (d); \
+ sh_u.parts.msw = (v); \
+ (d) = sh_u.value; \
+} while (0)
+
+
+static const double
+two54 = 1.80143985094819840000e+16, /* 0x43500000, 0x00000000 */
+twom54 = 5.55111512312578270212e-17, /* 0x3C900000, 0x00000000 */
+huge = 1.0e+300,
+tiny = 1.0e-300;
+
+static double
+_copysign(double x, double y)
+{
+ u_int32_t hx,hy;
+ GET_HIGH_WORD(hx,x);
+ GET_HIGH_WORD(hy,y);
+ SET_HIGH_WORD(x,(hx&0x7fffffff)|(hy&0x80000000));
+ return x;
+}
+
+double
+ldexp(double x, int n)
+{
+ int32_t k,hx,lx;
+ EXTRACT_WORDS(hx,lx,x);
+ k = (hx&0x7ff00000)>>20; /* extract exponent */
+ if (k==0) { /* 0 or subnormal x */
+ if ((lx|(hx&0x7fffffff))==0) return x; /* +-0 */
+ x *= two54;
+ GET_HIGH_WORD(hx,x);
+ k = ((hx&0x7ff00000)>>20) - 54;
+ if (n< -50000) return tiny*x; /*underflow*/
+ }
+ if (k==0x7ff) return x+x; /* NaN or Inf */
+ k = k+n;
+ if (k > 0x7fe) return huge*_copysign(huge,x); /* overflow */
+ if (k > 0) /* normal result */
+ {SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20)); return x;}
+ if (k <= -54) {
+ if (n > 50000) /* in case integer overflow in n+k */
+ return huge*_copysign(huge,x); /*overflow*/
+ else return tiny*_copysign(tiny,x); /*underflow*/
+ }
+ k += 54; /* subnormal result */
+ SET_HIGH_WORD(x,(hx&0x800fffff)|(k<<20));
+ return x*twom54;
+}
diff --git a/lib/libc/gen/libc_dlopen.c b/lib/libc/gen/libc_dlopen.c
new file mode 100644
index 0000000..2b1aa9e
--- /dev/null
+++ b/lib/libc/gen/libc_dlopen.c
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2011 Xin Li <delphij@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <dlfcn.h>
+#include <stddef.h>
+#include <unistd.h>
+
+#include "libc_private.h"
+
+/*
+ * Whether we want to restrict dlopen()s.
+ */
+static int __libc_restricted_mode = 0;
+
+void *
+libc_dlopen(const char *path, int mode)
+{
+
+ if (__libc_restricted_mode) {
+ _rtld_error("Service unavailable -- libc in restricted mode");
+ return (NULL);
+ } else
+ return (dlopen(path, mode));
+}
+
+void
+__FreeBSD_libc_enter_restricted_mode(void)
+{
+
+ __libc_restricted_mode = 1;
+ return;
+}
+
diff --git a/lib/libc/gen/lockf.3 b/lib/libc/gen/lockf.3
new file mode 100644
index 0000000..d9350d1
--- /dev/null
+++ b/lib/libc/gen/lockf.3
@@ -0,0 +1,266 @@
+.\" $NetBSD: lockf.3,v 1.10 2008/04/30 13:10:50 martin Exp $
+.\"
+.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Klaus Klein and S.P. Zeidler.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 19, 1997
+.Dt LOCKF 3
+.Os
+.Sh NAME
+.Nm lockf
+.Nd record locking on files
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn lockf "int filedes" "int function" "off_t size"
+.Sh DESCRIPTION
+The
+.Fn lockf
+function allows sections of a file to be locked with advisory-mode locks.
+Calls to
+.Fn lockf
+from other processes which attempt to lock the locked file section will
+either return an error value or block until the section becomes unlocked.
+All the locks for a process are removed when the process terminates.
+.Pp
+The argument
+.Fa filedes
+is an open file descriptor.
+The file descriptor must have been opened either for write-only
+.Dv ( O_WRONLY )
+or read/write
+.Dv ( O_RDWR )
+operation.
+.Pp
+The
+.Fa function
+argument is a control value which specifies the action to be taken.
+The permissible values for
+.Fa function
+are as follows:
+.Bl -tag -width F_ULOCKXX -compact -offset indent
+.It Sy Function
+.Sy Description
+.It Dv F_ULOCK
+unlock locked sections
+.It Dv F_LOCK
+lock a section for exclusive use
+.It Dv F_TLOCK
+test and lock a section for exclusive use
+.It Dv F_TEST
+test a section for locks by other processes
+.El
+.Pp
+.Dv F_ULOCK
+removes locks from a section of the file;
+.Dv F_LOCK
+and
+.Dv F_TLOCK
+both lock a section of a file if the section is available;
+.Dv F_TEST
+detects if a lock by another process is present on the specified section.
+.Pp
+The
+.Fa size
+argument is the number of contiguous bytes to be locked or
+unlocked.
+The section to be locked or unlocked starts at the current
+offset in the file and extends forward for a positive size or backward
+for a negative size (the preceding bytes up to but not including the
+current offset).
+However, it is not permitted to lock a section that
+starts or extends before the beginning of the file.
+If
+.Fa size
+is 0, the section from the current offset through the largest possible
+file offset is locked (that is, from the current offset through the
+present or any future end-of-file).
+.Pp
+The sections locked with
+.Dv F_LOCK
+or
+.Dv F_TLOCK
+may, in whole or in part, contain or be contained by a previously
+locked section for the same process.
+When this occurs, or if adjacent
+locked sections would occur, the sections are combined into a single
+locked section.
+If the request would cause the number of locks to
+exceed a system-imposed limit, the request will fail.
+.Pp
+.Dv F_LOCK
+and
+.Dv F_TLOCK
+requests differ only by the action taken if the section is not
+available.
+.Dv F_LOCK
+blocks the calling process until the section is available.
+.Dv F_TLOCK
+makes the function fail if the section is already locked by another
+process.
+.Pp
+File locks are released on first close by the locking process of any
+file descriptor for the file.
+.Pp
+.Dv F_ULOCK
+requests release (wholly or in part) one or more locked sections
+controlled by the process.
+Locked sections will be unlocked starting
+at the current file offset through
+.Fa size
+bytes or to the end of file if size is 0.
+When all of a locked section
+is not released (that is, when the beginning or end of the area to be
+unlocked falls within a locked section), the remaining portions of
+that section are still locked by the process.
+Releasing the center
+portion of a locked section will cause the remaining locked beginning
+and end portions to become two separate locked sections.
+If the
+request would cause the number of locks in the system to exceed a
+system-imposed limit, the request will fail.
+.Pp
+An
+.Dv F_ULOCK
+request in which size is non-zero and the offset of the last byte of
+the requested section is the maximum value for an object of type
+off_t, when the process has an existing lock in which size is 0 and
+which includes the last byte of the requested section, will be treated
+as a request to unlock from the start of the requested section with a
+size equal to 0.
+Otherwise an
+.Dv F_ULOCK
+request will attempt to unlock only the requested section.
+.Pp
+A potential for deadlock occurs if a process controlling a locked
+region is put to sleep by attempting to lock the locked region of
+another process.
+This implementation detects that sleeping until a
+locked region is unlocked would cause a deadlock and fails with an
+.Er EDEADLK
+error.
+.Pp
+The
+.Fn lockf ,
+.Xr fcntl 2 ,
+and
+.Xr flock 2
+locks are compatible.
+Processes using different locking interfaces can cooperate
+over the same file safely.
+However, only one of such interfaces should be used within
+the same process.
+If a file is locked by a process through
+.Xr flock 2 ,
+any record within the file will be seen as locked
+from the viewpoint of another process using
+.Xr fcntl 2
+or
+.Fn lockf ,
+and vice versa.
+.Pp
+Blocking on a section is interrupted by any signal.
+.Sh RETURN VALUES
+.Rv -std lockf
+In the case of a failure, existing locks are not changed.
+.Sh ERRORS
+The
+.Fn lockf
+function
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EAGAIN
+The argument
+.Fa function
+is
+.Dv F_TLOCK
+or
+.Dv F_TEST
+and the section is already locked by another process.
+.It Bq Er EBADF
+The argument
+.Fa filedes
+is not a valid open file descriptor.
+.Pp
+The argument
+.Fa function
+is
+.Dv F_LOCK
+or
+.Dv F_TLOCK ,
+and
+.Fa filedes
+is not a valid file descriptor open for writing.
+.It Bq Er EDEADLK
+The argument
+.Fa function
+is
+.Dv F_LOCK
+and a deadlock is detected.
+.It Bq Er EINTR
+The argument
+.Fa function
+is F_LOCK
+and
+.Fn lockf
+was interrupted by the delivery of a signal.
+.It Bq Er EINVAL
+The argument
+.Fa function
+is not one of
+.Dv F_ULOCK ,
+.Dv F_LOCK ,
+.Dv F_TLOCK
+or
+.Dv F_TEST .
+.Pp
+The argument
+.Fa filedes
+refers to a file that does not support locking.
+.It Bq Er ENOLCK
+The argument
+.Fa function
+is
+.Dv F_ULOCK ,
+.Dv F_LOCK
+or
+.Dv F_TLOCK ,
+and satisfying the lock or unlock request would result in the number
+of locked regions in the system exceeding a system-imposed limit.
+.El
+.Sh SEE ALSO
+.Xr fcntl 2 ,
+.Xr flock 2
+.Sh STANDARDS
+The
+.Fn lockf
+function conforms to
+.St -xpg4.2 .
diff --git a/lib/libc/gen/lockf.c b/lib/libc/gen/lockf.c
new file mode 100644
index 0000000..2c567ba
--- /dev/null
+++ b/lib/libc/gen/lockf.c
@@ -0,0 +1,79 @@
+/* $NetBSD: lockf.c,v 1.3 2008/04/28 20:22:59 martin Exp $ */
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+int
+lockf(int filedes, int function, off_t size)
+{
+ struct flock fl;
+ int cmd;
+
+ fl.l_start = 0;
+ fl.l_len = size;
+ fl.l_whence = SEEK_CUR;
+
+ switch (function) {
+ case F_ULOCK:
+ cmd = F_SETLK;
+ fl.l_type = F_UNLCK;
+ break;
+ case F_LOCK:
+ cmd = F_SETLKW;
+ fl.l_type = F_WRLCK;
+ break;
+ case F_TLOCK:
+ cmd = F_SETLK;
+ fl.l_type = F_WRLCK;
+ break;
+ case F_TEST:
+ fl.l_type = F_WRLCK;
+ if (_fcntl(filedes, F_GETLK, &fl) == -1)
+ return (-1);
+ if (fl.l_type == F_UNLCK || (fl.l_sysid == 0 && fl.l_pid == getpid()))
+ return (0);
+ errno = EAGAIN;
+ return (-1);
+ /* NOTREACHED */
+ default:
+ errno = EINVAL;
+ return (-1);
+ /* NOTREACHED */
+ }
+
+ return (_fcntl(filedes, cmd, &fl));
+}
diff --git a/lib/libc/gen/lrand48.c b/lib/libc/gen/lrand48.c
new file mode 100644
index 0000000..44a7f5d
--- /dev/null
+++ b/lib/libc/gen/lrand48.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "rand48.h"
+
+extern unsigned short _rand48_seed[3];
+
+long
+lrand48(void)
+{
+ _dorand48(_rand48_seed);
+ return ((long) _rand48_seed[2] << 15) + ((long) _rand48_seed[1] >> 1);
+}
diff --git a/lib/libc/gen/makecontext.3 b/lib/libc/gen/makecontext.3
new file mode 100644
index 0000000..ad55e7a
--- /dev/null
+++ b/lib/libc/gen/makecontext.3
@@ -0,0 +1,120 @@
+.\" Copyright (c) 2002 Packet Design, LLC.
+.\" All rights reserved.
+.\"
+.\" Subject to the following obligations and disclaimer of warranty,
+.\" use and redistribution of this software, in source or object code
+.\" forms, with or without modifications are expressly permitted by
+.\" Packet Design; provided, however, that:
+.\"
+.\" (i) Any and all reproductions of the source or object code
+.\" must include the copyright notice above and the following
+.\" disclaimer of warranties; and
+.\" (ii) No rights are granted, in any manner or form, to use
+.\" Packet Design trademarks, including the mark "PACKET DESIGN"
+.\" on advertising, endorsements, or otherwise except as such
+.\" appears in the above copyright notice or in the software.
+.\"
+.\" THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
+.\" TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
+.\" REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
+.\" THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
+.\" OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
+.\" OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
+.\" OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
+.\" RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
+.\" LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
+.\" OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
+.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
+.\" DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
+.\" USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
+.\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+.\" THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
+.\" THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 10, 2002
+.Dt MAKECONTEXT 3
+.Os
+.Sh NAME
+.Nm makecontext , swapcontext
+.Nd modify and exchange user thread contexts
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ucontext.h
+.Ft void
+.Fo makecontext
+.Fa "ucontext_t *ucp"
+.Fa "void \*[lp]*func\*[rp]\*[lp]void\*[rp]"
+.Fa "int argc" ...
+.Fc
+.Ft int
+.Fn swapcontext "ucontext_t *oucp" "const ucontext_t *ucp"
+.Sh DESCRIPTION
+The
+.Fn makecontext
+function
+modifies the user thread context pointed to by
+.Fa ucp ,
+which must have previously been initialized by a call to
+.Xr getcontext 3
+and had a stack allocated for it.
+The context is modified so that it will continue execution by invoking
+.Fn func
+with the arguments provided.
+The
+.Fa argc
+argument
+must be equal to the number of additional arguments provided to
+.Fn makecontext
+and also equal to the number of arguments to
+.Fn func ,
+or else the behavior is undefined.
+.Pp
+The
+.Fa "ucp->uc_link"
+argument
+must be initialized before calling
+.Fn makecontext
+and determines the action to take when
+.Fn func
+returns:
+if equal to
+.Dv NULL ,
+the process exits;
+otherwise,
+.Fn setcontext "ucp->uc_link"
+is implicitly invoked.
+.Pp
+The
+.Fn swapcontext
+function
+saves the current thread context in
+.Fa "*oucp"
+and makes
+.Fa "*ucp"
+the currently active context.
+.Sh RETURN VALUES
+If successful,
+.Fn swapcontext
+returns zero;
+otherwise \-1 is returned and the global variable
+.Va errno
+is set appropriately.
+.Sh ERRORS
+The
+.Fn swapcontext
+function
+will fail if:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+There is not enough stack space in
+.Fa ucp
+to complete the operation.
+.El
+.Sh SEE ALSO
+.Xr setcontext 3 ,
+.Xr ucontext 3
diff --git a/lib/libc/gen/modf.3 b/lib/libc/gen/modf.3
new file mode 100644
index 0000000..a3ee527
--- /dev/null
+++ b/lib/libc/gen/modf.3
@@ -0,0 +1,81 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)modf.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd March 29, 2008
+.Dt MODF 3
+.Os
+.Sh NAME
+.Nm modf ,
+.Nm modff ,
+.Nm modfl
+.Nd extract signed integral and fractional values from floating-point number
+.Sh LIBRARY
+.Lb libm
+.Sh SYNOPSIS
+.In math.h
+.Ft double
+.Fn modf "double value" "double *iptr"
+.Ft float
+.Fn modff "float value" "float *iptr"
+.Ft long double
+.Fn modfl "long double value" "long double *iptr"
+.Sh DESCRIPTION
+The
+.Fn modf ,
+.Fn modff ,
+and
+.Fn modfl
+functions break the argument
+.Fa value
+into integral and fractional parts, each of which has the
+same sign as the argument.
+It stores the integral part as a
+floating point number
+in the object pointed to by
+.Fa iptr .
+.Sh RETURN VALUES
+These functions return the signed fractional part of
+.Fa value .
+.Sh SEE ALSO
+.Xr frexp 3 ,
+.Xr ldexp 3 ,
+.Xr math 3
+.Sh STANDARDS
+The
+.Fn modf ,
+.Fn modff ,
+and
+.Fn modfl
+functions conform to
+.St -isoC-99 .
diff --git a/lib/libc/gen/modf.c b/lib/libc/gen/modf.c
new file mode 100644
index 0000000..d67b441
--- /dev/null
+++ b/lib/libc/gen/modf.c
@@ -0,0 +1,138 @@
+/* @(#)s_modf.c 5.1 93/09/24 */
+/*
+ * ====================================================
+ * Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
+ *
+ * Developed at SunPro, a Sun Microsystems, Inc. business.
+ * Permission to use, copy, modify, and distribute this
+ * software is freely granted, provided that this notice
+ * is preserved.
+ * ====================================================
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * modf(double x, double *iptr)
+ * return fraction part of x, and return x's integral part in *iptr.
+ * Method:
+ * Bit twiddling.
+ *
+ * Exception:
+ * No exception.
+ */
+
+#include <sys/types.h>
+#include <machine/endian.h>
+#include <math.h>
+
+/* Bit fiddling routines copied from msun/src/math_private.h,v 1.15 */
+
+#if BYTE_ORDER == BIG_ENDIAN
+
+typedef union
+{
+ double value;
+ struct
+ {
+ u_int32_t msw;
+ u_int32_t lsw;
+ } parts;
+} ieee_double_shape_type;
+
+#endif
+
+#if BYTE_ORDER == LITTLE_ENDIAN
+
+typedef union
+{
+ double value;
+ struct
+ {
+ u_int32_t lsw;
+ u_int32_t msw;
+ } parts;
+} ieee_double_shape_type;
+
+#endif
+
+/* Get two 32 bit ints from a double. */
+
+#define EXTRACT_WORDS(ix0,ix1,d) \
+do { \
+ ieee_double_shape_type ew_u; \
+ ew_u.value = (d); \
+ (ix0) = ew_u.parts.msw; \
+ (ix1) = ew_u.parts.lsw; \
+} while (0)
+
+/* Get the more significant 32 bit int from a double. */
+
+#define GET_HIGH_WORD(i,d) \
+do { \
+ ieee_double_shape_type gh_u; \
+ gh_u.value = (d); \
+ (i) = gh_u.parts.msw; \
+} while (0)
+
+/* Set a double from two 32 bit ints. */
+
+#define INSERT_WORDS(d,ix0,ix1) \
+do { \
+ ieee_double_shape_type iw_u; \
+ iw_u.parts.msw = (ix0); \
+ iw_u.parts.lsw = (ix1); \
+ (d) = iw_u.value; \
+} while (0)
+
+static const double one = 1.0;
+
+double
+modf(double x, double *iptr)
+{
+ int32_t i0,i1,j0;
+ u_int32_t i;
+ EXTRACT_WORDS(i0,i1,x);
+ j0 = ((i0>>20)&0x7ff)-0x3ff; /* exponent of x */
+ if(j0<20) { /* integer part in high x */
+ if(j0<0) { /* |x|<1 */
+ INSERT_WORDS(*iptr,i0&0x80000000,0); /* *iptr = +-0 */
+ return x;
+ } else {
+ i = (0x000fffff)>>j0;
+ if(((i0&i)|i1)==0) { /* x is integral */
+ u_int32_t high;
+ *iptr = x;
+ GET_HIGH_WORD(high,x);
+ INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
+ return x;
+ } else {
+ INSERT_WORDS(*iptr,i0&(~i),0);
+ return x - *iptr;
+ }
+ }
+ } else if (j0>51) { /* no fraction part */
+ u_int32_t high;
+ if (j0 == 0x400) { /* inf/NaN */
+ *iptr = x;
+ return 0.0 / x;
+ }
+ *iptr = x*one;
+ GET_HIGH_WORD(high,x);
+ INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
+ return x;
+ } else { /* fraction part in low x */
+ i = ((u_int32_t)(0xffffffff))>>(j0-20);
+ if((i1&i)==0) { /* x is integral */
+ u_int32_t high;
+ *iptr = x;
+ GET_HIGH_WORD(high,x);
+ INSERT_WORDS(x,high&0x80000000,0); /* return +-0 */
+ return x;
+ } else {
+ INSERT_WORDS(*iptr,i0,i1&(~i));
+ return x - *iptr;
+ }
+ }
+}
diff --git a/lib/libc/gen/mrand48.c b/lib/libc/gen/mrand48.c
new file mode 100644
index 0000000..ef20fb87b
--- /dev/null
+++ b/lib/libc/gen/mrand48.c
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "rand48.h"
+
+extern unsigned short _rand48_seed[3];
+
+long
+mrand48(void)
+{
+ _dorand48(_rand48_seed);
+ return ((long) _rand48_seed[2] << 16) + (long) _rand48_seed[1];
+}
diff --git a/lib/libc/gen/nftw.c b/lib/libc/gen/nftw.c
new file mode 100644
index 0000000..43110c1
--- /dev/null
+++ b/lib/libc/gen/nftw.c
@@ -0,0 +1,117 @@
+/* $OpenBSD: nftw.c,v 1.4 2004/07/07 16:05:23 millert Exp $ */
+
+/*
+ * Copyright (c) 2003, 2004 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$OpenBSD: nftw.c,v 1.4 2004/07/07 16:05:23 millert Exp $";
+#endif /* LIBC_SCCS and not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fts.h>
+#include <ftw.h>
+#include <limits.h>
+
+int
+nftw(const char *path, int (*fn)(const char *, const struct stat *, int,
+ struct FTW *), int nfds, int ftwflags)
+{
+ char * const paths[2] = { (char *)path, NULL };
+ struct FTW ftw;
+ FTSENT *cur;
+ FTS *ftsp;
+ int error = 0, ftsflags, fnflag, postorder, sverrno;
+
+ /* XXX - nfds is currently unused */
+ if (nfds < 1 || nfds > OPEN_MAX) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ftsflags = FTS_COMFOLLOW;
+ if (!(ftwflags & FTW_CHDIR))
+ ftsflags |= FTS_NOCHDIR;
+ if (ftwflags & FTW_MOUNT)
+ ftsflags |= FTS_XDEV;
+ if (ftwflags & FTW_PHYS)
+ ftsflags |= FTS_PHYSICAL;
+ else
+ ftsflags |= FTS_LOGICAL;
+ postorder = (ftwflags & FTW_DEPTH) != 0;
+ ftsp = fts_open(paths, ftsflags, NULL);
+ if (ftsp == NULL)
+ return (-1);
+ while ((cur = fts_read(ftsp)) != NULL) {
+ switch (cur->fts_info) {
+ case FTS_D:
+ if (postorder)
+ continue;
+ fnflag = FTW_D;
+ break;
+ case FTS_DNR:
+ fnflag = FTW_DNR;
+ break;
+ case FTS_DP:
+ if (!postorder)
+ continue;
+ fnflag = FTW_DP;
+ break;
+ case FTS_F:
+ case FTS_DEFAULT:
+ fnflag = FTW_F;
+ break;
+ case FTS_NS:
+ case FTS_NSOK:
+ fnflag = FTW_NS;
+ break;
+ case FTS_SL:
+ fnflag = FTW_SL;
+ break;
+ case FTS_SLNONE:
+ fnflag = FTW_SLN;
+ break;
+ case FTS_DC:
+ errno = ELOOP;
+ /* FALLTHROUGH */
+ default:
+ error = -1;
+ goto done;
+ }
+ ftw.base = cur->fts_pathlen - cur->fts_namelen;
+ ftw.level = cur->fts_level;
+ error = fn(cur->fts_path, cur->fts_statp, fnflag, &ftw);
+ if (error != 0)
+ break;
+ }
+done:
+ sverrno = errno;
+ if (fts_close(ftsp) != 0 && error == 0)
+ error = -1;
+ else
+ errno = sverrno;
+ return (error);
+}
diff --git a/lib/libc/gen/nice.3 b/lib/libc/gen/nice.3
new file mode 100644
index 0000000..9c39b78
--- /dev/null
+++ b/lib/libc/gen/nice.3
@@ -0,0 +1,69 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)nice.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt NICE 3
+.Os
+.Sh NAME
+.Nm nice
+.Nd set program scheduling priority
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn nice "int incr"
+.Sh DESCRIPTION
+.Bf -symbolic
+This interface is obsoleted by
+.Xr setpriority 2 .
+.Ef
+.Pp
+The
+.Fn nice
+function obtains the scheduling priority of the process
+from the system and sets it to the priority value specified in
+.Fa incr .
+The priority is a value in the range -20 to 20.
+The default priority is 0; lower priorities cause more favorable scheduling.
+Only the super-user may lower priorities.
+.Pp
+Children inherit the priority of their parent processes via
+.Xr fork 2 .
+.Sh SEE ALSO
+.Xr nice 1 ,
+.Xr fork 2 ,
+.Xr setpriority 2 ,
+.Xr renice 8
+.Sh HISTORY
+A
+.Fn nice
+syscall appeared in
+.At v6 .
diff --git a/lib/libc/gen/nice.c b/lib/libc/gen/nice.c
new file mode 100644
index 0000000..e8375e8
--- /dev/null
+++ b/lib/libc/gen/nice.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)nice.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+#include <errno.h>
+#include <unistd.h>
+
+/*
+ * Backwards compatible nice.
+ */
+int
+nice(incr)
+ int incr;
+{
+ int prio;
+
+ errno = 0;
+ prio = getpriority(PRIO_PROCESS, 0);
+ if (prio == -1 && errno)
+ return (-1);
+ return (setpriority(PRIO_PROCESS, 0, prio + incr));
+}
diff --git a/lib/libc/gen/nlist.3 b/lib/libc/gen/nlist.3
new file mode 100644
index 0000000..5bcd72a
--- /dev/null
+++ b/lib/libc/gen/nlist.3
@@ -0,0 +1,77 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)nlist.3 8.3 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd April 19, 1994
+.Dt NLIST 3
+.Os
+.Sh NAME
+.Nm nlist
+.Nd retrieve symbol table name list from an executable file
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In nlist.h
+.Ft int
+.Fn nlist "const char *filename" "struct nlist *nl"
+.Sh DESCRIPTION
+The
+.Fn nlist
+function
+retrieves name list entries from the symbol table of an
+executable file (see
+.Xr a.out 5 ) .
+The argument
+.Fa \&nl
+is set to reference the
+beginning of the list.
+The list is preened of binary and invalid data;
+if an entry in the
+name list is valid, the
+.Fa n_type
+and
+.Fa n_value
+for the entry are copied into the list
+referenced by
+.Fa \&nl .
+No other data is copied.
+The last entry in the list is always
+.Dv NULL .
+.Sh RETURN VALUES
+The number of invalid entries is returned if successful; otherwise,
+if the file
+.Fa filename
+does not exist or is not executable, the returned value is \-1.
+.Sh SEE ALSO
+.Xr a.out 5
+.Sh HISTORY
+A
+.Fn nlist
+function appeared in
+.At v6 .
diff --git a/lib/libc/gen/nlist.c b/lib/libc/gen/nlist.c
new file mode 100644
index 0000000..1361af3
--- /dev/null
+++ b/lib/libc/gen/nlist.c
@@ -0,0 +1,411 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)nlist.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/file.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <a.out.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#define _NLIST_DO_AOUT
+#define _NLIST_DO_ELF
+
+#ifdef _NLIST_DO_ELF
+#include <machine/elf.h>
+#include <elf-hints.h>
+#endif
+
+int __fdnlist(int, struct nlist *);
+int __aout_fdnlist(int, struct nlist *);
+int __elf_fdnlist(int, struct nlist *);
+
+int
+nlist(name, list)
+ const char *name;
+ struct nlist *list;
+{
+ int fd, n;
+
+ fd = _open(name, O_RDONLY, 0);
+ if (fd < 0)
+ return (-1);
+ n = __fdnlist(fd, list);
+ (void)_close(fd);
+ return (n);
+}
+
+static struct nlist_handlers {
+ int (*fn)(int fd, struct nlist *list);
+} nlist_fn[] = {
+#ifdef _NLIST_DO_AOUT
+ { __aout_fdnlist },
+#endif
+#ifdef _NLIST_DO_ELF
+ { __elf_fdnlist },
+#endif
+};
+
+int
+__fdnlist(fd, list)
+ int fd;
+ struct nlist *list;
+{
+ int n = -1, i;
+
+ for (i = 0; i < sizeof(nlist_fn) / sizeof(nlist_fn[0]); i++) {
+ n = (nlist_fn[i].fn)(fd, list);
+ if (n != -1)
+ break;
+ }
+ return (n);
+}
+
+#define ISLAST(p) (p->n_un.n_name == 0 || p->n_un.n_name[0] == 0)
+
+#ifdef _NLIST_DO_AOUT
+int
+__aout_fdnlist(fd, list)
+ int fd;
+ struct nlist *list;
+{
+ struct nlist *p, *symtab;
+ caddr_t strtab, a_out_mmap;
+ off_t stroff, symoff;
+ u_long symsize;
+ int nent;
+ struct exec * exec;
+ struct stat st;
+
+ /* check that file is at least as large as struct exec! */
+ if ((_fstat(fd, &st) < 0) || (st.st_size < sizeof(struct exec)))
+ return (-1);
+
+ /* Check for files too large to mmap. */
+ if (st.st_size > SIZE_T_MAX) {
+ errno = EFBIG;
+ return (-1);
+ }
+
+ /*
+ * Map the whole a.out file into our address space.
+ * We then find the string table withing this area.
+ * We do not just mmap the string table, as it probably
+ * does not start at a page boundary - we save ourselves a
+ * lot of nastiness by mmapping the whole file.
+ *
+ * This gives us an easy way to randomly access all the strings,
+ * without making the memory allocation permanent as with
+ * malloc/free (i.e., munmap will return it to the system).
+ */
+ a_out_mmap = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_PRIVATE, fd, (off_t)0);
+ if (a_out_mmap == MAP_FAILED)
+ return (-1);
+
+ exec = (struct exec *)a_out_mmap;
+ if (N_BADMAG(*exec)) {
+ munmap(a_out_mmap, (size_t)st.st_size);
+ return (-1);
+ }
+
+ symoff = N_SYMOFF(*exec);
+ symsize = exec->a_syms;
+ stroff = symoff + symsize;
+
+ /* find the string table in our mmapped area */
+ strtab = a_out_mmap + stroff;
+ symtab = (struct nlist *)(a_out_mmap + symoff);
+
+ /*
+ * clean out any left-over information for all valid entries.
+ * Type and value defined to be 0 if not found; historical
+ * versions cleared other and desc as well. Also figure out
+ * the largest string length so don't read any more of the
+ * string table than we have to.
+ *
+ * XXX clearing anything other than n_type and n_value violates
+ * the semantics given in the man page.
+ */
+ nent = 0;
+ for (p = list; !ISLAST(p); ++p) {
+ p->n_type = 0;
+ p->n_other = 0;
+ p->n_desc = 0;
+ p->n_value = 0;
+ ++nent;
+ }
+
+ while (symsize > 0) {
+ int soff;
+
+ symsize-= sizeof(struct nlist);
+ soff = symtab->n_un.n_strx;
+
+
+ if (soff != 0 && (symtab->n_type & N_STAB) == 0)
+ for (p = list; !ISLAST(p); p++)
+ if (!strcmp(&strtab[soff], p->n_un.n_name)) {
+ p->n_value = symtab->n_value;
+ p->n_type = symtab->n_type;
+ p->n_desc = symtab->n_desc;
+ p->n_other = symtab->n_other;
+ if (--nent <= 0)
+ break;
+ }
+ symtab++;
+ }
+ munmap(a_out_mmap, (size_t)st.st_size);
+ return (nent);
+}
+#endif
+
+#ifdef _NLIST_DO_ELF
+static void elf_sym_to_nlist(struct nlist *, Elf_Sym *, Elf_Shdr *, int);
+
+/*
+ * __elf_is_okay__ - Determine if ehdr really
+ * is ELF and valid for the target platform.
+ *
+ * WARNING: This is NOT an ELF ABI function and
+ * as such its use should be restricted.
+ */
+int
+__elf_is_okay__(Elf_Ehdr *ehdr)
+{
+ int retval = 0;
+ /*
+ * We need to check magic, class size, endianess,
+ * and version before we look at the rest of the
+ * Elf_Ehdr structure. These few elements are
+ * represented in a machine independant fashion.
+ */
+ if (IS_ELF(*ehdr) &&
+ ehdr->e_ident[EI_CLASS] == ELF_TARG_CLASS &&
+ ehdr->e_ident[EI_DATA] == ELF_TARG_DATA &&
+ ehdr->e_ident[EI_VERSION] == ELF_TARG_VER) {
+
+ /* Now check the machine dependant header */
+ if (ehdr->e_machine == ELF_TARG_MACH &&
+ ehdr->e_version == ELF_TARG_VER)
+ retval = 1;
+ }
+ return retval;
+}
+
+int
+__elf_fdnlist(fd, list)
+ int fd;
+ struct nlist *list;
+{
+ struct nlist *p;
+ Elf_Off symoff = 0, symstroff = 0;
+ Elf_Size symsize = 0, symstrsize = 0;
+ Elf_Ssize cc, i;
+ int nent = -1;
+ int errsave;
+ Elf_Sym sbuf[1024];
+ Elf_Sym *s;
+ Elf_Ehdr ehdr;
+ char *strtab = NULL;
+ Elf_Shdr *shdr = NULL;
+ Elf_Size shdr_size;
+ void *base;
+ struct stat st;
+
+ /* Make sure obj is OK */
+ if (lseek(fd, (off_t)0, SEEK_SET) == -1 ||
+ _read(fd, &ehdr, sizeof(Elf_Ehdr)) != sizeof(Elf_Ehdr) ||
+ !__elf_is_okay__(&ehdr) ||
+ _fstat(fd, &st) < 0)
+ return (-1);
+
+ /* calculate section header table size */
+ shdr_size = ehdr.e_shentsize * ehdr.e_shnum;
+
+ /* Make sure it's not too big to mmap */
+ if (shdr_size > SIZE_T_MAX) {
+ errno = EFBIG;
+ return (-1);
+ }
+
+ /* mmap section header table */
+ base = mmap(NULL, (size_t)shdr_size, PROT_READ, 0, fd,
+ (off_t)ehdr.e_shoff);
+ if (base == MAP_FAILED)
+ return (-1);
+ shdr = (Elf_Shdr *)base;
+
+ /*
+ * Find the symbol table entry and it's corresponding
+ * string table entry. Version 1.1 of the ABI states
+ * that there is only one symbol table but that this
+ * could change in the future.
+ */
+ for (i = 0; i < ehdr.e_shnum; i++) {
+ if (shdr[i].sh_type == SHT_SYMTAB) {
+ symoff = shdr[i].sh_offset;
+ symsize = shdr[i].sh_size;
+ symstroff = shdr[shdr[i].sh_link].sh_offset;
+ symstrsize = shdr[shdr[i].sh_link].sh_size;
+ break;
+ }
+ }
+
+ /* Check for files too large to mmap. */
+ if (symstrsize > SIZE_T_MAX) {
+ errno = EFBIG;
+ goto done;
+ }
+ /*
+ * Map string table into our address space. This gives us
+ * an easy way to randomly access all the strings, without
+ * making the memory allocation permanent as with malloc/free
+ * (i.e., munmap will return it to the system).
+ */
+ base = mmap(NULL, (size_t)symstrsize, PROT_READ, 0, fd,
+ (off_t)symstroff);
+ if (base == MAP_FAILED)
+ goto done;
+ strtab = (char *)base;
+
+ /*
+ * clean out any left-over information for all valid entries.
+ * Type and value defined to be 0 if not found; historical
+ * versions cleared other and desc as well. Also figure out
+ * the largest string length so don't read any more of the
+ * string table than we have to.
+ *
+ * XXX clearing anything other than n_type and n_value violates
+ * the semantics given in the man page.
+ */
+ nent = 0;
+ for (p = list; !ISLAST(p); ++p) {
+ p->n_type = 0;
+ p->n_other = 0;
+ p->n_desc = 0;
+ p->n_value = 0;
+ ++nent;
+ }
+
+ /* Don't process any further if object is stripped. */
+ if (symoff == 0)
+ goto done;
+
+ if (lseek(fd, (off_t) symoff, SEEK_SET) == -1) {
+ nent = -1;
+ goto done;
+ }
+
+ while (symsize > 0 && nent > 0) {
+ cc = MIN(symsize, sizeof(sbuf));
+ if (_read(fd, sbuf, cc) != cc)
+ break;
+ symsize -= cc;
+ for (s = sbuf; cc > 0 && nent > 0; ++s, cc -= sizeof(*s)) {
+ char *name;
+ struct nlist *p;
+
+ name = strtab + s->st_name;
+ if (name[0] == '\0')
+ continue;
+ for (p = list; !ISLAST(p); p++) {
+ if ((p->n_un.n_name[0] == '_' &&
+ strcmp(name, p->n_un.n_name+1) == 0)
+ || strcmp(name, p->n_un.n_name) == 0) {
+ elf_sym_to_nlist(p, s, shdr,
+ ehdr.e_shnum);
+ if (--nent <= 0)
+ break;
+ }
+ }
+ }
+ }
+ done:
+ errsave = errno;
+ if (strtab != NULL)
+ munmap(strtab, symstrsize);
+ if (shdr != NULL)
+ munmap(shdr, shdr_size);
+ errno = errsave;
+ return (nent);
+}
+
+/*
+ * Convert an Elf_Sym into an nlist structure. This fills in only the
+ * n_value and n_type members.
+ */
+static void
+elf_sym_to_nlist(nl, s, shdr, shnum)
+ struct nlist *nl;
+ Elf_Sym *s;
+ Elf_Shdr *shdr;
+ int shnum;
+{
+ nl->n_value = s->st_value;
+
+ switch (s->st_shndx) {
+ case SHN_UNDEF:
+ case SHN_COMMON:
+ nl->n_type = N_UNDF;
+ break;
+ case SHN_ABS:
+ nl->n_type = ELF_ST_TYPE(s->st_info) == STT_FILE ?
+ N_FN : N_ABS;
+ break;
+ default:
+ if (s->st_shndx >= shnum)
+ nl->n_type = N_UNDF;
+ else {
+ Elf_Shdr *sh = shdr + s->st_shndx;
+
+ nl->n_type = sh->sh_type == SHT_PROGBITS ?
+ (sh->sh_flags & SHF_WRITE ? N_DATA : N_TEXT) :
+ (sh->sh_type == SHT_NOBITS ? N_BSS : N_UNDF);
+ }
+ break;
+ }
+
+ if (ELF_ST_BIND(s->st_info) == STB_GLOBAL ||
+ ELF_ST_BIND(s->st_info) == STB_WEAK)
+ nl->n_type |= N_EXT;
+}
+#endif /* _NLIST_DO_ELF */
diff --git a/lib/libc/gen/nrand48.c b/lib/libc/gen/nrand48.c
new file mode 100644
index 0000000..16c8ca1
--- /dev/null
+++ b/lib/libc/gen/nrand48.c
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "rand48.h"
+
+long
+nrand48(unsigned short xseed[3])
+{
+ _dorand48(xseed);
+ return ((long) xseed[2] << 15) + ((long) xseed[1] >> 1);
+}
diff --git a/lib/libc/gen/opendir.c b/lib/libc/gen/opendir.c
new file mode 100644
index 0000000..3beead7
--- /dev/null
+++ b/lib/libc/gen/opendir.c
@@ -0,0 +1,314 @@
+/*-
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)opendir.c 8.8 (Berkeley) 5/1/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "telldir.h"
+
+static DIR * __opendir_common(int, const char *, int);
+
+/*
+ * Open a directory.
+ */
+DIR *
+opendir(const char *name)
+{
+
+ return (__opendir2(name, DTF_HIDEW|DTF_NODUP));
+}
+
+/*
+ * Open a directory with existing file descriptor.
+ */
+DIR *
+fdopendir(int fd)
+{
+ struct stat statb;
+
+ /* Check that fd is associated with a directory. */
+ if (_fstat(fd, &statb) != 0)
+ return (NULL);
+ if (!S_ISDIR(statb.st_mode)) {
+ errno = ENOTDIR;
+ return (NULL);
+ }
+ if (_fcntl(fd, F_SETFD, FD_CLOEXEC) == -1)
+ return (NULL);
+ return (__opendir_common(fd, NULL, DTF_HIDEW|DTF_NODUP));
+}
+
+DIR *
+__opendir2(const char *name, int flags)
+{
+ int fd;
+ DIR *dir;
+ int saved_errno;
+
+ if ((fd = _open(name,
+ O_RDONLY | O_NONBLOCK | O_DIRECTORY | O_CLOEXEC)) == -1)
+ return (NULL);
+
+ dir = __opendir_common(fd, name, flags);
+ if (dir == NULL) {
+ saved_errno = errno;
+ _close(fd);
+ errno = saved_errno;
+ }
+ return (dir);
+}
+
+static int
+opendir_compar(const void *p1, const void *p2)
+{
+
+ return (strcmp((*(const struct dirent **)p1)->d_name,
+ (*(const struct dirent **)p2)->d_name));
+}
+
+/*
+ * Common routine for opendir(3), __opendir2(3) and fdopendir(3).
+ */
+static DIR *
+__opendir_common(int fd, const char *name, int flags)
+{
+ DIR *dirp;
+ int incr;
+ int saved_errno;
+ int unionstack;
+ int fd2;
+
+ if ((dirp = malloc(sizeof(DIR) + sizeof(struct _telldir))) == NULL)
+ return (NULL);
+
+ dirp->dd_td = (struct _telldir *)((char *)dirp + sizeof(DIR));
+ LIST_INIT(&dirp->dd_td->td_locq);
+ dirp->dd_td->td_loccnt = 0;
+
+ /*
+ * Use the system page size if that is a multiple of DIRBLKSIZ.
+ * Hopefully this can be a big win someday by allowing page
+ * trades to user space to be done by _getdirentries().
+ */
+ incr = getpagesize();
+ if ((incr % DIRBLKSIZ) != 0)
+ incr = DIRBLKSIZ;
+
+ /*
+ * Determine whether this directory is the top of a union stack.
+ */
+ if (flags & DTF_NODUP) {
+ struct statfs sfb;
+
+ if (_fstatfs(fd, &sfb) < 0)
+ goto fail;
+ unionstack = !strcmp(sfb.f_fstypename, "unionfs")
+ || (sfb.f_flags & MNT_UNION);
+ } else {
+ unionstack = 0;
+ }
+
+ if (unionstack) {
+ int len = 0;
+ int space = 0;
+ char *buf = 0;
+ char *ddptr = 0;
+ char *ddeptr;
+ int n;
+ struct dirent **dpv;
+
+ /*
+ * The strategy here is to read all the directory
+ * entries into a buffer, sort the buffer, and
+ * remove duplicate entries by setting the inode
+ * number to zero.
+ */
+
+ do {
+ /*
+ * Always make at least DIRBLKSIZ bytes
+ * available to _getdirentries
+ */
+ if (space < DIRBLKSIZ) {
+ space += incr;
+ len += incr;
+ buf = reallocf(buf, len);
+ if (buf == NULL)
+ goto fail;
+ ddptr = buf + (len - space);
+ }
+
+ n = _getdirentries(fd, ddptr, space, &dirp->dd_seek);
+ if (n > 0) {
+ ddptr += n;
+ space -= n;
+ }
+ } while (n > 0);
+
+ ddeptr = ddptr;
+ flags |= __DTF_READALL;
+
+ /*
+ * Re-open the directory.
+ * This has the effect of rewinding back to the
+ * top of the union stack and is needed by
+ * programs which plan to fchdir to a descriptor
+ * which has also been read -- see fts.c.
+ */
+ if (flags & DTF_REWIND) {
+ if ((fd2 = _open(name, O_RDONLY | O_DIRECTORY)) == -1) {
+ saved_errno = errno;
+ free(buf);
+ free(dirp);
+ errno = saved_errno;
+ return (NULL);
+ }
+ (void)_dup2(fd2, fd);
+ _close(fd2);
+ }
+
+ /*
+ * There is now a buffer full of (possibly) duplicate
+ * names.
+ */
+ dirp->dd_buf = buf;
+
+ /*
+ * Go round this loop twice...
+ *
+ * Scan through the buffer, counting entries.
+ * On the second pass, save pointers to each one.
+ * Then sort the pointers and remove duplicate names.
+ */
+ for (dpv = 0;;) {
+ n = 0;
+ ddptr = buf;
+ while (ddptr < ddeptr) {
+ struct dirent *dp;
+
+ dp = (struct dirent *) ddptr;
+ if ((long)dp & 03L)
+ break;
+ if ((dp->d_reclen <= 0) ||
+ (dp->d_reclen > (ddeptr + 1 - ddptr)))
+ break;
+ ddptr += dp->d_reclen;
+ if (dp->d_fileno) {
+ if (dpv)
+ dpv[n] = dp;
+ n++;
+ }
+ }
+
+ if (dpv) {
+ struct dirent *xp;
+
+ /*
+ * This sort must be stable.
+ */
+ mergesort(dpv, n, sizeof(*dpv),
+ opendir_compar);
+
+ dpv[n] = NULL;
+ xp = NULL;
+
+ /*
+ * Scan through the buffer in sort order,
+ * zapping the inode number of any
+ * duplicate names.
+ */
+ for (n = 0; dpv[n]; n++) {
+ struct dirent *dp = dpv[n];
+
+ if ((xp == NULL) ||
+ strcmp(dp->d_name, xp->d_name)) {
+ xp = dp;
+ } else {
+ dp->d_fileno = 0;
+ }
+ if (dp->d_type == DT_WHT &&
+ (flags & DTF_HIDEW))
+ dp->d_fileno = 0;
+ }
+
+ free(dpv);
+ break;
+ } else {
+ dpv = malloc((n+1) * sizeof(struct dirent *));
+ if (dpv == NULL)
+ break;
+ }
+ }
+
+ dirp->dd_len = len;
+ dirp->dd_size = ddptr - dirp->dd_buf;
+ } else {
+ dirp->dd_len = incr;
+ dirp->dd_size = 0;
+ dirp->dd_buf = malloc(dirp->dd_len);
+ if (dirp->dd_buf == NULL)
+ goto fail;
+ dirp->dd_seek = 0;
+ flags &= ~DTF_REWIND;
+ }
+
+ dirp->dd_loc = 0;
+ dirp->dd_fd = fd;
+ dirp->dd_flags = flags;
+ dirp->dd_lock = NULL;
+
+ /*
+ * Set up seek point for rewinddir.
+ */
+ dirp->dd_rewind = telldir(dirp);
+
+ return (dirp);
+
+fail:
+ saved_errno = errno;
+ free(dirp);
+ errno = saved_errno;
+ return (NULL);
+}
diff --git a/lib/libc/gen/pause.3 b/lib/libc/gen/pause.3
new file mode 100644
index 0000000..ce715d2
--- /dev/null
+++ b/lib/libc/gen/pause.3
@@ -0,0 +1,82 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)pause.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt PAUSE 3
+.Os
+.Sh NAME
+.Nm pause
+.Nd stop until signal
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn pause void
+.Sh DESCRIPTION
+.Sy Pause is made obsolete by
+.Xr sigsuspend 2 .
+.Pp
+The
+.Fn pause
+function
+forces a process to pause until
+a signal is received from either the
+.Xr kill 2
+function
+or an interval timer.
+(See
+.Xr setitimer 2 . )
+Upon termination of a signal handler started during a
+.Fn pause ,
+the
+.Fn pause
+call will return.
+.Sh RETURN VALUES
+Always returns \-1.
+.Sh ERRORS
+The
+.Fn pause
+function
+always returns:
+.Bl -tag -width Er
+.It Bq Er EINTR
+The call was interrupted.
+.El
+.Sh SEE ALSO
+.Xr kill 2 ,
+.Xr select 2 ,
+.Xr sigsuspend 2
+.Sh HISTORY
+A
+.Fn pause
+syscall
+appeared in
+.At v6 .
diff --git a/lib/libc/gen/pause.c b/lib/libc/gen/pause.c
new file mode 100644
index 0000000..51706cf
--- /dev/null
+++ b/lib/libc/gen/pause.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)pause.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <signal.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+/*
+ * Backwards compatible pause.
+ */
+int
+__pause(void)
+{
+ sigset_t oset;
+
+ if (_sigprocmask(SIG_BLOCK, NULL, &oset) == -1)
+ return (-1);
+ return (_sigsuspend(&oset));
+}
+__weak_reference(__pause, pause);
+__weak_reference(__pause, _pause);
diff --git a/lib/libc/gen/pmadvise.c b/lib/libc/gen/pmadvise.c
new file mode 100644
index 0000000..60cef63
--- /dev/null
+++ b/lib/libc/gen/pmadvise.c
@@ -0,0 +1,16 @@
+/*
+ * The contents of this file are in the public domain.
+ * Written by Garrett A. Wollman, 2000-10-07.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/mman.h>
+
+int
+posix_madvise(void *address, size_t size, int how)
+{
+ return madvise(address, size, how);
+}
diff --git a/lib/libc/gen/popen.3 b/lib/libc/gen/popen.3
new file mode 100644
index 0000000..90297e4
--- /dev/null
+++ b/lib/libc/gen/popen.3
@@ -0,0 +1,197 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)popen.3 8.2 (Berkeley) 5/3/95
+.\" $FreeBSD$
+.\"
+.Dd May 3, 1995
+.Dt POPEN 3
+.Os
+.Sh NAME
+.Nm popen ,
+.Nm pclose
+.Nd process
+.Tn I/O
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft FILE *
+.Fn popen "const char *command" "const char *type"
+.Ft int
+.Fn pclose "FILE *stream"
+.Sh DESCRIPTION
+The
+.Fn popen
+function
+.Dq opens
+a process by creating a bidirectional pipe
+forking,
+and invoking the shell.
+Any streams opened by previous
+.Fn popen
+calls in the parent process are closed in the new child process.
+Historically,
+.Fn popen
+was implemented with a unidirectional pipe;
+hence many implementations of
+.Fn popen
+only allow the
+.Fa type
+argument to specify reading or writing, not both.
+Since
+.Fn popen
+is now implemented using a bidirectional pipe, the
+.Fa type
+argument may request a bidirectional data flow.
+The
+.Fa type
+argument is a pointer to a null-terminated string
+which must be
+.Ql r
+for reading,
+.Ql w
+for writing, or
+.Ql r+
+for reading and writing.
+.Pp
+The
+.Fa command
+argument is a pointer to a null-terminated string
+containing a shell command line.
+This command is passed to
+.Pa /bin/sh
+using the
+.Fl c
+flag; interpretation, if any, is performed by the shell.
+.Pp
+The return value from
+.Fn popen
+is a normal standard
+.Tn I/O
+stream in all respects
+save that it must be closed with
+.Fn pclose
+rather than
+.Fn fclose .
+Writing to such a stream
+writes to the standard input of the command;
+the command's standard output is the same as that of the process that called
+.Fn popen ,
+unless this is altered by the command itself.
+Conversely, reading from a
+.Dq popened
+stream reads the command's standard output, and
+the command's standard input is the same as that of the process that called
+.Fn popen .
+.Pp
+Note that output
+.Fn popen
+streams are fully buffered by default.
+.Pp
+The
+.Fn pclose
+function waits for the associated process to terminate
+and returns the exit status of the command
+as returned by
+.Xr wait4 2 .
+.Sh RETURN VALUES
+The
+.Fn popen
+function returns
+.Dv NULL
+if the
+.Xr fork 2
+or
+.Xr pipe 2
+calls fail,
+or if it cannot allocate memory.
+.Pp
+The
+.Fn pclose
+function
+returns \-1 if
+.Fa stream
+is not associated with a
+.Dq popened
+command, if
+.Fa stream
+already
+.Dq pclosed ,
+or if
+.Xr wait4 2
+returns an error.
+.Sh ERRORS
+The
+.Fn popen
+function does not reliably set
+.Va errno .
+.Sh SEE ALSO
+.Xr sh 1 ,
+.Xr fork 2 ,
+.Xr pipe 2 ,
+.Xr wait4 2 ,
+.Xr fclose 3 ,
+.Xr fflush 3 ,
+.Xr fopen 3 ,
+.Xr stdio 3 ,
+.Xr system 3
+.Sh HISTORY
+A
+.Fn popen
+and a
+.Fn pclose
+function appeared in
+.At v7 .
+.Pp
+Bidirectional functionality was added in
+.Fx 2.2.6 .
+.Sh BUGS
+Since the standard input of a command opened for reading
+shares its seek offset with the process that called
+.Fn popen ,
+if the original process has done a buffered read,
+the command's input position may not be as expected.
+Similarly, the output from a command opened for writing
+may become intermingled with that of the original process.
+The latter can be avoided by calling
+.Xr fflush 3
+before
+.Fn popen .
+.Pp
+Failure to execute the shell
+is indistinguishable from the shell's failure to execute command,
+or an immediate exit of the command.
+The only hint is an exit status of 127.
+.Pp
+The
+.Fn popen
+function
+always calls
+.Xr sh 1 ,
+never calls
+.Xr csh 1 .
diff --git a/lib/libc/gen/popen.c b/lib/libc/gen/popen.c
new file mode 100644
index 0000000..b123234
--- /dev/null
+++ b/lib/libc/gen/popen.c
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software written by Ken Arnold and
+ * published in UNIX Review, Vol. 6, No. 8.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)popen.c 8.3 (Berkeley) 5/3/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/wait.h>
+
+#include <signal.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+#include <pthread.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+extern char **environ;
+
+struct pid {
+ SLIST_ENTRY(pid) next;
+ FILE *fp;
+ pid_t pid;
+};
+static SLIST_HEAD(, pid) pidlist = SLIST_HEAD_INITIALIZER(pidlist);
+static pthread_mutex_t pidlist_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#define THREAD_LOCK() if (__isthreaded) _pthread_mutex_lock(&pidlist_mutex)
+#define THREAD_UNLOCK() if (__isthreaded) _pthread_mutex_unlock(&pidlist_mutex)
+
+FILE *
+popen(command, type)
+ const char *command, *type;
+{
+ struct pid *cur;
+ FILE *iop;
+ int pdes[2], pid, twoway;
+ char *argv[4];
+ struct pid *p;
+
+ /*
+ * Lite2 introduced two-way popen() pipes using _socketpair().
+ * FreeBSD's pipe() is bidirectional, so we use that.
+ */
+ if (strchr(type, '+')) {
+ twoway = 1;
+ type = "r+";
+ } else {
+ twoway = 0;
+ if ((*type != 'r' && *type != 'w') || type[1])
+ return (NULL);
+ }
+ if (pipe(pdes) < 0)
+ return (NULL);
+
+ if ((cur = malloc(sizeof(struct pid))) == NULL) {
+ (void)_close(pdes[0]);
+ (void)_close(pdes[1]);
+ return (NULL);
+ }
+
+ argv[0] = "sh";
+ argv[1] = "-c";
+ argv[2] = (char *)command;
+ argv[3] = NULL;
+
+ THREAD_LOCK();
+ switch (pid = vfork()) {
+ case -1: /* Error. */
+ THREAD_UNLOCK();
+ (void)_close(pdes[0]);
+ (void)_close(pdes[1]);
+ free(cur);
+ return (NULL);
+ /* NOTREACHED */
+ case 0: /* Child. */
+ if (*type == 'r') {
+ /*
+ * The _dup2() to STDIN_FILENO is repeated to avoid
+ * writing to pdes[1], which might corrupt the
+ * parent's copy. This isn't good enough in
+ * general, since the _exit() is no return, so
+ * the compiler is free to corrupt all the local
+ * variables.
+ */
+ (void)_close(pdes[0]);
+ if (pdes[1] != STDOUT_FILENO) {
+ (void)_dup2(pdes[1], STDOUT_FILENO);
+ (void)_close(pdes[1]);
+ if (twoway)
+ (void)_dup2(STDOUT_FILENO, STDIN_FILENO);
+ } else if (twoway && (pdes[1] != STDIN_FILENO))
+ (void)_dup2(pdes[1], STDIN_FILENO);
+ } else {
+ if (pdes[0] != STDIN_FILENO) {
+ (void)_dup2(pdes[0], STDIN_FILENO);
+ (void)_close(pdes[0]);
+ }
+ (void)_close(pdes[1]);
+ }
+ SLIST_FOREACH(p, &pidlist, next)
+ (void)_close(fileno(p->fp));
+ _execve(_PATH_BSHELL, argv, environ);
+ _exit(127);
+ /* NOTREACHED */
+ }
+ THREAD_UNLOCK();
+
+ /* Parent; assume fdopen can't fail. */
+ if (*type == 'r') {
+ iop = fdopen(pdes[0], type);
+ (void)_close(pdes[1]);
+ } else {
+ iop = fdopen(pdes[1], type);
+ (void)_close(pdes[0]);
+ }
+
+ /* Link into list of file descriptors. */
+ cur->fp = iop;
+ cur->pid = pid;
+ THREAD_LOCK();
+ SLIST_INSERT_HEAD(&pidlist, cur, next);
+ THREAD_UNLOCK();
+
+ return (iop);
+}
+
+/*
+ * pclose --
+ * Pclose returns -1 if stream is not associated with a `popened' command,
+ * if already `pclosed', or waitpid returns an error.
+ */
+int
+pclose(iop)
+ FILE *iop;
+{
+ struct pid *cur, *last = NULL;
+ int pstat;
+ pid_t pid;
+
+ /*
+ * Find the appropriate file pointer and remove it from the list.
+ */
+ THREAD_LOCK();
+ SLIST_FOREACH(cur, &pidlist, next) {
+ if (cur->fp == iop)
+ break;
+ last = cur;
+ }
+ if (cur == NULL) {
+ THREAD_UNLOCK();
+ return (-1);
+ }
+ if (last == NULL)
+ SLIST_REMOVE_HEAD(&pidlist, next);
+ else
+ SLIST_REMOVE_AFTER(last, next);
+ THREAD_UNLOCK();
+
+ (void)fclose(iop);
+
+ do {
+ pid = _wait4(cur->pid, &pstat, 0, (struct rusage *)0);
+ } while (pid == -1 && errno == EINTR);
+
+ free(cur);
+
+ return (pid == -1 ? -1 : pstat);
+}
diff --git a/lib/libc/gen/posix_spawn.3 b/lib/libc/gen/posix_spawn.3
new file mode 100644
index 0000000..73359b4
--- /dev/null
+++ b/lib/libc/gen/posix_spawn.3
@@ -0,0 +1,460 @@
+.\" Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 17, 2011
+.Dt POSIX_SPAWN 3
+.Os
+.Sh NAME
+.Nm posix_spawn ,
+.Nm posix_spawnp
+.Nd "spawn a process"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In spawn.h
+.Ft int
+.Fn posix_spawn "pid_t *restrict pid" "const char *restrict path" "const posix_spawn_file_actions_t *file_actions" "const posix_spawnattr_t *restrict attrp" "char *const argv[restrict]" "char *const envp[restrict]"
+.Ft int
+.Fn posix_spawnp "pid_t *restrict pid" "const char *restrict file" "const posix_spawn_file_actions_t *file_actions" "const posix_spawnattr_t *restrict attrp" "char *const argv[restrict]" "char *const envp[restrict]"
+.Sh DESCRIPTION
+The
+.Fn posix_spawn
+and
+.Fn posix_spawnp
+functions create a new process (child process) from the specified
+process image.
+The new process image is constructed from a regular executable
+file called the new process image file.
+.Pp
+When a C program is executed as the result of this call, it is
+entered as a C-language function call as follows:
+.Bd -literal -offset indent
+int main(int argc, char *argv[]);
+.Ed
+.Pp
+where
+.Fa argc
+is the argument count and
+.Fa argv
+is an array of character pointers to the arguments themselves.
+In addition, the variable:
+.Bd -literal -offset indent
+extern char **environ;
+.Ed
+.Pp
+points to an array of character pointers to
+the environment strings.
+.Pp
+The argument
+.Fa argv
+is an array of character pointers to null-terminated
+strings.
+The last member of this array is a null pointer and is not counted
+in
+.Fa argc .
+These strings constitute the argument list available to the new process
+image.
+The value in
+.Fa argv Ns [0]
+should point to
+a filename that is associated with the process image being started by
+the
+.Fn posix_spawn
+or
+.Fn posix_spawnp
+function.
+.Pp
+The argument
+.Fa envp
+is an array of character pointers to null-terminated strings.
+These strings constitute the environment for the new process image.
+The environment array is terminated by a null pointer.
+.Pp
+The
+.Fa path
+argument to
+.Fn posix_spawn
+is a pathname that identifies the new process image file to execute.
+.Pp
+The
+.Fa file
+parameter to
+.Fn posix_spawnp
+is used to construct a pathname that identifies the new process
+image file.
+If the file parameter contains a slash character, the file parameter
+is used as the pathname for the new process image file.
+Otherwise, the path prefix for this file is obtained by a search
+of the directories passed as the environment variable
+.Dq Ev PATH .
+If this variable is not specified,
+the default path is set according to the
+.Dv _PATH_DEFPATH
+definition in
+.In paths.h ,
+which is set to
+.Dq Ev /usr/bin:/bin .
+.Pp
+If
+.Fa file_actions
+is a null pointer, then file descriptors open in the
+calling process remain open in the child process, except for those
+whose close-on-exec flag
+.Dv FD_CLOEXEC
+is set (see
+.Fn fcntl ) .
+For those
+file descriptors that remain open, all attributes of the corresponding
+open file descriptions, including file locks (see
+.Fn fcntl ) ,
+remain unchanged.
+.Pp
+If
+.Fa file_actions
+is not NULL, then the file descriptors open in the child process are
+those open in the calling process as modified by the spawn file
+actions object pointed to by
+.Fa file_actions
+and the
+.Dv FD_CLOEXEC
+flag of each remaining open file descriptor after the spawn file actions
+have been processed.
+The effective order of processing the spawn file actions are:
+.Bl -enum
+.It
+The set of open file descriptors for the child process initially
+are the same set as is open for the calling process.
+All attributes of the corresponding open file descriptions, including
+file locks (see
+.Fn fcntl ) ,
+remain unchanged.
+.It
+The signal mask, signal default actions, and the effective user and
+group IDs for the child process are changed as specified in the
+attributes object referenced by
+.Fa attrp .
+.It
+The file actions specified by the spawn file actions object are
+performed in the order in which they were added to the spawn file
+actions object.
+.It
+Any file descriptor that has its
+.Dv FD_CLOEXEC
+flag set (see
+.Fn fcntl )
+is closed.
+.El
+.Pp
+The
+.Vt posix_spawnattr_t
+spawn attributes object type is defined in
+.In spawn.h .
+It contains the attributes defined below.
+.Pp
+If the
+.Dv POSIX_SPAWN_SETPGROUP
+flag is set in the spawn-flags attribute of the object referenced by
+.Fa attrp ,
+and the spawn-pgroup attribute of the same object is non-zero, then the
+child's process group is as specified in the spawn-pgroup
+attribute of the object referenced by
+.Fa attrp .
+.Pp
+As a special case, if the
+.Dv POSIX_SPAWN_SETPGROUP
+flag is set in the spawn-flags attribute of the object referenced by
+.Fa attrp ,
+and the spawn-pgroup attribute of the same object is set to zero, then
+the child is in a new process group with a process group ID equal
+to its process ID.
+.Pp
+If the
+.Dv POSIX_SPAWN_SETPGROUP
+flag is not set in the spawn-flags attribute of the object referenced by
+.Fa attrp ,
+the new child process inherits the parent's process group.
+.Pp
+If the
+.Dv POSIX_SPAWN_SETSCHEDPARAM
+flag is set in the spawn-flags attribute of the object referenced by
+.Fa attrp ,
+but
+.Dv POSIX_SPAWN_SETSCHEDULER
+is not set, the new process image initially has the scheduling
+policy of the calling process with the scheduling parameters specified
+in the spawn-schedparam attribute of the object referenced by
+.Fa attrp .
+.Pp
+If the
+.Dv POSIX_SPAWN_SETSCHEDULER
+flag is set in the spawn-flags attribute of the object referenced by
+.Fa attrp
+(regardless of the setting of the
+.Dv POSIX_SPAWN_SETSCHEDPARAM
+flag), the new process image initially has the scheduling policy
+specified in the spawn-schedpolicy attribute of the object referenced by
+.Fa attrp
+and the scheduling parameters specified in the spawn-schedparam
+attribute of the same object.
+.Pp
+The
+.Dv POSIX_SPAWN_RESETIDS
+flag in the spawn-flags attribute of the object referenced by
+.Fa attrp
+governs the effective user ID of the child process.
+If this flag is not set, the child process inherits the parent
+process' effective user ID.
+If this flag is set, the child process' effective user ID is reset
+to the parent's real user ID.
+In either case, if the set-user-ID mode bit of the new process image
+file is set, the effective user ID of the child process becomes
+that file's owner ID before the new process image begins execution.
+.Pp
+The
+.Dv POSIX_SPAWN_RESETIDS
+flag in the spawn-flags attribute of the object referenced by
+.Fa attrp
+also governs the effective group ID of the child process.
+If this flag is not set, the child process inherits the parent
+process' effective group ID.
+If this flag is set, the child process' effective group ID is
+reset to the parent's real group ID.
+In either case, if the set-group-ID mode bit of the new process image
+file is set, the effective group ID of the child process becomes
+that file's group ID before the new process image begins execution.
+.Pp
+If the
+.Dv POSIX_SPAWN_SETSIGMASK
+flag is set in the spawn-flags attribute of the object referenced by
+.Fa attrp ,
+the child process initially has the signal mask specified in the
+spawn-sigmask attribute of the object referenced by
+.Fa attrp .
+.Pp
+If the
+.Dv POSIX_SPAWN_SETSIGDEF
+flag is set in the spawn-flags attribute of the object referenced by
+.Fa attrp ,
+the signals specified in the spawn-sigdefault attribute of the same
+object is set to their default actions in the child process.
+Signals set to the default action in the parent process is set to
+the default action in the child process.
+.Pp
+Signals set to be caught by the calling process is set to the
+default action in the child process.
+.Pp
+Signals set to be ignored by the calling process image is set to
+be ignored by the child process, unless otherwise specified by the
+.Dv POSIX_SPAWN_SETSIGDEF
+flag being set in the spawn-flags attribute of the object referenced by
+.Fa attrp
+and the signals being indicated in the spawn-sigdefault attribute
+of the object referenced by
+.Fa attrp .
+.Pp
+If the value of the
+.Fa attrp
+pointer is NULL, then the default values are used.
+.Pp
+All process attributes, other than those influenced by the attributes
+set in the object referenced by
+.Fa attrp
+as specified above or by the file descriptor manipulations specified in
+.Fa file_actions ,
+appear in the new process image as though
+.Fn vfork
+had been called to create a child process and then
+.Fn execve
+had been called by the child process to execute the new process image.
+.Pp
+The implementation uses vfork(), thus the fork handlers are not run when
+.Fn posix_spawn
+or
+.Fn posix_spawnp
+is called.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn posix_spawn
+and
+.Fn posix_spawnp
+return the process ID of the child process to the parent process,
+in the variable pointed to by a non-NULL
+.Fa pid
+argument, and return zero as the function return value.
+Otherwise, no child process is created, no value is stored into
+the variable pointed to by
+.Fa pid ,
+and an error number is returned as the function return value to
+indicate the error.
+If the
+.Fa pid
+argument is a null pointer, the process ID of the child is not returned
+to the caller.
+.Sh ERRORS
+.Bl -enum
+.It
+If
+.Fn posix_spawn
+and
+.Fn posix_spawnp
+fail for any of the reasons that would cause
+.Fn vfork
+or one of the
+.Nm exec
+to fail, an error value is returned as described by
+.Fn vfork
+and
+.Nm exec ,
+respectively (or, if the error occurs after the calling process successfully
+returns, the child process exits with exit status 127).
+.It
+If
+.Nm POSIX_SPAWN_SETPGROUP
+is set in the spawn-flags attribute of the object referenced by attrp, and
+.Fn posix_spawn
+or
+.Fn posix_spawnp
+fails while changing the child's process group, an error value is returned as
+described by
+.Fn setpgid
+(or, if the error occurs after the calling process successfully returns,
+the child process exits with exit status 127).
+.It
+If
+.Nm POSIX_SPAWN_SETSCHEDPARAM
+is set and
+.Nm POSIX_SPAWN_SETSCHEDULER
+is not set in the spawn-flags attribute of the object referenced by attrp, then
+if
+.Fn posix_spawn
+or
+.Fn posix_spawnp
+fails for any of the reasons that would cause
+.Fn sched_setparam
+to fail, an error value is returned as described by
+.Fn sched_setparam
+(or, if the error occurs after the calling process successfully returns, the
+child process exits with exit status 127).
+.It
+If
+.Nm POSIX_SPAWN_SETSCHEDULER
+is set in the spawn-flags attribute of the object referenced by attrp, and if
+.Fn posix_spawn
+or
+.Fn posix_spawnp
+fails for any of the reasons that would cause
+.Fn sched_setscheduler
+to fail, an error value is returned as described by
+.Fn sched_setscheduler
+(or, if the error occurs after the calling process successfully returns,
+the child process exits with exit status 127).
+.It
+If the
+.Fa file_actions
+argument is not NULL, and specifies any dup2 or open actions to be
+performed, and if
+.Fn posix_spawn
+or
+.Fn posix_spawnp
+fails for any of the reasons that would cause
+.Fn dup2
+or
+.Fn open
+to fail, an error value is returned as described by
+.Fn dup2
+and
+.Fn open ,
+respectively (or, if the error occurs after the calling process successfully
+returns, the child process exits with exit status 127). An open file action
+may, by itself, result in any of the errors described by
+.Fn dup2 ,
+in addition to those described by
+.Fn open .
+This implementation ignores any errors from
+.Fn close ,
+including trying to close a descriptor that is not open.
+.El
+.Sh SEE ALSO
+.Xr close 2 ,
+.Xr dup2 2 ,
+.Xr execve 2 ,
+.Xr fcntl 2 ,
+.Xr open 2 ,
+.Xr posix_spawn_file_actions_addclose 3 ,
+.Xr posix_spawn_file_actions_adddup2 3 ,
+.Xr posix_spawn_file_actions_addopen 3 ,
+.Xr posix_spawn_file_actions_destroy 3 ,
+.Xr posix_spawn_file_actions_init 3 ,
+.Xr posix_spawnattr_destroy 3 ,
+.Xr posix_spawnattr_getflags 3 ,
+.Xr posix_spawnattr_getpgroup 3 ,
+.Xr posix_spawnattr_getschedparam 3 ,
+.Xr posix_spawnattr_getschedpolicy 3 ,
+.Xr posix_spawnattr_getsigdefault 3 ,
+.Xr posix_spawnattr_getsigmask 3 ,
+.Xr posix_spawnattr_init 3 ,
+.Xr posix_spawnattr_setflags 3 ,
+.Xr posix_spawnattr_setpgroup 3 ,
+.Xr posix_spawnattr_setschedparam 3 ,
+.Xr posix_spawnattr_setschedpolicy 3 ,
+.Xr posix_spawnattr_setsigdefault 3 ,
+.Xr posix_spawnattr_setsigmask 3 ,
+.Xr sched_setparam 2 ,
+.Xr sched_setscheduler 2 ,
+.Xr setpgid 2 ,
+.Xr vfork 2
+.Sh STANDARDS
+The
+.Fn posix_spawn
+and
+.Fn posix_spawnp
+functions conform to
+.St -p1003.1-2001 ,
+except that they ignore all errors from
+.Fn close .
+A future update of the Standard is expected to require that these functions
+not fail because a file descriptor to be closed (via
+.Fn posix_spawn_file_actions_addclose )
+is not open.
+.Sh HISTORY
+The
+.Fn posix_spawn
+and
+.Fn posix_spawnp
+functions first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Ed Schouten Aq ed@FreeBSD.org
diff --git a/lib/libc/gen/posix_spawn.c b/lib/libc/gen/posix_spawn.c
new file mode 100644
index 0000000..e3124b2
--- /dev/null
+++ b/lib/libc/gen/posix_spawn.c
@@ -0,0 +1,475 @@
+/*-
+ * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/queue.h>
+#include <sys/wait.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <spawn.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+extern char **environ;
+
+struct __posix_spawnattr {
+ short sa_flags;
+ pid_t sa_pgroup;
+ struct sched_param sa_schedparam;
+ int sa_schedpolicy;
+ sigset_t sa_sigdefault;
+ sigset_t sa_sigmask;
+};
+
+struct __posix_spawn_file_actions {
+ STAILQ_HEAD(, __posix_spawn_file_actions_entry) fa_list;
+};
+
+typedef struct __posix_spawn_file_actions_entry {
+ STAILQ_ENTRY(__posix_spawn_file_actions_entry) fae_list;
+ enum { FAE_OPEN, FAE_DUP2, FAE_CLOSE } fae_action;
+
+ int fae_fildes;
+ union {
+ struct {
+ char *path;
+#define fae_path fae_data.open.path
+ int oflag;
+#define fae_oflag fae_data.open.oflag
+ mode_t mode;
+#define fae_mode fae_data.open.mode
+ } open;
+ struct {
+ int newfildes;
+#define fae_newfildes fae_data.dup2.newfildes
+ } dup2;
+ } fae_data;
+} posix_spawn_file_actions_entry_t;
+
+/*
+ * Spawn routines
+ */
+
+static int
+process_spawnattr(const posix_spawnattr_t sa)
+{
+ struct sigaction sigact = { .sa_flags = 0, .sa_handler = SIG_DFL };
+ int i;
+
+ /*
+ * POSIX doesn't really describe in which order everything
+ * should be set. We'll just set them in the order in which they
+ * are mentioned.
+ */
+
+ /* Set process group */
+ if (sa->sa_flags & POSIX_SPAWN_SETPGROUP) {
+ if (setpgid(0, sa->sa_pgroup) != 0)
+ return (errno);
+ }
+
+ /* Set scheduler policy */
+ if (sa->sa_flags & POSIX_SPAWN_SETSCHEDULER) {
+ if (sched_setscheduler(0, sa->sa_schedpolicy,
+ &sa->sa_schedparam) != 0)
+ return (errno);
+ } else if (sa->sa_flags & POSIX_SPAWN_SETSCHEDPARAM) {
+ if (sched_setparam(0, &sa->sa_schedparam) != 0)
+ return (errno);
+ }
+
+ /* Reset user ID's */
+ if (sa->sa_flags & POSIX_SPAWN_RESETIDS) {
+ if (setegid(getgid()) != 0)
+ return (errno);
+ if (seteuid(getuid()) != 0)
+ return (errno);
+ }
+
+ /* Set signal masks/defaults */
+ if (sa->sa_flags & POSIX_SPAWN_SETSIGMASK) {
+ _sigprocmask(SIG_SETMASK, &sa->sa_sigmask, NULL);
+ }
+
+ if (sa->sa_flags & POSIX_SPAWN_SETSIGDEF) {
+ for (i = 1; i <= _SIG_MAXSIG; i++) {
+ if (sigismember(&sa->sa_sigdefault, i))
+ if (_sigaction(i, &sigact, NULL) != 0)
+ return (errno);
+ }
+ }
+
+ return (0);
+}
+
+static int
+process_file_actions_entry(posix_spawn_file_actions_entry_t *fae)
+{
+ int fd;
+
+ switch (fae->fae_action) {
+ case FAE_OPEN:
+ /* Perform an open(), make it use the right fd */
+ fd = _open(fae->fae_path, fae->fae_oflag, fae->fae_mode);
+ if (fd < 0)
+ return (errno);
+ if (fd != fae->fae_fildes) {
+ if (_dup2(fd, fae->fae_fildes) == -1)
+ return (errno);
+ if (_close(fd) != 0) {
+ if (errno == EBADF)
+ return (EBADF);
+ }
+ }
+ if (_fcntl(fae->fae_fildes, F_SETFD, 0) == -1)
+ return (errno);
+ break;
+ case FAE_DUP2:
+ /* Perform a dup2() */
+ if (_dup2(fae->fae_fildes, fae->fae_newfildes) == -1)
+ return (errno);
+ if (_fcntl(fae->fae_newfildes, F_SETFD, 0) == -1)
+ return (errno);
+ break;
+ case FAE_CLOSE:
+ /* Perform a close(), do not fail if already closed */
+ (void)_close(fae->fae_fildes);
+ break;
+ }
+ return (0);
+}
+
+static int
+process_file_actions(const posix_spawn_file_actions_t fa)
+{
+ posix_spawn_file_actions_entry_t *fae;
+ int error;
+
+ /* Replay all file descriptor modifications */
+ STAILQ_FOREACH(fae, &fa->fa_list, fae_list) {
+ error = process_file_actions_entry(fae);
+ if (error)
+ return (error);
+ }
+ return (0);
+}
+
+static int
+do_posix_spawn(pid_t *pid, const char *path,
+ const posix_spawn_file_actions_t *fa,
+ const posix_spawnattr_t *sa,
+ char * const argv[], char * const envp[], int use_env_path)
+{
+ pid_t p;
+ volatile int error = 0;
+
+ p = vfork();
+ switch (p) {
+ case -1:
+ return (errno);
+ case 0:
+ if (sa != NULL) {
+ error = process_spawnattr(*sa);
+ if (error)
+ _exit(127);
+ }
+ if (fa != NULL) {
+ error = process_file_actions(*fa);
+ if (error)
+ _exit(127);
+ }
+ if (use_env_path)
+ _execvpe(path, argv, envp != NULL ? envp : environ);
+ else
+ _execve(path, argv, envp != NULL ? envp : environ);
+ error = errno;
+ _exit(127);
+ default:
+ if (error != 0)
+ _waitpid(p, NULL, WNOHANG);
+ else if (pid != NULL)
+ *pid = p;
+ return (error);
+ }
+}
+
+int
+posix_spawn(pid_t *pid, const char *path,
+ const posix_spawn_file_actions_t *fa,
+ const posix_spawnattr_t *sa,
+ char * const argv[], char * const envp[])
+{
+ return do_posix_spawn(pid, path, fa, sa, argv, envp, 0);
+}
+
+int
+posix_spawnp(pid_t *pid, const char *path,
+ const posix_spawn_file_actions_t *fa,
+ const posix_spawnattr_t *sa,
+ char * const argv[], char * const envp[])
+{
+ return do_posix_spawn(pid, path, fa, sa, argv, envp, 1);
+}
+
+/*
+ * File descriptor actions
+ */
+
+int
+posix_spawn_file_actions_init(posix_spawn_file_actions_t *ret)
+{
+ posix_spawn_file_actions_t fa;
+
+ fa = malloc(sizeof(struct __posix_spawn_file_actions));
+ if (fa == NULL)
+ return (-1);
+
+ STAILQ_INIT(&fa->fa_list);
+ *ret = fa;
+ return (0);
+}
+
+int
+posix_spawn_file_actions_destroy(posix_spawn_file_actions_t *fa)
+{
+ posix_spawn_file_actions_entry_t *fae;
+
+ while ((fae = STAILQ_FIRST(&(*fa)->fa_list)) != NULL) {
+ /* Remove file action entry from the queue */
+ STAILQ_REMOVE_HEAD(&(*fa)->fa_list, fae_list);
+
+ /* Deallocate file action entry */
+ if (fae->fae_action == FAE_OPEN)
+ free(fae->fae_path);
+ free(fae);
+ }
+
+ free(*fa);
+ return (0);
+}
+
+int
+posix_spawn_file_actions_addopen(posix_spawn_file_actions_t * __restrict fa,
+ int fildes, const char * __restrict path, int oflag, mode_t mode)
+{
+ posix_spawn_file_actions_entry_t *fae;
+ int error;
+
+ if (fildes < 0)
+ return (EBADF);
+
+ /* Allocate object */
+ fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
+ if (fae == NULL)
+ return (errno);
+
+ /* Set values and store in queue */
+ fae->fae_action = FAE_OPEN;
+ fae->fae_path = strdup(path);
+ if (fae->fae_path == NULL) {
+ error = errno;
+ free(fae);
+ return (error);
+ }
+ fae->fae_fildes = fildes;
+ fae->fae_oflag = oflag;
+ fae->fae_mode = mode;
+
+ STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
+ return (0);
+}
+
+int
+posix_spawn_file_actions_adddup2(posix_spawn_file_actions_t *fa,
+ int fildes, int newfildes)
+{
+ posix_spawn_file_actions_entry_t *fae;
+
+ if (fildes < 0 || newfildes < 0)
+ return (EBADF);
+
+ /* Allocate object */
+ fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
+ if (fae == NULL)
+ return (errno);
+
+ /* Set values and store in queue */
+ fae->fae_action = FAE_DUP2;
+ fae->fae_fildes = fildes;
+ fae->fae_newfildes = newfildes;
+
+ STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
+ return (0);
+}
+
+int
+posix_spawn_file_actions_addclose(posix_spawn_file_actions_t *fa,
+ int fildes)
+{
+ posix_spawn_file_actions_entry_t *fae;
+
+ if (fildes < 0)
+ return (EBADF);
+
+ /* Allocate object */
+ fae = malloc(sizeof(posix_spawn_file_actions_entry_t));
+ if (fae == NULL)
+ return (errno);
+
+ /* Set values and store in queue */
+ fae->fae_action = FAE_CLOSE;
+ fae->fae_fildes = fildes;
+
+ STAILQ_INSERT_TAIL(&(*fa)->fa_list, fae, fae_list);
+ return (0);
+}
+
+/*
+ * Spawn attributes
+ */
+
+int
+posix_spawnattr_init(posix_spawnattr_t *ret)
+{
+ posix_spawnattr_t sa;
+
+ sa = calloc(1, sizeof(struct __posix_spawnattr));
+ if (sa == NULL)
+ return (errno);
+
+ /* Set defaults as specified by POSIX, cleared above */
+ *ret = sa;
+ return (0);
+}
+
+int
+posix_spawnattr_destroy(posix_spawnattr_t *sa)
+{
+ free(*sa);
+ return (0);
+}
+
+int
+posix_spawnattr_getflags(const posix_spawnattr_t * __restrict sa,
+ short * __restrict flags)
+{
+ *flags = (*sa)->sa_flags;
+ return (0);
+}
+
+int
+posix_spawnattr_getpgroup(const posix_spawnattr_t * __restrict sa,
+ pid_t * __restrict pgroup)
+{
+ *pgroup = (*sa)->sa_pgroup;
+ return (0);
+}
+
+int
+posix_spawnattr_getschedparam(const posix_spawnattr_t * __restrict sa,
+ struct sched_param * __restrict schedparam)
+{
+ *schedparam = (*sa)->sa_schedparam;
+ return (0);
+}
+
+int
+posix_spawnattr_getschedpolicy(const posix_spawnattr_t * __restrict sa,
+ int * __restrict schedpolicy)
+{
+ *schedpolicy = (*sa)->sa_schedpolicy;
+ return (0);
+}
+
+int
+posix_spawnattr_getsigdefault(const posix_spawnattr_t * __restrict sa,
+ sigset_t * __restrict sigdefault)
+{
+ *sigdefault = (*sa)->sa_sigdefault;
+ return (0);
+}
+
+int
+posix_spawnattr_getsigmask(const posix_spawnattr_t * __restrict sa,
+ sigset_t * __restrict sigmask)
+{
+ *sigmask = (*sa)->sa_sigmask;
+ return (0);
+}
+
+int
+posix_spawnattr_setflags(posix_spawnattr_t *sa, short flags)
+{
+ (*sa)->sa_flags = flags;
+ return (0);
+}
+
+int
+posix_spawnattr_setpgroup(posix_spawnattr_t *sa, pid_t pgroup)
+{
+ (*sa)->sa_pgroup = pgroup;
+ return (0);
+}
+
+int
+posix_spawnattr_setschedparam(posix_spawnattr_t * __restrict sa,
+ const struct sched_param * __restrict schedparam)
+{
+ (*sa)->sa_schedparam = *schedparam;
+ return (0);
+}
+
+int
+posix_spawnattr_setschedpolicy(posix_spawnattr_t *sa, int schedpolicy)
+{
+ (*sa)->sa_schedpolicy = schedpolicy;
+ return (0);
+}
+
+int
+posix_spawnattr_setsigdefault(posix_spawnattr_t * __restrict sa,
+ const sigset_t * __restrict sigdefault)
+{
+ (*sa)->sa_sigdefault = *sigdefault;
+ return (0);
+}
+
+int
+posix_spawnattr_setsigmask(posix_spawnattr_t * __restrict sa,
+ const sigset_t * __restrict sigmask)
+{
+ (*sa)->sa_sigmask = *sigmask;
+ return (0);
+}
diff --git a/lib/libc/gen/posix_spawn_file_actions_addopen.3 b/lib/libc/gen/posix_spawn_file_actions_addopen.3
new file mode 100644
index 0000000..c6fd017
--- /dev/null
+++ b/lib/libc/gen/posix_spawn_file_actions_addopen.3
@@ -0,0 +1,182 @@
+.\" Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 24, 2008
+.Dt POSIX_SPAWN_FILE_ACTIONS_ADDOPEN 3
+.Os
+.Sh NAME
+.Nm posix_spawn_file_actions_addopen ,
+.Nm posix_spawn_file_actions_adddup2 ,
+.Nm posix_spawn_file_actions_addclose
+.Nd "add open, dup2 or close action to spawn file actions object"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In spawn.h
+.Ft int
+.Fn posix_spawn_file_actions_addopen "posix_spawn_file_actions_t * file_actions" "int fildes" "const char *restrict path" "int oflag" "mode_t mode"
+.Ft int
+.Fn posix_spawn_file_actions_adddup2 "posix_spawn_file_actions_t * file_actions" "int fildes" "int newfildes"
+.Ft int
+.Fn posix_spawn_file_actions_addclose "posix_spawn_file_actions_t * file_actions" "int fildes"
+.Sh DESCRIPTION
+These functions add an open, dup2 or close action to a spawn
+file actions object.
+.Pp
+A spawn file actions object is of type
+.Vt posix_spawn_file_actions_t
+(defined in
+.In spawn.h )
+and is used to specify a series of actions to be performed by a
+.Fn posix_spawn
+or
+.Fn posix_spawnp
+operation in order to arrive at the set of open file descriptors for the
+child process given the set of open file descriptors of the parent.
+.Pp
+A spawn file actions object, when passed to
+.Fn posix_spawn
+or
+.Fn posix_spawnp ,
+specify how the set of open file descriptors in the calling
+process is transformed into a set of potentially open file descriptors
+for the spawned process.
+This transformation is as if the specified sequence of actions was
+performed exactly once, in the context of the spawned process (prior to
+execution of the new process image), in the order in which the actions
+were added to the object; additionally, when the new process image is
+executed, any file descriptor (from this new set) which has its
+.Dv FD_CLOEXEC
+flag set is closed (see
+.Fn posix_spawn ) .
+.Pp
+The
+.Fn posix_spawn_file_actions_addopen
+function adds an open action to the object referenced by
+.Fa file_actions
+that causes the file named by
+.Fa path
+to be opened (as if
+.Bd -literal -offset indent
+open(path, oflag, mode)
+.Ed
+.Pp
+had been called, and the returned file descriptor, if not
+.Fa fildes ,
+had been changed to
+.Fa fildes )
+when a new process is spawned using this file actions object.
+If
+.Fa fildes
+was already an open file descriptor, it is closed before the new
+file is opened.
+.Pp
+The string described by
+.Fa path
+is copied by the
+.Fn posix_spawn_file_actions_addopen
+function.
+.Pp
+The
+.Fn posix_spawn_file_actions_adddup2
+function adds a dup2 action to the object referenced by
+.Fa file_actions
+that causes the file descriptor
+.Fa fildes
+to be duplicated as
+.Fa newfildes
+(as if
+.Bd -literal -offset indent
+dup2(fildes, newfildes)
+.Ed
+.Pp
+had been called) when a new process is spawned using this file actions object.
+.Pp
+The
+.Fn posix_spawn_file_actions_addclose
+function adds a close action to the object referenced by
+.Fa file_actions
+that causes the file descriptor
+.Fa fildes
+to be closed (as if
+.Bd -literal -offset indent
+close(fildes)
+.Ed
+.Pp
+had been called) when a new process is spawned using this file actions
+object.
+.Sh RETURN VALUES
+Upon successful completion, these functions return zero;
+otherwise, an error number is returned to indicate the error.
+.Sh ERRORS
+These
+functions fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value specified by
+.Fa fildes
+or
+.Fa newfildes
+is negative.
+.It Bq Er ENOMEM
+Insufficient memory exists to add to the spawn file actions object.
+.El
+.Sh SEE ALSO
+.Xr close 2 ,
+.Xr dup2 2 ,
+.Xr open 2 ,
+.Xr posix_spawn 3 ,
+.Xr posix_spawn_file_actions_destroy 3 ,
+.Xr posix_spawn_file_actions_init 3 ,
+.Xr posix_spawnp 3
+.Sh STANDARDS
+The
+.Fn posix_spawn_file_actions_addopen ,
+.Fn posix_spawn_file_actions_adddup2
+and
+.Fn posix_spawn_file_actions_addclose
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn posix_spawn_file_actions_addopen ,
+.Fn posix_spawn_file_actions_adddup2
+and
+.Fn posix_spawn_file_actions_addclose
+functions first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Ed Schouten Aq ed@FreeBSD.org
diff --git a/lib/libc/gen/posix_spawn_file_actions_init.3 b/lib/libc/gen/posix_spawn_file_actions_init.3
new file mode 100644
index 0000000..d826b8b
--- /dev/null
+++ b/lib/libc/gen/posix_spawn_file_actions_init.3
@@ -0,0 +1,104 @@
+.\" Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 24, 2008
+.Dt POSIX_SPAWN_FILE_ACTIONS_INIT 3
+.Os
+.Sh NAME
+.Nm posix_spawn_file_actions_init ,
+.Nm posix_spawn_file_actions_destroy
+.Nd "initialize and destroy spawn file actions object"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In spawn.h
+.Ft int
+.Fn posix_spawn_file_actions_init "posix_spawn_file_actions_t * file_actions"
+.Ft int
+.Fn posix_spawn_file_actions_destroy "posix_spawn_file_actions_t * file_actions"
+.Sh DESCRIPTION
+The
+.Fn posix_spawn_file_actions_init
+function initialize the object referenced by
+.Fn file_actions
+to contain no file actions for
+.Fn posix_spawn
+or
+.Fn posix_spawnp .
+Initializing an already initialized spawn file actions object may cause
+memory to be leaked.
+.Pp
+The
+.Fn posix_spawn_file_actions_destroy
+function destroy the object referenced by
+.Fa file_actions ;
+the object becomes, in effect, uninitialized.
+A destroyed spawn file actions object can be reinitialized using
+.Fn posix_spawn_file_actions_init .
+The object should not be used after it has been destroyed.
+.Sh RETURN VALUES
+Upon successful completion, these functions return zero;
+otherwise, an error number is returned to indicate the error.
+.Sh ERRORS
+The
+.Fn posix_spawn_file_actions_init
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+Insufficient memory exists to initialize the spawn file actions object.
+.El
+.Sh SEE ALSO
+.Xr posix_spawn 3 ,
+.Xr posix_spawn_file_actions_addclose 3 ,
+.Xr posix_spawn_file_actions_adddup2 3 ,
+.Xr posix_spawn_file_actions_addopen 3 ,
+.Xr posix_spawnp 3
+.Sh STANDARDS
+The
+.Fn posix_spawn_file_actions_init
+and
+.Fn posix_spawn_file_actions_destroy
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn posix_spawn_file_actions_init
+and
+.Fn posix_spawn_file_actions_destroy
+functions first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Ed Schouten Aq ed@FreeBSD.org
diff --git a/lib/libc/gen/posix_spawnattr_getflags.3 b/lib/libc/gen/posix_spawnattr_getflags.3
new file mode 100644
index 0000000..a2dda02
--- /dev/null
+++ b/lib/libc/gen/posix_spawnattr_getflags.3
@@ -0,0 +1,111 @@
+.\" Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 24, 2008
+.Dt POSIX_SPAWNATTR_GETFLAGS 3
+.Os
+.Sh NAME
+.Nm posix_spawnattr_getflags ,
+.Nm posix_spawnattr_setflags
+.Nd "get and set the spawn-flags attribute of a spawn attributes object"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In spawn.h
+.Ft int
+.Fn posix_spawnattr_getflags "const posix_spawnattr_t *restrict attr" "short *restrict flags"
+.Ft int
+.Fn posix_spawnattr_setflags "posix_spawnattr_t *attr" "short flags"
+.Sh DESCRIPTION
+The
+.Fn posix_spawnattr_getflags
+function obtains the value of the spawn-flags attribute from the
+attributes object referenced by
+.Fa attr .
+.Pp
+The
+.Fn posix_spawnattr_setflags
+function sets the spawn-flags attribute in an initialized
+attributes object referenced by
+.Fa attr .
+.Pp
+The spawn-flags attribute is used to indicate which process attributes
+are to be changed in the new process image when invoking
+.Fn posix_spawn
+or
+.Fn posix_spawnp .
+It is the bitwise-inclusive OR of zero or more of the following flags
+(see
+.Fn posix_spawn ) :
+.Bl -tag -offset indent
+.It Dv POSIX_SPAWN_RESETIDS
+.It Dv POSIX_SPAWN_SETPGROUP
+.It Dv POSIX_SPAWN_SETSIGDEF
+.It Dv POSIX_SPAWN_SETSIGMASK
+.It Dv POSIX_SPAWN_SETSCHEDPARAM
+.It Dv POSIX_SPAWN_SETSCHEDULER
+.El
+.Pp
+These flags are defined in
+.In spawn.h .
+The default value of this attribute is as if no flags were set.
+.Sh RETURN VALUES
+The
+.Fn posix_spawnattr_getflags
+and
+.Fn posix_spawnattr_setflags
+functions return zero.
+.Sh SEE ALSO
+.Xr posix_spawn 3 ,
+.Xr posix_spawnattr_destroy 3 ,
+.Xr posix_spawnattr_init 3 ,
+.Xr posix_spawnp 3
+.Sh STANDARDS
+The
+.Fn posix_spawnattr_getflags
+and
+.Fn posix_spawnattr_setflags
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn posix_spawnattr_getflags
+and
+.Fn posix_spawnattr_setflags
+functions first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Ed Schouten Aq ed@FreeBSD.org
diff --git a/lib/libc/gen/posix_spawnattr_getpgroup.3 b/lib/libc/gen/posix_spawnattr_getpgroup.3
new file mode 100644
index 0000000..5cd51d6
--- /dev/null
+++ b/lib/libc/gen/posix_spawnattr_getpgroup.3
@@ -0,0 +1,96 @@
+.\" Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 24, 2008
+.Dt POSIX_SPAWNATTR_GETPGROUP 3
+.Os
+.Sh NAME
+.Nm posix_spawnattr_getpgroup ,
+.Nm posix_spawnattr_setpgroup
+.Nd "get and set the spawn-pgroup attribute of a spawn attributes object"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In spawn.h
+.Ft int
+.Fn posix_spawnattr_getpgroup "const posix_spawnattr_t *restrict attr" "pid_t *restrict pgroup"
+.Ft int
+.Fn posix_spawnattr_setpgroup "posix_spawnattr_t *attr" "pid_t pgroup"
+.Sh DESCRIPTION
+The
+.Fn posix_spawnattr_getpgroup
+function obtains the value of the spawn-pgroup attribute from the
+attributes object referenced by
+.Fa attr .
+.Pp
+The
+.Fn posix_spawnattr_setpgroup
+function sets the spawn-pgroup attribute in an initialized
+attributes object referenced by
+.Fa attr .
+.Pp
+The spawn-pgroup attribute represents the process group to be joined by
+the new process image in a spawn operation (if
+.Dv POSIX_SPAWN_SETPGROUP
+is set in the spawn-flags attribute).
+The default value of this attribute is zero.
+.Sh RETURN VALUES
+The
+.Fn posix_spawnattr_getpgroup
+and
+.Fn posix_spawnattr_setpgroup
+functions return zero.
+.Sh SEE ALSO
+.Xr posix_spawn 3 ,
+.Xr posix_spawnattr_destroy 3 ,
+.Xr posix_spawnattr_init 3 ,
+.Xr posix_spawnp 3
+.Sh STANDARDS
+The
+.Fn posix_spawnattr_getpgroup
+and
+.Fn posix_spawnattr_setpgroup
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn posix_spawnattr_getpgroup
+and
+.Fn posix_spawnattr_setpgroup
+functions first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Ed Schouten Aq ed@FreeBSD.org
diff --git a/lib/libc/gen/posix_spawnattr_getschedparam.3 b/lib/libc/gen/posix_spawnattr_getschedparam.3
new file mode 100644
index 0000000..70009b9
--- /dev/null
+++ b/lib/libc/gen/posix_spawnattr_getschedparam.3
@@ -0,0 +1,100 @@
+.\" Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 24, 2008
+.Dt POSIX_SPAWNATTR_GETSCHEDPARAM 3
+.Os
+.Sh NAME
+.Nm posix_spawnattr_getschedparam ,
+.Nm posix_spawnattr_setschedparam
+.Nd "get and set the spawn-schedparam attribute of a spawn attributes object"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In spawn.h
+.Ft int
+.Fn posix_spawnattr_getschedparam "const posix_spawnattr_t *restrict attr" "struct sched_param *restrict schedparam"
+.Ft int
+.Fn posix_spawnattr_setschedparam "posix_spawnattr_t *attr" "const struct sched_param *restrict schedparam"
+.Sh DESCRIPTION
+The
+.Fn posix_spawnattr_getschedparam
+function obtains the value of the spawn-schedparam attribute from the
+attributes object referenced by
+.Fa attr .
+.Pp
+The
+.Fn posix_spawnattr_setschedparam
+function sets the spawn-schedparam attribute in an initialized attributes
+object referenced by
+.Fa attr .
+.Pp
+The spawn-schedparam attribute represents the scheduling parameters to
+be assigned to the new process image in a spawn operation (if
+.Dv POSIX_SPAWN_SETSCHEDULER
+or
+.Dv POSIX_SPAWN_SETSCHEDPARAM
+is set in the spawn-flags attribute).
+The default value of this attribute is unspecified.
+.Sh RETURN VALUES
+The
+.Fn posix_spawnattr_getschedparam
+and
+.Fn posix_spawnattr_setschedparam
+functions return zero.
+.Sh SEE ALSO
+.Xr posix_spawn 3 ,
+.Xr posix_spawnattr_destroy 3 ,
+.Xr posix_spawnattr_getschedpolicy 3 ,
+.Xr posix_spawnattr_init 3 ,
+.Xr posix_spawnattr_setschedpolicy 3 ,
+.Xr posix_spawnp 3
+.Sh STANDARDS
+The
+.Fn posix_spawnattr_getschedparam
+and
+.Fn posix_spawnattr_setschedparam
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn posix_spawnattr_getschedparam
+and
+.Fn posix_spawnattr_setschedparam
+functions first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Ed Schouten Aq ed@FreeBSD.org
diff --git a/lib/libc/gen/posix_spawnattr_getschedpolicy.3 b/lib/libc/gen/posix_spawnattr_getschedpolicy.3
new file mode 100644
index 0000000..45c1965
--- /dev/null
+++ b/lib/libc/gen/posix_spawnattr_getschedpolicy.3
@@ -0,0 +1,98 @@
+.\" Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 24, 2008
+.Dt POSIX_SPAWNATTR_GETSCHEDPOLICY 3
+.Os
+.Sh NAME
+.Nm posix_spawnattr_getschedpolicy ,
+.Nm posix_spawnattr_setschedpolicy
+.Nd "get and set the spawn-schedpolicy attribute of a spawn attributes object"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In spawn.h
+.Ft int
+.Fn posix_spawnattr_getschedpolicy "const posix_spawnattr_t *restrict attr" "int *restrict schedpolicy"
+.Ft int
+.Fn posix_spawnattr_setschedpolicy "posix_spawnattr_t *attr" "int schedpolicy"
+.Sh DESCRIPTION
+The
+.Fn posix_spawnattr_getschedpolicy
+function obtains the value of the spawn-schedpolicy attribute from the
+attributes object referenced by
+.Fa attr .
+.Pp
+The
+.Fn posix_spawnattr_setschedpolicy
+function sets the spawn-schedpolicy attribute in an initialized attributes
+object referenced by
+.Fa attr .
+.Pp
+The spawn-schedpolicy attribute represents the scheduling policy to
+be assigned to the new process image in a spawn operation (if
+.Dv POSIX_SPAWN_SETSCHEDULER
+is set in the spawn-flags attribute).
+The default value of this attribute is unspecified.
+.Sh RETURN VALUES
+The
+.Fn posix_spawnattr_getschedpolicy
+and
+.Fn posix_spawnattr_setschedpolicy
+functions return zero.
+.Sh SEE ALSO
+.Xr posix_spawn 3 ,
+.Xr posix_spawnattr_destroy 3 ,
+.Xr posix_spawnattr_getschedparam 3 ,
+.Xr posix_spawnattr_init 3 ,
+.Xr posix_spawnattr_setschedparam 3 ,
+.Xr posix_spawnp 3
+.Sh STANDARDS
+The
+.Fn posix_spawnattr_getschedpolicy
+and
+.Fn posix_spawnattr_setschedpolicy
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn posix_spawnattr_getschedpolicy
+and
+.Fn posix_spawnattr_setschedpolicy
+functions first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Ed Schouten Aq ed@FreeBSD.org
diff --git a/lib/libc/gen/posix_spawnattr_getsigdefault.3 b/lib/libc/gen/posix_spawnattr_getsigdefault.3
new file mode 100644
index 0000000..9e13c37
--- /dev/null
+++ b/lib/libc/gen/posix_spawnattr_getsigdefault.3
@@ -0,0 +1,98 @@
+.\" Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 24, 2008
+.Dt POSIX_SPAWNATTR_GETSIGDEFAULT 3
+.Os
+.Sh NAME
+.Nm posix_spawnattr_getsigdefault ,
+.Nm posix_spawnattr_setsigdefault
+.Nd "get and set the spawn-sigdefault attribute of a spawn attributes object"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In spawn.h
+.Ft int
+.Fn posix_spawnattr_getsigdefault "const posix_spawnattr_t *restrict attr" "sigset_t *restrict sigdefault"
+.Ft int
+.Fn posix_spawnattr_setsigdefault "posix_spawnattr_t *attr" "const sigset_t *restrict sigdefault"
+.Sh DESCRIPTION
+The
+.Fn posix_spawnattr_getsigdefault
+function obtains the value of the spawn-sigdefault attribute from the
+attributes object referenced by
+.Fa attr .
+.Pp
+The
+.Fn posix_spawnattr_setsigdefault
+function sets the spawn-sigdefault attribute in an initialized attributes
+object referenced by
+.Fa attr .
+.Pp
+The spawn-sigdefault attribute represents the set of signals to be forced to
+default signal handling in the new process image (if
+.Dv POSIX_SPAWN_SETSIGDEF
+is set in the spawn-flags attribute) by a spawn operation.
+The default value of this attribute is an empty signal set.
+.Sh RETURN VALUES
+The
+.Fn posix_spawnattr_getsigdefault
+and
+.Fn posix_spawnattr_setsigdefault
+functions return zero.
+.Sh SEE ALSO
+.Xr posix_spawn 3 ,
+.Xr posix_spawnattr_destroy 3 ,
+.Xr posix_spawnattr_getsigmask 3 ,
+.Xr posix_spawnattr_init 3 ,
+.Xr posix_spawnattr_setsigmask 3 ,
+.Xr posix_spawnp 3
+.Sh STANDARDS
+The
+.Fn posix_spawnattr_getsigdefault
+and
+.Fn posix_spawnattr_setsigdefault
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn posix_spawnattr_getsigdefault
+and
+.Fn posix_spawnattr_setsigdefault
+functions first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Ed Schouten Aq ed@FreeBSD.org
diff --git a/lib/libc/gen/posix_spawnattr_getsigmask.3 b/lib/libc/gen/posix_spawnattr_getsigmask.3
new file mode 100644
index 0000000..5cee7ec
--- /dev/null
+++ b/lib/libc/gen/posix_spawnattr_getsigmask.3
@@ -0,0 +1,98 @@
+.\" Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 24, 2008
+.Dt POSIX_SPAWNATTR_GETSIGMASK 3
+.Os
+.Sh NAME
+.Nm posix_spawnattr_getsigmask ,
+.Nm posix_spawnattr_setsigmask
+.Nd "get and set the spawn-sigmask attribute of a spawn attributes object"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In spawn.h
+.Ft int
+.Fn posix_spawnattr_getsigmask "const posix_spawnattr_t *restrict attr" "sigset_t *restrict sigmask"
+.Ft int
+.Fn posix_spawnattr_setsigmask "posix_spawnattr_t *attr" "const sigset_t *restrict sigmask"
+.Sh DESCRIPTION
+The
+.Fn posix_spawnattr_getsigmask
+function obtains the value of the spawn-sigmask attribute from the
+attributes object referenced by
+.Fa attr .
+.Pp
+The
+.Fn posix_spawnattr_setsigmask
+function sets the spawn-sigmask attribute in an initialized attributes
+object referenced by
+.Fa attr .
+.Pp
+The spawn-sigmask attribute represents the signal mask in effect in the
+new process image of a spawn operation (if
+.Dv POSIX_SPAWN_SETSIGMASK
+is set in the spawn-flags attribute).
+The default value of this attribute is unspecified.
+.Sh RETURN VALUES
+The
+.Fn posix_spawnattr_getsigmask
+and
+.Fn posix_spawnattr_setsigmask
+functions return zero.
+.Sh SEE ALSO
+.Xr posix_spawn 3 ,
+.Xr posix_spawnattr_destroy 3 ,
+.Xr posix_spawnattr_getsigmask 3 ,
+.Xr posix_spawnattr_init 3 ,
+.Xr posix_spawnattr_setsigmask 3 ,
+.Xr posix_spawnp 3
+.Sh STANDARDS
+The
+.Fn posix_spawnattr_getsigmask
+and
+.Fn posix_spawnattr_setsigmask
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn posix_spawnattr_getsigmask
+and
+.Fn posix_spawnattr_setsigmask
+functions first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Ed Schouten Aq ed@FreeBSD.org
diff --git a/lib/libc/gen/posix_spawnattr_init.3 b/lib/libc/gen/posix_spawnattr_init.3
new file mode 100644
index 0000000..66c99cd
--- /dev/null
+++ b/lib/libc/gen/posix_spawnattr_init.3
@@ -0,0 +1,123 @@
+.\" Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 24, 2008
+.Dt POSIX_SPAWNATTR_INIT 3
+.Os
+.Sh NAME
+.Nm posix_spawnattr_init ,
+.Nm posix_spawnattr_destroy
+.Nd "initialize and destroy spawn attributes object"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In spawn.h
+.Ft int
+.Fn posix_spawnattr_init "posix_spawnattr_t * attr"
+.Ft int
+.Fn posix_spawnattr_destroy "posix_spawnattr_t * attr"
+.Sh DESCRIPTION
+The
+.Fn posix_spawnattr_init
+function initializes a spawn attributes object
+.Fa attr
+with the default value for all of the individual attributes used by the
+implementation.
+Initializing an already initialized spawn attributes object may cause
+memory to be leaked.
+.Pp
+The
+.Fn posix_spawnattr_destroy
+function destroys a spawn attributes object.
+A destroyed
+.Fa attr
+attributes object can be reinitialized using
+.Fn posix_spawnattr_init .
+The object should not be used after it has been destroyed.
+.Pp
+A spawn attributes object is of type
+.Vt posix_spawnattr_t
+(defined in
+.In spawn.h )
+and is used to specify the inheritance of process attributes across a
+spawn operation.
+.Pp
+The resulting spawn attributes object (possibly modified by setting
+individual attribute values), is used to modify the behavior of
+.Fn posix_spawn
+or
+.Fn posix_spawnp .
+After a spawn attributes object has been used to spawn a process by a
+call to a
+.Fn posix_spawn
+or
+.Fn posix_spawnp ,
+any function affecting the attributes object (including destruction)
+will not affect any process that has been spawned in this way.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn posix_spawnattr_init
+and
+.Fn posix_spawnattr_destroy
+return zero;
+otherwise, an error number is returned to indicate the error.
+.Sh ERRORS
+The
+.Fn posix_spawnattr_init
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+Insufficient memory exists to initialize the spawn file actions object.
+.El
+.Sh SEE ALSO
+.Xr posix_spawn 3 ,
+.Xr posix_spawnp 3
+.Sh STANDARDS
+The
+.Fn posix_spawnattr_init
+and
+.Fn posix_spawnattr_destroy
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn posix_spawnattr_init
+and
+.Fn posix_spawnattr_destroy
+functions first appeared in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Ed Schouten Aq ed@FreeBSD.org
diff --git a/lib/libc/gen/psignal.3 b/lib/libc/gen/psignal.3
new file mode 100644
index 0000000..231acfa
--- /dev/null
+++ b/lib/libc/gen/psignal.3
@@ -0,0 +1,109 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)psignal.3 8.2 (Berkeley) 2/27/95
+.\" $FreeBSD$
+.\"
+.Dd February 4, 2011
+.Dt PSIGNAL 3
+.Os
+.Sh NAME
+.Nm psignal ,
+.Nm strsignal ,
+.Nm sys_siglist ,
+.Nm sys_signame
+.Nd system signal messages
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In signal.h
+.Ft void
+.Fn psignal "unsigned sig" "const char *s"
+.Vt extern const char * const sys_siglist[] ;
+.Vt extern const char * const sys_signame[] ;
+.In string.h
+.Ft "char *"
+.Fn strsignal "int sig"
+.Sh DESCRIPTION
+The
+.Fn psignal
+and
+.Fn strsignal
+functions locate the descriptive message
+string for a signal number.
+.Pp
+The
+.Fn strsignal
+function accepts a signal number argument
+.Fa sig
+and returns a pointer to the corresponding message string.
+.Pp
+The
+.Fn psignal
+function accepts a signal number argument
+.Fa sig
+and writes it to the standard error.
+If the argument
+.Fa s
+is
+.Pf non- Dv NULL
+and does not point to the null character,
+.Fa s
+is written to the standard error file descriptor
+prior to the message string,
+immediately followed by a colon and a space.
+If the signal number is not recognized
+.Pq Xr sigaction 2 ,
+the string
+.Dq "Unknown signal"
+is produced.
+.Pp
+The message strings can be accessed directly
+through the external array
+.Va sys_siglist ,
+indexed by recognized signal numbers.
+The external array
+.Va sys_signame
+is used similarly and
+contains short, upper-case abbreviations for signals
+which are useful for recognizing signal names
+in user input.
+The defined variable
+.Dv NSIG
+contains a count of the strings in
+.Va sys_siglist
+and
+.Va sys_signame .
+.Sh SEE ALSO
+.Xr sigaction 2 ,
+.Xr perror 3 ,
+.Xr strerror 3
+.Sh HISTORY
+The
+.Fn psignal
+function appeared in
+.Bx 4.2 .
diff --git a/lib/libc/gen/psignal.c b/lib/libc/gen/psignal.c
new file mode 100644
index 0000000..6fca4b1
--- /dev/null
+++ b/lib/libc/gen/psignal.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)psignal.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Print the name of the signal indicated
+ * along with the supplied message.
+ */
+#include "namespace.h"
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+void
+psignal(sig, s)
+ unsigned int sig;
+ const char *s;
+{
+ const char *c;
+
+ if (sig < NSIG)
+ c = sys_siglist[sig];
+ else
+ c = "Unknown signal";
+ if (s != NULL && *s != '\0') {
+ (void)_write(STDERR_FILENO, s, strlen(s));
+ (void)_write(STDERR_FILENO, ": ", 2);
+ }
+ (void)_write(STDERR_FILENO, c, strlen(c));
+ (void)_write(STDERR_FILENO, "\n", 1);
+}
diff --git a/lib/libc/gen/pututxline.c b/lib/libc/gen/pututxline.c
new file mode 100644
index 0000000..98addee
--- /dev/null
+++ b/lib/libc/gen/pututxline.c
@@ -0,0 +1,331 @@
+/*-
+ * Copyright (c) 2010 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/endian.h>
+#include <sys/stat.h>
+#include <sys/uio.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <utmpx.h>
+#include "utxdb.h"
+#include "un-namespace.h"
+
+static FILE *
+futx_open(const char *file)
+{
+ FILE *fp;
+ struct stat sb;
+ int fd;
+
+ fd = _open(file, O_CREAT|O_RDWR|O_EXLOCK, 0644);
+ if (fd < 0)
+ return (NULL);
+
+ /* Safety check: never use broken files. */
+ if (_fstat(fd, &sb) != -1 && sb.st_size % sizeof(struct futx) != 0) {
+ _close(fd);
+ errno = EFTYPE;
+ return (NULL);
+ }
+
+ fp = fdopen(fd, "r+");
+ if (fp == NULL) {
+ _close(fd);
+ return (NULL);
+ }
+ return (fp);
+}
+
+static int
+utx_active_add(const struct futx *fu)
+{
+ FILE *fp;
+ struct futx fe;
+ off_t partial;
+ int error, ret;
+
+ partial = -1;
+ ret = 0;
+
+ /*
+ * Register user login sessions. Overwrite entries of sessions
+ * that have already been terminated.
+ */
+ fp = futx_open(_PATH_UTX_ACTIVE);
+ if (fp == NULL)
+ return (-1);
+ while (fread(&fe, sizeof(fe), 1, fp) == 1) {
+ switch (fe.fu_type) {
+ case BOOT_TIME:
+ /* Leave these intact. */
+ break;
+ case USER_PROCESS:
+ case INIT_PROCESS:
+ case LOGIN_PROCESS:
+ case DEAD_PROCESS:
+ /* Overwrite when ut_id matches. */
+ if (memcmp(fu->fu_id, fe.fu_id, sizeof(fe.fu_id)) ==
+ 0) {
+ ret = fseeko(fp, -(off_t)sizeof(fe), SEEK_CUR);
+ goto exact;
+ }
+ if (fe.fu_type != DEAD_PROCESS)
+ break;
+ /* FALLTHROUGH */
+ default:
+ /* Allow us to overwrite unused records. */
+ if (partial == -1) {
+ partial = ftello(fp);
+ /*
+ * Distinguish errors from valid values so we
+ * don't overwrite good data by accident.
+ */
+ if (partial != -1)
+ partial -= (off_t)sizeof(fe);
+ }
+ break;
+ }
+ }
+
+ /*
+ * No exact match found. Use the partial match. If no partial
+ * match was found, just append a new record.
+ */
+ if (partial != -1)
+ ret = fseeko(fp, partial, SEEK_SET);
+exact:
+ if (ret == -1)
+ error = errno;
+ else if (fwrite(fu, sizeof(*fu), 1, fp) < 1)
+ error = errno;
+ else
+ error = 0;
+ fclose(fp);
+ errno = error;
+ return (error == 0 ? 0 : 1);
+}
+
+static int
+utx_active_remove(struct futx *fu)
+{
+ FILE *fp;
+ struct futx fe;
+ int error, ret;
+
+ /*
+ * Remove user login sessions, having the same ut_id.
+ */
+ fp = futx_open(_PATH_UTX_ACTIVE);
+ if (fp == NULL)
+ return (-1);
+ error = ESRCH;
+ ret = -1;
+ while (fread(&fe, sizeof(fe), 1, fp) == 1 && ret != 0)
+ switch (fe.fu_type) {
+ case USER_PROCESS:
+ case INIT_PROCESS:
+ case LOGIN_PROCESS:
+ if (memcmp(fu->fu_id, fe.fu_id, sizeof(fe.fu_id)) != 0)
+ continue;
+
+ /* Terminate session. */
+ if (fseeko(fp, -(off_t)sizeof(fe), SEEK_CUR) == -1)
+ error = errno;
+ else if (fwrite(fu, sizeof(*fu), 1, fp) < 1)
+ error = errno;
+ else
+ ret = 0;
+
+ }
+
+ fclose(fp);
+ errno = error;
+ return (ret);
+}
+
+static void
+utx_active_init(const struct futx *fu)
+{
+ int fd;
+
+ /* Initialize utx.active with a single BOOT_TIME record. */
+ fd = _open(_PATH_UTX_ACTIVE, O_CREAT|O_RDWR|O_TRUNC, 0644);
+ if (fd < 0)
+ return;
+ _write(fd, fu, sizeof(*fu));
+ _close(fd);
+}
+
+static void
+utx_active_purge(void)
+{
+
+ truncate(_PATH_UTX_ACTIVE, 0);
+}
+
+static int
+utx_lastlogin_add(const struct futx *fu)
+{
+ struct futx fe;
+ FILE *fp;
+ int error, ret;
+
+ ret = 0;
+
+ /*
+ * Write an entry to lastlogin. Overwrite the entry if the
+ * current user already has an entry. If not, append a new
+ * entry.
+ */
+ fp = futx_open(_PATH_UTX_LASTLOGIN);
+ if (fp == NULL)
+ return (-1);
+ while (fread(&fe, sizeof fe, 1, fp) == 1) {
+ if (strncmp(fu->fu_user, fe.fu_user, sizeof fe.fu_user) != 0)
+ continue;
+
+ /* Found a previous lastlogin entry for this user. */
+ ret = fseeko(fp, -(off_t)sizeof fe, SEEK_CUR);
+ break;
+ }
+ if (ret == -1)
+ error = errno;
+ else if (fwrite(fu, sizeof *fu, 1, fp) < 1) {
+ error = errno;
+ ret = -1;
+ }
+ fclose(fp);
+ errno = error;
+ return (ret);
+}
+
+static void
+utx_lastlogin_upgrade(void)
+{
+ struct stat sb;
+ int fd;
+
+ fd = _open(_PATH_UTX_LASTLOGIN, O_RDWR, 0644);
+ if (fd < 0)
+ return;
+
+ /*
+ * Truncate broken lastlogin files. In the future we should
+ * check for older versions of the file format here and try to
+ * upgrade it.
+ */
+ if (_fstat(fd, &sb) != -1 && sb.st_size % sizeof(struct futx) != 0)
+ ftruncate(fd, 0);
+ _close(fd);
+}
+
+static int
+utx_log_add(const struct futx *fu)
+{
+ struct iovec vec[2];
+ int error, fd;
+ uint16_t l;
+
+ /*
+ * Append an entry to the log file. We only need to append
+ * records to this file, so to conserve space, trim any trailing
+ * zero-bytes. Prepend a length field, indicating the length of
+ * the record, excluding the length field itself.
+ */
+ for (l = sizeof(*fu); l > 0 && ((const char *)fu)[l - 1] == '\0'; l--) ;
+ vec[0].iov_base = &l;
+ vec[0].iov_len = sizeof(l);
+ vec[1].iov_base = __DECONST(void *, fu);
+ vec[1].iov_len = l;
+ l = htobe16(l);
+
+ fd = _open(_PATH_UTX_LOG, O_CREAT|O_WRONLY|O_APPEND, 0644);
+ if (fd < 0)
+ return (-1);
+ if (_writev(fd, vec, 2) == -1)
+ error = errno;
+ else
+ error = 0;
+ _close(fd);
+ errno = error;
+ return (error == 0 ? 0 : 1);
+}
+
+struct utmpx *
+pututxline(const struct utmpx *utmpx)
+{
+ struct futx fu;
+ int bad;
+
+ bad = 0;
+
+ utx_to_futx(utmpx, &fu);
+
+ switch (fu.fu_type) {
+ case BOOT_TIME:
+ utx_active_init(&fu);
+ utx_lastlogin_upgrade();
+ break;
+ case SHUTDOWN_TIME:
+ utx_active_purge();
+ break;
+ case OLD_TIME:
+ case NEW_TIME:
+ break;
+ case USER_PROCESS:
+ bad |= utx_active_add(&fu);
+ bad |= utx_lastlogin_add(&fu);
+ break;
+#if 0 /* XXX: Are these records of any use to us? */
+ case INIT_PROCESS:
+ case LOGIN_PROCESS:
+ bad |= utx_active_add(&fu);
+ break;
+#endif
+ case DEAD_PROCESS:
+ /*
+ * In case writing a logout entry fails, never attempt
+ * to write it to utx.log. The logout entry's ut_id
+ * might be invalid.
+ */
+ if (utx_active_remove(&fu) != 0)
+ return (NULL);
+ break;
+ default:
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ bad |= utx_log_add(&fu);
+ return (bad ? NULL : futx_to_utx(&fu));
+}
diff --git a/lib/libc/gen/pw_scan.c b/lib/libc/gen/pw_scan.c
new file mode 100644
index 0000000..24e8225
--- /dev/null
+++ b/lib/libc/gen/pw_scan.c
@@ -0,0 +1,212 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)pw_scan.c 8.3 (Berkeley) 4/2/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * This module is used to "verify" password entries by chpass(1) and
+ * pwd_mkdb(8).
+ */
+
+#include <sys/param.h>
+
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include "pw_scan.h"
+
+/*
+ * Some software assumes that IDs are short. We should emit warnings
+ * for id's which cannot be stored in a short, but we are more liberal
+ * by default, warning for IDs greater than USHRT_MAX.
+ *
+ * If pw_big_ids_warning is -1 on entry to pw_scan(), it will be set based
+ * on the existence of PW_SCAN_BIG_IDS in the environment.
+ *
+ * It is believed all baseline system software that can not handle the
+ * normal ID sizes is now gone so pw_big_ids_warning is disabled for now.
+ * But the code has been left in place in case end-users want to re-enable
+ * it and/or for the next time the ID sizes get bigger but pieces of the
+ * system lag behind.
+ */
+static int pw_big_ids_warning = 0;
+
+int
+__pw_scan(char *bp, struct passwd *pw, int flags)
+{
+ uid_t id;
+ int root;
+ char *ep, *p, *sh;
+ unsigned long temp;
+
+ if (pw_big_ids_warning == -1)
+ pw_big_ids_warning = getenv("PW_SCAN_BIG_IDS") == NULL ? 1 : 0;
+
+ pw->pw_fields = 0;
+ if (!(pw->pw_name = strsep(&bp, ":"))) /* login */
+ goto fmt;
+ root = !strcmp(pw->pw_name, "root");
+ if (pw->pw_name[0] && (pw->pw_name[0] != '+' || pw->pw_name[1] == '\0'))
+ pw->pw_fields |= _PWF_NAME;
+
+ if (!(pw->pw_passwd = strsep(&bp, ":"))) /* passwd */
+ goto fmt;
+ if (pw->pw_passwd[0])
+ pw->pw_fields |= _PWF_PASSWD;
+
+ if (!(p = strsep(&bp, ":"))) /* uid */
+ goto fmt;
+ if (p[0])
+ pw->pw_fields |= _PWF_UID;
+ else {
+ if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') {
+ if (flags & _PWSCAN_WARN)
+ warnx("no uid for user %s", pw->pw_name);
+ return (0);
+ }
+ }
+ errno = 0;
+ temp = strtoul(p, &ep, 10);
+ if ((temp == ULONG_MAX && errno == ERANGE) || temp > UID_MAX) {
+ if (flags & _PWSCAN_WARN)
+ warnx("%s > max uid value (%u)", p, UID_MAX);
+ return (0);
+ }
+ id = temp;
+ if (*ep != '\0') {
+ if (flags & _PWSCAN_WARN)
+ warnx("%s uid is incorrect", p);
+ return (0);
+ }
+ if (root && id) {
+ if (flags & _PWSCAN_WARN)
+ warnx("root uid should be 0");
+ return (0);
+ }
+ if (flags & _PWSCAN_WARN && pw_big_ids_warning && id > USHRT_MAX) {
+ warnx("%s > recommended max uid value (%u)", p, USHRT_MAX);
+ /*return (0);*/ /* THIS SHOULD NOT BE FATAL! */
+ }
+ pw->pw_uid = id;
+
+ if (!(p = strsep(&bp, ":"))) /* gid */
+ goto fmt;
+ if (p[0])
+ pw->pw_fields |= _PWF_GID;
+ else {
+ if (pw->pw_name[0] != '+' && pw->pw_name[0] != '-') {
+ if (flags & _PWSCAN_WARN)
+ warnx("no gid for user %s", pw->pw_name);
+ return (0);
+ }
+ }
+ errno = 0;
+ temp = strtoul(p, &ep, 10);
+ if ((temp == ULONG_MAX && errno == ERANGE) || temp > GID_MAX) {
+ if (flags & _PWSCAN_WARN)
+ warnx("%s > max gid value (%u)", p, GID_MAX);
+ return (0);
+ }
+ id = temp;
+ if (*ep != '\0') {
+ if (flags & _PWSCAN_WARN)
+ warnx("%s gid is incorrect", p);
+ return (0);
+ }
+ if (flags & _PWSCAN_WARN && pw_big_ids_warning && id > USHRT_MAX) {
+ warnx("%s > recommended max gid value (%u)", p, USHRT_MAX);
+ /* return (0); This should not be fatal! */
+ }
+ pw->pw_gid = id;
+
+ if (flags & _PWSCAN_MASTER ) {
+ if (!(pw->pw_class = strsep(&bp, ":"))) /* class */
+ goto fmt;
+ if (pw->pw_class[0])
+ pw->pw_fields |= _PWF_CLASS;
+
+ if (!(p = strsep(&bp, ":"))) /* change */
+ goto fmt;
+ if (p[0])
+ pw->pw_fields |= _PWF_CHANGE;
+ pw->pw_change = atol(p);
+
+ if (!(p = strsep(&bp, ":"))) /* expire */
+ goto fmt;
+ if (p[0])
+ pw->pw_fields |= _PWF_EXPIRE;
+ pw->pw_expire = atol(p);
+ }
+ if (!(pw->pw_gecos = strsep(&bp, ":"))) /* gecos */
+ goto fmt;
+ if (pw->pw_gecos[0])
+ pw->pw_fields |= _PWF_GECOS;
+
+ if (!(pw->pw_dir = strsep(&bp, ":"))) /* directory */
+ goto fmt;
+ if (pw->pw_dir[0])
+ pw->pw_fields |= _PWF_DIR;
+
+ if (!(pw->pw_shell = strsep(&bp, ":"))) /* shell */
+ goto fmt;
+
+ p = pw->pw_shell;
+ if (root && *p) { /* empty == /bin/sh */
+ for (setusershell();;) {
+ if (!(sh = getusershell())) {
+ if (flags & _PWSCAN_WARN)
+ warnx("warning, unknown root shell");
+ break;
+ }
+ if (!strcmp(p, sh))
+ break;
+ }
+ endusershell();
+ }
+ if (p[0])
+ pw->pw_fields |= _PWF_SHELL;
+
+ if ((p = strsep(&bp, ":"))) { /* too many */
+fmt:
+ if (flags & _PWSCAN_WARN)
+ warnx("corrupted entry");
+ return (0);
+ }
+ return (1);
+}
diff --git a/lib/libc/gen/pw_scan.h b/lib/libc/gen/pw_scan.h
new file mode 100644
index 0000000..468096c
--- /dev/null
+++ b/lib/libc/gen/pw_scan.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)pw_scan.h 8.1 (Berkeley) 4/1/94
+ * $FreeBSD$
+ */
+
+#define _PWSCAN_MASTER 0x01
+#define _PWSCAN_WARN 0x02
+
+extern int __pw_scan(char *, struct passwd *, int);
diff --git a/lib/libc/gen/pwcache.3 b/lib/libc/gen/pwcache.3
new file mode 100644
index 0000000..3910082
--- /dev/null
+++ b/lib/libc/gen/pwcache.3
@@ -0,0 +1,93 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)pwcache.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd March 22, 2002
+.Dt PWCACHE 3
+.Os
+.Sh NAME
+.Nm pwcache
+.Nd cache password and group entries
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In pwd.h
+.Ft const char *
+.Fn user_from_uid "uid_t uid" "int nouser"
+.In grp.h
+.Ft const char *
+.Fn group_from_gid "gid_t gid" "int nogroup"
+.Sh DESCRIPTION
+The
+.Fn user_from_uid
+function returns the user name associated with the argument
+.Fa uid .
+The user name is cached so that multiple calls with the same
+.Fa uid
+do not require additional calls to
+.Xr getpwuid 3 .
+If there is no user associated with the
+.Fa uid ,
+a pointer is returned
+to a string representation of the
+.Fa uid ,
+unless the argument
+.Fa nouser
+is non-zero, in which case a
+.Dv NULL
+pointer is returned.
+.Pp
+The
+.Fn group_from_gid
+function returns the group name associated with the argument
+.Fa gid .
+The group name is cached so that multiple calls with the same
+.Fa gid
+do not require additional calls to
+.Xr getgrgid 3 .
+If there is no group associated with the
+.Fa gid ,
+a pointer is returned
+to a string representation of the
+.Fa gid ,
+unless the argument
+.Fa nogroup
+is non-zero, in which case a
+.Dv NULL
+pointer is returned.
+.Sh SEE ALSO
+.Xr getgrgid 3 ,
+.Xr getpwuid 3
+.Sh HISTORY
+The
+.Fn user_from_uid
+and
+.Fn group_from_gid
+functions first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/pwcache.c b/lib/libc/gen/pwcache.c
new file mode 100644
index 0000000..a8a73f1
--- /dev/null
+++ b/lib/libc/gen/pwcache.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)pwcache.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+
+#define NCACHE 64 /* power of 2 */
+#define MASK (NCACHE - 1) /* bits to store with */
+
+const char *
+user_from_uid(uid_t uid, int nouser)
+{
+ static struct ncache {
+ uid_t uid;
+ int found;
+ char name[MAXLOGNAME];
+ } c_uid[NCACHE];
+ static int pwopen;
+ struct passwd *pw;
+ struct ncache *cp;
+
+ cp = c_uid + (uid & MASK);
+ if (cp->uid != uid || !*cp->name) {
+ if (pwopen == 0) {
+ setpassent(1);
+ pwopen = 1;
+ }
+ pw = getpwuid(uid);
+ cp->uid = uid;
+ if (pw != NULL) {
+ cp->found = 1;
+ (void)strncpy(cp->name, pw->pw_name, MAXLOGNAME - 1);
+ cp->name[MAXLOGNAME - 1] = '\0';
+ } else {
+ cp->found = 0;
+ (void)snprintf(cp->name, MAXLOGNAME - 1, "%u", uid);
+ if (nouser)
+ return (NULL);
+ }
+ }
+ return ((nouser && !cp->found) ? NULL : cp->name);
+}
+
+const char *
+group_from_gid(gid_t gid, int nogroup)
+{
+ static struct ncache {
+ gid_t gid;
+ int found;
+ char name[MAXLOGNAME];
+ } c_gid[NCACHE];
+ static int gropen;
+ struct group *gr;
+ struct ncache *cp;
+
+ cp = c_gid + (gid & MASK);
+ if (cp->gid != gid || !*cp->name) {
+ if (gropen == 0) {
+ setgroupent(1);
+ gropen = 1;
+ }
+ gr = getgrgid(gid);
+ cp->gid = gid;
+ if (gr != NULL) {
+ cp->found = 1;
+ (void)strncpy(cp->name, gr->gr_name, MAXLOGNAME - 1);
+ cp->name[MAXLOGNAME - 1] = '\0';
+ } else {
+ cp->found = 0;
+ (void)snprintf(cp->name, MAXLOGNAME - 1, "%u", gid);
+ if (nogroup)
+ return (NULL);
+ }
+ }
+ return ((nogroup && !cp->found) ? NULL : cp->name);
+}
diff --git a/lib/libc/gen/raise.3 b/lib/libc/gen/raise.3
new file mode 100644
index 0000000..fe75268
--- /dev/null
+++ b/lib/libc/gen/raise.3
@@ -0,0 +1,73 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)raise.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd May 7, 2010
+.Dt RAISE 3
+.Os
+.Sh NAME
+.Nm raise
+.Nd send a signal to the current thread
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In signal.h
+.Ft int
+.Fn raise "int sig"
+.Sh DESCRIPTION
+The
+.Fn raise
+function sends the signal
+.Fa sig
+to the current thread.
+.Sh RETURN VALUES
+.Rv -std raise
+.Sh ERRORS
+The
+.Fn raise
+function
+may fail and set
+.Va errno
+for any of the errors specified for the
+library functions
+.Xr getpid 2
+and
+.Xr kill 2 .
+.Sh SEE ALSO
+.Xr kill 2
+.Sh STANDARDS
+The
+.Fn raise
+function
+conforms to
+.St -isoC .
diff --git a/lib/libc/gen/raise.c b/lib/libc/gen/raise.c
new file mode 100644
index 0000000..b3d0aae
--- /dev/null
+++ b/lib/libc/gen/raise.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)raise.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <signal.h>
+#include <unistd.h>
+
+__weak_reference(__raise, raise);
+__weak_reference(__raise, _raise);
+
+int
+__raise(int s)
+{
+ return(kill(getpid(), s));
+}
diff --git a/lib/libc/gen/rand48.3 b/lib/libc/gen/rand48.3
new file mode 100644
index 0000000..8d325a1
--- /dev/null
+++ b/lib/libc/gen/rand48.3
@@ -0,0 +1,184 @@
+.\" Copyright (c) 1993 Martin Birgmeier
+.\" All rights reserved.
+.\"
+.\" You may redistribute unmodified or modified versions of this source
+.\" code provided that the above copyright notice and this and the
+.\" following conditions are retained.
+.\"
+.\" This software is provided ``as is'', and comes with no warranties
+.\" of any kind. I shall in no event be liable for anything that happens
+.\" to anyone/anything when using this software.
+.\"
+.\" @(#)rand48.3 V1.0 MB 8 Oct 1993
+.\" $FreeBSD$
+.\"
+.Dd February 2, 2010
+.Dt RAND48 3
+.Os
+.Sh NAME
+.Nm drand48 ,
+.Nm erand48 ,
+.Nm lrand48 ,
+.Nm nrand48 ,
+.Nm mrand48 ,
+.Nm jrand48 ,
+.Nm srand48 ,
+.Nm seed48 ,
+.Nm lcong48
+.Nd pseudo random number generators and initialization routines
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft double
+.Fn drand48 void
+.Ft double
+.Fn erand48 "unsigned short xseed[3]"
+.Ft long
+.Fn lrand48 void
+.Ft long
+.Fn nrand48 "unsigned short xseed[3]"
+.Ft long
+.Fn mrand48 void
+.Ft long
+.Fn jrand48 "unsigned short xseed[3]"
+.Ft void
+.Fn srand48 "long seed"
+.Ft "unsigned short *"
+.Fn seed48 "unsigned short xseed[3]"
+.Ft void
+.Fn lcong48 "unsigned short p[7]"
+.Sh DESCRIPTION
+The
+.Fn rand48
+family of functions generates pseudo-random numbers using a linear
+congruential algorithm working on integers 48 bits in size.
+The
+particular formula employed is
+r(n+1) = (a * r(n) + c) mod m
+where the default values are
+for the multiplicand a = 0x5deece66d = 25214903917 and
+the addend c = 0xb = 11.
+The modulo is always fixed at m = 2 ** 48.
+r(n) is called the seed of the random number generator.
+.Pp
+For all the six generator routines described next, the first
+computational step is to perform a single iteration of the algorithm.
+.Pp
+The
+.Fn drand48
+and
+.Fn erand48
+functions
+return values of type double.
+The full 48 bits of r(n+1) are
+loaded into the mantissa of the returned value, with the exponent set
+such that the values produced lie in the interval [0.0, 1.0).
+.Pp
+The
+.Fn lrand48
+and
+.Fn nrand48
+functions
+return values of type long in the range
+[0, 2**31-1].
+The high-order (31) bits of
+r(n+1) are loaded into the lower bits of the returned value, with
+the topmost (sign) bit set to zero.
+.Pp
+The
+.Fn mrand48
+and
+.Fn jrand48
+functions
+return values of type long in the range
+[-2**31, 2**31-1].
+The high-order (32) bits of
+r(n+1) are loaded into the returned value.
+.Pp
+The
+.Fn drand48 ,
+.Fn lrand48 ,
+and
+.Fn mrand48
+functions
+use an internal buffer to store r(n).
+For these functions
+the initial value of r(0) = 0x1234abcd330e = 20017429951246.
+.Pp
+On the other hand,
+.Fn erand48 ,
+.Fn nrand48 ,
+and
+.Fn jrand48
+use a user-supplied buffer to store the seed r(n),
+which consists of an array of 3 shorts, where the zeroth member
+holds the least significant bits.
+.Pp
+All functions share the same multiplicand and addend.
+.Pp
+The
+.Fn srand48
+function
+is used to initialize the internal buffer r(n) of
+.Fn drand48 ,
+.Fn lrand48 ,
+and
+.Fn mrand48
+such that the 32 bits of the seed value are copied into the upper 32 bits
+of r(n), with the lower 16 bits of r(n) arbitrarily being set to 0x330e.
+Additionally, the constant multiplicand and addend of the algorithm are
+reset to the default values given above.
+.Pp
+The
+.Fn seed48
+function
+also initializes the internal buffer r(n) of
+.Fn drand48 ,
+.Fn lrand48 ,
+and
+.Fn mrand48 ,
+but here all 48 bits of the seed can be specified in an array of 3 shorts,
+where the zeroth member specifies the lowest bits.
+Again,
+the constant multiplicand and addend of the algorithm are
+reset to the default values given above.
+The
+.Fn seed48
+function
+returns a pointer to an array of 3 shorts which contains the old seed.
+This array is statically allocated, thus its contents are lost after
+each new call to
+.Fn seed48 .
+.Pp
+Finally,
+.Fn lcong48
+allows full control over the multiplicand and addend used in
+.Fn drand48 ,
+.Fn erand48 ,
+.Fn lrand48 ,
+.Fn nrand48 ,
+.Fn mrand48 ,
+and
+.Fn jrand48 ,
+and the seed used in
+.Fn drand48 ,
+.Fn lrand48 ,
+and
+.Fn mrand48 .
+An array of 7 shorts is passed as argument; the first three shorts are
+used to initialize the seed; the second three are used to initialize the
+multiplicand; and the last short is used to initialize the addend.
+It is thus not possible to use values greater than 0xffff as the addend.
+.Pp
+Note that all three methods of seeding the random number generator
+always also set the multiplicand and addend for any of the six
+generator calls.
+.Pp
+For a more powerful random number generator, see
+.Xr random 3 .
+.Sh SEE ALSO
+.Xr rand 3 ,
+.Xr random 3
+.Sh AUTHORS
+.An Martin Birgmeier
diff --git a/lib/libc/gen/rand48.h b/lib/libc/gen/rand48.h
new file mode 100644
index 0000000..b6602dc
--- /dev/null
+++ b/lib/libc/gen/rand48.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _RAND48_H_
+#define _RAND48_H_
+
+#include <math.h>
+#include <stdlib.h>
+
+void _dorand48(unsigned short[3]);
+
+#define RAND48_SEED_0 (0x330e)
+#define RAND48_SEED_1 (0xabcd)
+#define RAND48_SEED_2 (0x1234)
+#define RAND48_MULT_0 (0xe66d)
+#define RAND48_MULT_1 (0xdeec)
+#define RAND48_MULT_2 (0x0005)
+#define RAND48_ADD (0x000b)
+
+#endif /* _RAND48_H_ */
diff --git a/lib/libc/gen/readdir.c b/lib/libc/gen/readdir.c
new file mode 100644
index 0000000..b4b4c39
--- /dev/null
+++ b/lib/libc/gen/readdir.c
@@ -0,0 +1,132 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)readdir.c 8.3 (Berkeley) 9/29/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <dirent.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+#include "telldir.h"
+
+/*
+ * get next entry in a directory.
+ */
+struct dirent *
+_readdir_unlocked(dirp, skip)
+ DIR *dirp;
+ int skip;
+{
+ struct dirent *dp;
+
+ for (;;) {
+ if (dirp->dd_loc >= dirp->dd_size) {
+ if (dirp->dd_flags & __DTF_READALL)
+ return (NULL);
+ dirp->dd_loc = 0;
+ }
+ if (dirp->dd_loc == 0 && !(dirp->dd_flags & __DTF_READALL)) {
+ dirp->dd_size = _getdirentries(dirp->dd_fd,
+ dirp->dd_buf, dirp->dd_len, &dirp->dd_seek);
+ if (dirp->dd_size <= 0)
+ return (NULL);
+ }
+ dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
+ if ((long)dp & 03L) /* bogus pointer check */
+ return (NULL);
+ if (dp->d_reclen <= 0 ||
+ dp->d_reclen > dirp->dd_len + 1 - dirp->dd_loc)
+ return (NULL);
+ dirp->dd_loc += dp->d_reclen;
+ if (dp->d_ino == 0 && skip)
+ continue;
+ if (dp->d_type == DT_WHT && (dirp->dd_flags & DTF_HIDEW))
+ continue;
+ return (dp);
+ }
+}
+
+struct dirent *
+readdir(dirp)
+ DIR *dirp;
+{
+ struct dirent *dp;
+
+ if (__isthreaded) {
+ _pthread_mutex_lock(&dirp->dd_lock);
+ dp = _readdir_unlocked(dirp, 1);
+ _pthread_mutex_unlock(&dirp->dd_lock);
+ }
+ else
+ dp = _readdir_unlocked(dirp, 1);
+ return (dp);
+}
+
+int
+readdir_r(dirp, entry, result)
+ DIR *dirp;
+ struct dirent *entry;
+ struct dirent **result;
+{
+ struct dirent *dp;
+ int saved_errno;
+
+ saved_errno = errno;
+ errno = 0;
+ if (__isthreaded) {
+ _pthread_mutex_lock(&dirp->dd_lock);
+ if ((dp = _readdir_unlocked(dirp, 1)) != NULL)
+ memcpy(entry, dp, _GENERIC_DIRSIZ(dp));
+ _pthread_mutex_unlock(&dirp->dd_lock);
+ }
+ else if ((dp = _readdir_unlocked(dirp, 1)) != NULL)
+ memcpy(entry, dp, _GENERIC_DIRSIZ(dp));
+
+ if (errno != 0) {
+ if (dp == NULL)
+ return (errno);
+ } else
+ errno = saved_errno;
+
+ if (dp != NULL)
+ *result = entry;
+ else
+ *result = NULL;
+
+ return (0);
+}
diff --git a/lib/libc/gen/readpassphrase.3 b/lib/libc/gen/readpassphrase.3
new file mode 100644
index 0000000..3bcee6f
--- /dev/null
+++ b/lib/libc/gen/readpassphrase.3
@@ -0,0 +1,181 @@
+.\" $OpenBSD: readpassphrase.3,v 1.17 2007/05/31 19:19:28 jmc Exp $
+.\"
+.\" Copyright (c) 2000, 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" Sponsored in part by the Defense Advanced Research Projects
+.\" Agency (DARPA) and Air Force Research Laboratory, Air Force
+.\" Materiel Command, USAF, under agreement number F39502-99-1-0512.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd May 31, 2007
+.Dt READPASSPHRASE 3
+.Os
+.Sh NAME
+.Nm readpassphrase
+.Nd get a passphrase from the user
+.Sh SYNOPSIS
+.In readpassphrase.h
+.Ft "char *"
+.Fn readpassphrase "const char *prompt" "char *buf" "size_t bufsiz" "int flags"
+.Sh DESCRIPTION
+The
+.Fn readpassphrase
+function displays a prompt to, and reads in a passphrase from,
+.Pa /dev/tty .
+If this file is inaccessible
+and the
+.Dv RPP_REQUIRE_TTY
+flag is not set,
+.Fn readpassphrase
+displays the prompt on the standard error output and reads from the standard
+input.
+In this case it is generally not possible to turn off echo.
+.Pp
+Up to
+.Fa bufsiz
+\- 1 characters (one is for the
+.Dv NUL )
+are read into the provided buffer
+.Fa buf .
+Any additional
+characters and the terminating newline (or return) character are discarded.
+.Pp
+The
+.Fn readpassphrase
+function
+takes the following optional
+.Fa flags :
+.Pp
+.Bl -tag -width ".Dv RPP_REQUIRE_TTY" -compact
+.It Dv RPP_ECHO_OFF
+turn off echo (default behavior)
+.It Dv RPP_ECHO_ON
+leave echo on
+.It Dv RPP_REQUIRE_TTY
+fail if there is no tty
+.It Dv RPP_FORCELOWER
+force input to lower case
+.It Dv RPP_FORCEUPPER
+force input to upper case
+.It Dv RPP_SEVENBIT
+strip the high bit from input
+.It Dv RPP_STDIN
+force read of passphrase from stdin
+.El
+.Pp
+The calling process should zero the passphrase as soon as possible to
+avoid leaving the cleartext passphrase visible in the process's address
+space.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn readpassphrase
+returns a pointer to the NUL-terminated passphrase.
+If an error is encountered, the terminal state is restored and
+a
+.Dv NULL
+pointer is returned.
+.Sh FILES
+.Bl -tag -width ".Pa /dev/tty" -compact
+.It Pa /dev/tty
+.El
+.Sh EXAMPLES
+The following code fragment will read a passphrase from
+.Pa /dev/tty
+into the buffer
+.Fa passbuf .
+.Bd -literal -offset indent
+char passbuf[1024];
+
+\&...
+
+if (readpassphrase("Response: ", passbuf, sizeof(passbuf),
+ RPP_REQUIRE_TTY) == NULL)
+ errx(1, "unable to read passphrase");
+
+if (compare(transform(passbuf), epass) != 0)
+ errx(1, "bad passphrase");
+
+\&...
+
+memset(passbuf, 0, sizeof(passbuf));
+.Ed
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EINTR
+The
+.Fn readpassphrase
+function was interrupted by a signal.
+.It Bq Er EINVAL
+The
+.Ar bufsiz
+argument was zero.
+.It Bq Er EIO
+The process is a member of a background process attempting to read
+from its controlling terminal, the process is ignoring or blocking
+the
+.Dv SIGTTIN
+signal, or the process group is orphaned.
+.It Bq Er EMFILE
+The process has already reached its limit for open file descriptors.
+.It Bq Er ENFILE
+The system file table is full.
+.It Bq Er ENOTTY
+There is no controlling terminal and the
+.Dv RPP_REQUIRE_TTY
+flag was specified.
+.El
+.Sh SIGNALS
+The
+.Fn readpassphrase
+function
+will catch the following signals:
+.Bd -literal -offset indent
+SIGALRM SIGHUP SIGINT
+SIGPIPE SIGQUIT SIGTERM
+SIGTSTP SIGTTIN SIGTTOU
+.Ed
+.Pp
+When one of the above signals is intercepted, terminal echo will
+be restored if it had previously been turned off.
+If a signal handler was installed for the signal when
+.Fn readpassphrase
+was called, that handler is then executed.
+If no handler was previously installed for the signal then the
+default action is taken as per
+.Xr sigaction 2 .
+.Pp
+The
+.Dv SIGTSTP , SIGTTIN
+and
+.Dv SIGTTOU
+signals (stop signals generated from keyboard or due to terminal I/O
+from a background process) are treated specially.
+When the process is resumed after it has been stopped,
+.Fn readpassphrase
+will reprint the prompt and the user may then enter a passphrase.
+.Sh SEE ALSO
+.Xr sigaction 2 ,
+.Xr getpass 3
+.Sh STANDARDS
+The
+.Fn readpassphrase
+function is an
+extension and should not be used if portability is desired.
+.Sh HISTORY
+The
+.Fn readpassphrase
+function first appeared in
+.Ox 2.9 .
diff --git a/lib/libc/gen/readpassphrase.c b/lib/libc/gen/readpassphrase.c
new file mode 100644
index 0000000..d57e703
--- /dev/null
+++ b/lib/libc/gen/readpassphrase.c
@@ -0,0 +1,194 @@
+/* $OpenBSD: readpassphrase.c,v 1.23 2010/05/14 13:30:34 millert Exp $ */
+
+/*
+ * Copyright (c) 2000-2002, 2007, 2010
+ * Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <ctype.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <pwd.h>
+#include <signal.h>
+#include <string.h>
+#include <termios.h>
+#include <unistd.h>
+#include <readpassphrase.h>
+#include "un-namespace.h"
+
+static volatile sig_atomic_t signo[NSIG];
+
+static void handler(int);
+
+char *
+readpassphrase(const char *prompt, char *buf, size_t bufsiz, int flags)
+{
+ ssize_t nr;
+ int input, output, save_errno, i, need_restart;
+ char ch, *p, *end;
+ struct termios term, oterm;
+ struct sigaction sa, savealrm, saveint, savehup, savequit, saveterm;
+ struct sigaction savetstp, savettin, savettou, savepipe;
+
+ /* I suppose we could alloc on demand in this case (XXX). */
+ if (bufsiz == 0) {
+ errno = EINVAL;
+ return(NULL);
+ }
+
+restart:
+ for (i = 0; i < NSIG; i++)
+ signo[i] = 0;
+ nr = -1;
+ save_errno = 0;
+ need_restart = 0;
+ /*
+ * Read and write to /dev/tty if available. If not, read from
+ * stdin and write to stderr unless a tty is required.
+ */
+ if ((flags & RPP_STDIN) ||
+ (input = output = _open(_PATH_TTY, O_RDWR)) == -1) {
+ if (flags & RPP_REQUIRE_TTY) {
+ errno = ENOTTY;
+ return(NULL);
+ }
+ input = STDIN_FILENO;
+ output = STDERR_FILENO;
+ }
+
+ /*
+ * Turn off echo if possible.
+ * If we are using a tty but are not the foreground pgrp this will
+ * generate SIGTTOU, so do it *before* installing the signal handlers.
+ */
+ if (input != STDIN_FILENO && tcgetattr(input, &oterm) == 0) {
+ memcpy(&term, &oterm, sizeof(term));
+ if (!(flags & RPP_ECHO_ON))
+ term.c_lflag &= ~(ECHO | ECHONL);
+ if (term.c_cc[VSTATUS] != _POSIX_VDISABLE)
+ term.c_cc[VSTATUS] = _POSIX_VDISABLE;
+ (void)tcsetattr(input, TCSAFLUSH|TCSASOFT, &term);
+ } else {
+ memset(&term, 0, sizeof(term));
+ term.c_lflag |= ECHO;
+ memset(&oterm, 0, sizeof(oterm));
+ oterm.c_lflag |= ECHO;
+ }
+
+ /*
+ * Catch signals that would otherwise cause the user to end
+ * up with echo turned off in the shell. Don't worry about
+ * things like SIGXCPU and SIGVTALRM for now.
+ */
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0; /* don't restart system calls */
+ sa.sa_handler = handler;
+ (void)_sigaction(SIGALRM, &sa, &savealrm);
+ (void)_sigaction(SIGHUP, &sa, &savehup);
+ (void)_sigaction(SIGINT, &sa, &saveint);
+ (void)_sigaction(SIGPIPE, &sa, &savepipe);
+ (void)_sigaction(SIGQUIT, &sa, &savequit);
+ (void)_sigaction(SIGTERM, &sa, &saveterm);
+ (void)_sigaction(SIGTSTP, &sa, &savetstp);
+ (void)_sigaction(SIGTTIN, &sa, &savettin);
+ (void)_sigaction(SIGTTOU, &sa, &savettou);
+
+ if (!(flags & RPP_STDIN))
+ (void)_write(output, prompt, strlen(prompt));
+ end = buf + bufsiz - 1;
+ p = buf;
+ while ((nr = _read(input, &ch, 1)) == 1 && ch != '\n' && ch != '\r') {
+ if (p < end) {
+ if ((flags & RPP_SEVENBIT))
+ ch &= 0x7f;
+ if (isalpha(ch)) {
+ if ((flags & RPP_FORCELOWER))
+ ch = (char)tolower(ch);
+ if ((flags & RPP_FORCEUPPER))
+ ch = (char)toupper(ch);
+ }
+ *p++ = ch;
+ }
+ }
+ *p = '\0';
+ save_errno = errno;
+ if (!(term.c_lflag & ECHO))
+ (void)_write(output, "\n", 1);
+
+ /* Restore old terminal settings and signals. */
+ if (memcmp(&term, &oterm, sizeof(term)) != 0) {
+ while (tcsetattr(input, TCSAFLUSH|TCSASOFT, &oterm) == -1 &&
+ errno == EINTR && !signo[SIGTTOU])
+ continue;
+ }
+ (void)_sigaction(SIGALRM, &savealrm, NULL);
+ (void)_sigaction(SIGHUP, &savehup, NULL);
+ (void)_sigaction(SIGINT, &saveint, NULL);
+ (void)_sigaction(SIGQUIT, &savequit, NULL);
+ (void)_sigaction(SIGPIPE, &savepipe, NULL);
+ (void)_sigaction(SIGTERM, &saveterm, NULL);
+ (void)_sigaction(SIGTSTP, &savetstp, NULL);
+ (void)_sigaction(SIGTTIN, &savettin, NULL);
+ (void)_sigaction(SIGTTOU, &savettou, NULL);
+ if (input != STDIN_FILENO)
+ (void)_close(input);
+
+ /*
+ * If we were interrupted by a signal, resend it to ourselves
+ * now that we have restored the signal handlers.
+ */
+ for (i = 0; i < NSIG; i++) {
+ if (signo[i]) {
+ kill(getpid(), i);
+ switch (i) {
+ case SIGTSTP:
+ case SIGTTIN:
+ case SIGTTOU:
+ need_restart = 1;
+ }
+ }
+ }
+ if (need_restart)
+ goto restart;
+
+ if (save_errno)
+ errno = save_errno;
+ return(nr == -1 ? NULL : buf);
+}
+
+char *
+getpass(const char *prompt)
+{
+ static char buf[_PASSWORD_LEN + 1];
+
+ if (readpassphrase(prompt, buf, sizeof(buf), RPP_ECHO_OFF) == NULL)
+ buf[0] = '\0';
+ return(buf);
+}
+
+static void handler(int s)
+{
+
+ signo[s] = 1;
+}
diff --git a/lib/libc/gen/rewinddir.c b/lib/libc/gen/rewinddir.c
new file mode 100644
index 0000000..45e450d
--- /dev/null
+++ b/lib/libc/gen/rewinddir.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rewinddir.c 8.1 (Berkeley) 6/8/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <dirent.h>
+
+#include "telldir.h"
+
+void
+rewinddir(dirp)
+ DIR *dirp;
+{
+
+ _seekdir(dirp, dirp->dd_rewind);
+ dirp->dd_rewind = telldir(dirp);
+}
diff --git a/lib/libc/gen/rfork_thread.3 b/lib/libc/gen/rfork_thread.3
new file mode 100644
index 0000000..dfd6fbc
--- /dev/null
+++ b/lib/libc/gen/rfork_thread.3
@@ -0,0 +1,87 @@
+.\"
+.\" Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 6, 2011
+.Dt RFORK_THREAD 3
+.Os
+.Sh NAME
+.Nm rfork_thread
+.Nd create a rfork-based process thread
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft pid_t
+.Fn rfork_thread "int flags" "void *stack" "int (*func)(void *arg)" "void *arg"
+.Sh DESCRIPTION
+.Bf -symbolic
+The
+.Fn rfork_thread
+function has been deprecated in favor of
+.Xr pthread_create 3 .
+.Ef
+.Pp
+The
+.Fn rfork_thread
+function
+is a helper function for
+.Xr rfork 2 .
+It arranges for a new process to be created and the child process will
+call the specified function with the specified argument, while running on
+the supplied stack.
+.Pp
+Using this function should avoid the need to implement complex stack
+swap code.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn rfork_thread
+returns the process ID of the child process to the parent process.
+Otherwise, a value of -1 is returned
+to the parent process, no child process is created, and the global
+variable
+.Va errno
+is set to indicate the error.
+.Pp
+The child process context is not aware of a return from the
+.Fn rfork_thread
+function as it begins executing directly with the supplied function.
+.Sh ERRORS
+See
+.Xr rfork 2
+for error return codes.
+.Sh SEE ALSO
+.Xr fork 2 ,
+.Xr intro 2 ,
+.Xr minherit 2 ,
+.Xr rfork 2 ,
+.Xr vfork 2 ,
+.Xr pthread_create 3
+.Sh HISTORY
+The
+.Fn rfork_thread
+function first appeared in
+.Fx 4.3 .
diff --git a/lib/libc/gen/scandir.3 b/lib/libc/gen/scandir.3
new file mode 100644
index 0000000..b3e0a7e
--- /dev/null
+++ b/lib/libc/gen/scandir.3
@@ -0,0 +1,106 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)scandir.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd January 3, 2010
+.Dt SCANDIR 3
+.Os
+.Sh NAME
+.Nm scandir ,
+.Nm alphasort
+.Nd scan a directory
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In dirent.h
+.Ft int
+.Fn scandir "const char *dirname" "struct dirent ***namelist" "int \*(lp*select\*(rp\*(lpconst struct dirent *\*(rp" "int \*(lp*compar\*(rp\*(lpconst struct dirent **, const struct dirent **\*(rp"
+.Ft int
+.Fn alphasort "const struct dirent **d1" "const struct dirent **d2"
+.Sh DESCRIPTION
+The
+.Fn scandir
+function
+reads the directory
+.Fa dirname
+and builds an array of pointers to directory
+entries using
+.Xr malloc 3 .
+It returns the number of entries in the array.
+A pointer to the array of directory entries is stored in the location
+referenced by
+.Fa namelist .
+.Pp
+The
+.Fa select
+argument is a pointer to a user supplied subroutine which is called by
+.Fn scandir
+to select which entries are to be included in the array.
+The select routine is passed a
+pointer to a directory entry and should return a non-zero
+value if the directory entry is to be included in the array.
+If
+.Fa select
+is null, then all the directory entries will be included.
+.Pp
+The
+.Fa compar
+argument is a pointer to a user supplied subroutine which is passed to
+.Xr qsort 3
+to sort the completed array.
+If this pointer is null, the array is not sorted.
+.Pp
+The
+.Fn alphasort
+function
+is a routine which can be used for the
+.Fa compar
+argument to sort the array alphabetically using
+.Xr strcoll 3 .
+.Pp
+The memory allocated for the array can be deallocated with
+.Xr free 3 ,
+by freeing each pointer in the array and then the array itself.
+.Sh DIAGNOSTICS
+Returns \-1 if the directory cannot be opened for reading or if
+.Xr malloc 3
+cannot allocate enough memory to hold all the data structures.
+.Sh SEE ALSO
+.Xr directory 3 ,
+.Xr malloc 3 ,
+.Xr qsort 3 ,
+.Xr dir 5 ,
+.Xr strcoll 3
+.Sh HISTORY
+The
+.Fn scandir
+and
+.Fn alphasort
+functions appeared in
+.Bx 4.2 .
diff --git a/lib/libc/gen/scandir.c b/lib/libc/gen/scandir.c
new file mode 100644
index 0000000..93bc852
--- /dev/null
+++ b/lib/libc/gen/scandir.c
@@ -0,0 +1,145 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)scandir.c 8.3 (Berkeley) 1/2/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Scan the directory dirname calling select to make a list of selected
+ * directory entries then sort using qsort and compare routine dcomp.
+ * Returns the number of entries and a pointer to a list of pointers to
+ * struct dirent (through namelist). Returns -1 if there were any errors.
+ */
+
+#include "namespace.h"
+#include <dirent.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+static int alphasort_thunk(void *thunk, const void *p1, const void *p2);
+
+/*
+ * The DIRSIZ macro is the minimum record length which will hold the directory
+ * entry. This requires the amount of space in struct dirent without the
+ * d_name field, plus enough space for the name and a terminating nul byte
+ * (dp->d_namlen + 1), rounded up to a 4 byte boundary.
+ */
+#undef DIRSIZ
+#define DIRSIZ(dp) \
+ ((sizeof(struct dirent) - sizeof(dp)->d_name) + \
+ (((dp)->d_namlen + 1 + 3) &~ 3))
+
+int
+scandir(const char *dirname, struct dirent ***namelist,
+ int (*select)(const struct dirent *), int (*dcomp)(const struct dirent **,
+ const struct dirent **))
+{
+ struct dirent *d, *p, **names = NULL;
+ size_t nitems = 0;
+ long arraysz;
+ DIR *dirp;
+
+ if ((dirp = opendir(dirname)) == NULL)
+ return(-1);
+
+ arraysz = 32; /* initial estimate of the array size */
+ names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ goto fail;
+
+ while ((d = readdir(dirp)) != NULL) {
+ if (select != NULL && !(*select)(d))
+ continue; /* just selected names */
+ /*
+ * Make a minimum size copy of the data
+ */
+ p = (struct dirent *)malloc(DIRSIZ(d));
+ if (p == NULL)
+ goto fail;
+ p->d_fileno = d->d_fileno;
+ p->d_type = d->d_type;
+ p->d_reclen = d->d_reclen;
+ p->d_namlen = d->d_namlen;
+ bcopy(d->d_name, p->d_name, p->d_namlen + 1);
+ /*
+ * Check to make sure the array has space left and
+ * realloc the maximum size.
+ */
+ if (nitems >= arraysz) {
+ struct dirent **names2;
+
+ names2 = (struct dirent **)realloc((char *)names,
+ (arraysz * 2) * sizeof(struct dirent *));
+ if (names2 == NULL) {
+ free(p);
+ goto fail;
+ }
+ names = names2;
+ arraysz *= 2;
+ }
+ names[nitems++] = p;
+ }
+ closedir(dirp);
+ if (nitems && dcomp != NULL)
+ qsort_r(names, nitems, sizeof(struct dirent *),
+ &dcomp, alphasort_thunk);
+ *namelist = names;
+ return (nitems);
+
+fail:
+ while (nitems > 0)
+ free(names[--nitems]);
+ free(names);
+ closedir(dirp);
+ return (-1);
+}
+
+/*
+ * Alphabetic order comparison routine for those who want it.
+ * POSIX 2008 requires that alphasort() uses strcoll().
+ */
+int
+alphasort(const struct dirent **d1, const struct dirent **d2)
+{
+
+ return (strcoll((*d1)->d_name, (*d2)->d_name));
+}
+
+static int
+alphasort_thunk(void *thunk, const void *p1, const void *p2)
+{
+ int (*dc)(const struct dirent **, const struct dirent **);
+
+ dc = *(int (**)(const struct dirent **, const struct dirent **))thunk;
+ return (dc((const struct dirent **)p1, (const struct dirent **)p2));
+}
diff --git a/lib/libc/gen/seed48.c b/lib/libc/gen/seed48.c
new file mode 100644
index 0000000..5339b8c
--- /dev/null
+++ b/lib/libc/gen/seed48.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "rand48.h"
+
+extern unsigned short _rand48_seed[3];
+extern unsigned short _rand48_mult[3];
+extern unsigned short _rand48_add;
+
+unsigned short *
+seed48(unsigned short xseed[3])
+{
+ static unsigned short sseed[3];
+
+ sseed[0] = _rand48_seed[0];
+ sseed[1] = _rand48_seed[1];
+ sseed[2] = _rand48_seed[2];
+ _rand48_seed[0] = xseed[0];
+ _rand48_seed[1] = xseed[1];
+ _rand48_seed[2] = xseed[2];
+ _rand48_mult[0] = RAND48_MULT_0;
+ _rand48_mult[1] = RAND48_MULT_1;
+ _rand48_mult[2] = RAND48_MULT_2;
+ _rand48_add = RAND48_ADD;
+ return sseed;
+}
diff --git a/lib/libc/gen/seekdir.c b/lib/libc/gen/seekdir.c
new file mode 100644
index 0000000..45ed6b5
--- /dev/null
+++ b/lib/libc/gen/seekdir.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)seekdir.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <dirent.h>
+#include <pthread.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+#include "telldir.h"
+
+/*
+ * Seek to an entry in a directory.
+ * _seekdir is in telldir.c so that it can share opaque data structures.
+ */
+void
+seekdir(dirp, loc)
+ DIR *dirp;
+ long loc;
+{
+ if (__isthreaded)
+ _pthread_mutex_lock(&dirp->dd_lock);
+ _seekdir(dirp, loc);
+ if (__isthreaded)
+ _pthread_mutex_unlock(&dirp->dd_lock);
+}
diff --git a/lib/libc/gen/sem.c b/lib/libc/gen/sem.c
new file mode 100644
index 0000000..71cd051
--- /dev/null
+++ b/lib/libc/gen/sem.c
@@ -0,0 +1,464 @@
+/*
+ * Copyright (C) 2010 David Xu <davidxu@freebsd.org>.
+ * Copyright (C) 2000 Jason Evans <jasone@freebsd.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice(s), this list of conditions and the following disclaimer as
+ * the first lines of this file unmodified other than the possible
+ * addition of one or more copyright notices.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice(s), this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Some notes about this implementation.
+ *
+ * This is mostly a simple implementation of POSIX semaphores that
+ * does not need threading. Any semaphore created is a kernel-based
+ * semaphore regardless of the pshared attribute. This is necessary
+ * because libc's stub for pthread_cond_wait() doesn't really wait,
+ * and it is not worth the effort impose this behavior on libc.
+ *
+ * All functions here are designed to be thread-safe so that a
+ * threads library need not provide wrappers except to make
+ * sem_wait() and sem_timedwait() cancellation points or to
+ * provide a faster userland implementation for non-pshared
+ * semaphores.
+ *
+ * Also, this implementation of semaphores cannot really support
+ * real pshared semaphores. The sem_t is an allocated object
+ * and can't be seen by other processes when placed in shared
+ * memory. It should work across forks as long as the semaphore
+ * is created before any forks.
+ *
+ * The function sem_init() should be overridden by a threads
+ * library if it wants to provide a different userland version
+ * of semaphores. The functions sem_wait() and sem_timedwait()
+ * need to be wrapped to provide cancellation points. The function
+ * sem_post() may need to be wrapped to be signal-safe.
+ */
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <machine/atomic.h>
+#include <errno.h>
+#include <sys/umtx.h>
+#include <sys/_semaphore.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <time.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+/*
+ * Old semaphore definitions.
+ */
+struct sem {
+#define SEM_MAGIC ((u_int32_t) 0x09fa4012)
+ u_int32_t magic;
+ pthread_mutex_t lock;
+ pthread_cond_t gtzero;
+ u_int32_t count;
+ u_int32_t nwaiters;
+#define SEM_USER (NULL)
+ semid_t semid; /* semaphore id if kernel (shared) semaphore */
+ int syssem; /* 1 if kernel (shared) semaphore */
+ LIST_ENTRY(sem) entry;
+ struct sem **backpointer;
+};
+
+typedef struct sem* sem_t;
+
+#define SEM_FAILED ((sem_t *)0)
+#define SEM_VALUE_MAX __INT_MAX
+
+#define SYM_FB10(sym) __CONCAT(sym, _fb10)
+#define WEAK_REF(sym, alias) __weak_reference(sym, alias)
+#define SYM_COMPAT(sym, impl, ver) __sym_compat(sym, impl, ver)
+
+#define FB10_COMPAT(func, sym) \
+ WEAK_REF(func, SYM_FB10(sym)); \
+ SYM_COMPAT(sym, SYM_FB10(sym), FBSD_1.0)
+
+static sem_t sem_alloc(unsigned int value, semid_t semid, int system_sem);
+static void sem_free(sem_t sem);
+
+static LIST_HEAD(, sem) named_sems = LIST_HEAD_INITIALIZER(named_sems);
+static pthread_mutex_t named_sems_mtx = PTHREAD_MUTEX_INITIALIZER;
+
+FB10_COMPAT(_libc_sem_init_compat, sem_init);
+FB10_COMPAT(_libc_sem_destroy_compat, sem_destroy);
+FB10_COMPAT(_libc_sem_open_compat, sem_open);
+FB10_COMPAT(_libc_sem_close_compat, sem_close);
+FB10_COMPAT(_libc_sem_unlink_compat, sem_unlink);
+FB10_COMPAT(_libc_sem_wait_compat, sem_wait);
+FB10_COMPAT(_libc_sem_trywait_compat, sem_trywait);
+FB10_COMPAT(_libc_sem_timedwait_compat, sem_timedwait);
+FB10_COMPAT(_libc_sem_post_compat, sem_post);
+FB10_COMPAT(_libc_sem_getvalue_compat, sem_getvalue);
+
+static inline int
+sem_check_validity(sem_t *sem)
+{
+
+ if ((sem != NULL) && ((*sem)->magic == SEM_MAGIC))
+ return (0);
+ else {
+ errno = EINVAL;
+ return (-1);
+ }
+}
+
+static void
+sem_free(sem_t sem)
+{
+
+ sem->magic = 0;
+ free(sem);
+}
+
+static sem_t
+sem_alloc(unsigned int value, semid_t semid, int system_sem)
+{
+ sem_t sem;
+
+ if (value > SEM_VALUE_MAX) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ sem = (sem_t)malloc(sizeof(struct sem));
+ if (sem == NULL) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+
+ sem->count = (u_int32_t)value;
+ sem->nwaiters = 0;
+ sem->magic = SEM_MAGIC;
+ sem->semid = semid;
+ sem->syssem = system_sem;
+ return (sem);
+}
+
+int
+_libc_sem_init_compat(sem_t *sem, int pshared, unsigned int value)
+{
+ semid_t semid;
+
+ /*
+ * We always have to create the kernel semaphore if the
+ * threads library isn't present since libc's version of
+ * pthread_cond_wait() is just a stub that doesn't really
+ * wait.
+ */
+ semid = (semid_t)SEM_USER;
+ if ((pshared != 0) && ksem_init(&semid, value) != 0)
+ return (-1);
+
+ *sem = sem_alloc(value, semid, pshared);
+ if ((*sem) == NULL) {
+ if (pshared != 0)
+ ksem_destroy(semid);
+ return (-1);
+ }
+ return (0);
+}
+
+int
+_libc_sem_destroy_compat(sem_t *sem)
+{
+ int retval;
+
+ if (sem_check_validity(sem) != 0)
+ return (-1);
+
+ /*
+ * If this is a system semaphore let the kernel track it otherwise
+ * make sure there are no waiters.
+ */
+ if ((*sem)->syssem != 0)
+ retval = ksem_destroy((*sem)->semid);
+ else if ((*sem)->nwaiters > 0) {
+ errno = EBUSY;
+ retval = -1;
+ }
+ else {
+ retval = 0;
+ (*sem)->magic = 0;
+ }
+
+ if (retval == 0)
+ sem_free(*sem);
+ return (retval);
+}
+
+sem_t *
+_libc_sem_open_compat(const char *name, int oflag, ...)
+{
+ sem_t *sem;
+ sem_t s;
+ semid_t semid;
+ mode_t mode;
+ unsigned int value;
+
+ mode = 0;
+ value = 0;
+
+ if ((oflag & O_CREAT) != 0) {
+ va_list ap;
+
+ va_start(ap, oflag);
+ mode = va_arg(ap, int);
+ value = va_arg(ap, unsigned int);
+ va_end(ap);
+ }
+ /*
+ * we can be lazy and let the kernel handle the "oflag",
+ * we'll just merge duplicate IDs into our list.
+ */
+ if (ksem_open(&semid, name, oflag, mode, value) == -1)
+ return (SEM_FAILED);
+ /*
+ * search for a duplicate ID, we must return the same sem_t *
+ * if we locate one.
+ */
+ _pthread_mutex_lock(&named_sems_mtx);
+ LIST_FOREACH(s, &named_sems, entry) {
+ if (s->semid == semid) {
+ sem = s->backpointer;
+ _pthread_mutex_unlock(&named_sems_mtx);
+ return (sem);
+ }
+ }
+ sem = (sem_t *)malloc(sizeof(*sem));
+ if (sem == NULL)
+ goto err;
+ *sem = sem_alloc(value, semid, 1);
+ if ((*sem) == NULL)
+ goto err;
+ LIST_INSERT_HEAD(&named_sems, *sem, entry);
+ (*sem)->backpointer = sem;
+ _pthread_mutex_unlock(&named_sems_mtx);
+ return (sem);
+err:
+ _pthread_mutex_unlock(&named_sems_mtx);
+ ksem_close(semid);
+ if (sem != NULL) {
+ if (*sem != NULL)
+ sem_free(*sem);
+ else
+ errno = ENOSPC;
+ free(sem);
+ } else {
+ errno = ENOSPC;
+ }
+ return (SEM_FAILED);
+}
+
+int
+_libc_sem_close_compat(sem_t *sem)
+{
+
+ if (sem_check_validity(sem) != 0)
+ return (-1);
+
+ if ((*sem)->syssem == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ _pthread_mutex_lock(&named_sems_mtx);
+ if (ksem_close((*sem)->semid) != 0) {
+ _pthread_mutex_unlock(&named_sems_mtx);
+ return (-1);
+ }
+ LIST_REMOVE((*sem), entry);
+ _pthread_mutex_unlock(&named_sems_mtx);
+ sem_free(*sem);
+ *sem = NULL;
+ free(sem);
+ return (0);
+}
+
+int
+_libc_sem_unlink_compat(const char *name)
+{
+
+ return (ksem_unlink(name));
+}
+
+static int
+_umtx_wait_uint(volatile unsigned *mtx, unsigned id, const struct timespec *abstime)
+{
+ struct _umtx_time *tm_p, timeout;
+ size_t tm_size;
+
+ if (abstime == NULL) {
+ tm_p = NULL;
+ tm_size = 0;
+ } else {
+ timeout._clockid = CLOCK_REALTIME;
+ timeout._flags = UMTX_ABSTIME;
+ timeout._timeout = *abstime;
+ tm_p = &timeout;
+ tm_size = sizeof(timeout);
+ }
+ return _umtx_op(__DEVOLATILE(void *, mtx),
+ UMTX_OP_WAIT_UINT_PRIVATE, id,
+ (void *)tm_size, __DECONST(void*, tm_p));
+}
+
+static int
+_umtx_wake(volatile void *mtx)
+{
+ return _umtx_op(__DEVOLATILE(void *, mtx), UMTX_OP_WAKE_PRIVATE,
+ 1, NULL, NULL);
+}
+
+#define TIMESPEC_SUB(dst, src, val) \
+ do { \
+ (dst)->tv_sec = (src)->tv_sec - (val)->tv_sec; \
+ (dst)->tv_nsec = (src)->tv_nsec - (val)->tv_nsec; \
+ if ((dst)->tv_nsec < 0) { \
+ (dst)->tv_sec--; \
+ (dst)->tv_nsec += 1000000000; \
+ } \
+ } while (0)
+
+
+static void
+sem_cancel_handler(void *arg)
+{
+ sem_t *sem = arg;
+
+ atomic_add_int(&(*sem)->nwaiters, -1);
+ if ((*sem)->nwaiters && (*sem)->count)
+ _umtx_wake(&(*sem)->count);
+}
+
+int
+_libc_sem_timedwait_compat(sem_t * __restrict sem,
+ const struct timespec * __restrict abstime)
+{
+ int val, retval;
+
+ if (sem_check_validity(sem) != 0)
+ return (-1);
+
+ if ((*sem)->syssem != 0) {
+ _pthread_cancel_enter(1);
+ retval = ksem_wait((*sem)->semid); /* XXX no timeout */
+ _pthread_cancel_leave(retval == -1);
+ return (retval);
+ }
+
+ retval = 0;
+ _pthread_testcancel();
+ for (;;) {
+ while ((val = (*sem)->count) > 0) {
+ if (atomic_cmpset_acq_int(&(*sem)->count, val, val - 1))
+ return (0);
+ }
+ if (retval) {
+ _pthread_testcancel();
+ break;
+ }
+ if (abstime) {
+ if (abstime->tv_nsec >= 1000000000 || abstime->tv_nsec < 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+ }
+ atomic_add_int(&(*sem)->nwaiters, 1);
+ pthread_cleanup_push(sem_cancel_handler, sem);
+ _pthread_cancel_enter(1);
+ retval = _umtx_wait_uint(&(*sem)->count, 0, abstime);
+ _pthread_cancel_leave(0);
+ pthread_cleanup_pop(0);
+ atomic_add_int(&(*sem)->nwaiters, -1);
+ }
+ return (retval);
+}
+
+int
+_libc_sem_wait_compat(sem_t *sem)
+{
+ return _libc_sem_timedwait_compat(sem, NULL);
+}
+
+int
+_libc_sem_trywait_compat(sem_t *sem)
+{
+ int val;
+
+ if (sem_check_validity(sem) != 0)
+ return (-1);
+
+ if ((*sem)->syssem != 0)
+ return ksem_trywait((*sem)->semid);
+
+ while ((val = (*sem)->count) > 0) {
+ if (atomic_cmpset_acq_int(&(*sem)->count, val, val - 1))
+ return (0);
+ }
+ errno = EAGAIN;
+ return (-1);
+}
+
+int
+_libc_sem_post_compat(sem_t *sem)
+{
+
+ if (sem_check_validity(sem) != 0)
+ return (-1);
+
+ if ((*sem)->syssem != 0)
+ return ksem_post((*sem)->semid);
+
+ atomic_add_rel_int(&(*sem)->count, 1);
+ rmb();
+ if ((*sem)->nwaiters)
+ return _umtx_wake(&(*sem)->count);
+ return (0);
+}
+
+int
+_libc_sem_getvalue_compat(sem_t * __restrict sem, int * __restrict sval)
+{
+ int retval;
+
+ if (sem_check_validity(sem) != 0)
+ return (-1);
+
+ if ((*sem)->syssem != 0)
+ retval = ksem_getvalue((*sem)->semid, sval);
+ else {
+ *sval = (int)(*sem)->count;
+ retval = 0;
+ }
+ return (retval);
+}
diff --git a/lib/libc/gen/sem_destroy.3 b/lib/libc/gen/sem_destroy.3
new file mode 100644
index 0000000..f488b4e
--- /dev/null
+++ b/lib/libc/gen/sem_destroy.3
@@ -0,0 +1,88 @@
+.\" Copyright (C) 2000 Jason Evans <jasone@FreeBSD.org>.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice(s), this list of conditions and the following disclaimer as
+.\" the first lines of this file unmodified other than the possible
+.\" addition of one or more copyright notices.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice(s), this list of conditions and the following disclaimer in
+.\" the documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+.\" OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 15, 2000
+.Dt SEM_DESTROY 3
+.Os
+.Sh NAME
+.Nm sem_destroy
+.Nd destroy an unnamed semaphore
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In semaphore.h
+.Ft int
+.Fn sem_destroy "sem_t *sem"
+.Sh DESCRIPTION
+The
+.Fn sem_destroy
+function destroys the unnamed semaphore pointed to by
+.Fa sem .
+After a successful call to
+.Fn sem_destroy ,
+.Fa sem
+is unusable until re-initialized by another call to
+.Xr sem_init 3 .
+.Sh RETURN VALUES
+.Rv -std sem_destroy
+.Sh ERRORS
+The
+.Fn sem_destroy
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa sem
+argument
+points to an invalid semaphore.
+.It Bq Er EBUSY
+There are currently threads blocked on the semaphore that
+.Fa sem
+points to.
+.El
+.Sh SEE ALSO
+.Xr sem_init 3 ,
+.Xr sem 4
+.Sh STANDARDS
+The
+.Fn sem_destroy
+function conforms to
+.St -p1003.1-96 .
+.Pp
+.Tn POSIX
+does not define the behavior of
+.Fn sem_destroy
+if called while there are threads blocked on
+.Fa sem ,
+but this implementation is guaranteed to return \-1 and set
+.Va errno
+to
+.Er EBUSY
+if there are threads blocked on
+.Fa sem .
diff --git a/lib/libc/gen/sem_getvalue.3 b/lib/libc/gen/sem_getvalue.3
new file mode 100644
index 0000000..a8dd177
--- /dev/null
+++ b/lib/libc/gen/sem_getvalue.3
@@ -0,0 +1,81 @@
+.\" Copyright (C) 2000 Jason Evans <jasone@FreeBSD.org>.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice(s), this list of conditions and the following disclaimer as
+.\" the first lines of this file unmodified other than the possible
+.\" addition of one or more copyright notices.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice(s), this list of conditions and the following disclaimer in
+.\" the documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+.\" OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 15, 2000
+.Dt SEM_GETVALUE 3
+.Os
+.Sh NAME
+.Nm sem_getvalue
+.Nd get the value of a semaphore
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In semaphore.h
+.Ft int
+.Fn sem_getvalue "sem_t * restrict sem" "int * restrict sval"
+.Sh DESCRIPTION
+The
+.Fn sem_getvalue
+function sets the variable pointed to by
+.Fa sval
+to the current value of the semaphore pointed to by
+.Fa sem ,
+as of the time that the call to
+.Fn sem_getvalue
+is actually run.
+.Sh RETURN VALUES
+.Rv -std sem_getvalue
+.Sh ERRORS
+The
+.Fn sem_getvalue
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa sem
+argument
+points to an invalid semaphore.
+.El
+.Sh SEE ALSO
+.Xr sem_post 3 ,
+.Xr sem_trywait 3 ,
+.Xr sem_wait 3 ,
+.Xr sem 4
+.Sh STANDARDS
+The
+.Fn sem_getvalue
+function conforms to
+.St -p1003.1-96 .
+.Pp
+The value of the semaphore is never negative, even if there are threads blocked
+on the semaphore.
+.Tn POSIX
+is somewhat ambiguous in its wording with regard to
+what the value of the semaphore should be if there are blocked waiting threads,
+but this behavior is conformant, given the wording of the specification.
diff --git a/lib/libc/gen/sem_init.3 b/lib/libc/gen/sem_init.3
new file mode 100644
index 0000000..52bcb75
--- /dev/null
+++ b/lib/libc/gen/sem_init.3
@@ -0,0 +1,102 @@
+.\" Copyright (C) 2000 Jason Evans <jasone@FreeBSD.org>.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice(s), this list of conditions and the following disclaimer as
+.\" the first lines of this file unmodified other than the possible
+.\" addition of one or more copyright notices.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice(s), this list of conditions and the following disclaimer in
+.\" the documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+.\" OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 9, 2010
+.Dt SEM_INIT 3
+.Os
+.Sh NAME
+.Nm sem_init
+.Nd initialize an unnamed semaphore
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In semaphore.h
+.Ft int
+.Fn sem_init "sem_t *sem" "int pshared" "unsigned int value"
+.Sh DESCRIPTION
+The
+.Fn sem_init
+function initializes the unnamed semaphore pointed to by
+.Fa sem
+to have the value
+.Fa value .
+.Pp
+A non-zero value for
+.Fa pshared
+specifies a shared semaphore that can be used by multiple processes,
+the semaphore should be located in shared memory region (see
+.Xr mmap 2 ,
+.Xr shm_open 2 ,
+and
+.Xr shmget 2 ) ,
+any process having read and write access to address
+.Fa sem
+can perform semaphore operations on
+.Fa sem .
+.Pp
+Following a successful call to
+.Fn sem_init ,
+.Fa sem
+can be used as an argument in subsequent calls to
+.Xr sem_wait 3 ,
+.Xr sem_trywait 3 ,
+.Xr sem_post 3 ,
+and
+.Xr sem_destroy 3 .
+The
+.Fa sem
+argument is no longer valid after a successful call to
+.Xr sem_destroy 3 .
+.Sh RETURN VALUES
+.Rv -std sem_init
+.Sh ERRORS
+The
+.Fn sem_init
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa value
+argument exceeds
+.Dv SEM_VALUE_MAX .
+.It Bq Er ENOSPC
+Memory allocation error.
+.El
+.Sh SEE ALSO
+.Xr sem_destroy 3 ,
+.Xr sem_getvalue 3 ,
+.Xr sem_post 3 ,
+.Xr sem_trywait 3 ,
+.Xr sem_wait 3 ,
+.Xr sem 4
+.Sh STANDARDS
+The
+.Fn sem_init
+function conforms to
+.St -p1003.1-96 .
diff --git a/lib/libc/gen/sem_new.c b/lib/libc/gen/sem_new.c
new file mode 100644
index 0000000..b748b49
--- /dev/null
+++ b/lib/libc/gen/sem_new.c
@@ -0,0 +1,445 @@
+/*
+ * Copyright (C) 2010 David Xu <davidxu@freebsd.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice(s), this list of conditions and the following disclaimer as
+ * the first lines of this file unmodified other than the possible
+ * addition of one or more copyright notices.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice(s), this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <machine/atomic.h>
+#include <sys/umtx.h>
+#include <limits.h>
+#include <fcntl.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <semaphore.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+__weak_reference(_sem_close, sem_close);
+__weak_reference(_sem_destroy, sem_destroy);
+__weak_reference(_sem_getvalue, sem_getvalue);
+__weak_reference(_sem_init, sem_init);
+__weak_reference(_sem_open, sem_open);
+__weak_reference(_sem_post, sem_post);
+__weak_reference(_sem_timedwait, sem_timedwait);
+__weak_reference(_sem_trywait, sem_trywait);
+__weak_reference(_sem_unlink, sem_unlink);
+__weak_reference(_sem_wait, sem_wait);
+
+#define SEM_PREFIX "/tmp/SEMD"
+#define SEM_MAGIC ((u_int32_t)0x73656d31)
+
+struct sem_nameinfo {
+ int open_count;
+ char *name;
+ sem_t *sem;
+ LIST_ENTRY(sem_nameinfo) next;
+};
+
+static pthread_once_t once = PTHREAD_ONCE_INIT;
+static pthread_mutex_t sem_llock;
+static LIST_HEAD(,sem_nameinfo) sem_list = LIST_HEAD_INITIALIZER(sem_list);
+
+static void
+sem_prefork()
+{
+
+ _pthread_mutex_lock(&sem_llock);
+}
+
+static void
+sem_postfork()
+{
+ _pthread_mutex_unlock(&sem_llock);
+}
+
+static void
+sem_child_postfork()
+{
+ _pthread_mutex_unlock(&sem_llock);
+}
+
+static void
+sem_module_init(void)
+{
+ pthread_mutexattr_t ma;
+
+ _pthread_mutexattr_init(&ma);
+ _pthread_mutexattr_settype(&ma, PTHREAD_MUTEX_RECURSIVE);
+ _pthread_mutex_init(&sem_llock, &ma);
+ _pthread_mutexattr_destroy(&ma);
+ _pthread_atfork(sem_prefork, sem_postfork, sem_child_postfork);
+}
+
+static inline int
+sem_check_validity(sem_t *sem)
+{
+
+ if (sem->_magic == SEM_MAGIC)
+ return (0);
+ else {
+ errno = EINVAL;
+ return (-1);
+ }
+}
+
+int
+_sem_init(sem_t *sem, int pshared, unsigned int value)
+{
+
+ if (value > SEM_VALUE_MAX) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ bzero(sem, sizeof(sem_t));
+ sem->_magic = SEM_MAGIC;
+ sem->_kern._count = (u_int32_t)value;
+ sem->_kern._has_waiters = 0;
+ sem->_kern._flags = pshared ? USYNC_PROCESS_SHARED : 0;
+ return (0);
+}
+
+sem_t *
+_sem_open(const char *name, int flags, ...)
+{
+ char path[PATH_MAX];
+
+ struct stat sb;
+ va_list ap;
+ struct sem_nameinfo *ni = NULL;
+ sem_t *sem = NULL;
+ int fd = -1, mode, len, errsave;
+ int value = 0;
+
+ if (name[0] != '/') {
+ errno = EINVAL;
+ return (SEM_FAILED);
+ }
+ name++;
+
+ if (flags & ~(O_CREAT|O_EXCL)) {
+ errno = EINVAL;
+ return (SEM_FAILED);
+ }
+
+ _pthread_once(&once, sem_module_init);
+
+ _pthread_mutex_lock(&sem_llock);
+ LIST_FOREACH(ni, &sem_list, next) {
+ if (strcmp(name, ni->name) == 0) {
+ if ((flags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) {
+ _pthread_mutex_unlock(&sem_llock);
+ errno = EEXIST;
+ return (SEM_FAILED);
+ } else {
+ ni->open_count++;
+ sem = ni->sem;
+ _pthread_mutex_unlock(&sem_llock);
+ return (sem);
+ }
+ }
+ }
+
+ if (flags & O_CREAT) {
+ va_start(ap, flags);
+ mode = va_arg(ap, int);
+ value = va_arg(ap, int);
+ va_end(ap);
+ }
+
+ len = sizeof(*ni) + strlen(name) + 1;
+ ni = (struct sem_nameinfo *)malloc(len);
+ if (ni == NULL) {
+ errno = ENOSPC;
+ goto error;
+ }
+
+ ni->name = (char *)(ni+1);
+ strcpy(ni->name, name);
+
+ strcpy(path, SEM_PREFIX);
+ if (strlcat(path, name, sizeof(path)) >= sizeof(path)) {
+ errno = ENAMETOOLONG;
+ goto error;
+ }
+
+ fd = _open(path, flags|O_RDWR, mode);
+ if (fd == -1)
+ goto error;
+ if (flock(fd, LOCK_EX) == -1)
+ goto error;
+ if (_fstat(fd, &sb)) {
+ flock(fd, LOCK_UN);
+ goto error;
+ }
+ if (sb.st_size < sizeof(sem_t)) {
+ sem_t tmp;
+
+ tmp._magic = SEM_MAGIC;
+ tmp._kern._has_waiters = 0;
+ tmp._kern._count = value;
+ tmp._kern._flags = USYNC_PROCESS_SHARED | SEM_NAMED;
+ if (_write(fd, &tmp, sizeof(tmp)) != sizeof(tmp)) {
+ flock(fd, LOCK_UN);
+ goto error;
+ }
+ }
+ flock(fd, LOCK_UN);
+ sem = (sem_t *)mmap(NULL, sizeof(sem_t), PROT_READ|PROT_WRITE,
+ MAP_SHARED|MAP_NOSYNC, fd, 0);
+ if (sem == MAP_FAILED) {
+ sem = NULL;
+ if (errno == ENOMEM)
+ errno = ENOSPC;
+ goto error;
+ }
+ if (sem->_magic != SEM_MAGIC) {
+ errno = EINVAL;
+ goto error;
+ }
+ ni->open_count = 1;
+ ni->sem = sem;
+ LIST_INSERT_HEAD(&sem_list, ni, next);
+ _pthread_mutex_unlock(&sem_llock);
+ _close(fd);
+ return (sem);
+
+error:
+ errsave = errno;
+ _pthread_mutex_unlock(&sem_llock);
+ if (fd != -1)
+ _close(fd);
+ if (sem != NULL)
+ munmap(sem, sizeof(sem_t));
+ free(ni);
+ errno = errsave;
+ return (SEM_FAILED);
+}
+
+int
+_sem_close(sem_t *sem)
+{
+ struct sem_nameinfo *ni;
+
+ if (sem_check_validity(sem) != 0)
+ return (-1);
+
+ if (!(sem->_kern._flags & SEM_NAMED)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ _pthread_once(&once, sem_module_init);
+
+ _pthread_mutex_lock(&sem_llock);
+ LIST_FOREACH(ni, &sem_list, next) {
+ if (sem == ni->sem) {
+ if (--ni->open_count > 0) {
+ _pthread_mutex_unlock(&sem_llock);
+ return (0);
+ }
+ else
+ break;
+ }
+ }
+
+ if (ni) {
+ LIST_REMOVE(ni, next);
+ _pthread_mutex_unlock(&sem_llock);
+ munmap(sem, sizeof(*sem));
+ free(ni);
+ return (0);
+ }
+ _pthread_mutex_unlock(&sem_llock);
+ errno = EINVAL;
+ return (-1);
+}
+
+int
+_sem_unlink(const char *name)
+{
+ char path[PATH_MAX];
+
+ if (name[0] != '/') {
+ errno = ENOENT;
+ return -1;
+ }
+ name++;
+
+ strcpy(path, SEM_PREFIX);
+ if (strlcat(path, name, sizeof(path)) >= sizeof(path)) {
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+ return unlink(path);
+}
+
+int
+_sem_destroy(sem_t *sem)
+{
+
+ if (sem_check_validity(sem) != 0)
+ return (-1);
+
+ if (sem->_kern._flags & SEM_NAMED) {
+ errno = EINVAL;
+ return (-1);
+ }
+ sem->_magic = 0;
+ return (0);
+}
+
+int
+_sem_getvalue(sem_t * __restrict sem, int * __restrict sval)
+{
+
+ if (sem_check_validity(sem) != 0)
+ return (-1);
+
+ *sval = (int)sem->_kern._count;
+ return (0);
+}
+
+static __inline int
+usem_wake(struct _usem *sem)
+{
+ return _umtx_op(sem, UMTX_OP_SEM_WAKE, 0, NULL, NULL);
+}
+
+static __inline int
+usem_wait(struct _usem *sem, const struct timespec *abstime)
+{
+ struct _umtx_time *tm_p, timeout;
+ size_t tm_size;
+
+ if (abstime == NULL) {
+ tm_p = NULL;
+ tm_size = 0;
+ } else {
+ timeout._clockid = CLOCK_REALTIME;
+ timeout._flags = UMTX_ABSTIME;
+ timeout._timeout = *abstime;
+ tm_p = &timeout;
+ tm_size = sizeof(timeout);
+ }
+ return _umtx_op(sem, UMTX_OP_SEM_WAIT, 0,
+ (void *)tm_size, __DECONST(void*, tm_p));
+}
+
+int
+_sem_trywait(sem_t *sem)
+{
+ int val;
+
+ if (sem_check_validity(sem) != 0)
+ return (-1);
+
+ while ((val = sem->_kern._count) > 0) {
+ if (atomic_cmpset_acq_int(&sem->_kern._count, val, val - 1))
+ return (0);
+ }
+ errno = EAGAIN;
+ return (-1);
+}
+
+int
+_sem_timedwait(sem_t * __restrict sem,
+ const struct timespec * __restrict abstime)
+{
+ int val, retval;
+
+ if (sem_check_validity(sem) != 0)
+ return (-1);
+
+ retval = 0;
+ for (;;) {
+ while ((val = sem->_kern._count) > 0) {
+ if (atomic_cmpset_acq_int(&sem->_kern._count, val, val - 1))
+ return (0);
+ }
+
+ if (retval) {
+ _pthread_testcancel();
+ break;
+ }
+
+ /*
+ * The timeout argument is only supposed to
+ * be checked if the thread would have blocked.
+ */
+ if (abstime != NULL) {
+ if (abstime->tv_nsec >= 1000000000 || abstime->tv_nsec < 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+ }
+ _pthread_cancel_enter(1);
+ retval = usem_wait(&sem->_kern, abstime);
+ _pthread_cancel_leave(0);
+ }
+ return (retval);
+}
+
+int
+_sem_wait(sem_t *sem)
+{
+ return _sem_timedwait(sem, NULL);
+}
+
+/*
+ * POSIX:
+ * The sem_post() interface is reentrant with respect to signals and may be
+ * invoked from a signal-catching function.
+ * The implementation does not use lock, so it should be safe.
+ */
+int
+_sem_post(sem_t *sem)
+{
+ unsigned int count;
+
+ if (sem_check_validity(sem) != 0)
+ return (-1);
+
+ do {
+ count = sem->_kern._count;
+ if (count + 1 > SEM_VALUE_MAX)
+ return (EOVERFLOW);
+ } while(!atomic_cmpset_rel_int(&sem->_kern._count, count, count+1));
+ (void)usem_wake(&sem->_kern);
+ return (0);
+}
diff --git a/lib/libc/gen/sem_open.3 b/lib/libc/gen/sem_open.3
new file mode 100644
index 0000000..3527605
--- /dev/null
+++ b/lib/libc/gen/sem_open.3
@@ -0,0 +1,225 @@
+.\" Copyright (C) 2000 Jason Evans <jasone@FreeBSD.org>.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice(s), this list of conditions and the following disclaimer as
+.\" the first lines of this file unmodified other than the possible
+.\" addition of one or more copyright notices.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice(s), this list of conditions and the following disclaimer in
+.\" the documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+.\" OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 9, 2010
+.Dt SEM_OPEN 3
+.Os
+.Sh NAME
+.Nm sem_open ,
+.Nm sem_close ,
+.Nm sem_unlink
+.Nd named semaphore operations
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In semaphore.h
+.Ft "sem_t *"
+.Fn sem_open "const char *name" "int oflag" ...
+.Ft int
+.Fn sem_close "sem_t *sem"
+.Ft int
+.Fn sem_unlink "const char *name"
+.Sh DESCRIPTION
+The
+.Fn sem_open
+function creates or opens the named semaphore specified by
+.Fa name .
+The returned semaphore may be used in subsequent calls to
+.Xr sem_getvalue 3 ,
+.Xr sem_wait 3 ,
+.Xr sem_trywait 3 ,
+.Xr sem_post 3 ,
+and
+.Fn sem_close .
+.Pp
+This implementation places strict requirements on the value of
+.Fa name :
+it must begin with a slash
+.Pq Ql /
+and contain no other slash characters.
+.Pp
+The following bits may be set in the
+.Fa oflag
+argument:
+.Bl -tag -width ".Dv O_CREAT"
+.It Dv O_CREAT
+Create the semaphore if it does not already exist.
+.Pp
+The third argument to the call to
+.Fn sem_open
+must be of type
+.Vt mode_t
+and specifies the mode for the semaphore.
+Only the
+.Dv S_IWUSR , S_IWGRP ,
+and
+.Dv S_IWOTH
+bits are examined;
+it is not possible to grant only
+.Dq read
+permission on a semaphore.
+The mode is modified according to the process's file creation
+mask; see
+.Xr umask 2 .
+.Pp
+The fourth argument must be an
+.Vt "unsigned int"
+and specifies the initial value for the semaphore,
+and must be no greater than
+.Dv SEM_VALUE_MAX .
+.It Dv O_EXCL
+Create the semaphore if it does not exist.
+If the semaphore already exists,
+.Fn sem_open
+will fail.
+This flag is ignored unless
+.Dv O_CREAT
+is also specified.
+.El
+.Pp
+The
+.Fn sem_close
+function closes a named semaphore that was opened by a call to
+.Fn sem_open .
+.Pp
+The
+.Fn sem_unlink
+function removes the semaphore named
+.Fa name .
+Resources allocated to the semaphore are only deallocated when all
+processes that have the semaphore open close it.
+.Sh RETURN VALUES
+If successful,
+the
+.Fn sem_open
+function returns the address of the opened semaphore.
+If the same
+.Fa name
+argument is given to multiple calls to
+.Fn sem_open
+by the same process without an intervening call to
+.Fn sem_close ,
+the same address is returned each time.
+If the semaphore cannot be opened,
+.Fn sem_open
+returns
+.Dv SEM_FAILED
+and the global variable
+.Va errno
+is set to indicate the error.
+.Pp
+.Rv -std sem_close sem_unlink
+.Sh ERRORS
+The
+.Fn sem_open
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EACCES
+The semaphore exists and the permissions specified by
+.Fa oflag
+at the time it was created deny access to this process.
+.It Bq Er EACCES
+The semaphore does not exist, but permission to create it is denied.
+.It Bq Er EEXIST
+.Dv O_CREAT
+and
+.Dv O_EXCL
+are set but the semaphore already exists.
+.It Bq Er EINTR
+The call was interrupted by a signal.
+.It Bq Er EINVAL
+The
+.Fn sem_open
+operation is not supported for the given
+.Fa name .
+.It Bq Er EINVAL
+The
+.Fa value
+argument is greater than
+.Dv SEM_VALUE_MAX .
+.\"FreeBSD never returns EMFILE
+.\".It Bq Er EMFILE
+.\"Too many semaphores are in use by this process.
+.It Bq Er ENAMETOOLONG
+The
+.Fa name
+argument is too long.
+.It Bq Er ENFILE
+The system limit on semaphores has been reached.
+.It Bq Er ENOENT
+.Dv O_CREAT
+is not set but the named semaphore does not exist.
+.It Bq Er ENOSPC
+There is not enough space to create the semaphore.
+.El
+.Pp
+The
+.Fn sem_close
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa sem
+argument is not a valid semaphore.
+.El
+.Pp
+The
+.Fn sem_unlink
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EACCES
+Permission is denied to unlink the semaphore.
+.It Bq Er ENAMETOOLONG
+The specified
+.Fa name
+is too long.
+.It Bq Er ENOENT
+The named semaphore does not exist.
+.El
+.Sh SEE ALSO
+.Xr close 2 ,
+.Xr open 2 ,
+.Xr umask 2 ,
+.Xr unlink 2 ,
+.Xr sem_getvalue 3 ,
+.Xr sem_post 3 ,
+.Xr sem_trywait 3 ,
+.Xr sem_wait 3 ,
+.Xr sem 4
+.Sh STANDARDS
+The
+.Fn sem_open ,
+.Fn sem_close ,
+and
+.Fn sem_unlink
+functions conform to
+.St -p1003.1-96 .
+.Sh HISTORY
+Support for named semaphores first appeared in
+.Fx 5.0 .
diff --git a/lib/libc/gen/sem_post.3 b/lib/libc/gen/sem_post.3
new file mode 100644
index 0000000..67559cc
--- /dev/null
+++ b/lib/libc/gen/sem_post.3
@@ -0,0 +1,78 @@
+.\" Copyright (C) 2000 Jason Evans <jasone@FreeBSD.org>.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice(s), this list of conditions and the following disclaimer as
+.\" the first lines of this file unmodified other than the possible
+.\" addition of one or more copyright notices.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice(s), this list of conditions and the following disclaimer in
+.\" the documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+.\" OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 15, 2000
+.Dt SEM_POST 3
+.Os
+.Sh NAME
+.Nm sem_post
+.Nd increment (unlock) a semaphore
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In semaphore.h
+.Ft int
+.Fn sem_post "sem_t *sem"
+.Sh DESCRIPTION
+The
+.Fn sem_post
+function increments (unlocks) the semaphore pointed to by
+.Fa sem .
+If there are threads blocked on the semaphore when
+.Fn sem_post
+is called, then the highest priority thread that has been blocked the longest on
+the semaphore will be allowed to return from
+.Fn sem_wait .
+.Pp
+The
+.Fn sem_post
+function is signal-reentrant and may be called within signal handlers.
+.Sh RETURN VALUES
+.Rv -std sem_post
+.Sh ERRORS
+The
+.Fn sem_post
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa sem
+argument
+points to an invalid semaphore.
+.El
+.Sh SEE ALSO
+.Xr sem_getvalue 3 ,
+.Xr sem_trywait 3 ,
+.Xr sem_wait 3 ,
+.Xr sem 4
+.Sh STANDARDS
+The
+.Fn sem_post
+function conforms to
+.St -p1003.1-96 .
diff --git a/lib/libc/gen/sem_timedwait.3 b/lib/libc/gen/sem_timedwait.3
new file mode 100644
index 0000000..3a58d41
--- /dev/null
+++ b/lib/libc/gen/sem_timedwait.3
@@ -0,0 +1,120 @@
+.\" Copyright (c) 2008, David Xu <davidxu@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 3, 2008
+.Dt SEM_TIMEDWAIT 3
+.Os
+.Sh NAME
+.Nm sem_timedwait
+.Nd "lock a semaphore"
+.Sh LIBRARY
+.Lb libpthread
+.Sh SYNOPSIS
+.In semaphore.h
+.Ft int
+.Fn sem_timedwait "sem_t *sem" "const struct timespec *abs_timeout"
+.Sh DESCRIPTION
+The
+.Fn sem_timedwait
+function locks the semaphore referenced by
+.Fa sem ,
+as in the
+.Xr sem_wait 3
+function.
+However, if the semaphore cannot be locked without waiting for
+another process or thread to unlock the semaphore by performing
+a
+.Xr sem_post 3
+function, this wait will be terminated when the specified timeout expires.
+.Pp
+The timeout will expire when the absolute time specified by
+.Fa abs_timeout
+passes, as measured by the clock on which timeouts are based (that is,
+when the value of that clock equals or exceeds
+.Fa abs_timeout ) ,
+or if the
+absolute time specified by
+.Fa abs_timeout
+has already been passed at the time of the call.
+.Pp
+Note that the timeout is based on the
+.Dv CLOCK_REALTIME
+clock.
+.Pp
+The validity of the
+.Fa abs_timeout
+is not checked if the semaphore can be locked immediately.
+.Sh RETURN VALUES
+The
+.Fn sem_timedwait
+function returns zero if the calling process successfully performed the
+semaphore lock operation on the semaphore designated by
+.Fa sem .
+If the call was unsuccessful, the state of the semaphore is unchanged,
+and the function returns a value of \-1 and sets the global variable
+.Va errno
+to indicate the error.
+.Sh ERRORS
+The
+.Fn sem_timedwait
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa sem
+argument does not refer to a valid semaphore, or the process or thread would
+have blocked, and the
+.Fa abs_timeout
+parameter specified a nanoseconds field value less than zero or greater than
+or equal to 1000 million.
+.It Bq Er ETIMEDOUT
+The semaphore could not be locked before the specified timeout expired.
+.It Bq Er EINTR
+A signal interrupted this function.
+.El
+.Sh SEE ALSO
+.Xr sem_post 3 ,
+.Xr sem_trywait 3 ,
+.Xr sem_wait 3 ,
+.Xr sem 4
+.Sh STANDARDS
+The
+.Fn sem_timedwait
+function conforms to
+.St -p1003.1-2004 .
+.Sh HISTORY
+The function first appeared in
+.Fx 5.0 .
diff --git a/lib/libc/gen/sem_wait.3 b/lib/libc/gen/sem_wait.3
new file mode 100644
index 0000000..18e9586
--- /dev/null
+++ b/lib/libc/gen/sem_wait.3
@@ -0,0 +1,95 @@
+.\" Copyright (C) 2000 Jason Evans <jasone@FreeBSD.org>.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice(s), this list of conditions and the following disclaimer as
+.\" the first lines of this file unmodified other than the possible
+.\" addition of one or more copyright notices.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice(s), this list of conditions and the following disclaimer in
+.\" the documentation and/or other materials provided with the
+.\" distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER(S) ``AS IS'' AND ANY
+.\" EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER(S) BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+.\" BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+.\" OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+.\" EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 15, 2000
+.Dt SEM_WAIT 3
+.Os
+.Sh NAME
+.Nm sem_wait ,
+.Nm sem_trywait
+.Nd decrement (lock) a semaphore
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In semaphore.h
+.Ft int
+.Fn sem_wait "sem_t *sem"
+.Ft int
+.Fn sem_trywait "sem_t *sem"
+.Sh DESCRIPTION
+The
+.Fn sem_wait
+function decrements (locks) the semaphore pointed to by
+.Fa sem ,
+but blocks if the value of
+.Fa sem
+is zero, until the value is non-zero and the value can be decremented.
+.Pp
+The
+.Fn sem_trywait
+function decrements (locks) the semaphore pointed to by
+.Fa sem
+only if the value is non-zero.
+Otherwise, the semaphore is not decremented and
+an error is returned.
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+The
+.Fn sem_wait
+and
+.Fn sem_trywait
+functions will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa sem
+argument
+points to an invalid semaphore.
+.El
+.Pp
+Additionally,
+.Fn sem_trywait
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EAGAIN
+The semaphore value was zero, and thus could not be decremented.
+.El
+.Sh SEE ALSO
+.Xr sem_getvalue 3 ,
+.Xr sem_post 3 ,
+.Xr sem_timedwait 3 ,
+.Xr sem 4
+.Sh STANDARDS
+The
+.Fn sem_wait
+and
+.Fn sem_trywait
+functions conform to
+.St -p1003.1-96 .
diff --git a/lib/libc/gen/semctl.c b/lib/libc/gen/semctl.c
new file mode 100644
index 0000000..156d18c
--- /dev/null
+++ b/lib/libc/gen/semctl.c
@@ -0,0 +1,83 @@
+/*-
+ * Copyright (c) 2002 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define _WANT_SEMUN_OLD
+
+#include <sys/types.h>
+#include <sys/ipc.h>
+#include <sys/sem.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+int __semctl(int semid, int semnum, int cmd, union semun *arg);
+int freebsd7___semctl(int semid, int semnum, int cmd, union semun_old *arg);
+
+int
+semctl(int semid, int semnum, int cmd, ...)
+{
+ va_list ap;
+ union semun semun;
+ union semun *semun_ptr;
+
+ va_start(ap, cmd);
+ if (cmd == IPC_SET || cmd == IPC_STAT || cmd == GETALL
+ || cmd == SETVAL || cmd == SETALL) {
+ semun = va_arg(ap, union semun);
+ semun_ptr = &semun;
+ } else {
+ semun_ptr = NULL;
+ }
+ va_end(ap);
+
+ return (__semctl(semid, semnum, cmd, semun_ptr));
+}
+
+int
+freebsd7_semctl(int semid, int semnum, int cmd, ...)
+{
+ va_list ap;
+ union semun_old semun;
+ union semun_old *semun_ptr;
+
+ va_start(ap, cmd);
+ if (cmd == IPC_SET || cmd == IPC_STAT || cmd == GETALL
+ || cmd == SETVAL || cmd == SETALL) {
+ semun = va_arg(ap, union semun_old);
+ semun_ptr = &semun;
+ } else {
+ semun_ptr = NULL;
+ }
+ va_end(ap);
+
+ return (freebsd7___semctl(semid, semnum, cmd, semun_ptr));
+}
+
+__sym_compat(semctl, freebsd7_semctl, FBSD_1.0);
diff --git a/lib/libc/gen/setdomainname.c b/lib/libc/gen/setdomainname.c
new file mode 100644
index 0000000..cba67a7
--- /dev/null
+++ b/lib/libc/gen/setdomainname.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)sethostname.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <unistd.h>
+
+int
+setdomainname(const char *name, int namelen)
+{
+ int mib[2];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_NISDOMAINNAME;
+ if (sysctl(mib, 2, NULL, NULL, (void *)name, namelen) == -1)
+ return (-1);
+ return (0);
+}
diff --git a/lib/libc/gen/sethostname.c b/lib/libc/gen/sethostname.c
new file mode 100644
index 0000000..466ff57
--- /dev/null
+++ b/lib/libc/gen/sethostname.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)sethostname.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <unistd.h>
+
+int
+sethostname(const char *name, int namelen)
+{
+ int mib[2];
+
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_HOSTNAME;
+ if (sysctl(mib, 2, NULL, NULL, (void *)name, namelen) == -1)
+ return (-1);
+ return (0);
+}
diff --git a/lib/libc/gen/setjmp.3 b/lib/libc/gen/setjmp.3
new file mode 100644
index 0000000..5c995f0
--- /dev/null
+++ b/lib/libc/gen/setjmp.3
@@ -0,0 +1,172 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)setjmp.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt SETJMP 3
+.Os
+.Sh NAME
+.Nm sigsetjmp ,
+.Nm siglongjmp ,
+.Nm setjmp ,
+.Nm longjmp ,
+.Nm _setjmp ,
+.Nm _longjmp ,
+.Nm longjmperror
+.Nd non-local jumps
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In setjmp.h
+.Ft int
+.Fn sigsetjmp "sigjmp_buf env" "int savemask"
+.Ft void
+.Fn siglongjmp "sigjmp_buf env" "int val"
+.Ft int
+.Fn setjmp "jmp_buf env"
+.Ft void
+.Fn longjmp "jmp_buf env" "int val"
+.Ft int
+.Fn _setjmp "jmp_buf env"
+.Ft void
+.Fn _longjmp "jmp_buf env" "int val"
+.Ft void
+.Fn longjmperror void
+.Sh DESCRIPTION
+The
+.Fn sigsetjmp ,
+.Fn setjmp ,
+and
+.Fn _setjmp
+functions save their calling environment in
+.Fa env .
+Each of these functions returns 0.
+.Pp
+The corresponding
+.Fn longjmp
+functions restore the environment saved by their most recent respective
+invocations
+of the
+.Fn setjmp
+function.
+They then return so that program execution continues as if the corresponding
+invocation of the
+.Fn setjmp
+call had just returned the value specified by
+.Fa val ,
+instead of 0.
+.Pp
+Pairs of calls may be intermixed, i.e., both
+.Fn sigsetjmp
+and
+.Fn siglongjmp
+and
+.Fn setjmp
+and
+.Fn longjmp
+combinations may be used in the same program, however, individual
+calls may not, e.g.\& the
+.Fa env
+argument to
+.Fn setjmp
+may not be passed to
+.Fn siglongjmp .
+.Pp
+The
+.Fn longjmp
+routines may not be called after the routine which called the
+.Fn setjmp
+routines returns.
+.Pp
+All accessible objects have values as of the time
+.Fn longjmp
+routine was called, except that the values of objects of automatic storage
+invocation duration that do not have the
+.Vt volatile
+type and have been changed between the
+.Fn setjmp
+invocation and
+.Fn longjmp
+call are indeterminate.
+.Pp
+The
+.Fn setjmp Ns / Ns Fn longjmp
+pairs save and restore the signal mask while
+.Fn _setjmp Ns / Ns Fn _longjmp
+pairs save and restore only the register set and the stack.
+(See
+.Fn sigprocmask 2 . )
+.Pp
+The
+.Fn sigsetjmp Ns / Ns Fn siglongjmp
+function
+pairs save and restore the signal mask if the argument
+.Fa savemask
+is non-zero, otherwise only the register set and the stack are saved.
+.Sh ERRORS
+If the contents of the
+.Fa env
+are corrupted, or correspond to an environment that has already returned,
+the
+.Fn longjmp
+routine calls the routine
+.Fn longjmperror 3 .
+If
+.Fn longjmperror
+returns the program is aborted (see
+.Xr abort 3 ) .
+The default version of
+.Fn longjmperror
+prints the message
+.Dq Li longjmp botch
+to standard error and returns.
+User programs wishing to exit more gracefully should write their own
+versions of
+.Fn longjmperror .
+.Sh SEE ALSO
+.Xr sigaction 2 ,
+.Xr sigaltstack 2 ,
+.Xr signal 3
+.Sh STANDARDS
+The
+.Fn setjmp
+and
+.Fn longjmp
+functions conform to
+.St -isoC .
+The
+.Fn sigsetjmp
+and
+.Fn siglongjmp
+functions conform to
+.St -p1003.1-88 .
diff --git a/lib/libc/gen/setjmperr.c b/lib/libc/gen/setjmperr.c
new file mode 100644
index 0000000..3cfeb55
--- /dev/null
+++ b/lib/libc/gen/setjmperr.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setjmperr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * This routine is called from longjmp() when an error occurs.
+ * Programs that wish to exit gracefully from this error may
+ * write their own versions.
+ * If this routine returns, the program is aborted.
+ */
+
+#include "namespace.h"
+#include <setjmp.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+void
+longjmperror()
+{
+#define ERRMSG "longjmp botch.\n"
+ (void)_write(STDERR_FILENO, ERRMSG, sizeof(ERRMSG) - 1);
+}
diff --git a/lib/libc/gen/setmode.3 b/lib/libc/gen/setmode.3
new file mode 100644
index 0000000..5cab44a
--- /dev/null
+++ b/lib/libc/gen/setmode.3
@@ -0,0 +1,114 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)setmode.3 8.2 (Berkeley) 4/28/95
+.\" $FreeBSD$
+.\"
+.Dd April 28, 1995
+.Dt SETMODE 3
+.Os
+.Sh NAME
+.Nm getmode ,
+.Nm setmode
+.Nd modify mode bits
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft mode_t
+.Fn getmode "const void *set" "mode_t mode"
+.Ft void *
+.Fn setmode "const char *mode_str"
+.Sh DESCRIPTION
+The
+.Fn getmode
+function
+returns a copy of the file permission bits
+.Fa mode
+as altered by the values pointed to by
+.Fa set .
+While only the mode bits are altered, other parts of the file mode
+may be examined.
+.Pp
+The
+.Fn setmode
+function
+takes an absolute (octal) or symbolic value, as described in
+.Xr chmod 1 ,
+as an argument
+and returns a pointer to mode values to be supplied to
+.Fn getmode .
+Because some of the symbolic values are relative to the file
+creation mask,
+.Fn setmode
+may call
+.Xr umask 2 .
+If this occurs, the file creation mask will be restored before
+.Fn setmode
+returns.
+If the calling program changes the value of its file creation mask
+after calling
+.Fn setmode ,
+.Fn setmode
+must be called again if
+.Fn getmode
+is to modify future file modes correctly.
+.Pp
+If the mode passed to
+.Fn setmode
+is invalid or if memory cannot be allocated for the return value,
+.Fn setmode
+returns
+.Dv NULL .
+.Pp
+The value returned from
+.Fn setmode
+is obtained from
+.Fn malloc
+and should be returned to the system with
+.Fn free
+when the program is done with it, generally after a call to
+.Fn getmode .
+.Sh ERRORS
+The
+.Fn setmode
+function
+may fail and set errno for any of the errors specified for the library
+routine
+.Xr malloc 3 .
+.Sh SEE ALSO
+.Xr chmod 1 ,
+.Xr stat 2 ,
+.Xr umask 2 ,
+.Xr malloc 3
+.Sh HISTORY
+The
+.Fn getmode
+and
+.Fn setmode
+functions first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/setmode.c b/lib/libc/gen/setmode.c
new file mode 100644
index 0000000..3966fd0
--- /dev/null
+++ b/lib/libc/gen/setmode.c
@@ -0,0 +1,446 @@
+/*
+ * Copyright (c) 1989, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Dave Borman at Cray Research, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setmode.c 8.2 (Berkeley) 3/25/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <ctype.h>
+#include <signal.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#ifdef SETMODE_DEBUG
+#include <stdio.h>
+#endif
+#include "un-namespace.h"
+
+#define SET_LEN 6 /* initial # of bitcmd struct to malloc */
+#define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */
+
+typedef struct bitcmd {
+ char cmd;
+ char cmd2;
+ mode_t bits;
+} BITCMD;
+
+#define CMD2_CLR 0x01
+#define CMD2_SET 0x02
+#define CMD2_GBITS 0x04
+#define CMD2_OBITS 0x08
+#define CMD2_UBITS 0x10
+
+static BITCMD *addcmd(BITCMD *, int, int, int, u_int);
+static void compress_mode(BITCMD *);
+#ifdef SETMODE_DEBUG
+static void dumpmode(BITCMD *);
+#endif
+
+/*
+ * Given the old mode and an array of bitcmd structures, apply the operations
+ * described in the bitcmd structures to the old mode, and return the new mode.
+ * Note that there is no '=' command; a strict assignment is just a '-' (clear
+ * bits) followed by a '+' (set bits).
+ */
+mode_t
+getmode(const void *bbox, mode_t omode)
+{
+ const BITCMD *set;
+ mode_t clrval, newmode, value;
+
+ set = (const BITCMD *)bbox;
+ newmode = omode;
+ for (value = 0;; set++)
+ switch(set->cmd) {
+ /*
+ * When copying the user, group or other bits around, we "know"
+ * where the bits are in the mode so that we can do shifts to
+ * copy them around. If we don't use shifts, it gets real
+ * grundgy with lots of single bit checks and bit sets.
+ */
+ case 'u':
+ value = (newmode & S_IRWXU) >> 6;
+ goto common;
+
+ case 'g':
+ value = (newmode & S_IRWXG) >> 3;
+ goto common;
+
+ case 'o':
+ value = newmode & S_IRWXO;
+common: if (set->cmd2 & CMD2_CLR) {
+ clrval =
+ (set->cmd2 & CMD2_SET) ? S_IRWXO : value;
+ if (set->cmd2 & CMD2_UBITS)
+ newmode &= ~((clrval<<6) & set->bits);
+ if (set->cmd2 & CMD2_GBITS)
+ newmode &= ~((clrval<<3) & set->bits);
+ if (set->cmd2 & CMD2_OBITS)
+ newmode &= ~(clrval & set->bits);
+ }
+ if (set->cmd2 & CMD2_SET) {
+ if (set->cmd2 & CMD2_UBITS)
+ newmode |= (value<<6) & set->bits;
+ if (set->cmd2 & CMD2_GBITS)
+ newmode |= (value<<3) & set->bits;
+ if (set->cmd2 & CMD2_OBITS)
+ newmode |= value & set->bits;
+ }
+ break;
+
+ case '+':
+ newmode |= set->bits;
+ break;
+
+ case '-':
+ newmode &= ~set->bits;
+ break;
+
+ case 'X':
+ if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
+ newmode |= set->bits;
+ break;
+
+ case '\0':
+ default:
+#ifdef SETMODE_DEBUG
+ (void)printf("getmode:%04o -> %04o\n", omode, newmode);
+#endif
+ return (newmode);
+ }
+}
+
+#define ADDCMD(a, b, c, d) \
+ if (set >= endset) { \
+ BITCMD *newset; \
+ setlen += SET_LEN_INCR; \
+ newset = realloc(saveset, sizeof(BITCMD) * setlen); \
+ if (!newset) { \
+ if (saveset) \
+ free(saveset); \
+ saveset = NULL; \
+ return (NULL); \
+ } \
+ set = newset + (set - saveset); \
+ saveset = newset; \
+ endset = newset + (setlen - 2); \
+ } \
+ set = addcmd(set, (a), (b), (c), (d))
+
+#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
+
+void *
+setmode(const char *p)
+{
+ int perm, who;
+ char op, *ep;
+ BITCMD *set, *saveset, *endset;
+ sigset_t sigset, sigoset;
+ mode_t mask;
+ int equalopdone=0, permXbits, setlen;
+ long perml;
+
+ if (!*p)
+ return (NULL);
+
+ /*
+ * Get a copy of the mask for the permissions that are mask relative.
+ * Flip the bits, we want what's not set. Since it's possible that
+ * the caller is opening files inside a signal handler, protect them
+ * as best we can.
+ */
+ sigfillset(&sigset);
+ (void)_sigprocmask(SIG_BLOCK, &sigset, &sigoset);
+ (void)umask(mask = umask(0));
+ mask = ~mask;
+ (void)_sigprocmask(SIG_SETMASK, &sigoset, NULL);
+
+ setlen = SET_LEN + 2;
+
+ if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
+ return (NULL);
+ saveset = set;
+ endset = set + (setlen - 2);
+
+ /*
+ * If an absolute number, get it and return; disallow non-octal digits
+ * or illegal bits.
+ */
+ if (isdigit((unsigned char)*p)) {
+ perml = strtol(p, &ep, 8);
+ if (*ep || perml < 0 || perml & ~(STANDARD_BITS|S_ISTXT)) {
+ free(saveset);
+ return (NULL);
+ }
+ perm = (mode_t)perml;
+ ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
+ set->cmd = 0;
+ return (saveset);
+ }
+
+ /*
+ * Build list of structures to set/clear/copy bits as described by
+ * each clause of the symbolic mode.
+ */
+ for (;;) {
+ /* First, find out which bits might be modified. */
+ for (who = 0;; ++p) {
+ switch (*p) {
+ case 'a':
+ who |= STANDARD_BITS;
+ break;
+ case 'u':
+ who |= S_ISUID|S_IRWXU;
+ break;
+ case 'g':
+ who |= S_ISGID|S_IRWXG;
+ break;
+ case 'o':
+ who |= S_IRWXO;
+ break;
+ default:
+ goto getop;
+ }
+ }
+
+getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
+ free(saveset);
+ return (NULL);
+ }
+ if (op == '=')
+ equalopdone = 0;
+
+ who &= ~S_ISTXT;
+ for (perm = 0, permXbits = 0;; ++p) {
+ switch (*p) {
+ case 'r':
+ perm |= S_IRUSR|S_IRGRP|S_IROTH;
+ break;
+ case 's':
+ /* If only "other" bits ignore set-id. */
+ if (!who || who & ~S_IRWXO)
+ perm |= S_ISUID|S_ISGID;
+ break;
+ case 't':
+ /* If only "other" bits ignore sticky. */
+ if (!who || who & ~S_IRWXO) {
+ who |= S_ISTXT;
+ perm |= S_ISTXT;
+ }
+ break;
+ case 'w':
+ perm |= S_IWUSR|S_IWGRP|S_IWOTH;
+ break;
+ case 'X':
+ permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
+ break;
+ case 'x':
+ perm |= S_IXUSR|S_IXGRP|S_IXOTH;
+ break;
+ case 'u':
+ case 'g':
+ case 'o':
+ /*
+ * When ever we hit 'u', 'g', or 'o', we have
+ * to flush out any partial mode that we have,
+ * and then do the copying of the mode bits.
+ */
+ if (perm) {
+ ADDCMD(op, who, perm, mask);
+ perm = 0;
+ }
+ if (op == '=')
+ equalopdone = 1;
+ if (op == '+' && permXbits) {
+ ADDCMD('X', who, permXbits, mask);
+ permXbits = 0;
+ }
+ ADDCMD(*p, who, op, mask);
+ break;
+
+ default:
+ /*
+ * Add any permissions that we haven't already
+ * done.
+ */
+ if (perm || (op == '=' && !equalopdone)) {
+ if (op == '=')
+ equalopdone = 1;
+ ADDCMD(op, who, perm, mask);
+ perm = 0;
+ }
+ if (permXbits) {
+ ADDCMD('X', who, permXbits, mask);
+ permXbits = 0;
+ }
+ goto apply;
+ }
+ }
+
+apply: if (!*p)
+ break;
+ if (*p != ',')
+ goto getop;
+ ++p;
+ }
+ set->cmd = 0;
+#ifdef SETMODE_DEBUG
+ (void)printf("Before compress_mode()\n");
+ dumpmode(saveset);
+#endif
+ compress_mode(saveset);
+#ifdef SETMODE_DEBUG
+ (void)printf("After compress_mode()\n");
+ dumpmode(saveset);
+#endif
+ return (saveset);
+}
+
+static BITCMD *
+addcmd(BITCMD *set, int op, int who, int oparg, u_int mask)
+{
+ switch (op) {
+ case '=':
+ set->cmd = '-';
+ set->bits = who ? who : STANDARD_BITS;
+ set++;
+
+ op = '+';
+ /* FALLTHROUGH */
+ case '+':
+ case '-':
+ case 'X':
+ set->cmd = op;
+ set->bits = (who ? who : mask) & oparg;
+ break;
+
+ case 'u':
+ case 'g':
+ case 'o':
+ set->cmd = op;
+ if (who) {
+ set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
+ ((who & S_IRGRP) ? CMD2_GBITS : 0) |
+ ((who & S_IROTH) ? CMD2_OBITS : 0);
+ set->bits = (mode_t)~0;
+ } else {
+ set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
+ set->bits = mask;
+ }
+
+ if (oparg == '+')
+ set->cmd2 |= CMD2_SET;
+ else if (oparg == '-')
+ set->cmd2 |= CMD2_CLR;
+ else if (oparg == '=')
+ set->cmd2 |= CMD2_SET|CMD2_CLR;
+ break;
+ }
+ return (set + 1);
+}
+
+#ifdef SETMODE_DEBUG
+static void
+dumpmode(BITCMD *set)
+{
+ for (; set->cmd; ++set)
+ (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
+ set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
+ set->cmd2 & CMD2_CLR ? " CLR" : "",
+ set->cmd2 & CMD2_SET ? " SET" : "",
+ set->cmd2 & CMD2_UBITS ? " UBITS" : "",
+ set->cmd2 & CMD2_GBITS ? " GBITS" : "",
+ set->cmd2 & CMD2_OBITS ? " OBITS" : "");
+}
+#endif
+
+/*
+ * Given an array of bitcmd structures, compress by compacting consecutive
+ * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
+ * 'g' and 'o' commands continue to be separate. They could probably be
+ * compacted, but it's not worth the effort.
+ */
+static void
+compress_mode(BITCMD *set)
+{
+ BITCMD *nset;
+ int setbits, clrbits, Xbits, op;
+
+ for (nset = set;;) {
+ /* Copy over any 'u', 'g' and 'o' commands. */
+ while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
+ *set++ = *nset++;
+ if (!op)
+ return;
+ }
+
+ for (setbits = clrbits = Xbits = 0;; nset++) {
+ if ((op = nset->cmd) == '-') {
+ clrbits |= nset->bits;
+ setbits &= ~nset->bits;
+ Xbits &= ~nset->bits;
+ } else if (op == '+') {
+ setbits |= nset->bits;
+ clrbits &= ~nset->bits;
+ Xbits &= ~nset->bits;
+ } else if (op == 'X')
+ Xbits |= nset->bits & ~setbits;
+ else
+ break;
+ }
+ if (clrbits) {
+ set->cmd = '-';
+ set->cmd2 = 0;
+ set->bits = clrbits;
+ set++;
+ }
+ if (setbits) {
+ set->cmd = '+';
+ set->cmd2 = 0;
+ set->bits = setbits;
+ set++;
+ }
+ if (Xbits) {
+ set->cmd = 'X';
+ set->cmd2 = 0;
+ set->bits = Xbits;
+ set++;
+ }
+ }
+}
diff --git a/lib/libc/gen/setproctitle.3 b/lib/libc/gen/setproctitle.3
new file mode 100644
index 0000000..0fefddf
--- /dev/null
+++ b/lib/libc/gen/setproctitle.3
@@ -0,0 +1,121 @@
+.\" Copyright (c) 1995 Peter Wemm <peter@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, is permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice immediately at the beginning of the file, without modification,
+.\" this list of conditions, and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. This work was done expressly for inclusion into FreeBSD. Other use
+.\" is permitted provided this notation is included.
+.\" 4. Absolutely no warranty of function or purpose is made by the author
+.\" Peter Wemm.
+.\" 5. Modifications may be freely made to this file providing the above
+.\" conditions are met.
+.\"
+.\" $FreeBSD$
+.\"
+.\" The following requests are required for all man pages.
+.Dd December 16, 1995
+.Dt SETPROCTITLE 3
+.Os
+.Sh NAME
+.Nm setproctitle
+.Nd set process title
+.Sh SYNOPSIS
+.In sys/types.h
+.In unistd.h
+.Ft void
+.Fn setproctitle "const char *fmt" "..."
+.Sh DESCRIPTION
+The
+.Fn setproctitle
+library routine sets the process title that appears on the
+.Xr ps 1
+command.
+.Pp
+The title is set from the executable's name, followed by the
+result of a
+.Xr printf 3
+style expansion of the arguments as specified by the
+.Va fmt
+argument.
+If the
+.Va fmt
+argument begins with a
+.Dq -
+character, the executable's name is skipped.
+.Pp
+If
+.Va fmt
+is NULL, the process title is restored.
+.Sh EXAMPLES
+To set the title on a daemon to indicate its activity:
+.Bd -literal -offset indent
+setproctitle("talking to %s", inet_ntoa(addr));
+.Ed
+.Sh SEE ALSO
+.Xr ps 1 ,
+.Xr w 1 ,
+.Xr kvm 3 ,
+.Xr kvm_getargv 3 ,
+.Xr printf 3
+.Sh STANDARDS
+The
+.Fn setproctitle
+function
+is implicitly non-standard.
+Other methods of causing the
+.Xr ps 1
+command line to change, including copying over the argv[0] string are
+also implicitly non-portable.
+It is preferable to use an operating system
+supplied
+.Fn setproctitle
+if present.
+.Pp
+Unfortunately, it is possible that there are other calling conventions
+to other versions of
+.Fn setproctitle ,
+although none have been found by the author as yet.
+This is believed to be
+the predominant convention.
+.Pp
+It is thought that the implementation is compatible with other systems,
+including
+.Nx
+and
+.Bsx .
+.Sh HISTORY
+The
+.Fn setproctitle
+function
+first appeared in
+.Fx 2.2 .
+Other operating systems have
+similar functions.
+.Sh AUTHORS
+.An -nosplit
+.An Peter Wemm Aq peter@FreeBSD.org
+stole the idea from the
+.Sy "Sendmail 8.7.3"
+source code by
+.An Eric Allman Aq eric@sendmail.org .
+.Sh BUGS
+Never pass a string with user-supplied data as a format without using
+.Ql %s .
+An attacker can put format specifiers in the string to mangle your stack,
+leading to a possible security hole.
+This holds true even if the string was built using a function like
+.Fn snprintf ,
+as the resulting string may still contain user-supplied conversion specifiers
+for later interpolation by
+.Fn setproctitle .
+.Pp
+Always use the proper secure idiom:
+.Pp
+.Dl setproctitle("%s", string);
diff --git a/lib/libc/gen/setproctitle.c b/lib/libc/gen/setproctitle.c
new file mode 100644
index 0000000..cd705fb
--- /dev/null
+++ b/lib/libc/gen/setproctitle.c
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 1995 Peter Wemm <peter@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, is permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice immediately at the beginning of the file, without modification,
+ * this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Absolutely no warranty of function or purpose is made by the author
+ * Peter Wemm.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/exec.h>
+#include <sys/sysctl.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+/*
+ * Older FreeBSD 2.0, 2.1 and 2.2 had different ps_strings structures and
+ * in different locations.
+ * 1: old_ps_strings at the very top of the stack.
+ * 2: old_ps_strings at SPARE_USRSPACE below the top of the stack.
+ * 3: ps_strings at the very top of the stack.
+ * This attempts to support a kernel built in the #2 and #3 era.
+ */
+
+struct old_ps_strings {
+ char *old_ps_argvstr;
+ int old_ps_nargvstr;
+ char *old_ps_envstr;
+ int old_ps_nenvstr;
+};
+#define OLD_PS_STRINGS ((struct old_ps_strings *) \
+ (USRSTACK - SPARE_USRSPACE - sizeof(struct old_ps_strings)))
+
+#include <stdarg.h>
+
+#define SPT_BUFSIZE 2048 /* from other parts of sendmail */
+
+void
+setproctitle(const char *fmt, ...)
+{
+ static struct ps_strings *ps_strings;
+ static char *buf = NULL;
+ static char *obuf = NULL;
+ static char **oargv, *kbuf;
+ static int oargc = -1;
+ static char *nargv[2] = { NULL, NULL };
+ char **nargvp;
+ int nargc;
+ int i;
+ va_list ap;
+ size_t len;
+ unsigned long ul_ps_strings;
+ int oid[4];
+
+ if (buf == NULL) {
+ buf = malloc(SPT_BUFSIZE);
+ if (buf == NULL)
+ return;
+ nargv[0] = buf;
+ }
+
+ if (obuf == NULL ) {
+ obuf = malloc(SPT_BUFSIZE);
+ if (obuf == NULL)
+ return;
+ *obuf = '\0';
+ }
+
+ va_start(ap, fmt);
+
+ if (fmt) {
+ buf[SPT_BUFSIZE - 1] = '\0';
+
+ if (fmt[0] == '-') {
+ /* skip program name prefix */
+ fmt++;
+ len = 0;
+ } else {
+ /* print program name heading for grep */
+ (void)snprintf(buf, SPT_BUFSIZE, "%s: ", _getprogname());
+ len = strlen(buf);
+ }
+
+ /* print the argument string */
+ (void) vsnprintf(buf + len, SPT_BUFSIZE - len, fmt, ap);
+
+ nargvp = nargv;
+ nargc = 1;
+ kbuf = buf;
+ } else if (*obuf != '\0') {
+ /* Idea from NetBSD - reset the title on fmt == NULL */
+ nargvp = oargv;
+ nargc = oargc;
+ kbuf = obuf;
+ } else
+ /* Nothing to restore */
+ return;
+
+ va_end(ap);
+
+ /* Set the title into the kernel cached command line */
+ oid[0] = CTL_KERN;
+ oid[1] = KERN_PROC;
+ oid[2] = KERN_PROC_ARGS;
+ oid[3] = getpid();
+ sysctl(oid, 4, 0, 0, kbuf, strlen(kbuf) + 1);
+
+ if (ps_strings == NULL) {
+ len = sizeof(ul_ps_strings);
+ if (sysctlbyname("kern.ps_strings", &ul_ps_strings, &len, NULL,
+ 0) == -1)
+ ul_ps_strings = PS_STRINGS;
+ ps_strings = (struct ps_strings *)ul_ps_strings;
+ }
+
+ /* PS_STRINGS points to zeroed memory on a style #2 kernel */
+ if (ps_strings->ps_argvstr) {
+ /* style #3 */
+ if (oargc == -1) {
+ /* Record our original args */
+ oargc = ps_strings->ps_nargvstr;
+ oargv = ps_strings->ps_argvstr;
+ for (i = len = 0; i < oargc; i++) {
+ /*
+ * The program may have scribbled into its
+ * argv array, e.g., to remove some arguments.
+ * If that has happened, break out before
+ * trying to call strlen on a NULL pointer.
+ */
+ if (oargv[i] == NULL) {
+ oargc = i;
+ break;
+ }
+ snprintf(obuf + len, SPT_BUFSIZE - len, "%s%s",
+ len ? " " : "", oargv[i]);
+ if (len)
+ len++;
+ len += strlen(oargv[i]);
+ if (len >= SPT_BUFSIZE)
+ break;
+ }
+ }
+ ps_strings->ps_nargvstr = nargc;
+ ps_strings->ps_argvstr = nargvp;
+ } else {
+ /* style #2 - we can only restore our first arg :-( */
+ if (*obuf == '\0')
+ strncpy(obuf, OLD_PS_STRINGS->old_ps_argvstr,
+ SPT_BUFSIZE - 1);
+ OLD_PS_STRINGS->old_ps_nargvstr = 1;
+ OLD_PS_STRINGS->old_ps_argvstr = nargvp[0];
+ }
+}
diff --git a/lib/libc/gen/setprogname.c b/lib/libc/gen/setprogname.c
new file mode 100644
index 0000000..29a6cd0
--- /dev/null
+++ b/lib/libc/gen/setprogname.c
@@ -0,0 +1,19 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <string.h>
+
+#include "libc_private.h"
+
+void
+setprogname(const char *progname)
+{
+ const char *p;
+
+ p = strrchr(progname, '/');
+ if (p != NULL)
+ __progname = p + 1;
+ else
+ __progname = progname;
+}
diff --git a/lib/libc/gen/siginterrupt.3 b/lib/libc/gen/siginterrupt.3
new file mode 100644
index 0000000..e790132
--- /dev/null
+++ b/lib/libc/gen/siginterrupt.3
@@ -0,0 +1,119 @@
+.\" Copyright (c) 1985, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)siginterrupt.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt SIGINTERRUPT 3
+.Os
+.Sh NAME
+.Nm siginterrupt
+.Nd allow signals to interrupt system calls
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In signal.h
+.Ft int
+.Fn siginterrupt "int sig" "int flag"
+.Sh DESCRIPTION
+The
+.Fn siginterrupt
+function
+is used to change the system call restart
+behavior when a system call is interrupted by the specified signal.
+If the flag is false (0), then system calls will be restarted if
+they are interrupted by the specified signal
+and no data has been transferred yet.
+System call restart has been the default behavior since
+.Bx 4.2 ,
+and is the default behaviour for
+.Xr signal 3
+on
+.Fx .
+.Pp
+If the flag is true (1),
+then restarting of system calls is disabled.
+If a system call is interrupted by the specified signal
+and no data has been transferred,
+the system call will return \-1 with the global variable
+.Va errno
+set to
+.Er EINTR .
+Interrupted system calls that have started transferring
+data will return the amount of data actually transferred.
+System call interrupt is the signal behavior found on
+.Bx 4.1
+and
+.At V
+systems.
+.Pp
+Note that the new
+.Bx 4.2
+signal handling semantics are not
+altered in any other way.
+Most notably, signal handlers always remain installed until
+explicitly changed by a subsequent
+.Xr sigaction 2
+call, and the signal mask operates as documented in
+.Xr sigaction 2 .
+Programs may switch between restartable and interruptible
+system call operation as often as desired in the execution of a program.
+.Pp
+Issuing a
+.Fn siginterrupt 3
+call during the execution of a signal handler will cause
+the new action to take place on the next signal to be caught.
+.Sh NOTES
+This library routine uses an extension of the
+.Xr sigaction 2
+system call that is not available in
+.Bx 4.2 ,
+hence it should not be used if backward compatibility is needed.
+.Sh RETURN VALUES
+.Rv -std siginterrupt
+.Sh ERRORS
+The
+.Fn siginterrupt
+call fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa sig
+argument
+is not a valid signal number.
+.El
+.Sh SEE ALSO
+.Xr sigaction 2 ,
+.Xr sigprocmask 2 ,
+.Xr sigsuspend 2 ,
+.Xr signal 3
+.Sh HISTORY
+The
+.Fn siginterrupt
+function appeared in
+.Bx 4.3 .
diff --git a/lib/libc/gen/siginterrupt.c b/lib/libc/gen/siginterrupt.c
new file mode 100644
index 0000000..dde474c
--- /dev/null
+++ b/lib/libc/gen/siginterrupt.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)siginterrupt.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <signal.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+/*
+ * Set signal state to prevent restart of system calls
+ * after an instance of the indicated signal.
+ */
+int
+siginterrupt(sig, flag)
+ int sig, flag;
+{
+ extern sigset_t _sigintr;
+ struct sigaction sa;
+ int ret;
+
+ if ((ret = _sigaction(sig, (struct sigaction *)0, &sa)) < 0)
+ return (ret);
+ if (flag) {
+ sigaddset(&_sigintr, sig);
+ sa.sa_flags &= ~SA_RESTART;
+ } else {
+ sigdelset(&_sigintr, sig);
+ sa.sa_flags |= SA_RESTART;
+ }
+ return (_sigaction(sig, &sa, (struct sigaction *)0));
+}
diff --git a/lib/libc/gen/siglist.c b/lib/libc/gen/siglist.c
new file mode 100644
index 0000000..d4abfaa
--- /dev/null
+++ b/lib/libc/gen/siglist.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)siglist.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <signal.h>
+
+const char *const sys_signame[NSIG] = {
+ "Signal 0",
+ "HUP", /* SIGHUP */
+ "INT", /* SIGINT */
+ "QUIT", /* SIGQUIT */
+ "ILL", /* SIGILL */
+ "TRAP", /* SIGTRAP */
+ "ABRT", /* SIGABRT */
+ "EMT", /* SIGEMT */
+ "FPE", /* SIGFPE */
+ "KILL", /* SIGKILL */
+ "BUS", /* SIGBUS */
+ "SEGV", /* SIGSEGV */
+ "SYS", /* SIGSYS */
+ "PIPE", /* SIGPIPE */
+ "ALRM", /* SIGALRM */
+ "TERM", /* SIGTERM */
+ "URG", /* SIGURG */
+ "STOP", /* SIGSTOP */
+ "TSTP", /* SIGTSTP */
+ "CONT", /* SIGCONT */
+ "CHLD", /* SIGCHLD */
+ "TTIN", /* SIGTTIN */
+ "TTOU", /* SIGTTOU */
+ "IO", /* SIGIO */
+ "XCPU", /* SIGXCPU */
+ "XFSZ", /* SIGXFSZ */
+ "VTALRM", /* SIGVTALRM */
+ "PROF", /* SIGPROF */
+ "WINCH", /* SIGWINCH */
+ "INFO", /* SIGINFO */
+ "USR1", /* SIGUSR1 */
+ "USR2" /* SIGUSR2 */
+};
+
+const char *const sys_siglist[NSIG] = {
+ "Signal 0",
+ "Hangup", /* SIGHUP */
+ "Interrupt", /* SIGINT */
+ "Quit", /* SIGQUIT */
+ "Illegal instruction", /* SIGILL */
+ "Trace/BPT trap", /* SIGTRAP */
+ "Abort trap", /* SIGABRT */
+ "EMT trap", /* SIGEMT */
+ "Floating point exception", /* SIGFPE */
+ "Killed", /* SIGKILL */
+ "Bus error", /* SIGBUS */
+ "Segmentation fault", /* SIGSEGV */
+ "Bad system call", /* SIGSYS */
+ "Broken pipe", /* SIGPIPE */
+ "Alarm clock", /* SIGALRM */
+ "Terminated", /* SIGTERM */
+ "Urgent I/O condition", /* SIGURG */
+ "Suspended (signal)", /* SIGSTOP */
+ "Suspended", /* SIGTSTP */
+ "Continued", /* SIGCONT */
+ "Child exited", /* SIGCHLD */
+ "Stopped (tty input)", /* SIGTTIN */
+ "Stopped (tty output)", /* SIGTTOU */
+ "I/O possible", /* SIGIO */
+ "Cputime limit exceeded", /* SIGXCPU */
+ "Filesize limit exceeded", /* SIGXFSZ */
+ "Virtual timer expired", /* SIGVTALRM */
+ "Profiling timer expired", /* SIGPROF */
+ "Window size changes", /* SIGWINCH */
+ "Information request", /* SIGINFO */
+ "User defined signal 1", /* SIGUSR1 */
+ "User defined signal 2" /* SIGUSR2 */
+};
+const int sys_nsig = sizeof(sys_siglist) / sizeof(sys_siglist[0]);
diff --git a/lib/libc/gen/signal.3 b/lib/libc/gen/signal.3
new file mode 100644
index 0000000..866eee3
--- /dev/null
+++ b/lib/libc/gen/signal.3
@@ -0,0 +1,280 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)signal.3 8.3 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd June 7, 2004
+.Dt SIGNAL 3
+.Os
+.Sh NAME
+.Nm signal
+.Nd simplified software signal facilities
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In signal.h
+.\" XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
+.\" The prototype for signal(3) cannot be cleanly marked up in -mdoc
+.\" without the following lower-level tweak.
+.nr in-synopsis-section 0
+.Pp
+.Ft "void \*(lp*" Ns
+.Fo signal
+.Fa "int sig"
+.Fa "void \*(lp*func\*(rp\*(lpint\*(rp"
+.Fc Ns
+.Ft "\*(rp\*(lpint\*(rp" ;
+.Pp
+.nr in-synopsis-section 1
+.\" XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX XXX
+or in
+.Fx Ap s
+equivalent but easier to read typedef'd version:
+.Ft typedef "void \*(lp*sig_t\*(rp \*(lpint\*(rp" ;
+.Pp
+.Ft sig_t
+.Fn signal "int sig" "sig_t func"
+.Sh DESCRIPTION
+This
+.Fn signal
+facility
+is a simplified interface to the more general
+.Xr sigaction 2
+facility.
+.Pp
+Signals allow the manipulation of a process from outside its
+domain as well as allowing the process to manipulate itself or
+copies of itself (children).
+There are two general types of signals:
+those that cause termination of a process and those that do not.
+Signals which cause termination of a program might result from
+an irrecoverable error or might be the result of a user at a terminal
+typing the `interrupt' character.
+Signals are used when a process is stopped because it wishes to access
+its control terminal while in the background (see
+.Xr tty 4 ) .
+Signals are optionally generated
+when a process resumes after being stopped,
+when the status of child processes changes,
+or when input is ready at the control terminal.
+Most signals result in the termination of the process receiving them
+if no action
+is taken; some signals instead cause the process receiving them
+to be stopped, or are simply discarded if the process has not
+requested otherwise.
+Except for the
+.Dv SIGKILL
+and
+.Dv SIGSTOP
+signals, the
+.Fn signal
+function allows for a signal to be caught, to be ignored, or to generate
+an interrupt.
+These signals are defined in the file
+.In signal.h :
+.Bl -column No ".Dv SIGVTALRM" "create core image"
+.It Sy "No Name Default Action Description"
+.It 1 Ta Dv SIGHUP Ta "terminate process" Ta "terminal line hangup"
+.It 2 Ta Dv SIGINT Ta "terminate process" Ta "interrupt program"
+.It 3 Ta Dv SIGQUIT Ta "create core image" Ta "quit program"
+.It 4 Ta Dv SIGILL Ta "create core image" Ta "illegal instruction"
+.It 5 Ta Dv SIGTRAP Ta "create core image" Ta "trace trap"
+.It 6 Ta Dv SIGABRT Ta "create core image" Ta "abort program"
+(formerly
+.Dv SIGIOT )
+.It 7 Ta Dv SIGEMT Ta "create core image" Ta "emulate instruction executed"
+.It 8 Ta Dv SIGFPE Ta "create core image" Ta "floating-point exception"
+.It 9 Ta Dv SIGKILL Ta "terminate process" Ta "kill program"
+.It 10 Ta Dv SIGBUS Ta "create core image" Ta "bus error"
+.It 11 Ta Dv SIGSEGV Ta "create core image" Ta "segmentation violation"
+.It 12 Ta Dv SIGSYS Ta "create core image" Ta "non-existent system call invoked"
+.It 13 Ta Dv SIGPIPE Ta "terminate process" Ta "write on a pipe with no reader"
+.It 14 Ta Dv SIGALRM Ta "terminate process" Ta "real-time timer expired"
+.It 15 Ta Dv SIGTERM Ta "terminate process" Ta "software termination signal"
+.It 16 Ta Dv SIGURG Ta "discard signal" Ta "urgent condition present on socket"
+.It 17 Ta Dv SIGSTOP Ta "stop process" Ta "stop (cannot be caught or ignored)"
+.It 18 Ta Dv SIGTSTP Ta "stop process" Ta "stop signal generated from keyboard"
+.It 19 Ta Dv SIGCONT Ta "discard signal" Ta "continue after stop"
+.It 20 Ta Dv SIGCHLD Ta "discard signal" Ta "child status has changed"
+.It 21 Ta Dv SIGTTIN Ta "stop process" Ta "background read attempted from"
+control terminal
+.It 22 Ta Dv SIGTTOU Ta "stop process" Ta "background write attempted to"
+control terminal
+.It 23 Ta Dv SIGIO Ta "discard signal" Ta Tn "I/O"
+is possible on a descriptor (see
+.Xr fcntl 2 )
+.It 24 Ta Dv SIGXCPU Ta "terminate process" Ta "cpu time limit exceeded (see"
+.Xr setrlimit 2 )
+.It 25 Ta Dv SIGXFSZ Ta "terminate process" Ta "file size limit exceeded (see"
+.Xr setrlimit 2 )
+.It 26 Ta Dv SIGVTALRM Ta "terminate process" Ta "virtual time alarm (see"
+.Xr setitimer 2 )
+.It 27 Ta Dv SIGPROF Ta "terminate process" Ta "profiling timer alarm (see"
+.Xr setitimer 2 )
+.It 28 Ta Dv SIGWINCH Ta "discard signal" Ta "Window size change"
+.It 29 Ta Dv SIGINFO Ta "discard signal" Ta "status request from keyboard"
+.It 30 Ta Dv SIGUSR1 Ta "terminate process" Ta "User defined signal 1"
+.It 31 Ta Dv SIGUSR2 Ta "terminate process" Ta "User defined signal 2"
+.It 32 Ta Dv SIGTHR Ta "terminate process" Ta "thread interrupt"
+.El
+.Pp
+The
+.Fa sig
+argument specifies which signal was received.
+The
+.Fa func
+procedure allows a user to choose the action upon receipt of a signal.
+To set the default action of the signal to occur as listed above,
+.Fa func
+should be
+.Dv SIG_DFL .
+A
+.Dv SIG_DFL
+resets the default action.
+To ignore the signal
+.Fa func
+should be
+.Dv SIG_IGN .
+This will cause subsequent instances of the signal to be ignored
+and pending instances to be discarded.
+If
+.Dv SIG_IGN
+is not used,
+further occurrences of the signal are
+automatically blocked and
+.Fa func
+is called.
+.Pp
+The handled signal is unblocked when the
+function returns and
+the process continues from where it left off when the signal occurred.
+.Bf -symbolic
+Unlike previous signal facilities, the handler
+func() remains installed after a signal has been delivered.
+.Ef
+.Pp
+For some system calls, if a signal is caught while the call is
+executing and the call is prematurely terminated,
+the call is automatically restarted.
+Any handler installed with
+.Xr signal 3
+will have the
+.Dv SA_RESTART
+flag set, meaning that any restartable system call will not return on
+receipt of a signal.
+The affected system calls include
+.Xr read 2 ,
+.Xr write 2 ,
+.Xr sendto 2 ,
+.Xr recvfrom 2 ,
+.Xr sendmsg 2
+and
+.Xr recvmsg 2
+on a communications channel or a low speed device
+and during a
+.Xr ioctl 2
+or
+.Xr wait 2 .
+However, calls that have already committed are not restarted,
+but instead return a partial success (for example, a short read count).
+These semantics could be changed with
+.Xr siginterrupt 3 .
+.Pp
+When a process which has installed signal handlers forks,
+the child process inherits the signals.
+All caught signals may be reset to their default action by a call
+to the
+.Xr execve 2
+function;
+ignored signals remain ignored.
+.Pp
+If a process explicitly specifies
+.Dv SIG_IGN
+as the action for the signal
+.Dv SIGCHLD ,
+the system will not create zombie processes when children
+of the calling process exit.
+As a consequence, the system will discard the exit status
+from the child processes.
+If the calling process subsequently issues a call to
+.Xr wait 2
+or equivalent, it will block until all of the calling process's
+children terminate, and then return a value of \-1 with
+.Va errno
+set to
+.Er ECHILD .
+.Pp
+See
+.Xr sigaction 2
+for a list of functions
+that are considered safe for use in signal handlers.
+.Sh RETURN VALUES
+The previous action is returned on a successful call.
+Otherwise, SIG_ERR is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+The
+.Fn signal
+function
+will fail and no action will take place if one of the
+following occur:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa sig
+argument
+is not a valid signal number.
+.It Bq Er EINVAL
+An attempt is made to ignore or supply a handler for
+.Dv SIGKILL
+or
+.Dv SIGSTOP .
+.El
+.Sh SEE ALSO
+.Xr kill 1 ,
+.Xr kill 2 ,
+.Xr ptrace 2 ,
+.Xr sigaction 2 ,
+.Xr sigaltstack 2 ,
+.Xr sigprocmask 2 ,
+.Xr sigsuspend 2 ,
+.Xr wait 2 ,
+.Xr fpsetmask 3 ,
+.Xr setjmp 3 ,
+.Xr siginterrupt 3 ,
+.Xr tty 4
+.Sh HISTORY
+The
+.Nm
+facility appeared in
+.Bx 4.0 .
+The option to avoid the creation of child zombies through ignoring
+.Dv SIGCHLD
+appeared in
+.Fx 5.0 .
diff --git a/lib/libc/gen/signal.c b/lib/libc/gen/signal.c
new file mode 100644
index 0000000..c93633e
--- /dev/null
+++ b/lib/libc/gen/signal.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1985, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)signal.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Almost backwards compatible signal.
+ */
+#include "namespace.h"
+#include <signal.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+sigset_t _sigintr; /* shared with siginterrupt */
+
+sig_t
+signal(s, a)
+ int s;
+ sig_t a;
+{
+ struct sigaction sa, osa;
+
+ sa.sa_handler = a;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+ if (!sigismember(&_sigintr, s))
+ sa.sa_flags |= SA_RESTART;
+ if (_sigaction(s, &sa, &osa) < 0)
+ return (SIG_ERR);
+ return (osa.sa_handler);
+}
diff --git a/lib/libc/gen/sigsetops.3 b/lib/libc/gen/sigsetops.3
new file mode 100644
index 0000000..88affad
--- /dev/null
+++ b/lib/libc/gen/sigsetops.3
@@ -0,0 +1,117 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)sigsetops.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd December 16, 2004
+.Dt SIGSETOPS 3
+.Os
+.Sh NAME
+.Nm sigemptyset ,
+.Nm sigfillset ,
+.Nm sigaddset ,
+.Nm sigdelset ,
+.Nm sigismember
+.Nd manipulate signal sets
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In signal.h
+.Ft int
+.Fn sigemptyset "sigset_t *set"
+.Ft int
+.Fn sigfillset "sigset_t *set"
+.Ft int
+.Fn sigaddset "sigset_t *set" "int signo"
+.Ft int
+.Fn sigdelset "sigset_t *set" "int signo"
+.Ft int
+.Fn sigismember "const sigset_t *set" "int signo"
+.Sh DESCRIPTION
+These functions manipulate signal sets stored in a
+.Fa sigset_t .
+Either
+.Fn sigemptyset
+or
+.Fn sigfillset
+must be called for every object of type
+.Fa sigset_t
+before any other use of the object.
+.Pp
+The
+.Fn sigemptyset
+function initializes a signal set to be empty.
+.Pp
+The
+.Fn sigfillset
+function initializes a signal set to contain all signals.
+.Pp
+The
+.Fn sigaddset
+function adds the specified signal
+.Fa signo
+to the signal set.
+.Pp
+The
+.Fn sigdelset
+function deletes the specified signal
+.Fa signo
+from the signal set.
+.Pp
+The
+.Fn sigismember
+function returns whether a specified signal
+.Fa signo
+is contained in the signal set.
+.Sh RETURN VALUES
+The
+.Fn sigismember
+function returns 1
+if the signal is a member of the set,
+0 otherwise.
+The other functions return 0 upon success.
+A \-1 return value
+indicates an error occurred and the global variable
+.Va errno
+is set to indicate the reason.
+.Sh ERRORS
+These functions could fail if one of the following occurs:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+.Fa signo
+has an invalid value.
+.El
+.Sh SEE ALSO
+.Xr kill 2 ,
+.Xr sigaction 2 ,
+.Xr sigpending 2 ,
+.Xr sigprocmask 2 ,
+.Xr sigsuspend 2
+.Sh STANDARDS
+These functions are defined by
+.St -p1003.1-88 .
diff --git a/lib/libc/gen/sigsetops.c b/lib/libc/gen/sigsetops.c
new file mode 100644
index 0000000..cf7e688
--- /dev/null
+++ b/lib/libc/gen/sigsetops.c
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)sigsetops.c 8.1 (Berkeley) 6/4/93
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)sigsetops.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <signal.h>
+
+int
+sigaddset(set, signo)
+ sigset_t *set;
+ int signo;
+{
+
+ if (signo <= 0 || signo > _SIG_MAXSIG) {
+ errno = EINVAL;
+ return (-1);
+ }
+ set->__bits[_SIG_WORD(signo)] |= _SIG_BIT(signo);
+ return (0);
+}
+
+int
+sigdelset(set, signo)
+ sigset_t *set;
+ int signo;
+{
+
+ if (signo <= 0 || signo > _SIG_MAXSIG) {
+ errno = EINVAL;
+ return (-1);
+ }
+ set->__bits[_SIG_WORD(signo)] &= ~_SIG_BIT(signo);
+ return (0);
+}
+
+int
+sigemptyset(set)
+ sigset_t *set;
+{
+ int i;
+
+ for (i = 0; i < _SIG_WORDS; i++)
+ set->__bits[i] = 0;
+ return (0);
+}
+
+int
+sigfillset(set)
+ sigset_t *set;
+{
+ int i;
+
+ for (i = 0; i < _SIG_WORDS; i++)
+ set->__bits[i] = ~0U;
+ return (0);
+}
+
+int
+sigismember(set, signo)
+ const sigset_t *set;
+ int signo;
+{
+
+ if (signo <= 0 || signo > _SIG_MAXSIG) {
+ errno = EINVAL;
+ return (-1);
+ }
+ return ((set->__bits[_SIG_WORD(signo)] & _SIG_BIT(signo)) ? 1 : 0);
+}
diff --git a/lib/libc/gen/sleep.3 b/lib/libc/gen/sleep.3
new file mode 100644
index 0000000..ecfa237
--- /dev/null
+++ b/lib/libc/gen/sleep.3
@@ -0,0 +1,83 @@
+.\" Copyright (c) 1986, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)sleep.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd February 13, 1998
+.Dt SLEEP 3
+.Os
+.Sh NAME
+.Nm sleep
+.Nd suspend process execution for an interval measured in seconds
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft unsigned int
+.Fn sleep "unsigned int seconds"
+.Sh DESCRIPTION
+The
+.Fn sleep
+function suspends execution of the calling process until either
+.Fa seconds
+seconds have elapsed or a signal is delivered to the process and its
+action is to invoke a signal-catching function or to terminate the
+process.
+System activity may lengthen the sleep by an indeterminate amount.
+.Pp
+This function is implemented using
+.Xr nanosleep 2
+by pausing for
+.Fa seconds
+seconds or until a signal occurs.
+Consequently, in this implementation,
+sleeping has no effect on the state of process timers,
+and there is no special handling for SIGALRM.
+.Sh RETURN VALUES
+If the
+.Fn sleep
+function returns because the requested time has elapsed, the value
+returned will be zero.
+If the
+.Fn sleep
+function returns due to the delivery of a signal, the value returned
+will be the unslept amount (the requested time minus the time actually
+slept) in seconds.
+.Sh SEE ALSO
+.Xr nanosleep 2 ,
+.Xr usleep 3
+.Sh STANDARDS
+The
+.Fn sleep
+function conforms to
+.St -p1003.1-90 .
+.Sh HISTORY
+A
+.Fn sleep
+function appeared in
+.At v7 .
diff --git a/lib/libc/gen/sleep.c b/lib/libc/gen/sleep.c
new file mode 100644
index 0000000..b807c2d
--- /dev/null
+++ b/lib/libc/gen/sleep.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)sleep.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <limits.h>
+#include <time.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+unsigned int
+__sleep(unsigned int seconds)
+{
+ struct timespec time_to_sleep;
+ struct timespec time_remaining;
+
+ /*
+ * Avoid overflow when `seconds' is huge. This assumes that
+ * the maximum value for a time_t is >= INT_MAX.
+ */
+ if (seconds > INT_MAX)
+ return (seconds - INT_MAX + __sleep(INT_MAX));
+
+ time_to_sleep.tv_sec = seconds;
+ time_to_sleep.tv_nsec = 0;
+ if (_nanosleep(&time_to_sleep, &time_remaining) != -1)
+ return (0);
+ if (errno != EINTR)
+ return (seconds); /* best guess */
+ return (time_remaining.tv_sec +
+ (time_remaining.tv_nsec != 0)); /* round up */
+}
+
+__weak_reference(__sleep, sleep);
+__weak_reference(__sleep, _sleep);
diff --git a/lib/libc/gen/srand48.c b/lib/libc/gen/srand48.c
new file mode 100644
index 0000000..fd369a0
--- /dev/null
+++ b/lib/libc/gen/srand48.c
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 1993 Martin Birgmeier
+ * All rights reserved.
+ *
+ * You may redistribute unmodified or modified versions of this source
+ * code provided that the above copyright notice and this and the
+ * following conditions are retained.
+ *
+ * This software is provided ``as is'', and comes with no warranties
+ * of any kind. I shall in no event be liable for anything that happens
+ * to anyone/anything when using this software.
+ */
+
+#include "rand48.h"
+
+extern unsigned short _rand48_seed[3];
+extern unsigned short _rand48_mult[3];
+extern unsigned short _rand48_add;
+
+void
+srand48(long seed)
+{
+ _rand48_seed[0] = RAND48_SEED_0;
+ _rand48_seed[1] = (unsigned short) seed;
+ _rand48_seed[2] = (unsigned short) (seed >> 16);
+ _rand48_mult[0] = RAND48_MULT_0;
+ _rand48_mult[1] = RAND48_MULT_1;
+ _rand48_mult[2] = RAND48_MULT_2;
+ _rand48_add = RAND48_ADD;
+}
diff --git a/lib/libc/gen/statvfs.3 b/lib/libc/gen/statvfs.3
new file mode 100644
index 0000000..f9c7430
--- /dev/null
+++ b/lib/libc/gen/statvfs.3
@@ -0,0 +1,187 @@
+.\"
+.\" Copyright 2002 Massachusetts Institute of Technology
+.\"
+.\" Permission to use, copy, modify, and distribute this software and
+.\" its documentation for any purpose and without fee is hereby
+.\" granted, provided that both the above copyright notice and this
+.\" permission notice appear in all copies, that both the above
+.\" copyright notice and this permission notice appear in all
+.\" supporting documentation, and that the name of M.I.T. not be used
+.\" in advertising or publicity pertaining to distribution of the
+.\" software without specific, written prior permission. M.I.T. makes
+.\" no representations about the suitability of this software for any
+.\" purpose. It is provided "as is" without express or implied
+.\" warranty.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+.\" ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+.\" SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 13, 2002
+.Dt STATVFS 3
+.Os
+.Sh NAME
+.Nm statvfs ,
+.Nm fstatvfs
+.Nd retrieve file system information
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/statvfs.h
+.Ft int
+.Fn statvfs "const char * restrict path" "struct statvfs * restrict buf"
+.Ft int
+.Fn fstatvfs "int fd" "struct statvfs *buf"
+.Sh DESCRIPTION
+The
+.Fn statvfs
+and
+.Fn fstatvfs
+functions fill the structure pointed to by
+.Fa buf
+with garbage.
+This garbage will occasionally bear resemblance to file system
+statistics, but portable applications must not depend on this.
+Applications must pass a pathname or file descriptor which refers to a
+file on the file system in which they are interested.
+.Pp
+The
+.Vt statvfs
+structure contains the following members:
+.Bl -tag -offset indent -width ".Va f_namemax"
+.It Va f_namemax
+The maximum length in bytes of a file name on this file system.
+Applications should use
+.Xr pathconf 2
+instead.
+.It Va f_fsid
+Not meaningful in this implementation.
+.It Va f_frsize
+The size in bytes of the minimum unit of allocation on this
+file system.
+(This corresponds to the
+.Va f_bsize
+member of
+.Vt "struct statfs" . )
+.It Va f_bsize
+The preferred length of I/O requests for files on this file system.
+(Corresponds to the
+.Va f_iosize
+member of
+.Vt "struct statfs" . )
+.It Va f_flag
+Flags describing mount options for this file system; see below.
+.El
+.Pp
+In addition, there are three members of type
+.Vt fsfilcnt_t ,
+which represent counts of file serial numbers
+.Em ( i.e. ,
+inodes); these are named
+.Va f_files , f_favail ,
+and
+.Va f_ffree ,
+and represent the number of file serial numbers which exist in total,
+are available to unprivileged processes, and are available to
+privileged processes, respectively.
+Likewise, the members
+.Va f_blocks , f_bavail ,
+and
+.Va f_bfree
+(all of type
+.Vt fsblkcnt_t )
+represent the respective allocation-block counts.
+.Pp
+There are two flags defined for the
+.Va f_flag
+member:
+.Bl -tag -offset indent -width ".Dv ST_NOSUID"
+.It Dv ST_RDONLY
+The file system is mounted read-only.
+.It Dv ST_NOSUID
+The semantics of the
+.Dv S_ISUID
+and
+.Dv S_ISGID
+file mode bits
+are not supported by, or are disabled on, this file system.
+.El
+.Sh IMPLEMENTATION NOTES
+The
+.Fn statvfs
+and
+.Fn fstatvfs
+functions are implemented as wrappers around the
+.Fn statfs
+and
+.Fn fstatfs
+functions, respectively.
+Not all the information provided by those functions is made available
+through this interface.
+.Sh RETURN VALUES
+.Rv -std statvfs fstatvfs
+.Sh ERRORS
+The
+.Fn statvfs
+and
+.Fn fstatvfs
+functions may fail for any of the reasons documented for
+.Xr statfs 2
+or
+.Xr fstatfs 2
+and
+.Xr pathconf 2
+or
+.Xr fpathconf 2 ,
+respectively.
+In addition,
+.Fn statvfs
+and
+.Fn fstatvfs
+functions may also fail for the following reason:
+.Bl -tag -width Er
+.It Bq Er EOVERFLOW
+One or more of the file system statistics has a value which cannot be
+represented by the data types used in
+.Vt "struct statvfs" .
+.El
+.Sh SEE ALSO
+.Xr pathconf 2 ,
+.Xr statfs 2
+.Sh STANDARDS
+The
+.Fn statvfs
+and
+.Fn fstatvfs
+functions conform to
+.St -p1003.1-2001 .
+As standardized, portable applications cannot depend on these functions
+returning any valid information at all.
+This implementation attempts to provide as much useful information as
+is provided by the underlying file system, subject to the limitations
+of the specified data types.
+.Sh HISTORY
+The
+.Fn statvfs
+and
+.Fn fstatvfs
+functions first appeared in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn statvfs
+and
+.Fn fstatvfs
+functions and this manual page were written by
+.An Garrett Wollman Aq wollman@FreeBSD.org .
diff --git a/lib/libc/gen/statvfs.c b/lib/libc/gen/statvfs.c
new file mode 100644
index 0000000..fe9462b
--- /dev/null
+++ b/lib/libc/gen/statvfs.c
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2002 Massachusetts Institute of Technology
+ *
+ * Permission to use, copy, modify, and distribute this software and
+ * its documentation for any purpose and without fee is hereby
+ * granted, provided that both the above copyright notice and this
+ * permission notice appear in all copies, that both the above
+ * copyright notice and this permission notice appear in all
+ * supporting documentation, and that the name of M.I.T. not be used
+ * in advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission. M.I.T. makes
+ * no representations about the suitability of this software for any
+ * purpose. It is provided "as is" without express or implied
+ * warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS
+ * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT
+ * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/statvfs.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+static int sfs2svfs(const struct statfs *from, struct statvfs *to);
+
+int
+fstatvfs(int fd, struct statvfs *result)
+{
+ struct statfs sfs;
+ int rv;
+ long pcval;
+
+ rv = _fstatfs(fd, &sfs);
+ if (rv != 0)
+ return (rv);
+
+ rv = sfs2svfs(&sfs, result);
+ if (rv != 0)
+ return (rv);
+
+ /*
+ * Whether pathconf's -1 return means error or unlimited does not
+ * make any difference in this best-effort implementation.
+ */
+ pcval = _fpathconf(fd, _PC_NAME_MAX);
+ if (pcval == -1)
+ result->f_namemax = ~0UL;
+ else
+ result->f_namemax = (unsigned long)pcval;
+ return (0);
+}
+
+int
+statvfs(const char * __restrict path, struct statvfs * __restrict result)
+{
+ struct statfs sfs;
+ int rv;
+ long pcval;
+
+ rv = statfs(path, &sfs);
+ if (rv != 0)
+ return (rv);
+
+ sfs2svfs(&sfs, result);
+
+ /*
+ * Whether pathconf's -1 return means error or unlimited does not
+ * make any difference in this best-effort implementation.
+ */
+ pcval = pathconf(path, _PC_NAME_MAX);
+ if (pcval == -1)
+ result->f_namemax = ~0UL;
+ else
+ result->f_namemax = (unsigned long)pcval;
+ return (0);
+}
+
+static int
+sfs2svfs(const struct statfs *from, struct statvfs *to)
+{
+ static const struct statvfs zvfs;
+
+ *to = zvfs;
+
+ if (from->f_flags & MNT_RDONLY)
+ to->f_flag |= ST_RDONLY;
+ if (from->f_flags & MNT_NOSUID)
+ to->f_flag |= ST_NOSUID;
+
+ /* XXX should we clamp negative values? */
+#define COPY(field) \
+ do { \
+ to->field = from->field; \
+ if (from->field != to->field) { \
+ errno = EOVERFLOW; \
+ return (-1); \
+ } \
+ } while(0)
+
+ COPY(f_bavail);
+ COPY(f_bfree);
+ COPY(f_blocks);
+ COPY(f_ffree);
+ COPY(f_files);
+ to->f_bsize = from->f_iosize;
+ to->f_frsize = from->f_bsize;
+ to->f_favail = to->f_ffree;
+ return (0);
+}
+
+#ifdef MAIN
+#include <err.h>
+#include <stdint.h>
+#include <stdio.h>
+
+int
+main(int argc, char **argv)
+{
+ struct statvfs buf;
+
+ if (statvfs(argv[1], &buf) < 0)
+ err(1, "statvfs");
+
+#define SHOW(field) \
+ printf(#field ": %ju\n", (uintmax_t)buf.field)
+
+ SHOW(f_bavail);
+ SHOW(f_bfree);
+ SHOW(f_blocks);
+ SHOW(f_favail);
+ SHOW(f_ffree);
+ SHOW(f_files);
+ SHOW(f_bsize);
+ SHOW(f_frsize);
+ SHOW(f_namemax);
+ printf("f_flag: %lx\n", (unsigned long)buf.f_flag);
+
+ return 0;
+}
+
+#endif /* MAIN */
diff --git a/lib/libc/gen/stringlist.3 b/lib/libc/gen/stringlist.3
new file mode 100644
index 0000000..82465b6
--- /dev/null
+++ b/lib/libc/gen/stringlist.3
@@ -0,0 +1,127 @@
+.\" $NetBSD: stringlist.3,v 1.5 1999/03/22 19:44:46 garbled Exp $
+.\"
+.\" Copyright (c) 1997, 1999 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This file was contributed to The NetBSD Foundation by Luke Mewburn.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE
+.\" LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 28, 1999
+.Dt STRINGLIST 3
+.Os
+.Sh NAME
+.Nm stringlist ,
+.Nm sl_init ,
+.Nm sl_add ,
+.Nm sl_free ,
+.Nm sl_find
+.Nd stringlist manipulation functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stringlist.h
+.Ft StringList *
+.Fn sl_init
+.Ft int
+.Fn sl_add "StringList *sl" "char *item"
+.Ft void
+.Fn sl_free "StringList *sl" "int freeall"
+.Ft char *
+.Fn sl_find "StringList *sl" "char *item"
+.Sh DESCRIPTION
+The
+.Nm
+functions manipulate stringlists, which are lists of
+strings that extend automatically if necessary.
+.Pp
+The
+.Vt StringList
+structure has the following definition:
+.Bd -literal -offset indent
+typedef struct _stringlist {
+ char **sl_str;
+ size_t sl_max;
+ size_t sl_cur;
+} StringList;
+.Ed
+.Bl -tag -width "sl_str" -offset indent
+.It Va sl_str
+a pointer to the base of the array containing the list.
+.It Va sl_max
+the size of
+.Va sl_str .
+.It Va sl_cur
+the offset in
+.Va sl_str
+of the current element.
+.El
+.Pp
+The following stringlist manipulation functions are available:
+.Bl -tag -width "sl_init()"
+.It Fn sl_init
+Create a stringlist.
+Returns a pointer to a
+.Vt StringList ,
+or
+.Dv NULL
+in case of failure.
+.It Fn sl_free
+Releases memory occupied by
+.Fa sl
+and the
+.Fa sl->sl_str
+array.
+If
+.Fa freeall
+is non-zero, then each of the items within
+.Fa sl->sl_str
+is released as well.
+.It Fn sl_add
+Add
+.Fa item
+to
+.Fa sl->sl_str
+at
+.Fa sl->sl_cur ,
+extending the size of
+.Fa sl->sl_str .
+Returns zero upon success, \-1 upon failure.
+.It Fn sl_find
+Find
+.Fa item
+in
+.Fa sl ,
+returning NULL if it is not found.
+.El
+.Sh SEE ALSO
+.Xr free 3 ,
+.Xr malloc 3
+.Sh HISTORY
+The
+.Nm
+functions appeared in
+.Fx 2.2.6
+and
+.Nx 1.3 .
diff --git a/lib/libc/gen/stringlist.c b/lib/libc/gen/stringlist.c
new file mode 100644
index 0000000..e0db3b6
--- /dev/null
+++ b/lib/libc/gen/stringlist.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1994 Christos Zoulas
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$NetBSD: stringlist.c,v 1.2 1997/01/17 07:26:20 lukem Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <string.h>
+#include <err.h>
+#include <stdlib.h>
+#include <stringlist.h>
+#include "un-namespace.h"
+
+#define _SL_CHUNKSIZE 20
+
+/*
+ * sl_init(): Initialize a string list
+ */
+StringList *
+sl_init()
+{
+ StringList *sl;
+
+ sl = malloc(sizeof(StringList));
+ if (sl == NULL)
+ _err(1, "stringlist: %m");
+
+ sl->sl_cur = 0;
+ sl->sl_max = _SL_CHUNKSIZE;
+ sl->sl_str = malloc(sl->sl_max * sizeof(char *));
+ if (sl->sl_str == NULL)
+ _err(1, "stringlist: %m");
+ return sl;
+}
+
+
+/*
+ * sl_add(): Add an item to the string list
+ */
+int
+sl_add(sl, name)
+ StringList *sl;
+ char *name;
+{
+ if (sl->sl_cur == sl->sl_max - 1) {
+ sl->sl_max += _SL_CHUNKSIZE;
+ sl->sl_str = reallocf(sl->sl_str, sl->sl_max * sizeof(char *));
+ if (sl->sl_str == NULL)
+ return (-1);
+ }
+ sl->sl_str[sl->sl_cur++] = name;
+ return (0);
+}
+
+
+/*
+ * sl_free(): Free a stringlist
+ */
+void
+sl_free(sl, all)
+ StringList *sl;
+ int all;
+{
+ size_t i;
+
+ if (sl == NULL)
+ return;
+ if (sl->sl_str) {
+ if (all)
+ for (i = 0; i < sl->sl_cur; i++)
+ free(sl->sl_str[i]);
+ free(sl->sl_str);
+ }
+ free(sl);
+}
+
+
+/*
+ * sl_find(): Find a name in the string list
+ */
+char *
+sl_find(sl, name)
+ StringList *sl;
+ char *name;
+{
+ size_t i;
+
+ for (i = 0; i < sl->sl_cur; i++)
+ if (strcmp(sl->sl_str[i], name) == 0)
+ return sl->sl_str[i];
+
+ return NULL;
+}
diff --git a/lib/libc/gen/strtofflags.3 b/lib/libc/gen/strtofflags.3
new file mode 100644
index 0000000..38c2ff5
--- /dev/null
+++ b/lib/libc/gen/strtofflags.3
@@ -0,0 +1,95 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)setmode.3 8.2 (Berkeley) 4/28/95
+.\" $FreeBSD$
+.\"
+.Dd January 1, 2000
+.Dt STRTOFFLAGS 3
+.Os
+.Sh NAME
+.Nm fflagstostr ,
+.Nm strtofflags
+.Nd convert between file flag bits and their string names
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft char *
+.Fn fflagstostr "u_long flags"
+.Ft int
+.Fn strtofflags "char **stringp" "u_long *setp" "u_long *clrp"
+.Sh DESCRIPTION
+The
+.Fn fflagstostr
+function returns a comma separated string of the file flags represented by
+.Fa flags .
+If no flags are set a zero length string is returned.
+.Pp
+If memory cannot be allocated for the return value,
+.Fn fflagstostr
+returns
+.Dv NULL .
+.Pp
+The value returned from
+.Fn fflagstostr
+is obtained from
+.Fn malloc
+and should be returned to the system with
+.Fn free
+when the program is done with it.
+.Pp
+The
+.Fn strtofflags
+function takes a string of file flags, as described in
+.Xr chflags 1 ,
+parses it, and returns the 'set' flags and 'clear' flags
+such as would be given as arguments to
+.Xr chflags 2 .
+On success
+.Fn strtofflags
+returns 0, otherwise it returns non-zero and
+.Fa stringp
+is left pointing to the offending token.
+.Sh ERRORS
+The
+.Fn fflagstostr
+function
+may fail and set errno for any of the errors specified for the library
+routine
+.Xr malloc 3 .
+.Sh SEE ALSO
+.Xr chflags 1 ,
+.Xr chflags 2 ,
+.Xr malloc 3
+.Sh HISTORY
+The
+.Fn fflagstostr
+and
+.Fn strtofflags
+functions first appeared in
+.Fx 4.0 .
diff --git a/lib/libc/gen/strtofflags.c b/lib/libc/gen/strtofflags.c
new file mode 100644
index 0000000..1edaa5a
--- /dev/null
+++ b/lib/libc/gen/strtofflags.c
@@ -0,0 +1,156 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)stat_flags.c 8.1 (Berkeley) 5/31/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define longestflaglen 12
+static struct {
+ char name[longestflaglen + 1];
+ char invert;
+ u_long flag;
+} const mapping[] = {
+ /* shorter names per flag first, all prefixed by "no" */
+ { "nosappnd", 0, SF_APPEND },
+ { "nosappend", 0, SF_APPEND },
+ { "noarch", 0, SF_ARCHIVED },
+ { "noarchived", 0, SF_ARCHIVED },
+ { "noschg", 0, SF_IMMUTABLE },
+ { "noschange", 0, SF_IMMUTABLE },
+ { "nosimmutable", 0, SF_IMMUTABLE },
+ { "nosunlnk", 0, SF_NOUNLINK },
+ { "nosunlink", 0, SF_NOUNLINK },
+#ifdef SF_SNAPSHOT
+ { "nosnapshot", 0, SF_SNAPSHOT },
+#endif
+ { "nouappnd", 0, UF_APPEND },
+ { "nouappend", 0, UF_APPEND },
+ { "nouchg", 0, UF_IMMUTABLE },
+ { "nouchange", 0, UF_IMMUTABLE },
+ { "nouimmutable", 0, UF_IMMUTABLE },
+ { "nodump", 1, UF_NODUMP },
+ { "noopaque", 0, UF_OPAQUE },
+ { "nouunlnk", 0, UF_NOUNLINK },
+ { "nouunlink", 0, UF_NOUNLINK }
+};
+#define nmappings (sizeof(mapping) / sizeof(mapping[0]))
+
+/*
+ * fflagstostr --
+ * Convert file flags to a comma-separated string. If no flags
+ * are set, return the empty string.
+ */
+char *
+fflagstostr(flags)
+ u_long flags;
+{
+ char *string;
+ const char *sp;
+ char *dp;
+ u_long setflags;
+ int i;
+
+ if ((string = (char *)malloc(nmappings * (longestflaglen + 1))) == NULL)
+ return (NULL);
+
+ setflags = flags;
+ dp = string;
+ for (i = 0; i < nmappings; i++) {
+ if (setflags & mapping[i].flag) {
+ if (dp > string)
+ *dp++ = ',';
+ for (sp = mapping[i].invert ? mapping[i].name :
+ mapping[i].name + 2; *sp; *dp++ = *sp++) ;
+ setflags &= ~mapping[i].flag;
+ }
+ }
+ *dp = '\0';
+ return (string);
+}
+
+/*
+ * strtofflags --
+ * Take string of arguments and return file flags. Return 0 on
+ * success, 1 on failure. On failure, stringp is set to point
+ * to the offending token.
+ */
+int
+strtofflags(stringp, setp, clrp)
+ char **stringp;
+ u_long *setp, *clrp;
+{
+ char *string, *p;
+ int i;
+
+ if (setp)
+ *setp = 0;
+ if (clrp)
+ *clrp = 0;
+ string = *stringp;
+ while ((p = strsep(&string, "\t ,")) != NULL) {
+ *stringp = p;
+ if (*p == '\0')
+ continue;
+ for (i = 0; i < nmappings; i++) {
+ if (strcmp(p, mapping[i].name + 2) == 0) {
+ if (mapping[i].invert) {
+ if (clrp)
+ *clrp |= mapping[i].flag;
+ } else {
+ if (setp)
+ *setp |= mapping[i].flag;
+ }
+ break;
+ } else if (strcmp(p, mapping[i].name) == 0) {
+ if (mapping[i].invert) {
+ if (setp)
+ *setp |= mapping[i].flag;
+ } else {
+ if (clrp)
+ *clrp |= mapping[i].flag;
+ }
+ break;
+ }
+ }
+ if (i == nmappings)
+ return 1;
+ }
+ return 0;
+}
diff --git a/lib/libc/gen/swapcontext.c b/lib/libc/gen/swapcontext.c
new file mode 100644
index 0000000..c34cb23
--- /dev/null
+++ b/lib/libc/gen/swapcontext.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2001 Daniel M. Eischen <deischen@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/signal.h>
+#include <sys/ucontext.h>
+
+#include <errno.h>
+#include <stddef.h>
+
+__weak_reference(__swapcontext, swapcontext);
+
+int
+__swapcontext(ucontext_t *oucp, const ucontext_t *ucp)
+{
+ int ret;
+
+ if ((oucp == NULL) || (ucp == NULL)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ oucp->uc_flags &= ~UCF_SWAPPED;
+ ret = getcontext(oucp);
+ if ((ret == 0) && !(oucp->uc_flags & UCF_SWAPPED)) {
+ oucp->uc_flags |= UCF_SWAPPED;
+ ret = setcontext(ucp);
+ }
+ return (ret);
+}
diff --git a/lib/libc/gen/sysconf.3 b/lib/libc/gen/sysconf.3
new file mode 100644
index 0000000..4af6f82
--- /dev/null
+++ b/lib/libc/gen/sysconf.3
@@ -0,0 +1,276 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)sysconf.3 8.3 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd February 13, 2011
+.Dt SYSCONF 3
+.Os
+.Sh NAME
+.Nm sysconf
+.Nd get configurable system variables
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft long
+.Fn sysconf "int name"
+.Sh DESCRIPTION
+This interface is defined by
+.St -p1003.1-88 .
+A far more complete interface is available using
+.Xr sysctl 3 .
+.Pp
+The
+.Fn sysconf
+function provides a method for applications to determine the current
+value of a configurable system limit or option variable.
+The
+.Fa name
+argument specifies the system variable to be queried.
+Symbolic constants for each name value are found in the include file
+.In unistd.h .
+Shell programmers who need access to these parameters should use the
+.Xr getconf 1
+utility.
+.Pp
+The available values are as follows:
+.Bl -tag -width 6n
+.It Li _SC_ARG_MAX
+The maximum bytes of argument to
+.Xr execve 2 .
+.It Li _SC_CHILD_MAX
+The maximum number of simultaneous processes per user id.
+.It Li _SC_CLK_TCK
+The frequency of the statistics clock in ticks per second.
+.It Li _SC_IOV_MAX
+The maximum number of elements in the I/O vector used by
+.Xr readv 2 ,
+.Xr writev 2 ,
+.Xr recvmsg 2 ,
+and
+.Xr sendmsg 2 .
+.It Li _SC_NGROUPS_MAX
+The maximum number of supplemental groups.
+.It Li _SC_NPROCESSORS_CONF
+The number of processors configured.
+.It Li _SC_NPROCESSORS_ONLN
+The number of processors currently online.
+.It Li _SC_OPEN_MAX
+The maximum number of open files per user id.
+.It Li _SC_PAGESIZE
+The size of a system page in bytes.
+.It Li _SC_PAGE_SIZE
+Equivalent to
+.Li _SC_PAGESIZE .
+.It Li _SC_STREAM_MAX
+The minimum maximum number of streams that a process may have open
+at any one time.
+.It Li _SC_TZNAME_MAX
+The minimum maximum number of types supported for the name of a
+timezone.
+.It Li _SC_JOB_CONTROL
+Return 1 if job control is available on this system, otherwise \-1.
+.It Li _SC_SAVED_IDS
+Returns 1 if saved set-group and saved set-user ID is available,
+otherwise \-1.
+.It Li _SC_VERSION
+The version of
+.St -p1003.1
+with which the system
+attempts to comply.
+.It Li _SC_BC_BASE_MAX
+The maximum ibase/obase values in the
+.Xr bc 1
+utility.
+.It Li _SC_BC_DIM_MAX
+The maximum array size in the
+.Xr bc 1
+utility.
+.It Li _SC_BC_SCALE_MAX
+The maximum scale value in the
+.Xr bc 1
+utility.
+.It Li _SC_BC_STRING_MAX
+The maximum string length in the
+.Xr bc 1
+utility.
+.It Li _SC_COLL_WEIGHTS_MAX
+The maximum number of weights that can be assigned to any entry of
+the LC_COLLATE order keyword in the locale definition file.
+.It Li _SC_EXPR_NEST_MAX
+The maximum number of expressions that can be nested within
+parenthesis by the
+.Xr expr 1
+utility.
+.It Li _SC_LINE_MAX
+The maximum length in bytes of a text-processing utility's input
+line.
+.It Li _SC_RE_DUP_MAX
+The maximum number of repeated occurrences of a regular expression
+permitted when using interval notation.
+.It Li _SC_2_VERSION
+The version of
+.St -p1003.2
+with which the system attempts to comply.
+.It Li _SC_2_C_BIND
+Return 1 if the system's C-language development facilities support the
+C-Language Bindings Option, otherwise \-1.
+.It Li _SC_2_C_DEV
+Return 1 if the system supports the C-Language Development Utilities Option,
+otherwise \-1.
+.It Li _SC_2_CHAR_TERM
+Return 1 if the system supports at least one terminal type capable of
+all operations described in
+.St -p1003.2 ,
+otherwise \-1.
+.It Li _SC_2_FORT_DEV
+Return 1 if the system supports the FORTRAN Development Utilities Option,
+otherwise \-1.
+.It Li _SC_2_FORT_RUN
+Return 1 if the system supports the FORTRAN Runtime Utilities Option,
+otherwise \-1.
+.It Li _SC_2_LOCALEDEF
+Return 1 if the system supports the creation of locales, otherwise \-1.
+.It Li _SC_2_SW_DEV
+Return 1 if the system supports the Software Development Utilities Option,
+otherwise \-1.
+.It Li _SC_2_UPE
+Return 1 if the system supports the User Portability Utilities Option,
+otherwise \-1.
+.It Li _SC_AIO_LISTIO_MAX
+Maximum number of I/O operations in a single list I/O call supported.
+.It Li _SC_AIO_MAX
+Maximum number of outstanding asynchronous I/O operations supported.
+.It Li _SC_AIO_PRIO_DELTA_MAX
+The maximum amount by which a process can decrease its asynchronous I/O
+priority level from its own scheduling priority.
+.It Li _SC_DELAYTIMER_MAX
+Maximum number of timer expiration overruns.
+.It Li _SC_MQ_OPEN_MAX
+The maximum number of open message queue descriptors a process may hold.
+.It Li _SC_RTSIG_MAX
+Maximum number of realtime signals reserved for application use.
+.It Li _SC_SEM_NSEMS_MAX
+Maximum number of semaphores that a process may have.
+.It Li _SC_SEM_VALUE_MAX
+The maximum value a semaphore may have.
+.It Li _SC_SIGQUEUE_MAX
+Maximum number of queued signals that a process may send and have pending at
+the receiver(s) at any time.
+.It Li _SC_TIMER_MAX
+Maximum number of timers per process supported.
+.It Li _SC_GETGR_R_SIZE_MAX
+Suggested initial value for the size of the group entry buffer.
+.It Li _SC_GETPW_R_SIZE_MAX
+Suggested initial value for the size of the password entry buffer.
+.It Li _SC_HOST_NAME_MAX
+Maximum length of a host name (not including the terminating null) as
+returned from the
+.Fn gethostname
+function.
+.It Li _SC_LOGIN_NAME_MAX
+Maximum length of a login name.
+.It Li _SC_THREAD_STACK_MIN
+Minimum size in bytes of thread stack storage.
+.It Li _SC_THREAD_THREADS_MAX
+Maximum number of threads that can be created per process.
+.It Li _SC_TTY_NAME_MAX
+Maximum length of terminal device name.
+.It Li _SC_SYMLOOP_MAX
+Maximum number of symbolic links that can be reliably traversed in the
+resolution of a pathname in the absence of a loop.
+.It Li _SC_ATEXIT_MAX
+Maximum number of functions that may be registered with
+.Fn atexit .
+.It Li _SC_XOPEN_VERSION
+An integer value greater than or equal to 4,
+indicating the version of the X/Open Portability Guide to which this
+system conforms.
+.It Li _SC_XOPEN_XCU_VERSION
+An integer value indicating the version of the XCU Specification to which
+this system conforms.
+.El
+.Pp
+These values also exist, but may not be standard:
+.Bl -tag -width 6n
+.It Li _SC_CPUSET_SIZE
+Size of the kernel cpuset.
+.It Li _SC_PHYS_PAGES
+The number of pages of physical memory.
+Note that it is possible that the product of this value and the value of
+.Li _SC_PAGESIZE
+will overflow a
+.Vt long
+in some configurations on a 32bit machine.
+.El
+.Sh RETURN VALUES
+If the call to
+.Fn sysconf
+is not successful, \-1 is returned and
+.Va errno
+is set appropriately.
+Otherwise, if the variable is associated with functionality that is not
+supported, \-1 is returned and
+.Va errno
+is not modified.
+Otherwise, the current variable value is returned.
+.Sh ERRORS
+The
+.Fn sysconf
+function may fail and set
+.Va errno
+for any of the errors specified for the library function
+.Xr sysctl 3 .
+In addition, the following error may be reported:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value of the
+.Fa name
+argument is invalid.
+.El
+.Sh SEE ALSO
+.Xr getconf 1 ,
+.Xr pathconf 2 ,
+.Xr confstr 3 ,
+.Xr sysctl 3
+.Sh STANDARDS
+Except for the fact that values returned by
+.Fn sysconf
+may change over the lifetime of the calling process,
+this function conforms to
+.St -p1003.1-88 .
+.Sh HISTORY
+The
+.Fn sysconf
+function first appeared in
+.Bx 4.4 .
+.Sh BUGS
+The value for _SC_STREAM_MAX is a minimum maximum, and required to be
+the same as ANSI C's FOPEN_MAX, so the returned value is a ridiculously
+small and misleading number.
diff --git a/lib/libc/gen/sysconf.c b/lib/libc/gen/sysconf.c
new file mode 100644
index 0000000..80ae626
--- /dev/null
+++ b/lib/libc/gen/sysconf.c
@@ -0,0 +1,617 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Sean Eric Fagan of Cygnus Support.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)sysconf.c 8.2 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/sysctl.h>
+#include <sys/resource.h>
+#include <sys/socket.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <pthread.h> /* we just need the limits */
+#include <time.h>
+#include <unistd.h>
+
+#include "../stdlib/atexit.h"
+#include "tzfile.h" /* from ../../../contrib/tzcode/stdtime */
+
+#define _PATH_ZONEINFO TZDIR /* from tzfile.h */
+
+/*
+ * sysconf --
+ * get configurable system variables.
+ *
+ * XXX
+ * POSIX 1003.1 (ISO/IEC 9945-1, 4.8.1.3) states that the variable values
+ * not change during the lifetime of the calling process. This would seem
+ * to require that any change to system limits kill all running processes.
+ * A workaround might be to cache the values when they are first retrieved
+ * and then simply return the cached value on subsequent calls. This is
+ * less useful than returning up-to-date values, however.
+ */
+long
+sysconf(name)
+ int name;
+{
+ struct rlimit rl;
+ size_t len;
+ int mib[2], sverrno, value;
+ long lvalue, defaultresult;
+ const char *path;
+
+ defaultresult = -1;
+
+ switch (name) {
+ case _SC_ARG_MAX:
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_ARGMAX;
+ break;
+ case _SC_CHILD_MAX:
+ if (getrlimit(RLIMIT_NPROC, &rl) != 0)
+ return (-1);
+ if (rl.rlim_cur == RLIM_INFINITY)
+ return (-1);
+ if (rl.rlim_cur > LONG_MAX) {
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ return ((long)rl.rlim_cur);
+ case _SC_CLK_TCK:
+ return (CLK_TCK);
+ case _SC_NGROUPS_MAX:
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_NGROUPS;
+ break;
+ case _SC_OPEN_MAX:
+ if (getrlimit(RLIMIT_NOFILE, &rl) != 0)
+ return (-1);
+ if (rl.rlim_cur == RLIM_INFINITY)
+ return (-1);
+ if (rl.rlim_cur > LONG_MAX) {
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ return ((long)rl.rlim_cur);
+ case _SC_STREAM_MAX:
+ if (getrlimit(RLIMIT_NOFILE, &rl) != 0)
+ return (-1);
+ if (rl.rlim_cur == RLIM_INFINITY)
+ return (-1);
+ if (rl.rlim_cur > LONG_MAX) {
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ /*
+ * struct __sFILE currently has a limitation that
+ * file descriptors must fit in a signed short.
+ * This doesn't precisely capture the letter of POSIX
+ * but approximates the spirit.
+ */
+ if (rl.rlim_cur > SHRT_MAX)
+ return (SHRT_MAX);
+
+ return ((long)rl.rlim_cur);
+ case _SC_JOB_CONTROL:
+ return (_POSIX_JOB_CONTROL);
+ case _SC_SAVED_IDS:
+ /* XXX - must be 1 */
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_SAVED_IDS;
+ goto yesno;
+ case _SC_VERSION:
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_POSIX1;
+ break;
+ case _SC_BC_BASE_MAX:
+ return (BC_BASE_MAX);
+ case _SC_BC_DIM_MAX:
+ return (BC_DIM_MAX);
+ case _SC_BC_SCALE_MAX:
+ return (BC_SCALE_MAX);
+ case _SC_BC_STRING_MAX:
+ return (BC_STRING_MAX);
+ case _SC_COLL_WEIGHTS_MAX:
+ return (COLL_WEIGHTS_MAX);
+ case _SC_EXPR_NEST_MAX:
+ return (EXPR_NEST_MAX);
+ case _SC_LINE_MAX:
+ return (LINE_MAX);
+ case _SC_RE_DUP_MAX:
+ return (RE_DUP_MAX);
+ case _SC_2_VERSION:
+ /*
+ * This is something of a lie, but it would be silly at
+ * this point to try to deduce this from the contents
+ * of the filesystem.
+ */
+ return (_POSIX2_VERSION);
+ case _SC_2_C_BIND:
+ return (_POSIX2_C_BIND);
+ case _SC_2_C_DEV:
+ return (_POSIX2_C_DEV);
+ case _SC_2_CHAR_TERM:
+ return (_POSIX2_CHAR_TERM);
+ case _SC_2_FORT_DEV:
+ return (_POSIX2_FORT_DEV);
+ case _SC_2_FORT_RUN:
+ return (_POSIX2_FORT_RUN);
+ case _SC_2_LOCALEDEF:
+ return (_POSIX2_LOCALEDEF);
+ case _SC_2_SW_DEV:
+ return (_POSIX2_SW_DEV);
+ case _SC_2_UPE:
+ return (_POSIX2_UPE);
+ case _SC_TZNAME_MAX:
+ path = _PATH_ZONEINFO;
+do_NAME_MAX:
+ sverrno = errno;
+ errno = 0;
+ lvalue = pathconf(path, _PC_NAME_MAX);
+ if (lvalue == -1 && errno != 0)
+ return (-1);
+ errno = sverrno;
+ return (lvalue);
+
+ case _SC_ASYNCHRONOUS_IO:
+#if _POSIX_ASYNCHRONOUS_IO == 0
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_ASYNCHRONOUS_IO;
+ break;
+#else
+ return (_POSIX_ASYNCHRONOUS_IO);
+#endif
+ case _SC_MAPPED_FILES:
+ return (_POSIX_MAPPED_FILES);
+ case _SC_MEMLOCK:
+ return (_POSIX_MEMLOCK);
+ case _SC_MEMLOCK_RANGE:
+ return (_POSIX_MEMLOCK_RANGE);
+ case _SC_MEMORY_PROTECTION:
+ return (_POSIX_MEMORY_PROTECTION);
+ case _SC_MESSAGE_PASSING:
+#if _POSIX_MESSAGE_PASSING == 0
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_MESSAGE_PASSING;
+ goto yesno;
+#else
+ return (_POSIX_MESSAGE_PASSING);
+#endif
+ case _SC_PRIORITIZED_IO:
+#if _POSIX_PRIORITIZED_IO == 0
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_PRIORITIZED_IO;
+ goto yesno;
+#else
+ return (_POSIX_PRIORITIZED_IO);
+#endif
+ case _SC_PRIORITY_SCHEDULING:
+#if _POSIX_PRIORITY_SCHEDULING == 0
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_PRIORITY_SCHEDULING;
+ goto yesno;
+#else
+ return (_POSIX_PRIORITY_SCHEDULING);
+#endif
+ case _SC_REALTIME_SIGNALS:
+#if _POSIX_REALTIME_SIGNALS == 0
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_REALTIME_SIGNALS;
+ goto yesno;
+#else
+ return (_POSIX_REALTIME_SIGNALS);
+#endif
+ case _SC_SEMAPHORES:
+#if _POSIX_SEMAPHORES == 0
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_SEMAPHORES;
+ goto yesno;
+#else
+ return (_POSIX_SEMAPHORES);
+#endif
+ case _SC_FSYNC:
+ return (_POSIX_FSYNC);
+
+ case _SC_SHARED_MEMORY_OBJECTS:
+ return (_POSIX_SHARED_MEMORY_OBJECTS);
+ case _SC_SYNCHRONIZED_IO:
+#if _POSIX_SYNCHRONIZED_IO == 0
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_SYNCHRONIZED_IO;
+ goto yesno;
+#else
+ return (_POSIX_SYNCHRONIZED_IO);
+#endif
+ case _SC_TIMERS:
+#if _POSIX_TIMERS == 0
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_TIMERS;
+ goto yesno;
+#else
+ return (_POSIX_TIMERS);
+#endif
+ case _SC_AIO_LISTIO_MAX:
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_AIO_LISTIO_MAX;
+ break;
+ case _SC_AIO_MAX:
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_AIO_MAX;
+ break;
+ case _SC_AIO_PRIO_DELTA_MAX:
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_AIO_PRIO_DELTA_MAX;
+ break;
+ case _SC_DELAYTIMER_MAX:
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_DELAYTIMER_MAX;
+ goto yesno;
+ case _SC_MQ_OPEN_MAX:
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_MQ_OPEN_MAX;
+ goto yesno;
+ case _SC_PAGESIZE:
+ defaultresult = getpagesize();
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_PAGESIZE;
+ goto yesno;
+ case _SC_RTSIG_MAX:
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_RTSIG_MAX;
+ goto yesno;
+ case _SC_SEM_NSEMS_MAX:
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_SEM_NSEMS_MAX;
+ goto yesno;
+ case _SC_SEM_VALUE_MAX:
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_SEM_VALUE_MAX;
+ goto yesno;
+ case _SC_SIGQUEUE_MAX:
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_SIGQUEUE_MAX;
+ goto yesno;
+ case _SC_TIMER_MAX:
+ mib[0] = CTL_P1003_1B;
+ mib[1] = CTL_P1003_1B_TIMER_MAX;
+yesno:
+ len = sizeof(value);
+ if (sysctl(mib, 2, &value, &len, NULL, 0) == -1)
+ return (-1);
+ if (value == 0)
+ return (defaultresult);
+ return ((long)value);
+
+ case _SC_2_PBS:
+ case _SC_2_PBS_ACCOUNTING:
+ case _SC_2_PBS_CHECKPOINT:
+ case _SC_2_PBS_LOCATE:
+ case _SC_2_PBS_MESSAGE:
+ case _SC_2_PBS_TRACK:
+#if _POSIX2_PBS == 0
+#error "don't know how to determine _SC_2_PBS"
+ /*
+ * This probably requires digging through the filesystem
+ * to see if the appropriate package has been installed.
+ * Since we don't currently support this option at all,
+ * it's not worth the effort to write the code now.
+ * Figuring out which of the sub-options are supported
+ * would be even more difficult, so it's probably easier
+ * to always say ``no''.
+ */
+#else
+ return (_POSIX2_PBS);
+#endif
+ case _SC_ADVISORY_INFO:
+#if _POSIX_ADVISORY_INFO == 0
+#error "_POSIX_ADVISORY_INFO"
+#else
+ return (_POSIX_ADVISORY_INFO);
+#endif
+ case _SC_BARRIERS:
+#if _POSIX_BARRIERS == 0
+#error "_POSIX_BARRIERS"
+#else
+ return (_POSIX_BARRIERS);
+#endif
+ case _SC_CLOCK_SELECTION:
+#if _POSIX_CLOCK_SELECTION == 0
+#error "_POSIX_CLOCK_SELECTION"
+#else
+ return (_POSIX_CLOCK_SELECTION);
+#endif
+ case _SC_CPUTIME:
+#if _POSIX_CPUTIME == 0
+#error "_POSIX_CPUTIME"
+#else
+ return (_POSIX_CPUTIME);
+#endif
+#ifdef notdef
+ case _SC_FILE_LOCKING:
+ /*
+ * XXX - The standard doesn't tell us how to define
+ * _POSIX_FILE_LOCKING, so we can't answer this one.
+ */
+#endif
+#if _POSIX_THREAD_SAFE_FUNCTIONS > -1
+ case _SC_GETGR_R_SIZE_MAX:
+ case _SC_GETPW_R_SIZE_MAX:
+#error "somebody needs to implement this"
+#endif
+ case _SC_HOST_NAME_MAX:
+ return (MAXHOSTNAMELEN - 1); /* does not include \0 */
+ case _SC_LOGIN_NAME_MAX:
+ return (MAXLOGNAME);
+ case _SC_MONOTONIC_CLOCK:
+#if _POSIX_MONOTONIC_CLOCK == 0
+#error "_POSIX_MONOTONIC_CLOCK"
+#else
+ return (_POSIX_MONOTONIC_CLOCK);
+#endif
+#if _POSIX_MESSAGE_PASSING > -1
+ case _SC_MQ_PRIO_MAX:
+ return (MQ_PRIO_MAX);
+#endif
+ case _SC_READER_WRITER_LOCKS:
+ return (_POSIX_READER_WRITER_LOCKS);
+ case _SC_REGEXP:
+ return (_POSIX_REGEXP);
+ case _SC_SHELL:
+ return (_POSIX_SHELL);
+ case _SC_SPAWN:
+ return (_POSIX_SPAWN);
+ case _SC_SPIN_LOCKS:
+ return (_POSIX_SPIN_LOCKS);
+ case _SC_SPORADIC_SERVER:
+#if _POSIX_SPORADIC_SERVER == 0
+#error "_POSIX_SPORADIC_SERVER"
+#else
+ return (_POSIX_SPORADIC_SERVER);
+#endif
+ case _SC_THREAD_ATTR_STACKADDR:
+ return (_POSIX_THREAD_ATTR_STACKADDR);
+ case _SC_THREAD_ATTR_STACKSIZE:
+ return (_POSIX_THREAD_ATTR_STACKSIZE);
+ case _SC_THREAD_CPUTIME:
+ return (_POSIX_THREAD_CPUTIME);
+ case _SC_THREAD_DESTRUCTOR_ITERATIONS:
+ return (PTHREAD_DESTRUCTOR_ITERATIONS);
+ case _SC_THREAD_KEYS_MAX:
+ return (PTHREAD_KEYS_MAX);
+ case _SC_THREAD_PRIO_INHERIT:
+ return (_POSIX_THREAD_PRIO_INHERIT);
+ case _SC_THREAD_PRIO_PROTECT:
+ return (_POSIX_THREAD_PRIO_PROTECT);
+ case _SC_THREAD_PRIORITY_SCHEDULING:
+ return (_POSIX_THREAD_PRIORITY_SCHEDULING);
+ case _SC_THREAD_PROCESS_SHARED:
+ return (_POSIX_THREAD_PROCESS_SHARED);
+ case _SC_THREAD_SAFE_FUNCTIONS:
+ return (_POSIX_THREAD_SAFE_FUNCTIONS);
+ case _SC_THREAD_STACK_MIN:
+ return (PTHREAD_STACK_MIN);
+ case _SC_THREAD_THREADS_MAX:
+ return (PTHREAD_THREADS_MAX); /* XXX wrong type! */
+ case _SC_TIMEOUTS:
+ return (_POSIX_TIMEOUTS);
+ case _SC_THREADS:
+ return (_POSIX_THREADS);
+ case _SC_TRACE:
+#if _POSIX_TRACE == 0
+#error "_POSIX_TRACE"
+ /* While you're implementing this, also do the ones below. */
+#else
+ return (_POSIX_TRACE);
+#endif
+#if _POSIX_TRACE > -1
+ case _SC_TRACE_EVENT_FILTER:
+ return (_POSIX_TRACE_EVENT_FILTER);
+ case _SC_TRACE_INHERIT:
+ return (_POSIX_TRACE_INHERIT);
+ case _SC_TRACE_LOG:
+ return (_POSIX_TRACE_LOG);
+#endif
+ case _SC_TTY_NAME_MAX:
+ path = _PATH_DEV;
+ goto do_NAME_MAX;
+ case _SC_TYPED_MEMORY_OBJECTS:
+#if _POSIX_TYPED_MEMORY_OBJECTS == 0
+#error "_POSIX_TYPED_MEMORY_OBJECTS"
+#else
+ return (_POSIX_TYPED_MEMORY_OBJECTS);
+#endif
+ case _SC_V6_ILP32_OFF32:
+#if _V6_ILP32_OFF32 == 0
+ if (sizeof(int) * CHAR_BIT == 32 &&
+ sizeof(int) == sizeof(long) &&
+ sizeof(long) == sizeof(void *) &&
+ sizeof(void *) == sizeof(off_t))
+ return 1;
+ else
+ return -1;
+#else
+ return (_V6_ILP32_OFF32);
+#endif
+ case _SC_V6_ILP32_OFFBIG:
+#if _V6_ILP32_OFFBIG == 0
+ if (sizeof(int) * CHAR_BIT == 32 &&
+ sizeof(int) == sizeof(long) &&
+ sizeof(long) == sizeof(void *) &&
+ sizeof(off_t) * CHAR_BIT >= 64)
+ return 1;
+ else
+ return -1;
+#else
+ return (_V6_ILP32_OFFBIG);
+#endif
+ case _SC_V6_LP64_OFF64:
+#if _V6_LP64_OFF64 == 0
+ if (sizeof(int) * CHAR_BIT == 32 &&
+ sizeof(long) * CHAR_BIT == 64 &&
+ sizeof(long) == sizeof(void *) &&
+ sizeof(void *) == sizeof(off_t))
+ return 1;
+ else
+ return -1;
+#else
+ return (_V6_LP64_OFF64);
+#endif
+ case _SC_V6_LPBIG_OFFBIG:
+#if _V6_LPBIG_OFFBIG == 0
+ if (sizeof(int) * CHAR_BIT >= 32 &&
+ sizeof(long) * CHAR_BIT >= 64 &&
+ sizeof(void *) * CHAR_BIT >= 64 &&
+ sizeof(off_t) * CHAR_BIT >= 64)
+ return 1;
+ else
+ return -1;
+#else
+ return (_V6_LPBIG_OFFBIG);
+#endif
+ case _SC_ATEXIT_MAX:
+ return (ATEXIT_SIZE);
+ case _SC_IOV_MAX:
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_IOV_MAX;
+ break;
+ case _SC_XOPEN_CRYPT:
+ return (_XOPEN_CRYPT);
+ case _SC_XOPEN_ENH_I18N:
+ return (_XOPEN_ENH_I18N);
+ case _SC_XOPEN_LEGACY:
+ return (_XOPEN_LEGACY);
+ case _SC_XOPEN_REALTIME:
+#if _XOPEN_REALTIME == 0
+ sverrno = errno;
+ value = sysconf(_SC_ASYNCHRONOUS_IO) > 0 &&
+ sysconf(_SC_MEMLOCK) > 0 &&
+ sysconf(_SC_MEMLOCK_RANGE) > 0 &&
+ sysconf(_SC_MESSAGE_PASSING) > 0 &&
+ sysconf(_SC_PRIORITY_SCHEDULING) > 0 &&
+ sysconf(_SC_REALTIME_SIGNALS) > 0 &&
+ sysconf(_SC_SEMAPHORES) > 0 &&
+ sysconf(_SC_SHARED_MEMORY_OBJECTS) > 0 &&
+ sysconf(_SC_SYNCHRONIZED_IO) > 0 &&
+ sysconf(_SC_TIMERS) > 0;
+ errno = sverrno;
+ if (value)
+ return (200112L);
+ else
+ return (-1);
+#else
+ return (_XOPEN_REALTIME);
+#endif
+ case _SC_XOPEN_REALTIME_THREADS:
+#if _XOPEN_REALTIME_THREADS == 0
+#error "_XOPEN_REALTIME_THREADS"
+#else
+ return (_XOPEN_REALTIME_THREADS);
+#endif
+ case _SC_XOPEN_SHM:
+ len = sizeof(lvalue);
+ sverrno = errno;
+ if (sysctlbyname("kern.ipc.shmmin", &lvalue, &len, NULL,
+ 0) == -1) {
+ errno = sverrno;
+ return (-1);
+ }
+ errno = sverrno;
+ return (1);
+ case _SC_XOPEN_STREAMS:
+ return (_XOPEN_STREAMS);
+ case _SC_XOPEN_UNIX:
+ return (_XOPEN_UNIX);
+#ifdef _XOPEN_VERSION
+ case _SC_XOPEN_VERSION:
+ return (_XOPEN_VERSION);
+#endif
+#ifdef _XOPEN_XCU_VERSION
+ case _SC_XOPEN_XCU_VERSION:
+ return (_XOPEN_XCU_VERSION);
+#endif
+ case _SC_SYMLOOP_MAX:
+ return (MAXSYMLINKS);
+ case _SC_RAW_SOCKETS:
+ return (_POSIX_RAW_SOCKETS);
+ case _SC_IPV6:
+#if _POSIX_IPV6 == 0
+ sverrno = errno;
+ value = socket(PF_INET6, SOCK_DGRAM, 0);
+ errno = sverrno;
+ if (value >= 0) {
+ close(value);
+ return (200112L);
+ } else
+ return (0);
+#else
+ return (_POSIX_IPV6);
+#endif
+
+ case _SC_NPROCESSORS_CONF:
+ case _SC_NPROCESSORS_ONLN:
+ mib[0] = CTL_HW;
+ mib[1] = HW_NCPU;
+ break;
+
+#ifdef _SC_PHYS_PAGES
+ case _SC_PHYS_PAGES:
+ len = sizeof(lvalue);
+ if (sysctlbyname("hw.availpages", &lvalue, &len, NULL, 0) == -1)
+ return (-1);
+ return (lvalue);
+#endif
+
+#ifdef _SC_CPUSET_SIZE
+ case _SC_CPUSET_SIZE:
+ len = sizeof(value);
+ if (sysctlbyname("kern.sched.cpusetsize", &value, &len, NULL,
+ 0) == -1)
+ return (-1);
+ return ((long)value);
+#endif
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+ len = sizeof(value);
+ if (sysctl(mib, 2, &value, &len, NULL, 0) == -1)
+ value = -1;
+ return ((long)value);
+}
diff --git a/lib/libc/gen/sysctl.3 b/lib/libc/gen/sysctl.3
new file mode 100644
index 0000000..b3737e2
--- /dev/null
+++ b/lib/libc/gen/sysctl.3
@@ -0,0 +1,874 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)sysctl.3 8.4 (Berkeley) 5/9/95
+.\" $FreeBSD$
+.\"
+.Dd February 11, 2012
+.Dt SYSCTL 3
+.Os
+.Sh NAME
+.Nm sysctl ,
+.Nm sysctlbyname ,
+.Nm sysctlnametomib
+.Nd get or set system information
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/sysctl.h
+.Ft int
+.Fn sysctl "const int *name" "u_int namelen" "void *oldp" "size_t *oldlenp" "const void *newp" "size_t newlen"
+.Ft int
+.Fn sysctlbyname "const char *name" "void *oldp" "size_t *oldlenp" "const void *newp" "size_t newlen"
+.Ft int
+.Fn sysctlnametomib "const char *name" "int *mibp" "size_t *sizep"
+.Sh DESCRIPTION
+The
+.Fn sysctl
+function retrieves system information and allows processes with
+appropriate privileges to set system information.
+The information available from
+.Fn sysctl
+consists of integers, strings, and tables.
+Information may be retrieved and set from the command interface
+using the
+.Xr sysctl 8
+utility.
+.Pp
+Unless explicitly noted below,
+.Fn sysctl
+returns a consistent snapshot of the data requested.
+Consistency is obtained by locking the destination
+buffer into memory so that the data may be copied out without blocking.
+Calls to
+.Fn sysctl
+are serialized to avoid deadlock.
+.Pp
+The state is described using a ``Management Information Base'' (MIB)
+style name, listed in
+.Fa name ,
+which is a
+.Fa namelen
+length array of integers.
+.Pp
+The
+.Fn sysctlbyname
+function accepts an ASCII representation of the name and internally
+looks up the integer name vector.
+Apart from that, it behaves the same
+as the standard
+.Fn sysctl
+function.
+.Pp
+The information is copied into the buffer specified by
+.Fa oldp .
+The size of the buffer is given by the location specified by
+.Fa oldlenp
+before the call,
+and that location gives the amount of data copied after a successful call
+and after a call that returns with the error code
+.Er ENOMEM .
+If the amount of data available is greater
+than the size of the buffer supplied,
+the call supplies as much data as fits in the buffer provided
+and returns with the error code
+.Er ENOMEM .
+If the old value is not desired,
+.Fa oldp
+and
+.Fa oldlenp
+should be set to NULL.
+.Pp
+The size of the available data can be determined by calling
+.Fn sysctl
+with the
+.Dv NULL
+argument for
+.Fa oldp .
+The size of the available data will be returned in the location pointed to by
+.Fa oldlenp .
+For some operations, the amount of space may change often.
+For these operations,
+the system attempts to round up so that the returned size is
+large enough for a call to return the data shortly thereafter.
+.Pp
+To set a new value,
+.Fa newp
+is set to point to a buffer of length
+.Fa newlen
+from which the requested value is to be taken.
+If a new value is not to be set,
+.Fa newp
+should be set to NULL and
+.Fa newlen
+set to 0.
+.Pp
+The
+.Fn sysctlnametomib
+function accepts an ASCII representation of the name,
+looks up the integer name vector,
+and returns the numeric representation in the mib array pointed to by
+.Fa mibp .
+The number of elements in the mib array is given by the location specified by
+.Fa sizep
+before the call,
+and that location gives the number of entries copied after a successful call.
+The resulting
+.Fa mib
+and
+.Fa size
+may be used in subsequent
+.Fn sysctl
+calls to get the data associated with the requested ASCII name.
+This interface is intended for use by applications that want to
+repeatedly request the same variable (the
+.Fn sysctl
+function runs in about a third the time as the same request made via the
+.Fn sysctlbyname
+function).
+The
+.Fn sysctlnametomib
+function is also useful for fetching mib prefixes and then adding
+a final component.
+For example, to fetch process information
+for processes with pid's less than 100:
+.Pp
+.Bd -literal -offset indent -compact
+int i, mib[4];
+size_t len;
+struct kinfo_proc kp;
+
+/* Fill out the first three components of the mib */
+len = 4;
+sysctlnametomib("kern.proc.pid", mib, &len);
+
+/* Fetch and print entries for pid's < 100 */
+for (i = 0; i < 100; i++) {
+ mib[3] = i;
+ len = sizeof(kp);
+ if (sysctl(mib, 4, &kp, &len, NULL, 0) == -1)
+ perror("sysctl");
+ else if (len > 0)
+ printkproc(&kp);
+}
+.Ed
+.Pp
+The top level names are defined with a CTL_ prefix in
+.In sys/sysctl.h ,
+and are as follows.
+The next and subsequent levels down are found in the include files
+listed here, and described in separate sections below.
+.Bl -column CTLXMACHDEPXXX "Next level namesXXXXXX" -offset indent
+.It Sy "Name Next level names Description"
+.It "CTL_DEBUG sys/sysctl.h Debugging"
+.It "CTL_VFS sys/mount.h File system"
+.It "CTL_HW sys/sysctl.h Generic CPU, I/O"
+.It "CTL_KERN sys/sysctl.h High kernel limits"
+.It "CTL_MACHDEP sys/sysctl.h Machine dependent"
+.It "CTL_NET sys/socket.h Networking"
+.It "CTL_USER sys/sysctl.h User-level"
+.It "CTL_VM vm/vm_param.h Virtual memory"
+.El
+.Pp
+For example, the following retrieves the maximum number of processes allowed
+in the system:
+.Pp
+.Bd -literal -offset indent -compact
+int mib[2], maxproc;
+size_t len;
+
+mib[0] = CTL_KERN;
+mib[1] = KERN_MAXPROC;
+len = sizeof(maxproc);
+sysctl(mib, 2, &maxproc, &len, NULL, 0);
+.Ed
+.Pp
+To retrieve the standard search path for the system utilities:
+.Pp
+.Bd -literal -offset indent -compact
+int mib[2];
+size_t len;
+char *p;
+
+mib[0] = CTL_USER;
+mib[1] = USER_CS_PATH;
+sysctl(mib, 2, NULL, &len, NULL, 0);
+p = malloc(len);
+sysctl(mib, 2, p, &len, NULL, 0);
+.Ed
+.Ss CTL_DEBUG
+The debugging variables vary from system to system.
+A debugging variable may be added or deleted without need to recompile
+.Fn sysctl
+to know about it.
+Each time it runs,
+.Fn sysctl
+gets the list of debugging variables from the kernel and
+displays their current values.
+The system defines twenty
+.Pq Vt "struct ctldebug"
+variables named
+.Va debug0
+through
+.Va debug19 .
+They are declared as separate variables so that they can be
+individually initialized at the location of their associated variable.
+The loader prevents multiple use of the same variable by issuing errors
+if a variable is initialized in more than one place.
+For example, to export the variable
+.Va dospecialcheck
+as a debugging variable, the following declaration would be used:
+.Pp
+.Bd -literal -offset indent -compact
+int dospecialcheck = 1;
+struct ctldebug debug5 = { "dospecialcheck", &dospecialcheck };
+.Ed
+.Ss CTL_VFS
+A distinguished second level name, VFS_GENERIC,
+is used to get general information about all file systems.
+One of its third level identifiers is VFS_MAXTYPENUM
+that gives the highest valid file system type number.
+Its other third level identifier is VFS_CONF that
+returns configuration information about the file system
+type given as a fourth level identifier (see
+.Xr getvfsbyname 3
+as an example of its use).
+The remaining second level identifiers are the
+file system type number returned by a
+.Xr statfs 2
+call or from VFS_CONF.
+The third level identifiers available for each file system
+are given in the header file that defines the mount
+argument structure for that file system.
+.Ss CTL_HW
+The string and integer information available for the CTL_HW level
+is detailed below.
+The changeable column shows whether a process with appropriate
+privilege may change the value.
+.Bl -column "Second level nameXXXXXX" integerXXX -offset indent
+.It Sy "Second level name Type Changeable"
+.It "HW_MACHINE string no"
+.It "HW_MODEL string no"
+.It "HW_NCPU integer no"
+.It "HW_BYTEORDER integer no"
+.It "HW_PHYSMEM integer no"
+.It "HW_USERMEM integer no"
+.It "HW_PAGESIZE integer no"
+.\".It "HW_DISKNAMES integer no"
+.\".It "HW_DISKSTATS integer no"
+.It "HW_FLOATINGPT integer no"
+.It "HW_MACHINE_ARCH string no"
+.It "HW_REALMEM integer no"
+.El
+.Bl -tag -width 6n
+.It Li HW_MACHINE
+The machine class.
+.It Li HW_MODEL
+The machine model
+.It Li HW_NCPU
+The number of cpus.
+.It Li HW_BYTEORDER
+The byteorder (4,321, or 1,234).
+.It Li HW_PHYSMEM
+The bytes of physical memory.
+.It Li HW_USERMEM
+The bytes of non-kernel memory.
+.It Li HW_PAGESIZE
+The software page size.
+.\".It Fa HW_DISKNAMES
+.\".It Fa HW_DISKSTATS
+.It Li HW_FLOATINGPT
+Nonzero if the floating point support is in hardware.
+.It Li HW_MACHINE_ARCH
+The machine dependent architecture type.
+.It Li HW_REALMEM
+The bytes of real memory.
+.El
+.Ss CTL_KERN
+The string and integer information available for the CTL_KERN level
+is detailed below.
+The changeable column shows whether a process with appropriate
+privilege may change the value.
+The types of data currently available are process information,
+system vnodes, the open file entries, routing table entries,
+virtual memory statistics, load average history, and clock rate
+information.
+.Bl -column "KERNXMAXFILESPERPROCXXX" "struct clockrateXXX" -offset indent
+.It Sy "Second level name Type Changeable"
+.It "KERN_ARGMAX integer no"
+.It "KERN_BOOTFILE string yes"
+.It "KERN_BOOTTIME struct timeval no"
+.It "KERN_CLOCKRATE struct clockinfo no"
+.It "KERN_FILE struct xfile no"
+.It "KERN_HOSTID integer yes"
+.It "KERN_HOSTUUID string yes"
+.It "KERN_HOSTNAME string yes"
+.It "KERN_JOB_CONTROL integer no"
+.It "KERN_MAXFILES integer yes"
+.It "KERN_MAXFILESPERPROC integer yes"
+.It "KERN_MAXPROC integer no"
+.It "KERN_MAXPROCPERUID integer yes"
+.It "KERN_MAXVNODES integer yes"
+.It "KERN_NGROUPS integer no"
+.It "KERN_NISDOMAINNAME string yes"
+.It "KERN_OSRELDATE integer no"
+.It "KERN_OSRELEASE string no"
+.It "KERN_OSREV integer no"
+.It "KERN_OSTYPE string no"
+.It "KERN_POSIX1 integer no"
+.It "KERN_PROC node not applicable"
+.It "KERN_PROF node not applicable"
+.It "KERN_QUANTUM integer yes"
+.It "KERN_SAVED_IDS integer no"
+.It "KERN_SECURELVL integer raise only"
+.It "KERN_UPDATEINTERVAL integer no"
+.It "KERN_VERSION string no"
+.It "KERN_VNODE struct xvnode no"
+.El
+.Bl -tag -width 6n
+.It Li KERN_ARGMAX
+The maximum bytes of argument to
+.Xr execve 2 .
+.It Li KERN_BOOTFILE
+The full pathname of the file from which the kernel was loaded.
+.It Li KERN_BOOTTIME
+A
+.Va struct timeval
+structure is returned.
+This structure contains the time that the system was booted.
+.It Li KERN_CLOCKRATE
+A
+.Va struct clockinfo
+structure is returned.
+This structure contains the clock, statistics clock and profiling clock
+frequencies, the number of micro-seconds per hz tick and the skew rate.
+.It Li KERN_FILE
+Return the entire file table.
+The returned data consists of an array of
+.Va struct xfile ,
+whose size depends on the current number of such objects in the system.
+.It Li KERN_HOSTID
+Get or set the host ID.
+.It Li KERN_HOSTUUID
+Get or set the host's universally unique identifier (UUID).
+.It Li KERN_HOSTNAME
+Get or set the hostname.
+.It Li KERN_JOB_CONTROL
+Return 1 if job control is available on this system, otherwise 0.
+.It Li KERN_MAXFILES
+The maximum number of files that may be open in the system.
+.It Li KERN_MAXFILESPERPROC
+The maximum number of files that may be open for a single process.
+This limit only applies to processes with an effective uid of nonzero
+at the time of the open request.
+Files that have already been opened are not affected if the limit
+or the effective uid is changed.
+.It Li KERN_MAXPROC
+The maximum number of concurrent processes the system will allow.
+.It Li KERN_MAXPROCPERUID
+The maximum number of concurrent processes the system will allow
+for a single effective uid.
+This limit only applies to processes with an effective uid of nonzero
+at the time of a fork request.
+Processes that have already been started are not affected if the limit
+is changed.
+.It Li KERN_MAXVNODES
+The maximum number of vnodes available on the system.
+.It Li KERN_NGROUPS
+The maximum number of supplemental groups.
+.It Li KERN_NISDOMAINNAME
+The name of the current YP/NIS domain.
+.It Li KERN_OSRELDATE
+The kernel release version in the format
+.Ar M Ns Ar mm Ns Ar R Ns Ar xx ,
+where
+.Ar M
+is the major version,
+.Ar mm
+is the two digit minor version,
+.Ar R
+is 0 if release branch, otherwise 1,
+and
+.Ar xx
+is updated when the available APIs change.
+.Pp
+The userland release version is available from
+.In osreldate.h ;
+parse this file if you need to get the release version of
+the currently installed userland.
+.It Li KERN_OSRELEASE
+The system release string.
+.It Li KERN_OSREV
+The system revision string.
+.It Li KERN_OSTYPE
+The system type string.
+.It Li KERN_POSIX1
+The version of
+.St -p1003.1
+with which the system
+attempts to comply.
+.It Li KERN_PROC
+Return selected information about specific running processes.
+.Pp
+For the following names, an array of
+.Va struct kinfo_proc
+structures is returned,
+whose size depends on the current number of such objects in the system.
+.Bl -column "Third level nameXXXXXX" "Fourth level is:XXXXXX" -offset indent
+.It "Third level name Fourth level is:"
+.It "KERN_PROC_ALL None"
+.It "KERN_PROC_PID A process ID"
+.It "KERN_PROC_PGRP A process group"
+.It "KERN_PROC_TTY A tty device"
+.It "KERN_PROC_UID A user ID"
+.It "KERN_PROC_RUID A real user ID"
+.El
+.Pp
+If the third level name is
+.Dv KERN_PROC_ARGS
+then the command line argument
+array is returned in a flattened form, i.e., zero-terminated arguments
+follow each other.
+The total size of array is returned.
+It is also possible for a process to set its own process title this way.
+If the third level name is
+.Dv KERN_PROC_PATHNAME ,
+the path of the
+process' text file is stored.
+For
+.Dv KERN_PROC_PATHNAME ,
+a process ID of
+.Li \-1
+implies the current process.
+.Bl -column "Third level nameXXXXXX" "Fourth level is:XXXXXX" -offset indent
+.It Sy "Third level name Fourth level is:"
+.It Dv KERN_PROC_ARGS Ta "A process ID"
+.It Dv KERN_PROC_PATHNAME Ta "A process ID"
+.El
+.It Li KERN_PROF
+Return profiling information about the kernel.
+If the kernel is not compiled for profiling,
+attempts to retrieve any of the KERN_PROF values will
+fail with
+.Er ENOENT .
+The third level names for the string and integer profiling information
+is detailed below.
+The changeable column shows whether a process with appropriate
+privilege may change the value.
+.Bl -column "GPROFXGMONPARAMXXX" "struct gmonparamXXX" -offset indent
+.It Sy "Third level name Type Changeable"
+.It "GPROF_STATE integer yes"
+.It "GPROF_COUNT u_short[\|] yes"
+.It "GPROF_FROMS u_short[\|] yes"
+.It "GPROF_TOS struct tostruct yes"
+.It "GPROF_GMONPARAM struct gmonparam no"
+.El
+.Pp
+The variables are as follows:
+.Bl -tag -width 6n
+.It Li GPROF_STATE
+Returns GMON_PROF_ON or GMON_PROF_OFF to show that profiling
+is running or stopped.
+.It Li GPROF_COUNT
+Array of statistical program counter counts.
+.It Li GPROF_FROMS
+Array indexed by program counter of call-from points.
+.It Li GPROF_TOS
+Array of
+.Va struct tostruct
+describing destination of calls and their counts.
+.It Li GPROF_GMONPARAM
+Structure giving the sizes of the above arrays.
+.El
+.It Li KERN_QUANTUM
+The maximum period of time, in microseconds, for which a process is allowed
+to run without being preempted if other processes are in the run queue.
+.It Li KERN_SAVED_IDS
+Returns 1 if saved set-group and saved set-user ID is available.
+.It Li KERN_SECURELVL
+The system security level.
+This level may be raised by processes with appropriate privilege.
+It may not be lowered.
+.It Li KERN_VERSION
+The system version string.
+.It Li KERN_VNODE
+Return the entire vnode table.
+Note, the vnode table is not necessarily a consistent snapshot of
+the system.
+The returned data consists of an array whose size depends on the
+current number of such objects in the system.
+Each element of the array consists of a
+.Va struct xvnode .
+.El
+.Ss CTL_NET
+The string and integer information available for the CTL_NET level
+is detailed below.
+The changeable column shows whether a process with appropriate
+privilege may change the value.
+.Bl -column "Second level nameXXXXXX" "routing messagesXXX" -offset indent
+.It Sy "Second level name Type Changeable"
+.It "PF_ROUTE routing messages no"
+.It "PF_INET IPv4 values yes"
+.It "PF_INET6 IPv6 values yes"
+.El
+.Bl -tag -width 6n
+.It Li PF_ROUTE
+Return the entire routing table or a subset of it.
+The data is returned as a sequence of routing messages (see
+.Xr route 4
+for the header file, format and meaning).
+The length of each message is contained in the message header.
+.Pp
+The third level name is a protocol number, which is currently always 0.
+The fourth level name is an address family, which may be set to 0 to
+select all address families.
+The fifth and sixth level names are as follows:
+.Bl -column "Fifth level nameXXXXXX" "Sixth level is:XXX" -offset indent
+.It Sy "Fifth level name Sixth level is:"
+.It "NET_RT_FLAGS rtflags"
+.It "NET_RT_DUMP None"
+.It "NET_RT_IFLIST 0 or if_index"
+.It "NET_RT_IFMALIST 0 or if_index"
+.It "NET_RT_IFLISTL 0 or if_index"
+.El
+.Pp
+The
+.Dv NET_RT_IFMALIST
+name returns information about multicast group memberships on all interfaces
+if 0 is specified, or for the interface specified by
+.Va if_index .
+.Pp
+The
+.Dv NET_RT_IFLISTL
+is like
+.Dv NET_RT_IFLIST ,
+just returning message header structs with additional fields allowing the
+interface to be extended without breaking binary compatibility.
+The
+.Dv NET_RT_IFLISTL
+uses 'l' versions of the message header structures:
+.Va struct if_msghdrl
+and
+.Va struct ifa_msghdrl .
+.It Li PF_INET
+Get or set various global information about the IPv4
+(Internet Protocol version 4).
+The third level name is the protocol.
+The fourth level name is the variable name.
+The currently defined protocols and names are:
+.Bl -column ProtocolXX VariableXX TypeXX ChangeableXX
+.It Sy "Protocol Variable Type Changeable"
+.It "icmp bmcastecho integer yes"
+.It "icmp maskrepl integer yes"
+.It "ip forwarding integer yes"
+.It "ip redirect integer yes"
+.It "ip ttl integer yes"
+.It "udp checksum integer yes"
+.El
+.Pp
+The variables are as follows:
+.Bl -tag -width 6n
+.It Li icmp.bmcastecho
+Returns 1 if an ICMP echo request to a broadcast or multicast address is
+to be answered.
+.It Li icmp.maskrepl
+Returns 1 if ICMP network mask requests are to be answered.
+.It Li ip.forwarding
+Returns 1 when IP forwarding is enabled for the host,
+meaning that the host is acting as a router.
+.It Li ip.redirect
+Returns 1 when ICMP redirects may be sent by the host.
+This option is ignored unless the host is routing IP packets,
+and should normally be enabled on all systems.
+.It Li ip.ttl
+The maximum time-to-live (hop count) value for an IP packet sourced by
+the system.
+This value applies to normal transport protocols, not to ICMP.
+.It Li udp.checksum
+Returns 1 when UDP checksums are being computed and checked.
+Disabling UDP checksums is strongly discouraged.
+.Pp
+For variables net.inet.*.ipsec, please refer to
+.Xr ipsec 4 .
+.El
+.It Li PF_INET6
+Get or set various global information about the IPv6
+(Internet Protocol version 6).
+The third level name is the protocol.
+The fourth level name is the variable name.
+.Pp
+For variables net.inet6.* please refer to
+.Xr inet6 4 .
+For variables net.inet6.*.ipsec6, please refer to
+.Xr ipsec 4 .
+.El
+.Ss CTL_USER
+The string and integer information available for the CTL_USER level
+is detailed below.
+The changeable column shows whether a process with appropriate
+privilege may change the value.
+.Bl -column "USER_COLL_WEIGHTS_MAXXXX" "integerXXX" -offset indent
+.It Sy "Second level name Type Changeable"
+.It "USER_BC_BASE_MAX integer no"
+.It "USER_BC_DIM_MAX integer no"
+.It "USER_BC_SCALE_MAX integer no"
+.It "USER_BC_STRING_MAX integer no"
+.It "USER_COLL_WEIGHTS_MAX integer no"
+.It "USER_CS_PATH string no"
+.It "USER_EXPR_NEST_MAX integer no"
+.It "USER_LINE_MAX integer no"
+.It "USER_POSIX2_CHAR_TERM integer no"
+.It "USER_POSIX2_C_BIND integer no"
+.It "USER_POSIX2_C_DEV integer no"
+.It "USER_POSIX2_FORT_DEV integer no"
+.It "USER_POSIX2_FORT_RUN integer no"
+.It "USER_POSIX2_LOCALEDEF integer no"
+.It "USER_POSIX2_SW_DEV integer no"
+.It "USER_POSIX2_UPE integer no"
+.It "USER_POSIX2_VERSION integer no"
+.It "USER_RE_DUP_MAX integer no"
+.It "USER_STREAM_MAX integer no"
+.It "USER_TZNAME_MAX integer no"
+.El
+.Bl -tag -width 6n
+.It Li USER_BC_BASE_MAX
+The maximum ibase/obase values in the
+.Xr bc 1
+utility.
+.It Li USER_BC_DIM_MAX
+The maximum array size in the
+.Xr bc 1
+utility.
+.It Li USER_BC_SCALE_MAX
+The maximum scale value in the
+.Xr bc 1
+utility.
+.It Li USER_BC_STRING_MAX
+The maximum string length in the
+.Xr bc 1
+utility.
+.It Li USER_COLL_WEIGHTS_MAX
+The maximum number of weights that can be assigned to any entry of
+the LC_COLLATE order keyword in the locale definition file.
+.It Li USER_CS_PATH
+Return a value for the
+.Ev PATH
+environment variable that finds all the standard utilities.
+.It Li USER_EXPR_NEST_MAX
+The maximum number of expressions that can be nested within
+parenthesis by the
+.Xr expr 1
+utility.
+.It Li USER_LINE_MAX
+The maximum length in bytes of a text-processing utility's input
+line.
+.It Li USER_POSIX2_CHAR_TERM
+Return 1 if the system supports at least one terminal type capable of
+all operations described in
+.St -p1003.2 ,
+otherwise 0.
+.It Li USER_POSIX2_C_BIND
+Return 1 if the system's C-language development facilities support the
+C-Language Bindings Option, otherwise 0.
+.It Li USER_POSIX2_C_DEV
+Return 1 if the system supports the C-Language Development Utilities Option,
+otherwise 0.
+.It Li USER_POSIX2_FORT_DEV
+Return 1 if the system supports the FORTRAN Development Utilities Option,
+otherwise 0.
+.It Li USER_POSIX2_FORT_RUN
+Return 1 if the system supports the FORTRAN Runtime Utilities Option,
+otherwise 0.
+.It Li USER_POSIX2_LOCALEDEF
+Return 1 if the system supports the creation of locales, otherwise 0.
+.It Li USER_POSIX2_SW_DEV
+Return 1 if the system supports the Software Development Utilities Option,
+otherwise 0.
+.It Li USER_POSIX2_UPE
+Return 1 if the system supports the User Portability Utilities Option,
+otherwise 0.
+.It Li USER_POSIX2_VERSION
+The version of
+.St -p1003.2
+with which the system attempts to comply.
+.It Li USER_RE_DUP_MAX
+The maximum number of repeated occurrences of a regular expression
+permitted when using interval notation.
+.It Li USER_STREAM_MAX
+The minimum maximum number of streams that a process may have open
+at any one time.
+.It Li USER_TZNAME_MAX
+The minimum maximum number of types supported for the name of a
+timezone.
+.El
+.Ss CTL_VM
+The string and integer information available for the CTL_VM level
+is detailed below.
+The changeable column shows whether a process with appropriate
+privilege may change the value.
+.Bl -column "Second level nameXXXXXX" "struct loadavgXXX" -offset indent
+.It Sy "Second level name Type Changeable"
+.It "VM_LOADAVG struct loadavg no"
+.It "VM_TOTAL struct vmtotal no"
+.It "VM_PAGEOUT_ALGORITHM integer yes"
+.It "VM_SWAPPING_ENABLED integer maybe"
+.It "VM_V_CACHE_MAX integer yes"
+.It "VM_V_CACHE_MIN integer yes"
+.It "VM_V_FREE_MIN integer yes"
+.It "VM_V_FREE_RESERVED integer yes"
+.It "VM_V_FREE_TARGET integer yes"
+.It "VM_V_INACTIVE_TARGET integer yes"
+.It "VM_V_PAGEOUT_FREE_MIN integer yes"
+.El
+.Bl -tag -width 6n
+.It Li VM_LOADAVG
+Return the load average history.
+The returned data consists of a
+.Va struct loadavg .
+.It Li VM_TOTAL
+Return the system wide virtual memory statistics.
+The returned data consists of a
+.Va struct vmtotal .
+.It Li VM_PAGEOUT_ALGORITHM
+0 if the statistics-based page management algorithm is in use
+or 1 if the near-LRU algorithm is in use.
+.It Li VM_SWAPPING_ENABLED
+1 if process swapping is enabled or 0 if disabled.
+This variable is
+permanently set to 0 if the kernel was built with swapping disabled.
+.It Li VM_V_CACHE_MAX
+Maximum desired size of the cache queue.
+.It Li VM_V_CACHE_MIN
+Minimum desired size of the cache queue.
+If the cache queue size
+falls very far below this value, the pageout daemon is awakened.
+.It Li VM_V_FREE_MIN
+Minimum amount of memory (cache memory plus free memory)
+required to be available before a process waiting on memory will be
+awakened.
+.It Li VM_V_FREE_RESERVED
+Processes will awaken the pageout daemon and wait for memory if the
+number of free and cached pages drops below this value.
+.It Li VM_V_FREE_TARGET
+The total amount of free memory (including cache memory) that the
+pageout daemon tries to maintain.
+.It Li VM_V_INACTIVE_TARGET
+The desired number of inactive pages that the pageout daemon should
+achieve when it runs.
+Inactive pages can be quickly inserted into
+process address space when needed.
+.It Li VM_V_PAGEOUT_FREE_MIN
+If the amount of free and cache memory falls below this value, the
+pageout daemon will enter "memory conserving mode" to avoid deadlock.
+.El
+.Sh RETURN VALUES
+.Rv -std
+.Sh FILES
+.Bl -tag -width <netinet/icmpXvar.h> -compact
+.It In sys/sysctl.h
+definitions for top level identifiers, second level kernel and hardware
+identifiers, and user level identifiers
+.It In sys/socket.h
+definitions for second level network identifiers
+.It In sys/gmon.h
+definitions for third level profiling identifiers
+.It In vm/vm_param.h
+definitions for second level virtual memory identifiers
+.It In netinet/in.h
+definitions for third level IPv4/IPv6 identifiers and
+fourth level IPv4/v6 identifiers
+.It In netinet/icmp_var.h
+definitions for fourth level ICMP identifiers
+.It In netinet/icmp6.h
+definitions for fourth level ICMPv6 identifiers
+.It In netinet/udp_var.h
+definitions for fourth level UDP identifiers
+.El
+.Sh ERRORS
+The following errors may be reported:
+.Bl -tag -width Er
+.It Bq Er EFAULT
+The buffer
+.Fa name ,
+.Fa oldp ,
+.Fa newp ,
+or length pointer
+.Fa oldlenp
+contains an invalid address.
+.It Bq Er EINVAL
+The
+.Fa name
+array is less than two or greater than CTL_MAXNAME.
+.It Bq Er EINVAL
+A non-null
+.Fa newp
+is given and its specified length in
+.Fa newlen
+is too large or too small.
+.It Bq Er ENOMEM
+The length pointed to by
+.Fa oldlenp
+is too short to hold the requested value.
+.It Bq Er ENOMEM
+The smaller of either the length pointed to by
+.Fa oldlenp
+or the estimated size of the returned data exceeds the
+system limit on locked memory.
+.It Bq Er ENOMEM
+Locking the buffer
+.Fa oldp ,
+or a portion of the buffer if the estimated size of the data
+to be returned is smaller,
+would cause the process to exceed its per-process locked memory limit.
+.It Bq Er ENOTDIR
+The
+.Fa name
+array specifies an intermediate rather than terminal name.
+.It Bq Er EISDIR
+The
+.Fa name
+array specifies a terminal name, but the actual name is not terminal.
+.It Bq Er ENOENT
+The
+.Fa name
+array specifies a value that is unknown.
+.It Bq Er EPERM
+An attempt is made to set a read-only value.
+.It Bq Er EPERM
+A process without appropriate privilege attempts to set a value.
+.El
+.Sh SEE ALSO
+.Xr confstr 3 ,
+.Xr kvm 3 ,
+.Xr sysconf 3 ,
+.Xr sysctl 8
+.Sh HISTORY
+The
+.Fn sysctl
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/sysctl.c b/lib/libc/gen/sysctl.c
new file mode 100644
index 0000000..fbc2c0c
--- /dev/null
+++ b/lib/libc/gen/sysctl.c
@@ -0,0 +1,180 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)sysctl.c 8.2 (Berkeley) 1/4/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/sysctl.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+
+extern int __sysctl(const int *name, u_int namelen, void *oldp,
+ size_t *oldlenp, const void *newp, size_t newlen);
+
+int
+sysctl(const int *name, u_int namelen, void *oldp, size_t *oldlenp,
+ const void *newp, size_t newlen)
+{
+ if (name[0] != CTL_USER)
+ return (__sysctl(name, namelen, oldp, oldlenp, newp, newlen));
+
+ if (newp != NULL) {
+ errno = EPERM;
+ return (-1);
+ }
+ if (namelen != 2) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ switch (name[1]) {
+ case USER_CS_PATH:
+ if (oldp && *oldlenp < sizeof(_PATH_STDPATH)) {
+ errno = ENOMEM;
+ return -1;
+ }
+ *oldlenp = sizeof(_PATH_STDPATH);
+ if (oldp != NULL)
+ memmove(oldp, _PATH_STDPATH, sizeof(_PATH_STDPATH));
+ return (0);
+ }
+
+ if (oldp && *oldlenp < sizeof(int)) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ *oldlenp = sizeof(int);
+ if (oldp == NULL)
+ return (0);
+
+ switch (name[1]) {
+ case USER_BC_BASE_MAX:
+ *(int *)oldp = BC_BASE_MAX;
+ return (0);
+ case USER_BC_DIM_MAX:
+ *(int *)oldp = BC_DIM_MAX;
+ return (0);
+ case USER_BC_SCALE_MAX:
+ *(int *)oldp = BC_SCALE_MAX;
+ return (0);
+ case USER_BC_STRING_MAX:
+ *(int *)oldp = BC_STRING_MAX;
+ return (0);
+ case USER_COLL_WEIGHTS_MAX:
+ *(int *)oldp = COLL_WEIGHTS_MAX;
+ return (0);
+ case USER_EXPR_NEST_MAX:
+ *(int *)oldp = EXPR_NEST_MAX;
+ return (0);
+ case USER_LINE_MAX:
+ *(int *)oldp = LINE_MAX;
+ return (0);
+ case USER_RE_DUP_MAX:
+ *(int *)oldp = RE_DUP_MAX;
+ return (0);
+ case USER_POSIX2_VERSION:
+ *(int *)oldp = _POSIX2_VERSION;
+ return (0);
+ case USER_POSIX2_C_BIND:
+#ifdef POSIX2_C_BIND
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_POSIX2_C_DEV:
+#ifdef POSIX2_C_DEV
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_POSIX2_CHAR_TERM:
+#ifdef POSIX2_CHAR_TERM
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_POSIX2_FORT_DEV:
+#ifdef POSIX2_FORT_DEV
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_POSIX2_FORT_RUN:
+#ifdef POSIX2_FORT_RUN
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_POSIX2_LOCALEDEF:
+#ifdef POSIX2_LOCALEDEF
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_POSIX2_SW_DEV:
+#ifdef POSIX2_SW_DEV
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_POSIX2_UPE:
+#ifdef POSIX2_UPE
+ *(int *)oldp = 1;
+#else
+ *(int *)oldp = 0;
+#endif
+ return (0);
+ case USER_STREAM_MAX:
+ *(int *)oldp = FOPEN_MAX;
+ return (0);
+ case USER_TZNAME_MAX:
+ *(int *)oldp = NAME_MAX;
+ return (0);
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+ /* NOTREACHED */
+}
diff --git a/lib/libc/gen/sysctlbyname.c b/lib/libc/gen/sysctlbyname.c
new file mode 100644
index 0000000..a2e0d5f
--- /dev/null
+++ b/lib/libc/gen/sysctlbyname.c
@@ -0,0 +1,31 @@
+/*
+ * ----------------------------------------------------------------------------
+ * "THE BEER-WARE LICENSE" (Revision 42):
+ * <phk@FreeBSD.org> wrote this file. As long as you retain this notice you
+ * can do whatever you want with this stuff. If we meet some day, and you think
+ * this stuff is worth it, you can buy me a beer in return. Poul-Henning Kamp
+ * ----------------------------------------------------------------------------
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+
+int
+sysctlbyname(const char *name, void *oldp, size_t *oldlenp,
+ const void *newp, size_t newlen)
+{
+ int real_oid[CTL_MAXNAME+2];
+ int error;
+ size_t oidlen;
+
+ oidlen = sizeof(real_oid) / sizeof(int);
+ error = sysctlnametomib(name, real_oid, &oidlen);
+ if (error < 0)
+ return (error);
+ error = sysctl(real_oid, oidlen, oldp, oldlenp, newp, newlen);
+ return (error);
+}
diff --git a/lib/libc/gen/sysctlnametomib.c b/lib/libc/gen/sysctlnametomib.c
new file mode 100644
index 0000000..afca95d
--- /dev/null
+++ b/lib/libc/gen/sysctlnametomib.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2001 The FreeBSD Project. All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/sysctl.h>
+#include <string.h>
+
+/*
+ * This function uses a presently undocumented interface to the kernel
+ * to walk the tree and get the type so it can print the value.
+ * This interface is under work and consideration, and should probably
+ * be killed with a big axe by the first person who can find the time.
+ * (be aware though, that the proper interface isn't as obvious as it
+ * may seem, there are various conflicting requirements.
+ */
+int
+sysctlnametomib(const char *name, int *mibp, size_t *sizep)
+{
+ int oid[2];
+ int error;
+
+ oid[0] = 0;
+ oid[1] = 3;
+
+ *sizep *= sizeof(int);
+ error = sysctl(oid, 2, mibp, sizep, name, strlen(name));
+ *sizep /= sizeof(int);
+ return (error);
+}
diff --git a/lib/libc/gen/syslog.3 b/lib/libc/gen/syslog.3
new file mode 100644
index 0000000..91404a3
--- /dev/null
+++ b/lib/libc/gen/syslog.3
@@ -0,0 +1,295 @@
+.\" Copyright (c) 1985, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)syslog.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd December 30, 2004
+.Dt SYSLOG 3
+.Os
+.Sh NAME
+.Nm syslog ,
+.Nm vsyslog ,
+.Nm openlog ,
+.Nm closelog ,
+.Nm setlogmask
+.Nd control system log
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In syslog.h
+.In stdarg.h
+.Ft void
+.Fn syslog "int priority" "const char *message" "..."
+.Ft void
+.Fn vsyslog "int priority" "const char *message" "va_list args"
+.Ft void
+.Fn openlog "const char *ident" "int logopt" "int facility"
+.Ft void
+.Fn closelog void
+.Ft int
+.Fn setlogmask "int maskpri"
+.Sh DESCRIPTION
+The
+.Fn syslog
+function
+writes
+.Fa message
+to the system message logger.
+The message is then written to the system console, log files,
+logged-in users, or forwarded to other machines as appropriate.
+(See
+.Xr syslogd 8 . )
+.Pp
+The message is identical to a
+.Xr printf 3
+format string, except that
+.Ql %m
+is replaced by the current error
+message.
+(As denoted by the global variable
+.Va errno ;
+see
+.Xr strerror 3 . )
+A trailing newline is added if none is present.
+.Pp
+The
+.Fn vsyslog
+function
+is an alternate form in which the arguments have already been captured
+using the variable-length argument facilities of
+.Xr stdarg 3 .
+.Pp
+The message is tagged with
+.Fa priority .
+Priorities are encoded as a
+.Fa facility
+and a
+.Em level .
+The facility describes the part of the system
+generating the message.
+The level is selected from the following
+.Em ordered
+(high to low) list:
+.Bl -tag -width LOG_AUTHPRIV
+.It Dv LOG_EMERG
+A panic condition.
+This is normally broadcast to all users.
+.It Dv LOG_ALERT
+A condition that should be corrected immediately, such as a corrupted
+system database.
+.It Dv LOG_CRIT
+Critical conditions, e.g., hard device errors.
+.It Dv LOG_ERR
+Errors.
+.It Dv LOG_WARNING
+Warning messages.
+.It Dv LOG_NOTICE
+Conditions that are not error conditions,
+but should possibly be handled specially.
+.It Dv LOG_INFO
+Informational messages.
+.It Dv LOG_DEBUG
+Messages that contain information
+normally of use only when debugging a program.
+.El
+.Pp
+The
+.Fn openlog
+function
+provides for more specialized processing of the messages sent
+by
+.Fn syslog
+and
+.Fn vsyslog .
+The
+.Fa ident
+argument
+is a string that will be prepended to every message.
+The
+.Fa logopt
+argument
+is a bit field specifying logging options, which is formed by
+.Tn OR Ns 'ing
+one or more of the following values:
+.Bl -tag -width LOG_AUTHPRIV
+.It Dv LOG_CONS
+If
+.Fn syslog
+cannot pass the message to
+.Xr syslogd 8
+it will attempt to write the message to the console
+.Pq Dq Pa /dev/console .
+.It Dv LOG_NDELAY
+Open the connection to
+.Xr syslogd 8
+immediately.
+Normally the open is delayed until the first message is logged.
+Useful for programs that need to manage the order in which file
+descriptors are allocated.
+.It Dv LOG_PERROR
+Write the message to standard error output as well to the system log.
+.It Dv LOG_PID
+Log the process id with each message: useful for identifying
+instantiations of daemons.
+.El
+.Pp
+The
+.Fa facility
+argument encodes a default facility to be assigned to all messages
+that do not have an explicit facility encoded:
+.Bl -tag -width LOG_AUTHPRIV
+.It Dv LOG_AUTH
+The authorization system:
+.Xr login 1 ,
+.Xr su 1 ,
+.Xr getty 8 ,
+etc.
+.It Dv LOG_AUTHPRIV
+The same as
+.Dv LOG_AUTH ,
+but logged to a file readable only by
+selected individuals.
+.It Dv LOG_CONSOLE
+Messages written to
+.Pa /dev/console
+by the kernel console output driver.
+.It Dv LOG_CRON
+The cron daemon:
+.Xr cron 8 .
+.It Dv LOG_DAEMON
+System daemons, such as
+.Xr routed 8 ,
+that are not provided for explicitly by other facilities.
+.It Dv LOG_FTP
+The file transfer protocol daemons:
+.Xr ftpd 8 ,
+.Xr tftpd 8 .
+.It Dv LOG_KERN
+Messages generated by the kernel.
+These cannot be generated by any user processes.
+.It Dv LOG_LPR
+The line printer spooling system:
+.Xr lpr 1 ,
+.Xr lpc 8 ,
+.Xr lpd 8 ,
+etc.
+.It Dv LOG_MAIL
+The mail system.
+.It Dv LOG_NEWS
+The network news system.
+.It Dv LOG_NTP
+The network time protocol system.
+.It Dv LOG_SECURITY
+Security subsystems, such as
+.Xr ipfw 4 .
+.It Dv LOG_SYSLOG
+Messages generated internally by
+.Xr syslogd 8 .
+.It Dv LOG_USER
+Messages generated by random user processes.
+This is the default facility identifier if none is specified.
+.It Dv LOG_UUCP
+The uucp system.
+.It Dv LOG_LOCAL0
+Reserved for local use.
+Similarly for
+.Dv LOG_LOCAL1
+through
+.Dv LOG_LOCAL7 .
+.El
+.Pp
+The
+.Fn closelog
+function
+can be used to close the log file.
+.Pp
+The
+.Fn setlogmask
+function
+sets the log priority mask to
+.Fa maskpri
+and returns the previous mask.
+Calls to
+.Fn syslog
+with a priority not set in
+.Fa maskpri
+are rejected.
+The mask for an individual priority
+.Fa pri
+is calculated by the macro
+.Fn LOG_MASK pri ;
+the mask for all priorities up to and including
+.Fa toppri
+is given by the macro
+.Fn LOG_UPTO toppri ; .
+The default allows all priorities to be logged.
+.Sh RETURN VALUES
+The routines
+.Fn closelog ,
+.Fn openlog ,
+.Fn syslog
+and
+.Fn vsyslog
+return no value.
+.Pp
+The routine
+.Fn setlogmask
+always returns the previous log mask level.
+.Sh EXAMPLES
+.Bd -literal -offset indent -compact
+syslog(LOG_ALERT, "who: internal error 23");
+
+openlog("ftpd", LOG_PID | LOG_NDELAY, LOG_FTP);
+
+setlogmask(LOG_UPTO(LOG_ERR));
+
+syslog(LOG_INFO, "Connection from host %d", CallingHost);
+
+syslog(LOG_INFO|LOG_LOCAL2, "foobar error: %m");
+.Ed
+.Sh SEE ALSO
+.Xr logger 1 ,
+.Xr syslogd 8
+.Sh HISTORY
+These
+functions appeared in
+.Bx 4.2 .
+.Sh BUGS
+Never pass a string with user-supplied data as a format without using
+.Ql %s .
+An attacker can put format specifiers in the string to mangle your stack,
+leading to a possible security hole.
+This holds true even if the string was built using a function like
+.Fn snprintf ,
+as the resulting string may still contain user-supplied conversion specifiers
+for later interpolation by
+.Fn syslog .
+.Pp
+Always use the proper secure idiom:
+.Pp
+.Dl syslog("%s", string);
diff --git a/lib/libc/gen/syslog.c b/lib/libc/gen/syslog.c
new file mode 100644
index 0000000..de438c4
--- /dev/null
+++ b/lib/libc/gen/syslog.c
@@ -0,0 +1,435 @@
+/*
+ * Copyright (c) 1983, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)syslog.c 8.5 (Berkeley) 4/29/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <netdb.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <stdarg.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+static int LogFile = -1; /* fd for log */
+static int status; /* connection status */
+static int opened; /* have done openlog() */
+static int LogStat = 0; /* status bits, set by openlog() */
+static const char *LogTag = NULL; /* string to tag the entry with */
+static int LogFacility = LOG_USER; /* default facility code */
+static int LogMask = 0xff; /* mask of priorities to be logged */
+static pthread_mutex_t syslog_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#define THREAD_LOCK() \
+ do { \
+ if (__isthreaded) _pthread_mutex_lock(&syslog_mutex); \
+ } while(0)
+#define THREAD_UNLOCK() \
+ do { \
+ if (__isthreaded) _pthread_mutex_unlock(&syslog_mutex); \
+ } while(0)
+
+static void disconnectlog(void); /* disconnect from syslogd */
+static void connectlog(void); /* (re)connect to syslogd */
+static void openlog_unlocked(const char *, int, int);
+
+enum {
+ NOCONN = 0,
+ CONNDEF,
+ CONNPRIV,
+};
+
+/*
+ * Format of the magic cookie passed through the stdio hook
+ */
+struct bufcookie {
+ char *base; /* start of buffer */
+ int left;
+};
+
+/*
+ * stdio write hook for writing to a static string buffer
+ * XXX: Maybe one day, dynamically allocate it so that the line length
+ * is `unlimited'.
+ */
+static int
+writehook(void *cookie, const char *buf, int len)
+{
+ struct bufcookie *h; /* private `handle' */
+
+ h = (struct bufcookie *)cookie;
+ if (len > h->left) {
+ /* clip in case of wraparound */
+ len = h->left;
+ }
+ if (len > 0) {
+ (void)memcpy(h->base, buf, len); /* `write' it. */
+ h->base += len;
+ h->left -= len;
+ }
+ return len;
+}
+
+/*
+ * syslog, vsyslog --
+ * print message on log file; output is intended for syslogd(8).
+ */
+void
+syslog(int pri, const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsyslog(pri, fmt, ap);
+ va_end(ap);
+}
+
+void
+vsyslog(int pri, const char *fmt, va_list ap)
+{
+ int cnt;
+ char ch, *p;
+ time_t now;
+ int fd, saved_errno;
+ char *stdp, tbuf[2048], fmt_cpy[1024], timbuf[26], errstr[64];
+ FILE *fp, *fmt_fp;
+ struct bufcookie tbuf_cookie;
+ struct bufcookie fmt_cookie;
+
+#define INTERNALLOG LOG_ERR|LOG_CONS|LOG_PERROR|LOG_PID
+ /* Check for invalid bits. */
+ if (pri & ~(LOG_PRIMASK|LOG_FACMASK)) {
+ syslog(INTERNALLOG,
+ "syslog: unknown facility/priority: %x", pri);
+ pri &= LOG_PRIMASK|LOG_FACMASK;
+ }
+
+ saved_errno = errno;
+
+ THREAD_LOCK();
+
+ /* Check priority against setlogmask values. */
+ if (!(LOG_MASK(LOG_PRI(pri)) & LogMask)) {
+ THREAD_UNLOCK();
+ return;
+ }
+
+ /* Set default facility if none specified. */
+ if ((pri & LOG_FACMASK) == 0)
+ pri |= LogFacility;
+
+ /* Create the primary stdio hook */
+ tbuf_cookie.base = tbuf;
+ tbuf_cookie.left = sizeof(tbuf);
+ fp = fwopen(&tbuf_cookie, writehook);
+ if (fp == NULL) {
+ THREAD_UNLOCK();
+ return;
+ }
+
+ /* Build the message. */
+ (void)time(&now);
+ (void)fprintf(fp, "<%d>", pri);
+ (void)fprintf(fp, "%.15s ", ctime_r(&now, timbuf) + 4);
+ if (LogStat & LOG_PERROR) {
+ /* Transfer to string buffer */
+ (void)fflush(fp);
+ stdp = tbuf + (sizeof(tbuf) - tbuf_cookie.left);
+ }
+ if (LogTag == NULL)
+ LogTag = _getprogname();
+ if (LogTag != NULL)
+ (void)fprintf(fp, "%s", LogTag);
+ if (LogStat & LOG_PID)
+ (void)fprintf(fp, "[%d]", getpid());
+ if (LogTag != NULL) {
+ (void)fprintf(fp, ": ");
+ }
+
+ /* Check to see if we can skip expanding the %m */
+ if (strstr(fmt, "%m")) {
+
+ /* Create the second stdio hook */
+ fmt_cookie.base = fmt_cpy;
+ fmt_cookie.left = sizeof(fmt_cpy) - 1;
+ fmt_fp = fwopen(&fmt_cookie, writehook);
+ if (fmt_fp == NULL) {
+ fclose(fp);
+ THREAD_UNLOCK();
+ return;
+ }
+
+ /*
+ * Substitute error message for %m. Be careful not to
+ * molest an escaped percent "%%m". We want to pass it
+ * on untouched as the format is later parsed by vfprintf.
+ */
+ for ( ; (ch = *fmt); ++fmt) {
+ if (ch == '%' && fmt[1] == 'm') {
+ ++fmt;
+ strerror_r(saved_errno, errstr, sizeof(errstr));
+ fputs(errstr, fmt_fp);
+ } else if (ch == '%' && fmt[1] == '%') {
+ ++fmt;
+ fputc(ch, fmt_fp);
+ fputc(ch, fmt_fp);
+ } else {
+ fputc(ch, fmt_fp);
+ }
+ }
+
+ /* Null terminate if room */
+ fputc(0, fmt_fp);
+ fclose(fmt_fp);
+
+ /* Guarantee null termination */
+ fmt_cpy[sizeof(fmt_cpy) - 1] = '\0';
+
+ fmt = fmt_cpy;
+ }
+
+ (void)vfprintf(fp, fmt, ap);
+ (void)fclose(fp);
+
+ cnt = sizeof(tbuf) - tbuf_cookie.left;
+
+ /* Remove a trailing newline */
+ if (tbuf[cnt - 1] == '\n')
+ cnt--;
+
+ /* Output to stderr if requested. */
+ if (LogStat & LOG_PERROR) {
+ struct iovec iov[2];
+ struct iovec *v = iov;
+
+ v->iov_base = stdp;
+ v->iov_len = cnt - (stdp - tbuf);
+ ++v;
+ v->iov_base = "\n";
+ v->iov_len = 1;
+ (void)_writev(STDERR_FILENO, iov, 2);
+ }
+
+ /* Get connected, output the message to the local logger. */
+ if (!opened)
+ openlog_unlocked(LogTag, LogStat | LOG_NDELAY, 0);
+ connectlog();
+
+ /*
+ * If the send() failed, there are two likely scenarios:
+ * 1) syslogd was restarted
+ * 2) /var/run/log is out of socket buffer space, which
+ * in most cases means local DoS.
+ * We attempt to reconnect to /var/run/log[priv] to take care of
+ * case #1 and keep send()ing data to cover case #2
+ * to give syslogd a chance to empty its socket buffer.
+ *
+ * If we are working with a priveleged socket, then take
+ * only one attempt, because we don't want to freeze a
+ * critical application like su(1) or sshd(8).
+ *
+ */
+
+ if (send(LogFile, tbuf, cnt, 0) < 0) {
+ if (errno != ENOBUFS) {
+ disconnectlog();
+ connectlog();
+ }
+ do {
+ if (status == CONNPRIV)
+ break;
+ _usleep(1);
+ if (send(LogFile, tbuf, cnt, 0) >= 0) {
+ THREAD_UNLOCK();
+ return;
+ }
+ } while (errno == ENOBUFS);
+ } else {
+ THREAD_UNLOCK();
+ return;
+ }
+
+ /*
+ * Output the message to the console; try not to block
+ * as a blocking console should not stop other processes.
+ * Make sure the error reported is the one from the syslogd failure.
+ */
+ if (LogStat & LOG_CONS &&
+ (fd = _open(_PATH_CONSOLE, O_WRONLY|O_NONBLOCK, 0)) >= 0) {
+ struct iovec iov[2];
+ struct iovec *v = iov;
+
+ p = strchr(tbuf, '>') + 1;
+ v->iov_base = p;
+ v->iov_len = cnt - (p - tbuf);
+ ++v;
+ v->iov_base = "\r\n";
+ v->iov_len = 2;
+ (void)_writev(fd, iov, 2);
+ (void)_close(fd);
+ }
+
+ THREAD_UNLOCK();
+}
+
+/* Should be called with mutex acquired */
+static void
+disconnectlog(void)
+{
+ /*
+ * If the user closed the FD and opened another in the same slot,
+ * that's their problem. They should close it before calling on
+ * system services.
+ */
+ if (LogFile != -1) {
+ _close(LogFile);
+ LogFile = -1;
+ }
+ status = NOCONN; /* retry connect */
+}
+
+/* Should be called with mutex acquired */
+static void
+connectlog(void)
+{
+ struct sockaddr_un SyslogAddr; /* AF_UNIX address of local logger */
+
+ if (LogFile == -1) {
+ if ((LogFile = _socket(AF_UNIX, SOCK_DGRAM, 0)) == -1)
+ return;
+ (void)_fcntl(LogFile, F_SETFD, FD_CLOEXEC);
+ }
+ if (LogFile != -1 && status == NOCONN) {
+ SyslogAddr.sun_len = sizeof(SyslogAddr);
+ SyslogAddr.sun_family = AF_UNIX;
+
+ /*
+ * First try priveleged socket. If no success,
+ * then try default socket.
+ */
+ (void)strncpy(SyslogAddr.sun_path, _PATH_LOG_PRIV,
+ sizeof SyslogAddr.sun_path);
+ if (_connect(LogFile, (struct sockaddr *)&SyslogAddr,
+ sizeof(SyslogAddr)) != -1)
+ status = CONNPRIV;
+
+ if (status == NOCONN) {
+ (void)strncpy(SyslogAddr.sun_path, _PATH_LOG,
+ sizeof SyslogAddr.sun_path);
+ if (_connect(LogFile, (struct sockaddr *)&SyslogAddr,
+ sizeof(SyslogAddr)) != -1)
+ status = CONNDEF;
+ }
+
+ if (status == NOCONN) {
+ /*
+ * Try the old "/dev/log" path, for backward
+ * compatibility.
+ */
+ (void)strncpy(SyslogAddr.sun_path, _PATH_OLDLOG,
+ sizeof SyslogAddr.sun_path);
+ if (_connect(LogFile, (struct sockaddr *)&SyslogAddr,
+ sizeof(SyslogAddr)) != -1)
+ status = CONNDEF;
+ }
+
+ if (status == NOCONN) {
+ (void)_close(LogFile);
+ LogFile = -1;
+ }
+ }
+}
+
+static void
+openlog_unlocked(const char *ident, int logstat, int logfac)
+{
+ if (ident != NULL)
+ LogTag = ident;
+ LogStat = logstat;
+ if (logfac != 0 && (logfac &~ LOG_FACMASK) == 0)
+ LogFacility = logfac;
+
+ if (LogStat & LOG_NDELAY) /* open immediately */
+ connectlog();
+
+ opened = 1; /* ident and facility has been set */
+}
+
+void
+openlog(const char *ident, int logstat, int logfac)
+{
+ THREAD_LOCK();
+ openlog_unlocked(ident, logstat, logfac);
+ THREAD_UNLOCK();
+}
+
+
+void
+closelog(void)
+{
+ THREAD_LOCK();
+ (void)_close(LogFile);
+ LogFile = -1;
+ LogTag = NULL;
+ status = NOCONN;
+ THREAD_UNLOCK();
+}
+
+/* setlogmask -- set the log mask level */
+int
+setlogmask(int pmask)
+{
+ int omask;
+
+ THREAD_LOCK();
+ omask = LogMask;
+ if (pmask != 0)
+ LogMask = pmask;
+ THREAD_UNLOCK();
+ return (omask);
+}
diff --git a/lib/libc/gen/tcgetpgrp.3 b/lib/libc/gen/tcgetpgrp.3
new file mode 100644
index 0000000..ba4d084
--- /dev/null
+++ b/lib/libc/gen/tcgetpgrp.3
@@ -0,0 +1,78 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)tcgetpgrp.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt TCGETPGRP 3
+.Os
+.Sh NAME
+.Nm tcgetpgrp
+.Nd get foreground process group ID
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In unistd.h
+.Ft pid_t
+.Fn tcgetpgrp "int fd"
+.Sh DESCRIPTION
+The
+.Fn tcgetpgrp
+function returns the value of the process group ID of the foreground
+process group associated with the terminal device.
+If there is no foreground process group,
+.Fn tcgetpgrp
+returns an invalid process ID.
+.Sh ERRORS
+If an error occurs,
+.Fn tcgetpgrp
+returns -1 and the global variable
+.Va errno
+is set to indicate the error, as follows:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa fd
+argument is not a valid file descriptor.
+.It Bq Er ENOTTY
+The calling process does not have a controlling terminal or the
+underlying terminal device represented by
+.Fa fd
+is not the controlling terminal.
+.El
+.Sh SEE ALSO
+.Xr setpgid 2 ,
+.Xr setsid 2 ,
+.Xr tcsetpgrp 3
+.Sh STANDARDS
+The
+.Fn tcgetpgrp
+function is expected to be compliant with the
+.St -p1003.1-88
+specification.
diff --git a/lib/libc/gen/tcgetsid.3 b/lib/libc/gen/tcgetsid.3
new file mode 100644
index 0000000..60bff8d
--- /dev/null
+++ b/lib/libc/gen/tcgetsid.3
@@ -0,0 +1,72 @@
+.\" Copyright (c) 2008 David Xu <davidxu@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 15, 2008
+.Dt TCGETSID 3
+.Os
+.Sh NAME
+.Nm tcgetsid
+.Nd get session ID associated with a controlling terminal
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In termios.h
+.Ft pid_t
+.Fn tcgetsid "int fd"
+.Sh DESCRIPTION
+The
+.Fn tcgetsid
+function returns the process group ID of the session leader for a
+controlling terminal specified by
+.Fa fd .
+.Sh ERRORS
+If an error occurs,
+.Fn tcgetsid
+returns -1 and the global variable
+.Va errno
+is set to indicate the error, as follows:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa fd
+argument is not a valid file descriptor.
+.It Bq Er ENOTTY
+The calling process does not have a controlling terminal or the
+underlying terminal device represented by
+.Fa fd
+is not the controlling terminal.
+.El
+.Sh SEE ALSO
+.Xr getsid 2 ,
+.Xr setsid 2 ,
+.Xr tcgetpgrp 3 ,
+.Xr tcsetsid 3
+.Sh STANDARDS
+The
+.Fn tcgetsid
+function conforms to
+.St -xpg4.2 .
diff --git a/lib/libc/gen/tcsendbreak.3 b/lib/libc/gen/tcsendbreak.3
new file mode 100644
index 0000000..a7e86d0
--- /dev/null
+++ b/lib/libc/gen/tcsendbreak.3
@@ -0,0 +1,153 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)tcsendbreak.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt TCSENDBREAK 3
+.Os
+.Sh NAME
+.Nm tcsendbreak ,
+.Nm tcdrain ,
+.Nm tcflush ,
+.Nm tcflow
+.Nd line control functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In termios.h
+.Ft int
+.Fn tcdrain "int fd"
+.Ft int
+.Fn tcflow "int fd" "int action"
+.Ft int
+.Fn tcflush "int fd" "int action"
+.Ft int
+.Fn tcsendbreak "int fd" "int len"
+.Sh DESCRIPTION
+The
+.Fn tcdrain
+function waits until all output written to the terminal referenced by
+.Fa fd
+has been transmitted to the terminal.
+.Pp
+The
+.Fn tcflow
+function suspends transmission of data to or the reception of data from
+the terminal referenced by
+.Fa fd
+depending on the value of
+.Fa action .
+The value of
+.Fa action
+must be one of the following:
+.Bl -tag -width "TCIOFF"
+.It Fa TCOOFF
+Suspend output.
+.It Fa TCOON
+Restart suspended output.
+.It Fa TCIOFF
+Transmit a STOP character, which is intended to cause the terminal to stop
+transmitting data to the system.
+(See the description of IXOFF in the
+.Ql Input Modes
+section of
+.Xr termios 4 ) .
+.It Fa TCION
+Transmit a START character, which is intended to cause the terminal to start
+transmitting data to the system.
+(See the description of IXOFF in the
+.Ql Input Modes
+section of
+.Xr termios 4 ) .
+.El
+.Pp
+The
+.Fn tcflush
+function discards any data written to the terminal referenced by
+.Fa fd
+which has not been transmitted to the terminal, or any data received
+from the terminal but not yet read, depending on the value of
+.Fa action .
+The value of
+.Fa action
+must be one of the following:
+.Bl -tag -width "TCIOFLUSH"
+.It Fa TCIFLUSH
+Flush data received but not read.
+.It Fa TCOFLUSH
+Flush data written but not transmitted.
+.It Fa TCIOFLUSH
+Flush both data received but not read and data written but not transmitted.
+.El
+.Pp
+The
+.Fn tcsendbreak
+function transmits a continuous stream of zero-valued bits for four-tenths
+of a second to the terminal referenced by
+.Fa fd .
+The
+.Fa len
+argument is ignored in this implementation.
+.Sh RETURN VALUES
+Upon successful completion, all of these functions return a value of zero.
+.Sh ERRORS
+If any error occurs, a value of -1 is returned and the global variable
+.Va errno
+is set to indicate the error, as follows:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa fd
+argument is not a valid file descriptor.
+.It Bq Er EINVAL
+The
+.Fa action
+argument is not a proper value.
+.It Bq Er ENOTTY
+The file associated with
+.Fa fd
+is not a terminal.
+.It Bq Er EINTR
+A signal interrupted the
+.Fn tcdrain
+function.
+.El
+.Sh SEE ALSO
+.Xr tcsetattr 3 ,
+.Xr termios 4
+.Sh STANDARDS
+The
+.Fn tcsendbreak ,
+.Fn tcdrain ,
+.Fn tcflush
+and
+.Fn tcflow
+functions are expected to be compliant with the
+.St -p1003.1-88
+specification.
diff --git a/lib/libc/gen/tcsetattr.3 b/lib/libc/gen/tcsetattr.3
new file mode 100644
index 0000000..9be012e
--- /dev/null
+++ b/lib/libc/gen/tcsetattr.3
@@ -0,0 +1,340 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)tcsetattr.3 8.3 (Berkeley) 1/2/94
+.\" $FreeBSD$
+.\"
+.Dd January 2, 1994
+.Dt TCSETATTR 3
+.Os
+.Sh NAME
+.Nm cfgetispeed ,
+.Nm cfsetispeed ,
+.Nm cfgetospeed ,
+.Nm cfsetospeed ,
+.Nm cfsetspeed ,
+.Nm cfmakeraw ,
+.Nm cfmakesane ,
+.Nm tcgetattr ,
+.Nm tcsetattr
+.Nd manipulating the termios structure
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In termios.h
+.Ft speed_t
+.Fn cfgetispeed "const struct termios *t"
+.Ft int
+.Fn cfsetispeed "struct termios *t" "speed_t speed"
+.Ft speed_t
+.Fn cfgetospeed "const struct termios *t"
+.Ft int
+.Fn cfsetospeed "struct termios *t" "speed_t speed"
+.Ft int
+.Fn cfsetspeed "struct termios *t" "speed_t speed"
+.Ft void
+.Fn cfmakeraw "struct termios *t"
+.Ft void
+.Fn cfmakesane "struct termios *t"
+.Ft int
+.Fn tcgetattr "int fd" "struct termios *t"
+.Ft int
+.Fn tcsetattr "int fd" "int action" "const struct termios *t"
+.Sh DESCRIPTION
+The
+.Fn cfmakeraw ,
+.Fn cfmakesane ,
+.Fn tcgetattr
+and
+.Fn tcsetattr
+functions are provided for getting and setting the termios structure.
+.Pp
+The
+.Fn cfgetispeed ,
+.Fn cfsetispeed ,
+.Fn cfgetospeed ,
+.Fn cfsetospeed
+and
+.Fn cfsetspeed
+functions are provided for getting and setting the baud rate values in
+the termios structure.
+The effects of the functions on the terminal as described below
+do not become effective, nor are all errors detected, until the
+.Fn tcsetattr
+function is called.
+Certain values for baud rates set in the termios structure and passed to
+.Fn tcsetattr
+have special meanings.
+These are discussed in the portion of the manual page that describes the
+.Fn tcsetattr
+function.
+.Sh GETTING AND SETTING THE BAUD RATE
+The input and output baud rates are found in the termios structure.
+The unsigned integer
+.Li speed_t
+is typedef'd in the include file
+.In termios.h .
+The value of the integer corresponds directly to the baud rate being
+represented, however, the following symbolic values are defined.
+.Bd -literal
+#define B0 0
+#define B50 50
+#define B75 75
+#define B110 110
+#define B134 134
+#define B150 150
+#define B200 200
+#define B300 300
+#define B600 600
+#define B1200 1200
+#define B1800 1800
+#define B2400 2400
+#define B4800 4800
+#define B9600 9600
+#define B19200 19200
+#define B38400 38400
+#ifndef _POSIX_SOURCE
+#define EXTA 19200
+#define EXTB 38400
+#endif /*_POSIX_SOURCE */
+.Ed
+.Pp
+The
+.Fn cfgetispeed
+function returns the input baud rate in the termios structure referenced by
+.Fa tp .
+.Pp
+The
+.Fn cfsetispeed
+function sets the input baud rate in the termios structure referenced by
+.Fa tp
+to
+.Fa speed .
+.Pp
+The
+.Fn cfgetospeed
+function returns the output baud rate in the termios structure referenced by
+.Fa tp .
+.Pp
+The
+.Fn cfsetospeed
+function sets the output baud rate in the termios structure referenced by
+.Fa tp
+to
+.Fa speed .
+.Pp
+The
+.Fn cfsetspeed
+function sets both the input and output baud rate in the termios structure
+referenced by
+.Fa tp
+to
+.Fa speed .
+.Pp
+Upon successful completion, the functions
+.Fn cfsetispeed ,
+.Fn cfsetospeed ,
+and
+.Fn cfsetspeed
+return a value of 0.
+Otherwise, a value of -1 is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh GETTING AND SETTING THE TERMIOS STATE
+This section describes the functions that are used to control the general
+terminal interface.
+Unless otherwise noted for a specific command, these functions are restricted
+from use by background processes.
+Attempts to perform these operations shall cause the process group to be sent
+a SIGTTOU signal.
+If the calling process is blocking or ignoring SIGTTOU signals, the process
+is allowed to perform the operation and the SIGTTOU signal is not sent.
+.Pp
+In all the functions, although
+.Fa fd
+is an open file descriptor, the functions affect the underlying terminal
+file, not just the open file description associated with the particular
+file descriptor.
+.Pp
+The
+.Fn cfmakeraw
+function sets the flags stored in the termios structure to a state disabling
+all input and output processing, giving a
+.Dq raw I/O path ,
+while the
+.Fn cfmakesane
+function sets them to a state similar to those of a newly created
+terminal device.
+It should be noted that there is no function to reverse this effect.
+This is because there are a variety of processing options that could be
+re-enabled and the correct method is for an application to snapshot the
+current terminal state using the function
+.Fn tcgetattr ,
+setting raw or sane mode with
+.Fn cfmakeraw
+or
+.Fn cfmakesane
+and the subsequent
+.Fn tcsetattr ,
+and then using another
+.Fn tcsetattr
+with the saved state to revert to the previous terminal state.
+.Pp
+The
+.Fn tcgetattr
+function copies the parameters associated with the terminal referenced
+by
+.Fa fd
+in the termios structure referenced by
+.Fa tp .
+This function is allowed from a background process, however, the terminal
+attributes may be subsequently changed by a foreground process.
+.Pp
+The
+.Fn tcsetattr
+function sets the parameters associated with the terminal from the
+termios structure referenced by
+.Fa tp .
+The
+.Fa action
+argument is created by
+.Em or Ns 'ing
+the following values, as specified in the include file
+.In termios.h .
+.Bl -tag -width "TCSADRAIN"
+.It Fa TCSANOW
+The change occurs immediately.
+.It Fa TCSADRAIN
+The change occurs after all output written to
+.Fa fd
+has been transmitted to the terminal.
+This value of
+.Fa action
+should be used when changing parameters that affect output.
+.It Fa TCSAFLUSH
+The change occurs after all output written to
+.Fa fd
+has been transmitted to the terminal.
+Additionally, any input that has been received but not read is discarded.
+.It Fa TCSASOFT
+If this value is
+.Em or Ns 'ed
+into the
+.Fa action
+value, the values of the
+.Va c_cflag ,
+.Va c_ispeed ,
+and
+.Va c_ospeed
+fields are ignored.
+.El
+.Pp
+The 0 baud rate is used to terminate the connection.
+If 0 is specified as the output speed to the function
+.Fn tcsetattr ,
+modem control will no longer be asserted on the terminal, disconnecting
+the terminal.
+.Pp
+If zero is specified as the input speed to the function
+.Fn tcsetattr ,
+the input baud rate will be set to the same value as that specified by
+the output baud rate.
+.Pp
+If
+.Fn tcsetattr
+is unable to make any of the requested changes, it returns -1 and
+sets errno.
+Otherwise, it makes all of the requested changes it can.
+If the specified input and output baud rates differ and are a combination
+that is not supported, neither baud rate is changed.
+.Pp
+Upon successful completion, the functions
+.Fn tcgetattr
+and
+.Fn tcsetattr
+return a value of 0.
+Otherwise, they
+return -1 and the global variable
+.Va errno
+is set to indicate the error, as follows:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa fd
+argument to
+.Fn tcgetattr
+or
+.Fn tcsetattr
+was not a valid file descriptor.
+.It Bq Er EINTR
+The
+.Fn tcsetattr
+function was interrupted by a signal.
+.It Bq Er EINVAL
+The
+.Fa action
+argument to the
+.Fn tcsetattr
+function was not valid, or an attempt was made to change an attribute
+represented in the termios structure to an unsupported value.
+.It Bq Er ENOTTY
+The file associated with the
+.Fa fd
+argument to
+.Fn tcgetattr
+or
+.Fn tcsetattr
+is not a terminal.
+.El
+.Sh SEE ALSO
+.Xr tcsendbreak 3 ,
+.Xr termios 4
+.Sh STANDARDS
+The
+.Fn cfgetispeed ,
+.Fn cfsetispeed ,
+.Fn cfgetospeed ,
+.Fn cfsetospeed ,
+.Fn tcgetattr
+and
+.Fn tcsetattr
+functions are expected to be compliant with the
+.St -p1003.1-88
+specification.
+The
+.Fn cfmakeraw ,
+.Fn cfmakesane
+and
+.Fn cfsetspeed
+functions,
+as well as the
+.Li TCSASOFT
+option to the
+.Fn tcsetattr
+function are extensions to the
+.St -p1003.1-88
+specification.
diff --git a/lib/libc/gen/tcsetpgrp.3 b/lib/libc/gen/tcsetpgrp.3
new file mode 100644
index 0000000..494731c
--- /dev/null
+++ b/lib/libc/gen/tcsetpgrp.3
@@ -0,0 +1,95 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)tcsetpgrp.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt TCSETPGRP 3
+.Os
+.Sh NAME
+.Nm tcsetpgrp
+.Nd set foreground process group ID
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In unistd.h
+.Ft int
+.Fn tcsetpgrp "int fd" "pid_t pgrp_id"
+.Sh DESCRIPTION
+If the process has a controlling terminal, the
+.Fn tcsetpgrp
+function sets the foreground process group ID associated with the
+terminal device to
+.Fa pgrp_id .
+The terminal device associated with
+.Fa fd
+must be the controlling terminal of the calling process and the
+controlling terminal must be currently associated with the session
+of the calling process.
+The value of
+.Fa pgrp_id
+must be the same as the process group ID of a process in the same
+session as the calling process.
+.Sh RETURN VALUES
+.Rv -std tcsetpgrp
+.Sh ERRORS
+The
+.Fn tcsetpgrp
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa fd
+argument is not a valid file descriptor.
+.It Bq Er EINVAL
+An invalid value of
+.Fa pgrp_id
+was specified.
+.It Bq Er ENOTTY
+The calling process does not have a controlling terminal, or the file
+represented by
+.Fa fd
+is not the controlling terminal, or the controlling terminal is no
+longer associated with the session of the calling process.
+.It Bq Er EPERM
+The
+.Fa pgrp_id
+argument does not match the process group ID of a process in the same
+session as the calling process.
+.El
+.Sh SEE ALSO
+.Xr setpgid 2 ,
+.Xr setsid 2 ,
+.Xr tcgetpgrp 3
+.Sh STANDARDS
+The
+.Fn tcsetpgrp
+function is expected to be compliant with the
+.St -p1003.1-88
+specification.
diff --git a/lib/libc/gen/tcsetsid.3 b/lib/libc/gen/tcsetsid.3
new file mode 100644
index 0000000..d0f1d98
--- /dev/null
+++ b/lib/libc/gen/tcsetsid.3
@@ -0,0 +1,92 @@
+.\" Copyright (c) 2009 Ed Schouten <ed@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd May 4, 2009
+.Dt TCSETSID 3
+.Os
+.Sh NAME
+.Nm tcsetsid
+.Nd set session ID associated with a controlling terminal
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In termios.h
+.Ft int
+.Fn tcsetsid "int fd" "pid_t pid"
+.Sh DESCRIPTION
+The
+.Fn tcsetsid
+function sets associates a session identified by
+.Fa pid
+with a controlling terminal specified by
+.Fa fd .
+.Pp
+This implementation only allows the controlling terminal to be changed
+by the session leader itself.
+This implies that
+.Fa pid
+always has to be equal to the process ID.
+.Pp
+It is unsupported to associate with a terminal that already has an
+associated session.
+Conversely, it is also unsupported to associate to a terminal when
+the session is already associated with a different terminal.
+.Sh ERRORS
+If an error occurs,
+.Fn tcsetsid
+returns -1 and the global variable
+.Va errno
+is set to indicate the error, as follows:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa fd
+argument is not a valid file descriptor.
+.It Bq Er ENOTTY
+The file descriptor represented by
+.Fa fd
+is not a terminal.
+.It Bq Er EINVAL
+The
+.Fa pid
+argument is not equal to the session ID of the calling process.
+.It Bq Er EPERM
+The calling process is not a session leader.
+.It Bq Er EPERM
+The session already has an associated terminal or the terminal already
+has an associated session.
+.El
+.Sh SEE ALSO
+.Xr getsid 2 ,
+.Xr setsid 2 ,
+.Xr tcgetpgrp 3 ,
+.Xr tcgetsid 3
+.Sh HISTORY
+A
+.Fn tcsetsid
+function first appeared in QNX.
+It does not comply to any standard.
diff --git a/lib/libc/gen/telldir.c b/lib/libc/gen/telldir.c
new file mode 100644
index 0000000..c217333
--- /dev/null
+++ b/lib/libc/gen/telldir.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)telldir.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <dirent.h>
+#include <pthread.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+#include "telldir.h"
+
+/*
+ * The option SINGLEUSE may be defined to say that a telldir
+ * cookie may be used only once before it is freed. This option
+ * is used to avoid having memory usage grow without bound.
+ */
+#define SINGLEUSE
+
+/*
+ * return a pointer into a directory
+ */
+long
+telldir(dirp)
+ DIR *dirp;
+{
+ struct ddloc *lp;
+
+ if ((lp = (struct ddloc *)malloc(sizeof(struct ddloc))) == NULL)
+ return (-1);
+ if (__isthreaded)
+ _pthread_mutex_lock(&dirp->dd_lock);
+ lp->loc_index = dirp->dd_td->td_loccnt++;
+ lp->loc_seek = dirp->dd_seek;
+ lp->loc_loc = dirp->dd_loc;
+ LIST_INSERT_HEAD(&dirp->dd_td->td_locq, lp, loc_lqe);
+ if (__isthreaded)
+ _pthread_mutex_unlock(&dirp->dd_lock);
+ return (lp->loc_index);
+}
+
+/*
+ * seek to an entry in a directory.
+ * Only values returned by "telldir" should be passed to seekdir.
+ */
+void
+_seekdir(dirp, loc)
+ DIR *dirp;
+ long loc;
+{
+ struct ddloc *lp;
+ struct dirent *dp;
+
+ LIST_FOREACH(lp, &dirp->dd_td->td_locq, loc_lqe) {
+ if (lp->loc_index == loc)
+ break;
+ }
+ if (lp == NULL)
+ return;
+ if (lp->loc_loc == dirp->dd_loc && lp->loc_seek == dirp->dd_seek)
+ goto found;
+ (void) lseek(dirp->dd_fd, (off_t)lp->loc_seek, SEEK_SET);
+ dirp->dd_seek = lp->loc_seek;
+ dirp->dd_loc = 0;
+ while (dirp->dd_loc < lp->loc_loc) {
+ dp = _readdir_unlocked(dirp, 0);
+ if (dp == NULL)
+ break;
+ }
+found:
+#ifdef SINGLEUSE
+ LIST_REMOVE(lp, loc_lqe);
+ free((caddr_t)lp);
+#endif
+}
+
+/*
+ * Reclaim memory for telldir cookies which weren't used.
+ */
+void
+_reclaim_telldir(dirp)
+ DIR *dirp;
+{
+ struct ddloc *lp;
+ struct ddloc *templp;
+
+ lp = LIST_FIRST(&dirp->dd_td->td_locq);
+ while (lp != NULL) {
+ templp = lp;
+ lp = LIST_NEXT(lp, loc_lqe);
+ free(templp);
+ }
+ LIST_INIT(&dirp->dd_td->td_locq);
+}
diff --git a/lib/libc/gen/telldir.h b/lib/libc/gen/telldir.h
new file mode 100644
index 0000000..ef930d2
--- /dev/null
+++ b/lib/libc/gen/telldir.h
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2000
+ * Daniel Eischen. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _TELLDIR_H_
+#define _TELLDIR_H_
+
+#include <sys/queue.h>
+
+/*
+ * One of these structures is malloced to describe the current directory
+ * position each time telldir is called. It records the current magic
+ * cookie returned by getdirentries and the offset within the buffer
+ * associated with that return value.
+ */
+struct ddloc {
+ LIST_ENTRY(ddloc) loc_lqe; /* entry in list */
+ long loc_index; /* key associated with structure */
+ long loc_seek; /* magic cookie returned by getdirentries */
+ long loc_loc; /* offset of entry in buffer */
+};
+
+/*
+ * One of these structures is malloced for each DIR to record telldir
+ * positions.
+ */
+struct _telldir {
+ LIST_HEAD(, ddloc) td_locq; /* list of locations */
+ long td_loccnt; /* index of entry for sequential readdir's */
+};
+
+struct dirent *_readdir_unlocked(DIR *, int);
+void _reclaim_telldir(DIR *);
+void _seekdir(DIR *, long);
+
+#endif
diff --git a/lib/libc/gen/termios.c b/lib/libc/gen/termios.c
new file mode 100644
index 0000000..7e9f169
--- /dev/null
+++ b/lib/libc/gen/termios.c
@@ -0,0 +1,265 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)termios.c 8.2 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+
+#include <errno.h>
+#include <string.h>
+#define TTYDEFCHARS
+#include <termios.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+int
+tcgetattr(int fd, struct termios *t)
+{
+
+ return (_ioctl(fd, TIOCGETA, t));
+}
+
+int
+tcsetattr(int fd, int opt, const struct termios *t)
+{
+ struct termios localterm;
+
+ if (opt & TCSASOFT) {
+ localterm = *t;
+ localterm.c_cflag |= CIGNORE;
+ t = &localterm;
+ }
+ switch (opt & ~TCSASOFT) {
+ case TCSANOW:
+ return (_ioctl(fd, TIOCSETA, t));
+ case TCSADRAIN:
+ return (_ioctl(fd, TIOCSETAW, t));
+ case TCSAFLUSH:
+ return (_ioctl(fd, TIOCSETAF, t));
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+}
+
+int
+tcsetpgrp(int fd, pid_t pgrp)
+{
+ int s;
+
+ s = pgrp;
+ return (_ioctl(fd, TIOCSPGRP, &s));
+}
+
+pid_t
+tcgetpgrp(int fd)
+{
+ int s;
+
+ if (_ioctl(fd, TIOCGPGRP, &s) < 0)
+ return ((pid_t)-1);
+
+ return ((pid_t)s);
+}
+
+pid_t
+tcgetsid(int fd)
+{
+ int s;
+
+ if (_ioctl(fd, TIOCGSID, &s) < 0)
+ return ((pid_t)-1);
+
+ return ((pid_t)s);
+}
+
+int
+tcsetsid(int fd, pid_t pid)
+{
+
+ if (pid != getsid(0)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (_ioctl(fd, TIOCSCTTY, NULL));
+}
+
+speed_t
+cfgetospeed(const struct termios *t)
+{
+
+ return (t->c_ospeed);
+}
+
+speed_t
+cfgetispeed(const struct termios *t)
+{
+
+ return (t->c_ispeed);
+}
+
+int
+cfsetospeed(struct termios *t, speed_t speed)
+{
+
+ t->c_ospeed = speed;
+ return (0);
+}
+
+int
+cfsetispeed(struct termios *t, speed_t speed)
+{
+
+ t->c_ispeed = speed;
+ return (0);
+}
+
+int
+cfsetspeed(struct termios *t, speed_t speed)
+{
+
+ t->c_ispeed = t->c_ospeed = speed;
+ return (0);
+}
+
+/*
+ * Make a pre-existing termios structure into "raw" mode: character-at-a-time
+ * mode with no characters interpreted, 8-bit data path.
+ */
+void
+cfmakeraw(struct termios *t)
+{
+
+ t->c_iflag &= ~(IMAXBEL|IXOFF|INPCK|BRKINT|PARMRK|ISTRIP|INLCR|IGNCR|ICRNL|IXON|IGNPAR);
+ t->c_iflag |= IGNBRK;
+ t->c_oflag &= ~OPOST;
+ t->c_lflag &= ~(ECHO|ECHOE|ECHOK|ECHONL|ICANON|ISIG|IEXTEN|NOFLSH|TOSTOP|PENDIN);
+ t->c_cflag &= ~(CSIZE|PARENB);
+ t->c_cflag |= CS8|CREAD;
+ t->c_cc[VMIN] = 1;
+ t->c_cc[VTIME] = 0;
+}
+
+/*
+ * Obtain a termios structure which is similar to the one provided by
+ * the kernel.
+ */
+void
+cfmakesane(struct termios *t)
+{
+
+ t->c_cflag = TTYDEF_CFLAG;
+ t->c_iflag = TTYDEF_IFLAG;
+ t->c_lflag = TTYDEF_LFLAG;
+ t->c_oflag = TTYDEF_OFLAG;
+ t->c_ispeed = TTYDEF_SPEED;
+ t->c_ospeed = TTYDEF_SPEED;
+ memcpy(&t->c_cc, ttydefchars, sizeof ttydefchars);
+}
+
+int
+tcsendbreak(int fd, int len __unused)
+{
+ struct timeval sleepytime;
+
+ sleepytime.tv_sec = 0;
+ sleepytime.tv_usec = 400000;
+ if (_ioctl(fd, TIOCSBRK, 0) == -1)
+ return (-1);
+ (void)_select(0, 0, 0, 0, &sleepytime);
+ if (_ioctl(fd, TIOCCBRK, 0) == -1)
+ return (-1);
+ return (0);
+}
+
+int
+__tcdrain(int fd)
+{
+ return (_ioctl(fd, TIOCDRAIN, 0));
+}
+
+__weak_reference(__tcdrain, tcdrain);
+__weak_reference(__tcdrain, _tcdrain);
+
+int
+tcflush(int fd, int which)
+{
+ int com;
+
+ switch (which) {
+ case TCIFLUSH:
+ com = FREAD;
+ break;
+ case TCOFLUSH:
+ com = FWRITE;
+ break;
+ case TCIOFLUSH:
+ com = FREAD | FWRITE;
+ break;
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+ return (_ioctl(fd, TIOCFLUSH, &com));
+}
+
+int
+tcflow(int fd, int action)
+{
+ struct termios term;
+ u_char c;
+
+ switch (action) {
+ case TCOOFF:
+ return (_ioctl(fd, TIOCSTOP, 0));
+ case TCOON:
+ return (_ioctl(fd, TIOCSTART, 0));
+ case TCION:
+ case TCIOFF:
+ if (tcgetattr(fd, &term) == -1)
+ return (-1);
+ c = term.c_cc[action == TCIOFF ? VSTOP : VSTART];
+ if (c != _POSIX_VDISABLE && _write(fd, &c, sizeof(c)) == -1)
+ return (-1);
+ return (0);
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+ /* NOTREACHED */
+}
diff --git a/lib/libc/gen/time.3 b/lib/libc/gen/time.3
new file mode 100644
index 0000000..d022e06
--- /dev/null
+++ b/lib/libc/gen/time.3
@@ -0,0 +1,101 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)time.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd July 18, 2003
+.Dt TIME 3
+.Os
+.Sh NAME
+.Nm time
+.Nd get time of day
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In time.h
+.Ft time_t
+.Fn time "time_t *tloc"
+.Sh DESCRIPTION
+The
+.Fn time
+function
+returns the value of time in seconds since 0 hours, 0 minutes,
+0 seconds, January 1, 1970, Coordinated Universal Time.
+If an error occurs,
+.Fn time
+returns the value
+.Po Vt time_t Pc Ns \-1 .
+.Pp
+The return value is also stored in
+.No \&* Ns Va tloc ,
+provided that
+.Va tloc
+is non-null.
+.Sh ERRORS
+The
+.Fn time
+function may fail for any of the reasons described in
+.Xr gettimeofday 2 .
+.Sh SEE ALSO
+.Xr clock_gettime 2 ,
+.Xr gettimeofday 2 ,
+.Xr ctime 3
+.Sh STANDARDS
+The
+.Nm
+function conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+A
+.Fn time
+function appeared in
+.At v6 .
+.Sh BUGS
+Neither
+.St -isoC-99
+nor
+.St -p1003.1-2001
+requires
+.Fn time
+to set
+.Va errno
+on failure; thus, it is impossible for an application to distinguish
+the valid time value \-1 (representing the last UTC second of 1969)
+from the error return value.
+.Pp
+Systems conforming to earlier versions of the C and
+.Tn POSIX
+standards (including older versions of
+.Fx )
+did not set
+.No \&* Ns Va tloc
+in the error case.
diff --git a/lib/libc/gen/time.c b/lib/libc/gen/time.c
new file mode 100644
index 0000000..214dfce
--- /dev/null
+++ b/lib/libc/gen/time.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)time.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/time.h>
+
+time_t
+time(time_t *t)
+{
+ struct timespec tt;
+ time_t retval;
+
+ if (clock_gettime(CLOCK_SECOND, &tt) < 0)
+ retval = -1;
+ else
+ retval = tt.tv_sec;
+ if (t != NULL)
+ *t = retval;
+ return (retval);
+}
diff --git a/lib/libc/gen/times.3 b/lib/libc/gen/times.3
new file mode 100644
index 0000000..a77c69f
--- /dev/null
+++ b/lib/libc/gen/times.3
@@ -0,0 +1,145 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)times.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd December 1, 2008
+.Dt TIMES 3
+.Os
+.Sh NAME
+.Nm times
+.Nd process times
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/times.h
+.Ft clock_t
+.Fn times "struct tms *tp"
+.Sh DESCRIPTION
+.Bf -symbolic
+This interface is obsoleted by
+.Xr getrusage 2
+and
+.Xr gettimeofday 2 .
+.Ef
+.Pp
+The
+.Fn times
+function returns the value of time in
+.Dv CLK_TCK Ns 's
+of a second since the system startup time.
+The current value of
+.Dv CLK_TCK ,
+the frequency of the statistics clock in ticks per second, may be
+obtained through the
+.Xr sysconf 3
+interface.
+.Pp
+It also fills in the structure pointed to by
+.Fa tp
+with time-accounting information.
+.Pp
+The
+.Vt tms
+structure is defined as follows:
+.Bd -literal -offset indent
+struct tms {
+ clock_t tms_utime;
+ clock_t tms_stime;
+ clock_t tms_cutime;
+ clock_t tms_cstime;
+};
+.Ed
+.Pp
+The elements of this structure are defined as follows:
+.Bl -tag -width ".Va tms_cutime"
+.It Va tms_utime
+The
+.Tn CPU
+time charged for the execution of user instructions.
+.It Va tms_stime
+The
+.Tn CPU
+time charged for execution by the system on behalf of
+the process.
+.It Va tms_cutime
+The sum of the
+.Va tms_utime Ns s
+and
+.Va tms_cutime Ns s
+of the child processes.
+.It Va tms_cstime
+The sum of the
+.Fa tms_stime Ns s
+and
+.Fa tms_cstime Ns s
+of the child processes.
+.El
+.Pp
+All times are in
+.Dv CLK_TCK Ns 's
+of a second.
+.Pp
+The times of a terminated child process are included in the
+.Va tms_cutime
+and
+.Va tms_cstime
+elements of the parent when one of the
+.Xr wait 2
+functions returns the process ID of the terminated child to the parent.
+If an error occurs,
+.Fn times
+returns the value
+.Pq Po Vt clock_t Pc Ns \-1 ,
+and sets
+.Va errno
+to indicate the error.
+.Sh ERRORS
+The
+.Fn times
+function
+may fail and set the global variable
+.Va errno
+for any of the errors specified for the library
+routines
+.Xr getrusage 2
+and
+.Xr gettimeofday 2 .
+.Sh SEE ALSO
+.Xr time 1 ,
+.Xr getrusage 2 ,
+.Xr gettimeofday 2 ,
+.Xr wait 2 ,
+.Xr sysconf 3 ,
+.Xr clocks 7
+.Sh STANDARDS
+The
+.Fn times
+function
+conforms to
+.St -p1003.1-88 .
diff --git a/lib/libc/gen/times.c b/lib/libc/gen/times.c
new file mode 100644
index 0000000..936511e
--- /dev/null
+++ b/lib/libc/gen/times.c
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)times.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/times.h>
+#include <sys/resource.h>
+
+/*
+ * Convert usec to clock ticks; could do (usec * CLK_TCK) / 1000000,
+ * but this would overflow if we switch to nanosec.
+ */
+#define CONVTCK(r) (r.tv_sec * CLK_TCK + r.tv_usec / (1000000 / CLK_TCK))
+
+clock_t
+times(tp)
+ struct tms *tp;
+{
+ struct rusage ru;
+ struct timespec t;
+ clock_t c;
+
+ if (getrusage(RUSAGE_SELF, &ru) < 0)
+ return ((clock_t)-1);
+ tp->tms_utime = CONVTCK(ru.ru_utime);
+ tp->tms_stime = CONVTCK(ru.ru_stime);
+ if (getrusage(RUSAGE_CHILDREN, &ru) < 0)
+ return ((clock_t)-1);
+ tp->tms_cutime = CONVTCK(ru.ru_utime);
+ tp->tms_cstime = CONVTCK(ru.ru_stime);
+ if (clock_gettime(CLOCK_MONOTONIC, &t))
+ return ((clock_t)-1);
+ c = t.tv_sec * CLK_TCK + t.tv_nsec / (1000000000 / CLK_TCK);
+ return (c);
+}
diff --git a/lib/libc/gen/timezone.3 b/lib/libc/gen/timezone.3
new file mode 100644
index 0000000..dcf2665
--- /dev/null
+++ b/lib/libc/gen/timezone.3
@@ -0,0 +1,69 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)timezone.3 8.2 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd April 19, 1994
+.Dt TIMEZONE 3
+.Os
+.Sh NAME
+.Nm timezone
+.Nd return the timezone abbreviation
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Ft char *
+.Fn timezone "int zone" "int dst"
+.Sh DESCRIPTION
+.Bf Sy
+This interface is for compatibility only; it is impossible to reliably
+map timezone's arguments to a time zone abbreviation.
+See
+.Xr ctime 3 .
+.Ef
+.Pp
+The
+.Fn timezone
+function returns a pointer to a time zone abbreviation for the specified
+.Fa zone
+and
+.Fa dst
+values.
+The
+.Fa zone
+argument
+is the number of minutes west of GMT and
+.Fa dst
+is non-zero if daylight savings time is in effect.
+.Sh SEE ALSO
+.Xr ctime 3
+.Sh HISTORY
+A
+.Fn timezone
+function appeared in
+.At v7 .
diff --git a/lib/libc/gen/timezone.c b/lib/libc/gen/timezone.c
new file mode 100644
index 0000000..9b50e79
--- /dev/null
+++ b/lib/libc/gen/timezone.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)timezone.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define TZ_MAX_CHARS 255
+
+char *_tztab(int, int);
+
+/*
+ * timezone --
+ * The arguments are the number of minutes of time you are westward
+ * from Greenwich and whether DST is in effect. It returns a string
+ * giving the name of the local timezone. Should be replaced, in the
+ * application code, by a call to localtime.
+ */
+
+static char czone[TZ_MAX_CHARS]; /* space for zone name */
+
+char *
+timezone(int zone, int dst)
+{
+ char *beg,
+ *end;
+
+ if ( (beg = getenv("TZNAME")) ) { /* set in environment */
+ if ((end = strchr(beg, ','))) { /* "PST,PDT" */
+ if (dst)
+ return(++end);
+ *end = '\0';
+ (void)strncpy(czone,beg,sizeof(czone) - 1);
+ czone[sizeof(czone) - 1] = '\0';
+ *end = ',';
+ return(czone);
+ }
+ return(beg);
+ }
+ return(_tztab(zone,dst)); /* default: table or created zone */
+}
+
+static struct zone {
+ int offset;
+ char *stdzone;
+ char *dlzone;
+} zonetab[] = {
+ {-1*60, "MET", "MET DST"}, /* Middle European */
+ {-2*60, "EET", "EET DST"}, /* Eastern European */
+ {4*60, "AST", "ADT"}, /* Atlantic */
+ {5*60, "EST", "EDT"}, /* Eastern */
+ {6*60, "CST", "CDT"}, /* Central */
+ {7*60, "MST", "MDT"}, /* Mountain */
+ {8*60, "PST", "PDT"}, /* Pacific */
+#ifdef notdef
+ /* there's no way to distinguish this from WET */
+ {0, "GMT", 0}, /* Greenwich */
+#endif
+ {0*60, "WET", "WET DST"}, /* Western European */
+ {-10*60,"EST", "EST"}, /* Aust: Eastern */
+ {-10*60+30,"CST", "CST"}, /* Aust: Central */
+ {-8*60, "WST", 0}, /* Aust: Western */
+ {-1}
+};
+
+/*
+ * _tztab --
+ * check static tables or create a new zone name; broken out so that
+ * we can make a guess as to what the zone is if the standard tables
+ * aren't in place in /etc. DO NOT USE THIS ROUTINE OUTSIDE OF THE
+ * STANDARD LIBRARY.
+ */
+char *
+_tztab(int zone, int dst)
+{
+ struct zone *zp;
+ char sign;
+
+ for (zp = zonetab; zp->offset != -1;++zp) /* static tables */
+ if (zp->offset == zone) {
+ if (dst && zp->dlzone)
+ return(zp->dlzone);
+ if (!dst && zp->stdzone)
+ return(zp->stdzone);
+ }
+
+ if (zone < 0) { /* create one */
+ zone = -zone;
+ sign = '+';
+ }
+ else
+ sign = '-';
+ (void)snprintf(czone, sizeof(czone),
+ "GMT%c%d:%02d",sign,zone / 60,zone % 60);
+ return(czone);
+}
diff --git a/lib/libc/gen/tls.c b/lib/libc/gen/tls.c
new file mode 100644
index 0000000..466f957
--- /dev/null
+++ b/lib/libc/gen/tls.c
@@ -0,0 +1,327 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Define stubs for TLS internals so that programs and libraries can
+ * link. These functions will be replaced by functional versions at
+ * runtime from ld-elf.so.1.
+ */
+
+#include <sys/cdefs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <elf.h>
+
+#include "libc_private.h"
+
+/* Provided by jemalloc to avoid bootstrapping issues. */
+void *__jemalloc_a0malloc(size_t size);
+void *__jemalloc_a0calloc(size_t num, size_t size);
+void __jemalloc_a0free(void *ptr);
+
+__weak_reference(__libc_allocate_tls, _rtld_allocate_tls);
+__weak_reference(__libc_free_tls, _rtld_free_tls);
+
+#ifdef __i386__
+
+__weak_reference(___libc_tls_get_addr, ___tls_get_addr);
+__attribute__((__regparm__(1))) void * ___libc_tls_get_addr(void *);
+
+#endif
+
+void * __libc_tls_get_addr(void *);
+__weak_reference(__libc_tls_get_addr, __tls_get_addr);
+
+void *_rtld_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign);
+void _rtld_free_tls(void *tls, size_t tcbsize, size_t tcbalign);
+void *__libc_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign);
+void __libc_free_tls(void *tls, size_t tcbsize, size_t tcbalign);
+
+#if defined(__ia64__) || defined(__amd64__)
+#define TLS_TCB_ALIGN 16
+#elif defined(__powerpc__) || defined(__i386__) || defined(__arm__) || \
+ defined(__sparc64__) || defined(__mips__)
+#define TLS_TCB_ALIGN sizeof(void *)
+#else
+#error TLS_TCB_ALIGN undefined for target architecture
+#endif
+
+#if defined(__arm__) || defined(__ia64__) || defined(__mips__) || \
+ defined(__powerpc__)
+#define TLS_VARIANT_I
+#endif
+#if defined(__i386__) || defined(__amd64__) || defined(__sparc64__)
+#define TLS_VARIANT_II
+#endif
+
+#ifndef PIC
+
+#define round(size, align) \
+ (((size) + (align) - 1) & ~((align) - 1))
+
+static size_t tls_static_space;
+static size_t tls_init_size;
+static void *tls_init;
+#endif
+
+#ifdef __i386__
+
+/* GNU ABI */
+
+__attribute__((__regparm__(1)))
+void *
+___libc_tls_get_addr(void *ti __unused)
+{
+ return (0);
+}
+
+#endif
+
+void *
+__libc_tls_get_addr(void *ti __unused)
+{
+ return (0);
+}
+
+#ifndef PIC
+
+#ifdef TLS_VARIANT_I
+
+#define TLS_TCB_SIZE (2 * sizeof(void *))
+
+/*
+ * Free Static TLS using the Variant I method.
+ */
+void
+__libc_free_tls(void *tcb, size_t tcbsize, size_t tcbalign __unused)
+{
+ Elf_Addr *dtv;
+ Elf_Addr **tls;
+
+ tls = (Elf_Addr **)((Elf_Addr)tcb + tcbsize - TLS_TCB_SIZE);
+ dtv = tls[0];
+ __jemalloc_a0free(dtv);
+ __jemalloc_a0free(tcb);
+}
+
+/*
+ * Allocate Static TLS using the Variant I method.
+ */
+void *
+__libc_allocate_tls(void *oldtcb, size_t tcbsize, size_t tcbalign __unused)
+{
+ Elf_Addr *dtv;
+ Elf_Addr **tls;
+ char *tcb;
+
+ if (oldtcb != NULL && tcbsize == TLS_TCB_SIZE)
+ return (oldtcb);
+
+ tcb = __jemalloc_a0calloc(1, tls_static_space + tcbsize - TLS_TCB_SIZE);
+ tls = (Elf_Addr **)(tcb + tcbsize - TLS_TCB_SIZE);
+
+ if (oldtcb != NULL) {
+ memcpy(tls, oldtcb, tls_static_space);
+ __jemalloc_a0free(oldtcb);
+
+ /* Adjust the DTV. */
+ dtv = tls[0];
+ dtv[2] = (Elf_Addr)tls + TLS_TCB_SIZE;
+ } else {
+ dtv = __jemalloc_a0malloc(3 * sizeof(Elf_Addr));
+ tls[0] = dtv;
+ dtv[0] = 1;
+ dtv[1] = 1;
+ dtv[2] = (Elf_Addr)tls + TLS_TCB_SIZE;
+
+ if (tls_init_size > 0)
+ memcpy((void*)dtv[2], tls_init, tls_init_size);
+ if (tls_static_space > tls_init_size)
+ memset((void*)(dtv[2] + tls_init_size), 0,
+ tls_static_space - tls_init_size);
+ }
+
+ return(tcb);
+}
+
+#endif
+
+#ifdef TLS_VARIANT_II
+
+#define TLS_TCB_SIZE (3 * sizeof(Elf_Addr))
+
+/*
+ * Free Static TLS using the Variant II method.
+ */
+void
+__libc_free_tls(void *tcb, size_t tcbsize __unused, size_t tcbalign)
+{
+ size_t size;
+ Elf_Addr* dtv;
+ Elf_Addr tlsstart, tlsend;
+
+ /*
+ * Figure out the size of the initial TLS block so that we can
+ * find stuff which ___tls_get_addr() allocated dynamically.
+ */
+ size = round(tls_static_space, tcbalign);
+
+ dtv = ((Elf_Addr**)tcb)[1];
+ tlsend = (Elf_Addr) tcb;
+ tlsstart = tlsend - size;
+ __jemalloc_a0free((void*) tlsstart);
+ __jemalloc_a0free(dtv);
+}
+
+/*
+ * Allocate Static TLS using the Variant II method.
+ */
+void *
+__libc_allocate_tls(void *oldtls, size_t tcbsize, size_t tcbalign)
+{
+ size_t size;
+ char *tls;
+ Elf_Addr *dtv;
+ Elf_Addr segbase, oldsegbase;
+
+ size = round(tls_static_space, tcbalign);
+
+ if (tcbsize < 2 * sizeof(Elf_Addr))
+ tcbsize = 2 * sizeof(Elf_Addr);
+ tls = __jemalloc_a0calloc(1, size + tcbsize);
+ dtv = __jemalloc_a0malloc(3 * sizeof(Elf_Addr));
+
+ segbase = (Elf_Addr)(tls + size);
+ ((Elf_Addr*)segbase)[0] = segbase;
+ ((Elf_Addr*)segbase)[1] = (Elf_Addr) dtv;
+
+ dtv[0] = 1;
+ dtv[1] = 1;
+ dtv[2] = segbase - tls_static_space;
+
+ if (oldtls) {
+ /*
+ * Copy the static TLS block over whole.
+ */
+ oldsegbase = (Elf_Addr) oldtls;
+ memcpy((void *)(segbase - tls_static_space),
+ (const void *)(oldsegbase - tls_static_space),
+ tls_static_space);
+
+ /*
+ * We assume that this block was the one we created with
+ * allocate_initial_tls().
+ */
+ _rtld_free_tls(oldtls, 2*sizeof(Elf_Addr), sizeof(Elf_Addr));
+ } else {
+ memcpy((void *)(segbase - tls_static_space),
+ tls_init, tls_init_size);
+ memset((void *)(segbase - tls_static_space + tls_init_size),
+ 0, tls_static_space - tls_init_size);
+ }
+
+ return (void*) segbase;
+}
+
+#endif /* TLS_VARIANT_II */
+
+#else
+
+void *
+__libc_allocate_tls(void *oldtls __unused, size_t tcbsize __unused,
+ size_t tcbalign __unused)
+{
+ return (0);
+}
+
+void
+__libc_free_tls(void *tcb __unused, size_t tcbsize __unused,
+ size_t tcbalign __unused)
+{
+}
+
+#endif /* PIC */
+
+extern char **environ;
+
+void
+_init_tls()
+{
+#ifndef PIC
+ Elf_Addr *sp;
+ Elf_Auxinfo *aux, *auxp;
+ Elf_Phdr *phdr;
+ size_t phent, phnum;
+ int i;
+ void *tls;
+
+ sp = (Elf_Addr *) environ;
+ while (*sp++ != 0)
+ ;
+ aux = (Elf_Auxinfo *) sp;
+ phdr = 0;
+ phent = phnum = 0;
+ for (auxp = aux; auxp->a_type != AT_NULL; auxp++) {
+ switch (auxp->a_type) {
+ case AT_PHDR:
+ phdr = auxp->a_un.a_ptr;
+ break;
+
+ case AT_PHENT:
+ phent = auxp->a_un.a_val;
+ break;
+
+ case AT_PHNUM:
+ phnum = auxp->a_un.a_val;
+ break;
+ }
+ }
+ if (phdr == 0 || phent != sizeof(Elf_Phdr) || phnum == 0)
+ return;
+
+ for (i = 0; (unsigned) i < phnum; i++) {
+ if (phdr[i].p_type == PT_TLS) {
+ tls_static_space = round(phdr[i].p_memsz,
+ phdr[i].p_align);
+ tls_init_size = phdr[i].p_filesz;
+ tls_init = (void*) phdr[i].p_vaddr;
+ }
+ }
+
+#ifdef TLS_VARIANT_I
+ /*
+ * tls_static_space should include space for TLS structure
+ */
+ tls_static_space += TLS_TCB_SIZE;
+#endif
+
+ tls = _rtld_allocate_tls(NULL, TLS_TCB_SIZE, TLS_TCB_ALIGN);
+
+ _set_tp(tls);
+#endif
+}
diff --git a/lib/libc/gen/ttyname.3 b/lib/libc/gen/ttyname.3
new file mode 100644
index 0000000..9420bbe
--- /dev/null
+++ b/lib/libc/gen/ttyname.3
@@ -0,0 +1,124 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)ttyname.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd May 14, 2005
+.Dt TTYNAME 3
+.Os
+.Sh NAME
+.Nm ttyname ,
+.Nm ttyname_r ,
+.Nm isatty
+.Nd get name of associated terminal (tty) from file descriptor
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft char *
+.Fn ttyname "int fd"
+.Ft int
+.Fn ttyname_r "int fd" "char *buf" "size_t len"
+.Ft int
+.Fn isatty "int fd"
+.Sh DESCRIPTION
+These functions operate on file descriptors for terminal type devices.
+.Pp
+The
+.Fn isatty
+function
+determines if the file descriptor
+.Fa fd
+refers to a valid
+terminal type device.
+.Pp
+The
+.Fn ttyname
+function
+gets the related device name of
+a file descriptor for which
+.Fn isatty
+is true.
+.Pp
+The
+.Fn ttyname
+function
+returns the name stored in a static buffer which will be overwritten
+on subsequent calls.
+The
+.Fn ttyname_r
+function
+takes a buffer and length as arguments to avoid this problem.
+.Sh RETURN VALUES
+The
+.Fn ttyname
+function
+returns the null terminated name if the device is found and
+.Fn isatty
+is true; otherwise
+a
+.Dv NULL
+pointer is returned.
+The
+.Fn ttyname_r
+function returns 0 if successful.
+Otherwise an error number is returned.
+.Sh ERRORS
+The
+.Fn ttyname_r
+may fail and return the following error codes:
+.Bl -tag -width Er
+.It Bq Er ENOTTY
+The
+.Fa fd
+argument
+is not a valid file descriptor.
+.It Bq Er ERANGE
+The
+.Fa bufsize
+argument
+is smaller than the length of the string to be returned.
+.El
+.Sh SEE ALSO
+.Xr fdevname 3 ,
+.Xr ptsname 3 ,
+.Xr tcgetattr 3 ,
+.Xr tty 4
+.Sh HISTORY
+The
+.Fn isatty
+and
+.Fn ttyname
+functions
+appeared in
+.At v7 .
+The
+.Fn ttyname_r
+function
+appeared in
+.Fx 6.0 .
diff --git a/lib/libc/gen/ttyname.c b/lib/libc/gen/ttyname.c
new file mode 100644
index 0000000..a21b77f
--- /dev/null
+++ b/lib/libc/gen/ttyname.c
@@ -0,0 +1,110 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ttyname.c 8.2 (Berkeley) 1/27/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/filio.h>
+#include <fcntl.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <termios.h>
+#include <unistd.h>
+#include <string.h>
+#include <paths.h>
+#include <errno.h>
+#include "reentrant.h"
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+static char ttyname_buf[sizeof(_PATH_DEV) + MAXNAMLEN];
+
+static once_t ttyname_init_once = ONCE_INITIALIZER;
+static thread_key_t ttyname_key;
+static int ttyname_keycreated = 0;
+
+int
+ttyname_r(int fd, char *buf, size_t len)
+{
+ size_t used;
+
+ *buf = '\0';
+
+ /* Must be a terminal. */
+ if (!isatty(fd))
+ return (ENOTTY);
+ /* Must have enough room */
+ if (len <= sizeof(_PATH_DEV))
+ return (ERANGE);
+
+ strcpy(buf, _PATH_DEV);
+ used = strlen(buf);
+ if (fdevname_r(fd, buf + used, len - used) == NULL)
+ return (ENOTTY);
+ return (0);
+}
+
+static void
+ttyname_keycreate(void)
+{
+ ttyname_keycreated = (thr_keycreate(&ttyname_key, free) == 0);
+}
+
+char *
+ttyname(int fd)
+{
+ char *buf;
+
+ if (thr_main() != 0)
+ buf = ttyname_buf;
+ else {
+ if (thr_once(&ttyname_init_once, ttyname_keycreate) != 0 ||
+ !ttyname_keycreated)
+ return (NULL);
+ if ((buf = thr_getspecific(ttyname_key)) == NULL) {
+ if ((buf = malloc(sizeof ttyname_buf)) == NULL)
+ return (NULL);
+ if (thr_setspecific(ttyname_key, buf) != 0) {
+ free(buf);
+ return (NULL);
+ }
+ }
+ }
+
+ if (ttyname_r(fd, buf, sizeof ttyname_buf) != 0)
+ return (NULL);
+ return (buf);
+}
diff --git a/lib/libc/gen/ttyslot.c b/lib/libc/gen/ttyslot.c
new file mode 100644
index 0000000..1de0837
--- /dev/null
+++ b/lib/libc/gen/ttyslot.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ttyslot.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+int
+__ttyslot(void)
+{
+
+ return (0);
+}
+
+__sym_compat(ttyslot, __ttyslot, FBSD_1.0);
diff --git a/lib/libc/gen/tzset.3 b/lib/libc/gen/tzset.3
new file mode 100644
index 0000000..8d37fca
--- /dev/null
+++ b/lib/libc/gen/tzset.3
@@ -0,0 +1,338 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Arthur Olson.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)tzset.3 8.2 (Berkeley) 11/17/93
+.\" $FreeBSD$
+.\"
+.Dd November 17, 1993
+.Dt TZSET 3
+.Os
+.Sh NAME
+.Nm tzset ,
+.Nm tzsetwall
+.Nd initialize time conversion information
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In time.h
+.Ft void
+.Fn tzset void
+.Ft void
+.Fn tzsetwall void
+.Sh DESCRIPTION
+The
+.Fn tzset
+function
+initializes time conversion information used by the library routine
+.Xr localtime 3 .
+The environment variable
+.Ev TZ
+specifies how this is done.
+.Pp
+If
+.Ev TZ
+does not appear in the environment, the best available approximation to
+local wall clock time, as specified by the
+.Xr tzfile 5 Ns -format
+file
+.Pa /etc/localtime
+is used.
+.Pp
+If
+.Ev TZ
+appears in the environment but its value is a null string, Coordinated
+Universal Time
+.Pq Tn UTC
+is used (without leap second correction).
+.Pp
+If
+.Ev TZ
+appears in the environment and its value begins with a colon
+.Pq Ql \&: ,
+the rest of its value is used as a pathname of a
+.Xr tzfile 5 Ns -format
+file from which to read the time conversion information.
+If the first character of the pathname is a slash
+.Pq Ql /
+it is used as
+an absolute pathname; otherwise, it is used as a pathname relative to
+the system time conversion information directory.
+.Pp
+If its value does not begin with a colon, it is first used as the pathname
+of a file (as described above) from which to read the time conversion
+information.
+If that file cannot be read, the value is then interpreted as a direct
+specification (the format is described below) of the time conversion
+information.
+.Pp
+If the
+.Ev TZ
+environment variable does not specify a
+.Xr tzfile 5 Ns -format
+file and cannot be interpreted as a direct specification,
+.Tn UTC
+is used.
+.Pp
+The
+.Fn tzsetwall
+function
+sets things up so that
+.Xr localtime 3
+returns the best available approximation of local wall clock time.
+.Sh SPECIFICATION FORMAT
+When
+.Ev TZ
+is used directly as a specification of the time conversion information,
+it must have the following syntax (spaces inserted for clarity):
+.Bd -ragged -offset indent
+.Em std offset
+.Bo
+.Em dst
+.Bq Em offset
+.Bq , Em rule
+.Bc
+.Ed
+.Pp
+Where:
+.Bl -tag -width std_and_dst -offset indent
+.It Em std No and Em dst
+Three or more bytes that are the designation for the standard
+.Pq Em std
+or summer
+.Pq Em dst
+time zone.
+Only
+.Em std
+is required; if
+.Em dst
+is missing, then summer time does not apply in this locale.
+Upper and lowercase letters are explicitly allowed.
+Any characters
+except a leading colon
+.Pq Ql \&: ,
+digits, comma
+.Pq Ql \&, ,
+minus
+.Pq Ql \- ,
+plus
+.Pq Ql + ,
+and
+.Tn ASCII
+.Dv NUL
+are allowed.
+.It Em offset
+Indicates the value one must add to the local time to arrive at
+Coordinated Universal Time.
+The
+.Em offset
+has the form:
+.Bd -ragged -offset indent
+.Sm off
+.Em hh Bo
+.Em : mm
+.Bq Em : ss
+.Bc
+.Sm on
+.Ed
+.Pp
+The minutes
+.Pq Em mm
+and seconds
+.Pq Em ss
+are optional.
+The hour
+.Pq Em hh
+is required and may be a single digit.
+The
+.Em offset
+following
+.Em std
+is required.
+If no
+.Em offset
+follows
+.Em dst ,
+summer time is assumed to be one hour ahead of standard time.
+One or
+more digits may be used; the value is always interpreted as a decimal
+number.
+The hour must be between zero and 24, and the minutes (and
+seconds) \(em if present \(em between zero and 59.
+If preceded by a
+.Pq Ql \-
+the time zone shall be east of the Prime Meridian; otherwise it shall be
+west (which may be indicated by an optional preceding
+.Pq Ql + ) .
+.It Em rule
+Indicates when to change to and back from summer time.
+The
+.Em rule
+has the form:
+.Bd -ragged -offset indent
+.Em date/time,date/time
+.Ed
+.Pp
+where the first
+.Em date
+describes when the change from standard to summer time occurs and the
+second
+.Em date
+describes when the change back happens.
+Each
+.Em time
+field describes when, in current local time, the change to the other
+time is made.
+.Pp
+The format of
+.Em date
+is one of the following:
+.Bl -tag -width "M.m.n.d"
+.It Sy J Em n
+The Julian day
+.Em n
+(1 \*(Le
+.Em n
+\*(Le 365).
+Leap days are not counted; that is, in all years \(em including leap
+years \(em February 28 is day 59 and March 1 is day 60.
+It is
+impossible to explicitly refer to the occasional February 29.
+.It Em n
+The zero-based Julian day
+(0 \*(Le
+.Em n
+\*(Le 365 ) .
+Leap days are counted, and it is possible to refer to February 29.
+.It Sy M Em m.n.d
+The
+.Em d Ns 'th
+day (0 \*(Le
+.Em d
+\*(Le 6)
+of week
+.Em n
+of month
+.Em m
+of the year
+(1 \*(Le
+.Em n
+\*(Le 5),
+(1 \*(Le
+.Em m
+\*(Le 12),
+where week 5 means
+.Do
+the last
+.Em d
+day in month
+.Em m
+.Dc
+which may occur in either the fourth or the fifth week).
+Week 1 is the
+first week in which the
+.Em d Ns 'th
+day occurs.
+Day zero is Sunday.
+.Pp
+The
+.Em time
+has the same format as
+.Em offset
+except that no leading sign
+.Pq Ql \-
+or
+.Pq Ql +
+is allowed.
+The default, if
+.Em time
+is not given, is
+.Sy 02:00:00 .
+.El
+.Pp
+If no
+.Em rule
+is present in the
+.Ev TZ
+specification, the rules specified
+by the
+.Xr tzfile 5 Ns -format
+file
+.Em posixrules
+in the system time conversion information directory are used, with the
+standard and summer time offsets from
+.Tn UTC
+replaced by those specified by
+the
+.Em offset
+values in
+.Ev TZ .
+.El
+.Pp
+For compatibility with System V Release 3.1, a semicolon
+.Pq Ql \&;
+may be used to separate the
+.Em rule
+from the rest of the specification.
+.Sh FILES
+.Bl -tag -width /usr/share/zoneinfo/posixrules -compact
+.It Pa /etc/localtime
+local time zone file
+.It Pa /usr/share/zoneinfo
+time zone directory
+.It Pa /usr/share/zoneinfo/posixrules
+rules for
+.Tn POSIX Ns -style
+.Tn TZ Ns 's
+.It Pa /usr/share/zoneinfo/Etc/GMT
+for
+.Tn UTC
+leap seconds
+.El
+.Pp
+If the file
+.Pa /usr/share/zoneinfo/UTC
+does not exist,
+.Tn UTC
+leap seconds are loaded from
+.Pa /usr/share/zoneinfo/posixrules .
+.Sh SEE ALSO
+.Xr date 1 ,
+.Xr gettimeofday 2 ,
+.Xr ctime 3 ,
+.Xr getenv 3 ,
+.Xr time 3 ,
+.Xr tzfile 5
+.Sh HISTORY
+The
+.Fn tzset
+and
+.Fn tzsetwall
+functions first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/ualarm.3 b/lib/libc/gen/ualarm.3
new file mode 100644
index 0000000..5719896
--- /dev/null
+++ b/lib/libc/gen/ualarm.3
@@ -0,0 +1,97 @@
+.\" Copyright (c) 1986, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)ualarm.3 8.2 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd April 19, 1994
+.Dt UALARM 3
+.Os
+.Sh NAME
+.Nm ualarm
+.Nd schedule signal after specified time
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft useconds_t
+.Fn ualarm "useconds_t microseconds" "useconds_t interval"
+.Sh DESCRIPTION
+.Bf -symbolic
+This is a simplified interface to
+.Xr setitimer 2 .
+.Ef
+.Pp
+The
+.Fn ualarm
+function
+waits a count of
+.Fa microseconds
+before asserting the terminating signal
+.Dv SIGALRM .
+System activity or time used in processing the call may cause a slight
+delay.
+.Pp
+If the
+.Fa interval
+argument is non-zero, the
+.Dv SIGALRM
+signal will be sent
+to the process every
+.Fa interval
+microseconds after the timer expires (e.g.\& after
+.Fa microseconds
+number of microseconds have passed).
+.Pp
+Due to
+.Xr setitimer 2
+restriction the maximum number of
+.Fa microseconds
+and
+.Fa interval
+is limited to 100000000000000
+(in case this value fits in the unsigned integer).
+.Sh RETURN VALUES
+When the signal has successfully been caught,
+.Fn ualarm
+returns the amount of time left on the clock.
+.Sh NOTES
+A microsecond is 0.000001 seconds.
+.Sh SEE ALSO
+.Xr getitimer 2 ,
+.Xr setitimer 2 ,
+.Xr sigaction 2 ,
+.Xr sigsuspend 2 ,
+.Xr alarm 3 ,
+.Xr signal 3 ,
+.Xr sleep 3 ,
+.Xr usleep 3
+.Sh HISTORY
+The
+.Fn ualarm
+function appeared in
+.Bx 4.3 .
diff --git a/lib/libc/gen/ualarm.c b/lib/libc/gen/ualarm.c
new file mode 100644
index 0000000..bf75775
--- /dev/null
+++ b/lib/libc/gen/ualarm.c
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ualarm.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/time.h>
+#include <unistd.h>
+
+#define USPS 1000000 /* # of microseconds in a second */
+
+/*
+ * Generate a SIGALRM signal in ``usecs'' microseconds.
+ * If ``reload'' is non-zero, keep generating SIGALRM
+ * every ``reload'' microseconds after the first signal.
+ */
+useconds_t
+ualarm(usecs, reload)
+ useconds_t usecs;
+ useconds_t reload;
+{
+ struct itimerval new, old;
+
+ new.it_interval.tv_usec = reload % USPS;
+ new.it_interval.tv_sec = reload / USPS;
+
+ new.it_value.tv_usec = usecs % USPS;
+ new.it_value.tv_sec = usecs / USPS;
+
+ if (setitimer(ITIMER_REAL, &new, &old) == 0)
+ return (old.it_value.tv_sec * USPS + old.it_value.tv_usec);
+ /* else */
+ return (-1);
+}
diff --git a/lib/libc/gen/ucontext.3 b/lib/libc/gen/ucontext.3
new file mode 100644
index 0000000..69ecbc1
--- /dev/null
+++ b/lib/libc/gen/ucontext.3
@@ -0,0 +1,111 @@
+.\" Copyright (c) 2002 Packet Design, LLC.
+.\" All rights reserved.
+.\"
+.\" Subject to the following obligations and disclaimer of warranty,
+.\" use and redistribution of this software, in source or object code
+.\" forms, with or without modifications are expressly permitted by
+.\" Packet Design; provided, however, that:
+.\"
+.\" (i) Any and all reproductions of the source or object code
+.\" must include the copyright notice above and the following
+.\" disclaimer of warranties; and
+.\" (ii) No rights are granted, in any manner or form, to use
+.\" Packet Design trademarks, including the mark "PACKET DESIGN"
+.\" on advertising, endorsements, or otherwise except as such
+.\" appears in the above copyright notice or in the software.
+.\"
+.\" THIS SOFTWARE IS BEING PROVIDED BY PACKET DESIGN "AS IS", AND
+.\" TO THE MAXIMUM EXTENT PERMITTED BY LAW, PACKET DESIGN MAKES NO
+.\" REPRESENTATIONS OR WARRANTIES, EXPRESS OR IMPLIED, REGARDING
+.\" THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY AND ALL IMPLIED
+.\" WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE,
+.\" OR NON-INFRINGEMENT. PACKET DESIGN DOES NOT WARRANT, GUARANTEE,
+.\" OR MAKE ANY REPRESENTATIONS REGARDING THE USE OF, OR THE RESULTS
+.\" OF THE USE OF THIS SOFTWARE IN TERMS OF ITS CORRECTNESS, ACCURACY,
+.\" RELIABILITY OR OTHERWISE. IN NO EVENT SHALL PACKET DESIGN BE
+.\" LIABLE FOR ANY DAMAGES RESULTING FROM OR ARISING OUT OF ANY USE
+.\" OF THIS SOFTWARE, INCLUDING WITHOUT LIMITATION, ANY DIRECT,
+.\" INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, PUNITIVE, OR CONSEQUENTIAL
+.\" DAMAGES, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, LOSS OF
+.\" USE, DATA OR PROFITS, HOWEVER CAUSED AND UNDER ANY THEORY OF
+.\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
+.\" THE USE OF THIS SOFTWARE, EVEN IF PACKET DESIGN IS ADVISED OF
+.\" THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 10, 2002
+.Dt UCONTEXT 3
+.Os
+.Sh NAME
+.Nm ucontext
+.Nd user thread context
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ucontext.h
+.Sh DESCRIPTION
+The
+.Vt ucontext_t
+type is a structure type suitable for holding the context for a user
+thread of execution.
+A thread's context includes its stack, saved registers, and list of
+blocked signals.
+.Pp
+The
+.Vt ucontext_t
+structure contains at least these fields:
+.Pp
+.Bl -tag -width ".Va mcontext_t\ \ uc_mcontext" -offset 3n -compact
+.It Va "ucontext_t *uc_link"
+context to assume when this one returns
+.It Va "sigset_t uc_sigmask"
+signals being blocked
+.It Va "stack_t uc_stack"
+stack area
+.It Va "mcontext_t uc_mcontext"
+saved registers
+.El
+.Pp
+The
+.Va uc_link
+field points to the context to resume when this context's entry point
+function returns.
+If
+.Va uc_link
+is equal to
+.Dv NULL ,
+then the process exits when this context returns.
+.Pp
+The
+.Va uc_mcontext
+field is machine-dependent and should be treated as opaque by
+portable applications.
+.Pp
+The following functions are defined to manipulate
+.Vt ucontext_t
+structures:
+.Pp
+.Bl -item -offset 3n -compact
+.It
+.Ft int
+.Fn getcontext "ucontext_t *" ;
+.It
+.Ft "ucontext_t *"
+.Fn getcontextx "void" ;
+.It
+.Ft int
+.Fn setcontext "const ucontext_t *" ;
+.It
+.Ft void
+.Fn makecontext "ucontext_t *" "void \*[lp]*\*[rp]\*[lp]void\*[rp]" int ... ;
+.It
+.Ft int
+.Fn swapcontext "ucontext_t *" "const ucontext_t *" ;
+.El
+.Sh SEE ALSO
+.Xr sigaltstack 2 ,
+.Xr getcontext 3 ,
+.Xr getcontextx 3 ,
+.Xr makecontext 3
diff --git a/lib/libc/gen/ulimit.3 b/lib/libc/gen/ulimit.3
new file mode 100644
index 0000000..e4c2d76
--- /dev/null
+++ b/lib/libc/gen/ulimit.3
@@ -0,0 +1,98 @@
+.\" Copyright (c) 2002 Kyle Martin. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 4, 2003
+.Dt ULIMIT 3
+.Os
+.Sh NAME
+.Nm ulimit
+.Nd get and set process limits
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ulimit.h
+.Ft long
+.Fn ulimit "int cmd" "..."
+.Sh DESCRIPTION
+The
+.Fn ulimit
+function will get and set process limits.
+Currently this is limited to the maximum file size.
+The
+.Fa cmd
+argument is one of the following:
+.Bl -tag -width ".Dv UL_GETFSIZE"
+.It Dv UL_GETFSIZE
+will return the maximum file size in units of 512 blocks of
+the current process.
+.It Dv UL_SETFSIZE
+will attempt to set the maximum file size of the current
+process and its children with the second argument expressed as a long.
+.El
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn ulimit
+returns the value requested;
+otherwise the value \-1 is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+The
+.Fn ulimit
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The command specified was invalid.
+.It Bq Er EPERM
+The limit specified to
+.Fn ulimit
+would have raised the maximum limit value,
+and the caller is not the super-user.
+.El
+.Sh SEE ALSO
+.Xr getrlimit 2
+.Sh STANDARDS
+The
+.Fn ulimit
+function conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn ulimit
+function first appeared in
+.Fx 5.0 .
+.Sh BUGS
+The
+.Fn ulimit
+function provides limited precision for
+setting and retrieving process limits.
+If there is a need for greater precision than the
+type
+.Vt long
+provides, the
+.Xr getrlimit 2
+and
+.Xr setrlimit 2
+functions should be considered.
diff --git a/lib/libc/gen/ulimit.c b/lib/libc/gen/ulimit.c
new file mode 100644
index 0000000..e1bc020
--- /dev/null
+++ b/lib/libc/gen/ulimit.c
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2002 Kyle Martin <mkm@ieee.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/resource.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <ulimit.h>
+
+long
+ulimit(int cmd, ...)
+{
+ struct rlimit limit;
+ va_list ap;
+ long arg;
+
+ if (cmd == UL_GETFSIZE) {
+ if (getrlimit(RLIMIT_FSIZE, &limit) == -1)
+ return (-1);
+ limit.rlim_cur /= 512;
+ if (limit.rlim_cur > LONG_MAX)
+ return (LONG_MAX);
+ return ((long)limit.rlim_cur);
+ } else if (cmd == UL_SETFSIZE) {
+ va_start(ap, cmd);
+ arg = va_arg(ap, long);
+ va_end(ap);
+ limit.rlim_max = limit.rlim_cur = (rlim_t)arg * 512;
+
+ /* The setrlimit() function sets errno to EPERM if needed. */
+ if (setrlimit(RLIMIT_FSIZE, &limit) == -1)
+ return (-1);
+ if (arg * 512 > LONG_MAX)
+ return (LONG_MAX);
+ return (arg);
+ } else {
+ errno = EINVAL;
+ return (-1);
+ }
+}
diff --git a/lib/libc/gen/uname.3 b/lib/libc/gen/uname.3
new file mode 100644
index 0000000..a906e79
--- /dev/null
+++ b/lib/libc/gen/uname.3
@@ -0,0 +1,117 @@
+.\" Copyright (c) 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)uname.3 8.1 (Berkeley) 1/4/94
+.\" $FreeBSD$
+.\"
+.Dd December 2, 2005
+.Dt UNAME 3
+.Os
+.Sh NAME
+.Nm uname
+.Nd get system identification
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/utsname.h
+.Ft int
+.Fn uname "struct utsname *name"
+.Sh DESCRIPTION
+The
+.Fn uname
+function stores
+.Dv NUL Ns -terminated
+strings of information identifying
+the current system into the structure referenced by
+.Fa name .
+.Pp
+The
+.Vt utsname
+structure is defined in the
+.In sys/utsname.h
+header file, and contains the following members:
+.Bl -tag -width nodenameXXXX -offset indent
+.It sysname
+Name of the operating system implementation.
+.It nodename
+Network name of this machine.
+.It release
+Release level of the operating system.
+.It version
+Version level of the operating system.
+.It machine
+Machine hardware platform.
+.El
+.Sh RETURN VALUES
+.Rv -std uname
+.Sh ENVIRONMENT
+.Bl -tag -width ".Ev UNAME_s"
+.It Ev UNAME_s
+If the environment variable
+.Ev UNAME_s
+is set, it will override the
+.Va sysname
+member.
+.It Ev UNAME_r
+If the environment variable
+.Ev UNAME_r
+is set, it will override the
+.Va release
+member.
+.It Ev UNAME_v
+If the environment variable
+.Ev UNAME_v
+is set, it will override the
+.Va version
+member.
+.It Ev UNAME_m
+If the environment variable
+.Ev UNAME_m
+is set, it will override the
+.Va machine
+member.
+.El
+.Sh ERRORS
+The
+.Fn uname
+function may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr sysctl 3 .
+.Sh SEE ALSO
+.Xr uname 1 ,
+.Xr sysctl 3
+.Sh STANDARDS
+The
+.Fn uname
+function conforms to
+.St -p1003.1-88 .
+.Sh HISTORY
+The
+.Fn uname
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/uname.c b/lib/libc/gen/uname.c
new file mode 100644
index 0000000..5a7baf7
--- /dev/null
+++ b/lib/libc/gen/uname.c
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "From: @(#)uname.c 8.1 (Berkeley) 1/4/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define uname wrapped_uname
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/utsname.h>
+#include <errno.h>
+#undef uname
+
+int
+uname(struct utsname *name)
+{
+ return __xuname(32, name);
+}
diff --git a/lib/libc/gen/unvis.3 b/lib/libc/gen/unvis.3
new file mode 100644
index 0000000..9164f79
--- /dev/null
+++ b/lib/libc/gen/unvis.3
@@ -0,0 +1,200 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)unvis.3 8.2 (Berkeley) 12/11/93
+.\" $FreeBSD$
+.\"
+.Dd December 11, 1993
+.Dt UNVIS 3
+.Os
+.Sh NAME
+.Nm unvis ,
+.Nm strunvis
+.Nd decode a visual representation of characters
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In vis.h
+.Ft int
+.Fn unvis "char *cp" "int c" "int *astate" "int flag"
+.Ft int
+.Fn strunvis "char *dst" "const char *src"
+.Ft int
+.Fn strunvisx "char *dst" "const char *src" "int flag"
+.Sh DESCRIPTION
+The
+.Fn unvis ,
+.Fn strunvis
+and
+.Fn strunvisx
+functions
+are used to decode a visual representation of characters, as produced
+by the
+.Xr vis 3
+function, back into
+the original form.
+Unvis is called with successive characters in
+.Fa c
+until a valid
+sequence is recognized, at which time the decoded character is
+available at the character pointed to by
+.Fa cp .
+Strunvis decodes the
+characters pointed to by
+.Fa src
+into the buffer pointed to by
+.Fa dst .
+.Pp
+The
+.Fn strunvis
+function
+simply copies
+.Fa src
+to
+.Fa dst ,
+decoding any escape sequences along the way,
+and returns the number of characters placed into
+.Fa dst ,
+or \-1 if an
+invalid escape sequence was detected.
+The size of
+.Fa dst
+should be
+equal to the size of
+.Fa src
+(that is, no expansion takes place during
+decoding).
+.Pp
+The
+.Fn strunvisx
+function does the same as the
+.Fn strunvis
+function,
+but it allows you to add a flag that specifies the style the string
+.Fa src
+is encoded with.
+Currently, the only supported flag is
+.Dv VIS_HTTPSTYLE .
+.Pp
+The
+.Fn unvis
+function
+implements a state machine that can be used to decode an arbitrary
+stream of bytes.
+All state associated with the bytes being decoded
+is stored outside the
+.Fn unvis
+function (that is, a pointer to the state is passed in), so
+calls decoding different streams can be freely intermixed.
+To
+start decoding a stream of bytes, first initialize an integer
+to zero.
+Call
+.Fn unvis
+with each successive byte, along with a pointer
+to this integer, and a pointer to a destination character.
+The
+.Fn unvis
+function
+has several return codes that must be handled properly.
+They are:
+.Bl -tag -width UNVIS_VALIDPUSH
+.It Li \&0 (zero)
+Another character is necessary; nothing has been recognized yet.
+.It Dv UNVIS_VALID
+A valid character has been recognized and is available at the location
+pointed to by cp.
+.It Dv UNVIS_VALIDPUSH
+A valid character has been recognized and is available at the location
+pointed to by cp; however, the character currently passed in should
+be passed in again.
+.It Dv UNVIS_NOCHAR
+A valid sequence was detected, but no character was produced.
+This
+return code is necessary to indicate a logical break between characters.
+.It Dv UNVIS_SYNBAD
+An invalid escape sequence was detected, or the decoder is in an
+unknown state.
+The decoder is placed into the starting state.
+.El
+.Pp
+When all bytes in the stream have been processed, call
+.Fn unvis
+one more time with
+.Fa flag
+set to
+.Dv UNVIS_END
+to extract any remaining character (the character passed in is ignored).
+.Pp
+The
+.Fa flag
+argument is also used to specify the encoding style of the source.
+If set to
+.Dv VIS_HTTPSTYLE ,
+.Fn unvis
+will decode URI strings as specified in RFC 1808.
+.Pp
+The following code fragment illustrates a proper use of
+.Fn unvis .
+.Bd -literal -offset indent
+int state = 0;
+char out;
+
+while ((ch = getchar()) != EOF) {
+again:
+ switch(unvis(&out, ch, &state, 0)) {
+ case 0:
+ case UNVIS_NOCHAR:
+ break;
+ case UNVIS_VALID:
+ (void) putchar(out);
+ break;
+ case UNVIS_VALIDPUSH:
+ (void) putchar(out);
+ goto again;
+ case UNVIS_SYNBAD:
+ (void)fprintf(stderr, "bad sequence!\en");
+ exit(1);
+ }
+}
+if (unvis(&out, (char)0, &state, UNVIS_END) == UNVIS_VALID)
+ (void) putchar(out);
+.Ed
+.Sh SEE ALSO
+.Xr vis 1 ,
+.Xr vis 3
+.Rs
+.%A R. Fielding
+.%T Relative Uniform Resource Locators
+.%O RFC1808
+.Re
+.Sh HISTORY
+The
+.Fn unvis
+function
+first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/gen/unvis.c b/lib/libc/gen/unvis.c
new file mode 100644
index 0000000..9069e55
--- /dev/null
+++ b/lib/libc/gen/unvis.c
@@ -0,0 +1,293 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)unvis.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <vis.h>
+
+/*
+ * decode driven by state machine
+ */
+#define S_GROUND 0 /* haven't seen escape char */
+#define S_START 1 /* start decoding special sequence */
+#define S_META 2 /* metachar started (M) */
+#define S_META1 3 /* metachar more, regular char (-) */
+#define S_CTRL 4 /* control char started (^) */
+#define S_OCTAL2 5 /* octal digit 2 */
+#define S_OCTAL3 6 /* octal digit 3 */
+#define S_HEX2 7 /* hex digit 2 */
+
+#define S_HTTP 0x080 /* %HEXHEX escape */
+
+#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+#define ishex(c) ((((u_char)(c)) >= '0' && ((u_char)(c)) <= '9') || (((u_char)(c)) >= 'a' && ((u_char)(c)) <= 'f'))
+
+/*
+ * unvis - decode characters previously encoded by vis
+ */
+int
+unvis(char *cp, int c, int *astate, int flag)
+{
+
+ if (flag & UNVIS_END) {
+ if (*astate == S_OCTAL2 || *astate == S_OCTAL3) {
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ }
+ return (*astate == S_GROUND ? UNVIS_NOCHAR : UNVIS_SYNBAD);
+ }
+
+ switch (*astate & ~S_HTTP) {
+
+ case S_GROUND:
+ *cp = 0;
+ if (c == '\\') {
+ *astate = S_START;
+ return (0);
+ }
+ if (flag & VIS_HTTPSTYLE && c == '%') {
+ *astate = S_START | S_HTTP;
+ return (0);
+ }
+ *cp = c;
+ return (UNVIS_VALID);
+
+ case S_START:
+ if (*astate & S_HTTP) {
+ if (ishex(tolower(c))) {
+ *cp = isdigit(c) ? (c - '0') : (tolower(c) - 'a');
+ *astate = S_HEX2;
+ return (0);
+ }
+ }
+ switch(c) {
+ case '\\':
+ *cp = c;
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ *cp = (c - '0');
+ *astate = S_OCTAL2;
+ return (0);
+ case 'M':
+ *cp = 0200;
+ *astate = S_META;
+ return (0);
+ case '^':
+ *astate = S_CTRL;
+ return (0);
+ case 'n':
+ *cp = '\n';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'r':
+ *cp = '\r';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'b':
+ *cp = '\b';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'a':
+ *cp = '\007';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'v':
+ *cp = '\v';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 't':
+ *cp = '\t';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'f':
+ *cp = '\f';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 's':
+ *cp = ' ';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case 'E':
+ *cp = '\033';
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+ case '\n':
+ /*
+ * hidden newline
+ */
+ *astate = S_GROUND;
+ return (UNVIS_NOCHAR);
+ case '$':
+ /*
+ * hidden marker
+ */
+ *astate = S_GROUND;
+ return (UNVIS_NOCHAR);
+ }
+ *astate = S_GROUND;
+ return (UNVIS_SYNBAD);
+
+ case S_META:
+ if (c == '-')
+ *astate = S_META1;
+ else if (c == '^')
+ *astate = S_CTRL;
+ else {
+ *astate = S_GROUND;
+ return (UNVIS_SYNBAD);
+ }
+ return (0);
+
+ case S_META1:
+ *astate = S_GROUND;
+ *cp |= c;
+ return (UNVIS_VALID);
+
+ case S_CTRL:
+ if (c == '?')
+ *cp |= 0177;
+ else
+ *cp |= c & 037;
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+
+ case S_OCTAL2: /* second possible octal digit */
+ if (isoctal(c)) {
+ /*
+ * yes - and maybe a third
+ */
+ *cp = (*cp << 3) + (c - '0');
+ *astate = S_OCTAL3;
+ return (0);
+ }
+ /*
+ * no - done with current sequence, push back passed char
+ */
+ *astate = S_GROUND;
+ return (UNVIS_VALIDPUSH);
+
+ case S_OCTAL3: /* third possible octal digit */
+ *astate = S_GROUND;
+ if (isoctal(c)) {
+ *cp = (*cp << 3) + (c - '0');
+ return (UNVIS_VALID);
+ }
+ /*
+ * we were done, push back passed char
+ */
+ return (UNVIS_VALIDPUSH);
+
+ case S_HEX2: /* second mandatory hex digit */
+ if (ishex(tolower(c))) {
+ *cp = (isdigit(c) ? (*cp << 4) + (c - '0') : (*cp << 4) + (tolower(c) - 'a' + 10));
+ }
+ *astate = S_GROUND;
+ return (UNVIS_VALID);
+
+ default:
+ /*
+ * decoder in unknown state - (probably uninitialized)
+ */
+ *astate = S_GROUND;
+ return (UNVIS_SYNBAD);
+ }
+}
+
+/*
+ * strunvis - decode src into dst
+ *
+ * Number of chars decoded into dst is returned, -1 on error.
+ * Dst is null terminated.
+ */
+
+int
+strunvis(char *dst, const char *src)
+{
+ char c;
+ char *start = dst;
+ int state = 0;
+
+ while ( (c = *src++) ) {
+ again:
+ switch (unvis(dst, c, &state, 0)) {
+ case UNVIS_VALID:
+ dst++;
+ break;
+ case UNVIS_VALIDPUSH:
+ dst++;
+ goto again;
+ case 0:
+ case UNVIS_NOCHAR:
+ break;
+ default:
+ return (-1);
+ }
+ }
+ if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
+ dst++;
+ *dst = '\0';
+ return (dst - start);
+}
+
+int
+strunvisx(char *dst, const char *src, int flag)
+{
+ char c;
+ char *start = dst;
+ int state = 0;
+
+ while ( (c = *src++) ) {
+ again:
+ switch (unvis(dst, c, &state, flag)) {
+ case UNVIS_VALID:
+ dst++;
+ break;
+ case UNVIS_VALIDPUSH:
+ dst++;
+ goto again;
+ case 0:
+ case UNVIS_NOCHAR:
+ break;
+ default:
+ return (-1);
+ }
+ }
+ if (unvis(dst, c, &state, UNVIS_END) == UNVIS_VALID)
+ dst++;
+ *dst = '\0';
+ return (dst - start);
+}
diff --git a/lib/libc/gen/usleep.3 b/lib/libc/gen/usleep.3
new file mode 100644
index 0000000..a17468b
--- /dev/null
+++ b/lib/libc/gen/usleep.3
@@ -0,0 +1,80 @@
+.\" Copyright (c) 1986, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)usleep.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd February 13, 1998
+.Dt USLEEP 3
+.Os
+.Sh NAME
+.Nm usleep
+.Nd suspend process execution for an interval measured in microseconds
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn usleep "useconds_t microseconds"
+.Sh DESCRIPTION
+The
+.Fn usleep
+function suspends execution of the calling process until either
+.Fa microseconds
+microseconds have elapsed or a signal is delivered to the process and its
+action is to invoke a signal-catching function or to terminate the
+process.
+System activity may lengthen the sleep by an indeterminate amount.
+.Pp
+This function is implemented using
+.Xr nanosleep 2
+by pausing for
+.Fa microseconds
+microseconds or until a signal occurs.
+Consequently, in this implementation,
+sleeping has no effect on the state of process timers,
+and there is no special handling for SIGALRM.
+.Sh RETURN VALUES
+.Rv -std usleep
+.Sh ERRORS
+The
+.Fn usleep
+function
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINTR
+A signal was delivered to the process and its
+action was to invoke a signal-catching function.
+.El
+.Sh SEE ALSO
+.Xr nanosleep 2 ,
+.Xr sleep 3
+.Sh HISTORY
+The
+.Fn usleep
+function appeared in
+.Bx 4.3 .
diff --git a/lib/libc/gen/usleep.c b/lib/libc/gen/usleep.c
new file mode 100644
index 0000000..7d6559b
--- /dev/null
+++ b/lib/libc/gen/usleep.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)usleep.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <time.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+int
+__usleep(useconds_t useconds)
+{
+ struct timespec time_to_sleep;
+
+ time_to_sleep.tv_nsec = (useconds % 1000000) * 1000;
+ time_to_sleep.tv_sec = useconds / 1000000;
+ return (_nanosleep(&time_to_sleep, NULL));
+}
+
+__weak_reference(__usleep, usleep);
+__weak_reference(__usleep, _usleep);
diff --git a/lib/libc/gen/utime.3 b/lib/libc/gen/utime.3
new file mode 100644
index 0000000..1951613
--- /dev/null
+++ b/lib/libc/gen/utime.3
@@ -0,0 +1,92 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)utime.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt UTIME 3
+.Os
+.Sh NAME
+.Nm utime
+.Nd set file times
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In utime.h
+.Ft int
+.Fn utime "const char *file" "const struct utimbuf *timep"
+.Sh DESCRIPTION
+.Bf -symbolic
+This interface is obsoleted by
+.Xr utimes 2 .
+.Ef
+.Pp
+The
+.Fn utime
+function sets the access and modification times of the named file from
+the
+.Va actime
+and
+.Va modtime
+fields of the
+.Vt "struct utimbuf"
+pointed at by
+.Fa timep .
+.Pp
+If the times are specified (the
+.Fa timep
+argument is
+.Pf non- Dv NULL )
+the caller must be the owner of the file or be the super-user.
+.Pp
+If the times are not specified (the
+.Fa timep
+argument is
+.Dv NULL )
+the caller must be the owner of the file, have permission to write
+the file, or be the super-user.
+.Sh ERRORS
+The
+.Fn utime
+function may fail and set
+.Va errno
+for any of the errors specified for the library function
+.Xr utimes 2 .
+.Sh SEE ALSO
+.Xr stat 2 ,
+.Xr utimes 2
+.Sh STANDARDS
+The
+.Fn utime
+function conforms to
+.St -p1003.1-88 .
+.Sh HISTORY
+A
+.Fn utime
+function appeared in
+.At v7 .
diff --git a/lib/libc/gen/utime.c b/lib/libc/gen/utime.c
new file mode 100644
index 0000000..97bf878
--- /dev/null
+++ b/lib/libc/gen/utime.c
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)utime.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/time.h>
+
+#include <utime.h>
+
+int
+utime(path, times)
+ const char *path;
+ const struct utimbuf *times;
+{
+ struct timeval tv[2], *tvp;
+
+ if (times) {
+ tv[0].tv_sec = times->actime;
+ tv[1].tv_sec = times->modtime;
+ tv[0].tv_usec = tv[1].tv_usec = 0;
+ tvp = tv;
+ } else
+ tvp = NULL;
+ return (utimes(path, tvp));
+}
diff --git a/lib/libc/gen/utxdb.c b/lib/libc/gen/utxdb.c
new file mode 100644
index 0000000..6667129
--- /dev/null
+++ b/lib/libc/gen/utxdb.c
@@ -0,0 +1,179 @@
+/*-
+ * Copyright (c) 2010 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/endian.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <string.h>
+#include <utmpx.h>
+#include "utxdb.h"
+#include "un-namespace.h"
+
+#define UTOF_STRING(ut, fu, field) do { \
+ strncpy((fu)->fu_ ## field, (ut)->ut_ ## field, \
+ MIN(sizeof (fu)->fu_ ## field, sizeof (ut)->ut_ ## field)); \
+} while (0)
+#define UTOF_ID(ut, fu) do { \
+ memcpy((fu)->fu_id, (ut)->ut_id, \
+ MIN(sizeof (fu)->fu_id, sizeof (ut)->ut_id)); \
+} while (0)
+#define UTOF_PID(ut, fu) do { \
+ (fu)->fu_pid = htobe32((ut)->ut_pid); \
+} while (0)
+#define UTOF_TYPE(ut, fu) do { \
+ (fu)->fu_type = (ut)->ut_type; \
+} while (0)
+#define UTOF_TV(fu) do { \
+ struct timeval tv; \
+ gettimeofday(&tv, NULL); \
+ (fu)->fu_tv = htobe64((uint64_t)tv.tv_sec * 1000000 + \
+ (uint64_t)tv.tv_usec); \
+} while (0)
+
+void
+utx_to_futx(const struct utmpx *ut, struct futx *fu)
+{
+
+ memset(fu, 0, sizeof *fu);
+
+ switch (ut->ut_type) {
+ case BOOT_TIME:
+ case OLD_TIME:
+ case NEW_TIME:
+ /* Extension: shutdown time. */
+ case SHUTDOWN_TIME:
+ break;
+ case USER_PROCESS:
+ UTOF_ID(ut, fu);
+ UTOF_STRING(ut, fu, user);
+ UTOF_STRING(ut, fu, line);
+ /* Extension: host name. */
+ UTOF_STRING(ut, fu, host);
+ UTOF_PID(ut, fu);
+ break;
+ case INIT_PROCESS:
+ UTOF_ID(ut, fu);
+ UTOF_PID(ut, fu);
+ break;
+ case LOGIN_PROCESS:
+ UTOF_ID(ut, fu);
+ UTOF_STRING(ut, fu, user);
+ UTOF_STRING(ut, fu, line);
+ UTOF_PID(ut, fu);
+ break;
+ case DEAD_PROCESS:
+ UTOF_ID(ut, fu);
+ UTOF_PID(ut, fu);
+ break;
+ default:
+ fu->fu_type = EMPTY;
+ return;
+ }
+
+ UTOF_TYPE(ut, fu);
+ UTOF_TV(fu);
+}
+
+#define FTOU_STRING(fu, ut, field) do { \
+ strncpy((ut)->ut_ ## field, (fu)->fu_ ## field, \
+ MIN(sizeof (ut)->ut_ ## field - 1, sizeof (fu)->fu_ ## field)); \
+} while (0)
+#define FTOU_ID(fu, ut) do { \
+ memcpy((ut)->ut_id, (fu)->fu_id, \
+ MIN(sizeof (ut)->ut_id, sizeof (fu)->fu_id)); \
+} while (0)
+#define FTOU_PID(fu, ut) do { \
+ (ut)->ut_pid = be32toh((fu)->fu_pid); \
+} while (0)
+#define FTOU_TYPE(fu, ut) do { \
+ (ut)->ut_type = (fu)->fu_type; \
+} while (0)
+#define FTOU_TV(fu, ut) do { \
+ uint64_t t; \
+ t = be64toh((fu)->fu_tv); \
+ (ut)->ut_tv.tv_sec = t / 1000000; \
+ (ut)->ut_tv.tv_usec = t % 1000000; \
+} while (0)
+
+struct utmpx *
+futx_to_utx(const struct futx *fu)
+{
+#ifdef __NO_TLS
+ static struct utmpx *ut;
+#else
+ static _Thread_local struct utmpx *ut;
+#endif
+
+ if (ut == NULL) {
+ ut = calloc(1, sizeof *ut);
+ if (ut == NULL)
+ return (NULL);
+ } else
+ memset(ut, 0, sizeof *ut);
+
+ switch (fu->fu_type) {
+ case BOOT_TIME:
+ case OLD_TIME:
+ case NEW_TIME:
+ /* Extension: shutdown time. */
+ case SHUTDOWN_TIME:
+ break;
+ case USER_PROCESS:
+ FTOU_ID(fu, ut);
+ FTOU_STRING(fu, ut, user);
+ FTOU_STRING(fu, ut, line);
+ /* Extension: host name. */
+ FTOU_STRING(fu, ut, host);
+ FTOU_PID(fu, ut);
+ break;
+ case INIT_PROCESS:
+ FTOU_ID(fu, ut);
+ FTOU_PID(fu, ut);
+ break;
+ case LOGIN_PROCESS:
+ FTOU_ID(fu, ut);
+ FTOU_STRING(fu, ut, user);
+ FTOU_STRING(fu, ut, line);
+ FTOU_PID(fu, ut);
+ break;
+ case DEAD_PROCESS:
+ FTOU_ID(fu, ut);
+ FTOU_PID(fu, ut);
+ break;
+ default:
+ ut->ut_type = EMPTY;
+ return (ut);
+ }
+
+ FTOU_TYPE(fu, ut);
+ FTOU_TV(fu, ut);
+ return (ut);
+}
diff --git a/lib/libc/gen/utxdb.h b/lib/libc/gen/utxdb.h
new file mode 100644
index 0000000..d9ebc93
--- /dev/null
+++ b/lib/libc/gen/utxdb.h
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2010 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _UTXDB_H_
+#define _UTXDB_H_
+
+#include <stdint.h>
+
+#define _PATH_UTX_ACTIVE "/var/run/utx.active"
+#define _PATH_UTX_LASTLOGIN "/var/log/utx.lastlogin"
+#define _PATH_UTX_LOG "/var/log/utx.log"
+
+/*
+ * Entries in struct futx are ordered by how often they are used. In
+ * utx.log only entries will be written until the last non-zero byte,
+ * which means we want to put the hostname at the end. Most primitive
+ * records only store a ut_type and ut_tv, which means we want to store
+ * those at the front.
+ */
+
+struct utmpx;
+
+struct futx {
+ uint8_t fu_type;
+ uint64_t fu_tv;
+ char fu_id[8];
+ uint32_t fu_pid;
+ char fu_user[32];
+ char fu_line[16];
+ char fu_host[128];
+} __packed;
+
+void utx_to_futx(const struct utmpx *, struct futx *);
+struct utmpx *futx_to_utx(const struct futx *);
+
+#endif /* !_UTXDB_H_ */
diff --git a/lib/libc/gen/valloc.3 b/lib/libc/gen/valloc.3
new file mode 100644
index 0000000..610ca1c
--- /dev/null
+++ b/lib/libc/gen/valloc.3
@@ -0,0 +1,75 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)valloc.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd October 30, 2007
+.Dt VALLOC 3
+.Os
+.Sh NAME
+.Nm valloc
+.Nd aligned memory allocation function
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft void *
+.Fn valloc "size_t size"
+.Sh DESCRIPTION
+The
+.Fn valloc
+function is obsoleted by
+.Xr posix_memalign 3 ,
+which can be used to request page-aligned allocations.
+.Pp
+The
+.Fn valloc
+function
+allocates
+.Fa size
+bytes aligned on a page boundary.
+.Sh RETURN VALUES
+The
+.Fn valloc
+function returns
+a pointer to the allocated space if successful; otherwise
+a null pointer is returned.
+.Sh SEE ALSO
+.Xr posix_memalign 3
+.Sh HISTORY
+The
+.Fn valloc
+function appeared in
+.Bx 3.0 .
+.Pp
+The
+.Fn valloc
+function correctly allocated memory that could be deallocated via
+.Fn free
+starting in
+.Fx 7.0 .
diff --git a/lib/libc/gen/valloc.c b/lib/libc/gen/valloc.c
new file mode 100644
index 0000000..a5b0f75
--- /dev/null
+++ b/lib/libc/gen/valloc.c
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 1980, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)valloc.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <unistd.h>
+
+void *
+valloc(size_t i)
+{
+ void *ret;
+
+ if (posix_memalign(&ret, getpagesize(), i) != 0)
+ ret = NULL;
+
+ return ret;
+}
diff --git a/lib/libc/gen/vis.3 b/lib/libc/gen/vis.3
new file mode 100644
index 0000000..8ec16eb
--- /dev/null
+++ b/lib/libc/gen/vis.3
@@ -0,0 +1,308 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)vis.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd April 9, 2006
+.Dt VIS 3
+.Os
+.Sh NAME
+.Nm vis
+.Nd visually encode characters
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In vis.h
+.Ft char *
+.Fn vis "char *dst" "int c" "int flag" "int nextc"
+.Ft int
+.Fn strvis "char *dst" "const char *src" "int flag"
+.Ft int
+.Fn strvisx "char *dst" "const char *src" "size_t len" "int flag"
+.Sh DESCRIPTION
+The
+.Fn vis
+function
+copies into
+.Fa dst
+a string which represents the character
+.Fa c .
+If
+.Fa c
+needs no encoding, it is copied in unaltered.
+The string is
+null terminated, and a pointer to the end of the string is
+returned.
+The maximum length of any encoding is four
+characters (not including the trailing
+.Dv NUL ) ;
+thus, when
+encoding a set of characters into a buffer, the size of the buffer should
+be four times the number of characters encoded, plus one for the trailing
+.Dv NUL .
+The
+.Fa flag
+argument is used for altering the default range of
+characters considered for encoding and for altering the visual
+representation.
+The additional character,
+.Fa nextc ,
+is only used when selecting the
+.Dv VIS_CSTYLE
+encoding format (explained below).
+.Pp
+The
+.Fn strvis
+and
+.Fn strvisx
+functions copy into
+.Fa dst
+a visual representation of
+the string
+.Fa src .
+The
+.Fn strvis
+function encodes characters from
+.Fa src
+up to the
+first
+.Dv NUL .
+The
+.Fn strvisx
+function encodes exactly
+.Fa len
+characters from
+.Fa src
+(this
+is useful for encoding a block of data that may contain
+.Dv NUL Ns 's ) .
+Both forms
+.Dv NUL
+terminate
+.Fa dst .
+The size of
+.Fa dst
+must be four times the number
+of characters encoded from
+.Fa src
+(plus one for the
+.Dv NUL ) .
+Both
+forms return the number of characters in dst (not including
+the trailing
+.Dv NUL ) .
+.Pp
+The encoding is a unique, invertible representation composed entirely of
+graphic characters; it can be decoded back into the original form using
+the
+.Xr unvis 3
+or
+.Xr strunvis 3
+functions.
+.Pp
+There are two parameters that can be controlled: the range of
+characters that are encoded, and the type
+of representation used.
+By default, all non-graphic characters
+except space, tab, and newline are encoded.
+(See
+.Xr isgraph 3 . )
+The following flags
+alter this:
+.Bl -tag -width VIS_WHITEX
+.It Dv VIS_GLOB
+Also encode magic characters
+.Ql ( * ,
+.Ql \&? ,
+.Ql \&[
+and
+.Ql # )
+recognized by
+.Xr glob 3 .
+.It Dv VIS_SP
+Also encode space.
+.It Dv VIS_TAB
+Also encode tab.
+.It Dv VIS_NL
+Also encode newline.
+.It Dv VIS_WHITE
+Synonym for
+.Dv VIS_SP
+\&|
+.Dv VIS_TAB
+\&|
+.Dv VIS_NL .
+.It Dv VIS_SAFE
+Only encode "unsafe" characters.
+Unsafe means control
+characters which may cause common terminals to perform
+unexpected functions.
+Currently this form allows space,
+tab, newline, backspace, bell, and return - in addition
+to all graphic characters - unencoded.
+.El
+.Pp
+There are four forms of encoding.
+Most forms use the backslash character
+.Ql \e
+to introduce a special
+sequence; two backslashes are used to represent a real backslash.
+These are the visual formats:
+.Bl -tag -width VIS_HTTPSTYLE
+.It (default)
+Use an
+.Ql M
+to represent meta characters (characters with the 8th
+bit set), and use caret
+.Ql ^
+to represent control characters see
+.Pf ( Xr iscntrl 3 ) .
+The following formats are used:
+.Bl -tag -width xxxxx
+.It Dv \e^C
+Represents the control character
+.Ql C .
+Spans characters
+.Ql \e000
+through
+.Ql \e037 ,
+and
+.Ql \e177
+(as
+.Ql \e^? ) .
+.It Dv \eM-C
+Represents character
+.Ql C
+with the 8th bit set.
+Spans characters
+.Ql \e241
+through
+.Ql \e376 .
+.It Dv \eM^C
+Represents control character
+.Ql C
+with the 8th bit set.
+Spans characters
+.Ql \e200
+through
+.Ql \e237 ,
+and
+.Ql \e377
+(as
+.Ql \eM^? ) .
+.It Dv \e040
+Represents
+.Tn ASCII
+space.
+.It Dv \e240
+Represents Meta-space.
+.El
+.Pp
+.It Dv VIS_CSTYLE
+Use C-style backslash sequences to represent standard non-printable
+characters.
+The following sequences are used to represent the indicated characters:
+.Pp
+.Bl -tag -width ".Li \e0" -offset indent -compact
+.It Li \ea
+.Dv BEL No (007)
+.It Li \eb
+.Dv BS No (010)
+.It Li \ef
+.Dv NP No (014)
+.It Li \en
+.Dv NL No (012)
+.It Li \er
+.Dv CR No (015)
+.It Li \es
+.Dv SP No (040)
+.It Li \et
+.Dv HT No (011)
+.It Li \ev
+.Dv VT No (013)
+.It Li \e0
+.Dv NUL No (000)
+.El
+.Pp
+When using this format, the
+.Fa nextc
+argument is looked at to determine
+if a
+.Dv NUL
+character can be encoded as
+.Ql \e0
+instead of
+.Ql \e000 .
+If
+.Fa nextc
+is an octal digit, the latter representation is used to
+avoid ambiguity.
+.It Dv VIS_HTTPSTYLE
+Use URI encoding as described in RFC 1808.
+The form is
+.Ql %dd
+where
+.Ar d
+represents a hexadecimal digit.
+.It Dv VIS_OCTAL
+Use a three digit octal sequence.
+The form is
+.Ql \eddd
+where
+.Ar d
+represents an octal digit.
+.El
+.Pp
+There is one additional flag,
+.Dv VIS_NOSLASH ,
+which inhibits the
+doubling of backslashes and the backslash before the default
+format (that is, control characters are represented by
+.Ql ^C
+and
+meta characters as
+.Ql M-C ) .
+With this flag set, the encoding is
+ambiguous and non-invertible.
+.Sh SEE ALSO
+.Xr unvis 1 ,
+.Xr unvis 3
+.Rs
+.%A R. Fielding
+.%T Relative Uniform Resource Locators
+.%O RFC1808
+.Re
+.Sh HISTORY
+These functions first appeared in
+.Bx 4.4 .
+.Sh BUGS
+The
+.Nm
+family of functions do not recognize multibyte characters, and thus
+may consider them to be non-printable when they are in fact printable
+(and vice versa.)
diff --git a/lib/libc/gen/vis.c b/lib/libc/gen/vis.c
new file mode 100644
index 0000000..362f4dc
--- /dev/null
+++ b/lib/libc/gen/vis.c
@@ -0,0 +1,201 @@
+/*-
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vis.c 8.1 (Berkeley) 7/19/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <limits.h>
+#include <ctype.h>
+#include <stdio.h>
+#include <vis.h>
+
+#define isoctal(c) (((u_char)(c)) >= '0' && ((u_char)(c)) <= '7')
+
+/*
+ * vis - visually encode characters
+ */
+char *
+vis(dst, c, flag, nextc)
+ char *dst;
+ int c, nextc;
+ int flag;
+{
+ c = (unsigned char)c;
+
+ if (flag & VIS_HTTPSTYLE) {
+ /* Described in RFC 1808 */
+ if (!(isalnum(c) /* alpha-numeric */
+ /* safe */
+ || c == '$' || c == '-' || c == '_' || c == '.' || c == '+'
+ /* extra */
+ || c == '!' || c == '*' || c == '\'' || c == '('
+ || c == ')' || c == ',')) {
+ *dst++ = '%';
+ snprintf(dst, 4, (c < 16 ? "0%X" : "%X"), c);
+ dst += 2;
+ goto done;
+ }
+ }
+
+ if ((flag & VIS_GLOB) &&
+ (c == '*' || c == '?' || c == '[' || c == '#'))
+ ;
+ else if (isgraph(c) ||
+ ((flag & VIS_SP) == 0 && c == ' ') ||
+ ((flag & VIS_TAB) == 0 && c == '\t') ||
+ ((flag & VIS_NL) == 0 && c == '\n') ||
+ ((flag & VIS_SAFE) && (c == '\b' || c == '\007' || c == '\r'))) {
+ *dst++ = c;
+ if (c == '\\' && (flag & VIS_NOSLASH) == 0)
+ *dst++ = '\\';
+ *dst = '\0';
+ return (dst);
+ }
+
+ if (flag & VIS_CSTYLE) {
+ switch(c) {
+ case '\n':
+ *dst++ = '\\';
+ *dst++ = 'n';
+ goto done;
+ case '\r':
+ *dst++ = '\\';
+ *dst++ = 'r';
+ goto done;
+ case '\b':
+ *dst++ = '\\';
+ *dst++ = 'b';
+ goto done;
+ case '\a':
+ *dst++ = '\\';
+ *dst++ = 'a';
+ goto done;
+ case '\v':
+ *dst++ = '\\';
+ *dst++ = 'v';
+ goto done;
+ case '\t':
+ *dst++ = '\\';
+ *dst++ = 't';
+ goto done;
+ case '\f':
+ *dst++ = '\\';
+ *dst++ = 'f';
+ goto done;
+ case ' ':
+ *dst++ = '\\';
+ *dst++ = 's';
+ goto done;
+ case '\0':
+ *dst++ = '\\';
+ *dst++ = '0';
+ if (isoctal(nextc)) {
+ *dst++ = '0';
+ *dst++ = '0';
+ }
+ goto done;
+ }
+ }
+ if (((c & 0177) == ' ') || isgraph(c) || (flag & VIS_OCTAL)) {
+ *dst++ = '\\';
+ *dst++ = ((u_char)c >> 6 & 07) + '0';
+ *dst++ = ((u_char)c >> 3 & 07) + '0';
+ *dst++ = ((u_char)c & 07) + '0';
+ goto done;
+ }
+ if ((flag & VIS_NOSLASH) == 0)
+ *dst++ = '\\';
+ if (c & 0200) {
+ c &= 0177;
+ *dst++ = 'M';
+ }
+ if (iscntrl(c)) {
+ *dst++ = '^';
+ if (c == 0177)
+ *dst++ = '?';
+ else
+ *dst++ = c + '@';
+ } else {
+ *dst++ = '-';
+ *dst++ = c;
+ }
+done:
+ *dst = '\0';
+ return (dst);
+}
+
+/*
+ * strvis, strvisx - visually encode characters from src into dst
+ *
+ * Dst must be 4 times the size of src to account for possible
+ * expansion. The length of dst, not including the trailing NUL,
+ * is returned.
+ *
+ * Strvisx encodes exactly len bytes from src into dst.
+ * This is useful for encoding a block of data.
+ */
+int
+strvis(dst, src, flag)
+ char *dst;
+ const char *src;
+ int flag;
+{
+ char c;
+ char *start;
+
+ for (start = dst; (c = *src); )
+ dst = vis(dst, c, flag, *++src);
+ *dst = '\0';
+ return (dst - start);
+}
+
+int
+strvisx(dst, src, len, flag)
+ char *dst;
+ const char *src;
+ size_t len;
+ int flag;
+{
+ int c;
+ char *start;
+
+ for (start = dst; len > 1; len--) {
+ c = *src;
+ dst = vis(dst, c, flag, *++src);
+ }
+ if (len)
+ dst = vis(dst, *src, flag, '\0');
+ *dst = '\0';
+
+ return (dst - start);
+}
diff --git a/lib/libc/gen/wait.c b/lib/libc/gen/wait.c
new file mode 100644
index 0000000..2169b9d
--- /dev/null
+++ b/lib/libc/gen/wait.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)wait.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include "un-namespace.h"
+
+pid_t
+__wait(int *istat)
+{
+ return (_wait4(WAIT_ANY, istat, 0, (struct rusage *)0));
+}
+
+__weak_reference(__wait, wait);
+__weak_reference(__wait, _wait);
diff --git a/lib/libc/gen/wait3.c b/lib/libc/gen/wait3.c
new file mode 100644
index 0000000..6098773
--- /dev/null
+++ b/lib/libc/gen/wait3.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)wait3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include "un-namespace.h"
+
+pid_t
+wait3(istat, options, rup)
+ int *istat;
+ int options;
+ struct rusage *rup;
+{
+ return (_wait4(WAIT_ANY, istat, options, rup));
+}
diff --git a/lib/libc/gen/waitpid.c b/lib/libc/gen/waitpid.c
new file mode 100644
index 0000000..b001837
--- /dev/null
+++ b/lib/libc/gen/waitpid.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)waitpid.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/time.h>
+#include <sys/wait.h>
+#include <sys/resource.h>
+#include "un-namespace.h"
+
+pid_t
+__waitpid(pid_t pid, int *istat, int options)
+{
+ return (_wait4(pid, istat, options, (struct rusage *)0));
+}
+
+__weak_reference(__waitpid, waitpid);
+__weak_reference(__waitpid, _waitpid);
diff --git a/lib/libc/gen/wordexp.3 b/lib/libc/gen/wordexp.3
new file mode 100644
index 0000000..02fc253
--- /dev/null
+++ b/lib/libc/gen/wordexp.3
@@ -0,0 +1,206 @@
+.\"
+.\" Copyright (c) 2002 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 29, 2004
+.Dt WORDEXP 3
+.Os
+.Sh NAME
+.Nm wordexp
+.Nd "perform shell-style word expansions"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wordexp.h
+.Ft int
+.Fn wordexp "const char * restrict words" "wordexp_t * restrict we" "int flags"
+.Ft void
+.Fn wordfree "wordexp_t *we"
+.Sh DESCRIPTION
+The
+.Fn wordexp
+function performs shell-style word expansion on
+.Fa words
+and places the list of words into the
+.Va we_wordv
+member of
+.Fa we ,
+and the number of words into
+.Va we_wordc .
+.Pp
+The
+.Fa flags
+argument is the bitwise inclusive OR of any of the following constants:
+.Bl -tag -width ".Dv WRDE_SHOWERR"
+.It Dv WRDE_APPEND
+Append the words to those generated by a previous call to
+.Fn wordexp .
+.It Dv WRDE_DOOFFS
+As many
+.Dv NULL
+pointers as are specified by the
+.Va we_offs
+member of
+.Fa we
+are added to the front of
+.Va we_wordv .
+.It Dv WRDE_NOCMD
+Disallow command substitution in
+.Fa words .
+See the note in
+.Sx BUGS
+before using this.
+.It Dv WRDE_REUSE
+The
+.Fa we
+argument was passed to a previous successful call to
+.Fn wordexp
+but has not been passed to
+.Fn wordfree .
+The implementation may reuse the space allocated to it.
+.It Dv WRDE_SHOWERR
+Do not redirect shell error messages to
+.Pa /dev/null .
+.It Dv WRDE_UNDEF
+Report error on an attempt to expand an undefined shell variable.
+.El
+.Pp
+The
+.Vt wordexp_t
+structure is defined in
+.In wordexp.h
+as:
+.Bd -literal -offset indent
+typedef struct {
+ size_t we_wordc; /* count of words matched */
+ char **we_wordv; /* pointer to list of words */
+ size_t we_offs; /* slots to reserve in we_wordv */
+} wordexp_t;
+.Ed
+.Pp
+The
+.Fn wordfree
+function frees the memory allocated by
+.Fn wordexp .
+.Sh IMPLEMENTATION NOTES
+The
+.Fn wordexp
+function is implemented as a wrapper around the undocumented
+.Ic wordexp
+shell built-in command.
+.Sh RETURN VALUES
+The
+.Fn wordexp
+function returns zero if successful, otherwise it returns one of the following
+error codes:
+.Bl -tag -width ".Dv WRDE_NOSPACE"
+.It Dv WRDE_BADCHAR
+The
+.Fa words
+argument contains one of the following unquoted characters:
+.Aq newline ,
+.Ql | ,
+.Ql & ,
+.Ql \&; ,
+.Ql < ,
+.Ql > ,
+.Ql \&( ,
+.Ql \&) ,
+.Ql { ,
+.Ql } .
+.It Dv WRDE_BADVAL
+An attempt was made to expand an undefined shell variable and
+.Dv WRDE_UNDEF
+is set in
+.Fa flags .
+.It Dv WRDE_CMDSUB
+An attempt was made to use command substitution and
+.Dv WRDE_NOCMD
+is set in
+.Fa flags .
+.It Dv WRDE_NOSPACE
+Not enough memory to store the result.
+.It Dv WRDE_SYNTAX
+Shell syntax error in
+.Fa words .
+.El
+.Pp
+The
+.Fn wordfree
+function returns no value.
+.Sh ENVIRONMENT
+.Bl -tag -width ".Ev IFS"
+.It Ev IFS
+Field separator.
+.El
+.Sh EXAMPLES
+Invoke the editor on all
+.Pa .c
+files in the current directory
+and
+.Pa /etc/motd
+(error checking omitted):
+.Bd -literal -offset indent
+wordexp_t we;
+
+wordexp("${EDITOR:-vi} *.c /etc/motd", &we, 0);
+execvp(we.we_wordv[0], we.we_wordv);
+.Ed
+.Sh DIAGNOSTICS
+Diagnostic messages from the shell are written to the standard error output
+if
+.Dv WRDE_SHOWERR
+is set in
+.Fa flags .
+.Sh SEE ALSO
+.Xr sh 1 ,
+.Xr fnmatch 3 ,
+.Xr glob 3 ,
+.Xr popen 3 ,
+.Xr system 3
+.Sh STANDARDS
+The
+.Fn wordexp
+and
+.Fn wordfree
+functions conform to
+.St -p1003.1-2001 .
+.Sh BUGS
+Do not pass untrusted user data to
+.Fn wordexp ,
+regardless of whether the
+.Dv WRDE_NOCMD
+flag is set.
+The
+.Fn wordexp
+function attempts to detect input that would cause commands to be
+executed before passing it to the shell
+but it does not use the same parser so it may be fooled.
+.Pp
+The current
+.Fn wordexp
+implementation does not recognize multibyte characters, since the
+shell (which it invokes to perform expansions) does not.
diff --git a/lib/libc/gen/wordexp.c b/lib/libc/gen/wordexp.c
new file mode 100644
index 0000000..bcab1f5
--- /dev/null
+++ b/lib/libc/gen/wordexp.c
@@ -0,0 +1,354 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "namespace.h"
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <paths.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <wordexp.h>
+#include "un-namespace.h"
+
+__FBSDID("$FreeBSD$");
+
+static int we_askshell(const char *, wordexp_t *, int);
+static int we_check(const char *, int);
+
+/*
+ * wordexp --
+ * Perform shell word expansion on `words' and place the resulting list
+ * of words in `we'. See wordexp(3).
+ *
+ * Specified by IEEE Std. 1003.1-2001.
+ */
+int
+wordexp(const char * __restrict words, wordexp_t * __restrict we, int flags)
+{
+ int error;
+
+ if (flags & WRDE_REUSE)
+ wordfree(we);
+ if ((flags & WRDE_APPEND) == 0) {
+ we->we_wordc = 0;
+ we->we_wordv = NULL;
+ we->we_strings = NULL;
+ we->we_nbytes = 0;
+ }
+ if ((error = we_check(words, flags)) != 0) {
+ wordfree(we);
+ return (error);
+ }
+ if ((error = we_askshell(words, we, flags)) != 0) {
+ wordfree(we);
+ return (error);
+ }
+ return (0);
+}
+
+static size_t
+we_read_fully(int fd, char *buffer, size_t len)
+{
+ size_t done;
+ ssize_t nread;
+
+ done = 0;
+ do {
+ nread = _read(fd, buffer + done, len - done);
+ if (nread == -1 && errno == EINTR)
+ continue;
+ if (nread <= 0)
+ break;
+ done += nread;
+ } while (done != len);
+ return done;
+}
+
+/*
+ * we_askshell --
+ * Use the `wordexp' /bin/sh builtin function to do most of the work
+ * in expanding the word string. This function is complicated by
+ * memory management.
+ */
+static int
+we_askshell(const char *words, wordexp_t *we, int flags)
+{
+ int pdes[2]; /* Pipe to child */
+ char bbuf[9]; /* Buffer for byte count */
+ char wbuf[9]; /* Buffer for word count */
+ long nwords, nbytes; /* Number of words, bytes from child */
+ long i; /* Handy integer */
+ size_t sofs; /* Offset into we->we_strings */
+ size_t vofs; /* Offset into we->we_wordv */
+ pid_t pid; /* Process ID of child */
+ pid_t wpid; /* waitpid return value */
+ int status; /* Child exit status */
+ int error; /* Our return value */
+ int serrno; /* errno to return */
+ char *ifs; /* IFS env. var. */
+ char *np, *p; /* Handy pointers */
+ char *nstrings; /* Temporary for realloc() */
+ char **nwv; /* Temporary for realloc() */
+ sigset_t newsigblock, oldsigblock;
+
+ serrno = errno;
+ if ((ifs = getenv("IFS")) == NULL)
+ ifs = " \t\n";
+
+ if (pipe(pdes) < 0)
+ return (WRDE_NOSPACE); /* XXX */
+ (void)sigemptyset(&newsigblock);
+ (void)sigaddset(&newsigblock, SIGCHLD);
+ (void)_sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock);
+ if ((pid = fork()) < 0) {
+ serrno = errno;
+ _close(pdes[0]);
+ _close(pdes[1]);
+ (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
+ errno = serrno;
+ return (WRDE_NOSPACE); /* XXX */
+ }
+ else if (pid == 0) {
+ /*
+ * We are the child; just get /bin/sh to run the wordexp
+ * builtin on `words'.
+ */
+ int devnull;
+ char *cmd;
+
+ (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
+ _close(pdes[0]);
+ if (_dup2(pdes[1], STDOUT_FILENO) < 0)
+ _exit(1);
+ _close(pdes[1]);
+ if (asprintf(&cmd, "wordexp%c%s\n", *ifs, words) < 0)
+ _exit(1);
+ if ((flags & WRDE_SHOWERR) == 0) {
+ if ((devnull = _open(_PATH_DEVNULL, O_RDWR, 0666)) < 0)
+ _exit(1);
+ if (_dup2(devnull, STDERR_FILENO) < 0)
+ _exit(1);
+ _close(devnull);
+ }
+ execl(_PATH_BSHELL, "sh", flags & WRDE_UNDEF ? "-u" : "+u",
+ "-c", cmd, (char *)NULL);
+ _exit(1);
+ }
+
+ /*
+ * We are the parent; read the output of the shell wordexp function,
+ * which is a 32-bit hexadecimal word count, a 32-bit hexadecimal
+ * byte count (not including terminating null bytes), followed by
+ * the expanded words separated by nulls.
+ */
+ _close(pdes[1]);
+ if (we_read_fully(pdes[0], wbuf, 8) != 8 ||
+ we_read_fully(pdes[0], bbuf, 8) != 8) {
+ error = flags & WRDE_UNDEF ? WRDE_BADVAL : WRDE_SYNTAX;
+ serrno = errno;
+ goto cleanup;
+ }
+ wbuf[8] = bbuf[8] = '\0';
+ nwords = strtol(wbuf, NULL, 16);
+ nbytes = strtol(bbuf, NULL, 16) + nwords;
+
+ /*
+ * Allocate or reallocate (when flags & WRDE_APPEND) the word vector
+ * and string storage buffers for the expanded words we're about to
+ * read from the child.
+ */
+ sofs = we->we_nbytes;
+ vofs = we->we_wordc;
+ if ((flags & (WRDE_DOOFFS|WRDE_APPEND)) == (WRDE_DOOFFS|WRDE_APPEND))
+ vofs += we->we_offs;
+ we->we_wordc += nwords;
+ we->we_nbytes += nbytes;
+ if ((nwv = realloc(we->we_wordv, (we->we_wordc + 1 +
+ (flags & WRDE_DOOFFS ? we->we_offs : 0)) *
+ sizeof(char *))) == NULL) {
+ error = WRDE_NOSPACE;
+ goto cleanup;
+ }
+ we->we_wordv = nwv;
+ if ((nstrings = realloc(we->we_strings, we->we_nbytes)) == NULL) {
+ error = WRDE_NOSPACE;
+ goto cleanup;
+ }
+ for (i = 0; i < vofs; i++)
+ if (we->we_wordv[i] != NULL)
+ we->we_wordv[i] += nstrings - we->we_strings;
+ we->we_strings = nstrings;
+
+ if (we_read_fully(pdes[0], we->we_strings + sofs, nbytes) != nbytes) {
+ error = flags & WRDE_UNDEF ? WRDE_BADVAL : WRDE_SYNTAX;
+ serrno = errno;
+ goto cleanup;
+ }
+
+ error = 0;
+cleanup:
+ _close(pdes[0]);
+ do
+ wpid = _waitpid(pid, &status, 0);
+ while (wpid < 0 && errno == EINTR);
+ (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
+ if (error != 0) {
+ errno = serrno;
+ return (error);
+ }
+ if (wpid < 0 || !WIFEXITED(status) || WEXITSTATUS(status) != 0)
+ return (flags & WRDE_UNDEF ? WRDE_BADVAL : WRDE_SYNTAX);
+
+ /*
+ * Break the null-terminated expanded word strings out into
+ * the vector.
+ */
+ if (vofs == 0 && flags & WRDE_DOOFFS)
+ while (vofs < we->we_offs)
+ we->we_wordv[vofs++] = NULL;
+ p = we->we_strings + sofs;
+ while (nwords-- != 0) {
+ we->we_wordv[vofs++] = p;
+ if ((np = memchr(p, '\0', nbytes)) == NULL)
+ return (WRDE_NOSPACE); /* XXX */
+ nbytes -= np - p + 1;
+ p = np + 1;
+ }
+ we->we_wordv[vofs] = NULL;
+
+ return (0);
+}
+
+/*
+ * we_check --
+ * Check that the string contains none of the following unquoted
+ * special characters: <newline> |&;<>(){}
+ * or command substitutions when WRDE_NOCMD is set in flags.
+ */
+static int
+we_check(const char *words, int flags)
+{
+ char c;
+ int dquote, level, quote, squote;
+
+ quote = squote = dquote = 0;
+ while ((c = *words++) != '\0') {
+ switch (c) {
+ case '\\':
+ quote ^= 1;
+ continue;
+ case '\'':
+ if (quote + dquote == 0)
+ squote ^= 1;
+ break;
+ case '"':
+ if (quote + squote == 0)
+ dquote ^= 1;
+ break;
+ case '`':
+ if (quote + squote == 0 && flags & WRDE_NOCMD)
+ return (WRDE_CMDSUB);
+ while ((c = *words++) != '\0' && c != '`')
+ if (c == '\\' && (c = *words++) == '\0')
+ break;
+ if (c == '\0')
+ return (WRDE_SYNTAX);
+ break;
+ case '|': case '&': case ';': case '<': case '>':
+ case '{': case '}': case '(': case ')': case '\n':
+ if (quote + squote + dquote == 0)
+ return (WRDE_BADCHAR);
+ break;
+ case '$':
+ if ((c = *words++) == '\0')
+ break;
+ else if (quote + squote == 0 && c == '(') {
+ if (flags & WRDE_NOCMD && *words != '(')
+ return (WRDE_CMDSUB);
+ level = 1;
+ while ((c = *words++) != '\0') {
+ if (c == '\\') {
+ if ((c = *words++) == '\0')
+ break;
+ } else if (c == '(')
+ level++;
+ else if (c == ')' && --level == 0)
+ break;
+ }
+ if (c == '\0' || level != 0)
+ return (WRDE_SYNTAX);
+ } else if (quote + squote == 0 && c == '{') {
+ level = 1;
+ while ((c = *words++) != '\0') {
+ if (c == '\\') {
+ if ((c = *words++) == '\0')
+ break;
+ } else if (c == '{')
+ level++;
+ else if (c == '}' && --level == 0)
+ break;
+ }
+ if (c == '\0' || level != 0)
+ return (WRDE_SYNTAX);
+ } else
+ --words;
+ break;
+ default:
+ break;
+ }
+ quote = 0;
+ }
+ if (quote + squote + dquote != 0)
+ return (WRDE_SYNTAX);
+
+ return (0);
+}
+
+/*
+ * wordfree --
+ * Free the result of wordexp(). See wordexp(3).
+ *
+ * Specified by IEEE Std. 1003.1-2001.
+ */
+void
+wordfree(wordexp_t *we)
+{
+
+ if (we == NULL)
+ return;
+ free(we->we_wordv);
+ free(we->we_strings);
+ we->we_wordv = NULL;
+ we->we_strings = NULL;
+ we->we_nbytes = 0;
+ we->we_wordc = 0;
+}
diff --git a/lib/libc/gmon/Makefile.inc b/lib/libc/gmon/Makefile.inc
new file mode 100644
index 0000000..98c7395
--- /dev/null
+++ b/lib/libc/gmon/Makefile.inc
@@ -0,0 +1,17 @@
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+# gmon sources
+.PATH: ${.CURDIR}/gmon
+
+SRCS+= gmon.c mcount.c
+
+SYM_MAPS+=${.CURDIR}/gmon/Symbol.map
+
+MAN+= moncontrol.3
+
+MLINKS+=moncontrol.3 monstartup.3
+
+# mcount cannot be compiled with profiling
+mcount.po: mcount.o
+ cp mcount.o mcount.po
diff --git a/lib/libc/gmon/Symbol.map b/lib/libc/gmon/Symbol.map
new file mode 100644
index 0000000..8227899
--- /dev/null
+++ b/lib/libc/gmon/Symbol.map
@@ -0,0 +1,14 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ _mcleanup;
+ monstartup;
+ moncontrol;
+ mexitcount;
+};
+
+FBSDprivate_1.0 {
+ _gmonparam;
+};
diff --git a/lib/libc/gmon/gmon.c b/lib/libc/gmon/gmon.c
new file mode 100644
index 0000000..edf4e2f
--- /dev/null
+++ b/lib/libc/gmon/gmon.c
@@ -0,0 +1,250 @@
+/*-
+ * Copyright (c) 1983, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gmon.c 8.1 (Berkeley) 6/4/93";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/gmon.h>
+#include <sys/sysctl.h>
+
+#include <err.h>
+#include <fcntl.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+#if defined(__i386__) || defined(__sparc64__) || defined(__amd64__) || (defined(__powerpc__) && !defined(__powerpc64__))
+extern char *minbrk __asm (".minbrk");
+#elif defined(__powerpc64__)
+extern char *minbrk __asm ("_minbrk");
+#else
+extern char *minbrk __asm ("minbrk");
+#endif
+
+struct gmonparam _gmonparam = { GMON_PROF_OFF };
+
+static int s_scale;
+/* See profil(2) where this is described (incorrectly). */
+#define SCALE_SHIFT 16
+
+#define ERR(s) _write(2, s, sizeof(s))
+
+void moncontrol(int);
+static int hertz(void);
+
+void
+monstartup(lowpc, highpc)
+ u_long lowpc;
+ u_long highpc;
+{
+ int o;
+ char *cp;
+ struct gmonparam *p = &_gmonparam;
+
+ /*
+ * round lowpc and highpc to multiples of the density we're using
+ * so the rest of the scaling (here and in gprof) stays in ints.
+ */
+ p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER));
+ p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER));
+ p->textsize = p->highpc - p->lowpc;
+ p->kcountsize = p->textsize / HISTFRACTION;
+ p->hashfraction = HASHFRACTION;
+ p->fromssize = p->textsize / HASHFRACTION;
+ p->tolimit = p->textsize * ARCDENSITY / 100;
+ if (p->tolimit < MINARCS)
+ p->tolimit = MINARCS;
+ else if (p->tolimit > MAXARCS)
+ p->tolimit = MAXARCS;
+ p->tossize = p->tolimit * sizeof(struct tostruct);
+
+ cp = sbrk(p->kcountsize + p->fromssize + p->tossize);
+ if (cp == (char *)-1) {
+ ERR("monstartup: out of memory\n");
+ return;
+ }
+#ifdef notdef
+ bzero(cp, p->kcountsize + p->fromssize + p->tossize);
+#endif
+ p->tos = (struct tostruct *)cp;
+ cp += p->tossize;
+ p->kcount = (u_short *)cp;
+ cp += p->kcountsize;
+ p->froms = (u_short *)cp;
+
+ minbrk = sbrk(0);
+ p->tos[0].link = 0;
+
+ o = p->highpc - p->lowpc;
+ s_scale = (p->kcountsize < o) ?
+ ((uintmax_t)p->kcountsize << SCALE_SHIFT) / o : (1 << SCALE_SHIFT);
+ moncontrol(1);
+}
+
+void
+_mcleanup(void)
+{
+ int fd;
+ int fromindex;
+ int endfrom;
+ u_long frompc;
+ int toindex;
+ struct rawarc rawarc;
+ struct gmonparam *p = &_gmonparam;
+ struct gmonhdr gmonhdr, *hdr;
+ struct clockinfo clockinfo;
+ char outname[128];
+ int mib[2];
+ size_t size;
+#ifdef DEBUG
+ int log, len;
+ char buf[200];
+#endif
+
+ if (p->state == GMON_PROF_ERROR)
+ ERR("_mcleanup: tos overflow\n");
+
+ size = sizeof(clockinfo);
+ mib[0] = CTL_KERN;
+ mib[1] = KERN_CLOCKRATE;
+ if (sysctl(mib, 2, &clockinfo, &size, NULL, 0) < 0) {
+ /*
+ * Best guess
+ */
+ clockinfo.profhz = hertz();
+ } else if (clockinfo.profhz == 0) {
+ if (clockinfo.hz != 0)
+ clockinfo.profhz = clockinfo.hz;
+ else
+ clockinfo.profhz = hertz();
+ }
+
+ moncontrol(0);
+ snprintf(outname, sizeof(outname), "%s.gmon", _getprogname());
+ fd = _open(outname, O_CREAT|O_TRUNC|O_WRONLY, 0666);
+ if (fd < 0) {
+ _warn("_mcleanup: %s", outname);
+ return;
+ }
+#ifdef DEBUG
+ log = _open("gmon.log", O_CREAT|O_TRUNC|O_WRONLY, 0664);
+ if (log < 0) {
+ _warn("_mcleanup: gmon.log");
+ return;
+ }
+ len = sprintf(buf, "[mcleanup1] kcount 0x%p ssiz %lu\n",
+ p->kcount, p->kcountsize);
+ _write(log, buf, len);
+#endif
+ hdr = (struct gmonhdr *)&gmonhdr;
+ bzero(hdr, sizeof(*hdr));
+ hdr->lpc = p->lowpc;
+ hdr->hpc = p->highpc;
+ hdr->ncnt = p->kcountsize + sizeof(gmonhdr);
+ hdr->version = GMONVERSION;
+ hdr->profrate = clockinfo.profhz;
+ _write(fd, (char *)hdr, sizeof *hdr);
+ _write(fd, p->kcount, p->kcountsize);
+ endfrom = p->fromssize / sizeof(*p->froms);
+ for (fromindex = 0; fromindex < endfrom; fromindex++) {
+ if (p->froms[fromindex] == 0)
+ continue;
+
+ frompc = p->lowpc;
+ frompc += fromindex * p->hashfraction * sizeof(*p->froms);
+ for (toindex = p->froms[fromindex]; toindex != 0;
+ toindex = p->tos[toindex].link) {
+#ifdef DEBUG
+ len = sprintf(buf,
+ "[mcleanup2] frompc 0x%lx selfpc 0x%lx count %lu\n" ,
+ frompc, p->tos[toindex].selfpc,
+ p->tos[toindex].count);
+ _write(log, buf, len);
+#endif
+ rawarc.raw_frompc = frompc;
+ rawarc.raw_selfpc = p->tos[toindex].selfpc;
+ rawarc.raw_count = p->tos[toindex].count;
+ _write(fd, &rawarc, sizeof rawarc);
+ }
+ }
+ _close(fd);
+}
+
+/*
+ * Control profiling
+ * profiling is what mcount checks to see if
+ * all the data structures are ready.
+ */
+void
+moncontrol(mode)
+ int mode;
+{
+ struct gmonparam *p = &_gmonparam;
+
+ if (mode) {
+ /* start */
+ profil((char *)p->kcount, p->kcountsize, p->lowpc, s_scale);
+ p->state = GMON_PROF_ON;
+ } else {
+ /* stop */
+ profil((char *)0, 0, 0, 0);
+ p->state = GMON_PROF_OFF;
+ }
+}
+
+/*
+ * discover the tick frequency of the machine
+ * if something goes wrong, we return 0, an impossible hertz.
+ */
+static int
+hertz()
+{
+ struct itimerval tim;
+
+ tim.it_interval.tv_sec = 0;
+ tim.it_interval.tv_usec = 1;
+ tim.it_value.tv_sec = 0;
+ tim.it_value.tv_usec = 0;
+ setitimer(ITIMER_REAL, &tim, 0);
+ setitimer(ITIMER_REAL, 0, &tim);
+ if (tim.it_interval.tv_usec < 2)
+ return(0);
+ return (1000000 / tim.it_interval.tv_usec);
+}
diff --git a/lib/libc/gmon/mcount.c b/lib/libc/gmon/mcount.c
new file mode 100644
index 0000000..02f3efd
--- /dev/null
+++ b/lib/libc/gmon/mcount.c
@@ -0,0 +1,321 @@
+/*-
+ * Copyright (c) 1983, 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if !defined(_KERNEL) && defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)mcount.c 8.1 (Berkeley) 6/4/93";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/gmon.h>
+#ifdef _KERNEL
+#include <sys/systm.h>
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+void bintr(void);
+void btrap(void);
+void eintr(void);
+void user(void);
+#endif
+#include <machine/atomic.h>
+
+/*
+ * mcount is called on entry to each function compiled with the profiling
+ * switch set. _mcount(), which is declared in a machine-dependent way
+ * with _MCOUNT_DECL, does the actual work and is either inlined into a
+ * C routine or called by an assembly stub. In any case, this magic is
+ * taken care of by the MCOUNT definition in <machine/profile.h>.
+ *
+ * _mcount updates data structures that represent traversals of the
+ * program's call graph edges. frompc and selfpc are the return
+ * address and function address that represents the given call graph edge.
+ *
+ * Note: the original BSD code used the same variable (frompcindex) for
+ * both frompcindex and frompc. Any reasonable, modern compiler will
+ * perform this optimization.
+ */
+/* _mcount; may be static, inline, etc */
+_MCOUNT_DECL(uintfptr_t frompc, uintfptr_t selfpc)
+{
+#ifdef GUPROF
+ u_int delta;
+#endif
+ fptrdiff_t frompci;
+ u_short *frompcindex;
+ struct tostruct *top, *prevtop;
+ struct gmonparam *p;
+ long toindex;
+#ifdef _KERNEL
+ MCOUNT_DECL(s)
+#endif
+
+ p = &_gmonparam;
+#ifndef GUPROF /* XXX */
+ /*
+ * check that we are profiling
+ * and that we aren't recursively invoked.
+ */
+ if (p->state != GMON_PROF_ON)
+ return;
+#endif
+#ifdef _KERNEL
+ MCOUNT_ENTER(s);
+#else
+ if (!atomic_cmpset_acq_int(&p->state, GMON_PROF_ON, GMON_PROF_BUSY))
+ return;
+#endif
+ frompci = frompc - p->lowpc;
+
+#ifdef _KERNEL
+ /*
+ * When we are called from an exception handler, frompci may be
+ * for a user address. Convert such frompci's to the index of
+ * user() to merge all user counts.
+ */
+ if (frompci >= p->textsize) {
+ if (frompci + p->lowpc
+ >= (uintfptr_t)(VM_MAXUSER_ADDRESS + UPAGES * PAGE_SIZE))
+ goto done;
+ frompci = (uintfptr_t)user - p->lowpc;
+ if (frompci >= p->textsize)
+ goto done;
+ }
+#endif
+
+#ifdef GUPROF
+ if (p->state != GMON_PROF_HIRES)
+ goto skip_guprof_stuff;
+ /*
+ * Look at the clock and add the count of clock cycles since the
+ * clock was last looked at to a counter for frompc. This
+ * solidifies the count for the function containing frompc and
+ * effectively starts another clock for the current function.
+ * The count for the new clock will be solidified when another
+ * function call is made or the function returns.
+ *
+ * We use the usual sampling counters since they can be located
+ * efficiently. 4-byte counters are usually necessary.
+ *
+ * There are many complications for subtracting the profiling
+ * overheads from the counts for normal functions and adding
+ * them to the counts for mcount(), mexitcount() and cputime().
+ * We attempt to handle fractional cycles, but the overheads
+ * are usually underestimated because they are calibrated for
+ * a simpler than usual setup.
+ */
+ delta = cputime() - p->mcount_overhead;
+ p->cputime_overhead_resid += p->cputime_overhead_frac;
+ p->mcount_overhead_resid += p->mcount_overhead_frac;
+ if ((int)delta < 0)
+ *p->mcount_count += delta + p->mcount_overhead
+ - p->cputime_overhead;
+ else if (delta != 0) {
+ if (p->cputime_overhead_resid >= CALIB_SCALE) {
+ p->cputime_overhead_resid -= CALIB_SCALE;
+ ++*p->cputime_count;
+ --delta;
+ }
+ if (delta != 0) {
+ if (p->mcount_overhead_resid >= CALIB_SCALE) {
+ p->mcount_overhead_resid -= CALIB_SCALE;
+ ++*p->mcount_count;
+ --delta;
+ }
+ KCOUNT(p, frompci) += delta;
+ }
+ *p->mcount_count += p->mcount_overhead_sub;
+ }
+ *p->cputime_count += p->cputime_overhead;
+skip_guprof_stuff:
+#endif /* GUPROF */
+
+#ifdef _KERNEL
+ /*
+ * When we are called from an exception handler, frompc is faked
+ * to be for where the exception occurred. We've just solidified
+ * the count for there. Now convert frompci to the index of btrap()
+ * for trap handlers and bintr() for interrupt handlers to make
+ * exceptions appear in the call graph as calls from btrap() and
+ * bintr() instead of calls from all over.
+ */
+ if ((uintfptr_t)selfpc >= (uintfptr_t)btrap
+ && (uintfptr_t)selfpc < (uintfptr_t)eintr) {
+ if ((uintfptr_t)selfpc >= (uintfptr_t)bintr)
+ frompci = (uintfptr_t)bintr - p->lowpc;
+ else
+ frompci = (uintfptr_t)btrap - p->lowpc;
+ }
+#endif
+
+ /*
+ * check that frompc is a reasonable pc value.
+ * for example: signal catchers get called from the stack,
+ * not from text space. too bad.
+ */
+ if (frompci >= p->textsize)
+ goto done;
+
+ frompcindex = &p->froms[frompci / (p->hashfraction * sizeof(*p->froms))];
+ toindex = *frompcindex;
+ if (toindex == 0) {
+ /*
+ * first time traversing this arc
+ */
+ toindex = ++p->tos[0].link;
+ if (toindex >= p->tolimit)
+ /* halt further profiling */
+ goto overflow;
+
+ *frompcindex = toindex;
+ top = &p->tos[toindex];
+ top->selfpc = selfpc;
+ top->count = 1;
+ top->link = 0;
+ goto done;
+ }
+ top = &p->tos[toindex];
+ if (top->selfpc == selfpc) {
+ /*
+ * arc at front of chain; usual case.
+ */
+ top->count++;
+ goto done;
+ }
+ /*
+ * have to go looking down chain for it.
+ * top points to what we are looking at,
+ * prevtop points to previous top.
+ * we know it is not at the head of the chain.
+ */
+ for (; /* goto done */; ) {
+ if (top->link == 0) {
+ /*
+ * top is end of the chain and none of the chain
+ * had top->selfpc == selfpc.
+ * so we allocate a new tostruct
+ * and link it to the head of the chain.
+ */
+ toindex = ++p->tos[0].link;
+ if (toindex >= p->tolimit)
+ goto overflow;
+
+ top = &p->tos[toindex];
+ top->selfpc = selfpc;
+ top->count = 1;
+ top->link = *frompcindex;
+ *frompcindex = toindex;
+ goto done;
+ }
+ /*
+ * otherwise, check the next arc on the chain.
+ */
+ prevtop = top;
+ top = &p->tos[top->link];
+ if (top->selfpc == selfpc) {
+ /*
+ * there it is.
+ * increment its count
+ * move it to the head of the chain.
+ */
+ top->count++;
+ toindex = prevtop->link;
+ prevtop->link = top->link;
+ top->link = *frompcindex;
+ *frompcindex = toindex;
+ goto done;
+ }
+
+ }
+done:
+#ifdef _KERNEL
+ MCOUNT_EXIT(s);
+#else
+ atomic_store_rel_int(&p->state, GMON_PROF_ON);
+#endif
+ return;
+overflow:
+ atomic_store_rel_int(&p->state, GMON_PROF_ERROR);
+#ifdef _KERNEL
+ MCOUNT_EXIT(s);
+#endif
+ return;
+}
+
+/*
+ * Actual definition of mcount function. Defined in <machine/profile.h>,
+ * which is included by <sys/gmon.h>.
+ */
+MCOUNT
+
+#ifdef GUPROF
+void
+mexitcount(selfpc)
+ uintfptr_t selfpc;
+{
+ struct gmonparam *p;
+ uintfptr_t selfpcdiff;
+
+ p = &_gmonparam;
+ selfpcdiff = selfpc - (uintfptr_t)p->lowpc;
+ if (selfpcdiff < p->textsize) {
+ u_int delta;
+
+ /*
+ * Solidify the count for the current function.
+ */
+ delta = cputime() - p->mexitcount_overhead;
+ p->cputime_overhead_resid += p->cputime_overhead_frac;
+ p->mexitcount_overhead_resid += p->mexitcount_overhead_frac;
+ if ((int)delta < 0)
+ *p->mexitcount_count += delta + p->mexitcount_overhead
+ - p->cputime_overhead;
+ else if (delta != 0) {
+ if (p->cputime_overhead_resid >= CALIB_SCALE) {
+ p->cputime_overhead_resid -= CALIB_SCALE;
+ ++*p->cputime_count;
+ --delta;
+ }
+ if (delta != 0) {
+ if (p->mexitcount_overhead_resid
+ >= CALIB_SCALE) {
+ p->mexitcount_overhead_resid
+ -= CALIB_SCALE;
+ ++*p->mexitcount_count;
+ --delta;
+ }
+ KCOUNT(p, selfpcdiff) += delta;
+ }
+ *p->mexitcount_count += p->mexitcount_overhead_sub;
+ }
+ *p->cputime_count += p->cputime_overhead;
+ }
+}
+#endif /* GUPROF */
diff --git a/lib/libc/gmon/moncontrol.3 b/lib/libc/gmon/moncontrol.3
new file mode 100644
index 0000000..7979a71
--- /dev/null
+++ b/lib/libc/gmon/moncontrol.3
@@ -0,0 +1,110 @@
+.\" Copyright (c) 1980, 1991, 1992, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)moncontrol.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 14, 2004
+.Dt MONCONTROL 3
+.Os
+.Sh NAME
+.Nm moncontrol ,
+.Nm monstartup
+.Nd control execution profile
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/gmon.h
+.Ft void
+.Fn moncontrol "int mode"
+.Ft void
+.Fn monstartup "u_long lowpc" "u_long highpc"
+.Sh DESCRIPTION
+An executable program compiled using the
+.Fl pg
+option to
+.Xr cc 1
+automatically includes calls to collect statistics for the
+.Xr gprof 1
+call-graph execution profiler.
+In typical operation, profiling begins at program startup
+and ends when the program calls exit.
+When the program exits, the profiling data are written to the file
+.Ar progname Ns Pa .gmon ,
+where progname is the name of the program, then
+.Xr gprof 1
+can be used to examine the results.
+.Pp
+The
+.Fn moncontrol
+function
+selectively controls profiling within a program.
+When the program starts, profiling begins.
+To stop the collection of histogram ticks and call counts use
+.Fn moncontrol 0 ;
+to resume the collection of histogram ticks and call counts use
+.Fn moncontrol 1 .
+This feature allows the cost of particular operations to be measured.
+Note that an output file will be produced on program exit
+regardless of the state of
+.Fn moncontrol .
+.Pp
+Programs that are not loaded with
+.Fl pg
+may selectively collect profiling statistics by calling
+.Fn monstartup
+with the range of addresses to be profiled.
+The
+.Fa lowpc
+and
+.Fa highpc
+arguments
+specify the address range that is to be sampled;
+the lowest address sampled is that of
+.Fa lowpc
+and the highest is just below
+.Fa highpc .
+Only functions in that range that have been compiled with the
+.Fl pg
+option to
+.Xr cc 1
+will appear in the call graph part of the output;
+however, all functions in that address range will
+have their execution time measured.
+Profiling begins on return from
+.Fn monstartup .
+.Sh FILES
+.Bl -tag -width progname.gmon -compact
+.It Pa progname.gmon
+execution data file
+.El
+.Sh SEE ALSO
+.Xr cc 1 ,
+.Xr gprof 1 ,
+.Xr profil 2 ,
+.Xr clocks 7
diff --git a/lib/libc/i386/Makefile.inc b/lib/libc/i386/Makefile.inc
new file mode 100644
index 0000000..ba8e502
--- /dev/null
+++ b/lib/libc/i386/Makefile.inc
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+# Long double is 80 bits
+GDTOASRCS+=strtorx.c
+MDSRCS+=machdep_ldisx.c
+SYM_MAPS+=${.CURDIR}/i386/Symbol.map
diff --git a/lib/libc/i386/SYS.h b/lib/libc/i386/SYS.h
new file mode 100644
index 0000000..a4a147a
--- /dev/null
+++ b/lib/libc/i386/SYS.h
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)SYS.h 5.5 (Berkeley) 5/7/91
+ * $FreeBSD$
+ */
+
+#include <sys/syscall.h>
+#include <machine/asm.h>
+
+#define SYSCALL(x) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); \
+ ENTRY(__CONCAT(__sys_,x)); \
+ .weak CNAME(x); \
+ .set CNAME(x),CNAME(__CONCAT(__sys_,x)); \
+ .weak CNAME(__CONCAT(_,x)); \
+ .set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \
+ mov __CONCAT($SYS_,x),%eax; KERNCALL; jb 2b
+
+#define RSYSCALL(x) SYSCALL(x); ret; END(__CONCAT(__sys_,x))
+
+#define PSEUDO(x) 2: PIC_PROLOGUE; jmp PIC_PLT(HIDENAME(cerror)); \
+ ENTRY(__CONCAT(__sys_,x)); \
+ .weak CNAME(__CONCAT(_,x)); \
+ .set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)); \
+ mov __CONCAT($SYS_,x),%eax; KERNCALL; jb 2b; ret; \
+ END(__CONCAT(__sys_,x))
+
+/* gas messes up offset -- although we don't currently need it, do for BCS */
+#define LCALL(x,y) .byte 0x9a ; .long y; .word x
+
+#define KERNCALL int $0x80
diff --git a/lib/libc/i386/Symbol.map b/lib/libc/i386/Symbol.map
new file mode 100644
index 0000000..8a01802
--- /dev/null
+++ b/lib/libc/i386/Symbol.map
@@ -0,0 +1,70 @@
+/*
+ * $FreeBSD$
+ */
+
+/*
+ * This only needs to contain symbols that are not listed in
+ * symbol maps from other parts of libc (i.e., not found in
+ * stdlib/Symbol.map, string/Symbol.map, sys/Symbol.map, ...).
+ */
+FBSD_1.0 {
+ /* PSEUDO syscalls */
+ _exit;
+
+ .mcount;
+ _setjmp;
+ _longjmp;
+ alloca;
+ fabs;
+ __flt_rounds;
+ __nan;
+ __infinity;
+ makecontext;
+ rfork_thread;
+ setjmp;
+ longjmp;
+ sigsetjmp;
+ siglongjmp;
+ htonl;
+ htons;
+ ntohl;
+ ntohs;
+ vfork;
+ brk;
+ exect;
+ i386_clr_watch;
+ i386_get_fsbase;
+ i386_get_gsbase;
+ i386_get_ioperm;
+ i386_get_ldt;
+ i386_set_fsbase;
+ i386_set_gsbase;
+ i386_set_ioperm;
+ i386_set_ldt;
+ i386_set_watch;
+ i386_vm86;
+ sbrk;
+ ___tls_get_addr;
+};
+
+FBSDprivate_1.0 {
+ /* PSEUDO syscalls */
+ __sys_getlogin;
+ _getlogin;
+ __sys_exit;
+
+ _set_tp;
+ ___longjmp;
+ __makecontext;
+ __longjmp;
+ __signalcontext;
+ signalcontext;
+ __siglongjmp;
+ __sys_vfork;
+ _vfork;
+ _end;
+ .cerror;
+ _brk;
+ .curbrk;
+ .minbrk;
+};
diff --git a/lib/libc/i386/_fpmath.h b/lib/libc/i386/_fpmath.h
new file mode 100644
index 0000000..4f1f5f4
--- /dev/null
+++ b/lib/libc/i386/_fpmath.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+union IEEEl2bits {
+ long double e;
+ struct {
+ unsigned int manl :32;
+ unsigned int manh :32;
+ unsigned int exp :15;
+ unsigned int sign :1;
+ unsigned int junk :16;
+ } bits;
+ struct {
+ unsigned long long man :64;
+ unsigned int expsign :16;
+ unsigned int junk :16;
+ } xbits;
+};
+
+#define LDBL_NBIT 0x80000000
+#define mask_nbit_l(u) ((u).bits.manh &= ~LDBL_NBIT)
+
+#define LDBL_MANH_SIZE 32
+#define LDBL_MANL_SIZE 32
+
+#define LDBL_TO_ARRAY32(u, a) do { \
+ (a)[0] = (uint32_t)(u).bits.manl; \
+ (a)[1] = (uint32_t)(u).bits.manh; \
+} while (0)
diff --git a/lib/libc/i386/arith.h b/lib/libc/i386/arith.h
new file mode 100644
index 0000000..2d65061
--- /dev/null
+++ b/lib/libc/i386/arith.h
@@ -0,0 +1,15 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * NOTE: The definitions in this file must be correct or strtod(3) and
+ * floating point formats in printf(3) will break! The file can be
+ * generated by running contrib/gdtoa/arithchk.c on the target
+ * architecture. See contrib/gdtoa/gdtoaimp.h for details.
+ */
+
+#define IEEE_8087
+#define Arith_Kind_ASL 1
diff --git a/lib/libc/i386/gd_qnan.h b/lib/libc/i386/gd_qnan.h
new file mode 100644
index 0000000..3992386
--- /dev/null
+++ b/lib/libc/i386/gd_qnan.h
@@ -0,0 +1,21 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * This file can be generated by compiling and running contrib/gdtoa/qnan.c
+ * on the target architecture after arith.h has been generated.
+ *
+ * $FreeBSD$
+ */
+
+#define f_QNAN 0x7fc00000
+#define d_QNAN0 0x0
+#define d_QNAN1 0x7ff80000
+#define ld_QNAN0 0x0
+#define ld_QNAN1 0xc0000000
+#define ld_QNAN2 0x7fff
+#define ld_QNAN3 0x0
+#define ldus_QNAN0 0x0
+#define ldus_QNAN1 0x0
+#define ldus_QNAN2 0x0
+#define ldus_QNAN3 0xc000
+#define ldus_QNAN4 0x7fff
diff --git a/lib/libc/i386/gen/Makefile.inc b/lib/libc/i386/gen/Makefile.inc
new file mode 100644
index 0000000..73dcabb
--- /dev/null
+++ b/lib/libc/i386/gen/Makefile.inc
@@ -0,0 +1,6 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+SRCS+= _ctx_start.S _setjmp.S _set_tp.c fabs.S \
+ flt_rounds.c getcontextx.c infinity.c ldexp.c makecontext.c \
+ rfork_thread.S setjmp.S signalcontext.c sigsetjmp.S
diff --git a/lib/libc/i386/gen/_ctx_start.S b/lib/libc/i386/gen/_ctx_start.S
new file mode 100644
index 0000000..fdea371
--- /dev/null
+++ b/lib/libc/i386/gen/_ctx_start.S
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2001 Daniel Eischen <deischen@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * _ctx_start((void *func)(int arg1, ..., argn),
+ * int arg1, ..., argn, ucontext_t *ucp)
+ *
+ * 0(%esp) - func
+ * 4(%esp) - arg1
+ * 8(%esp) - arg2
+ * ...
+ * (4*n)(%esp) - argn
+ * (4*(n + 1))(%esp) - ucp, %ebp setup to point here (base of stack)
+ */
+ENTRY(_ctx_start)
+ popl %eax /* get start function */
+ call *%eax /* call start function */
+ PIC_PROLOGUE
+ movl %esi, %esp /*
+ * setup stack for completion routine;
+ * ucp is now at top of stack
+ */
+ call PIC_PLT(_ctx_done) /* should never return */
+ call PIC_PLT(abort) /* fubar */
+ ret
+END(_ctx_start)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/gen/_set_tp.c b/lib/libc/i386/gen/_set_tp.c
new file mode 100644
index 0000000..8a6c929
--- /dev/null
+++ b/lib/libc/i386/gen/_set_tp.c
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <string.h>
+#include <stdint.h>
+#include <machine/sysarch.h>
+
+#include "libc_private.h"
+
+void
+_set_tp(void *tp)
+{
+
+ i386_set_gsbase(tp);
+}
diff --git a/lib/libc/i386/gen/_setjmp.S b/lib/libc/i386/gen/_setjmp.S
new file mode 100644
index 0000000..3d9fdb4
--- /dev/null
+++ b/lib/libc/i386/gen/_setjmp.S
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ .asciz "@(#)_setjmp.s 5.1 (Berkeley) 4/23/90"
+#endif /* LIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * C library -- _setjmp, _longjmp
+ *
+ * _longjmp(a,v)
+ * will generate a "return(v)" from the last call to
+ * _setjmp(a)
+ * by restoring registers from the environment 'a'.
+ * The previous signal state is NOT restored.
+ */
+
+ENTRY(_setjmp)
+ movl 4(%esp),%eax
+ movl 0(%esp),%edx
+ movl %edx, 0(%eax) /* rta */
+ movl %ebx, 4(%eax)
+ movl %esp, 8(%eax)
+ movl %ebp,12(%eax)
+ movl %esi,16(%eax)
+ movl %edi,20(%eax)
+ fnstcw 24(%eax)
+ xorl %eax,%eax
+ ret
+END(_setjmp)
+
+ .weak CNAME(_longjmp)
+ .set CNAME(_longjmp),CNAME(___longjmp)
+ENTRY(___longjmp)
+ movl 4(%esp),%edx
+ movl 8(%esp),%eax
+ movl 0(%edx),%ecx
+ movl 4(%edx),%ebx
+ movl 8(%edx),%esp
+ movl 12(%edx),%ebp
+ movl 16(%edx),%esi
+ movl 20(%edx),%edi
+ fldcw 24(%edx)
+ testl %eax,%eax
+ jnz 1f
+ incl %eax
+1: movl %ecx,0(%esp)
+ ret
+END(___longjmp)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/gen/fabs.S b/lib/libc/i386/gen/fabs.S
new file mode 100644
index 0000000..7fb1531
--- /dev/null
+++ b/lib/libc/i386/gen/fabs.S
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ .asciz "@(#)fabs.s 5.2 (Berkeley) 12/17/90"
+#endif /* LIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(fabs)
+ fldl 4(%esp)
+ fabs
+ ret
+END(fabs)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/gen/flt_rounds.c b/lib/libc/i386/gen/flt_rounds.c
new file mode 100644
index 0000000..16417ff
--- /dev/null
+++ b/lib/libc/i386/gen/flt_rounds.c
@@ -0,0 +1,25 @@
+/*
+ * Written by J.T. Conklin, Apr 10, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <float.h>
+
+static const int map[] = {
+ 1, /* round to nearest */
+ 3, /* round to zero */
+ 2, /* round to negative infinity */
+ 0 /* round to positive infinity */
+};
+
+int
+__flt_rounds(void)
+{
+ int x;
+
+ __asm("fnstcw %0" : "=m" (x));
+ return (map[(x >> 10) & 0x03]);
+}
diff --git a/lib/libc/i386/gen/getcontextx.c b/lib/libc/i386/gen/getcontextx.c
new file mode 100644
index 0000000..5908ce7
--- /dev/null
+++ b/lib/libc/i386/gen/getcontextx.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2011 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <machine/npx.h>
+#include <machine/specialreg.h>
+#include <machine/sysarch.h>
+
+static int xstate_sz = -1;
+
+int
+__getcontextx_size(void)
+{
+ u_int p[4];
+ int cpuid_supported;
+
+ if (xstate_sz == -1) {
+ __asm __volatile(
+ " pushfl\n"
+ " popl %%eax\n"
+ " movl %%eax,%%ecx\n"
+ " xorl $0x200000,%%eax\n"
+ " pushl %%eax\n"
+ " popfl\n"
+ " pushfl\n"
+ " popl %%eax\n"
+ " xorl %%eax,%%ecx\n"
+ " je 1f\n"
+ " movl $1,%0\n"
+ " jmp 2f\n"
+ "1: movl $0,%0\n"
+ "2:\n"
+ : "=r" (cpuid_supported) : : "eax", "ecx");
+ if (cpuid_supported) {
+ __asm __volatile(
+ " pushl %%ebx\n"
+ " cpuid\n"
+ " movl %%ebx,%1\n"
+ " popl %%ebx\n"
+ : "=a" (p[0]), "=r" (p[1]), "=c" (p[2]), "=d" (p[3])
+ : "0" (0x0));
+ if ((p[2] & CPUID2_OSXSAVE) != 0) {
+ __asm __volatile(
+ " pushl %%ebx\n"
+ " cpuid\n"
+ " movl %%ebx,%1\n"
+ " popl %%ebx\n"
+ : "=a" (p[0]), "=r" (p[1]), "=c" (p[2]),
+ "=d" (p[3])
+ : "0" (0xd), "2" (0x0));
+ xstate_sz = p[1] - sizeof(struct savexmm);
+ } else
+ xstate_sz = 0;
+ } else
+ xstate_sz = 0;
+ }
+
+ return (sizeof(ucontext_t) + xstate_sz);
+}
+
+int
+__fillcontextx(char *ctx)
+{
+ struct i386_get_xfpustate xfpu;
+ ucontext_t *ucp;
+
+ ucp = (ucontext_t *)ctx;
+ if (getcontext(ucp) == -1)
+ return (-1);
+ if (xstate_sz != 0) {
+ xfpu.addr = (char *)(ucp + 1);
+ xfpu.len = xstate_sz;
+ if (sysarch(I386_GET_XFPUSTATE, &xfpu) == -1)
+ return (-1);
+ ucp->uc_mcontext.mc_xfpustate = (__register_t)xfpu.addr;
+ ucp->uc_mcontext.mc_xfpustate_len = xstate_sz;
+ ucp->uc_mcontext.mc_flags |= _MC_HASFPXSTATE;
+ } else {
+ ucp->uc_mcontext.mc_xfpustate = 0;
+ ucp->uc_mcontext.mc_xfpustate_len = 0;
+ }
+ return (0);
+}
+
+__weak_reference(__getcontextx, getcontextx);
+
+ucontext_t *
+__getcontextx(void)
+{
+ char *ctx;
+ int error;
+
+ ctx = malloc(__getcontextx_size());
+ if (ctx == NULL)
+ return (NULL);
+ if (__fillcontextx(ctx) == -1) {
+ error = errno;
+ free(ctx);
+ errno = error;
+ return (NULL);
+ }
+ return ((ucontext_t *)ctx);
+}
diff --git a/lib/libc/i386/gen/infinity.c b/lib/libc/i386/gen/infinity.c
new file mode 100644
index 0000000..464b402
--- /dev/null
+++ b/lib/libc/i386/gen/infinity.c
@@ -0,0 +1,14 @@
+/*
+ * infinity.c
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <math.h>
+
+/* bytes for +Infinity on a 387 */
+const union __infinity_un __infinity = { { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } };
+
+/* bytes for NaN */
+const union __nan_un __nan = { { 0, 0, 0xc0, 0xff } };
diff --git a/lib/libc/i386/gen/makecontext.c b/lib/libc/i386/gen/makecontext.c
new file mode 100644
index 0000000..167cb12
--- /dev/null
+++ b/lib/libc/i386/gen/makecontext.c
@@ -0,0 +1,163 @@
+/*
+ * Copyright (c) 2001 Daniel M. Eischen <deischen@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Neither the name of the author nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/signal.h>
+#include <sys/ucontext.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+/* Prototypes */
+extern void _ctx_start(ucontext_t *, int argc, ...);
+
+
+__weak_reference(__makecontext, makecontext);
+
+void
+_ctx_done (ucontext_t *ucp)
+{
+ if (ucp->uc_link == NULL)
+ exit(0);
+ else {
+ /*
+ * Since this context has finished, don't allow it
+ * to be restarted without being reinitialized (via
+ * setcontext or swapcontext).
+ */
+ ucp->uc_mcontext.mc_len = 0;
+
+ /* Set context to next one in link */
+ /* XXX - what to do for error, abort? */
+ setcontext((const ucontext_t *)ucp->uc_link);
+ abort(); /* should never get here */
+ }
+}
+
+void
+__makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...)
+{
+ va_list ap;
+ char *stack_top;
+ intptr_t *argp;
+ int i;
+
+ if (ucp == NULL)
+ return;
+ else if ((ucp->uc_stack.ss_sp == NULL) ||
+ (ucp->uc_stack.ss_size < MINSIGSTKSZ)) {
+ /*
+ * This should really return -1 with errno set to ENOMEM
+ * or something, but the spec says that makecontext is
+ * a void function. At least make sure that the context
+ * isn't valid so it can't be used without an error.
+ */
+ ucp->uc_mcontext.mc_len = 0;
+ }
+ /* XXX - Do we want to sanity check argc? */
+ else if ((argc < 0) || (argc > NCARGS)) {
+ ucp->uc_mcontext.mc_len = 0;
+ }
+ /* Make sure the context is valid. */
+ else if (ucp->uc_mcontext.mc_len == sizeof(mcontext_t)) {
+ /*
+ * Arrange the stack as follows:
+ *
+ * _ctx_start() - context start wrapper
+ * start() - user start routine
+ * arg1 - first argument, aligned(16)
+ * ...
+ * argn
+ * ucp - this context, %ebp points here
+ *
+ * When the context is started, control will return to
+ * the context start wrapper which will pop the user
+ * start routine from the top of the stack. After that,
+ * the top of the stack will be setup with all arguments
+ * necessary for calling the start routine. When the
+ * start routine returns, the context wrapper then sets
+ * the stack pointer to %ebp which was setup to point to
+ * the base of the stack (and where ucp is stored). It
+ * will then call _ctx_done() to swap in the next context
+ * (uc_link != 0) or exit the program (uc_link == 0).
+ */
+ stack_top = (char *)(ucp->uc_stack.ss_sp +
+ ucp->uc_stack.ss_size - sizeof(intptr_t));
+
+ /*
+ * Adjust top of stack to allow for 3 pointers (return
+ * address, _ctx_start, and ucp) and argc arguments.
+ * We allow the arguments to be pointers also. The first
+ * argument to the user function must be properly aligned.
+ */
+ stack_top = stack_top - (sizeof(intptr_t) * (1 + argc));
+ stack_top = (char *)((unsigned)stack_top & ~15);
+ stack_top = stack_top - (2 * sizeof(intptr_t));
+ argp = (intptr_t *)stack_top;
+
+ /*
+ * Setup the top of the stack with the user start routine
+ * followed by all of its aguments and the pointer to the
+ * ucontext. We need to leave a spare spot at the top of
+ * the stack because setcontext will move eip to the top
+ * of the stack before returning.
+ */
+ *argp = (intptr_t)_ctx_start; /* overwritten with same value */
+ argp++;
+ *argp = (intptr_t)start;
+ argp++;
+
+ /* Add all the arguments: */
+ va_start(ap, argc);
+ for (i = 0; i < argc; i++) {
+ *argp = va_arg(ap, intptr_t);
+ argp++;
+ }
+ va_end(ap);
+
+ /* The ucontext is placed at the bottom of the stack. */
+ *argp = (intptr_t)ucp;
+
+ /*
+ * Set the machine context to point to the top of the
+ * stack and the program counter to the context start
+ * wrapper. Note that setcontext() pushes the return
+ * address onto the top of the stack, so allow for this
+ * by adjusting the stack downward 1 slot. Also set
+ * %esi to point to the base of the stack where ucp
+ * is stored.
+ */
+ ucp->uc_mcontext.mc_esi = (int)argp;
+ ucp->uc_mcontext.mc_ebp = 0;
+ ucp->uc_mcontext.mc_esp = (int)stack_top + sizeof(caddr_t);
+ ucp->uc_mcontext.mc_eip = (int)_ctx_start;
+ }
+}
diff --git a/lib/libc/i386/gen/rfork_thread.S b/lib/libc/i386/gen/rfork_thread.S
new file mode 100644
index 0000000..3333d84
--- /dev/null
+++ b/lib/libc/i386/gen/rfork_thread.S
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 2000 Peter Wemm <peter@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * With thanks to John Dyson for the original version of this.
+ */
+
+#include <SYS.h>
+
+/*
+ * 8 12 16 20
+ * rfork_thread(flags, stack_addr, start_fnc, start_arg);
+ *
+ * flags: Flags to rfork system call. See rfork(2).
+ * stack_addr: Top of stack for thread.
+ * start_fnc: Address of thread function to call in child.
+ * start_arg: Argument to pass to the thread function in child.
+ */
+
+ENTRY(rfork_thread)
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %esi
+
+ /*
+ * Push thread info onto the new thread's stack
+ */
+ movl 12(%ebp), %esi # get stack addr
+
+ subl $4, %esi
+ movl 20(%ebp), %eax # get start argument
+ movl %eax, (%esi)
+
+ subl $4, %esi
+ movl 16(%ebp), %eax # get start thread address
+ movl %eax, (%esi)
+
+ /*
+ * Prepare and execute the thread creation syscall
+ */
+ pushl 8(%ebp)
+ pushl $0
+ movl $SYS_rfork, %eax
+ KERNCALL
+ jb 2f
+
+ /*
+ * Check to see if we are in the parent or child
+ */
+ cmpl $0, %edx
+ jnz 1f
+ addl $8, %esp
+ popl %esi
+ movl %ebp, %esp
+ popl %ebp
+ ret
+ .p2align 2
+
+ /*
+ * If we are in the child (new thread), then
+ * set-up the call to the internal subroutine. If it
+ * returns, then call __exit.
+ */
+1:
+ movl %esi,%esp
+ popl %eax
+ call *%eax
+ addl $4, %esp
+
+ /*
+ * Exit system call
+ */
+ pushl %eax
+ pushl $0
+#ifdef SYS_exit
+ movl $SYS_exit, %eax
+#else
+ movl $SYS_sys_exit, %eax
+#endif
+ KERNCALL
+
+ /*
+ * Branch here if the thread creation fails:
+ */
+2:
+ addl $8, %esp
+ popl %esi
+ movl %ebp, %esp
+ popl %ebp
+ PIC_PROLOGUE
+ jmp PIC_PLT(HIDENAME(cerror))
+END(rfork_thread)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/gen/setjmp.S b/lib/libc/i386/gen/setjmp.S
new file mode 100644
index 0000000..a409e35
--- /dev/null
+++ b/lib/libc/i386/gen/setjmp.S
@@ -0,0 +1,116 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ .asciz "@(#)setjmp.s 5.1 (Berkeley) 4/23/90"
+#endif /* LIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * C library -- _setjmp, _longjmp
+ *
+ * longjmp(a,v)
+ * will generate a "return(v)" from the last call to
+ * setjmp(a)
+ * by restoring registers from the environment 'a'.
+ * The previous signal state is restored.
+ */
+
+#include "SYS.h"
+
+ENTRY(setjmp)
+ movl 4(%esp),%ecx
+ PIC_PROLOGUE
+#ifdef PIC
+ subl $12,%esp /* make the stack 16-byte aligned */
+#endif
+ leal 28(%ecx), %eax
+ pushl %eax /* (sigset_t*)oset */
+ pushl $0 /* (sigset_t*)set */
+ pushl $1 /* SIG_BLOCK */
+ call PIC_PLT(CNAME(_sigprocmask))
+#ifdef PIC
+ addl $24,%esp
+#else
+ addl $12,%esp
+#endif
+ PIC_EPILOGUE
+ movl 4(%esp),%ecx
+ movl 0(%esp),%edx
+ movl %edx, 0(%ecx)
+ movl %ebx, 4(%ecx)
+ movl %esp, 8(%ecx)
+ movl %ebp,12(%ecx)
+ movl %esi,16(%ecx)
+ movl %edi,20(%ecx)
+ fnstcw 24(%ecx)
+ xorl %eax,%eax
+ ret
+END(setjmp)
+
+ .weak CNAME(longjmp)
+ .set CNAME(longjmp),CNAME(__longjmp)
+ENTRY(__longjmp)
+ movl 4(%esp),%edx
+ PIC_PROLOGUE
+#ifdef PIC
+ subl $12,%esp /* make the stack 16-byte aligned */
+#endif
+ pushl $0 /* (sigset_t*)oset */
+ leal 28(%edx), %eax
+ pushl %eax /* (sigset_t*)set */
+ pushl $3 /* SIG_SETMASK */
+ call PIC_PLT(CNAME(_sigprocmask))
+#ifdef PIC
+ addl $24,%esp
+#else
+ addl $12,%esp
+#endif
+ PIC_EPILOGUE
+ movl 4(%esp),%edx
+ movl 8(%esp),%eax
+ movl 0(%edx),%ecx
+ movl 4(%edx),%ebx
+ movl 8(%edx),%esp
+ movl 12(%edx),%ebp
+ movl 16(%edx),%esi
+ movl 20(%edx),%edi
+ fldcw 24(%edx)
+ testl %eax,%eax
+ jnz 1f
+ incl %eax
+1: movl %ecx,0(%esp)
+ ret
+END(__longjmp)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/gen/signalcontext.c b/lib/libc/i386/gen/signalcontext.c
new file mode 100644
index 0000000..877b655
--- /dev/null
+++ b/lib/libc/i386/gen/signalcontext.c
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 2002 Jonathan Mini <mini@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/ucontext.h>
+#include <machine/psl.h>
+#include <machine/sigframe.h>
+#include <signal.h>
+#include <strings.h>
+
+__weak_reference(__signalcontext, signalcontext);
+
+extern void _ctx_start(ucontext_t *, int argc, ...);
+
+int
+__signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func)
+{
+ register_t *p;
+ struct sigframe *sfp;
+
+ /*-
+ * Set up stack.
+ * (n = sizeof(int))
+ * 2n+sizeof(struct sigframe) ucp
+ * 2n struct sigframe
+ * 1n &func
+ * 0n &_ctx_start
+ */
+ p = (register_t *)(void *)(intptr_t)ucp->uc_mcontext.mc_esp;
+ *--p = (register_t)(intptr_t)ucp;
+ p = (register_t *)((u_register_t)p & ~0xF); /* Align to 16 bytes. */
+ p = (register_t *)((u_register_t)p - sizeof(struct sigframe));
+ sfp = (struct sigframe *)p;
+ bzero(sfp, sizeof(struct sigframe));
+ sfp->sf_signum = sig;
+ sfp->sf_siginfo = (register_t)(intptr_t)&sfp->sf_si;
+ sfp->sf_ucontext = (register_t)(intptr_t)&sfp->sf_uc;
+ sfp->sf_ahu.sf_action = (__siginfohandler_t *)func;
+ bcopy(ucp, &sfp->sf_uc, sizeof(ucontext_t));
+ sfp->sf_si.si_signo = sig;
+ *--p = (register_t)(intptr_t)func;
+
+ /*
+ * Set up ucontext_t.
+ */
+ ucp->uc_mcontext.mc_esi = ucp->uc_mcontext.mc_esp - sizeof(int);
+ ucp->uc_mcontext.mc_esp = (register_t)(intptr_t)p;
+ ucp->uc_mcontext.mc_eip = (register_t)(intptr_t)_ctx_start;
+ ucp->uc_mcontext.mc_eflags &= ~PSL_T;
+ ucp->uc_link = &sfp->sf_uc;
+ sigdelset(&ucp->uc_sigmask, sig);
+ return (0);
+}
diff --git a/lib/libc/i386/gen/sigsetjmp.S b/lib/libc/i386/gen/sigsetjmp.S
new file mode 100644
index 0000000..936edba
--- /dev/null
+++ b/lib/libc/i386/gen/sigsetjmp.S
@@ -0,0 +1,128 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)setjmp.s 5.1 (Berkeley) 4/23/90"
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ .text
+ .asciz "$Id: sigsetjmp.S,v 1.1 1993/12/05 13:01:05 ats Exp $"
+#endif /* LIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+/*-
+ * TODO:
+ * Rename sigsetjmp to __sigsetjmp and siglongjmp to __siglongjmp,
+ * remove the other *jmp functions and define everything in terms
+ * of the renamed functions. This requires compiler support for
+ * the renamed functions (introduced in gcc-2.5.3; previous versions
+ * only supported *jmp with 0 or 1 leading underscores).
+ *
+ * Restore _all_ the registers and the signal mask atomically. Can
+ * use sigreturn() if sigreturn() works.
+ */
+
+ENTRY(sigsetjmp)
+ movl 8(%esp),%eax
+ movl 4(%esp),%ecx
+ movl %eax,44(%ecx)
+ testl %eax,%eax
+ jz 2f
+ PIC_PROLOGUE
+#ifdef PIC
+ subl $12,%esp /* make the stack 16-byte aligned */
+#endif
+ leal 28(%ecx), %eax
+ pushl %eax /* (sigset_t*)oset */
+ pushl $0 /* (sigset_t*)set */
+ pushl $1 /* SIG_BLOCK */
+ call PIC_PLT(CNAME(_sigprocmask))
+#ifdef PIC
+ addl $24,%esp
+#else
+ addl $12,%esp
+#endif
+ PIC_EPILOGUE
+ movl 4(%esp),%ecx
+2: movl 0(%esp),%edx
+ movl %edx, 0(%ecx)
+ movl %ebx, 4(%ecx)
+ movl %esp, 8(%ecx)
+ movl %ebp,12(%ecx)
+ movl %esi,16(%ecx)
+ movl %edi,20(%ecx)
+ fnstcw 24(%ecx)
+ xorl %eax,%eax
+ ret
+END(sigsetjmp)
+
+ .weak CNAME(siglongjmp);
+ .set CNAME(siglongjmp),CNAME(__siglongjmp)
+ENTRY(__siglongjmp)
+ movl 4(%esp),%edx
+ cmpl $0,44(%edx)
+ jz 2f
+ PIC_PROLOGUE
+#ifdef PIC
+ subl $12,%esp /* make the stack 16-byte aligned */
+#endif
+ pushl $0 /* (sigset_t*)oset */
+ leal 28(%edx), %eax
+ pushl %eax /* (sigset_t*)set */
+ pushl $3 /* SIG_SETMASK */
+ call PIC_PLT(CNAME(_sigprocmask))
+#ifdef PIC
+ addl $24,%esp
+#else
+ addl $12,%esp
+#endif
+ PIC_EPILOGUE
+ movl 4(%esp),%edx
+2: movl 8(%esp),%eax
+ movl 0(%edx),%ecx
+ movl 4(%edx),%ebx
+ movl 8(%edx),%esp
+ movl 12(%edx),%ebp
+ movl 16(%edx),%esi
+ movl 20(%edx),%edi
+ fninit
+ fldcw 24(%edx)
+ testl %eax,%eax
+ jnz 1f
+ incl %eax
+1: movl %ecx,0(%esp)
+ ret
+END(__siglongjmp)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/stdlib/Makefile.inc b/lib/libc/i386/stdlib/Makefile.inc
new file mode 100644
index 0000000..e4197d8
--- /dev/null
+++ b/lib/libc/i386/stdlib/Makefile.inc
@@ -0,0 +1,4 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+MDSRCS+=div.S ldiv.S
diff --git a/lib/libc/i386/stdlib/div.S b/lib/libc/i386/stdlib/div.S
new file mode 100644
index 0000000..81d6e6e
--- /dev/null
+++ b/lib/libc/i386/stdlib/div.S
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(div)
+ movl 4(%esp),%eax
+ movl 8(%esp),%ecx
+ cdq
+ idiv %ecx
+ ret
+END(div)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/stdlib/ldiv.S b/lib/libc/i386/stdlib/ldiv.S
new file mode 100644
index 0000000..c40c631
--- /dev/null
+++ b/lib/libc/i386/stdlib/ldiv.S
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(ldiv)
+ movl 4(%esp),%eax
+ movl 8(%esp),%ecx
+ cdq
+ idiv %ecx
+ ret
+END(ldiv)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/Makefile.inc b/lib/libc/i386/string/Makefile.inc
new file mode 100644
index 0000000..f574c8f
--- /dev/null
+++ b/lib/libc/i386/string/Makefile.inc
@@ -0,0 +1,6 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+MDSRCS+=bcmp.S bcopy.S bzero.S ffs.S memchr.S memcmp.S memcpy.S memmove.S \
+ memset.S strcat.S strchr.S strcmp.S strcpy.S strncmp.S strrchr.S \
+ swab.S wcschr.S wcscmp.S wcslen.S wmemchr.S
diff --git a/lib/libc/i386/string/bcmp.S b/lib/libc/i386/string/bcmp.S
new file mode 100644
index 0000000..b25ee6e
--- /dev/null
+++ b/lib/libc/i386/string/bcmp.S
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * bcmp (void *b1, void *b2, size_t len)
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+ENTRY(bcmp)
+ pushl %edi
+ pushl %esi
+ movl 12(%esp),%edi
+ movl 16(%esp),%esi
+ cld /* set compare direction forward */
+
+ movl 20(%esp),%ecx /* compare by words */
+ shrl $2,%ecx
+ repe
+ cmpsl
+ jne L1
+
+ movl 20(%esp),%ecx /* compare remainder by bytes */
+ andl $3,%ecx
+ repe
+ cmpsb
+L1:
+ setne %al
+ movsbl %al,%eax
+ popl %esi
+ popl %edi
+ ret
+END(bcmp)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/bcopy.S b/lib/libc/i386/string/bcopy.S
new file mode 100644
index 0000000..cab1de6
--- /dev/null
+++ b/lib/libc/i386/string/bcopy.S
@@ -0,0 +1,110 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from locore.s.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if 0
+ RCSID("$NetBSD: bcopy.S,v 1.6 1996/11/12 00:50:06 jtc Exp $")
+#endif
+
+ /*
+ * (ov)bcopy (src,dst,cnt)
+ * ws@tools.de (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
+ */
+
+#ifdef MEMCOPY
+ENTRY(memcpy)
+#else
+#ifdef MEMMOVE
+ENTRY(memmove)
+#else
+ENTRY(bcopy)
+#endif
+#endif
+ pushl %esi
+ pushl %edi
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ movl 12(%esp),%edi
+ movl 16(%esp),%esi
+ movl %edi,%eax
+#else
+ movl 12(%esp),%esi
+ movl 16(%esp),%edi
+#endif
+ movl 20(%esp),%ecx
+ movl %edi,%edx
+ subl %esi,%edx
+ cmpl %ecx,%edx /* overlapping? */
+ jb 1f
+ cld /* nope, copy forwards. */
+ movl %ecx,%edx
+ shrl $2,%ecx /* copy by words */
+ rep
+ movsl
+ movl %edx,%ecx
+ andl $3,%ecx /* any bytes left? */
+ rep
+ movsb
+ popl %edi
+ popl %esi
+ ret
+1:
+ addl %ecx,%edi /* copy backwards. */
+ addl %ecx,%esi
+ std
+ movl %ecx,%edx
+ andl $3,%ecx /* any fractional bytes? */
+ decl %edi
+ decl %esi
+ rep
+ movsb
+ movl %edx,%ecx /* copy remainder by words */
+ shrl $2,%ecx
+ subl $3,%esi
+ subl $3,%edi
+ rep
+ movsl
+ popl %edi
+ popl %esi
+ cld
+ ret
+#ifdef MEMCOPY
+END(memcpy)
+#else
+#ifdef MEMMOVE
+END(memmove)
+#else
+END(bcopy)
+#endif
+#endif
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/bzero.S b/lib/libc/i386/string/bzero.S
new file mode 100644
index 0000000..c8d3776
--- /dev/null
+++ b/lib/libc/i386/string/bzero.S
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * bzero (void *b, size_t len)
+ * write len zero bytes to the string b.
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+ENTRY(bzero)
+ pushl %edi
+ pushl %ebx
+ movl 12(%esp),%edi
+ movl 16(%esp),%ecx
+
+ cld /* set fill direction forward */
+ xorl %eax,%eax /* set fill data to 0 */
+
+ /*
+ * if the string is too short, it's really not worth the overhead
+ * of aligning to word boundries, etc. So we jump to a plain
+ * unaligned set.
+ */
+ cmpl $0x0f,%ecx
+ jle L1
+
+ movl %edi,%edx /* compute misalignment */
+ negl %edx
+ andl $3,%edx
+ movl %ecx,%ebx
+ subl %edx,%ebx
+
+ movl %edx,%ecx /* zero until word aligned */
+ rep
+ stosb
+
+ movl %ebx,%ecx /* zero by words */
+ shrl $2,%ecx
+ rep
+ stosl
+
+ movl %ebx,%ecx
+ andl $3,%ecx /* zero remainder by bytes */
+L1: rep
+ stosb
+
+ popl %ebx
+ popl %edi
+ ret
+END(bzero)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/ffs.S b/lib/libc/i386/string/ffs.S
new file mode 100644
index 0000000..3a0431c
--- /dev/null
+++ b/lib/libc/i386/string/ffs.S
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * ffs(value)
+ * finds the first bit set in value and returns the index of
+ * that bit. Bits are numbered starting from 1, starting at the
+ * rightmost bit. A return value of 0 means that the argument
+ * was zero.
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+ENTRY(ffs)
+ bsfl 4(%esp),%eax
+ jz L1 /* ZF is set if all bits are 0 */
+ incl %eax /* bits numbered from 1, not 0 */
+ ret
+
+ .align 2
+L1: xorl %eax,%eax /* clear result */
+ ret
+END(ffs)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/memchr.S b/lib/libc/i386/string/memchr.S
new file mode 100644
index 0000000..03828db
--- /dev/null
+++ b/lib/libc/i386/string/memchr.S
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * memchr (b, c, len)
+ * locates the first occurance of c in string b.
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+ENTRY(memchr)
+ pushl %edi
+ movl 8(%esp),%edi /* string address */
+ movl 12(%esp),%eax /* set character to search for */
+ movl 16(%esp),%ecx /* set length of search */
+ testl %esp,%esp /* clear Z flag, for len == 0 */
+ cld /* set search forward */
+ repne /* search! */
+ scasb
+ jnz L1 /* scan failed, return null */
+ leal -1(%edi),%eax /* adjust result of scan */
+ popl %edi
+ ret
+ .align 2,0x90
+L1: xorl %eax,%eax
+ popl %edi
+ ret
+END(memchr)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/memcmp.S b/lib/libc/i386/string/memcmp.S
new file mode 100644
index 0000000..cbb3b8a
--- /dev/null
+++ b/lib/libc/i386/string/memcmp.S
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * memcmp (void *b1, void *b2, size_t len)
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+ENTRY(memcmp)
+ pushl %edi
+ pushl %esi
+ movl 12(%esp),%edi
+ movl 16(%esp),%esi
+ cld /* set compare direction forward */
+
+ movl 20(%esp),%ecx /* compare by words */
+ shrl $2,%ecx
+ repe
+ cmpsl
+ jne L5 /* do we match so far? */
+
+ movl 20(%esp),%ecx /* compare remainder by bytes */
+ andl $3,%ecx
+ repe
+ cmpsb
+ jne L6 /* do we match? */
+
+ xorl %eax,%eax /* we match, return zero */
+ popl %esi
+ popl %edi
+ ret
+
+L5: movl $4,%ecx /* We know that one of the next */
+ subl %ecx,%edi /* four pairs of bytes do not */
+ subl %ecx,%esi /* match. */
+ repe
+ cmpsb
+L6: movzbl -1(%edi),%eax /* Perform unsigned comparison */
+ movzbl -1(%esi),%edx
+ subl %edx,%eax
+ popl %esi
+ popl %edi
+ ret
+END(memcmp)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/memcpy.S b/lib/libc/i386/string/memcpy.S
new file mode 100644
index 0000000..f85a1a5
--- /dev/null
+++ b/lib/libc/i386/string/memcpy.S
@@ -0,0 +1,5 @@
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#define MEMCOPY
+#include "bcopy.S"
diff --git a/lib/libc/i386/string/memmove.S b/lib/libc/i386/string/memmove.S
new file mode 100644
index 0000000..02330c4
--- /dev/null
+++ b/lib/libc/i386/string/memmove.S
@@ -0,0 +1,5 @@
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#define MEMMOVE
+#include "bcopy.S"
diff --git a/lib/libc/i386/string/memset.S b/lib/libc/i386/string/memset.S
new file mode 100644
index 0000000..f5da603
--- /dev/null
+++ b/lib/libc/i386/string/memset.S
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * memset(void *b, int c, size_t len)
+ * write len bytes of value c (converted to an unsigned char) to
+ * the string b.
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+ENTRY(memset)
+ pushl %edi
+ pushl %ebx
+ movl 12(%esp),%edi
+ movzbl 16(%esp),%eax /* unsigned char, zero extend */
+ movl 20(%esp),%ecx
+ pushl %edi /* push address of buffer */
+
+ cld /* set fill direction forward */
+
+ /*
+ * if the string is too short, it's really not worth the overhead
+ * of aligning to word boundries, etc. So we jump to a plain
+ * unaligned set.
+ */
+ cmpl $0x0f,%ecx
+ jle L1
+
+ movb %al,%ah /* copy char to all bytes in word */
+ movl %eax,%edx
+ sall $16,%eax
+ orl %edx,%eax
+
+ movl %edi,%edx /* compute misalignment */
+ negl %edx
+ andl $3,%edx
+ movl %ecx,%ebx
+ subl %edx,%ebx
+
+ movl %edx,%ecx /* set until word aligned */
+ rep
+ stosb
+
+ movl %ebx,%ecx
+ shrl $2,%ecx /* set by words */
+ rep
+ stosl
+
+ movl %ebx,%ecx /* set remainder by bytes */
+ andl $3,%ecx
+L1: rep
+ stosb
+
+ popl %eax /* pop address of buffer */
+ popl %ebx
+ popl %edi
+ ret
+END(memset)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/strcat.S b/lib/libc/i386/string/strcat.S
new file mode 100644
index 0000000..835a7e9
--- /dev/null
+++ b/lib/libc/i386/string/strcat.S
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * strcat(s, append)
+ * append a copy of the null-terminated string "append" to the end
+ * of the null-terminated string s, then add a terminating `\0'.
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+/*
+ * I've unrolled the loop eight times: large enough to make a
+ * significant difference, and small enough not to totally trash the
+ * cache.
+ */
+
+ENTRY(strcat)
+ pushl %edi /* save edi */
+ movl 8(%esp),%edi /* dst address */
+ movl 12(%esp),%edx /* src address */
+ pushl %edi /* push destination address */
+
+ cld /* set search forward */
+ xorl %eax,%eax /* set search for null terminator */
+ movl $-1,%ecx /* set search for lots of characters */
+ repne /* search! */
+ scasb
+
+ leal -1(%edi),%ecx /* correct dst address */
+
+ .align 2,0x90
+L1: movb (%edx),%al /* unroll loop, but not too much */
+ movb %al,(%ecx)
+ testb %al,%al
+ je L2
+ movb 1(%edx),%al
+ movb %al,1(%ecx)
+ testb %al,%al
+ je L2
+ movb 2(%edx),%al
+ movb %al,2(%ecx)
+ testb %al,%al
+ je L2
+ movb 3(%edx),%al
+ movb %al,3(%ecx)
+ testb %al,%al
+ je L2
+ movb 4(%edx),%al
+ movb %al,4(%ecx)
+ testb %al,%al
+ je L2
+ movb 5(%edx),%al
+ movb %al,5(%ecx)
+ testb %al,%al
+ je L2
+ movb 6(%edx),%al
+ movb %al,6(%ecx)
+ testb %al,%al
+ je L2
+ movb 7(%edx),%al
+ movb %al,7(%ecx)
+ addl $8,%edx
+ addl $8,%ecx
+ testb %al,%al
+ jne L1
+L2: popl %eax /* pop destination address */
+ popl %edi /* restore edi */
+ ret
+END(strcat)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/strchr.S b/lib/libc/i386/string/strchr.S
new file mode 100644
index 0000000..57fc6dd
--- /dev/null
+++ b/lib/libc/i386/string/strchr.S
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * strchr(s, c)
+ * return a pointer to the first occurance of the character c in
+ * string s, or NULL if c does not occur in the string.
+ *
+ * %edx - pointer iterating through string
+ * %eax - pointer to first occurance of 'c'
+ * %cl - character we're comparing against
+ * %bl - character at %edx
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+ENTRY(strchr)
+ pushl %ebx
+ movl 8(%esp),%eax
+ movb 12(%esp),%cl
+ .align 2,0x90
+L1:
+ movb (%eax),%bl
+ cmpb %bl,%cl /* found char??? */
+ je L2
+ incl %eax
+ testb %bl,%bl /* null terminator??? */
+ jne L1
+ xorl %eax,%eax
+L2:
+ popl %ebx
+ ret
+END(strchr)
+
+WEAK_ALIAS(index, strchr)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/strcmp.S b/lib/libc/i386/string/strcmp.S
new file mode 100644
index 0000000..6599577
--- /dev/null
+++ b/lib/libc/i386/string/strcmp.S
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * strcmp(s1, s2)
+ * return an integer greater than, equal to, or less than 0,
+ * according as string s1 is greater than, equal to, or less
+ * than the string s2.
+ *
+ * %eax - pointer to s1
+ * %edx - pointer to s2
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+/*
+ * I've unrolled the loop eight times: large enough to make a
+ * significant difference, and small enough not to totally trash the
+ * cache.
+ */
+
+ENTRY(strcmp)
+ movl 0x04(%esp),%eax
+ movl 0x08(%esp),%edx
+ jmp L2 /* Jump into the loop! */
+
+ .align 2,0x90
+L1: incl %eax
+ incl %edx
+L2: movb (%eax),%cl
+ testb %cl,%cl
+ je L3
+ cmpb %cl,(%edx)
+ jne L3
+ incl %eax
+ incl %edx
+ movb (%eax),%cl
+ testb %cl,%cl
+ je L3
+ cmpb %cl,(%edx)
+ jne L3
+ incl %eax
+ incl %edx
+ movb (%eax),%cl
+ testb %cl,%cl
+ je L3
+ cmpb %cl,(%edx)
+ jne L3
+ incl %eax
+ incl %edx
+ movb (%eax),%cl
+ testb %cl,%cl
+ je L3
+ cmpb %cl,(%edx)
+ jne L3
+ incl %eax
+ incl %edx
+ movb (%eax),%cl
+ testb %cl,%cl
+ je L3
+ cmpb %cl,(%edx)
+ jne L3
+ incl %eax
+ incl %edx
+ movb (%eax),%cl
+ testb %cl,%cl
+ je L3
+ cmpb %cl,(%edx)
+ jne L3
+ incl %eax
+ incl %edx
+ movb (%eax),%cl
+ testb %cl,%cl
+ je L3
+ cmpb %cl,(%edx)
+ jne L3
+ incl %eax
+ incl %edx
+ movb (%eax),%cl
+ testb %cl,%cl
+ je L3
+ cmpb %cl,(%edx)
+ je L1
+ .align 2, 0x90
+L3: movzbl (%eax),%eax /* unsigned comparison */
+ movzbl (%edx),%edx
+ subl %edx,%eax
+ ret
+END(strcmp)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/strcpy.S b/lib/libc/i386/string/strcpy.S
new file mode 100644
index 0000000..c5113f6
--- /dev/null
+++ b/lib/libc/i386/string/strcpy.S
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * strcpy (dst, src)
+ * copy the string src to dst.
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+/*
+ * I've unrolled the loop eight times: large enough to make a
+ * significant difference, and small enough not to totally trash the
+ * cache.
+ */
+
+ENTRY(strcpy)
+ movl 4(%esp),%ecx /* dst address */
+ movl 8(%esp),%edx /* src address */
+ pushl %ecx /* push dst address */
+
+ .align 2,0x90
+L1: movb (%edx),%al /* unroll loop, but not too much */
+ movb %al,(%ecx)
+ testb %al,%al
+ je L2
+ movb 1(%edx),%al
+ movb %al,1(%ecx)
+ testb %al,%al
+ je L2
+ movb 2(%edx),%al
+ movb %al,2(%ecx)
+ testb %al,%al
+ je L2
+ movb 3(%edx),%al
+ movb %al,3(%ecx)
+ testb %al,%al
+ je L2
+ movb 4(%edx),%al
+ movb %al,4(%ecx)
+ testb %al,%al
+ je L2
+ movb 5(%edx),%al
+ movb %al,5(%ecx)
+ testb %al,%al
+ je L2
+ movb 6(%edx),%al
+ movb %al,6(%ecx)
+ testb %al,%al
+ je L2
+ movb 7(%edx),%al
+ movb %al,7(%ecx)
+ addl $8,%edx
+ addl $8,%ecx
+ testb %al,%al
+ jne L1
+L2: popl %eax /* pop dst address */
+ ret
+END(strcpy)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/strncmp.S b/lib/libc/i386/string/strncmp.S
new file mode 100644
index 0000000..ec9b531
--- /dev/null
+++ b/lib/libc/i386/string/strncmp.S
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * strncmp(s1, s2, n)
+ * return an integer greater than, equal to, or less than 0,
+ * according as the first n characters of string s1 is greater
+ * than, equal to, or less than the string s2.
+ *
+ * %eax - pointer to s1
+ * %ecx - pointer to s2
+ * %edx - length
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+/*
+ * I've unrolled the loop eight times: large enough to make a
+ * significant difference, and small enough not to totally trash the
+ * cache.
+ *
+ * TODO: change all the jz's back to je for consistency.
+ */
+
+ENTRY(strncmp)
+ pushl %ebx
+ movl 8(%esp),%eax
+ movl 12(%esp),%ecx
+ movl 16(%esp),%edx
+ testl %edx,%edx
+ jmp L2 /* Jump into the loop! */
+
+ .align 2,0x90
+L1: incl %eax
+ incl %ecx
+ decl %edx
+L2: jz L4 /* strings are equal */
+ movb (%eax),%bl
+ testb %bl,%bl
+ jz L3
+ cmpb %bl,(%ecx)
+ jne L3
+
+/*
+ * XXX it might be best to move the next 4 instructions to the end of the
+ * unrolled part of the loop. The unrolled part would then be
+ * movb n(%eax),%bl; testb %bl, %bl; je L3; cmpb n(%ecx); jne L3
+ * or maybe better
+ * movb n(%eax),%bl; cmpb n(%ecx); jne L3; testb %bl,%bl; je return_0
+ * for n = 0, 1, ..., 8. The end of the loop would be
+ * L1: addl $8,%eax; addl $8,%ecx; subl $8,%edx; cmpl $8,%edx; jae Lx
+ * where residual counts of 0 to 7 are handled at Lx. However, this would
+ * be slower for short strings. Cache effects are probably not so
+ * important because we are only handling a byte at a time.
+ */
+ incl %eax
+ incl %ecx
+ decl %edx
+ jz L4
+ movb (%eax),%bl
+ testb %bl,%bl
+ jz L3
+ cmpb %bl,(%ecx)
+ jne L3
+
+ incl %eax
+ incl %ecx
+ decl %edx
+ jz L4
+ movb (%eax),%bl
+ testb %bl,%bl
+ jz L3
+ cmpb %bl,(%ecx)
+ jne L3
+
+ incl %eax
+ incl %ecx
+ decl %edx
+ jz L4
+ movb (%eax),%bl
+ testb %bl,%bl
+ jz L3
+ cmpb %bl,(%ecx)
+ jne L3
+
+ incl %eax
+ incl %ecx
+ decl %edx
+ jz L4
+ movb (%eax),%bl
+ testb %bl,%bl
+ jz L3
+ cmpb %bl,(%ecx)
+ jne L3
+
+ incl %eax
+ incl %ecx
+ decl %edx
+ jz L4
+ movb (%eax),%bl
+ testb %bl,%bl
+ jz L3
+ cmpb %bl,(%ecx)
+ jne L3
+
+ incl %eax
+ incl %ecx
+ decl %edx
+ jz L4
+ movb (%eax),%bl
+ testb %bl,%bl
+ jz L3
+ cmpb %bl,(%ecx)
+ jne L3
+
+ incl %eax
+ incl %ecx
+ decl %edx
+ jz L4
+ movb (%eax),%bl
+ testb %bl,%bl
+ jz L3
+ cmpb %bl,(%ecx)
+ je L1
+
+ .align 2,0x90
+L3: movzbl (%eax),%eax /* unsigned comparison */
+ movzbl (%ecx),%ecx
+ subl %ecx,%eax
+ popl %ebx
+ ret
+ .align 2,0x90
+L4: xorl %eax,%eax
+ popl %ebx
+ ret
+END(strncmp)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/strrchr.S b/lib/libc/i386/string/strrchr.S
new file mode 100644
index 0000000..29942c4
--- /dev/null
+++ b/lib/libc/i386/string/strrchr.S
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1993 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * strrchr(s, c)
+ * return a pointer to the last occurance of the character c in
+ * string s, or NULL if c does not occur in the string.
+ *
+ * %edx - pointer iterating through string
+ * %eax - pointer to last occurance of 'c'
+ * %cl - character we're comparing against
+ * %bl - character at %edx
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+ENTRY(strrchr)
+ pushl %ebx
+ movl 8(%esp),%edx
+ movb 12(%esp),%cl
+ xorl %eax,%eax /* init pointer to null */
+ .align 2,0x90
+L1:
+ movb (%edx),%bl
+ cmpb %bl,%cl
+ jne L2
+ movl %edx,%eax
+L2:
+ incl %edx
+ testb %bl,%bl /* null terminator??? */
+ jne L1
+ popl %ebx
+ ret
+END(strrchr)
+
+WEAK_ALIAS(rindex, strrchr)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/swab.S b/lib/libc/i386/string/swab.S
new file mode 100644
index 0000000..3d21e64
--- /dev/null
+++ b/lib/libc/i386/string/swab.S
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 1993,94 Winning Strategies, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Winning Strategies, Inc.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * void
+ * swab (const void *src, void *dst, size_t len)
+ * copy len bytes from src to dst, swapping adjacent bytes
+ *
+ * On the i486, this code is negligibly faster than the code generated
+ * by gcc at about half the size. If my i386 databook is correct, it
+ * should be considerably faster than the gcc code on an i386.
+ *
+ * Written by:
+ * J.T. Conklin (jtc@wimsey.com), Winning Strategies, Inc.
+ */
+
+ENTRY(swab)
+ pushl %esi
+ pushl %edi
+ movl 12(%esp),%esi
+ movl 16(%esp),%edi
+ movl 20(%esp),%ecx
+
+ cld # set direction forward
+
+ shrl $1,%ecx
+ testl $7,%ecx # copy first group of 1 to 7 words
+ jz L2 # while swaping alternate bytes.
+ .align 2,0x90
+L1: lodsw
+ rorw $8,%ax
+ stosw
+ decl %ecx
+ testl $7,%ecx
+ jnz L1
+
+L2: shrl $3,%ecx # copy remainder 8 words at a time
+ jz L4 # while swapping alternate bytes.
+ .align 2,0x90
+L3: lodsw
+ rorw $8,%ax
+ stosw
+ lodsw
+ rorw $8,%ax
+ stosw
+ lodsw
+ rorw $8,%ax
+ stosw
+ lodsw
+ rorw $8,%ax
+ stosw
+ lodsw
+ rorw $8,%ax
+ stosw
+ lodsw
+ rorw $8,%ax
+ stosw
+ lodsw
+ rorw $8,%ax
+ stosw
+ lodsw
+ rorw $8,%ax
+ stosw
+ decl %ecx
+ jnz L3
+
+L4: popl %edi
+ popl %esi
+ ret
+END(swab)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/wcschr.S b/lib/libc/i386/string/wcschr.S
new file mode 100644
index 0000000..37862a9
--- /dev/null
+++ b/lib/libc/i386/string/wcschr.S
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 2003 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * wchar_t *
+ * wcschr(const wchar_t *s, wchar_t c) --
+ * Return pointer to first occurrence of the character `c' in the wide
+ * character string `s', or NULL if not found.
+ */
+ENTRY(wcschr)
+ movl 4(%esp),%ecx /* String */
+ movl 8(%esp),%eax /* Character */
+ pushl %ebx
+.p2align 4,0x90
+L1: movl (%ecx),%ebx
+ cmpl %eax,%ebx
+ je found0
+ testl %ebx,%ebx
+ jz no
+ movl 4(%ecx),%ebx
+ cmpl %eax,%ebx
+ je found1
+ testl %ebx,%ebx
+ jz no
+ movl 8(%ecx),%ebx
+ cmpl %eax,%ebx
+ je found2
+ testl %ebx,%ebx
+ jz no
+ movl 12(%ecx),%ebx
+ cmpl %eax,%ebx
+ je found3
+ testl %ebx,%ebx
+ jz no
+ leal 16(%ecx),%ecx
+ jmp L1
+.p2align 2,0x90
+found3: leal 4(%ecx),%ecx
+.p2align 2,0x90
+found2: leal 4(%ecx),%ecx
+.p2align 2,0x90
+found1: leal 4(%ecx),%ecx
+.p2align 2,0x90
+found0: popl %ebx
+ movl %ecx,%eax
+ ret
+.p2align 2,0x90
+no: popl %ebx
+ xorl %eax,%eax
+ ret
+END(wcschr)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/wcscmp.S b/lib/libc/i386/string/wcscmp.S
new file mode 100644
index 0000000..6fbcb8c
--- /dev/null
+++ b/lib/libc/i386/string/wcscmp.S
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2003 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * int
+ * wcscmp(const wchar_t *s1, const wchar_t *s2) --
+ * Return an integer greater than, equal to, or less than 0, when
+ * the string s1 is greater than, equal to, or less than the string s2.
+ */
+ENTRY(wcscmp)
+ pushl %edi
+ pushl %esi
+ movl 12(%esp),%edi /* s1 */
+ movl 16(%esp),%esi /* s2 */
+.p2align 4,0x90
+top: movl (%edi),%eax
+ cmpl %eax,(%esi)
+ jne no0
+ testl %eax,%eax
+ jz same
+ movl 4(%edi),%eax
+ cmpl %eax,4(%esi)
+ jne no4
+ testl %eax,%eax
+ jz same
+ movl 8(%edi),%eax
+ cmpl %eax,8(%esi)
+ jne no8
+ testl %eax,%eax
+ jz same
+ movl 12(%edi),%eax
+ cmpl %eax,12(%esi)
+ jne no12
+ leal 16(%edi),%edi
+ leal 16(%esi),%esi
+ testl %eax,%eax
+ jnz top
+.p2align 2,0x90
+same: xorl %eax,%eax
+ popl %esi
+ popl %edi
+ ret
+.p2align 2,0x90
+no12: leal 4(%esi),%esi
+.p2align 2,0x90
+no8: leal 4(%esi),%esi
+.p2align 2,0x90
+no4: leal 4(%esi),%esi
+.p2align 2,0x90
+no0: subl (%esi),%eax
+ popl %esi
+ popl %edi
+ ret
+END(wcscmp)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/wcslen.S b/lib/libc/i386/string/wcslen.S
new file mode 100644
index 0000000..691e17f
--- /dev/null
+++ b/lib/libc/i386/string/wcslen.S
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2003 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * size_t
+ * wcslen(const wchar_t *s) --
+ * Find the length of a wide character string.
+ */
+ENTRY(wcslen)
+ movl 4(%esp),%ecx /* String */
+ pushl %ebx
+ xorl %ebx,%ebx
+ xorl %eax,%eax
+.p2align 4,0x90
+L1: cmpl %ebx,(%ecx)
+ jz found0
+ cmpl %ebx,4(%ecx)
+ jz found1
+ cmpl %ebx,8(%ecx)
+ jz found2
+ cmpl %ebx,12(%ecx)
+ jz found3
+ cmpl %ebx,16(%ecx)
+ jz found4
+ cmpl %ebx,20(%ecx)
+ jz found5
+ cmpl %ebx,24(%ecx)
+ jz found6
+ cmpl %ebx,28(%ecx)
+ jz found7
+ leal 32(%ecx),%ecx
+ addl $8,%eax
+ jmp L1
+found7: incl %eax
+found6: incl %eax
+found5: incl %eax
+found4: incl %eax
+found3: incl %eax
+found2: incl %eax
+found1: incl %eax
+found0: popl %ebx
+ ret
+END(wcslen)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/string/wmemchr.S b/lib/libc/i386/string/wmemchr.S
new file mode 100644
index 0000000..2e81c09
--- /dev/null
+++ b/lib/libc/i386/string/wmemchr.S
@@ -0,0 +1,108 @@
+/*-
+ * Copyright (c) 2003 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * wchar_t *
+ * wmemchr(const wchar_t *buf, wchar_t c, size_t n) --
+ * Search the wide character array `buf', which has length `n',
+ * the character `c', return a pointer to it if found, or NULL on
+ * failure.
+ */
+ENTRY(wmemchr)
+ pushl %edi
+ pushl %ebx
+ movl 12(%esp),%edi /* Buffer */
+ movl 16(%esp),%eax /* Wide character */
+ movl 20(%esp),%ecx /* Length of buffer */
+
+ /*
+ * Search in chunks of 8 wide characters (32 bytes).
+ */
+ movl %ecx,%ebx
+ shrl $3,%ecx
+ jz small
+.p2align 4,0x90
+bigloop:cmpl %eax,(%edi)
+ je found
+ cmpl %eax,4(%edi)
+ je found4
+ cmpl %eax,8(%edi)
+ je found8
+ cmpl %eax,12(%edi)
+ je found12
+ cmpl %eax,16(%edi)
+ je found16
+ cmpl %eax,20(%edi)
+ je found20
+ cmpl %eax,24(%edi)
+ je found24
+ cmpl %eax,28(%edi)
+ je found28
+ leal 32(%edi),%edi
+ decl %ecx
+ jnz bigloop
+ jmp small
+found: movl %edi,%eax
+ popl %ebx
+ popl %edi
+ ret
+found4: leal 4(%edi),%edi
+ jmp found
+found8: leal 8(%edi),%edi
+ jmp found
+found12:leal 12(%edi),%edi
+ jmp found
+found16:leal 16(%edi),%edi
+ jmp found
+found20:leal 20(%edi),%edi
+ jmp found
+found24:leal 24(%edi),%edi
+ jmp found
+found28:leal 28(%edi),%edi
+ jmp found
+
+ /*
+ * Search remaining part of string.
+ */
+small: movl %ebx,%ecx
+ andl $7,%ecx
+ jz no
+.p2align 2,0x90
+smltop: cmpl %eax,(%edi)
+ je found
+ leal 4(%edi),%edi
+ decl %ecx
+ jnz smltop
+no: xorl %eax,%eax
+ popl %ebx
+ popl %edi
+ ret
+END(wmemchr)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/Makefile.inc b/lib/libc/i386/sys/Makefile.inc
new file mode 100644
index 0000000..98a9c9e
--- /dev/null
+++ b/lib/libc/i386/sys/Makefile.inc
@@ -0,0 +1,26 @@
+# from: Makefile.inc,v 1.1 1993/09/03 19:04:23 jtc Exp
+# $FreeBSD$
+
+.if !defined(COMPAT_32BIT)
+SRCS+= i386_clr_watch.c i386_set_watch.c i386_vm86.c
+.endif
+SRCS+= i386_get_fsbase.c i386_get_gsbase.c i386_get_ioperm.c i386_get_ldt.c \
+ i386_set_fsbase.c i386_set_gsbase.c i386_set_ioperm.c i386_set_ldt.c
+
+MDASM= Ovfork.S brk.S cerror.S exect.S getcontext.S pipe.S ptrace.S \
+ reboot.S sbrk.S setlogin.S sigreturn.S syscall.S
+
+# Don't generate default code for these syscalls:
+NOASM= break.o exit.o getlogin.o openbsd_poll.o sstk.o vfork.o yield.o
+
+PSEUDO= _getlogin.o _exit.o
+.if !defined(WITHOUT_SYSCALL_COMPAT)
+PSEUDO+= _pread.o _pwrite.o _lseek.o _mmap.o _ftruncate.o _truncate.o
+.endif
+
+MAN+= i386_get_ioperm.2 i386_get_ldt.2 i386_vm86.2
+MAN+= i386_set_watch.3
+
+MLINKS+=i386_get_ioperm.2 i386_set_ioperm.2
+MLINKS+=i386_get_ldt.2 i386_set_ldt.2
+MLINKS+=i386_set_watch.3 i386_clr_watch.3
diff --git a/lib/libc/i386/sys/Ovfork.S b/lib/libc/i386/sys/Ovfork.S
new file mode 100644
index 0000000..e3cc45d
--- /dev/null
+++ b/lib/libc/i386/sys/Ovfork.S
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)Ovfork.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .weak _vfork
+ .set _vfork,__sys_vfork
+ .weak vfork
+ .set vfork,__sys_vfork
+ENTRY(__sys_vfork)
+ popl %ecx /* my rta into ecx */
+ mov $SYS_vfork,%eax
+ KERNCALL
+ jb 1f
+ jmp *%ecx
+1:
+ pushl %ecx
+ PIC_PROLOGUE
+ jmp PIC_PLT(HIDENAME(cerror))
+END(__sys_vfork)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/brk.S b/lib/libc/i386/sys/brk.S
new file mode 100644
index 0000000..968e437
--- /dev/null
+++ b/lib/libc/i386/sys/brk.S
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)brk.s 5.2 (Berkeley) 12/17/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl HIDENAME(curbrk)
+ .globl HIDENAME(minbrk)
+ENTRY(_brk)
+ jmp ok
+END(_brk)
+
+ENTRY(brk)
+#ifdef PIC
+ movl 4(%esp),%eax
+ PIC_PROLOGUE
+ movl PIC_GOT(HIDENAME(curbrk)),%edx # set up GOT addressing
+ movl PIC_GOT(HIDENAME(minbrk)),%ecx #
+ PIC_EPILOGUE
+ cmpl %eax,(%ecx)
+ jbe ok
+ movl (%ecx),%eax
+ movl %eax,4(%esp)
+ok:
+ mov $SYS_break,%eax
+ KERNCALL
+ jb err
+ movl 4(%esp),%eax
+ movl %eax,(%edx)
+ movl $0,%eax
+ ret
+err:
+ PIC_PROLOGUE
+ jmp PIC_PLT(HIDENAME(cerror))
+
+#else
+
+ movl 4(%esp),%eax
+ cmpl %eax,HIDENAME(minbrk)
+ jbe ok
+ movl HIDENAME(minbrk),%eax
+ movl %eax,4(%esp)
+ok:
+ mov $SYS_break,%eax
+ KERNCALL
+ jb err
+ movl 4(%esp),%eax
+ movl %eax,HIDENAME(curbrk)
+ movl $0,%eax
+ ret
+err:
+ jmp HIDENAME(cerror)
+#endif
+END(brk)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/cerror.S b/lib/libc/i386/sys/cerror.S
new file mode 100644
index 0000000..129cc1b
--- /dev/null
+++ b/lib/libc/i386/sys/cerror.S
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)cerror.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl HIDENAME(cerror)
+
+ /*
+ * The __error() function is thread aware. For non-threaded
+ * programs and the initial threaded in threaded programs,
+ * it returns a pointer to the global errno variable.
+ */
+ .globl CNAME(__error)
+ .type CNAME(__error),@function
+HIDENAME(cerror):
+ pushl %eax
+#ifdef PIC
+ /* The caller must execute the PIC prologue before jumping to cerror. */
+ call PIC_PLT(CNAME(__error))
+ popl %ecx
+ PIC_EPILOGUE
+#else
+ call CNAME(__error)
+ popl %ecx
+#endif
+ movl %ecx,(%eax)
+ movl $-1,%eax
+ movl $-1,%edx
+ ret
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/exect.S b/lib/libc/i386/sys/exect.S
new file mode 100644
index 0000000..3ae87b8
--- /dev/null
+++ b/lib/libc/i386/sys/exect.S
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)exect.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+#include <machine/psl.h>
+
+ENTRY(exect)
+ mov $SYS_execve,%eax
+ pushf
+ popl %edx
+ orl $ PSL_T,%edx
+ pushl %edx
+ popf
+ KERNCALL
+ PIC_PROLOGUE
+ jmp PIC_PLT(HIDENAME(cerror)) /* exect(file, argv, env); */
+END(exect)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/getcontext.S b/lib/libc/i386/sys/getcontext.S
new file mode 100644
index 0000000..c24dbdc
--- /dev/null
+++ b/lib/libc/i386/sys/getcontext.S
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2003 Peter Wemm <peter@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include <SYS.h>
+
+/*
+ * This has to be magic to handle the multiple returns.
+ * Otherwise, the setcontext() syscall will return here and we'll
+ * pop off the return address and go to the *setcontext* call.
+ */
+ .weak _getcontext
+ .set _getcontext,__sys_getcontext
+ .weak getcontext
+ .set getcontext,__sys_getcontext
+ENTRY(__sys_getcontext)
+ movl (%esp),%ecx /* save getcontext return address */
+ mov $SYS_getcontext,%eax
+ KERNCALL
+ jb 1f
+ addl $4,%esp /* remove stale (setcontext) return address */
+ jmp *%ecx /* restore return address */
+1:
+ PIC_PROLOGUE
+ jmp PIC_PLT(HIDENAME(cerror))
+END(__sys_getcontext)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/i386_clr_watch.c b/lib/libc/i386/sys/i386_clr_watch.c
new file mode 100644
index 0000000..721c1b8
--- /dev/null
+++ b/lib/libc/i386/sys/i386_clr_watch.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright 2000 Brian S. Dean <bsd@bsdhome.com>
+ * All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRIAN S. DEAN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRIAN S. DEAN BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/reg.h>
+#include <machine/sysarch.h>
+
+int
+i386_clr_watch(int watchnum, struct dbreg * d)
+{
+
+ if (watchnum < 0 || watchnum >= 4)
+ return -1;
+
+ DBREG_DRX(d,7) = DBREG_DRX(d,7) & ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16)));
+ DBREG_DRX(d,watchnum) = 0;
+
+ return 0;
+}
diff --git a/lib/libc/i386/sys/i386_get_fsbase.c b/lib/libc/i386/sys/i386_get_fsbase.c
new file mode 100644
index 0000000..24c4764
--- /dev/null
+++ b/lib/libc/i386/sys/i386_get_fsbase.c
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2005 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/sysarch.h>
+
+int
+i386_get_fsbase(void **addr)
+{
+
+ return (sysarch(I386_GET_FSBASE, addr));
+}
diff --git a/lib/libc/i386/sys/i386_get_gsbase.c b/lib/libc/i386/sys/i386_get_gsbase.c
new file mode 100644
index 0000000..f524f31
--- /dev/null
+++ b/lib/libc/i386/sys/i386_get_gsbase.c
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2005 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/sysarch.h>
+
+int
+i386_get_gsbase(void **addr)
+{
+
+ return (sysarch(I386_GET_GSBASE, addr));
+}
diff --git a/lib/libc/i386/sys/i386_get_ioperm.2 b/lib/libc/i386/sys/i386_get_ioperm.2
new file mode 100644
index 0000000..75fdd10
--- /dev/null
+++ b/lib/libc/i386/sys/i386_get_ioperm.2
@@ -0,0 +1,87 @@
+.\" Copyright (c) 1998 Jonathan Lemon
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 27, 1998
+.Dt I386_GET_IOPERM 2
+.Os
+.Sh NAME
+.Nm i386_get_ioperm ,
+.Nm i386_set_ioperm
+.Nd manage per-process access to the i386 I/O port space
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In machine/sysarch.h
+.Ft int
+.Fn i386_get_ioperm "unsigned int start" "unsigned int *length" "int *enable"
+.Ft int
+.Fn i386_set_ioperm "unsigned int start" "unsigned int length" "int enable"
+.Sh DESCRIPTION
+The
+.Fn i386_get_ioperm
+system call
+will return the permission for the process' I/O port space in the
+.Fa *enable
+argument.
+The port range starts at
+.Fa start
+and the number of contiguous entries will be returned in
+.Fa *length .
+.Pp
+The
+.Fn i386_set_ioperm
+system call
+will set access to a range of I/O ports described by the
+.Fa start
+and
+.Fa length
+arguments to the state specified by the
+.Fa enable
+argument.
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+The
+.Fn i386_get_ioperm
+and
+.Fn i386_set_ioperm
+system calls
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+An invalid range was specified by the
+.Fa start
+or
+.Fa length
+arguments.
+.It Bq Er EPERM
+The caller of i386_set_ioperm was not the superuser.
+.El
+.Sh SEE ALSO
+.Xr io 4
+.Sh AUTHORS
+This man page was written by
+.An Jonathan Lemon .
diff --git a/lib/libc/i386/sys/i386_get_ioperm.c b/lib/libc/i386/sys/i386_get_ioperm.c
new file mode 100644
index 0000000..7bc27f8
--- /dev/null
+++ b/lib/libc/i386/sys/i386_get_ioperm.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1998 Jonathan Lemon
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/sysarch.h>
+
+int
+i386_get_ioperm(unsigned int start, unsigned int *length, int *enable)
+{
+ struct i386_ioperm_args p;
+ int error;
+
+ p.start = start;
+ p.length = *length;
+ p.enable = *enable;
+
+ error = sysarch(I386_GET_IOPERM, &p);
+
+ *length = p.length;
+ *enable = p.enable;
+
+ return (error);
+}
diff --git a/lib/libc/i386/sys/i386_get_ldt.2 b/lib/libc/i386/sys/i386_get_ldt.2
new file mode 100644
index 0000000..d6bf872
--- /dev/null
+++ b/lib/libc/i386/sys/i386_get_ldt.2
@@ -0,0 +1,139 @@
+.\" Copyright (c) 1980, 1991 Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from: @(#)fork.2 6.5 (Berkeley) 3/10/91
+.\" $FreeBSD$
+.\"
+.Dd October 14, 2006
+.Dt I386_GET_LDT 2
+.Os
+.Sh NAME
+.Nm i386_get_ldt ,
+.Nm i386_set_ldt
+.Nd manage i386 per-process Local Descriptor Table entries
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In machine/segments.h
+.In machine/sysarch.h
+.Ft int
+.Fn i386_get_ldt "int start_sel" "union descriptor *descs" "int num_sels"
+.Ft int
+.Fn i386_set_ldt "int start_sel" "union descriptor *descs" "int num_sels"
+.Sh DESCRIPTION
+The
+.Fn i386_get_ldt
+system call
+returns a list of the i386 descriptors in the current process'
+LDT.
+The
+.Fn i386_set_ldt
+system call
+sets a list of i386 descriptors in the current process'
+LDT.
+For both routines,
+.Fa start_sel
+specifies the index of the selector in the LDT at which to begin and
+.Fa descs
+points to an array of
+.Fa num_sels
+descriptors to be set or returned.
+.Pp
+Each entry in the
+.Fa descs
+array can be either a segment_descriptor or gate_descriptor and are defined in
+.In i386/segments.h .
+These structures are defined by the architecture
+as disjoint bit-fields, so care must be taken in constructing them.
+.Pp
+If
+.Fa start_sel
+is
+.Em LDT_AUTO_ALLOC ,
+.Fa num_sels
+is 1 and the descriptor pointed to by
+.Fa descs
+is legal, then
+.Fn i386_set_ldt
+will allocate a descriptor and return its
+selector number.
+.Pp
+If
+.Fa num_descs
+is 1,
+.Fa start_sels
+is valid, and
+.Fa descs
+is NULL, then
+.Fn i386_set_ldt
+will free that descriptor
+(making it available to be reallocated again later).
+.Pp
+If
+.Fa num_descs
+is 0,
+.Fa start_sels
+is 0 and
+.Fa descs
+is NULL then, as a special case,
+.Fn i386_set_ldt
+will free all descriptors.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn i386_get_ldt
+returns the number of descriptors currently in the LDT.
+The
+.Fn i386_set_ldt
+system call
+returns the first selector set on success.
+If the kernel allocated a descriptor in the LDT,
+the allocated index is returned.
+Otherwise, a value of -1 is returned and the global
+variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+The
+.Fn i386_get_ldt
+and
+.Fn i386_set_ldt
+system calls
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+An inappropriate value was used for
+.Fa start_sel
+or
+.Fa num_sels .
+.It Bq Er EACCES
+The caller attempted to use a descriptor that would
+circumvent protection or cause a failure.
+.El
+.Sh SEE ALSO
+i386 Microprocessor Programmer's Reference Manual, Intel
+.Sh WARNING
+You can really hose your process using this.
diff --git a/lib/libc/i386/sys/i386_get_ldt.c b/lib/libc/i386/sys/i386_get_ldt.c
new file mode 100644
index 0000000..73d7667
--- /dev/null
+++ b/lib/libc/i386/sys/i386_get_ldt.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1993 John Brezak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/cdefs.h>
+#include <machine/segments.h>
+#include <machine/sysarch.h>
+
+int
+i386_get_ldt(int start, union descriptor *descs, int num)
+{
+ struct i386_ldt_args p;
+
+ p.start = start;
+ p.descs = descs;
+ p.num = num;
+
+ return sysarch(I386_GET_LDT, &p);
+}
diff --git a/lib/libc/i386/sys/i386_set_fsbase.c b/lib/libc/i386/sys/i386_set_fsbase.c
new file mode 100644
index 0000000..6b55446
--- /dev/null
+++ b/lib/libc/i386/sys/i386_set_fsbase.c
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2005 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/sysarch.h>
+
+int
+i386_set_fsbase(void *addr)
+{
+
+ return (sysarch(I386_SET_FSBASE, &addr));
+}
diff --git a/lib/libc/i386/sys/i386_set_gsbase.c b/lib/libc/i386/sys/i386_set_gsbase.c
new file mode 100644
index 0000000..aaf2312
--- /dev/null
+++ b/lib/libc/i386/sys/i386_set_gsbase.c
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2005 Peter Wemm
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/sysarch.h>
+
+int
+i386_set_gsbase(void *addr)
+{
+
+ return (sysarch(I386_SET_GSBASE, &addr));
+}
diff --git a/lib/libc/i386/sys/i386_set_ioperm.c b/lib/libc/i386/sys/i386_set_ioperm.c
new file mode 100644
index 0000000..258e2af
--- /dev/null
+++ b/lib/libc/i386/sys/i386_set_ioperm.c
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 1998 Jonathan Lemon
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/sysarch.h>
+
+int
+i386_set_ioperm(unsigned int start, unsigned int length, int enable)
+{
+ struct i386_ioperm_args p;
+
+ p.start = start;
+ p.length = length;
+ p.enable = enable;
+
+ return (sysarch(I386_SET_IOPERM, &p));
+}
diff --git a/lib/libc/i386/sys/i386_set_ldt.c b/lib/libc/i386/sys/i386_set_ldt.c
new file mode 100644
index 0000000..0bb109a
--- /dev/null
+++ b/lib/libc/i386/sys/i386_set_ldt.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1993 John Brezak
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR `AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
+ * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/cdefs.h>
+#include <machine/segments.h>
+#include <machine/sysarch.h>
+
+int
+i386_set_ldt(int start, union descriptor *descs, int num)
+{
+ struct i386_ldt_args p;
+
+ p.start = start;
+ p.descs = descs;
+ p.num = num;
+
+ return sysarch(I386_SET_LDT, &p);
+}
diff --git a/lib/libc/i386/sys/i386_set_watch.3 b/lib/libc/i386/sys/i386_set_watch.3
new file mode 100644
index 0000000..9f37c9d
--- /dev/null
+++ b/lib/libc/i386/sys/i386_set_watch.3
@@ -0,0 +1,118 @@
+.\" Copyright (c) 2000 Brian S. Dean
+.\" All rights reserved.
+.\"
+.\" This man-page is based on a similar man-page by Jonathan Lemon
+.\" which is copyrighted under the following conditions:
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 24, 2000
+.Dt I386_SET_WATCH 3
+.Os
+.Sh NAME
+.Nm i386_clr_watch ,
+.Nm i386_set_watch
+.Nd manage i386 debug register values
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In machine/reg.h
+.In machine/sysarch.h
+.Ft int
+.Fn i386_clr_watch "int watchnum" "struct dbreg *d"
+.Ft int
+.Fn i386_set_watch "int watchnum" "unsigned int watchaddr" "int size" "int access" "struct dbreg *d"
+.Sh DESCRIPTION
+The
+.Fn i386_clr_watch
+function
+will disable the indicated watch point within the specified debug
+register set.
+.Pp
+The
+.Fn i386_set_watch
+function
+will set up the specified debug registers as indicated by the
+arguments.
+The
+.Fa watchnum
+argument specifies which watch register is used, 0, 1, 2, 3, or \-1.
+If
+.Fa watchnum
+is \-1, a free watch register is found and used.
+If there are no free
+watch registers, an error code of \-1 is returned.
+The
+.Fa watchaddr
+argument
+specifies the watch address,
+.Fa size
+specifies the size in bytes of the area to be watched (1, 2, or 4 bytes),
+and
+.Fa access
+specifies the type of watch point:
+.Pp
+.Bd -literal -offset indent -compact
+DBREG_DR7_EXEC An execution breakpoint.
+DBREG_DR7_WRONLY Break only when the watch area is written to.
+DBREG_DR7_RDWR Break when the watch area is read from or written
+ to.
+.Ed
+.Pp
+Note that these functions do not actually set or clear breakpoints;
+they manipulate the indicated debug register set.
+You must use
+.Xr ptrace 2
+to retrieve and install the debug register values for a process.
+.Sh RETURN VALUES
+On success, the
+.Fn i386_clr_watch
+function returns 0.
+On error, \-1 returned which indicates that
+.Fa watchnum
+is invalid (not in the range of 0-3).
+If the specified watchnum was already disabled, no error is returned.
+.Pp
+On success, the
+.Fn i386_set_watch
+function returns the
+.Fa watchnum
+argument, or the watchnum actually used in the case where the specified
+.Fa watchnum
+was \-1.
+On error, the
+.Fn i386_set_watch
+function returns \-1 indicating that the watchpoint could not established
+because either no more watchpoints are available, or
+.Fa watchnum ,
+.Fa size ,
+or
+.Fa access
+is invalid.
+.Sh SEE ALSO
+.Xr ptrace 2 ,
+.Xr procfs 5
+.Sh AUTHORS
+This man page was written by
+.An Brian S. Dean .
diff --git a/lib/libc/i386/sys/i386_set_watch.c b/lib/libc/i386/sys/i386_set_watch.c
new file mode 100644
index 0000000..cc1b8ed
--- /dev/null
+++ b/lib/libc/i386/sys/i386_set_watch.c
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2000 Brian S. Dean <bsd@bsdhome.com>
+ * All Rights Reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRIAN S. DEAN ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRIAN S. DEAN BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
+ * OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
+ * DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/reg.h>
+#include <machine/sysarch.h>
+
+int
+i386_set_watch(int watchnum, unsigned int watchaddr, int size,
+ int access, struct dbreg * d)
+{
+ int i;
+ unsigned int mask;
+
+ if (watchnum == -1) {
+ for (i = 0, mask = 0x3; i < 4; i++, mask <<= 2)
+ if ((DBREG_DRX(d,7) & mask) == 0)
+ break;
+ if (i < 4)
+ watchnum = i;
+ else
+ return -1;
+ }
+
+ switch (access) {
+ case DBREG_DR7_EXEC:
+ size = 1; /* size must be 1 for an execution breakpoint */
+ /* fall through */
+ case DBREG_DR7_WRONLY:
+ case DBREG_DR7_RDWR:
+ break;
+ default : return -1; break;
+ }
+
+ /*
+ * we can watch a 1, 2, or 4 byte sized location
+ */
+ switch (size) {
+ case 1 : mask = 0x00; break;
+ case 2 : mask = 0x01 << 2; break;
+ case 4 : mask = 0x03 << 2; break;
+ default : return -1; break;
+ }
+
+ mask |= access;
+
+ /* clear the bits we are about to affect */
+ DBREG_DRX(d,7) &= ~((0x3 << (watchnum*2)) | (0x0f << (watchnum*4+16)));
+
+ /* set drN register to the address, N=watchnum */
+ DBREG_DRX(d,watchnum) = watchaddr;
+
+ /* enable the watchpoint */
+ DBREG_DRX(d,7) |= (0x2 << (watchnum*2)) | (mask << (watchnum*4+16));
+
+ return watchnum;
+}
diff --git a/lib/libc/i386/sys/i386_vm86.2 b/lib/libc/i386/sys/i386_vm86.2
new file mode 100644
index 0000000..5958f31
--- /dev/null
+++ b/lib/libc/i386/sys/i386_vm86.2
@@ -0,0 +1,141 @@
+.\" Copyright (c) 1998 Jonathan Lemon
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 27, 1998
+.Dt I386_VM86 2
+.Os
+.Sh NAME
+.Nm i386_vm86
+.Nd control vm86-related functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In machine/sysarch.h
+.In machine/vm86.h
+.Ft int
+.Fn i386_vm86 "int function" "void *data"
+.Sh DESCRIPTION
+The
+.Fn i386_vm86
+system call
+is used to call various vm86 related functions.
+The
+.Fa function
+argument
+can be one of the following values:
+.Bl -tag -offset indent -width VM86_SET_VME
+.It Dv VM86_INIT
+This will initialize the kernel's vm86 parameter area for the
+process, and permit the process to make vm86 calls.
+The
+.Fa data
+argument
+points to the following structure:
+.Bd -literal
+struct vm86_init_args {
+ int debug;
+ int cpu_type;
+ u_char int_map[32];
+};
+.Ed
+.Pp
+The
+.Fa debug
+argument
+is used to turn on debugging code.
+The
+.Fa cpu_type
+argument
+controls the type of CPU being emulated, and is currently unimplemented.
+The
+.Fa int_map
+argument
+is a bitmap which determines whether vm86 interrupts should be handled
+in vm86 mode, or reflected back to the process.
+If the
+.Em Nth
+bit is set, the interrupt will be reflected to the process, otherwise
+it will be dispatched by the vm86 interrupt table.
+.It Dv VM86_INTCALL
+This allows calls to be made to vm86 interrupt handlers by the process.
+It effectively simulates an INT instruction.
+.Fa data
+should point to the following structure:
+.Bd -literal
+struct vm86_intcall_args {
+ int intnum;
+ struct vm86frame vmf;
+};
+.Ed
+.Pp
+.Fa intnum
+specifies the operand of INT for the simulated call.
+A value of 0x10, for example, would often be used to call into the VGA BIOS.
+.Fa vmf
+is used to initialize CPU registers according to the calling convention for
+the interrupt handler.
+.It Dv VM86_GET_VME
+This is used to retrieve the current state of the Pentium(r) processor's
+VME (Virtual-8086 Mode Extensions) flag, which is bit 0 of CR4.
+.Fa data
+should be initialized to point to the following:
+.Bd -literal
+struct vm86_vme_args {
+ int state; /* status */
+};
+.Ed
+.Pp
+.Fa state
+will contain the state of the VME flag on return.
+.\" .It Dv VM86_SET_VME
+.El
+.Pp
+vm86 mode is entered by calling
+.Xr sigreturn 2
+with the correct machine context for vm86, and with the
+.Dv PSL_VM
+bit set.
+Control returns to the process upon delivery of a signal.
+.Sh RETURN VALUES
+.Rv -std i386_vm86
+.Sh ERRORS
+The
+.Fn i386_vm86
+system call
+will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The kernel does not have vm86 support, or an invalid function was specified.
+.It Bq Er ENOMEM
+There is not enough memory to initialize the kernel data structures.
+.El
+.Sh AUTHORS
+.An -nosplit
+This man page was written by
+.An Jonathan Lemon ,
+and updated by
+.An Bruce M Simpson .
diff --git a/lib/libc/i386/sys/i386_vm86.c b/lib/libc/i386/sys/i386_vm86.c
new file mode 100644
index 0000000..c007608
--- /dev/null
+++ b/lib/libc/i386/sys/i386_vm86.c
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 1998 Jonathan Lemon
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/sysarch.h>
+
+int
+i386_vm86(int fcn, void *data)
+{
+ struct i386_vm86_args p;
+
+ p.sub_op = fcn;
+ p.sub_args = (char *)data;
+
+ return (sysarch(I386_VM86, &p));
+}
diff --git a/lib/libc/i386/sys/pipe.S b/lib/libc/i386/sys/pipe.S
new file mode 100644
index 0000000..85f4fd2
--- /dev/null
+++ b/lib/libc/i386/sys/pipe.S
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)pipe.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+SYSCALL(pipe)
+ movl 4(%esp),%ecx
+ movl %eax,(%ecx)
+ movl %edx,4(%ecx)
+ movl $0,%eax
+ ret
+END(__sys_pipe)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/ptrace.S b/lib/libc/i386/sys/ptrace.S
new file mode 100644
index 0000000..6e5e885
--- /dev/null
+++ b/lib/libc/i386/sys/ptrace.S
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)ptrace.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ENTRY(ptrace)
+ xorl %eax,%eax
+#ifdef PIC
+ PIC_PROLOGUE
+ movl PIC_GOT(CNAME(errno)),%edx
+ movl %eax,(%edx)
+ PIC_EPILOGUE
+#else
+ movl %eax,CNAME(errno)
+#endif
+ mov $SYS_ptrace,%eax
+ KERNCALL
+ jb err
+ ret
+err:
+ PIC_PROLOGUE
+ jmp PIC_PLT(HIDENAME(cerror))
+END(ptrace)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/reboot.S b/lib/libc/i386/sys/reboot.S
new file mode 100644
index 0000000..f11000e
--- /dev/null
+++ b/lib/libc/i386/sys/reboot.S
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)reboot.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+SYSCALL(reboot)
+ iret
+END(__sys_reboot)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/sbrk.S b/lib/libc/i386/sys/sbrk.S
new file mode 100644
index 0000000..337087a
--- /dev/null
+++ b/lib/libc/i386/sys/sbrk.S
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)sbrk.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl CNAME(_end)
+ .globl HIDENAME(minbrk)
+ .globl HIDENAME(curbrk)
+
+ .data
+HIDENAME(minbrk): .long CNAME(_end)
+HIDENAME(curbrk): .long CNAME(_end)
+ .text
+
+ENTRY(sbrk)
+#ifdef PIC
+ movl 4(%esp),%ecx
+ PIC_PROLOGUE
+ movl PIC_GOT(HIDENAME(curbrk)),%edx
+ movl (%edx),%eax
+ PIC_EPILOGUE
+ testl %ecx,%ecx
+ jz back
+ addl %eax,4(%esp)
+ mov $SYS_break,%eax
+ KERNCALL
+ jb err
+ PIC_PROLOGUE
+ movl PIC_GOT(HIDENAME(curbrk)),%edx
+ movl (%edx),%eax
+ addl %ecx,(%edx)
+ PIC_EPILOGUE
+back:
+ ret
+err:
+ PIC_PROLOGUE
+ jmp PIC_PLT(HIDENAME(cerror))
+
+#else /* !PIC */
+
+ movl 4(%esp),%ecx
+ movl HIDENAME(curbrk),%eax
+ testl %ecx,%ecx
+ jz back
+ addl %eax,4(%esp)
+ mov $SYS_break,%eax
+ KERNCALL
+ jb err
+ movl HIDENAME(curbrk),%eax
+ addl %ecx,HIDENAME(curbrk)
+back:
+ ret
+err:
+ jmp HIDENAME(cerror)
+#endif /* PIC */
+END(sbrk)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/setlogin.S b/lib/libc/i386/sys/setlogin.S
new file mode 100644
index 0000000..c6436b5
--- /dev/null
+++ b/lib/libc/i386/sys/setlogin.S
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 1991 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ .asciz "@(#)setlogin.s 5.2 (Berkeley) 4/12/91"
+#endif /* LIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+.globl CNAME(_logname_valid) /* in _getlogin() */
+
+SYSCALL(setlogin)
+#ifdef PIC
+ PIC_PROLOGUE
+ pushl %eax
+ movl PIC_GOT(CNAME(_logname_valid)),%eax
+ movl $0,(%eax)
+ popl %eax
+ PIC_EPILOGUE
+#else
+ movl $0,CNAME(_logname_valid)
+#endif
+ ret /* setlogin(name) */
+END(__sys_setlogin)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/sigreturn.S b/lib/libc/i386/sys/sigreturn.S
new file mode 100644
index 0000000..f91816e
--- /dev/null
+++ b/lib/libc/i386/sys/sigreturn.S
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)sigreturn.s 5.2 (Berkeley) 12/17/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+/*
+ * NOTE: If the profiling ENTRY() code ever changes any registers, they
+ * must be saved. On FreeBSD, this is not the case.
+ */
+
+RSYSCALL(sigreturn)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/i386/sys/syscall.S b/lib/libc/i386/sys/syscall.S
new file mode 100644
index 0000000..e5d6e23
--- /dev/null
+++ b/lib/libc/i386/sys/syscall.S
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)syscall.s 5.1 (Berkeley) 4/23/90"
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ENTRY(syscall)
+ pop %ecx /* rta */
+ pop %eax /* syscall number */
+ push %ecx
+ KERNCALL
+ push %ecx /* need to push a word to keep stack frame intact
+ upon return; the word must be the return address. */
+ jb 1f
+ ret
+1:
+ PIC_PROLOGUE
+ jmp PIC_PLT(HIDENAME(cerror))
+END(syscall)
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/ia64/Makefile.inc b/lib/libc/ia64/Makefile.inc
new file mode 100644
index 0000000..b451f85
--- /dev/null
+++ b/lib/libc/ia64/Makefile.inc
@@ -0,0 +1,9 @@
+# $FreeBSD$
+#
+# Machine dependent definitions for the ia64 architecture.
+#
+
+# Long double is 80 bits
+GDTOASRCS+=strtorx.c
+MDSRCS+=machdep_ldisx.c
+SYM_MAPS+=${.CURDIR}/ia64/Symbol.map
diff --git a/lib/libc/ia64/SYS.h b/lib/libc/ia64/SYS.h
new file mode 100644
index 0000000..eb019a2
--- /dev/null
+++ b/lib/libc/ia64/SYS.h
@@ -0,0 +1,63 @@
+/* $NetBSD: SYS.h,v 1.5 1997/05/02 18:15:15 kleink Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ *
+ * $FreeBSD$
+ */
+
+#include <machine/asm.h>
+#include <sys/syscall.h>
+
+#define CALLSYS_ERROR(name) \
+ CALLSYS_NOERROR(name); \
+ cmp.ne p6,p0=r0,r10; \
+(p6) br.cond.sptk.few .cerror
+
+
+#define SYSCALL(name) \
+ENTRY(__sys_ ## name,0); /* XXX # of args? */ \
+ WEAK_ALIAS(name, __sys_ ## name); \
+ WEAK_ALIAS(_ ## name, __sys_ ## name); \
+ CALLSYS_ERROR(name)
+
+#define SYSCALL_NOERROR(name) \
+ENTRY(__sys_ ## name,0); /* XXX # of args? */ \
+ WEAK_ALIAS(name, __sys_ ## name); \
+ WEAK_ALIAS(_ ## name, __sys_ ## name); \
+ CALLSYS_NOERROR(name)
+
+#define RSYSCALL(name) \
+ SYSCALL(name); \
+ br.ret.sptk.few rp; \
+END(__sys_ ## name)
+
+#define PSEUDO(name) \
+ENTRY(__sys_ ## name,0); /* XXX # of args? */ \
+ WEAK_ALIAS(_ ## name, __sys_ ## name); \
+ CALLSYS_ERROR(name); \
+ br.ret.sptk.few rp; \
+END(__sys_ ## name);
diff --git a/lib/libc/ia64/Symbol.map b/lib/libc/ia64/Symbol.map
new file mode 100644
index 0000000..7a31a51
--- /dev/null
+++ b/lib/libc/ia64/Symbol.map
@@ -0,0 +1,71 @@
+/*
+ * $FreeBSD$
+ */
+
+/*
+ * This only needs to contain symbols that are not listed in
+ * symbol maps from other parts of libc (i.e., not found in
+ * stdlib/Symbol.map, string/Symbol.map, sys/Symbol.map, ...).
+ */
+FBSD_1.0 {
+ /* PSEUDO syscalls */
+ _exit;
+
+ mcount;
+ _setjmp;
+ _longjmp;
+ fabs;
+ __flt_rounds;
+ fpgetmask;
+ fpgetround;
+ fpsetmask;
+ fpsetround;
+ __infinity;
+ __nan;
+ makecontext;
+ setjmp;
+ longjmp;
+ sigsetjmp;
+ siglongjmp;
+ htonl;
+ htons;
+ ntohl;
+ ntohs;
+ vfork;
+ brk;
+ exect;
+ sbrk;
+};
+
+FBSDprivate_1.0 {
+ /* PSEUDO syscalls */
+ __sys_getlogin;
+ _getlogin;
+ __sys_exit;
+
+ _set_tp;
+ __divdf3;
+ __divdi3;
+ __divsf3;
+ __divsi3;
+ __moddi3;
+ __modsi3;
+ __udivdi3;
+ __udivsi3;
+ __umoddi3;
+ __umodsi3;
+ _mcount;
+ ___longjmp;
+ __makecontext;
+ __longjmp;
+ signalcontext;
+ __signalcontext;
+ __siglongjmp;
+ _Unwind_FindTableEntry;
+ __sys_vfork;
+ _vfork;
+ _end;
+ minbrk;
+ .cerror;
+ curbrk;
+};
diff --git a/lib/libc/ia64/_fpmath.h b/lib/libc/ia64/_fpmath.h
new file mode 100644
index 0000000..936ce23
--- /dev/null
+++ b/lib/libc/ia64/_fpmath.h
@@ -0,0 +1,82 @@
+/*-
+ * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/endian.h>
+
+union IEEEl2bits {
+ long double e;
+ struct {
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+ unsigned int manl :32;
+ unsigned int manh :32;
+ unsigned int exp :15;
+ unsigned int sign :1;
+ unsigned long junk :48;
+#else /* _BIG_ENDIAN */
+ unsigned long junk :48;
+ unsigned int sign :1;
+ unsigned int exp :15;
+ unsigned int manh :32;
+ unsigned int manl :32;
+#endif
+ } bits;
+ struct {
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+ unsigned long man :64;
+ unsigned int expsign :16;
+ unsigned long junk :48;
+#else /* _BIG_ENDIAN */
+ unsigned long junk :48;
+ unsigned int expsign :16;
+ unsigned long man :64;
+#endif
+ } xbits;
+};
+
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+#define LDBL_NBIT 0x80000000
+#define mask_nbit_l(u) ((u).bits.manh &= ~LDBL_NBIT)
+#else /* _BIG_ENDIAN */
+/*
+ * XXX This doesn't look right. Very few machines have a different
+ * endianness for integers and floating-point, and in nextafterl()
+ * we assume that none do. If you have an environment for testing
+ * this, please let me know. --das
+ */
+#define LDBL_NBIT 0x80
+#define mask_nbit_l(u) ((u).bits.manh &= ~LDBL_NBIT)
+#endif
+
+#define LDBL_MANH_SIZE 32
+#define LDBL_MANL_SIZE 32
+
+#define LDBL_TO_ARRAY32(u, a) do { \
+ (a)[0] = (uint32_t)(u).bits.manl; \
+ (a)[1] = (uint32_t)(u).bits.manh; \
+} while (0)
diff --git a/lib/libc/ia64/arith.h b/lib/libc/ia64/arith.h
new file mode 100644
index 0000000..6726528
--- /dev/null
+++ b/lib/libc/ia64/arith.h
@@ -0,0 +1,37 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * NOTE: The definitions in this file must be correct or strtod(3) and
+ * floating point formats in printf(3) will break! The file can be
+ * generated by running contrib/gdtoa/arithchk.c on the target
+ * architecture. See contrib/gdtoa/gdtoaimp.h for details.
+ */
+
+#include <machine/endian.h>
+
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+
+#define IEEE_8087
+#define Arith_Kind_ASL 1
+#define Long int
+#define Intcast (int)(long)
+#define Double_Align
+#define X64_bit_pointers
+
+#else /* _BYTE_ORDER == _LITTLE_ENDIAN */
+
+#define IEEE_MC68k
+#define Arith_Kind_ASL 2
+#define Long int
+#define Intcast (int)(long)
+#define Double_Align
+#define X64_bit_pointers
+#ifdef gcc_bug /* XXX Why does arithchk report sudden underflow here? */
+#define Sudden_Underflow
+#endif
+
+#endif
diff --git a/lib/libc/ia64/gd_qnan.h b/lib/libc/ia64/gd_qnan.h
new file mode 100644
index 0000000..3992386
--- /dev/null
+++ b/lib/libc/ia64/gd_qnan.h
@@ -0,0 +1,21 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * This file can be generated by compiling and running contrib/gdtoa/qnan.c
+ * on the target architecture after arith.h has been generated.
+ *
+ * $FreeBSD$
+ */
+
+#define f_QNAN 0x7fc00000
+#define d_QNAN0 0x0
+#define d_QNAN1 0x7ff80000
+#define ld_QNAN0 0x0
+#define ld_QNAN1 0xc0000000
+#define ld_QNAN2 0x7fff
+#define ld_QNAN3 0x0
+#define ldus_QNAN0 0x0
+#define ldus_QNAN1 0x0
+#define ldus_QNAN2 0x0
+#define ldus_QNAN3 0xc000
+#define ldus_QNAN4 0x7fff
diff --git a/lib/libc/ia64/gen/Makefile.inc b/lib/libc/ia64/gen/Makefile.inc
new file mode 100644
index 0000000..1e3373a
--- /dev/null
+++ b/lib/libc/ia64/gen/Makefile.inc
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+SRCS+= __divdf3.S __divdi3.S __divsf3.S __divsi3.S __moddi3.S __modsi3.S \
+ __udivdi3.S __udivsi3.S __umoddi3.S __umodsi3.S _mcount.S _set_tp.c \
+ _setjmp.S fabs.S flt_rounds.c fpgetmask.c fpgetround.c fpsetmask.c \
+ fpsetround.c getcontextx.c infinity.c ldexp.c makecontext.c setjmp.S \
+ signalcontext.c sigsetjmp.S
+
+# The following may go away if function _Unwind_FindTableEntry()
+# will be part of GCC.
+SRCS+= unwind.c
diff --git a/lib/libc/ia64/gen/__divdf3.S b/lib/libc/ia64/gen/__divdf3.S
new file mode 100644
index 0000000..58425d9
--- /dev/null
+++ b/lib/libc/ia64/gen/__divdf3.S
@@ -0,0 +1,142 @@
+//
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache,
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab,
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ .section .text
+
+ENTRY(__divdf3, 0)
+{ .mfi
+ // a is in f8
+ // b is in f9
+
+ // predicate registers used: p6
+ // floating-point registers used: f6, f7, f8, f9, f10, f11
+
+ // load a, the first argument, in f6
+ nop.m 0
+ mov f6=f8
+ nop.i 0
+} { .mfi
+ // load b, the second argument, in f7
+ nop.m 0
+ mov f7=f9
+ nop.i 0;;
+} { .mfi
+
+ // BEGIN DOUBLE PRECISION LATENCY-OPTIMIZED DIVIDE ALGORITHM
+
+ nop.m 0
+ // Step (1)
+ // y0 = 1 / b in f8
+ frcpa.s0 f8,p6=f6,f7
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (2)
+ // q0 = a * y0 in f9
+ (p6) fma.s1 f9=f6,f8,f0
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (3)
+ // e0 = 1 - b * y0 in f10
+ (p6) fnma.s1 f10=f7,f8,f1
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (4)
+ // q1 = q0 + e0 * q0 in f9
+ (p6) fma.s1 f9=f10,f9,f9
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (5)
+ // e1 = e0 * e0 in f11
+ (p6) fma.s1 f11=f10,f10,f0
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (6)
+ // y1 = y0 + e0 * y0 in f8
+ (p6) fma.s1 f8=f10,f8,f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (7)
+ // q2 = q1 + e1 * q1 in f9
+ (p6) fma.s1 f9=f11,f9,f9
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (8)
+ // e2 = e1 * e1 in f10
+ (p6) fma.s1 f10=f11,f11,f0
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (9)
+ // y2 = y1 + e1 * y1 in f8
+ (p6) fma.s1 f8=f11,f8,f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (10)
+ // q3 = q2 + e2 * q2 in f9
+ (p6) fma.d.s1 f9=f10,f9,f9
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (11)
+ // y3 = y2 + e2 * y2 in f8
+ (p6) fma.s1 f8=f10,f8,f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (12)
+ // r0 = a - b * q3 in f6
+ (p6) fnma.d.s1 f6=f7,f9,f6
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (13)
+ // q4 = q3 + r0 * y3 in f8
+ (p6) fma.d.s0 f8=f6,f8,f9
+ nop.i 0;;
+
+ // END DOUBLE PRECISION LATENCY-OPTIMIZED DIVIDE ALGORITHM
+
+} { .mib
+ nop.m 0
+ nop.i 0
+ // return
+ br.ret.sptk b0;;
+}
+
+END(__divdf3)
+
diff --git a/lib/libc/ia64/gen/__divdi3.S b/lib/libc/ia64/gen/__divdi3.S
new file mode 100644
index 0000000..92e2911
--- /dev/null
+++ b/lib/libc/ia64/gen/__divdi3.S
@@ -0,0 +1,143 @@
+.file "__divdi3.s"
+
+//
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache,
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab,
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+.section .text
+.proc __divdi3#
+.align 32
+.global __divdi3#
+.align 32
+
+// 64-bit signed integer divide
+
+__divdi3:
+
+{ .mii
+ alloc r31=ar.pfs,2,0,0,0
+ nop.i 0
+ nop.i 0;;
+} { .mmi
+
+ // 64-BIT SIGNED INTEGER DIVIDE BEGINS HERE
+
+ setf.sig f8=r32
+ setf.sig f9=r33
+ nop.i 0;;
+} { .mfb
+ nop.m 0
+ fcvt.xf f6=f8
+ nop.b 0
+} { .mfb
+ nop.m 0
+ fcvt.xf f7=f9
+ nop.b 0;;
+} { .mfi
+ nop.m 0
+ // Step (1)
+ // y0 = 1 / b in f8
+ frcpa.s1 f8,p6=f6,f7
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (2)
+ // e0 = 1 - b * y0 in f9
+ (p6) fnma.s1 f9=f7,f8,f1
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (3)
+ // q0 = a * y0 in f10
+ (p6) fma.s1 f10=f6,f8,f0
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (4)
+ // e1 = e0 * e0 in f11
+ (p6) fma.s1 f11=f9,f9,f0
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (5)
+ // q1 = q0 + e0 * q0 in f10
+ (p6) fma.s1 f10=f9,f10,f10
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (6)
+ // y1 = y0 + e0 * y0 in f8
+ (p6) fma.s1 f8=f9,f8,f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (7)
+ // q2 = q1 + e1 * q1 in f9
+ (p6) fma.s1 f9=f11,f10,f10
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (8)
+ // y2 = y1 + e1 * y1 in f8
+ (p6) fma.s1 f8=f11,f8,f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (9)
+ // r2 = a - b * q2 in f10
+ (p6) fnma.s1 f10=f7,f9,f6
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (10)
+ // q3 = q2 + r2 * y2 in f8
+ (p6) fma.s1 f8=f10,f8,f9
+ nop.i 0;;
+} { .mfb
+ nop.m 0
+ // Step (11)
+ // q = trunc (q3)
+ fcvt.fx.trunc.s1 f8=f8
+ nop.b 0;;
+} { .mmi
+ // quotient will be in r8 (if b != 0)
+ getf.sig r8=f8
+ nop.m 0
+ nop.i 0;;
+}
+
+ // 64-BIT SIGNED INTEGER DIVIDE ENDS HERE
+
+{ .mmb
+ nop.m 0
+ nop.m 0
+ br.ret.sptk b0;;
+}
+
+.endp __divdi3
diff --git a/lib/libc/ia64/gen/__divsf3.S b/lib/libc/ia64/gen/__divsf3.S
new file mode 100644
index 0000000..fe7bcb4
--- /dev/null
+++ b/lib/libc/ia64/gen/__divsf3.S
@@ -0,0 +1,116 @@
+//
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache,
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab,
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(__divsf3, 0)
+{ .mfi
+ // a is in f8
+ // b is in f9
+
+ // general registers used: r31, r32, r33, r34
+ // predicate registers used: p6
+ // floating-point registers used: f6, f7, f8
+
+ nop.m 0
+ // load a, the first argument, in f6
+ mov f6=f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // load b, the second argument, in f7
+ mov f7=f9
+ nop.i 0;;
+} { .mfi
+
+ // BEGIN SINGLE PRECISION LATENCY-OPTIMIZED DIVIDE ALGORITHM
+
+ nop.m 0
+ // Step (1)
+ // y0 = 1 / b in f8
+ frcpa.s0 f8,p6=f6,f7
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (2)
+ // q0 = a * y0 in f6
+ (p6) fma.s1 f6=f6,f8,f0
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (3)
+ // e0 = 1 - b * y0 in f7
+ (p6) fnma.s1 f7=f7,f8,f1
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (4)
+ // q1 = q0 + e0 * q0 in f6
+ (p6) fma.s1 f6=f7,f6,f6
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (5)
+ // e1 = e0 * e0 in f7
+ (p6) fma.s1 f7=f7,f7,f0
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (6)
+ // q2 = q1 + e1 * q1 in f6
+ (p6) fma.s1 f6=f7,f6,f6
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (7)
+ // e2 = e1 * e1 in f7
+ (p6) fma.s1 f7=f7,f7,f0
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (8)
+ // q3 = q2 + e2 * q2 in f6
+ (p6) fma.d.s1 f6=f7,f6,f6
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (9)
+ // q3' = q3 in f8
+ (p6) fma.s.s0 f8=f6,f1,f0
+ nop.i 0;;
+
+ // END SINGLE PRECISION LATENCY-OPTIMIZED DIVIDE ALGORITHM
+
+} { .mmb
+ nop.m 0
+ nop.m 0
+ // return
+ br.ret.sptk b0;;
+}
+
+END(__divsf3)
diff --git a/lib/libc/ia64/gen/__divsi3.S b/lib/libc/ia64/gen/__divsi3.S
new file mode 100644
index 0000000..4c82e32
--- /dev/null
+++ b/lib/libc/ia64/gen/__divsi3.S
@@ -0,0 +1,125 @@
+.file "__divsi3.s"
+
+//
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache,
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab,
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+.section .text
+
+// 32-bit signed integer divide
+
+.proc __divsi3#
+.align 32
+.global __divsi3#
+.align 32
+
+__divsi3:
+
+{ .mii
+ alloc r31=ar.pfs,2,0,0,0
+ nop.i 0
+ nop.i 0;;
+} { .mii
+ nop.m 0
+
+ // 32-BIT SIGNED INTEGER DIVIDE BEGINS HERE
+
+ // general register used:
+ // r32 - 32-bit signed integer dividend
+ // r33 - 32-bit signed integer divisor
+ // r8 - 32-bit signed integer result
+ // r2 - scratch register
+ // floating-point registers used: f6, f7, f8, f9
+ // predicate registers used: p6
+
+ sxt4 r32=r32
+ sxt4 r33=r33;;
+} { .mmb
+ setf.sig f6=r32
+ setf.sig f7=r33
+ nop.b 0;;
+} { .mfi
+ nop.m 0
+ fcvt.xf f6=f6
+ nop.i 0
+} { .mfi
+ nop.m 0
+ fcvt.xf f7=f7
+ mov r2 = 0x0ffdd;;
+} { .mfi
+ setf.exp f9 = r2
+ // (1) y0
+ frcpa.s1 f8,p6=f6,f7
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (2) q0 = a * y0
+ (p6) fma.s1 f6=f6,f8,f0
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // (3) e0 = 1 - b * y0
+ (p6) fnma.s1 f7=f7,f8,f1
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (4) q1 = q0 + e0 * q0
+ (p6) fma.s1 f6=f7,f6,f6
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // (5) e1 = e0 * e0 + 2^-34
+ (p6) fma.s1 f7=f7,f7,f9
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (6) q2 = q1 + e1 * q1
+ (p6) fma.s1 f8=f7,f6,f6
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (7) q = trunc(q2)
+ fcvt.fx.trunc.s1 f8=f8
+ nop.i 0;;
+} { .mmi
+ // quotient will be in the least significant 32 bits of r8 (if b != 0)
+ getf.sig r8=f8
+ nop.m 0
+ nop.i 0;;
+}
+
+ // 32-BIT SIGNED INTEGER DIVIDE ENDS HERE
+
+{ .mmb
+ nop.m 0
+ nop.m 0
+ br.ret.sptk b0;;
+}
+
+.endp __divsi3
diff --git a/lib/libc/ia64/gen/__moddi3.S b/lib/libc/ia64/gen/__moddi3.S
new file mode 100644
index 0000000..e15f964
--- /dev/null
+++ b/lib/libc/ia64/gen/__moddi3.S
@@ -0,0 +1,160 @@
+.file "__moddi3.s"
+
+//
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache,
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab,
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+.section .text
+
+// 64-bit signed integer remainder
+
+.proc __moddi3#
+.align 32
+.global __moddi3#
+.align 32
+
+__moddi3:
+
+{ .mii
+ alloc r31=ar.pfs,3,0,0,0
+ nop.i 0
+ nop.i 0
+} { .mmb
+
+ // 64-BIT SIGNED INTEGER REMAINDER BEGINS HERE
+
+ // general register used:
+ // r32 - 64-bit signed integer dividend
+ // r33 - 64-bit signed integer divisor
+ // r8 - 64-bit signed integer result
+ // r2 - scratch register
+ // floating-point registers used: f6, f7, f8, f9, f10, f11, f12
+ // predicate registers used: p6
+
+ setf.sig f12=r32 // holds an in integer form
+ setf.sig f7=r33
+ nop.b 0
+} { .mlx
+ nop.m 0
+ //movl r2=0x8000000000000000;;
+ movl r2=0xffffffffffffffff;;
+} { .mfi
+ // get the 2's complement of b
+ sub r33=r0,r33
+ fcvt.xf f6=f12
+ nop.i 0
+} { .mfi
+ nop.m 0
+ fcvt.xf f7=f7
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (1)
+ // y0 = 1 / b in f8
+ frcpa.s1 f8,p6=f6,f7
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (2)
+ // q0 = a * y0 in f10
+ (p6) fma.s1 f10=f6,f8,f0
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (3)
+ // e0 = 1 - b * y0 in f9
+ (p6) fnma.s1 f9=f7,f8,f1
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (4)
+ // q1 = q0 + e0 * q0 in f10
+ (p6) fma.s1 f10=f9,f10,f10
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (5)
+ // e1 = e0 * e0 in f11
+ (p6) fma.s1 f11=f9,f9,f0
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (6)
+ // y1 = y0 + e0 * y0 in f8
+ (p6) fma.s1 f8=f9,f8,f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (7)
+ // q2 = q1 + e1 * q1 in f9
+ (p6) fma.s1 f9=f11,f10,f10
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (8)
+ // y2 = y1 + e1 * y1 in f8
+ (p6) fma.s1 f8=f11,f8,f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (9)
+ // r2 = a - b * q2 in f10
+ (p6) fnma.s1 f10=f7,f9,f6
+ nop.i 0;;
+} { .mfi
+ setf.sig f7=r33
+ // Step (10)
+ // q3 = q2 + r2 * y2 in f8
+ (p6) fma.s1 f8=f10,f8,f9
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (11) q = trunc(q3)
+ fcvt.fx.trunc.s1 f8=f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (12) r = a + (-b) * q
+ xma.l f8=f8,f7,f12
+ nop.i 0;;
+} { .mib
+ getf.sig r8=f8
+ nop.i 0
+ nop.b 0
+}
+
+ // 64-BIT SIGNED INTEGER REMAINDER ENDS HERE
+
+{ .mib
+ nop.m 0
+ nop.i 0
+ br.ret.sptk b0;;
+}
+
+.endp __moddi3
diff --git a/lib/libc/ia64/gen/__modsi3.S b/lib/libc/ia64/gen/__modsi3.S
new file mode 100644
index 0000000..1939493
--- /dev/null
+++ b/lib/libc/ia64/gen/__modsi3.S
@@ -0,0 +1,132 @@
+.file "__modsi3.s"
+
+//
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache,
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab,
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+.section .text
+
+// 32-bit signed integer remainder
+
+.proc __modsi3#
+.align 32
+.global __modsi3#
+.align 32
+
+__modsi3:
+
+{ .mii
+ alloc r31=ar.pfs,2,0,0,0
+ nop.i 0
+ nop.i 0;;
+} { .mii
+ nop.m 0
+
+ // 32-BIT SIGNED INTEGER REMAINDER BEGINS HERE
+
+ // general register used:
+ // r32 - 32-bit signed integer dividend
+ // r33 - 32-bit signed integer divisor
+ // r8 - 32-bit signed integer result
+ // r2 - scratch register
+ // floating-point registers used: f6, f7, f8, f9, f10, f11
+ // predicate registers used: p6
+
+ sxt4 r32=r32
+ sxt4 r33=r33;;
+} { .mmb
+ setf.sig f11=r32
+ setf.sig f7=r33
+ nop.b 0;;
+} { .mfi
+ // get 2's complement of b
+ sub r33=r0,r33
+ fcvt.xf f6=f11
+ nop.i 0
+} { .mfi
+ nop.m 0
+ fcvt.xf f7=f7
+ mov r2 = 0x0ffdd;;
+} { .mfi
+ setf.exp f9 = r2
+ // (1) y0
+ frcpa.s1 f8,p6=f6,f7
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (2) q0 = a * y0
+ (p6) fma.s1 f10=f6,f8,f0
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // (3) e0 = 1 - b * y0
+ (p6) fnma.s1 f8=f7,f8,f1
+ nop.i 0;;
+} { .mfi
+ // 2's complement of b
+ setf.sig f7=r33
+ // (4) q1 = q0 + e0 * q0
+ (p6) fma.s1 f10=f8,f10,f10
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // (5) e1 = e0 * e0 + 2^-34
+ (p6) fma.s1 f8=f8,f8,f9
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (6) q2 = q1 + e1 * q1
+ (p6) fma.s1 f8=f8,f10,f10
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (7) q = trunc(q2)
+ fcvt.fx.trunc.s1 f8=f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (8) r = a + (-b) * q
+ xma.l f8=f8,f7,f11
+ nop.i 0;;
+} { .mmi
+ // remainder will be in the least significant 32 bits of r8 (if b != 0)
+ getf.sig r8=f8
+ nop.m 0
+ nop.i 0;;
+}
+
+ // 32-BIT SIGNED INTEGER REMAINDER ENDS HERE
+
+{ .mmb
+ nop.m 0
+ nop.m 0
+ br.ret.sptk b0;;
+}
+
+.endp __modsi3
diff --git a/lib/libc/ia64/gen/__udivdi3.S b/lib/libc/ia64/gen/__udivdi3.S
new file mode 100644
index 0000000..1233e8a
--- /dev/null
+++ b/lib/libc/ia64/gen/__udivdi3.S
@@ -0,0 +1,144 @@
+.file "__udivdi3.s"
+
+//
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache,
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab,
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+.section .text
+.proc __udivdi3#
+.align 32
+.global __udivdi3#
+.align 32
+
+// 64-bit unsigned integer divide
+
+__udivdi3:
+
+{ .mii
+ alloc r31=ar.pfs,2,0,0,0
+ nop.i 0
+ nop.i 0;;
+}
+
+{ .mmi
+
+ // 64-BIT UNSIGNED INTEGER DIVIDE BEGINS HERE
+
+ setf.sig f8=r32
+ setf.sig f9=r33
+ nop.i 0;;
+} { .mfb
+ nop.m 0
+ fma.s1 f6=f8,f1,f0
+ nop.b 0
+} { .mfb
+ nop.m 0
+ fma.s1 f7=f9,f1,f0
+ nop.b 0;;
+} { .mfi
+ nop.m 0
+ // Step (1)
+ // y0 = 1 / b in f8
+ frcpa.s1 f8,p6=f6,f7
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (2)
+ // e0 = 1 - b * y0 in f9
+ (p6) fnma.s1 f9=f7,f8,f1
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (3)
+ // q0 = a * y0 in f10
+ (p6) fma.s1 f10=f6,f8,f0
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (4)
+ // e1 = e0 * e0 in f11
+ (p6) fma.s1 f11=f9,f9,f0
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (5)
+ // q1 = q0 + e0 * q0 in f10
+ (p6) fma.s1 f10=f9,f10,f10
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (6)
+ // y1 = y0 + e0 * y0 in f8
+ (p6) fma.s1 f8=f9,f8,f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (7)
+ // q2 = q1 + e1 * q1 in f9
+ (p6) fma.s1 f9=f11,f10,f10
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (8)
+ // y2 = y1 + e1 * y1 in f8
+ (p6) fma.s1 f8=f11,f8,f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (9)
+ // r2 = a - b * q2 in f10
+ (p6) fnma.s1 f10=f7,f9,f6
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (10)
+ // q3 = q2 + r2 * y2 in f8
+ (p6) fma.s1 f8=f10,f8,f9
+ nop.i 0;;
+} { .mfb
+ nop.m 0
+ // (11) q = trunc(q3)
+ fcvt.fxu.trunc.s1 f8=f8
+ nop.b 0;;
+} { .mmi
+ // quotient will be in r8 (if b != 0)
+ getf.sig r8=f8
+ nop.m 0
+ nop.i 0;;
+}
+
+ // 64-BIT UNSIGNED INTEGER DIVIDE ENDS HERE
+
+{ .mmb
+ nop.m 0
+ nop.m 0
+ br.ret.sptk b0;;
+}
+
+.endp __udivdi3
diff --git a/lib/libc/ia64/gen/__udivsi3.S b/lib/libc/ia64/gen/__udivsi3.S
new file mode 100644
index 0000000..25959b8
--- /dev/null
+++ b/lib/libc/ia64/gen/__udivsi3.S
@@ -0,0 +1,125 @@
+.file "__udivsi3.s"
+
+//
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache,
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab,
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+.section .text
+
+// 32-bit unsigned integer divide
+
+.proc __udivsi3#
+.align 32
+.global __udivsi3#
+.align 32
+
+__udivsi3:
+
+{ .mii
+ alloc r31=ar.pfs,2,0,0,0
+ nop.i 0
+ nop.i 0;;
+} { .mii
+ nop.m 0
+
+ // 32-BIT UNSIGNED INTEGER DIVIDE BEGINS HERE
+
+ // general register used:
+ // r32 - 32-bit unsigned integer dividend
+ // r33 - 32-bit unsigned integer divisor
+ // r8 - 32-bit unsigned integer result
+ // r2 - scratch register
+ // floating-point registers used: f6, f7, f8, f9
+ // predicate registers used: p6
+
+ zxt4 r32=r32
+ zxt4 r33=r33;;
+} { .mmb
+ setf.sig f6=r32
+ setf.sig f7=r33
+ nop.b 0;;
+} { .mfi
+ nop.m 0
+ fcvt.xf f6=f6
+ nop.i 0
+} { .mfi
+ nop.m 0
+ fcvt.xf f7=f7
+ mov r2 = 0x0ffdd;;
+} { .mfi
+ setf.exp f9 = r2
+ // (1) y0
+ frcpa.s1 f8,p6=f6,f7
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (2) q0 = a * y0
+ (p6) fma.s1 f6=f6,f8,f0
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // (3) e0 = 1 - b * y0
+ (p6) fnma.s1 f7=f7,f8,f1
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (4) q1 = q0 + e0 * q0
+ (p6) fma.s1 f6=f7,f6,f6
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // (5) e1 = e0 * e0 + 2^-34
+ (p6) fma.s1 f7=f7,f7,f9
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (6) q2 = q1 + e1 * q1
+ (p6) fma.s1 f8=f7,f6,f6
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (7) q = trunc(q2)
+ fcvt.fxu.trunc.s1 f8=f8
+ nop.i 0;;
+} { .mmi
+ // quotient will be in the least significant 32 bits of r8 (if b != 0)
+ getf.sig r8=f8
+ nop.m 0
+ nop.i 0;;
+}
+
+ // 32-BIT UNSIGNED INTEGER DIVIDE ENDS HERE
+
+{ .mmb
+ nop.m 0
+ nop.m 0
+ br.ret.sptk b0;;
+}
+
+.endp __udivsi3
diff --git a/lib/libc/ia64/gen/__umoddi3.S b/lib/libc/ia64/gen/__umoddi3.S
new file mode 100644
index 0000000..509c62b
--- /dev/null
+++ b/lib/libc/ia64/gen/__umoddi3.S
@@ -0,0 +1,156 @@
+.file "__umoddi3.s"
+
+//
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache,
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab,
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+.section .text
+
+ // 64-bit unsigned integer remainder
+
+.proc __umoddi3#
+.align 32
+.global __umoddi3#
+.align 32
+
+__umoddi3:
+
+{ .mii
+ alloc r31=ar.pfs,3,0,0,0
+ nop.i 0
+ nop.i 0
+} { .mmb
+
+ // 64-BIT UNSIGNED INTEGER REMAINDER BEGINS HERE
+
+ // general register used:
+ // r32 - 64-bit unsigned integer dividend
+ // r33 - 64-bit unsigned integer divisor
+ // r8 - 64-bit unsigned integer result
+ // floating-point registers used: f6, f7, f8, f9, f10, f11, f12
+ // predicate registers used: p6
+
+ setf.sig f12=r32 // holds an in integer form
+ setf.sig f7=r33
+ nop.b 0;;
+} { .mfi
+ // get 2's complement of b
+ sub r33=r0,r33
+ fcvt.xuf.s1 f6=f12
+ nop.i 0
+} { .mfi
+ nop.m 0
+ fcvt.xuf.s1 f7=f7
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (1)
+ // y0 = 1 / b in f8
+ frcpa.s1 f8,p6=f6,f7
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (2)
+ // q0 = a * y0 in f10
+ (p6) fma.s1 f10=f6,f8,f0
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (3)
+ // e0 = 1 - b * y0 in f9
+ (p6) fnma.s1 f9=f7,f8,f1
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (4)
+ // q1 = q0 + e0 * q0 in f10
+ (p6) fma.s1 f10=f9,f10,f10
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // Step (5)
+ // e1 = e0 * e0 in f11
+ (p6) fma.s1 f11=f9,f9,f0
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (6)
+ // y1 = y0 + e0 * y0 in f8
+ (p6) fma.s1 f8=f9,f8,f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (7)
+ // q2 = q1 + e1 * q1 in f9
+ (p6) fma.s1 f9=f11,f10,f10
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (8)
+ // y2 = y1 + e1 * y1 in f8
+ (p6) fma.s1 f8=f11,f8,f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // Step (9)
+ // r2 = a - b * q2 in f10
+ (p6) fnma.s1 f10=f7,f9,f6
+ nop.i 0;;
+} { .mfi
+ // f7=-b
+ setf.sig f7=r33
+ // Step (10)
+ // q3 = q2 + r2 * y2 in f8
+ (p6) fma.s1 f8=f10,f8,f9
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (11) q = trunc(q3)
+ fcvt.fxu.trunc.s1 f8=f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (12) r = a + (-b) * q
+ xma.l f8=f8,f7,f12
+ nop.i 0;;
+} { .mib
+ getf.sig r8=f8
+ nop.i 0
+ nop.b 0
+}
+
+ // 64-BIT UNSIGNED INTEGER REMAINDER ENDS HERE
+
+{ .mib
+ nop.m 0
+ nop.i 0
+ br.ret.sptk b0;;
+}
+
+.endp __umoddi3
diff --git a/lib/libc/ia64/gen/__umodsi3.S b/lib/libc/ia64/gen/__umodsi3.S
new file mode 100644
index 0000000..697db2e
--- /dev/null
+++ b/lib/libc/ia64/gen/__umodsi3.S
@@ -0,0 +1,132 @@
+.file "__umodsi3.s"
+
+//
+// Copyright (c) 2000, Intel Corporation
+// All rights reserved.
+//
+// Contributed 2/15/2000 by Marius Cornea, John Harrison, Cristina Iordache,
+// Ted Kubaska, Bob Norin, and Shane Story of the Computational Software Lab,
+// Intel Corporation.
+//
+// WARRANTY DISCLAIMER
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL INTEL OR ITS
+// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY OR TORT (INCLUDING
+// NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+// SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+//
+// Intel Corporation is the author of this code, and requests that all
+// problem reports or change requests be submitted to it directly at
+// http://developer.intel.com/opensource.
+//
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+.section .text
+
+// 32-bit unsigned integer remainder
+
+.proc __umodsi3#
+.align 32
+.global __umodsi3#
+.align 32
+
+__umodsi3:
+
+{ .mii
+ alloc r31=ar.pfs,2,0,0,0
+ nop.i 0
+ nop.i 0;;
+} { .mii
+ nop.m 0
+
+ // 32-BIT UNSIGNED INTEGER REMAINDER BEGINS HERE
+
+ // general register used:
+ // r32 - 32-bit unsigned integer dividend
+ // r33 - 32-bit unsigned integer divisor
+ // r8 - 32-bit unsigned integer result
+ // r2 - scratch register
+ // floating-point registers used: f6, f7, f8, f9, f10, f11
+ // predicate registers used: p6
+
+ zxt4 r32=r32
+ zxt4 r33=r33;;
+} { .mmb
+ setf.sig f11=r32
+ setf.sig f7=r33
+ nop.b 0;;
+} { .mfi
+ nop.m 0
+ fcvt.xf f6=f11
+ nop.i 0
+} { .mfi
+ // get 2's complement of b
+ sub r33=r0,r33
+ fcvt.xf f7=f7
+ mov r2 = 0x0ffdd;;
+} { .mfi
+ setf.exp f9 = r2
+ // (1) y0
+ frcpa.s1 f8,p6=f6,f7
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (2) q0 = a * y0
+ (p6) fma.s1 f10=f6,f8,f0
+ nop.i 0
+} { .mfi
+ nop.m 0
+ // (3) e0 = 1 - b * y0
+ (p6) fnma.s1 f8=f7,f8,f1
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (4) q1 = q0 + e0 * q0
+ (p6) fma.s1 f10=f8,f10,f10
+ nop.i 0
+} { .mfi
+ // get 2's complement of b
+ setf.sig f7=r33
+ // (5) e1 = e0 * e0 + 2^-34
+ (p6) fma.s1 f8=f8,f8,f9
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (6) q2 = q1 + e1 * q1
+ (p6) fma.s1 f8=f8,f10,f10
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (7) q = trunc(q2)
+ fcvt.fxu.trunc.s1 f8=f8
+ nop.i 0;;
+} { .mfi
+ nop.m 0
+ // (8) r = a + (-b) * q
+ xma.l f8=f8,f7,f11
+ nop.i 0;;
+} { .mmi
+ // remainder will be in the least significant 32 bits of r8 (if b != 0)
+ getf.sig r8=f8
+ nop.m 0
+ nop.i 0;;
+}
+
+ // 32-BIT UNSIGNED INTEGER REMAINDER ENDS HERE
+
+{ .mmb
+ nop.m 0
+ nop.m 0
+ br.ret.sptk b0;;
+}
+
+.endp __umodsi3
diff --git a/lib/libc/ia64/gen/_mcount.S b/lib/libc/ia64/gen/_mcount.S
new file mode 100644
index 0000000..d9e9b76
--- /dev/null
+++ b/lib/libc/ia64/gen/_mcount.S
@@ -0,0 +1,75 @@
+/*
+ * Copyright (c) 2004 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ .text
+
+/*
+ * Important registers:
+ * r8 structure return address
+ * r15 static link (nested routines)
+ * rp our return address
+ * in0 caller's ar.pfs
+ * in1 caller's gp
+ * in2 caller's rp
+ * in3 GOT entry
+ * ar.pfs our pfs
+ */
+ENTRY_NOPROFILE(_mcount, 4)
+ alloc loc0 = ar.pfs, 4, 4, 2, 0
+ mov loc1 = r8
+ mov loc2 = rp
+ mov loc3 = r15
+ ;;
+ mov out0 = in2
+ mov out1 = rp
+ br.call.sptk rp = __mcount
+ ;;
+1:
+ mov gp = in1
+ mov r14 = ip
+ mov b7 = loc2
+ ;;
+ add r14 = 2f - 1b, r14
+ mov ar.pfs = loc0
+ mov rp = in2
+ ;;
+ mov r15 = loc3
+ mov b7 = r14
+ mov b6 = loc2
+ mov r8 = loc1
+ mov r14 = in0
+ br.ret.sptk b7
+ ;;
+2:
+ mov ar.pfs = r14
+ br.sptk b6
+ ;;
+END(_mcount)
+
+WEAK_ALIAS(mcount, _mcount)
diff --git a/lib/libc/ia64/gen/_set_tp.c b/lib/libc/ia64/gen/_set_tp.c
new file mode 100644
index 0000000..901e901
--- /dev/null
+++ b/lib/libc/ia64/gen/_set_tp.c
@@ -0,0 +1,34 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+void
+_set_tp(void *tpval)
+{
+
+ __asm __volatile("mov r13 = %0" :: "r"(tpval));
+}
diff --git a/lib/libc/ia64/gen/_setjmp.S b/lib/libc/ia64/gen/_setjmp.S
new file mode 100644
index 0000000..3966e83
--- /dev/null
+++ b/lib/libc/ia64/gen/_setjmp.S
@@ -0,0 +1,310 @@
+//
+// Copyright (c) 1999, 2000
+// Intel Corporation.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions
+// are met:
+//
+// 1. Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//
+// 2. Redistributions in binary form must reproduce the above copyright
+// notice, this list of conditions and the following disclaimer in the
+// documentation and/or other materials provided with the distribution.
+//
+// 3. All advertising materials mentioning features or use of this software
+// must display the following acknowledgement:
+//
+// This product includes software developed by Intel Corporation and
+// its contributors.
+//
+// 4. Neither the name of Intel Corporation or its contributors may be
+// used to endorse or promote products derived from this software
+// without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY INTEL CORPORATION AND CONTRIBUTORS ``AS IS''
+// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+// ARE DISCLAIMED. IN NO EVENT SHALL INTEL CORPORATION OR CONTRIBUTORS BE
+// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+// THE POSSIBILITY OF SUCH DAMAGE.
+//
+//
+
+//
+// Module Name:
+//
+// setjmp.s
+//
+// Abstract:
+//
+// Contains an implementation of setjmp and longjmp for the
+// IA-64 architecture.
+
+ .file "setjmp.s"
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#define LOCORE
+#include <machine/setjmp.h>
+
+// int _setjmp(struct jmp_buffer *)
+//
+// Setup a non-local goto.
+//
+// Description:
+//
+// SetJump stores the current register set in the area pointed to
+// by "save". It returns zero. Subsequent calls to "LongJump" will
+// restore the registers and return non-zero to the same location.
+//
+// On entry, r32 contains the pointer to the jmp_buffer
+//
+
+ENTRY(_setjmp, 1)
+ add r10 = J_PREDS, r32 // skip Unats & pfs save area
+ add r11 = J_BSP, r32
+ //
+ // save immediate context
+ //
+ mov r2 = ar.bsp // save backing store pointer
+ mov r3 = pr // save predicates
+ flushrs
+ ;;
+ //
+ // save user Unat register
+ //
+ mov r16 = ar.lc // save loop count register
+ mov r14 = ar.unat // save user Unat register
+
+ st8 [r10] = r3, J_LC-J_PREDS
+ st8 [r11] = r2, J_R4-J_BSP
+ ;;
+ st8 [r10] = r16, J_R5-J_LC
+ st8 [r32] = r14, J_NATS // Note: Unat at the
+ // beginning of the save area
+ mov r15 = ar.pfs
+ ;;
+ //
+ // save preserved general registers & NaT's
+ //
+ .mem.offset 0,0
+ st8.spill [r11] = r4, J_R6-J_R4
+ .mem.offset 8,0
+ st8.spill [r10] = r5, J_R7-J_R5
+ ;;
+ .mem.offset 16,0
+ st8.spill [r11] = r6, J_SP-J_R6
+ .mem.offset 24,0
+ st8.spill [r10] = r7, J_F3-J_R7
+ ;;
+ st8.spill [r11] = sp, J_F2-J_SP
+ mov r16 = ar.rsc
+ ;;
+ //
+ // save spilled Unat and pfs registers
+ //
+ mov r2 = ar.unat // save Unat register after spill
+ mov ar.rsc = r0
+ ;;
+ st8 [r32] = r2, J_PFS-J_NATS // save unat for spilled regs
+ mov r17 = ar.rnat
+ ;;
+ st8 [r32] = r15, J_RNAT-J_PFS // save pfs
+ mov ar.rsc = r16
+ //
+ // save floating registers
+ //
+ stf.spill [r11] = f2, J_F4-J_F2
+ stf.spill [r10] = f3, J_F5-J_F3
+ ;;
+ stf.spill [r11] = f4, J_F16-J_F4
+ stf.spill [r10] = f5, J_F17-J_F5
+ ;;
+ stf.spill [r11] = f16, J_F18-J_F16
+ stf.spill [r10] = f17, J_F19-J_F17
+ ;;
+ stf.spill [r11] = f18, J_F20-J_F18
+ stf.spill [r10] = f19, J_F21-J_F19
+ ;;
+ stf.spill [r11] = f20, J_F22-J_F20
+ stf.spill [r10] = f21, J_F23-J_F21
+ ;;
+ stf.spill [r11] = f22, J_F24-J_F22
+ stf.spill [r10] = f23, J_F25-J_F23
+ ;;
+ stf.spill [r11] = f24, J_F26-J_F24
+ stf.spill [r10] = f25, J_F27-J_F25
+ ;;
+ stf.spill [r11] = f26, J_F28-J_F26
+ stf.spill [r10] = f27, J_F29-J_F27
+ ;;
+ stf.spill [r11] = f28, J_F30-J_F28
+ stf.spill [r10] = f29, J_F31-J_F29
+ ;;
+ stf.spill [r11] = f30, J_FPSR-J_F30
+ stf.spill [r10] = f31, J_B0-J_F31 // size of f31 + fpsr
+ ;;
+ st8 [r32] = r17
+ //
+ // save FPSR register & branch registers
+ //
+ mov r2 = ar.fpsr // save fpsr register
+ mov r3 = b0
+ ;;
+ st8 [r11] = r2, J_B1-J_FPSR
+ st8 [r10] = r3, J_B2-J_B0
+ mov r2 = b1
+ mov r3 = b2
+ ;;
+ st8 [r11] = r2, J_B3-J_B1
+ st8 [r10] = r3, J_B4-J_B2
+ mov r2 = b3
+ mov r3 = b4
+ ;;
+ st8 [r11] = r2, J_B5-J_B3
+ st8 [r10] = r3
+ mov r2 = b5
+ ;;
+ st8 [r11] = r2
+ ;;
+ //
+ // return
+ //
+ mov r8 = r0 // return 0 from setjmp
+ mov ar.unat = r14 // restore unat
+ br.ret.sptk b0
+
+END(_setjmp)
+
+
+//
+// void _longjmp(struct jmp_buffer *, int val)
+//
+// Perform a non-local goto.
+//
+// Description:
+//
+// LongJump initializes the register set to the values saved by a
+// previous 'SetJump' and jumps to the return location saved by that
+// 'SetJump'. This has the effect of unwinding the stack and returning
+// for a second time to the 'SetJump'.
+//
+
+ WEAK_ALIAS(_longjmp,___longjmp)
+ENTRY(___longjmp, 2)
+ mov r14 = ar.rsc // get user RSC conf
+ mov r8 = r33 // return value
+ add r10 = J_PFS, r32 // get address of pfs
+ ;;
+ mov ar.rsc = r0
+ add r11 = J_NATS, r32
+ add r17 = J_RNAT, r32
+ ;;
+ ld8 r15 = [r10], J_BSP-J_PFS // get pfs
+ ld8 r2 = [r11], J_LC-J_NATS // get unat for spilled regs
+ mov r31 = r32
+ ;;
+ loadrs
+ mov ar.unat = r2
+ cmp.eq p6,p0=0,r8 // Return value 0?
+ ;;
+ ld8 r16 = [r10], J_PREDS-J_BSP // get backing store pointer
+ ld8 r17 = [r17] // ar.rnat
+ mov ar.pfs = r15
+ ;;
+ mov ar.bspstore = r16
+(p6) add r8 = 1, r0
+ ;;
+ mov ar.rnat = r17
+ mov ar.rsc = r14 // restore RSC conf
+
+ ld8 r3 = [r11], J_R4-J_LC // get lc register
+ ld8 r2 = [r10], J_R5-J_PREDS // get predicates
+ ;;
+ mov pr = r2, -1
+ mov ar.lc = r3
+ //
+ // restore preserved general registers & NaT's
+ //
+ ld8.fill r4 = [r11], J_R6-J_R4
+ ;;
+ ld8.fill r5 = [r10], J_R7-J_R5
+ ld8.fill r6 = [r11], J_SP-J_R6
+ ;;
+ ld8.fill r7 = [r10], J_F2-J_R7
+ ld8.fill sp = [r11], J_F3-J_SP
+ ;;
+ //
+ // restore floating registers
+ //
+ ldf.fill f2 = [r10], J_F4-J_F2
+ ldf.fill f3 = [r11], J_F5-J_F3
+ ;;
+ ldf.fill f4 = [r10], J_F16-J_F4
+ ldf.fill f5 = [r11], J_F17-J_F5
+ ;;
+ ldf.fill f16 = [r10], J_F18-J_F16
+ ldf.fill f17 = [r11], J_F19-J_F17
+ ;;
+ ldf.fill f18 = [r10], J_F20-J_F18
+ ldf.fill f19 = [r11], J_F21-J_F19
+ ;;
+ ldf.fill f20 = [r10], J_F22-J_F20
+ ldf.fill f21 = [r11], J_F23-J_F21
+ ;;
+ ldf.fill f22 = [r10], J_F24-J_F22
+ ldf.fill f23 = [r11], J_F25-J_F23
+ ;;
+ ldf.fill f24 = [r10], J_F26-J_F24
+ ldf.fill f25 = [r11], J_F27-J_F25
+ ;;
+ ldf.fill f26 = [r10], J_F28-J_F26
+ ldf.fill f27 = [r11], J_F29-J_F27
+ ;;
+ ldf.fill f28 = [r10], J_F30-J_F28
+ ldf.fill f29 = [r11], J_F31-J_F29
+ ;;
+ ldf.fill f30 = [r10], J_FPSR-J_F30
+ ldf.fill f31 = [r11], J_B0-J_F31 ;;
+
+ //
+ // restore branch registers and fpsr
+ //
+ ld8 r16 = [r10], J_B1-J_FPSR // get fpsr
+ ld8 r17 = [r11], J_B2-J_B0 // get return pointer
+ ;;
+ mov ar.fpsr = r16
+ mov b0 = r17
+ ld8 r2 = [r10], J_B3-J_B1
+ ld8 r3 = [r11], J_B4-J_B2
+ ;;
+ mov b1 = r2
+ mov b2 = r3
+ ld8 r2 = [r10], J_B5-J_B3
+ ld8 r3 = [r11]
+ ;;
+ mov b3 = r2
+ mov b4 = r3
+ ld8 r2 = [r10]
+ ld8 r21 = [r31] // get user unat
+ ;;
+ mov b5 = r2
+ mov ar.unat = r21
+
+ //
+ // invalidate ALAT
+ //
+ invala ;;
+
+ br.ret.sptk b0
+
+END(___longjmp)
diff --git a/lib/libc/ia64/gen/fabs.S b/lib/libc/ia64/gen/fabs.S
new file mode 100644
index 0000000..036d492
--- /dev/null
+++ b/lib/libc/ia64/gen/fabs.S
@@ -0,0 +1,33 @@
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(fabs, 1)
+ fabs fret0=farg0
+ br.ret.sptk.few rp
+END(fabs)
diff --git a/lib/libc/ia64/gen/flt_rounds.c b/lib/libc/ia64/gen/flt_rounds.c
new file mode 100644
index 0000000..d650965
--- /dev/null
+++ b/lib/libc/ia64/gen/flt_rounds.c
@@ -0,0 +1,25 @@
+/*
+ * Written by J.T. Conklin, Apr 10, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <float.h>
+
+static const int map[] = {
+ 1, /* round to nearest */
+ 3, /* round to zero */
+ 2, /* round to negative infinity */
+ 0 /* round to positive infinity */
+};
+
+int
+__flt_rounds(void)
+{
+ int x;
+
+ __asm("mov %0=ar.fpsr" : "=r" (x));
+ return (map[(x >> 10) & 0x03]);
+}
diff --git a/lib/libc/ia64/gen/fpgetmask.c b/lib/libc/ia64/gen/fpgetmask.c
new file mode 100644
index 0000000..ac166e2
--- /dev/null
+++ b/lib/libc/ia64/gen/fpgetmask.c
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2001 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <ieeefp.h>
+
+fp_except_t
+fpgetmask(void)
+{
+ u_int64_t fpsr;
+
+ __asm __volatile("mov %0=ar.fpsr" : "=r" (fpsr));
+ return (~fpsr & 0x3d);
+}
diff --git a/lib/libc/ia64/gen/fpgetround.c b/lib/libc/ia64/gen/fpgetround.c
new file mode 100644
index 0000000..6f5e8cc
--- /dev/null
+++ b/lib/libc/ia64/gen/fpgetround.c
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <ieeefp.h>
+
+fp_rnd_t
+fpgetround(void)
+{
+ uint64_t fpsr;
+
+ __asm __volatile("mov %0=ar.fpsr" : "=r"(fpsr));
+ return ((fp_rnd_t)((fpsr >> 10) & 3));
+}
diff --git a/lib/libc/ia64/gen/fpsetmask.c b/lib/libc/ia64/gen/fpsetmask.c
new file mode 100644
index 0000000..d959dc6
--- /dev/null
+++ b/lib/libc/ia64/gen/fpsetmask.c
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c) 2001 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <ieeefp.h>
+
+fp_except_t
+fpsetmask(fp_except_t mask)
+{
+ u_int64_t fpsr;
+ u_int64_t oldmask;
+
+ __asm __volatile("mov %0=ar.fpsr" : "=r" (fpsr));
+ oldmask = ~fpsr & 0x3d;
+ fpsr = (fpsr & ~0x3d) | (~mask & 0x3d);
+ __asm __volatile("mov ar.fpsr=%0" :: "r" (fpsr));
+ return (oldmask);
+}
diff --git a/lib/libc/ia64/gen/fpsetround.c b/lib/libc/ia64/gen/fpsetround.c
new file mode 100644
index 0000000..db2eef1
--- /dev/null
+++ b/lib/libc/ia64/gen/fpsetround.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <ieeefp.h>
+
+fp_rnd_t
+fpsetround(fp_rnd_t rnd)
+{
+ uint64_t fpsr;
+ fp_rnd_t prev;
+
+ __asm __volatile("mov %0=ar.fpsr" : "=r"(fpsr));
+ prev = (fp_rnd_t)((fpsr >> 10) & 3);
+ fpsr = (fpsr & ~0xC00ULL) | ((unsigned int)rnd << 10);
+ __asm __volatile("mov ar.fpsr=%0" :: "r"(fpsr));
+ return (prev);
+}
diff --git a/lib/libc/ia64/gen/getcontextx.c b/lib/libc/ia64/gen/getcontextx.c
new file mode 100644
index 0000000..307978a
--- /dev/null
+++ b/lib/libc/ia64/gen/getcontextx.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int
+__getcontextx_size(void)
+{
+
+ return (sizeof(ucontext_t));
+}
+
+int
+__fillcontextx(char *ctx)
+{
+ ucontext_t *ucp;
+
+ ucp = (ucontext_t *)ctx;
+ return (getcontext(ucp));
+}
+
+__weak_reference(__getcontextx, getcontextx);
+
+ucontext_t *
+__getcontextx(void)
+{
+ char *ctx;
+ int error;
+
+ ctx = malloc(__getcontextx_size());
+ if (ctx == NULL)
+ return (NULL);
+ if (__fillcontextx(ctx) == -1) {
+ error = errno;
+ free(ctx);
+ errno = error;
+ return (NULL);
+ }
+ return ((ucontext_t *)ctx);
+}
diff --git a/lib/libc/ia64/gen/infinity.c b/lib/libc/ia64/gen/infinity.c
new file mode 100644
index 0000000..1ae92a8
--- /dev/null
+++ b/lib/libc/ia64/gen/infinity.c
@@ -0,0 +1,48 @@
+/* $NetBSD: infinity.c,v 1.1 1995/02/10 17:50:23 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/endian.h>
+#include <math.h>
+
+/* bytes for +Infinity on an ia64 (IEEE double format) */
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+const union __infinity_un __infinity = { { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f } };
+#else /* _BIG_ENDIAN */
+const union __infinity_un __infinity = { { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } };
+#endif
+
+/* bytes for NaN */
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+const union __nan_un __nan = { { 0, 0, 0xc0, 0xff } };
+#else /* _BIG_ENDIAN */
+const union __nan_un __nan = { { 0xff, 0xc0, 0, 0 } };
+#endif
diff --git a/lib/libc/ia64/gen/makecontext.c b/lib/libc/ia64/gen/makecontext.c
new file mode 100644
index 0000000..bee47f1
--- /dev/null
+++ b/lib/libc/ia64/gen/makecontext.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <machine/fpu.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+struct fdesc {
+ uint64_t ip;
+ uint64_t gp;
+};
+
+typedef void (*func_t)(uint64_t, uint64_t, uint64_t, uint64_t, uint64_t,
+ uint64_t, uint64_t, uint64_t);
+
+static __inline uint64_t *
+spill(uint64_t *bsp, uint64_t arg)
+{
+ *bsp++ = arg;
+ if (((intptr_t)bsp & 0x1ff) == 0x1f8)
+ *bsp++ = 0;
+ return (bsp);
+}
+
+static void
+ctx_wrapper(ucontext_t *ucp, func_t func, uint64_t *args)
+{
+
+ (*func)(args[0], args[1], args[2], args[3], args[4], args[5], args[6],
+ args[7]);
+ if (ucp->uc_link == NULL)
+ exit(0);
+ setcontext((const ucontext_t *)ucp->uc_link);
+ /* should never get here */
+ abort();
+ /* NOTREACHED */
+}
+
+__weak_reference(__makecontext, makecontext);
+
+void
+__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
+{
+ uint64_t *args, *bsp;
+ va_list ap;
+ int i;
+
+ /*
+ * Drop the ball completely if something's not right. We only
+ * support general registers as arguments and not more than 8
+ * of them. Things get hairy if we need to support FP registers
+ * (alignment issues) or more than 8 arguments (stack based).
+ */
+ if (argc < 0 || argc > 8 || ucp == NULL ||
+ ucp->uc_stack.ss_sp == NULL || (ucp->uc_stack.ss_size & 15) ||
+ ((intptr_t)ucp->uc_stack.ss_sp & 15) ||
+ ucp->uc_stack.ss_size < MINSIGSTKSZ)
+ abort();
+
+ /*
+ * Copy the arguments of function 'func' onto the (memory) stack.
+ * Always take up space for 8 arguments.
+ */
+ va_start(ap, argc);
+ args = (uint64_t*)(ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size) - 8;
+ i = 0;
+ while (i < argc)
+ args[i++] = va_arg(ap, uint64_t);
+ while (i < 8)
+ args[i++] = 0;
+ va_end(ap);
+
+ /*
+ * Push (spill) the arguments of the context wrapper onto the register
+ * stack. They get loaded by the RSE on a context switch.
+ */
+ bsp = (uint64_t*)ucp->uc_stack.ss_sp;
+ bsp = spill(bsp, (intptr_t)ucp);
+ bsp = spill(bsp, (intptr_t)func);
+ bsp = spill(bsp, (intptr_t)args);
+
+ /*
+ * Setup the MD portion of the context.
+ */
+ memset(&ucp->uc_mcontext, 0, sizeof(ucp->uc_mcontext));
+ ucp->uc_mcontext.mc_special.sp = (intptr_t)args - 16;
+ ucp->uc_mcontext.mc_special.bspstore = (intptr_t)bsp;
+ ucp->uc_mcontext.mc_special.pfs = (3 << 7) | 3;
+ ucp->uc_mcontext.mc_special.rsc = 0xf;
+ ucp->uc_mcontext.mc_special.rp = ((struct fdesc*)ctx_wrapper)->ip;
+ ucp->uc_mcontext.mc_special.gp = ((struct fdesc*)ctx_wrapper)->gp;
+ ucp->uc_mcontext.mc_special.fpsr = IA64_FPSR_DEFAULT;
+}
diff --git a/lib/libc/ia64/gen/setjmp.S b/lib/libc/ia64/gen/setjmp.S
new file mode 100644
index 0000000..a2b56d6
--- /dev/null
+++ b/lib/libc/ia64/gen/setjmp.S
@@ -0,0 +1,82 @@
+/* $NetBSD: setjmp.S,v 1.3 1997/12/05 02:06:27 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#define LOCORE
+#include <machine/setjmp.h>
+
+/*
+ * C library -- setjmp, longjmp
+ *
+ * longjmp(a,v)
+ * will generate a "return(v)" from
+ * the last call to
+ * setjmp(a)
+ * by restoring registers from the stack,
+ * and the previous signal state.
+ */
+
+ENTRY(setjmp, 1)
+ alloc loc0=ar.pfs,1,2,3,0
+ mov loc1=rp
+ ;;
+ mov out0=1 // how = SIG_BLOCK
+ mov out1=0 // set = NULL
+ add out2=J_SIGSET,in0 // oset = &jb[J_SIGSET]
+ br.call.sptk.few rp=__sys_sigprocmask
+ ;;
+ mov rp=loc1
+ mov r14=loc0
+ ;;
+ alloc r15=ar.pfs,1,0,0,0 // drop register frame
+ ;;
+ mov ar.pfs=r14 // restore ar.pfs
+ br.sptk.many _setjmp // finish saving state
+END(setjmp)
+
+ WEAK_ALIAS(longjmp,__longjmp)
+ENTRY(__longjmp, 2)
+ alloc loc0=ar.pfs,2,2,3,0
+ mov loc1=rp
+ ;;
+ mov out0=3 // how = SIG_SETMASK
+ add out1=J_SIGSET,in0 // set = &jb[J_SIGSET]
+ mov out2=0 // oset = NULL
+ br.call.sptk.few rp=__sys_sigprocmask
+ ;;
+ mov rp=loc1
+ mov r14=loc0
+ ;;
+ alloc r15=ar.pfs,2,0,0,0 // drop register frame
+ ;;
+ mov ar.pfs=r14 // restore ar.pfs
+ br.sptk.many _longjmp // finish restoring state
+END(__longjmp)
diff --git a/lib/libc/ia64/gen/signalcontext.c b/lib/libc/ia64/gen/signalcontext.c
new file mode 100644
index 0000000..b47daf3
--- /dev/null
+++ b/lib/libc/ia64/gen/signalcontext.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <machine/fpu.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <strings.h>
+
+struct fdesc {
+ uint64_t ip;
+ uint64_t gp;
+};
+
+typedef void (*handler_t)(uint64_t, uint64_t, uint64_t);
+
+static __inline uint64_t *
+spill(uint64_t *bsp, uint64_t arg)
+{
+ *bsp++ = arg;
+ if (((intptr_t)bsp & 0x1ff) == 0x1f8)
+ *bsp++ = 0;
+ return (bsp);
+}
+
+static void
+ctx_wrapper(ucontext_t *ucp, handler_t func, uint64_t *args)
+{
+
+ (*func)(args[0], args[1], args[2]);
+ if (ucp->uc_link == NULL)
+ exit(0);
+ setcontext((const ucontext_t *)ucp->uc_link);
+ /* should never get here */
+ abort();
+ /* NOTREACHED */
+}
+
+__weak_reference(__signalcontext, signalcontext);
+
+int
+__signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func)
+{
+ uint64_t *args, *bsp;
+ siginfo_t *sig_si;
+ ucontext_t *sig_uc;
+ uint64_t sp;
+
+ /* Bail out if we don't have a valid ucontext pointer. */
+ if (ucp == NULL)
+ abort();
+
+ /*
+ * Build a signal frame and copy the arguments of signal handler
+ * 'func' onto the (memory) stack. We only need 3 arguments, but
+ * we create room for 4 so that we are 16-byte aligned.
+ */
+ sp = (ucp->uc_mcontext.mc_special.sp - sizeof(ucontext_t)) & ~15UL;
+ sig_uc = (ucontext_t*)sp;
+ bcopy(ucp, sig_uc, sizeof(*sig_uc));
+ sp = (sp - sizeof(siginfo_t)) & ~15UL;
+ sig_si = (siginfo_t*)sp;
+ bzero(sig_si, sizeof(*sig_si));
+ sig_si->si_signo = sig;
+ sp -= 4 * sizeof(uint64_t);
+ args = (uint64_t*)sp;
+ args[0] = sig;
+ args[1] = (intptr_t)sig_si;
+ args[2] = (intptr_t)sig_uc;
+
+ /*
+ * Push (spill) the arguments of the context wrapper onto the register
+ * stack. They get loaded by the RSE on a context switch.
+ */
+ bsp = (uint64_t*)ucp->uc_mcontext.mc_special.bspstore;
+ bsp = spill(bsp, (intptr_t)ucp);
+ bsp = spill(bsp, (intptr_t)func);
+ bsp = spill(bsp, (intptr_t)args);
+
+ /*
+ * Setup the ucontext of the signal handler.
+ */
+ memset(&ucp->uc_mcontext, 0, sizeof(ucp->uc_mcontext));
+ ucp->uc_link = sig_uc;
+ sigdelset(&ucp->uc_sigmask, sig);
+ ucp->uc_mcontext.mc_special.sp = (intptr_t)args - 16;
+ ucp->uc_mcontext.mc_special.bspstore = (intptr_t)bsp;
+ ucp->uc_mcontext.mc_special.pfs = (3 << 7) | 3;
+ ucp->uc_mcontext.mc_special.rsc = 0xf;
+ ucp->uc_mcontext.mc_special.rp = ((struct fdesc*)ctx_wrapper)->ip;
+ ucp->uc_mcontext.mc_special.gp = ((struct fdesc*)ctx_wrapper)->gp;
+ ucp->uc_mcontext.mc_special.fpsr = IA64_FPSR_DEFAULT;
+ return (0);
+}
diff --git a/lib/libc/ia64/gen/sigsetjmp.S b/lib/libc/ia64/gen/sigsetjmp.S
new file mode 100644
index 0000000..9f02a26
--- /dev/null
+++ b/lib/libc/ia64/gen/sigsetjmp.S
@@ -0,0 +1,66 @@
+/* $NetBSD: sigsetjmp.S,v 1.2 1996/10/17 03:08:07 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#define LOCORE
+#include <machine/setjmp.h>
+
+/*
+ * C library -- sigsetjmp, siglongjmp
+ *
+ * siglongjmp(a,v)
+ * will generate a "return(v)" from
+ * the last call to
+ * sigsetjmp(a, mask)
+ * by restoring registers from the stack.
+ * If `mask' is non-zero, the previous signal
+ * state will be restored.
+ */
+
+ENTRY(sigsetjmp, 2)
+ add r14=J_SIGMASK,in0 // place to save mask
+ cmp.ne p6,p7=0,in1 // save signal state?
+ ;;
+ st8 [r14]=in1 // save mask value
+(p6) br.cond.dptk.many setjmp
+(p7) br.cond.dpnt.many _setjmp
+END(sigsetjmp)
+
+ WEAK_ALIAS(siglongjmp,__siglongjmp)
+ENTRY(__siglongjmp, 2)
+ add r14=J_SIGMASK,in0 // address of mask value
+ ;;
+ ld8 r14=[r14]
+ ;;
+ cmp.ne p6,p7=0,r14 // did we save signals?
+(p6) br.cond.dptk.many longjmp
+(p7) br.cond.dpnt.many _longjmp
+END(__siglongjmp)
diff --git a/lib/libc/ia64/gen/unwind.c b/lib/libc/ia64/gen/unwind.c
new file mode 100644
index 0000000..7afd0ef
--- /dev/null
+++ b/lib/libc/ia64/gen/unwind.c
@@ -0,0 +1,129 @@
+/*
+ * Copyright (c) 2002 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+
+#include <assert.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+
+#include <machine/elf.h>
+
+#ifndef PT_IA_64_UNWIND
+#define PT_IA_64_UNWIND 0x70000001
+#endif
+
+#define SANITY 0
+
+struct ia64_unwind_entry
+{
+ Elf64_Addr start;
+ Elf64_Addr end;
+ Elf64_Addr descr;
+};
+
+struct ia64_unwind_entry *
+_Unwind_FindTableEntry(const void *pc, unsigned long *pseg, unsigned long *pgp)
+{
+ Dl_info info;
+ Elf_Dyn *dyn;
+ Elf_Ehdr *ehdr;
+ Elf_Phdr *phdr;
+ char *p, *p_top;
+ struct ia64_unwind_entry *unw, *res;
+ register unsigned long gp __asm__("gp"); /* XXX assumes gcc */
+ unsigned long reloc, vaddr;
+ size_t l, m, r;
+
+ if (!dladdr(pc, &info))
+ return NULL;
+
+ ehdr = (Elf_Ehdr*)info.dli_fbase;
+
+#if SANITY
+ assert(IS_ELF(*ehdr));
+ assert(ehdr->e_ident[EI_CLASS] == ELFCLASS64);
+ assert(ehdr->e_ident[EI_DATA] == ELFDATA2LSB);
+ assert(ehdr->e_machine == EM_IA_64);
+#endif
+
+ reloc = (ehdr->e_type == ET_DYN) ? (uintptr_t)info.dli_fbase : 0;
+ *pgp = gp;
+ *pseg = 0UL;
+ res = NULL;
+
+ p = (char*)info.dli_fbase + ehdr->e_phoff;
+ p_top = p + ehdr->e_phnum * ehdr->e_phentsize;
+ while (p < p_top) {
+ phdr = (Elf_Phdr*)p;
+ vaddr = phdr->p_vaddr + reloc;
+
+ switch (phdr->p_type) {
+ case PT_DYNAMIC:
+ dyn = (Elf_Dyn*)vaddr;
+ while (dyn->d_tag != DT_NULL) {
+ if (dyn->d_tag == DT_PLTGOT) {
+ *pgp = dyn->d_un.d_ptr + reloc;
+ break;
+ }
+ dyn++;
+ }
+ break;
+ case PT_LOAD:
+ if (pc >= (void*)vaddr &&
+ pc < (void*)(vaddr + phdr->p_memsz))
+ *pseg = vaddr;
+ break;
+ case PT_IA_64_UNWIND:
+#if SANITY
+ assert(*pseg != 0UL);
+ assert(res == NULL);
+#endif
+ unw = (struct ia64_unwind_entry*)vaddr;
+ l = 0;
+ r = phdr->p_memsz / sizeof(struct ia64_unwind_entry);
+ while (l < r) {
+ m = (l + r) >> 1;
+ res = unw + m;
+ if (pc < (void*)(res->start + *pseg))
+ r = m;
+ else if (pc >= (void*)(res->end + *pseg))
+ l = m + 1;
+ else
+ break; /* found */
+ }
+ if (l >= r)
+ res = NULL;
+ break;
+ }
+
+ p += ehdr->e_phentsize;
+ }
+
+ return res;
+}
diff --git a/lib/libc/ia64/string/Makefile.inc b/lib/libc/ia64/string/Makefile.inc
new file mode 100644
index 0000000..7bbcc8d
--- /dev/null
+++ b/lib/libc/ia64/string/Makefile.inc
@@ -0,0 +1,3 @@
+# $FreeBSD$
+
+MDSRCS+= bcopy.S bzero.S ffs.S memcpy.S memmove.S
diff --git a/lib/libc/ia64/string/bcopy.S b/lib/libc/ia64/string/bcopy.S
new file mode 100644
index 0000000..34aac19
--- /dev/null
+++ b/lib/libc/ia64/string/bcopy.S
@@ -0,0 +1,95 @@
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Not the fastest bcopy in the world.
+ */
+ENTRY(bcopy, 3)
+
+ cmp.le p6,p0=in2,r0 // bail if len <= 0
+(p6) br.ret.spnt.few rp
+
+ sub r14=in1,in0 ;; // check for overlap
+ cmp.ltu p6,p0=r14,in2 // dst-src < len
+(p6) br.cond.spnt.few 5f
+
+ extr.u r14=in0,0,3 // src & 7
+ extr.u r15=in1,0,3 ;; // dst & 7
+ cmp.eq p6,p0=r14,r15 // different alignment?
+(p6) br.cond.spnt.few 2f // branch if same alignment
+
+1: ld1 r14=[in0],1 ;; // copy bytewise
+ st1 [in1]=r14,1
+ add in2=-1,in2 ;; // len--
+ cmp.ne p6,p0=r0,in2
+(p6) br.cond.dptk.few 1b // loop
+ br.ret.sptk.few rp // done
+
+2: cmp.eq p6,p0=r14,r0 // aligned?
+(p6) br.cond.sptk.few 4f
+
+3: ld1 r14=[in0],1 ;; // copy bytewise
+ st1 [in1]=r14,1
+ extr.u r15=in0,0,3 // src & 7
+ add in2=-1,in2 ;; // len--
+ cmp.eq p6,p0=r0,in2 // done?
+ cmp.eq p7,p0=r0,r15 ;; // aligned now?
+(p6) br.ret.spnt.few rp // return if done
+(p7) br.cond.spnt.few 4f // go to main copy
+ br.cond.sptk.few 3b // more bytes to copy
+
+ // At this point, in2 is non-zero
+
+4: mov r14=8 ;;
+ cmp.ltu p6,p0=in2,r14 ;; // len < 8?
+(p6) br.cond.spnt.few 1b // byte copy the end
+ ld8 r15=[in0],8 ;; // copy word
+ st8 [in1]=r15,8
+ add in2=-8,in2 ;; // len -= 8
+ cmp.ne p6,p0=r0,in2 // done?
+(p6) br.cond.spnt.few 4b // again
+
+ br.ret.sptk.few rp // return
+
+ // Don't bother optimising overlap case
+
+5: add in0=in0,in2
+ add in1=in1,in2 ;;
+ add in0=-1,in0
+ add in1=-1,in1 ;;
+
+6: ld1 r14=[in0],-1 ;;
+ st1 [in1]=r14,-1
+ add in2=-1,in2 ;;
+ cmp.ne p6,p0=r0,in2
+(p6) br.cond.spnt.few 6b
+
+ br.ret.sptk.few rp
+
+END(bcopy)
diff --git a/lib/libc/ia64/string/bzero.S b/lib/libc/ia64/string/bzero.S
new file mode 100644
index 0000000..0963c36
--- /dev/null
+++ b/lib/libc/ia64/string/bzero.S
@@ -0,0 +1,81 @@
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(bzero, 2)
+
+ cmp.le p6,p0=in1,r0 // bail if len <= 0
+(p6) br.ret.spnt.few rp
+ ;;
+ mov r14=ar.lc // save ar.lc
+
+ cmp.ltu p6,p0=17,in1 // check for small
+(p6) br.dptk.few 3f
+
+1: add r15=-1,in1 ;;
+ mov ar.lc=r15 ;;
+2: st1 [in0]=r0,1 // zero one byte
+ br.cloop.sptk.few 2b // loop
+
+ ;;
+ mov ar.lc=r14 // done
+ br.ret.sptk.few rp
+
+ // Zero up to 8byte alignment
+
+3: tbit.nz p6,p0=in0,0 ;;
+(p6) st1 [in0]=r0,1
+(p6) add in1=-1,in1 ;;
+
+ tbit.nz p6,p0=in0,1 ;;
+(p6) st2 [in0]=r0,2
+(p6) add in1=-2,in1 ;;
+
+ tbit.nz p6,p0=in0,2 ;;
+(p6) st4 [in0]=r0,4
+(p6) add in1=-4,in1
+
+ ;;
+ shr.u r15=in1,3 // word count
+ extr.u in1=in1,0,3 ;; // trailing bytes
+ cmp.eq p6,p0=r15,r0 // check for zero
+ cmp.ne p7,p0=in1,r0
+(p6) br.dpnt.few 1b // zero last bytes
+
+ add r15=-1,r15 ;;
+ mov ar.lc=r15 ;;
+4: st8 [in0]=r0,8
+ br.cloop.sptk.few 4b
+
+(p7) br.dpnt.few 1b // zero last bytes
+
+ ;;
+ mov ar.lc=r14 // done
+ br.ret.sptk.few rp
+
+END(bzero)
diff --git a/lib/libc/ia64/string/ffs.S b/lib/libc/ia64/string/ffs.S
new file mode 100644
index 0000000..d99d765
--- /dev/null
+++ b/lib/libc/ia64/string/ffs.S
@@ -0,0 +1,99 @@
+/* $NetBSD: ffs.S,v 1.3 1996/10/17 03:08:13 cgd Exp $ */
+
+/*
+ * Copyright (c) 1995 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Christopher G. Demetriou
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(ffs, 1)
+ sxt4 r14=in0 ;;
+ cmp.eq p6,p0=r14,r0
+(p6) br.dpnt.few Lallzero
+
+ /*
+ * Initialize return value (ret0), and set up r15 so that it
+ * contains the mask with only the lowest bit set.
+ */
+ sub r15=r0,r14
+ mov ret0=1 ;;
+ and r15=r14,r15 ;;
+
+ extr.u r16=r15,0,8 ;;
+ cmp.ne p6,p0=r0,r16
+(p6) br.dptk.few Ldo8
+
+ /*
+ * If lower 16 bits empty, add 16 to result and use upper 16.
+ */
+ extr.u r16=r15,0,16 ;;
+ cmp.ne p6,p0=r0,r16
+(p6) br.dptk.few Ldo16
+ extr.u r15=r15,16,16
+ add ret0=16,ret0 ;;
+
+Ldo16:
+ /*
+ * If lower 8 bits empty, add 8 to result and use upper 8.
+ */
+ extr.u r16=r15,0,8 ;;
+ cmp.ne p6,p0=r0,r16
+(p6) br.dptk.few Ldo8
+ extr.u r15=r15,8,24
+ add ret0=8,ret0 ;;
+
+Ldo8:
+ and r16=0x0f,r15 /* lower 4 of 8 empty? */
+ and r17=0x33,r15 /* lower 2 of each 4 empty? */
+ and r18=0x55,r15 ;; /* lower 1 of each 2 empty? */
+ cmp.ne p6,p0=r16,r0
+ cmp.ne p7,p0=r17,r0
+ cmp.ne p8,p0=r18,r0
+
+ /* If lower 4 bits empty, add 4 to result. */
+(p6) br.dptk.few Ldo4
+ add ret0=4,ret0 ;;
+
+Ldo4: /* If lower 2 bits of each 4 empty, add 2 to result. */
+(p7) br.dptk.few Ldo2
+ add ret0=2,ret0 ;;
+
+Ldo2: /* If lower bit of each 2 empty, add 1 to result. */
+(p8) br.dptk.few Ldone
+ add ret0=1,ret0
+
+Ldone:
+ br.ret.sptk.few rp
+
+Lallzero:
+ mov ret0=0
+ br.ret.sptk.few rp
+END(ffs)
diff --git a/lib/libc/ia64/string/memcpy.S b/lib/libc/ia64/string/memcpy.S
new file mode 100644
index 0000000..d7557c1
--- /dev/null
+++ b/lib/libc/ia64/string/memcpy.S
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(memcpy,3)
+ mov r8 = in0
+ mov in0 = in1
+ ;;
+ mov in1 = r8
+ br.sptk.few bcopy
+END(memcpy)
diff --git a/lib/libc/ia64/string/memmove.S b/lib/libc/ia64/string/memmove.S
new file mode 100644
index 0000000..19fa8af
--- /dev/null
+++ b/lib/libc/ia64/string/memmove.S
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(memmove,3)
+ mov r8 = in0
+ mov in0 = in1
+ ;;
+ mov in1 = r8
+ br.sptk.few bcopy
+END(memmove)
diff --git a/lib/libc/ia64/sys/Makefile.inc b/lib/libc/ia64/sys/Makefile.inc
new file mode 100644
index 0000000..3876d3a
--- /dev/null
+++ b/lib/libc/ia64/sys/Makefile.inc
@@ -0,0 +1,12 @@
+# $FreeBSD$
+
+MDASM+= Ovfork.S brk.S cerror.S exect.S fork.S getcontext.S pipe.S ptrace.S \
+ sbrk.S setlogin.S sigreturn.S swapcontext.S
+
+# Don't generate default code for these syscalls:
+NOASM= break.o exit.o getlogin.o openbsd_poll.o sstk.o vfork.o yield.o
+
+PSEUDO= _getlogin.o _exit.o
+.if !defined(WITHOUT_SYSCALL_COMPAT)
+PSEUDO+= _pread.o _pwrite.o _lseek.o _mmap.o _ftruncate.o _truncate.o
+.endif
diff --git a/lib/libc/ia64/sys/Ovfork.S b/lib/libc/ia64/sys/Ovfork.S
new file mode 100644
index 0000000..6eb6958
--- /dev/null
+++ b/lib/libc/ia64/sys/Ovfork.S
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+SYSCALL(vfork)
+ cmp.ne p7,p0=ret1,r0 /* ret1!=0 for child */
+ ;;
+(p7) mov ret0=r0
+ br.ret.sptk.few rp
+END(__sys_vfork)
diff --git a/lib/libc/ia64/sys/brk.S b/lib/libc/ia64/sys/brk.S
new file mode 100644
index 0000000..fee1728
--- /dev/null
+++ b/lib/libc/ia64/sys/brk.S
@@ -0,0 +1,57 @@
+/* $NetBSD: brk.S,v 1.4 1996/10/17 03:08:15 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl _end
+IMPORT(curbrk, 8)
+
+ .data
+EXPORT(minbrk)
+ .quad _end
+
+ .text
+ENTRY(brk, 1)
+ add r14=@ltoff(minbrk),gp ;;
+ ld8 r14=[r14] ;;
+ ld8 r14=[r14] ;;
+ cmp.ltu p6,p0=r32,r14 ;;
+(p6) mov r32=r14 ;;
+ st8 [sp]=r32
+ CALLSYS_ERROR(break)
+ ld8 r15=[sp]
+ add r14=@ltoff(curbrk),gp ;;
+ ld8 r14=[r14] ;;
+ st8 [r14]=r15
+ mov ret0=0
+ br.ret.sptk.few rp
+END(brk)
diff --git a/lib/libc/ia64/sys/cerror.S b/lib/libc/ia64/sys/cerror.S
new file mode 100644
index 0000000..ca0b0c7
--- /dev/null
+++ b/lib/libc/ia64/sys/cerror.S
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+
+ENTRY(.cerror, 0)
+ alloc loc0=ar.pfs,0,3,1,0
+ ;;
+ mov loc1=rp
+ mov loc2=ret0
+ mov out0=ret0
+ ;;
+ br.call.sptk.few rp=__error
+ st4 [ret0]=loc2
+ ;;
+ mov ret0=-1
+ mov ar.pfs=loc0
+ mov rp=loc1
+ ;;
+ br.ret.sptk.few rp
+END(.cerror)
diff --git a/lib/libc/ia64/sys/exect.S b/lib/libc/ia64/sys/exect.S
new file mode 100644
index 0000000..817d3b1
--- /dev/null
+++ b/lib/libc/ia64/sys/exect.S
@@ -0,0 +1,38 @@
+/* $NetBSD: exect.S,v 1.2 1996/10/17 03:08:18 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ENTRY(exect, 3)
+ CALLSYS_ERROR(execve)
+ br.ret.sptk.few rp
+END(exect)
diff --git a/lib/libc/ia64/sys/fork.S b/lib/libc/ia64/sys/fork.S
new file mode 100644
index 0000000..5b09f77
--- /dev/null
+++ b/lib/libc/ia64/sys/fork.S
@@ -0,0 +1,37 @@
+/*-
+ * Copyright (c) 2000 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+SYSCALL(fork)
+ cmp.ne p7,p0=ret1,r0 /* ret1!=0 for child */
+ ;;
+(p7) mov ret0=r0
+ br.ret.sptk.few rp
+END(__sys_fork)
diff --git a/lib/libc/ia64/sys/getcontext.S b/lib/libc/ia64/sys/getcontext.S
new file mode 100644
index 0000000..0ec6f92
--- /dev/null
+++ b/lib/libc/ia64/sys/getcontext.S
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ENTRY(__sys_getcontext,2)
+ WEAK_ALIAS(getcontext, __sys_getcontext)
+ WEAK_ALIAS(_getcontext, __sys_getcontext)
+ flushrs
+ ;;
+ CALLSYS_ERROR(getcontext)
+ br.ret.sptk.few rp
+END(__sys_getcontext)
diff --git a/lib/libc/ia64/sys/pipe.S b/lib/libc/ia64/sys/pipe.S
new file mode 100644
index 0000000..a6413df
--- /dev/null
+++ b/lib/libc/ia64/sys/pipe.S
@@ -0,0 +1,47 @@
+/* $NetBSD: pipe.S,v 1.1 1995/02/10 17:50:35 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ENTRY(__sys_pipe, 1)
+ WEAK_ALIAS(pipe, __sys_pipe)
+ WEAK_ALIAS(_pipe, __sys_pipe)
+ st8 [sp]=r32
+ CALLSYS_ERROR(pipe)
+ ld8 r14=[sp]
+ ;;
+ st4 [r14]=ret0,4
+ ;;
+ st4 [r14]=ret1
+ mov ret0=0
+ br.ret.sptk.few rp
+END(__sys_pipe)
diff --git a/lib/libc/ia64/sys/ptrace.S b/lib/libc/ia64/sys/ptrace.S
new file mode 100644
index 0000000..b6d3abd
--- /dev/null
+++ b/lib/libc/ia64/sys/ptrace.S
@@ -0,0 +1,41 @@
+/* $NetBSD: ptrace.S,v 1.4 1996/11/08 00:51:24 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ENTRY(ptrace, 4)
+ add r14=@ltoff(errno),gp ;;
+ ld8 r14=[r14] ;;
+ st4 [r14]=r0
+ CALLSYS_ERROR(ptrace)
+ br.ret.sptk.few rp
+END(ptrace)
diff --git a/lib/libc/ia64/sys/sbrk.S b/lib/libc/ia64/sys/sbrk.S
new file mode 100644
index 0000000..98b5ce9
--- /dev/null
+++ b/lib/libc/ia64/sys/sbrk.S
@@ -0,0 +1,63 @@
+/* $NetBSD: sbrk.S,v 1.4 1996/10/17 03:08:20 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl _end
+
+ .data
+EXPORT(curbrk)
+ .quad _end
+
+ .text
+ENTRY(sbrk, 1)
+ add r14 = @ltoff(curbrk), gp
+ ;;
+ ld8 r14 = [r14]
+ cmp.eq p6, p0 = r32, r0
+ ;;
+ ld8 ret0 = [r14]
+(p6) br.ret.sptk.few rp
+ ;;
+ add r32 = ret0, r32
+ ;;
+ st8 [sp] = r32
+ CALLSYS_ERROR(break)
+ ld8 r15 = [sp]
+ add r14 = @ltoff(curbrk), gp
+ ;;
+ ld8 r14 = [r14]
+ ;;
+ ld8 ret0 = [r14]
+ st8 [r14] = r15
+ br.ret.sptk.few rp
+END(sbrk)
diff --git a/lib/libc/ia64/sys/setlogin.S b/lib/libc/ia64/sys/setlogin.S
new file mode 100644
index 0000000..1d29a40
--- /dev/null
+++ b/lib/libc/ia64/sys/setlogin.S
@@ -0,0 +1,42 @@
+/* $NetBSD: setlogin.S,v 1.1 1995/02/10 17:50:39 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+IMPORT(_logname_valid, 4) /* in getlogin() */
+
+SYSCALL(setlogin)
+ add r14=@ltoff(_logname_valid),gp ;;
+ ld8 r14=[r14] ;;
+ st4 [r14]=r0 /* clear it */
+ br.ret.sptk.few rp
+END(__sys_setlogin)
diff --git a/lib/libc/ia64/sys/sigreturn.S b/lib/libc/ia64/sys/sigreturn.S
new file mode 100644
index 0000000..2c7a710
--- /dev/null
+++ b/lib/libc/ia64/sys/sigreturn.S
@@ -0,0 +1,41 @@
+/* $NetBSD: sigreturn.S,v 1.1 1995/02/10 17:50:42 cgd Exp $ */
+
+/*
+ * Copyright (c) 1994, 1995 Carnegie-Mellon University.
+ * All rights reserved.
+ *
+ * Author: Chris G. Demetriou
+ *
+ * Permission to use, copy, modify and distribute this software and
+ * its documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND
+ * FOR ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie the
+ * rights to redistribute these changes.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+/*
+ * We must preserve the state of the registers as the user has set them up.
+ * However, that doesn't involve any special work on the ia64.
+ * (XXX PROFILING)
+ */
+
+RSYSCALL(sigreturn)
diff --git a/lib/libc/ia64/sys/swapcontext.S b/lib/libc/ia64/sys/swapcontext.S
new file mode 100644
index 0000000..210189f
--- /dev/null
+++ b/lib/libc/ia64/sys/swapcontext.S
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2003 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ENTRY(__sys_swapcontext,2)
+ WEAK_ALIAS(swapcontext, __sys_swapcontext)
+ WEAK_ALIAS(_swapcontext, __sys_swapcontext)
+ flushrs
+ ;;
+ CALLSYS_ERROR(swapcontext)
+ br.ret.sptk.few rp
+END(__sys_swapcontext)
diff --git a/lib/libc/iconv/Makefile.inc b/lib/libc/iconv/Makefile.inc
new file mode 100644
index 0000000..8c43a20
--- /dev/null
+++ b/lib/libc/iconv/Makefile.inc
@@ -0,0 +1,18 @@
+# $FreeBSD$
+
+# iconv sources
+.PATH: ${.CURDIR}/iconv
+
+MAN+= iconv.3 iconvctl.3 iconv_canonicalize.3 iconvlist.3 __iconv_get_list.3
+MLINKS+= iconv.3 iconv_open.3 \
+ iconv.3 iconv_open_into.3 \
+ iconv.3 iconv_close.3 \
+ iconv.3 __iconv.3 \
+ __iconv_get_list.3 __iconv_free_list.3
+SRCS+= citrus_bcs.c citrus_bcs_strtol.c citrus_bcs_strtoul.c \
+ citrus_csmapper.c citrus_db.c citrus_db_factory.c citrus_db_hash.c \
+ citrus_esdb.c citrus_hash.c citrus_iconv.c citrus_lookup.c \
+ citrus_lookup_factory.c citrus_mapper.c citrus_memstream.c \
+ citrus_mmap.c citrus_module.c citrus_none.c citrus_pivot_factory.c \
+ citrus_prop.c citrus_stdenc.c iconv.c
+SYM_MAPS+= ${.CURDIR}/iconv/Symbol.map
diff --git a/lib/libc/iconv/Symbol.map b/lib/libc/iconv/Symbol.map
new file mode 100644
index 0000000..73e0e22
--- /dev/null
+++ b/lib/libc/iconv/Symbol.map
@@ -0,0 +1,104 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.2 {
+ __iconv;
+ __iconv_free_list;
+ __iconv_get_list;
+ _libiconv_version;
+ iconv_canonicalize;
+ libiconv;
+ libiconv_close;
+ libiconv_open;
+ libiconv_open_into;
+ libiconv_set_relocation_prefix;
+ libiconvctl;
+ libiconvlist;
+};
+
+FBSDprivate_1.0 {
+ _citrus_bcs_convert_to_lower;
+ _citrus_bcs_convert_to_upper;
+ _citrus_bcs_isalnum;
+ _citrus_bcs_isalpha;
+ _citrus_bcs_isblank;
+ _citrus_bcs_isdigit;
+ _citrus_bcs_iseol;
+ _citrus_bcs_islower;
+ _citrus_bcs_isspace;
+ _citrus_bcs_isupper;
+ _citrus_bcs_isxdigit;
+ _citrus_bcs_skip_nonws;
+ _citrus_bcs_skip_nonws_len;
+ _citrus_bcs_skip_ws;
+ _citrus_bcs_skip_ws_len;
+ _citrus_bcs_strcasecmp;
+ _citrus_bcs_strncasecmp;
+ _citrus_bcs_strtol;
+ _citrus_bcs_strtoul;
+ _citrus_bcs_tolower;
+ _citrus_bcs_toupper;
+ _citrus_bcs_trunc_ws_len;
+ _citrus_csmapper_open;
+ _citrus_csmapper_close;
+ _citrus_db_factory_add_by_string;
+ _citrus_db_factory_add_string_by_string;
+ _citrus_db_factory_add32_by_string;
+ _citrus_db_factory_calc_size;
+ _citrus_db_factory_create;
+ _citrus_db_factory_serialize;
+ _citrus_db_hash_std;
+ _citrus_db_close;
+ _citrus_db_get_entry;
+ _citrus_db_get_number_of_entries;
+ _citrus_db_lookup;
+ _citrus_db_lookup_by_string;
+ _citrus_db_lookup8_by_string;
+ _citrus_db_lookup16_by_string;
+ _citrus_db_lookup_string_by_string;
+ _citrus_db_open;
+ _citrus_esdb_close;
+ _citrus_esdb_open;
+ _citrus_lookup_factory_convert;
+ _citrus_map_file;
+ _citrus_mapper_close;
+ _citrus_mapper_convert;
+ _citrus_mapper_create_area;
+ _citrus_mapper_get_dst_max;
+ _citrus_mapper_get_src_max;
+ _citrus_mapper_get_state_size;
+ _citrus_mapper_init_state;
+ _citrus_mapper_open;
+ _citrus_mapper_open_direct;
+ _citrus_mapper_set_persistent;
+ _citrus_memory_stream_bind;
+ _citrus_memory_stream_chr;
+ _citrus_memory_stream_getc;
+ _citrus_memory_stream_getln;
+ _citrus_memory_stream_getln_region;
+ _citrus_memory_stream_getregion;
+ _citrus_memory_stream_iseof;
+ _citrus_memory_stream_matchline;
+ _citrus_memory_stream_peek;
+ _citrus_memory_stream_remainder;
+ _citrus_memory_stream_rewind;
+ _citrus_memory_stream_seek;
+ _citrus_memory_stream_skip_ws;
+ _citrus_memory_stream_tell;
+ _citrus_memory_stream_ungetc;
+ _citrus_pivot_factory_convert;
+ _citrus_prop_object_init;
+ _citrus_prop_object_uninit;
+ _citrus_prop_parse_variable;
+ _citrus_prop_read_bool;
+ _citrus_prop_read_character;
+ _citrus_prop_read_character_common;
+ _citrus_prop_read_element;
+ _citrus_prop_read_num;
+ _citrus_prop_read_str;
+ _citrus_prop_read_symbol;
+ _citrus_stdenc_close;
+ _citrus_stdenc_open;
+ _citrus_unmap_file;
+};
diff --git a/lib/libc/iconv/__iconv_get_list.3 b/lib/libc/iconv/__iconv_get_list.3
new file mode 100644
index 0000000..7c8d015
--- /dev/null
+++ b/lib/libc/iconv/__iconv_get_list.3
@@ -0,0 +1,95 @@
+.\" Copyright (c) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 20, 2009
+.Dt __ICONV_GET_LIST 3
+.Os
+.Sh NAME
+.Nm __iconv_get_list
+.Nm __iconv_free_list
+.Nd retrieving a list of character encodings supported by
+.Xr iconv 3
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In iconv.h
+.Ft int
+.Fn __iconv_get_list "char ***names" "size_t count" "bool paired"
+.Ft void
+.Fn __iconv_free_list "char **names" "size_t count"
+.Sh DESCRIPTION
+The
+.Fn __iconv_get_list
+function obtains a list of character encodings that are supported by the
+.Xr iconv 3
+call.
+The list of the encoding names will be stored in
+.Fa names
+and the number of the entries is stored in
+.Fa count .
+If the
+.Fa paired
+variable is true, the list will be arranged into
+canonical/alias name pairs.
+.Pp
+The
+.Fn __iconv_free_list
+function is to free the allocated memory during the call of
+.Fn __iconv_get_list .
+.Sh RETURN VALUES
+Upon successful completion
+.Fn __iconv_get_list
+returns 0 and set the
+.Fa names
+and
+.Fa count
+arguments.
+Otherwise, \-1 is returned and errno is set to indicate the error.
+.Sh SEE ALSO
+.Xr iconv 3 ,
+.Xr iconvlist 3
+.Sh STANDARDS
+The
+.Nm __iconv_get_list
+and
+.Nm __iconv_free_list
+functions are non-standard interfaces, which appeared in
+the implementation of the Citrus Project.
+The iconv implementation of the Citrus Project was adopted in
+.Fx 9 .
+.Sh AUTHORS
+This manual page was written by
+.An Gabor Kovesdan Aq gabor@FreeBSD.org .
diff --git a/lib/libc/iconv/_strtol.h b/lib/libc/iconv/_strtol.h
new file mode 100644
index 0000000..d2d9d84
--- /dev/null
+++ b/lib/libc/iconv/_strtol.h
@@ -0,0 +1,167 @@
+/* $FreeBSD$ */
+/* $NetBSD: _strtol.h,v 1.2 2009/05/20 22:03:29 christos Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Original version ID:
+ * NetBSD: src/lib/libc/locale/_wcstol.h,v 1.2 2003/08/07 16:43:03 agc Exp
+ */
+
+/*
+ * function template for strtol, strtoll and strtoimax.
+ *
+ * parameters:
+ * _FUNCNAME : function name
+ * __INT : return type
+ * __INT_MIN : lower limit of the return type
+ * __INT_MAX : upper limit of the return type
+ */
+
+__INT
+_FUNCNAME(const char *nptr, char **endptr, int base)
+{
+ const char *s;
+ __INT acc, cutoff;
+ unsigned char c;
+ int any, cutlim, i, neg;
+
+ /* check base value */
+ if (base && (base < 2 || base > 36)) {
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+ errno = EINVAL;
+ if (endptr != NULL)
+ /* LINTED interface specification */
+ *endptr = __DECONST(void *, nptr);
+ return (0);
+#else
+ panic("%s: invalid base %d", __func__, base);
+#endif
+ }
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = (c == '0' ? 8 : 10);
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set any if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = (neg ? __INT_MIN : __INT_MAX);
+ cutlim = (int)(cutoff % base);
+ cutoff /= base;
+ if (neg) {
+ if (cutlim > 0) {
+ cutlim -= base;
+ cutoff += 1;
+ }
+ cutlim = -cutlim;
+ }
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ i = c - '0';
+ else if (isalpha(c))
+ i = c - (isupper(c) ? 'A' - 10 : 'a' - 10);
+ else
+ break;
+ if (i >= base)
+ break;
+ if (any < 0)
+ continue;
+ if (neg) {
+ if (acc < cutoff || (acc == cutoff && i > cutlim)) {
+ acc = __INT_MIN;
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+ any = -1;
+ errno = ERANGE;
+#else
+ any = 0;
+ break;
+#endif
+ } else {
+ any = 1;
+ acc *= base;
+ acc -= i;
+ }
+ } else {
+ if (acc > cutoff || (acc == cutoff && i > cutlim)) {
+ acc = __INT_MAX;
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+ any = -1;
+ errno = ERANGE;
+#else
+ any = 0;
+ break;
+#endif
+ } else {
+ any = 1;
+ acc *= base;
+ acc += i;
+ }
+ }
+ }
+ if (endptr != NULL)
+ /* LINTED interface specification */
+ *endptr = __DECONST(void *, any ? s - 1 : nptr);
+ return(acc);
+}
diff --git a/lib/libc/iconv/_strtoul.h b/lib/libc/iconv/_strtoul.h
new file mode 100644
index 0000000..64e0d46
--- /dev/null
+++ b/lib/libc/iconv/_strtoul.h
@@ -0,0 +1,126 @@
+/* $FreeBSD$ */
+/* $NetBSD: _strtoul.h,v 1.1 2008/08/20 12:42:26 joerg Exp $ */
+
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Original version ID:
+ * NetBSD: src/lib/libc/locale/_wcstoul.h,v 1.2 2003/08/07 16:43:03 agc Exp
+ */
+
+/*
+ * function template for strtoul, strtoull and strtoumax.
+ *
+ * parameters:
+ * _FUNCNAME : function name
+ * __UINT : return type
+ * __UINT_MAX : upper limit of the return type
+ */
+
+__UINT
+_FUNCNAME(const char *nptr, char **endptr, int base)
+{
+ const char *s;
+ __UINT acc, cutoff;
+ unsigned char c;
+ int any, cutlim, i, neg;
+
+ /* check base value */
+ if (base && (base < 2 || base > 36)) {
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+ errno = EINVAL;
+ return (0);
+#else
+ panic("%s: invalid base %d", __func__, base);
+#endif
+ }
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace(c));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = (c == '0' ? 8 : 10);
+
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ cutoff = __UINT_MAX / (__UINT)base;
+ cutlim = (int)(__UINT_MAX % (__UINT)base);
+ for (acc = 0, any = 0;; c = *s++) {
+ if (isdigit(c))
+ i = c - '0';
+ else if (isalpha(c))
+ i = c - (isupper(c) ? 'A' - 10 : 'a' - 10);
+ else
+ break;
+ if (i >= base)
+ break;
+ if (any < 0)
+ continue;
+ if (acc > cutoff || (acc == cutoff && i > cutlim)) {
+ acc = __UINT_MAX;
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+ any = -1;
+ errno = ERANGE;
+#else
+ any = 0;
+ break;
+#endif
+ } else {
+ any = 1;
+ acc *= (__UINT)base;
+ acc += i;
+ }
+ }
+ if (neg && any > 0)
+ acc = -acc;
+ if (endptr != NULL)
+ /* LINTED interface specification */
+ *endptr = __DECONST(void *, any ? s - 1 : nptr);
+ return (acc);
+}
diff --git a/lib/libc/iconv/citrus_aliasname_local.h b/lib/libc/iconv/citrus_aliasname_local.h
new file mode 100644
index 0000000..687362b
--- /dev/null
+++ b/lib/libc/iconv/citrus_aliasname_local.h
@@ -0,0 +1,49 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_aliasname_local.h,v 1.2 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c)2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ALIASNAME_LOCAL_H_
+#define _CITRUS_ALIASNAME_LOCAL_H_
+
+static __inline const char *
+__unaliasname(const char *dbname, const char *alias,
+ void *buf, size_t bufsize)
+{
+
+ return (_lookup_simple(dbname, alias,
+ buf, bufsize, _LOOKUP_CASE_SENSITIVE));
+}
+
+static __inline int
+__isforcemapping(const char *name)
+{
+
+ return (_bcs_strcasecmp("/force", name));
+}
+
+#endif /*_CITRUS_ALIASNAME_LOCAL_H_*/
diff --git a/lib/libc/iconv/citrus_bcs.c b/lib/libc/iconv/citrus_bcs.c
new file mode 100644
index 0000000..e86fb37
--- /dev/null
+++ b/lib/libc/iconv/citrus_bcs.c
@@ -0,0 +1,168 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_bcs.c,v 1.5 2005/05/14 17:55:42 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <stdlib.h>
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+
+/*
+ * case insensitive comparison between two C strings.
+ */
+int
+_citrus_bcs_strcasecmp(const char * __restrict str1,
+ const char * __restrict str2)
+{
+ int c1, c2;
+
+ c1 = c2 = 1;
+
+ while (c1 && c2 && c1 == c2) {
+ c1 = _bcs_toupper(*str1++);
+ c2 = _bcs_toupper(*str2++);
+ }
+
+ return ((c1 == c2) ? 0 : ((c1 > c2) ? 1 : -1));
+}
+
+/*
+ * case insensitive comparison between two C strings with limitation of length.
+ */
+int
+_citrus_bcs_strncasecmp(const char * __restrict str1,
+ const char * __restrict str2, size_t sz)
+{
+ int c1, c2;
+
+ c1 = c2 = 1;
+
+ while (c1 && c2 && c1 == c2 && sz != 0) {
+ c1 = _bcs_toupper(*str1++);
+ c2 = _bcs_toupper(*str2++);
+ sz--;
+ }
+
+ return ((c1 == c2) ? 0 : ((c1 > c2) ? 1 : -1));
+}
+
+/*
+ * skip white space characters.
+ */
+const char *
+_citrus_bcs_skip_ws(const char *p)
+{
+
+ while (*p && _bcs_isspace(*p))
+ p++;
+
+ return (p);
+}
+
+/*
+ * skip non white space characters.
+ */
+const char *
+_citrus_bcs_skip_nonws(const char *p)
+{
+
+ while (*p && !_bcs_isspace(*p))
+ p++;
+
+ return (p);
+}
+
+/*
+ * skip white space characters with limitation of length.
+ */
+const char *
+_citrus_bcs_skip_ws_len(const char * __restrict p, size_t * __restrict len)
+{
+
+ while (*p && *len > 0 && _bcs_isspace(*p)) {
+ p++;
+ (*len)--;
+ }
+
+ return (p);
+}
+
+/*
+ * skip non white space characters with limitation of length.
+ */
+const char *
+_citrus_bcs_skip_nonws_len(const char * __restrict p, size_t * __restrict len)
+{
+
+ while (*p && *len > 0 && !_bcs_isspace(*p)) {
+ p++;
+ (*len)--;
+ }
+
+ return (p);
+}
+
+/*
+ * truncate trailing white space characters.
+ */
+void
+_citrus_bcs_trunc_rws_len(const char * __restrict p, size_t * __restrict len)
+{
+
+ while (*len > 0 && _bcs_isspace(p[*len - 1]))
+ (*len)--;
+}
+
+/*
+ * destructive transliterate to lowercase.
+ */
+void
+_citrus_bcs_convert_to_lower(char *s)
+{
+
+ while (*s) {
+ *s = _bcs_tolower(*s);
+ s++;
+ }
+}
+
+/*
+ * destructive transliterate to uppercase.
+ */
+void
+_citrus_bcs_convert_to_upper(char *s)
+{
+
+ while (*s) {
+ *s = _bcs_toupper(*s);
+ s++;
+ }
+}
diff --git a/lib/libc/iconv/citrus_bcs.h b/lib/libc/iconv/citrus_bcs.h
new file mode 100644
index 0000000..3b1f537
--- /dev/null
+++ b/lib/libc/iconv/citrus_bcs.h
@@ -0,0 +1,102 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_bcs.h,v 1.6 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+#ifndef _CITRUS_BCS_H_
+#define _CITRUS_BCS_H_
+
+/*
+ * predicate/conversion for basic character set.
+ *
+ * `Basic character set' is a term defined in the ISO C standard.
+ * Citrus bcs is, if anything, close to `portable character set'
+ * defined in the POSIX.
+ */
+
+#define _CITRUS_BCS_PRED(_name_, _cond_) \
+static __inline int _citrus_bcs_##_name_(uint8_t c) { return (_cond_); }
+
+/*
+ * predicates.
+ * Unlike predicates defined in ctype.h, these do not accept EOF.
+ */
+_CITRUS_BCS_PRED(isblank, c == ' ' || c == '\t')
+_CITRUS_BCS_PRED(iseol, c == '\n' || c == '\r')
+_CITRUS_BCS_PRED(isspace, _citrus_bcs_isblank(c) || _citrus_bcs_iseol(c) ||
+ c == '\f' || c == '\v')
+_CITRUS_BCS_PRED(isdigit, c >= '0' && c <= '9')
+_CITRUS_BCS_PRED(isupper, c >= 'A' && c <= 'Z')
+_CITRUS_BCS_PRED(islower, c >= 'a' && c <= 'z')
+_CITRUS_BCS_PRED(isalpha, _citrus_bcs_isupper(c) || _citrus_bcs_islower(c))
+_CITRUS_BCS_PRED(isalnum, _citrus_bcs_isdigit(c) || _citrus_bcs_isalpha(c))
+_CITRUS_BCS_PRED(isxdigit, _citrus_bcs_isdigit(c) ||
+ (c >= 'A' && c <= 'F') || (c >= 'a' && c <= 'f'))
+
+/*
+ * transliterate between uppercase and lowercase.
+ * Unlike transliterator defined in ctype.h, these do not accept EOF.
+ */
+static __inline uint8_t
+_citrus_bcs_toupper(uint8_t c)
+{
+
+ return (_citrus_bcs_islower(c) ? (c - 'a' + 'A') : c);
+}
+
+static __inline uint8_t
+_citrus_bcs_tolower(uint8_t c)
+{
+
+ return (_citrus_bcs_isupper(c) ? (c - 'A' + 'a') : c);
+}
+
+__BEGIN_DECLS
+int _citrus_bcs_strcasecmp(const char * __restrict,
+ const char * __restrict);
+int _citrus_bcs_strncasecmp(const char * __restrict,
+ const char * __restrict, size_t);
+const char *_citrus_bcs_skip_ws(const char * __restrict);
+const char *_citrus_bcs_skip_nonws(const char * __restrict);
+const char *_citrus_bcs_skip_ws_len(const char * __restrict,
+ size_t * __restrict);
+const char *_citrus_bcs_skip_nonws_len(const char * __restrict,
+ size_t * __restrict);
+void _citrus_bcs_trunc_rws_len(const char * __restrict,
+ size_t * __restrict);
+void _citrus_bcs_convert_to_lower(char *);
+void _citrus_bcs_convert_to_upper(char *);
+
+long int _citrus_bcs_strtol(const char * __restrict,
+ char ** __restrict, int);
+unsigned long _citrus_bcs_strtoul(const char * __restrict,
+ char ** __restrict, int);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_bcs_strtol.c b/lib/libc/iconv/citrus_bcs_strtol.c
new file mode 100644
index 0000000..4073622
--- /dev/null
+++ b/lib/libc/iconv/citrus_bcs_strtol.c
@@ -0,0 +1,57 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_bcs_strtol.c,v 1.2 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c) 2005 The DragonFly Project. All rights reserved.
+ * Copyright (c) 2003, 2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+
+#define _FUNCNAME _bcs_strtol
+#define __INT long int
+
+#undef isspace
+#define isspace(c) _bcs_isspace(c)
+
+#undef isdigit
+#define isdigit(c) _bcs_isdigit(c)
+
+#undef isalpha
+#define isalpha(c) _bcs_isalpha(c)
+
+#undef isupper
+#define isupper(c) _bcs_isupper(c)
+
+#include "_strtol.h"
diff --git a/lib/libc/iconv/citrus_bcs_strtoul.c b/lib/libc/iconv/citrus_bcs_strtoul.c
new file mode 100644
index 0000000..d9fa97c
--- /dev/null
+++ b/lib/libc/iconv/citrus_bcs_strtoul.c
@@ -0,0 +1,57 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_bcs_strtoul.c,v 1.3 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c) 2005 The DragonFly Project. All rights reserved.
+ * Copyright (c) 2003, 2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
+#include <stdlib.h>
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+
+#define _FUNCNAME _bcs_strtoul
+#define __UINT unsigned long int
+
+#undef isspace
+#define isspace(c) _bcs_isspace(c)
+
+#undef isdigit
+#define isdigit(c) _bcs_isdigit(c)
+
+#undef isalpha
+#define isalpha(c) _bcs_isalpha(c)
+
+#undef isupper
+#define isupper(c) _bcs_isupper(c)
+
+#include "_strtoul.h"
diff --git a/lib/libc/iconv/citrus_csmapper.c b/lib/libc/iconv/citrus_csmapper.c
new file mode 100644
index 0000000..5e0a01a
--- /dev/null
+++ b/lib/libc/iconv/citrus_csmapper.c
@@ -0,0 +1,383 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_csmapper.c,v 1.10 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/endian.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_lock.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_module.h"
+#include "citrus_hash.h"
+#include "citrus_mapper.h"
+#include "citrus_csmapper.h"
+#include "citrus_pivot_file.h"
+#include "citrus_db.h"
+#include "citrus_db_hash.h"
+#include "citrus_lookup.h"
+
+static struct _citrus_mapper_area *maparea = NULL;
+
+#define CS_ALIAS _PATH_CSMAPPER "/charset.alias"
+#define CS_PIVOT _PATH_CSMAPPER "/charset.pivot"
+
+
+/* ---------------------------------------------------------------------- */
+
+static int
+get32(struct _region *r, uint32_t *rval)
+{
+
+ if (_region_size(r) != 4)
+ return (EFTYPE);
+
+ memcpy(rval, _region_head(r), (size_t)4);
+ *rval = be32toh(*rval);
+
+ return (0);
+}
+
+static int
+open_subdb(struct _citrus_db **subdb, struct _citrus_db *db, const char *src)
+{
+ struct _region r;
+ int ret;
+
+ ret = _db_lookup_by_s(db, src, &r, NULL);
+ if (ret)
+ return (ret);
+ ret = _db_open(subdb, &r, _CITRUS_PIVOT_SUB_MAGIC, _db_hash_std, NULL);
+ if (ret)
+ return (ret);
+
+ return (0);
+}
+
+
+#define NO_SUCH_FILE EOPNOTSUPP
+static int
+find_best_pivot_pvdb(const char *src, const char *dst, char *pivot,
+ size_t pvlen, unsigned long *rnorm)
+{
+ struct _citrus_db *db1, *db2, *db3;
+ struct _region fr, r1, r2;
+ char buf[LINE_MAX];
+ uint32_t val32;
+ unsigned long norm;
+ int i, num, ret;
+
+ ret = _map_file(&fr, CS_PIVOT ".pvdb");
+ if (ret) {
+ if (ret == ENOENT)
+ ret = NO_SUCH_FILE;
+ return (ret);
+ }
+ ret = _db_open(&db1, &fr, _CITRUS_PIVOT_MAGIC, _db_hash_std, NULL);
+ if (ret)
+ goto quit1;
+ ret = open_subdb(&db2, db1, src);
+ if (ret)
+ goto quit2;
+
+ num = _db_get_num_entries(db2);
+ *rnorm = ULONG_MAX;
+ for (i = 0; i < num; i++) {
+ /* iterate each pivot */
+ ret = _db_get_entry(db2, i, &r1, &r2);
+ if (ret)
+ goto quit3;
+ /* r1:pivot name, r2:norm among src and pivot */
+ ret = get32(&r2, &val32);
+ if (ret)
+ goto quit3;
+ norm = val32;
+ snprintf(buf, sizeof(buf), "%.*s",
+ (int)_region_size(&r1), (char *)_region_head(&r1));
+ /* buf: pivot name */
+ ret = open_subdb(&db3, db1, buf);
+ if (ret)
+ goto quit3;
+ if (_db_lookup_by_s(db3, dst, &r2, NULL) != 0)
+ goto quit4;
+ /* r2: norm among pivot and dst */
+ ret = get32(&r2, &val32);
+ if (ret)
+ goto quit4;
+ norm += val32;
+ /* judge minimum norm */
+ if (norm < *rnorm) {
+ *rnorm = norm;
+ strlcpy(pivot, buf, pvlen);
+ }
+quit4:
+ _db_close(db3);
+ if (ret)
+ goto quit3;
+ }
+quit3:
+ _db_close(db2);
+quit2:
+ _db_close(db1);
+quit1:
+ _unmap_file(&fr);
+ if (ret)
+ return (ret);
+
+ if (*rnorm == ULONG_MAX)
+ return (ENOENT);
+
+ return (0);
+}
+
+/* ---------------------------------------------------------------------- */
+
+struct zone {
+ const char *begin, *end;
+};
+
+struct parse_arg {
+ char dst[PATH_MAX];
+ unsigned long norm;
+};
+
+static int
+parse_line(struct parse_arg *pa, struct _region *r)
+{
+ struct zone z1, z2;
+ char buf[20];
+ size_t len;
+
+ len = _region_size(r);
+ z1.begin = _bcs_skip_ws_len(_region_head(r), &len);
+ if (len == 0)
+ return (EFTYPE);
+ z1.end = _bcs_skip_nonws_len(z1.begin, &len);
+ if (len == 0)
+ return (EFTYPE);
+ z2.begin = _bcs_skip_ws_len(z1.end, &len);
+ if (len == 0)
+ return (EFTYPE);
+ z2.end = _bcs_skip_nonws_len(z2.begin, &len);
+
+ /* z1 : dst name, z2 : norm */
+ snprintf(pa->dst, sizeof(pa->dst),
+ "%.*s", (int)(z1.end-z1.begin), z1.begin);
+ snprintf(buf, sizeof(buf),
+ "%.*s", (int)(z2.end-z2.begin), z2.begin);
+ pa->norm = _bcs_strtoul(buf, NULL, 0);
+
+ return (0);
+}
+
+static int
+find_dst(struct parse_arg *pasrc, const char *dst)
+{
+ struct _lookup *cl;
+ struct parse_arg padst;
+ struct _region data;
+ int ret;
+
+ ret = _lookup_seq_open(&cl, CS_PIVOT, _LOOKUP_CASE_IGNORE);
+ if (ret)
+ return (ret);
+
+ ret = _lookup_seq_lookup(cl, pasrc->dst, &data);
+ while (ret == 0) {
+ ret = parse_line(&padst, &data);
+ if (ret)
+ break;
+ if (strcmp(dst, padst.dst) == 0) {
+ pasrc->norm += padst.norm;
+ break;
+ }
+ ret = _lookup_seq_next(cl, NULL, &data);
+ }
+ _lookup_seq_close(cl);
+
+ return (ret);
+}
+
+static int
+find_best_pivot_lookup(const char *src, const char *dst, char *pivot,
+ size_t pvlen, unsigned long *rnorm)
+{
+ struct _lookup *cl;
+ struct _region data;
+ struct parse_arg pa;
+ char pivot_min[PATH_MAX];
+ unsigned long norm_min;
+ int ret;
+
+ ret = _lookup_seq_open(&cl, CS_PIVOT, _LOOKUP_CASE_IGNORE);
+ if (ret)
+ return (ret);
+
+ norm_min = ULONG_MAX;
+
+ /* find pivot code */
+ ret = _lookup_seq_lookup(cl, src, &data);
+ while (ret == 0) {
+ ret = parse_line(&pa, &data);
+ if (ret)
+ break;
+ ret = find_dst(&pa, dst);
+ if (ret)
+ break;
+ if (pa.norm < norm_min) {
+ norm_min = pa.norm;
+ strlcpy(pivot_min, pa.dst, sizeof(pivot_min));
+ }
+ ret = _lookup_seq_next(cl, NULL, &data);
+ }
+ _lookup_seq_close(cl);
+
+ if (ret != ENOENT)
+ return (ret);
+ if (norm_min == ULONG_MAX)
+ return (ENOENT);
+ strlcpy(pivot, pivot_min, pvlen);
+ if (rnorm)
+ *rnorm = norm_min;
+
+ return (0);
+}
+
+static int
+find_best_pivot(const char *src, const char *dst, char *pivot, size_t pvlen,
+ unsigned long *rnorm)
+{
+ int ret;
+
+ ret = find_best_pivot_pvdb(src, dst, pivot, pvlen, rnorm);
+ if (ret == NO_SUCH_FILE)
+ ret = find_best_pivot_lookup(src, dst, pivot, pvlen, rnorm);
+
+ return (ret);
+}
+
+static __inline int
+open_serial_mapper(struct _citrus_mapper_area *__restrict ma,
+ struct _citrus_mapper * __restrict * __restrict rcm,
+ const char *src, const char *pivot, const char *dst)
+{
+ char buf[PATH_MAX];
+
+ snprintf(buf, sizeof(buf), "%s/%s,%s/%s", src, pivot, pivot, dst);
+
+ return (_mapper_open_direct(ma, rcm, "mapper_serial", buf));
+}
+
+static struct _citrus_csmapper *csm_none = NULL;
+static int
+get_none(struct _citrus_mapper_area *__restrict ma,
+ struct _citrus_csmapper *__restrict *__restrict rcsm)
+{
+ int ret;
+
+ WLOCK;
+ if (csm_none) {
+ *rcsm = csm_none;
+ ret = 0;
+ goto quit;
+ }
+
+ ret = _mapper_open_direct(ma, &csm_none, "mapper_none", "");
+ if (ret)
+ goto quit;
+ _mapper_set_persistent(csm_none);
+
+ *rcsm = csm_none;
+ ret = 0;
+quit:
+ UNLOCK;
+ return (ret);
+}
+
+int
+_citrus_csmapper_open(struct _citrus_csmapper * __restrict * __restrict rcsm,
+ const char * __restrict src, const char * __restrict dst, uint32_t flags,
+ unsigned long *rnorm)
+{
+ const char *realsrc, *realdst;
+ char buf1[PATH_MAX], buf2[PATH_MAX], key[PATH_MAX], pivot[PATH_MAX];
+ unsigned long norm;
+ int ret;
+
+ norm = 0;
+
+ ret = _citrus_mapper_create_area(&maparea, _PATH_CSMAPPER);
+ if (ret)
+ return (ret);
+
+ realsrc = _lookup_alias(CS_ALIAS, src, buf1, sizeof(buf1),
+ _LOOKUP_CASE_IGNORE);
+ realdst = _lookup_alias(CS_ALIAS, dst, buf2, sizeof(buf2),
+ _LOOKUP_CASE_IGNORE);
+ if (!strcmp(realsrc, realdst)) {
+ ret = get_none(maparea, rcsm);
+ if (ret == 0 && rnorm != NULL)
+ *rnorm = 0;
+ return (ret);
+ }
+
+ snprintf(key, sizeof(key), "%s/%s", realsrc, realdst);
+
+ ret = _mapper_open(maparea, rcsm, key);
+ if (ret == 0) {
+ if (rnorm != NULL)
+ *rnorm = 0;
+ return (0);
+ }
+ if (ret != ENOENT || (flags & _CSMAPPER_F_PREVENT_PIVOT)!=0)
+ return (ret);
+
+ ret = find_best_pivot(realsrc, realdst, pivot, sizeof(pivot), &norm);
+ if (ret)
+ return (ret);
+
+ ret = open_serial_mapper(maparea, rcsm, realsrc, pivot, realdst);
+ if (ret == 0 && rnorm != NULL)
+ *rnorm = norm;
+
+ return (ret);
+}
diff --git a/lib/libc/iconv/citrus_csmapper.h b/lib/libc/iconv/citrus_csmapper.h
new file mode 100644
index 0000000..dd178da
--- /dev/null
+++ b/lib/libc/iconv/citrus_csmapper.h
@@ -0,0 +1,48 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_csmapper.h,v 1.2 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_CSMAPPER_H_
+#define _CITRUS_CSMAPPER_H
+
+#define _citrus_csmapper _citrus_mapper
+#define _citrus_csmapper_close _citrus_mapper_close
+#define _citrus_csmapper_convert _citrus_mapper_convert
+#define _citrus_csmapper_init_state _citrus_mapper_init_state
+#define _citrus_csmapper_get_state_size _citrus_mapper_get_state_size
+#define _citrus_csmapper_get_src_max _citrus_mapper_get_src_max
+#define _citrus_csmapper_get_dst_max _citrus_mapper_get_dst_max
+
+#define _CITRUS_CSMAPPER_F_PREVENT_PIVOT 0x00000001
+__BEGIN_DECLS
+int _citrus_csmapper_open(struct _citrus_csmapper *__restrict *__restrict,
+ const char *__restrict, const char *__restrict, uint32_t,
+ unsigned long *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_db.c b/lib/libc/iconv/citrus_db.c
new file mode 100644
index 0000000..2de848b
--- /dev/null
+++ b/lib/libc/iconv/citrus_db.c
@@ -0,0 +1,331 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_db.c,v 1.5 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/endian.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_db.h"
+#include "citrus_db_factory.h"
+#include "citrus_db_file.h"
+
+struct _citrus_db {
+ struct _region db_region;
+ _citrus_db_hash_func_t db_hashfunc;
+ void *db_hashfunc_closure;
+};
+
+int
+_citrus_db_open(struct _citrus_db **rdb, struct _region *r, const char *magic,
+ _citrus_db_hash_func_t hashfunc, void *hashfunc_closure)
+{
+ struct _citrus_db *db;
+ struct _citrus_db_header_x *dhx;
+ struct _memstream ms;
+
+ _memstream_bind(&ms, r);
+
+ /* sanity check */
+ dhx = _memstream_getregion(&ms, NULL, sizeof(*dhx));
+ if (dhx == NULL)
+ return (EFTYPE);
+ if (strncmp(dhx->dhx_magic, magic, _CITRUS_DB_MAGIC_SIZE) != 0)
+ return (EFTYPE);
+ if (_memstream_seek(&ms, be32toh(dhx->dhx_entry_offset), SEEK_SET))
+ return (EFTYPE);
+
+ if (be32toh(dhx->dhx_num_entries)*_CITRUS_DB_ENTRY_SIZE >
+ _memstream_remainder(&ms))
+ return (EFTYPE);
+
+ db = malloc(sizeof(*db));
+ if (db == NULL)
+ return (errno);
+ db->db_region = *r;
+ db->db_hashfunc = hashfunc;
+ db->db_hashfunc_closure = hashfunc_closure;
+ *rdb = db;
+
+ return (0);
+}
+
+void
+_citrus_db_close(struct _citrus_db *db)
+{
+
+ free(db);
+}
+
+int
+_citrus_db_lookup(struct _citrus_db *db, struct _citrus_region *key,
+ struct _citrus_region *data, struct _citrus_db_locator *dl)
+{
+ struct _citrus_db_entry_x *dex;
+ struct _citrus_db_header_x *dhx;
+ struct _citrus_region r;
+ struct _memstream ms;
+ uint32_t hashval, num_entries;
+ size_t offset;
+
+ _memstream_bind(&ms, &db->db_region);
+
+ dhx = _memstream_getregion(&ms, NULL, sizeof(*dhx));
+ num_entries = be32toh(dhx->dhx_num_entries);
+ if (num_entries == 0)
+ return (ENOENT);
+
+ if (dl != NULL && dl->dl_offset>0) {
+ hashval = dl->dl_hashval;
+ offset = dl->dl_offset;
+ if (offset >= _region_size(&db->db_region))
+ return (ENOENT);
+ } else {
+ hashval = db->db_hashfunc(key)%num_entries;
+ offset = be32toh(dhx->dhx_entry_offset) +
+ hashval * _CITRUS_DB_ENTRY_SIZE;
+ if (dl)
+ dl->dl_hashval = hashval;
+ }
+ do {
+ /* seek to the next entry */
+ if (_citrus_memory_stream_seek(&ms, offset, SEEK_SET))
+ return (EFTYPE);
+ /* get the entry record */
+ dex = _memstream_getregion(&ms, NULL, _CITRUS_DB_ENTRY_SIZE);
+ if (dex == NULL)
+ return (EFTYPE);
+
+ /* jump to next entry having the same hash value. */
+ offset = be32toh(dex->dex_next_offset);
+
+ /* save the current position */
+ if (dl) {
+ dl->dl_offset = offset;
+ if (offset == 0)
+ dl->dl_offset = _region_size(&db->db_region);
+ }
+
+ /* compare hash value. */
+ if (be32toh(dex->dex_hash_value) != hashval)
+ /* not found */
+ break;
+ /* compare key length */
+ if (be32toh(dex->dex_key_size) == _region_size(key)) {
+ /* seek to the head of the key. */
+ if (_memstream_seek(&ms, be32toh(dex->dex_key_offset),
+ SEEK_SET))
+ return (EFTYPE);
+ /* get the region of the key */
+ if (_memstream_getregion(&ms, &r,
+ _region_size(key)) == NULL)
+ return (EFTYPE);
+ /* compare key byte stream */
+ if (memcmp(_region_head(&r), _region_head(key),
+ _region_size(key)) == 0) {
+ /* match */
+ if (_memstream_seek(
+ &ms, be32toh(dex->dex_data_offset),
+ SEEK_SET))
+ return (EFTYPE);
+ if (_memstream_getregion(
+ &ms, data,
+ be32toh(dex->dex_data_size)) == NULL)
+ return (EFTYPE);
+ return (0);
+ }
+ }
+ } while (offset != 0);
+
+ return (ENOENT);
+}
+
+int
+_citrus_db_lookup_by_string(struct _citrus_db *db, const char *key,
+ struct _citrus_region *data, struct _citrus_db_locator *dl)
+{
+ struct _region r;
+
+ _region_init(&r, __DECONST(void *, key), strlen(key));
+
+ return (_citrus_db_lookup(db, &r, data, dl));
+}
+
+int
+_citrus_db_lookup8_by_string(struct _citrus_db *db, const char *key,
+ uint8_t *rval, struct _citrus_db_locator *dl)
+{
+ struct _region r;
+ int ret;
+
+ ret = _citrus_db_lookup_by_string(db, key, &r, dl);
+ if (ret)
+ return (ret);
+
+ if (_region_size(&r) != 1)
+ return (EFTYPE);
+
+ if (rval)
+ memcpy(rval, _region_head(&r), 1);
+
+ return (0);
+}
+
+int
+_citrus_db_lookup16_by_string(struct _citrus_db *db, const char *key,
+ uint16_t *rval, struct _citrus_db_locator *dl)
+{
+ struct _region r;
+ int ret;
+ uint16_t val;
+
+ ret = _citrus_db_lookup_by_string(db, key, &r, dl);
+ if (ret)
+ return (ret);
+
+ if (_region_size(&r) != 2)
+ return (EFTYPE);
+
+ if (rval) {
+ memcpy(&val, _region_head(&r), 2);
+ *rval = be16toh(val);
+ }
+
+ return (0);
+}
+
+int
+_citrus_db_lookup32_by_string(struct _citrus_db *db, const char *key,
+ uint32_t *rval, struct _citrus_db_locator *dl)
+{
+ struct _region r;
+ uint32_t val;
+ int ret;
+
+ ret = _citrus_db_lookup_by_string(db, key, &r, dl);
+ if (ret)
+ return (ret);
+
+ if (_region_size(&r) != 4)
+ return (EFTYPE);
+
+ if (rval) {
+ memcpy(&val, _region_head(&r), 4);
+ *rval = be32toh(val);
+ }
+
+ return (0);
+}
+
+int
+_citrus_db_lookup_string_by_string(struct _citrus_db *db, const char *key,
+ const char **rdata, struct _citrus_db_locator *dl)
+{
+ struct _region r;
+ int ret;
+
+ ret = _citrus_db_lookup_by_string(db, key, &r, dl);
+ if (ret)
+ return (ret);
+
+ /* check whether the string is null terminated */
+ if (_region_size(&r) == 0)
+ return (EFTYPE);
+ if (*((const char*)_region_head(&r)+_region_size(&r)-1) != '\0')
+ return (EFTYPE);
+
+ if (rdata)
+ *rdata = _region_head(&r);
+
+ return (0);
+}
+
+int
+_citrus_db_get_number_of_entries(struct _citrus_db *db)
+{
+ struct _citrus_db_header_x *dhx;
+ struct _memstream ms;
+
+ _memstream_bind(&ms, &db->db_region);
+
+ dhx = _memstream_getregion(&ms, NULL, sizeof(*dhx));
+ return ((int)be32toh(dhx->dhx_num_entries));
+}
+
+int
+_citrus_db_get_entry(struct _citrus_db *db, int idx, struct _region *key,
+ struct _region *data)
+{
+ struct _citrus_db_entry_x *dex;
+ struct _citrus_db_header_x *dhx;
+ struct _memstream ms;
+ uint32_t num_entries;
+ size_t offset;
+
+ _memstream_bind(&ms, &db->db_region);
+
+ dhx = _memstream_getregion(&ms, NULL, sizeof(*dhx));
+ num_entries = be32toh(dhx->dhx_num_entries);
+ if (idx < 0 || (uint32_t)idx >= num_entries)
+ return (EINVAL);
+
+ /* seek to the next entry */
+ offset = be32toh(dhx->dhx_entry_offset) + idx * _CITRUS_DB_ENTRY_SIZE;
+ if (_citrus_memory_stream_seek(&ms, offset, SEEK_SET))
+ return (EFTYPE);
+ /* get the entry record */
+ dex = _memstream_getregion(&ms, NULL, _CITRUS_DB_ENTRY_SIZE);
+ if (dex == NULL)
+ return (EFTYPE);
+ /* seek to the head of the key. */
+ if (_memstream_seek(&ms, be32toh(dex->dex_key_offset), SEEK_SET))
+ return (EFTYPE);
+ /* get the region of the key. */
+ if (_memstream_getregion(&ms, key, be32toh(dex->dex_key_size))==NULL)
+ return (EFTYPE);
+ /* seek to the head of the data. */
+ if (_memstream_seek(&ms, be32toh(dex->dex_data_offset), SEEK_SET))
+ return (EFTYPE);
+ /* get the region of the data. */
+ if (_memstream_getregion(&ms, data, be32toh(dex->dex_data_size))==NULL)
+ return (EFTYPE);
+
+ return (0);
+}
diff --git a/lib/libc/iconv/citrus_db.h b/lib/libc/iconv/citrus_db.h
new file mode 100644
index 0000000..27e16f3
--- /dev/null
+++ b/lib/libc/iconv/citrus_db.h
@@ -0,0 +1,70 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_db.h,v 1.2 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_DB_H_
+#define _CITRUS_DB_H_
+
+#include "citrus_db_factory.h"
+
+struct _citrus_db;
+struct _citrus_db_locator {
+ uint32_t dl_hashval;
+ size_t dl_offset;
+};
+
+__BEGIN_DECLS
+int _citrus_db_open(struct _citrus_db **, struct _citrus_region *,
+ const char *, _citrus_db_hash_func_t, void *);
+void _citrus_db_close(struct _citrus_db *);
+int _citrus_db_lookup(struct _citrus_db *, struct _citrus_region *,
+ struct _citrus_region *, struct _citrus_db_locator *);
+int _citrus_db_lookup_by_string(struct _citrus_db *, const char *,
+ struct _citrus_region *, struct _citrus_db_locator *);
+int _citrus_db_lookup8_by_string(struct _citrus_db *, const char *,
+ uint8_t *, struct _citrus_db_locator *);
+int _citrus_db_lookup16_by_string(struct _citrus_db *, const char *,
+ uint16_t *, struct _citrus_db_locator *);
+int _citrus_db_lookup32_by_string(struct _citrus_db *, const char *,
+ uint32_t *, struct _citrus_db_locator *);
+int _citrus_db_lookup_string_by_string(struct _citrus_db *, const char *,
+ const char **, struct _citrus_db_locator *);
+int _citrus_db_get_number_of_entries(struct _citrus_db *);
+int _citrus_db_get_entry(struct _citrus_db *, int,
+ struct _citrus_region *, struct _citrus_region *);
+__END_DECLS
+
+static __inline void
+_citrus_db_locator_init(struct _citrus_db_locator *dl)
+{
+
+ dl->dl_hashval = 0;
+ dl->dl_offset = 0;
+}
+
+#endif
diff --git a/lib/libc/iconv/citrus_db_factory.c b/lib/libc/iconv/citrus_db_factory.c
new file mode 100644
index 0000000..9a3edf2
--- /dev/null
+++ b/lib/libc/iconv/citrus_db_factory.c
@@ -0,0 +1,348 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_db_factory.c,v 1.9 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_region.h"
+#include "citrus_db_file.h"
+#include "citrus_db_factory.h"
+
+struct _citrus_db_factory_entry {
+ STAILQ_ENTRY(_citrus_db_factory_entry) de_entry;
+ struct _citrus_db_factory_entry *de_next;
+ uint32_t de_hashvalue;
+ struct _region de_key;
+ int de_key_free;
+ struct _region de_data;
+ int de_data_free;
+ int de_idx;
+};
+
+struct _citrus_db_factory {
+ size_t df_num_entries;
+ STAILQ_HEAD(, _citrus_db_factory_entry) df_entries;
+ size_t df_total_key_size;
+ size_t df_total_data_size;
+ uint32_t (*df_hashfunc)(struct _citrus_region *);
+ void *df_hashfunc_closure;
+};
+
+#define DB_ALIGN 16
+
+int
+_citrus_db_factory_create(struct _citrus_db_factory **rdf,
+ _citrus_db_hash_func_t hashfunc, void *hashfunc_closure)
+{
+ struct _citrus_db_factory *df;
+
+ df = malloc(sizeof(*df));
+ if (df == NULL)
+ return (errno);
+ df->df_num_entries = 0;
+ df->df_total_key_size = df->df_total_data_size = 0;
+ STAILQ_INIT(&df->df_entries);
+ df->df_hashfunc = hashfunc;
+ df->df_hashfunc_closure = hashfunc_closure;
+
+ *rdf = df;
+
+ return (0);
+}
+
+void
+_citrus_db_factory_free(struct _citrus_db_factory *df)
+{
+ struct _citrus_db_factory_entry *de;
+
+ while ((de = STAILQ_FIRST(&df->df_entries)) != NULL) {
+ STAILQ_REMOVE_HEAD(&df->df_entries, de_entry);
+ if (de->de_key_free)
+ free(_region_head(&de->de_key));
+ if (de->de_data_free)
+ free(_region_head(&de->de_data));
+ free(de);
+ }
+ free(df);
+}
+
+static __inline size_t
+ceilto(size_t sz)
+{
+ return ((sz + DB_ALIGN - 1) & ~(DB_ALIGN - 1));
+}
+
+int
+_citrus_db_factory_add(struct _citrus_db_factory *df, struct _region *key,
+ int keyfree, struct _region *data, int datafree)
+{
+ struct _citrus_db_factory_entry *de;
+
+ de = malloc(sizeof(*de));
+ if (de == NULL)
+ return (-1);
+
+ de->de_hashvalue = df->df_hashfunc(key);
+ de->de_key = *key;
+ de->de_key_free = keyfree;
+ de->de_data = *data;
+ de->de_data_free = datafree;
+ de->de_idx = -1;
+
+ STAILQ_INSERT_TAIL(&df->df_entries, de, de_entry);
+ df->df_total_key_size += _region_size(key);
+ df->df_total_data_size += ceilto(_region_size(data));
+ df->df_num_entries++;
+
+ return (0);
+
+}
+
+int
+_citrus_db_factory_add_by_string(struct _citrus_db_factory *df,
+ const char *key, struct _citrus_region *data, int datafree)
+{
+ struct _region r;
+ char *tmp;
+
+ tmp = strdup(key);
+ if (tmp == NULL)
+ return (errno);
+ _region_init(&r, tmp, strlen(key));
+ return _citrus_db_factory_add(df, &r, 1, data, datafree);
+}
+
+int
+_citrus_db_factory_add8_by_string(struct _citrus_db_factory *df,
+ const char *key, uint8_t val)
+{
+ struct _region r;
+ uint8_t *p;
+
+ p = malloc(sizeof(*p));
+ if (p == NULL)
+ return (errno);
+ *p = val;
+ _region_init(&r, p, 1);
+ return (_citrus_db_factory_add_by_string(df, key, &r, 1));
+}
+
+int
+_citrus_db_factory_add16_by_string(struct _citrus_db_factory *df,
+ const char *key, uint16_t val)
+{
+ struct _region r;
+ uint16_t *p;
+
+ p = malloc(sizeof(*p));
+ if (p == NULL)
+ return (errno);
+ *p = htons(val);
+ _region_init(&r, p, 2);
+ return (_citrus_db_factory_add_by_string(df, key, &r, 1));
+}
+
+int
+_citrus_db_factory_add32_by_string(struct _citrus_db_factory *df,
+ const char *key, uint32_t val)
+{
+ struct _region r;
+ uint32_t *p;
+
+ p = malloc(sizeof(*p));
+ if (p == NULL)
+ return (errno);
+ *p = htonl(val);
+ _region_init(&r, p, 4);
+ return (_citrus_db_factory_add_by_string(df, key, &r, 1));
+}
+
+int
+_citrus_db_factory_add_string_by_string(struct _citrus_db_factory *df,
+ const char *key, const char *data)
+{
+ char *p;
+ struct _region r;
+
+ p = strdup(data);
+ if (p == NULL)
+ return (errno);
+ _region_init(&r, p, strlen(p) + 1);
+ return (_citrus_db_factory_add_by_string(df, key, &r, 1));
+}
+
+size_t
+_citrus_db_factory_calc_size(struct _citrus_db_factory *df)
+{
+ size_t sz;
+
+ sz = ceilto(_CITRUS_DB_HEADER_SIZE);
+ sz += ceilto(_CITRUS_DB_ENTRY_SIZE * df->df_num_entries);
+ sz += ceilto(df->df_total_key_size);
+ sz += df->df_total_data_size;
+
+ return (sz);
+}
+
+static __inline void
+put8(struct _region *r, size_t *rofs, uint8_t val)
+{
+
+ *(uint8_t *)_region_offset(r, *rofs) = val;
+ *rofs += 1;
+}
+
+static __inline void
+put16(struct _region *r, size_t *rofs, uint16_t val)
+{
+
+ val = htons(val);
+ memcpy(_region_offset(r, *rofs), &val, 2);
+ *rofs += 2;
+}
+
+static __inline void
+put32(struct _region *r, size_t *rofs, uint32_t val)
+{
+
+ val = htonl(val);
+ memcpy(_region_offset(r, *rofs), &val, 4);
+ *rofs += 4;
+}
+
+static __inline void
+putpad(struct _region *r, size_t *rofs)
+{
+ size_t i;
+
+ for (i = ceilto(*rofs) - *rofs; i > 0; i--)
+ put8(r, rofs, 0);
+}
+
+static __inline void
+dump_header(struct _region *r, const char *magic, size_t *rofs,
+ size_t num_entries)
+{
+
+ while (*rofs<_CITRUS_DB_MAGIC_SIZE)
+ put8(r, rofs, *magic++);
+ put32(r, rofs, num_entries);
+ put32(r, rofs, _CITRUS_DB_HEADER_SIZE);
+}
+
+int
+_citrus_db_factory_serialize(struct _citrus_db_factory *df, const char *magic,
+ struct _region *r)
+{
+ struct _citrus_db_factory_entry *de, **depp, *det;
+ size_t dataofs, i, keyofs, nextofs, ofs;
+
+ ofs = 0;
+ /* check whether more than 0 entries exist */
+ if (df->df_num_entries == 0) {
+ dump_header(r, magic, &ofs, 0);
+ return (0);
+ }
+ /* allocate hash table */
+ depp = malloc(sizeof(*depp) * df->df_num_entries);
+ if (depp == NULL)
+ return (-1);
+ for (i = 0; i < df->df_num_entries; i++)
+ depp[i] = NULL;
+
+ /* step1: store the entries which are not conflicting */
+ STAILQ_FOREACH(de, &df->df_entries, de_entry) {
+ de->de_hashvalue %= df->df_num_entries;
+ de->de_idx = -1;
+ de->de_next = NULL;
+ if (depp[de->de_hashvalue] == NULL) {
+ depp[de->de_hashvalue] = de;
+ de->de_idx = (int)de->de_hashvalue;
+ }
+ }
+
+ /* step2: resolve conflicts */
+ i = 0;
+ STAILQ_FOREACH(de, &df->df_entries, de_entry) {
+ if (de->de_idx == -1) {
+ det = depp[de->de_hashvalue];
+ while (det->de_next != NULL)
+ det = det->de_next;
+ det->de_next = de;
+ while (depp[i] != NULL)
+ i++;
+ depp[i] = de;
+ de->de_idx = (int)i;
+ }
+ }
+
+ keyofs = _CITRUS_DB_HEADER_SIZE +
+ ceilto(df->df_num_entries*_CITRUS_DB_ENTRY_SIZE);
+ dataofs = keyofs + ceilto(df->df_total_key_size);
+
+ /* dump header */
+ dump_header(r, magic, &ofs, df->df_num_entries);
+
+ /* dump entries */
+ for (i = 0; i < df->df_num_entries; i++) {
+ de = depp[i];
+ nextofs = 0;
+ if (de->de_next) {
+ nextofs = _CITRUS_DB_HEADER_SIZE +
+ de->de_next->de_idx * _CITRUS_DB_ENTRY_SIZE;
+ }
+ put32(r, &ofs, de->de_hashvalue);
+ put32(r, &ofs, nextofs);
+ put32(r, &ofs, keyofs);
+ put32(r, &ofs, _region_size(&de->de_key));
+ put32(r, &ofs, dataofs);
+ put32(r, &ofs, _region_size(&de->de_data));
+ memcpy(_region_offset(r, keyofs),
+ _region_head(&de->de_key), _region_size(&de->de_key));
+ keyofs += _region_size(&de->de_key);
+ memcpy(_region_offset(r, dataofs),
+ _region_head(&de->de_data), _region_size(&de->de_data));
+ dataofs += _region_size(&de->de_data);
+ putpad(r, &dataofs);
+ }
+ putpad(r, &ofs);
+ putpad(r, &keyofs);
+ free(depp);
+
+ return (0);
+}
diff --git a/lib/libc/iconv/citrus_db_factory.h b/lib/libc/iconv/citrus_db_factory.h
new file mode 100644
index 0000000..b98b19c
--- /dev/null
+++ b/lib/libc/iconv/citrus_db_factory.h
@@ -0,0 +1,57 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_db_factory.h,v 1.3 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_DB_FACTORY_H_
+#define _CITRUS_DB_FACTORY_H_
+
+struct _citrus_db_factory;
+typedef uint32_t (*_citrus_db_hash_func_t)(struct _citrus_region *);
+
+__BEGIN_DECLS
+int _citrus_db_factory_create(struct _citrus_db_factory **,
+ _citrus_db_hash_func_t, void *);
+void _citrus_db_factory_free(struct _citrus_db_factory *);
+int _citrus_db_factory_add(struct _citrus_db_factory *,
+ struct _citrus_region *, int, struct _citrus_region *, int);
+int _citrus_db_factory_add_by_string(struct _citrus_db_factory *,
+ const char *, struct _citrus_region *, int);
+int _citrus_db_factory_add8_by_string(struct _citrus_db_factory *,
+ const char *, uint8_t);
+int _citrus_db_factory_add16_by_string(struct _citrus_db_factory *,
+ const char *, uint16_t);
+int _citrus_db_factory_add32_by_string(struct _citrus_db_factory *,
+ const char *, uint32_t);
+int _citrus_db_factory_add_string_by_string(struct _citrus_db_factory *,
+ const char *, const char *);
+size_t _citrus_db_factory_calc_size(struct _citrus_db_factory *);
+int _citrus_db_factory_serialize(struct _citrus_db_factory *,
+ const char *, struct _citrus_region *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_db_file.h b/lib/libc/iconv/citrus_db_file.h
new file mode 100644
index 0000000..aed07e8
--- /dev/null
+++ b/lib/libc/iconv/citrus_db_file.h
@@ -0,0 +1,85 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_db_file.h,v 1.4 2008/02/10 05:58:22 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_DB_FILE_H_
+#define _CITRUS_DB_FILE_H_
+
+/*
+ * db format:
+ * +---
+ * | header
+ * | - magic
+ * | - num entries
+ * +---
+ * | entry directory
+ * | +------------
+ * | | entry0
+ * | | - hash value
+ * | | - next entry
+ * | | - key offset
+ * | | - key len
+ * | | - data offset
+ * | | - data size
+ * | |---
+ * | | entry1
+ * | | ..
+ * | | entryN
+ * | +---
+ * +---
+ * | key table
+ * | - key0
+ * | ...
+ * | - keyN
+ * +---
+ * | data table
+ * | - data0
+ * | ...
+ * | - dataN
+ * +---
+ */
+
+#define _CITRUS_DB_MAGIC_SIZE 8
+#define _CITRUS_DB_HEADER_SIZE 16
+struct _citrus_db_header_x {
+ char dhx_magic[_CITRUS_DB_MAGIC_SIZE];
+ uint32_t dhx_num_entries;
+ uint32_t dhx_entry_offset;
+} __packed;
+
+struct _citrus_db_entry_x {
+ uint32_t dex_hash_value;
+ uint32_t dex_next_offset;
+ uint32_t dex_key_offset;
+ uint32_t dex_key_size;
+ uint32_t dex_data_offset;
+ uint32_t dex_data_size;
+} __packed;
+#define _CITRUS_DB_ENTRY_SIZE 24
+
+#endif
diff --git a/lib/libc/iconv/citrus_db_hash.c b/lib/libc/iconv/citrus_db_hash.c
new file mode 100644
index 0000000..2c599ff
--- /dev/null
+++ b/lib/libc/iconv/citrus_db_hash.c
@@ -0,0 +1,64 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_db_hash.c,v 1.5 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_db_hash.h"
+
+uint32_t
+_citrus_db_hash_std(struct _region *r)
+{
+ const uint8_t *p;
+ uint32_t hash, tmp;
+ size_t i;
+
+ hash = 0;
+ p = _region_head(r);
+
+ for (i = _region_size(r); i > 0; i--) {
+ hash <<= 4;
+ hash += _bcs_tolower(*p);
+ tmp = hash & 0xF0000000;
+ if (tmp != 0) {
+ hash ^= tmp;
+ hash ^= tmp >> 24;
+ }
+ p++;
+ }
+ return (hash);
+}
diff --git a/lib/libc/iconv/citrus_db_hash.h b/lib/libc/iconv/citrus_db_hash.h
new file mode 100644
index 0000000..549af26
--- /dev/null
+++ b/lib/libc/iconv/citrus_db_hash.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_db_hash.h,v 1.2 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_DB_HASH_H_
+#define _CITRUS_DB_HASH_H_
+
+__BEGIN_DECLS
+uint32_t _citrus_db_hash_std(struct _citrus_region *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_esdb.c b/lib/libc/iconv/citrus_esdb.c
new file mode 100644
index 0000000..578cbc1
--- /dev/null
+++ b/lib/libc/iconv/citrus_esdb.c
@@ -0,0 +1,374 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_esdb.c,v 1.5 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_lookup.h"
+#include "citrus_db.h"
+#include "citrus_db_hash.h"
+#include "citrus_esdb.h"
+#include "citrus_esdb_file.h"
+
+#define ESDB_DIR "esdb.dir"
+#define ESDB_ALIAS "esdb.alias"
+
+/*
+ * _citrus_esdb_alias:
+ * resolve encoding scheme name aliases.
+ */
+const char *
+_citrus_esdb_alias(const char *esname, char *buf, size_t bufsize)
+{
+
+ return (_lookup_alias(_PATH_ESDB "/" ESDB_ALIAS, esname, buf, bufsize,
+ _LOOKUP_CASE_IGNORE));
+}
+
+
+/*
+ * conv_esdb:
+ * external representation -> local structure.
+ */
+static int
+conv_esdb(struct _citrus_esdb *esdb, struct _region *fr)
+{
+ struct _citrus_db *db;
+ const char *str;
+ char buf[100];
+ uint32_t csid, i, num_charsets, tmp, version;
+ int ret;
+
+ /* open db */
+ ret = _db_open(&db, fr, _CITRUS_ESDB_MAGIC, &_db_hash_std, NULL);
+ if (ret)
+ goto err0;
+
+ /* check version */
+ ret = _db_lookup32_by_s(db, _CITRUS_ESDB_SYM_VERSION, &version, NULL);
+ if (ret)
+ goto err1;
+ switch (version) {
+ case 0x00000001:
+ /* current version */
+ /* initial version */
+ break;
+ default:
+ ret = EFTYPE;
+ goto err1;
+ }
+
+ /* get encoding/variable */
+ ret = _db_lookupstr_by_s(db, _CITRUS_ESDB_SYM_ENCODING, &str, NULL);
+ if (ret)
+ goto err1;
+ esdb->db_encname = strdup(str);
+ if (esdb->db_encname == NULL) {
+ ret = errno;
+ goto err1;
+ }
+
+ esdb->db_len_variable = 0;
+ esdb->db_variable = NULL;
+ ret = _db_lookupstr_by_s(db, _CITRUS_ESDB_SYM_VARIABLE, &str, NULL);
+ if (ret == 0) {
+ esdb->db_len_variable = strlen(str) + 1;
+ esdb->db_variable = strdup(str);
+ if (esdb->db_variable == NULL) {
+ ret = errno;
+ goto err2;
+ }
+ } else if (ret != ENOENT)
+ goto err2;
+
+ /* get number of charsets */
+ ret = _db_lookup32_by_s(db, _CITRUS_ESDB_SYM_NUM_CHARSETS,
+ &num_charsets, NULL);
+ if (ret)
+ goto err3;
+ esdb->db_num_charsets = num_charsets;
+
+ /* get invalid character */
+ ret = _db_lookup32_by_s(db, _CITRUS_ESDB_SYM_INVALID, &tmp, NULL);
+ if (ret == 0) {
+ esdb->db_use_invalid = 1;
+ esdb->db_invalid = tmp;
+ } else if (ret == ENOENT)
+ esdb->db_use_invalid = 0;
+ else
+ goto err3;
+
+ /* get charsets */
+ esdb->db_charsets = malloc(num_charsets * sizeof(*esdb->db_charsets));
+ if (esdb->db_charsets == NULL) {
+ ret = errno;
+ goto err3;
+ }
+ for (i = 0; i < num_charsets; i++) {
+ snprintf(buf, sizeof(buf),
+ _CITRUS_ESDB_SYM_CSID_PREFIX "%d", i);
+ ret = _db_lookup32_by_s(db, buf, &csid, NULL);
+ if (ret)
+ goto err4;
+ esdb->db_charsets[i].ec_csid = csid;
+
+ snprintf(buf, sizeof(buf),
+ _CITRUS_ESDB_SYM_CSNAME_PREFIX "%d", i);
+ ret = _db_lookupstr_by_s(db, buf, &str, NULL);
+ if (ret)
+ goto err4;
+ esdb->db_charsets[i].ec_csname = strdup(str);
+ if (esdb->db_charsets[i].ec_csname == NULL) {
+ ret = errno;
+ goto err4;
+ }
+ }
+
+ _db_close(db);
+ return (0);
+
+err4:
+ for (; i > 0; i--)
+ free(esdb->db_charsets[i - 1].ec_csname);
+ free(esdb->db_charsets);
+err3:
+ free(esdb->db_variable);
+err2:
+ free(esdb->db_encname);
+err1:
+ _db_close(db);
+ if (ret == ENOENT)
+ ret = EFTYPE;
+err0:
+ return (ret);
+}
+
+/*
+ * _citrus_esdb_open:
+ * open an ESDB file.
+ */
+int
+_citrus_esdb_open(struct _citrus_esdb *db, const char *esname)
+{
+ struct _region fr;
+ const char *realname, *encfile;
+ char buf1[PATH_MAX], buf2[PATH_MAX], path[PATH_MAX];
+ int ret;
+
+ snprintf(path, sizeof(path), "%s/%s", _PATH_ESDB, ESDB_ALIAS);
+ realname = _lookup_alias(path, esname, buf1, sizeof(buf1),
+ _LOOKUP_CASE_IGNORE);
+
+ snprintf(path, sizeof(path), "%s/%s", _PATH_ESDB, ESDB_DIR);
+ encfile = _lookup_simple(path, realname, buf2, sizeof(buf2),
+ _LOOKUP_CASE_IGNORE);
+ if (encfile == NULL)
+ return (ENOENT);
+
+ /* open file */
+ snprintf(path, sizeof(path), "%s/%s", _PATH_ESDB, encfile);
+ ret = _map_file(&fr, path);
+ if (ret)
+ return (ret);
+
+ ret = conv_esdb(db, &fr);
+
+ _unmap_file(&fr);
+
+ return (ret);
+}
+
+/*
+ * _citrus_esdb_close:
+ * free an ESDB.
+ */
+void
+_citrus_esdb_close(struct _citrus_esdb *db)
+{
+
+ for (int i = 0; i < db->db_num_charsets; i++)
+ free(db->db_charsets[i].ec_csname);
+ db->db_num_charsets = 0;
+ free(db->db_charsets); db->db_charsets = NULL;
+ free(db->db_encname); db->db_encname = NULL;
+ db->db_len_variable = 0;
+ free(db->db_variable); db->db_variable = NULL;
+}
+
+/*
+ * _citrus_esdb_free_list:
+ * free the list.
+ */
+void
+_citrus_esdb_free_list(char **list, size_t num)
+{
+
+ for (size_t i = 0; i < num; i++)
+ free(list[i]);
+ free(list);
+}
+
+/*
+ * _citrus_esdb_get_list:
+ * get esdb entries.
+ */
+int
+_citrus_esdb_get_list(char ***rlist, size_t *rnum, bool sorted)
+{
+ struct _citrus_lookup *cla, *cld;
+ struct _region key, data;
+ char **list, **q;
+ char buf[PATH_MAX];
+ size_t num;
+ int ret;
+
+ num = 0;
+
+ ret = _lookup_seq_open(&cla, _PATH_ESDB "/" ESDB_ALIAS,
+ _LOOKUP_CASE_IGNORE);
+ if (ret)
+ goto quit0;
+
+ ret = _lookup_seq_open(&cld, _PATH_ESDB "/" ESDB_DIR,
+ _LOOKUP_CASE_IGNORE);
+ if (ret)
+ goto quit1;
+
+ /* count number of entries */
+ num = _lookup_get_num_entries(cla) + _lookup_get_num_entries(cld);
+
+ _lookup_seq_rewind(cla);
+ _lookup_seq_rewind(cld);
+
+ /* allocate list pointer space */
+ list = malloc(num * sizeof(char *));
+ num = 0;
+ if (list == NULL) {
+ ret = errno;
+ goto quit3;
+ }
+
+ /* get alias entries */
+ while ((ret = _lookup_seq_next(cla, &key, &data)) == 0) {
+ if (sorted)
+ snprintf(buf, sizeof(buf), "%.*s/%.*s",
+ (int)_region_size(&data),
+ (const char *)_region_head(&data),
+ (int)_region_size(&key),
+ (const char *)_region_head(&key));
+ else
+ snprintf(buf, sizeof(buf), "%.*s/%.*s",
+ (int)_region_size(&data),
+ (const char *)_region_head(&data),
+ (int)_region_size(&key),
+ (const char *)_region_head(&key));
+ _bcs_convert_to_upper(buf);
+ list[num] = strdup(buf);
+ if (list[num] == NULL) {
+ ret = errno;
+ goto quit3;
+ }
+ num++;
+ }
+ if (ret != ENOENT)
+ goto quit3;
+ /* get dir entries */
+ while ((ret = _lookup_seq_next(cld, &key, &data)) == 0) {
+ if (!sorted)
+ snprintf(buf, sizeof(buf), "%.*s",
+ (int)_region_size(&key),
+ (const char *)_region_head(&key));
+ else {
+ /* check duplicated entry */
+ char *p;
+ char buf1[PATH_MAX];
+
+ snprintf(buf1, sizeof(buf1), "%.*s",
+ (int)_region_size(&data),
+ (const char *)_region_head(&data));
+ if ((p = strchr(buf1, '/')) != NULL)
+ memcpy(buf1, p + 1, strlen(p) - 1);
+ if ((p = strstr(buf1, ".esdb")) != NULL)
+ *p = '\0';
+ snprintf(buf, sizeof(buf), "%s/%.*s", buf1,
+ (int)_region_size(&key),
+ (const char *)_region_head(&key));
+ }
+ _bcs_convert_to_upper(buf);
+ ret = _lookup_seq_lookup(cla, buf, NULL);
+ if (ret) {
+ if (ret != ENOENT)
+ goto quit3;
+ /* not duplicated */
+ list[num] = strdup(buf);
+ if (list[num] == NULL) {
+ ret = errno;
+ goto quit3;
+ }
+ num++;
+ }
+ }
+ if (ret != ENOENT)
+ goto quit3;
+
+ ret = 0;
+ /* XXX: why reallocing the list space posteriorly?
+ shouldn't be done earlier? */
+ q = realloc(list, num * sizeof(char *));
+ if (!q) {
+ ret = ENOMEM;
+ goto quit3;
+ }
+ list = q;
+ *rlist = list;
+ *rnum = num;
+quit3:
+ if (ret)
+ _citrus_esdb_free_list(list, num);
+ _lookup_seq_close(cld);
+quit1:
+ _lookup_seq_close(cla);
+quit0:
+ return (ret);
+}
diff --git a/lib/libc/iconv/citrus_esdb.h b/lib/libc/iconv/citrus_esdb.h
new file mode 100644
index 0000000..f82a398
--- /dev/null
+++ b/lib/libc/iconv/citrus_esdb.h
@@ -0,0 +1,58 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_esdb.h,v 1.1 2003/06/25 09:51:32 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ESDB_H_
+#define _CITRUS_ESDB_H_
+
+#include "citrus_types.h"
+
+struct _citrus_esdb_charset {
+ _citrus_csid_t ec_csid;
+ char *ec_csname;
+};
+
+struct _citrus_esdb {
+ char *db_encname;
+ void *db_variable;
+ size_t db_len_variable;
+ int db_num_charsets;
+ struct _citrus_esdb_charset *db_charsets;
+ int db_use_invalid;
+ _citrus_wc_t db_invalid;
+};
+
+__BEGIN_DECLS
+const char *_citrus_esdb_alias(const char *, char *, size_t);
+int _citrus_esdb_open(struct _citrus_esdb *, const char *);
+void _citrus_esdb_close(struct _citrus_esdb *);
+void _citrus_esdb_free_list(char **, size_t);
+int _citrus_esdb_get_list(char ***, size_t *, bool);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_esdb_file.h b/lib/libc/iconv/citrus_esdb_file.h
new file mode 100644
index 0000000..98609d1
--- /dev/null
+++ b/lib/libc/iconv/citrus_esdb_file.h
@@ -0,0 +1,45 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_esdb_file.h,v 1.1 2003/06/25 09:51:32 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ESDB_FILE_H_
+#define _CITRUS_ESDB_FILE_H_
+
+#define _CITRUS_ESDB_MAGIC "ESDB\0\0\0\0"
+
+#define _CITRUS_ESDB_SYM_VERSION "version"
+#define _CITRUS_ESDB_SYM_ENCODING "encoding"
+#define _CITRUS_ESDB_SYM_VARIABLE "variable"
+#define _CITRUS_ESDB_SYM_NUM_CHARSETS "num_charsets"
+#define _CITRUS_ESDB_SYM_INVALID "invalid"
+#define _CITRUS_ESDB_SYM_CSNAME_PREFIX "csname_"
+#define _CITRUS_ESDB_SYM_CSID_PREFIX "csid_"
+
+#define _CITRUS_ESDB_VERSION 0x00000001
+
+#endif
diff --git a/lib/libc/iconv/citrus_fix_grouping.h b/lib/libc/iconv/citrus_fix_grouping.h
new file mode 100644
index 0000000..fbb1788
--- /dev/null
+++ b/lib/libc/iconv/citrus_fix_grouping.h
@@ -0,0 +1,53 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_fix_grouping.h,v 1.2 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c)2008 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_FIX_GROUPING_H_
+#define _CITRUS_FIX_GROUPING_H_
+
+#define _CITRUS_LC_GROUPING_VALUE_MIN 0
+#define _CITRUS_LC_GROUPING_VALUE_MAX 126
+#define _CITRUS_LC_GROUPING_VALUE_NO_FUTHER 127
+
+#if CHAR_MAX != _CITRUS_LC_GROUPING_VALUE_NO_FUTHER
+static __inline void
+_citrus_fixup_char_max_md(char *grouping)
+{
+ char *p;
+
+ for (p = grouping; *p != '\0'; ++p)
+ if (*p == _CITRUS_LC_GROUPING_VALUE_NO_FUTHER)
+ *p = (char)CHAR_MAX;
+}
+#define _CITRUS_FIXUP_CHAR_MAX_MD(grouping) \
+ _citrus_fixup_char_max_md(__DECONST(void *, grouping))
+#else
+#define _CITRUS_FIXUP_CHAR_MAX_MD(grouping) /* nothing to do */
+#endif
+
+#endif /*_CITRUS_FIX_GROUPING_H_*/
diff --git a/lib/libc/iconv/citrus_hash.c b/lib/libc/iconv/citrus_hash.c
new file mode 100644
index 0000000..4db1bda
--- /dev/null
+++ b/lib/libc/iconv/citrus_hash.c
@@ -0,0 +1,51 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_hash.c,v 1.3 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_region.h"
+#include "citrus_hash.h"
+#include "citrus_db_hash.h"
+
+int
+_citrus_string_hash_func(const char *key, int hashsize)
+{
+ struct _region r;
+
+ _region_init(&r, __DECONST(void *, key), strlen(key));
+
+ return ((int)(_db_hash_std(&r) % (uint32_t)hashsize));
+}
diff --git a/lib/libc/iconv/citrus_hash.h b/lib/libc/iconv/citrus_hash.h
new file mode 100644
index 0000000..c3e7311
--- /dev/null
+++ b/lib/libc/iconv/citrus_hash.h
@@ -0,0 +1,59 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_hash.h,v 1.3 2004/01/02 21:49:35 itojun Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_HASH_H_
+#define _CITRUS_HASH_H_
+
+#define _CITRUS_HASH_ENTRY(type) LIST_ENTRY(type)
+#define _CITRUS_HASH_HEAD(headname, type, hashsize) \
+struct headname { \
+ LIST_HEAD(, type) chh_table[hashsize]; \
+}
+#define _CITRUS_HASH_INIT(head, hashsize) \
+do { \
+ int _ch_loop; \
+ \
+ for (_ch_loop = 0; _ch_loop < hashsize; _ch_loop++) \
+ LIST_INIT(&(head)->chh_table[_ch_loop]); \
+} while (0)
+#define _CITRUS_HASH_REMOVE(elm, field) LIST_REMOVE(elm, field)
+#define _CITRUS_HASH_INSERT(head, elm, field, hashval) \
+ LIST_INSERT_HEAD(&(head)->chh_table[hashval], elm, field)
+#define _CITRUS_HASH_SEARCH(head, elm, field, matchfunc, key, hashval) \
+do { \
+ LIST_FOREACH((elm), &(head)->chh_table[hashval], field) \
+ if (matchfunc((elm), key) == 0) \
+ break; \
+} while (0)
+
+__BEGIN_DECLS
+int _citrus_string_hash_func(const char *, int);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_iconv.c b/lib/libc/iconv/citrus_iconv.c
new file mode 100644
index 0000000..941ee02
--- /dev/null
+++ b/lib/libc/iconv/citrus_iconv.c
@@ -0,0 +1,335 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_iconv.c,v 1.7 2008/07/25 14:05:25 christos Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <iconv.h>
+#include <langinfo.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_esdb.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_module.h"
+#include "citrus_lock.h"
+#include "citrus_lookup.h"
+#include "citrus_hash.h"
+#include "citrus_iconv.h"
+
+#define _CITRUS_ICONV_DIR "iconv.dir"
+#define _CITRUS_ICONV_ALIAS "iconv.alias"
+
+#define CI_HASH_SIZE 101
+#define CI_INITIAL_MAX_REUSE 5
+#define CI_ENV_MAX_REUSE "ICONV_MAX_REUSE"
+
+static bool isinit = false;
+static int shared_max_reuse, shared_num_unused;
+static _CITRUS_HASH_HEAD(, _citrus_iconv_shared, CI_HASH_SIZE) shared_pool;
+static TAILQ_HEAD(, _citrus_iconv_shared) shared_unused;
+
+static __inline void
+init_cache(void)
+{
+
+ WLOCK;
+ if (!isinit) {
+ _CITRUS_HASH_INIT(&shared_pool, CI_HASH_SIZE);
+ TAILQ_INIT(&shared_unused);
+ shared_max_reuse = -1;
+ if (!issetugid() && getenv(CI_ENV_MAX_REUSE))
+ shared_max_reuse = atoi(getenv(CI_ENV_MAX_REUSE));
+ if (shared_max_reuse < 0)
+ shared_max_reuse = CI_INITIAL_MAX_REUSE;
+ isinit = true;
+ }
+ UNLOCK;
+}
+
+static __inline void
+close_shared(struct _citrus_iconv_shared *ci)
+{
+
+ if (ci) {
+ if (ci->ci_module) {
+ if (ci->ci_ops) {
+ if (ci->ci_closure)
+ (*ci->ci_ops->io_uninit_shared)(ci);
+ free(ci->ci_ops);
+ }
+ _citrus_unload_module(ci->ci_module);
+ }
+ free(ci);
+ }
+}
+
+static __inline int
+open_shared(struct _citrus_iconv_shared * __restrict * __restrict rci,
+ const char * __restrict convname, const char * __restrict src,
+ const char * __restrict dst)
+{
+ struct _citrus_iconv_shared *ci;
+ _citrus_iconv_getops_t getops;
+ const char *module;
+ size_t len_convname;
+ int ret;
+
+ module = (strcmp(src, dst) != 0) ? "iconv_std" : "iconv_none";
+
+ /* initialize iconv handle */
+ len_convname = strlen(convname);
+ ci = malloc(sizeof(*ci) + len_convname + 1);
+ if (!ci) {
+ ret = errno;
+ goto err;
+ }
+ ci->ci_module = NULL;
+ ci->ci_ops = NULL;
+ ci->ci_closure = NULL;
+ ci->ci_convname = (void *)&ci[1];
+ memcpy(ci->ci_convname, convname, len_convname + 1);
+
+ /* load module */
+ ret = _citrus_load_module(&ci->ci_module, module);
+ if (ret)
+ goto err;
+
+ /* get operators */
+ getops = (_citrus_iconv_getops_t)_citrus_find_getops(ci->ci_module,
+ module, "iconv");
+ if (!getops) {
+ ret = EOPNOTSUPP;
+ goto err;
+ }
+ ci->ci_ops = malloc(sizeof(*ci->ci_ops));
+ if (!ci->ci_ops) {
+ ret = errno;
+ goto err;
+ }
+ ret = (*getops)(ci->ci_ops);
+ if (ret)
+ goto err;
+
+ if (ci->ci_ops->io_init_shared == NULL ||
+ ci->ci_ops->io_uninit_shared == NULL ||
+ ci->ci_ops->io_init_context == NULL ||
+ ci->ci_ops->io_uninit_context == NULL ||
+ ci->ci_ops->io_convert == NULL)
+ goto err;
+
+ /* initialize the converter */
+ ret = (*ci->ci_ops->io_init_shared)(ci, src, dst);
+ if (ret)
+ goto err;
+
+ *rci = ci;
+
+ return (0);
+err:
+ close_shared(ci);
+ return (ret);
+}
+
+static __inline int
+hash_func(const char *key)
+{
+
+ return (_string_hash_func(key, CI_HASH_SIZE));
+}
+
+static __inline int
+match_func(struct _citrus_iconv_shared * __restrict ci,
+ const char * __restrict key)
+{
+
+ return (strcmp(ci->ci_convname, key));
+}
+
+static int
+get_shared(struct _citrus_iconv_shared * __restrict * __restrict rci,
+ const char *src, const char *dst)
+{
+ struct _citrus_iconv_shared * ci;
+ char convname[PATH_MAX];
+ int hashval, ret = 0;
+
+ snprintf(convname, sizeof(convname), "%s/%s", src, dst);
+
+ WLOCK;
+
+ /* lookup alread existing entry */
+ hashval = hash_func(convname);
+ _CITRUS_HASH_SEARCH(&shared_pool, ci, ci_hash_entry, match_func,
+ convname, hashval);
+ if (ci != NULL) {
+ /* found */
+ if (ci->ci_used_count == 0) {
+ TAILQ_REMOVE(&shared_unused, ci, ci_tailq_entry);
+ shared_num_unused--;
+ }
+ ci->ci_used_count++;
+ *rci = ci;
+ goto quit;
+ }
+
+ /* create new entry */
+ ret = open_shared(&ci, convname, src, dst);
+ if (ret)
+ goto quit;
+
+ _CITRUS_HASH_INSERT(&shared_pool, ci, ci_hash_entry, hashval);
+ ci->ci_used_count = 1;
+ *rci = ci;
+
+quit:
+ UNLOCK;
+
+ return (ret);
+}
+
+static void
+release_shared(struct _citrus_iconv_shared * __restrict ci)
+{
+
+ WLOCK;
+ ci->ci_used_count--;
+ if (ci->ci_used_count == 0) {
+ /* put it into unused list */
+ shared_num_unused++;
+ TAILQ_INSERT_TAIL(&shared_unused, ci, ci_tailq_entry);
+ /* flood out */
+ while (shared_num_unused > shared_max_reuse) {
+ ci = TAILQ_FIRST(&shared_unused);
+ TAILQ_REMOVE(&shared_unused, ci, ci_tailq_entry);
+ _CITRUS_HASH_REMOVE(ci, ci_hash_entry);
+ shared_num_unused--;
+ close_shared(ci);
+ }
+ }
+
+ UNLOCK;
+}
+
+/*
+ * _citrus_iconv_open:
+ * open a converter for the specified in/out codes.
+ */
+int
+_citrus_iconv_open(struct _citrus_iconv * __restrict * __restrict rcv,
+ const char * __restrict src, const char * __restrict dst)
+{
+ struct _citrus_iconv *cv;
+ struct _citrus_iconv_shared *ci = NULL;
+ char realdst[PATH_MAX], realsrc[PATH_MAX];
+ char buf[PATH_MAX], path[PATH_MAX];
+ int ret;
+
+ init_cache();
+
+ /* GNU behaviour, using locale encoding if "" or "char" is specified */
+ if ((strcmp(src, "") == 0) || (strcmp(src, "char") == 0))
+ src = nl_langinfo(CODESET);
+ if ((strcmp(dst, "") == 0) || (strcmp(dst, "char") == 0))
+ dst = nl_langinfo(CODESET);
+
+ /* resolve codeset name aliases */
+ strlcpy(realsrc, _lookup_alias(path, src, buf, (size_t)PATH_MAX,
+ _LOOKUP_CASE_IGNORE), (size_t)PATH_MAX);
+ strlcpy(realdst, _lookup_alias(path, dst, buf, (size_t)PATH_MAX,
+ _LOOKUP_CASE_IGNORE), (size_t)PATH_MAX);
+
+ /* sanity check */
+ if (strchr(realsrc, '/') != NULL || strchr(realdst, '/'))
+ return (EINVAL);
+
+ /* get shared record */
+ ret = get_shared(&ci, realsrc, realdst);
+ if (ret)
+ return (ret);
+
+ /* create/init context */
+ if (*rcv == NULL) {
+ cv = malloc(sizeof(*cv));
+ if (cv == NULL) {
+ ret = errno;
+ release_shared(ci);
+ return (ret);
+ }
+ *rcv = cv;
+ }
+ (*rcv)->cv_shared = ci;
+ ret = (*ci->ci_ops->io_init_context)(*rcv);
+ if (ret) {
+ release_shared(ci);
+ free(*rcv);
+ return (ret);
+ }
+ return (0);
+}
+
+/*
+ * _citrus_iconv_close:
+ * close the specified converter.
+ */
+void
+_citrus_iconv_close(struct _citrus_iconv *cv)
+{
+
+ if (cv) {
+ (*cv->cv_shared->ci_ops->io_uninit_context)(cv);
+ release_shared(cv->cv_shared);
+ free(cv);
+ }
+}
+
+const char
+*_citrus_iconv_canonicalize(const char *name)
+{
+ char *buf;
+
+ if ((buf = malloc((size_t)PATH_MAX)) == NULL)
+ return (NULL);
+ memset((void *)buf, 0, (size_t)PATH_MAX);
+ _citrus_esdb_alias(name, buf, (size_t)PATH_MAX);
+ return (buf);
+}
diff --git a/lib/libc/iconv/citrus_iconv.h b/lib/libc/iconv/citrus_iconv.h
new file mode 100644
index 0000000..99604e9
--- /dev/null
+++ b/lib/libc/iconv/citrus_iconv.h
@@ -0,0 +1,64 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_iconv.h,v 1.5 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ICONV_H_
+#define _CITRUS_ICONV_H_
+
+struct _citrus_iconv_shared;
+struct _citrus_iconv_ops;
+struct _citrus_iconv;
+
+__BEGIN_DECLS
+int _citrus_iconv_open(struct _citrus_iconv * __restrict * __restrict,
+ const char * __restrict, const char * __restrict);
+void _citrus_iconv_close(struct _citrus_iconv *);
+const char *_citrus_iconv_canonicalize(const char *);
+__END_DECLS
+
+
+#include "citrus_iconv_local.h"
+
+#define _CITRUS_ICONV_F_HIDE_INVALID 0x0001
+
+/*
+ * _citrus_iconv_convert:
+ * convert a string.
+ */
+static __inline int
+_citrus_iconv_convert(struct _citrus_iconv * __restrict cv,
+ char * __restrict * __restrict in, size_t * __restrict inbytes,
+ char * __restrict * __restrict out, size_t * __restrict outbytes,
+ uint32_t flags, size_t * __restrict nresults)
+{
+
+ return (*cv->cv_shared->ci_ops->io_convert)(cv, in, inbytes, out,
+ outbytes, flags, nresults);
+}
+
+#endif
diff --git a/lib/libc/iconv/citrus_iconv_local.h b/lib/libc/iconv/citrus_iconv_local.h
new file mode 100644
index 0000000..db20363
--- /dev/null
+++ b/lib/libc/iconv/citrus_iconv_local.h
@@ -0,0 +1,107 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_iconv_local.h,v 1.3 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_ICONV_LOCAL_H_
+#define _CITRUS_ICONV_LOCAL_H_
+
+#include <iconv.h>
+
+#define _CITRUS_ICONV_GETOPS_FUNC_BASE(_n_) \
+ int _n_(struct _citrus_iconv_ops *)
+#define _CITRUS_ICONV_GETOPS_FUNC(_n_) \
+ _CITRUS_ICONV_GETOPS_FUNC_BASE(_citrus_##_n_##_iconv_getops)
+
+#define _CITRUS_ICONV_DECLS(_m_) \
+static int _citrus_##_m_##_iconv_init_shared \
+ (struct _citrus_iconv_shared * __restrict, \
+ const char * __restrict, const char * __restrict); \
+static void _citrus_##_m_##_iconv_uninit_shared \
+ (struct _citrus_iconv_shared *); \
+static int _citrus_##_m_##_iconv_convert \
+ (struct _citrus_iconv * __restrict, \
+ char * __restrict * __restrict, \
+ size_t * __restrict, \
+ char * __restrict * __restrict, \
+ size_t * __restrict outbytes, \
+ uint32_t, size_t * __restrict); \
+static int _citrus_##_m_##_iconv_init_context \
+ (struct _citrus_iconv *); \
+static void _citrus_##_m_##_iconv_uninit_context \
+ (struct _citrus_iconv *)
+
+
+#define _CITRUS_ICONV_DEF_OPS(_m_) \
+struct _citrus_iconv_ops _citrus_##_m_##_iconv_ops = { \
+ /* io_init_shared */ &_citrus_##_m_##_iconv_init_shared, \
+ /* io_uninit_shared */ &_citrus_##_m_##_iconv_uninit_shared, \
+ /* io_init_context */ &_citrus_##_m_##_iconv_init_context, \
+ /* io_uninit_context */ &_citrus_##_m_##_iconv_uninit_context, \
+ /* io_convert */ &_citrus_##_m_##_iconv_convert \
+}
+
+typedef _CITRUS_ICONV_GETOPS_FUNC_BASE((*_citrus_iconv_getops_t));
+typedef int (*_citrus_iconv_init_shared_t)
+ (struct _citrus_iconv_shared * __restrict,
+ const char * __restrict, const char * __restrict);
+typedef void (*_citrus_iconv_uninit_shared_t)
+ (struct _citrus_iconv_shared *);
+typedef int (*_citrus_iconv_convert_t)
+ (struct _citrus_iconv * __restrict,
+ char *__restrict* __restrict, size_t * __restrict,
+ char * __restrict * __restrict, size_t * __restrict, uint32_t,
+ size_t * __restrict);
+typedef int (*_citrus_iconv_init_context_t)(struct _citrus_iconv *);
+typedef void (*_citrus_iconv_uninit_context_t)(struct _citrus_iconv *);
+
+struct _citrus_iconv_ops {
+ _citrus_iconv_init_shared_t io_init_shared;
+ _citrus_iconv_uninit_shared_t io_uninit_shared;
+ _citrus_iconv_init_context_t io_init_context;
+ _citrus_iconv_uninit_context_t io_uninit_context;
+ _citrus_iconv_convert_t io_convert;
+};
+
+struct _citrus_iconv_shared {
+ struct _citrus_iconv_ops *ci_ops;
+ void *ci_closure;
+ _CITRUS_HASH_ENTRY(_citrus_iconv_shared) ci_hash_entry;
+ TAILQ_ENTRY(_citrus_iconv_shared) ci_tailq_entry;
+ _citrus_module_t ci_module;
+ unsigned int ci_used_count;
+ char *ci_convname;
+ bool ci_discard_ilseq;
+ struct iconv_hooks *ci_hooks;
+};
+
+struct _citrus_iconv {
+ struct _citrus_iconv_shared *cv_shared;
+ void *cv_closure;
+};
+
+#endif
diff --git a/lib/libc/iconv/citrus_lock.h b/lib/libc/iconv/citrus_lock.h
new file mode 100644
index 0000000..ad9443a
--- /dev/null
+++ b/lib/libc/iconv/citrus_lock.h
@@ -0,0 +1,35 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (C) 2010 Gabor Kovesdan <gabor@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <pthread.h>
+
+static pthread_rwlock_t lock;
+
+#define WLOCK if (__isthreaded) \
+ pthread_rwlock_wrlock(&lock);
+#define UNLOCK if (__isthreaded) \
+ pthread_rwlock_unlock(&lock);
diff --git a/lib/libc/iconv/citrus_lookup.c b/lib/libc/iconv/citrus_lookup.c
new file mode 100644
index 0000000..09b1298
--- /dev/null
+++ b/lib/libc/iconv/citrus_lookup.c
@@ -0,0 +1,362 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_lookup.c,v 1.6 2009/02/03 04:58:38 lukem Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_mmap.h"
+#include "citrus_db.h"
+#include "citrus_db_hash.h"
+#include "citrus_lookup.h"
+#include "citrus_lookup_file.h"
+
+struct _citrus_lookup {
+ union {
+ struct {
+ struct _citrus_db *db;
+ struct _citrus_region file;
+ int num, idx;
+ struct _db_locator locator;
+ } db;
+ struct {
+ struct _region r;
+ struct _memstream ms;
+ } plain;
+ } u;
+#define cl_db u.db.db
+#define cl_dbidx u.db.idx
+#define cl_dbfile u.db.file
+#define cl_dbnum u.db.num
+#define cl_dblocator u.db.locator
+#define cl_plainr u.plain.r
+#define cl_plainms u.plain.ms
+ int cl_ignore_case;
+ int cl_rewind;
+ char *cl_key;
+ size_t cl_keylen;
+ int (*cl_next)(struct _citrus_lookup *, struct _region *,
+ struct _region *);
+ int (*cl_lookup)(struct _citrus_lookup *, const char *,
+ struct _region *);
+ int (*cl_num_entries)(struct _citrus_lookup *);
+ void (*cl_close)(struct _citrus_lookup *);
+};
+
+static int
+seq_get_num_entries_db(struct _citrus_lookup *cl)
+{
+
+ return (cl->cl_dbnum);
+}
+
+static int
+seq_next_db(struct _citrus_lookup *cl, struct _region *key,
+ struct _region *data)
+{
+
+ if (cl->cl_key) {
+ if (key)
+ _region_init(key, cl->cl_key, cl->cl_keylen);
+ return (_db_lookup_by_s(cl->cl_db, cl->cl_key, data,
+ &cl->cl_dblocator));
+ }
+
+ if (cl->cl_rewind) {
+ cl->cl_dbidx = 0;
+ }
+ cl->cl_rewind = 0;
+ if (cl->cl_dbidx >= cl->cl_dbnum)
+ return (ENOENT);
+
+ return (_db_get_entry(cl->cl_db, cl->cl_dbidx++, key, data));
+}
+
+static int
+seq_lookup_db(struct _citrus_lookup *cl, const char *key, struct _region *data)
+{
+
+ cl->cl_rewind = 0;
+ free(cl->cl_key);
+ cl->cl_key = strdup(key);
+ if (cl->cl_ignore_case)
+ _bcs_convert_to_lower(cl->cl_key);
+ cl->cl_keylen = strlen(cl->cl_key);
+ _db_locator_init(&cl->cl_dblocator);
+ return (_db_lookup_by_s(cl->cl_db, cl->cl_key, data,
+ &cl->cl_dblocator));
+}
+
+static void
+seq_close_db(struct _citrus_lookup *cl)
+{
+
+ _db_close(cl->cl_db);
+ _unmap_file(&cl->cl_dbfile);
+}
+
+static int
+seq_open_db(struct _citrus_lookup *cl, const char *name)
+{
+ struct _region r;
+ char path[PATH_MAX];
+ int ret;
+
+ snprintf(path, sizeof(path), "%s.db", name);
+ ret = _map_file(&r, path);
+ if (ret)
+ return (ret);
+
+ ret = _db_open(&cl->cl_db, &r, _CITRUS_LOOKUP_MAGIC,
+ _db_hash_std, NULL);
+ if (ret) {
+ _unmap_file(&r);
+ return (ret);
+ }
+
+ cl->cl_dbfile = r;
+ cl->cl_dbnum = _db_get_num_entries(cl->cl_db);
+ cl->cl_dbidx = 0;
+ cl->cl_rewind = 1;
+ cl->cl_lookup = &seq_lookup_db;
+ cl->cl_next = &seq_next_db;
+ cl->cl_num_entries = &seq_get_num_entries_db;
+ cl->cl_close = &seq_close_db;
+
+ return (0);
+}
+
+#define T_COMM '#'
+static int
+seq_next_plain(struct _citrus_lookup *cl, struct _region *key,
+ struct _region *data)
+{
+ const char *p, *q;
+ size_t len;
+
+ if (cl->cl_rewind)
+ _memstream_bind(&cl->cl_plainms, &cl->cl_plainr);
+ cl->cl_rewind = 0;
+
+retry:
+ p = _memstream_getln(&cl->cl_plainms, &len);
+ if (p == NULL)
+ return (ENOENT);
+ /* ignore comment */
+ q = memchr(p, T_COMM, len);
+ if (q) {
+ len = q - p;
+ }
+ /* ignore trailing spaces */
+ _bcs_trunc_rws_len(p, &len);
+ p = _bcs_skip_ws_len(p, &len);
+ q = _bcs_skip_nonws_len(p, &len);
+ if (p == q)
+ goto retry;
+ if (cl->cl_key && ((size_t)(q - p) != cl->cl_keylen ||
+ memcmp(p, cl->cl_key, (size_t)(q - p)) != 0))
+ goto retry;
+
+ /* found a entry */
+ if (key)
+ _region_init(key, __DECONST(void *, p), (size_t)(q - p));
+ p = _bcs_skip_ws_len(q, &len);
+ if (data)
+ _region_init(data, len ? __DECONST(void *, p) : NULL, len);
+
+ return (0);
+}
+
+static int
+seq_get_num_entries_plain(struct _citrus_lookup *cl)
+{
+ int num;
+
+ num = 0;
+ while (seq_next_plain(cl, NULL, NULL) == 0)
+ num++;
+
+ return (num);
+}
+
+static int
+seq_lookup_plain(struct _citrus_lookup *cl, const char *key,
+ struct _region *data)
+{
+ size_t len;
+ const char *p;
+
+ cl->cl_rewind = 0;
+ free(cl->cl_key);
+ cl->cl_key = strdup(key);
+ if (cl->cl_ignore_case)
+ _bcs_convert_to_lower(cl->cl_key);
+ cl->cl_keylen = strlen(cl->cl_key);
+ _memstream_bind(&cl->cl_plainms, &cl->cl_plainr);
+ p = _memstream_matchline(&cl->cl_plainms, cl->cl_key, &len, 0);
+ if (p == NULL)
+ return (ENOENT);
+ if (data)
+ _region_init(data, __DECONST(void *, p), len);
+
+ return (0);
+}
+
+static void
+seq_close_plain(struct _citrus_lookup *cl)
+{
+
+ _unmap_file(&cl->cl_plainr);
+}
+
+static int
+seq_open_plain(struct _citrus_lookup *cl, const char *name)
+{
+ int ret;
+
+ /* open read stream */
+ ret = _map_file(&cl->cl_plainr, name);
+ if (ret)
+ return (ret);
+
+ cl->cl_rewind = 1;
+ cl->cl_next = &seq_next_plain;
+ cl->cl_lookup = &seq_lookup_plain;
+ cl->cl_num_entries = &seq_get_num_entries_plain;
+ cl->cl_close = &seq_close_plain;
+
+ return (0);
+}
+
+int
+_citrus_lookup_seq_open(struct _citrus_lookup **rcl, const char *name,
+ int ignore_case)
+{
+ int ret;
+ struct _citrus_lookup *cl;
+
+ cl = malloc(sizeof(*cl));
+ if (cl == NULL)
+ return (errno);
+
+ cl->cl_key = NULL;
+ cl->cl_keylen = 0;
+ cl->cl_ignore_case = ignore_case;
+ ret = seq_open_db(cl, name);
+ if (ret == ENOENT)
+ ret = seq_open_plain(cl, name);
+ if (!ret)
+ *rcl = cl;
+ else
+ free(cl);
+
+ return (ret);
+}
+
+void
+_citrus_lookup_seq_rewind(struct _citrus_lookup *cl)
+{
+
+ cl->cl_rewind = 1;
+ free(cl->cl_key);
+ cl->cl_key = NULL;
+ cl->cl_keylen = 0;
+}
+
+int
+_citrus_lookup_seq_next(struct _citrus_lookup *cl,
+ struct _region *key, struct _region *data)
+{
+
+ return ((*cl->cl_next)(cl, key, data));
+}
+
+int
+_citrus_lookup_seq_lookup(struct _citrus_lookup *cl, const char *key,
+ struct _region *data)
+{
+
+ return ((*cl->cl_lookup)(cl, key, data));
+}
+
+int
+_citrus_lookup_get_number_of_entries(struct _citrus_lookup *cl)
+{
+
+ return ((*cl->cl_num_entries)(cl));
+}
+
+void
+_citrus_lookup_seq_close(struct _citrus_lookup *cl)
+{
+
+ free(cl->cl_key);
+ (*cl->cl_close)(cl);
+ free(cl);
+}
+
+char *
+_citrus_lookup_simple(const char *name, const char *key,
+ char *linebuf, size_t linebufsize, int ignore_case)
+{
+ struct _citrus_lookup *cl;
+ struct _region data;
+ int ret;
+
+ ret = _citrus_lookup_seq_open(&cl, name, ignore_case);
+ if (ret)
+ return (NULL);
+
+ ret = _citrus_lookup_seq_lookup(cl, key, &data);
+ if (ret) {
+ _citrus_lookup_seq_close(cl);
+ return (NULL);
+ }
+
+ snprintf(linebuf, linebufsize, "%.*s", (int)_region_size(&data),
+ (const char *)_region_head(&data));
+
+ _citrus_lookup_seq_close(cl);
+
+ return (linebuf);
+}
diff --git a/lib/libc/iconv/citrus_lookup.h b/lib/libc/iconv/citrus_lookup.h
new file mode 100644
index 0000000..e7a7150
--- /dev/null
+++ b/lib/libc/iconv/citrus_lookup.h
@@ -0,0 +1,64 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_lookup.h,v 1.2 2004/07/21 14:16:34 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_LOOKUP_H_
+#define _CITRUS_LOOKUP_H_
+
+#define _CITRUS_LOOKUP_CASE_SENSITIVE 0
+#define _CITRUS_LOOKUP_CASE_IGNORE 1
+
+struct _citrus_lookup;
+__BEGIN_DECLS
+char *_citrus_lookup_simple(const char *, const char *, char *,
+ size_t, int);
+int _citrus_lookup_seq_open(struct _citrus_lookup **,
+ const char *, int);
+void _citrus_lookup_seq_rewind(struct _citrus_lookup *);
+int _citrus_lookup_seq_next(struct _citrus_lookup *,
+ struct _region *, struct _region *);
+int _citrus_lookup_seq_lookup(struct _citrus_lookup *,
+ const char *, struct _region *);
+int _citrus_lookup_get_number_of_entries(struct _citrus_lookup *);
+void _citrus_lookup_seq_close(struct _citrus_lookup *);
+__END_DECLS
+
+static __inline const char *
+_citrus_lookup_alias(const char *path, const char *key, char *buf, size_t n,
+ int ignore_case)
+{
+ const char *ret;
+
+ ret = _citrus_lookup_simple(path, key, buf, n, ignore_case);
+ if (ret == NULL)
+ ret = key;
+
+ return (ret);
+}
+
+#endif
diff --git a/lib/libc/iconv/citrus_lookup_factory.c b/lib/libc/iconv/citrus_lookup_factory.c
new file mode 100644
index 0000000..ec5a5d6
--- /dev/null
+++ b/lib/libc/iconv/citrus_lookup_factory.c
@@ -0,0 +1,121 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_lookup_factory.c,v 1.4 2003/10/27 00:12:42 lukem Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_region.h"
+#include "citrus_bcs.h"
+#include "citrus_db_factory.h"
+#include "citrus_db_hash.h"
+#include "citrus_lookup_factory.h"
+#include "citrus_lookup_file.h"
+
+#define T_COMM '#'
+static int
+convert_line(struct _citrus_db_factory *df, const char *line, size_t len)
+{
+ const char *p;
+ char data[LINE_MAX], key[LINE_MAX];
+
+ /* cut off trailing comment */
+ p = memchr(line, T_COMM, len);
+ if (p)
+ len = p - line;
+
+ /* key */
+ line = _bcs_skip_ws_len(line, &len);
+ if (len == 0)
+ return (0);
+ p = _bcs_skip_nonws_len(line, &len);
+ if (p == line)
+ return (0);
+ snprintf(key, sizeof(key), "%.*s", (int)(p-line), line);
+ _bcs_convert_to_lower(key);
+
+ /* data */
+ line = _bcs_skip_ws_len(p, &len);
+ _bcs_trunc_rws_len(line, &len);
+ snprintf(data, sizeof(data), "%.*s", (int)len, line);
+
+ return (_db_factory_addstr_by_s(df, key, data));
+}
+
+static int
+dump_db(struct _citrus_db_factory *df, struct _region *r)
+{
+ void *ptr;
+ size_t size;
+
+ size = _db_factory_calc_size(df);
+ ptr = malloc(size);
+ if (ptr == NULL)
+ return (errno);
+ _region_init(r, ptr, size);
+
+ return (_db_factory_serialize(df, _CITRUS_LOOKUP_MAGIC, r));
+}
+
+int
+_citrus_lookup_factory_convert(FILE *out, FILE *in)
+{
+ struct _citrus_db_factory *df;
+ struct _region r;
+ char *line;
+ size_t size;
+ int ret;
+
+ ret = _db_factory_create(&df, &_db_hash_std, NULL);
+ if (ret)
+ return (ret);
+
+ while ((line = fgetln(in, &size)) != NULL)
+ if ((ret = convert_line(df, line, size))) {
+ _db_factory_free(df);
+ return (ret);
+ }
+
+ ret = dump_db(df, &r);
+ _db_factory_free(df);
+ if (ret)
+ return (ret);
+
+ if (fwrite(_region_head(&r), _region_size(&r), 1, out) != 1)
+ return (errno);
+
+ return (0);
+}
diff --git a/lib/libc/iconv/citrus_lookup_factory.h b/lib/libc/iconv/citrus_lookup_factory.h
new file mode 100644
index 0000000..9016de5
--- /dev/null
+++ b/lib/libc/iconv/citrus_lookup_factory.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_lookup_factory.h,v 1.1 2003/06/25 09:51:35 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_LOOKUP_FACTORY_H_
+#define _CITRUS_LOOKUP_FACTORY_H_
+
+__BEGIN_DECLS
+int _citrus_lookup_factory_convert(FILE *, FILE *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_lookup_file.h b/lib/libc/iconv/citrus_lookup_file.h
new file mode 100644
index 0000000..43944b3
--- /dev/null
+++ b/lib/libc/iconv/citrus_lookup_file.h
@@ -0,0 +1,35 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_lookup_file.h,v 1.1 2003/06/25 09:51:36 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_LOOKUP_FILE_H_
+#define _CITRUS_LOOKUP_FILE_H_
+
+#define _CITRUS_LOOKUP_MAGIC "LOOKUP\0\0"
+
+#endif
diff --git a/lib/libc/iconv/citrus_mapper.c b/lib/libc/iconv/citrus_mapper.c
new file mode 100644
index 0000000..b5ae96d
--- /dev/null
+++ b/lib/libc/iconv/citrus_mapper.c
@@ -0,0 +1,399 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper.c,v 1.7 2008/07/25 14:05:25 christos Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_region.h"
+#include "citrus_lock.h"
+#include "citrus_memstream.h"
+#include "citrus_bcs.h"
+#include "citrus_mmap.h"
+#include "citrus_module.h"
+#include "citrus_hash.h"
+#include "citrus_mapper.h"
+
+#define _CITRUS_MAPPER_DIR "mapper.dir"
+
+#define CM_HASH_SIZE 101
+#define REFCOUNT_PERSISTENT -1
+
+struct _citrus_mapper_area {
+ _CITRUS_HASH_HEAD(, _citrus_mapper, CM_HASH_SIZE) ma_cache;
+ char *ma_dir;
+};
+
+/*
+ * _citrus_mapper_create_area:
+ * create mapper area
+ */
+
+int
+_citrus_mapper_create_area(
+ struct _citrus_mapper_area *__restrict *__restrict rma,
+ const char *__restrict area)
+{
+ struct _citrus_mapper_area *ma;
+ struct stat st;
+ char path[PATH_MAX];
+ int ret;
+
+ WLOCK;
+
+ if (*rma != NULL) {
+ ret = 0;
+ goto quit;
+ }
+
+ snprintf(path, (size_t)PATH_MAX, "%s/%s", area, _CITRUS_MAPPER_DIR);
+
+ ret = stat(path, &st);
+ if (ret)
+ goto quit;
+
+ ma = malloc(sizeof(*ma));
+ if (ma == NULL) {
+ ret = errno;
+ goto quit;
+ }
+ ma->ma_dir = strdup(area);
+ if (ma->ma_dir == NULL) {
+ ret = errno;
+ free(ma->ma_dir);
+ goto quit;
+ }
+ _CITRUS_HASH_INIT(&ma->ma_cache, CM_HASH_SIZE);
+
+ *rma = ma;
+ ret = 0;
+quit:
+ UNLOCK;
+
+ return (ret);
+}
+
+
+/*
+ * lookup_mapper_entry:
+ * lookup mapper.dir entry in the specified directory.
+ *
+ * line format of iconv.dir file:
+ * mapper module arg
+ * mapper : mapper name.
+ * module : mapper module name.
+ * arg : argument for the module (generally, description file name)
+ */
+
+static int
+lookup_mapper_entry(const char *dir, const char *mapname, void *linebuf,
+ size_t linebufsize, const char **module, const char **variable)
+{
+ struct _region r;
+ struct _memstream ms;
+ const char *cp, *cq;
+ char *p;
+ char path[PATH_MAX];
+ size_t len;
+ int ret;
+
+ /* create mapper.dir path */
+ snprintf(path, (size_t)PATH_MAX, "%s/%s", dir, _CITRUS_MAPPER_DIR);
+
+ /* open read stream */
+ ret = _map_file(&r, path);
+ if (ret)
+ return (ret);
+
+ _memstream_bind(&ms, &r);
+
+ /* search the line matching to the map name */
+ cp = _memstream_matchline(&ms, mapname, &len, 0);
+ if (!cp) {
+ ret = ENOENT;
+ goto quit;
+ }
+ if (!len || len > linebufsize - 1) {
+ ret = EINVAL;
+ goto quit;
+ }
+
+ p = linebuf;
+ /* get module name */
+ *module = p;
+ cq = _bcs_skip_nonws_len(cp, &len);
+ strlcpy(p, cp, (size_t)(cq - cp + 1));
+ p += cq - cp + 1;
+
+ /* get variable */
+ *variable = p;
+ cp = _bcs_skip_ws_len(cq, &len);
+ strlcpy(p, cp, len + 1);
+
+ ret = 0;
+
+quit:
+ _unmap_file(&r);
+ return (ret);
+}
+
+/*
+ * mapper_close:
+ * simply close a mapper. (without handling hash)
+ */
+static void
+mapper_close(struct _citrus_mapper *cm)
+{
+ if (cm->cm_module) {
+ if (cm->cm_ops) {
+ if (cm->cm_closure)
+ (*cm->cm_ops->mo_uninit)(cm);
+ free(cm->cm_ops);
+ }
+ _citrus_unload_module(cm->cm_module);
+ }
+ free(cm->cm_traits);
+ free(cm);
+}
+
+/*
+ * mapper_open:
+ * simply open a mapper. (without handling hash)
+ */
+static int
+mapper_open(struct _citrus_mapper_area *__restrict ma,
+ struct _citrus_mapper * __restrict * __restrict rcm,
+ const char * __restrict module,
+ const char * __restrict variable)
+{
+ struct _citrus_mapper *cm;
+ _citrus_mapper_getops_t getops;
+ int ret;
+
+ /* initialize mapper handle */
+ cm = malloc(sizeof(*cm));
+ if (!cm)
+ return (errno);
+
+ cm->cm_module = NULL;
+ cm->cm_ops = NULL;
+ cm->cm_closure = NULL;
+ cm->cm_traits = NULL;
+ cm->cm_refcount = 0;
+ cm->cm_key = NULL;
+
+ /* load module */
+ ret = _citrus_load_module(&cm->cm_module, module);
+ if (ret)
+ goto err;
+
+ /* get operators */
+ getops = (_citrus_mapper_getops_t)
+ _citrus_find_getops(cm->cm_module, module, "mapper");
+ if (!getops) {
+ ret = EOPNOTSUPP;
+ goto err;
+ }
+ cm->cm_ops = malloc(sizeof(*cm->cm_ops));
+ if (!cm->cm_ops) {
+ ret = errno;
+ goto err;
+ }
+ ret = (*getops)(cm->cm_ops);
+ if (ret)
+ goto err;
+
+ if (!cm->cm_ops->mo_init ||
+ !cm->cm_ops->mo_uninit ||
+ !cm->cm_ops->mo_convert ||
+ !cm->cm_ops->mo_init_state)
+ goto err;
+
+ /* allocate traits structure */
+ cm->cm_traits = malloc(sizeof(*cm->cm_traits));
+ if (cm->cm_traits == NULL) {
+ ret = errno;
+ goto err;
+ }
+ /* initialize the mapper */
+ ret = (*cm->cm_ops->mo_init)(ma, cm, ma->ma_dir,
+ (const void *)variable, strlen(variable) + 1,
+ cm->cm_traits, sizeof(*cm->cm_traits));
+ if (ret)
+ goto err;
+
+ *rcm = cm;
+
+ return (0);
+
+err:
+ mapper_close(cm);
+ return (ret);
+}
+
+/*
+ * _citrus_mapper_open_direct:
+ * open a mapper.
+ */
+int
+_citrus_mapper_open_direct(struct _citrus_mapper_area *__restrict ma,
+ struct _citrus_mapper * __restrict * __restrict rcm,
+ const char * __restrict module, const char * __restrict variable)
+{
+
+ return (mapper_open(ma, rcm, module, variable));
+}
+
+/*
+ * hash_func
+ */
+static __inline int
+hash_func(const char *key)
+{
+
+ return (_string_hash_func(key, CM_HASH_SIZE));
+}
+
+/*
+ * match_func
+ */
+static __inline int
+match_func(struct _citrus_mapper *cm, const char *key)
+{
+
+ return (strcmp(cm->cm_key, key));
+}
+
+/*
+ * _citrus_mapper_open:
+ * open a mapper with looking up "mapper.dir".
+ */
+int
+_citrus_mapper_open(struct _citrus_mapper_area *__restrict ma,
+ struct _citrus_mapper * __restrict * __restrict rcm,
+ const char * __restrict mapname)
+{
+ struct _citrus_mapper *cm;
+ char linebuf[PATH_MAX];
+ const char *module, *variable;
+ int hashval, ret;
+
+ variable = NULL;
+
+ WLOCK;
+
+ /* search in the cache */
+ hashval = hash_func(mapname);
+ _CITRUS_HASH_SEARCH(&ma->ma_cache, cm, cm_entry, match_func, mapname,
+ hashval);
+ if (cm) {
+ /* found */
+ cm->cm_refcount++;
+ *rcm = cm;
+ ret = 0;
+ goto quit;
+ }
+
+ /* search mapper entry */
+ ret = lookup_mapper_entry(ma->ma_dir, mapname, linebuf,
+ (size_t)PATH_MAX, &module, &variable);
+ if (ret)
+ goto quit;
+
+ /* open mapper */
+ UNLOCK;
+ ret = mapper_open(ma, &cm, module, variable);
+ WLOCK;
+ if (ret)
+ goto quit;
+ cm->cm_key = strdup(mapname);
+ if (cm->cm_key == NULL) {
+ ret = errno;
+ _mapper_close(cm);
+ goto quit;
+ }
+
+ /* insert to the cache */
+ cm->cm_refcount = 1;
+ _CITRUS_HASH_INSERT(&ma->ma_cache, cm, cm_entry, hashval);
+
+ *rcm = cm;
+ ret = 0;
+quit:
+ UNLOCK;
+
+ return (ret);
+}
+
+/*
+ * _citrus_mapper_close:
+ * close the specified mapper.
+ */
+void
+_citrus_mapper_close(struct _citrus_mapper *cm)
+{
+
+ if (cm) {
+ WLOCK;
+ if (cm->cm_refcount == REFCOUNT_PERSISTENT)
+ goto quit;
+ if (cm->cm_refcount > 0) {
+ if (--cm->cm_refcount > 0)
+ goto quit;
+ _CITRUS_HASH_REMOVE(cm, cm_entry);
+ free(cm->cm_key);
+ }
+ mapper_close(cm);
+quit:
+ UNLOCK;
+ }
+}
+
+/*
+ * _citrus_mapper_set_persistent:
+ * set persistent count.
+ */
+void
+_citrus_mapper_set_persistent(struct _citrus_mapper * __restrict cm)
+{
+
+ WLOCK;
+ cm->cm_refcount = REFCOUNT_PERSISTENT;
+ UNLOCK;
+}
diff --git a/lib/libc/iconv/citrus_mapper.h b/lib/libc/iconv/citrus_mapper.h
new file mode 100644
index 0000000..429b2a1
--- /dev/null
+++ b/lib/libc/iconv/citrus_mapper.h
@@ -0,0 +1,131 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper.h,v 1.3 2003/07/12 15:39:19 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_H_
+#define _CITRUS_MAPPER_H_
+
+struct _citrus_mapper_area;
+struct _citrus_mapper;
+struct _citrus_mapper_ops;
+struct _citrus_mapper_traits;
+
+__BEGIN_DECLS
+int _citrus_mapper_create_area(
+ struct _citrus_mapper_area *__restrict *__restrict,
+ const char *__restrict);
+int _citrus_mapper_open(struct _citrus_mapper_area *__restrict,
+ struct _citrus_mapper *__restrict *__restrict,
+ const char *__restrict);
+int _citrus_mapper_open_direct(
+ struct _citrus_mapper_area *__restrict,
+ struct _citrus_mapper *__restrict *__restrict,
+ const char *__restrict, const char *__restrict);
+void _citrus_mapper_close(struct _citrus_mapper *);
+void _citrus_mapper_set_persistent(struct _citrus_mapper * __restrict);
+__END_DECLS
+
+#include "citrus_mapper_local.h"
+
+/* return values of _citrus_mapper_convert */
+#define _CITRUS_MAPPER_CONVERT_SUCCESS (0)
+#define _CITRUS_MAPPER_CONVERT_NONIDENTICAL (1)
+#define _CITRUS_MAPPER_CONVERT_SRC_MORE (2)
+#define _CITRUS_MAPPER_CONVERT_DST_MORE (3)
+#define _CITRUS_MAPPER_CONVERT_ILSEQ (4)
+#define _CITRUS_MAPPER_CONVERT_FATAL (5)
+
+/*
+ * _citrus_mapper_convert:
+ * convert an index.
+ * - if the converter supports M:1 converter, the function may return
+ * _CITRUS_MAPPER_CONVERT_SRC_MORE and the storage pointed by dst
+ * may be unchanged in this case, although the internal status of
+ * the mapper is affected.
+ * - if the converter supports 1:N converter, the function may return
+ * _CITRUS_MAPPER_CONVERT_DST_MORE. In this case, the contiguous
+ * call of this function ignores src and changes the storage pointed
+ * by dst.
+ * - if the converter supports M:N converter, the function may behave
+ * the combination of the above.
+ *
+ */
+static __inline int
+_citrus_mapper_convert(struct _citrus_mapper * __restrict cm,
+ _citrus_index_t * __restrict dst, _citrus_index_t src,
+ void * __restrict ps)
+{
+
+ return ((*cm->cm_ops->mo_convert)(cm, dst, src, ps));
+}
+
+/*
+ * _citrus_mapper_init_state:
+ * initialize the state.
+ */
+static __inline void
+_citrus_mapper_init_state(struct _citrus_mapper * __restrict cm)
+{
+
+ (*cm->cm_ops->mo_init_state)();
+}
+
+/*
+ * _citrus_mapper_get_state_size:
+ * get the size of state storage.
+ */
+static __inline size_t
+_citrus_mapper_get_state_size(struct _citrus_mapper * __restrict cm)
+{
+
+ return (cm->cm_traits->mt_state_size);
+}
+
+/*
+ * _citrus_mapper_get_src_max:
+ * get the maximum number of suspended sources.
+ */
+static __inline size_t
+_citrus_mapper_get_src_max(struct _citrus_mapper * __restrict cm)
+{
+
+ return (cm->cm_traits->mt_src_max);
+}
+
+/*
+ * _citrus_mapper_get_dst_max:
+ * get the maximum number of suspended destinations.
+ */
+static __inline size_t
+_citrus_mapper_get_dst_max(struct _citrus_mapper * __restrict cm)
+{
+
+ return (cm->cm_traits->mt_dst_max);
+}
+
+#endif
diff --git a/lib/libc/iconv/citrus_mapper_local.h b/lib/libc/iconv/citrus_mapper_local.h
new file mode 100644
index 0000000..887a35d
--- /dev/null
+++ b/lib/libc/iconv/citrus_mapper_local.h
@@ -0,0 +1,96 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mapper_local.h,v 1.2 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_MAPPER_LOCAL_H_
+#define _CITRUS_MAPPER_LOCAL_H_
+
+#define _CITRUS_MAPPER_GETOPS_FUNC_BASE(_n_) \
+int _n_(struct _citrus_mapper_ops *)
+#define _CITRUS_MAPPER_GETOPS_FUNC(_n_) \
+_CITRUS_MAPPER_GETOPS_FUNC_BASE(_citrus_##_n_##_mapper_getops)
+
+#define _CITRUS_MAPPER_DECLS(_m_) \
+static int _citrus_##_m_##_mapper_init \
+ (struct _citrus_mapper_area *__restrict, \
+ struct _citrus_mapper * __restrict, \
+ const char * __restrict, const void * __restrict, \
+ size_t, struct _citrus_mapper_traits * __restrict, \
+ size_t); \
+static void _citrus_##_m_##_mapper_uninit( \
+ struct _citrus_mapper *); \
+static int _citrus_##_m_##_mapper_convert \
+ (struct _citrus_mapper * __restrict, \
+ _citrus_index_t * __restrict, _citrus_index_t, \
+ void * __restrict); \
+static void _citrus_##_m_##_mapper_init_state \
+ (void);
+
+#define _CITRUS_MAPPER_DEF_OPS(_m_) \
+struct _citrus_mapper_ops _citrus_##_m_##_mapper_ops = { \
+ /* mo_init */ &_citrus_##_m_##_mapper_init, \
+ /* mo_uninit */ &_citrus_##_m_##_mapper_uninit, \
+ /* mo_convert */ &_citrus_##_m_##_mapper_convert, \
+ /* mo_init_state */ &_citrus_##_m_##_mapper_init_state \
+}
+
+typedef _CITRUS_MAPPER_GETOPS_FUNC_BASE((*_citrus_mapper_getops_t));
+typedef int (*_citrus_mapper_init_t)(
+ struct _citrus_mapper_area *__restrict,
+ struct _citrus_mapper *__restrict, const char *__restrict,
+ const void *__restrict, size_t,
+ struct _citrus_mapper_traits * __restrict, size_t);
+typedef void (*_citrus_mapper_uninit_t)(struct _citrus_mapper *);
+typedef int (*_citrus_mapper_convert_t)(struct _citrus_mapper * __restrict,
+ _citrus_index_t * __restrict, _citrus_index_t, void * __restrict);
+typedef void (*_citrus_mapper_init_state_t)(void);
+
+struct _citrus_mapper_ops {
+ _citrus_mapper_init_t mo_init;
+ _citrus_mapper_uninit_t mo_uninit;
+ _citrus_mapper_convert_t mo_convert;
+ _citrus_mapper_init_state_t mo_init_state;
+};
+
+struct _citrus_mapper_traits {
+ /* version 0x00000001 */
+ size_t mt_state_size;
+ size_t mt_src_max;
+ size_t mt_dst_max;
+};
+
+struct _citrus_mapper {
+ struct _citrus_mapper_ops *cm_ops;
+ void *cm_closure;
+ _citrus_module_t cm_module;
+ struct _citrus_mapper_traits *cm_traits;
+ _CITRUS_HASH_ENTRY(_citrus_mapper) cm_entry;
+ int cm_refcount;
+ char *cm_key;
+};
+#endif
diff --git a/lib/libc/iconv/citrus_memstream.c b/lib/libc/iconv/citrus_memstream.c
new file mode 100644
index 0000000..d7ad4fd
--- /dev/null
+++ b/lib/libc/iconv/citrus_memstream.c
@@ -0,0 +1,148 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_memstream.c,v 1.4 2009/02/03 05:02:12 lukem Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_bcs.h"
+
+const char *
+_citrus_memory_stream_getln(struct _citrus_memory_stream * __restrict ms,
+ size_t * __restrict rlen)
+{
+ const uint8_t *h, *p;
+ size_t ret;
+ int i;
+
+ if (ms->ms_pos>=_region_size(&ms->ms_region))
+ return (NULL);
+
+ h = p = (uint8_t *)_region_offset(&ms->ms_region, ms->ms_pos);
+ ret = 0;
+ for (i = _region_size(&ms->ms_region) - ms->ms_pos; i > 0; i--) {
+ ret++;
+ if (_bcs_iseol(*p))
+ break;
+ p++;
+ }
+
+ ms->ms_pos += ret;
+ *rlen = ret;
+ return ((const char *)h);
+}
+
+#define T_COMM '#'
+
+const char *
+_citrus_memory_stream_matchline(struct _citrus_memory_stream * __restrict ms,
+ const char * __restrict key, size_t * __restrict rlen, int iscasesensitive)
+{
+ const char *p, *q;
+ size_t keylen, len;
+
+ keylen = strlen(key);
+ for(;;) {
+ p = _citrus_memory_stream_getln(ms, &len);
+ if (p == NULL)
+ return (NULL);
+
+ /* ignore comment */
+ q = memchr(p, T_COMM, len);
+ if (q) {
+ len = q - p;
+ }
+ /* ignore trailing white space and newline */
+ _bcs_trunc_rws_len(p, &len);
+ if (len == 0)
+ continue; /* ignore null line */
+
+ /* skip white spaces at the head of the line */
+ p = _bcs_skip_ws_len(p, &len);
+ q = _bcs_skip_nonws_len(p, &len);
+
+ if ((size_t)(q - p) == keylen) {
+ if (iscasesensitive) {
+ if (memcmp(key, p, keylen) == 0)
+ break; /* match */
+ } else {
+ if (_bcs_strncasecmp(key, p, keylen) == 0)
+ break; /* match */
+ }
+ }
+ }
+
+ p = _bcs_skip_ws_len(q, &len);
+ *rlen = len;
+
+ return (p);
+}
+
+void *
+_citrus_memory_stream_chr(struct _citrus_memory_stream *ms,
+ struct _citrus_region *r, char ch)
+{
+ void *chr, *head;
+ size_t sz;
+
+ if (ms->ms_pos >= _region_size(&ms->ms_region))
+ return (NULL);
+
+ head = _region_offset(&ms->ms_region, ms->ms_pos);
+ chr = memchr(head, ch, _memstream_remainder(ms));
+ if (chr == NULL) {
+ _region_init(r, head, _memstream_remainder(ms));
+ ms->ms_pos = _region_size(&ms->ms_region);
+ return (NULL);
+ }
+ sz = (char *)chr - (char *)head;
+
+ _region_init(r, head, sz);
+ ms->ms_pos += sz + 1;
+
+ return (chr);
+}
+
+void
+_citrus_memory_stream_skip_ws(struct _citrus_memory_stream *ms)
+{
+ int ch;
+
+ while ((ch = _memstream_peek(ms)) != EOF) {
+ if (!_bcs_isspace(ch))
+ break;
+ _memstream_getc(ms);
+ }
+}
diff --git a/lib/libc/iconv/citrus_memstream.h b/lib/libc/iconv/citrus_memstream.h
new file mode 100644
index 0000000..cd5ef13
--- /dev/null
+++ b/lib/libc/iconv/citrus_memstream.h
@@ -0,0 +1,226 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_memstream.h,v 1.3 2005/05/14 17:55:42 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_MEMSTREAM_H_
+#define _CITRUS_MEMSTREAM_H_
+
+struct _citrus_memory_stream {
+ struct _citrus_region ms_region;
+ size_t ms_pos;
+};
+
+__BEGIN_DECLS
+const char *_citrus_memory_stream_getln(
+ struct _citrus_memory_stream * __restrict,
+ size_t * __restrict);
+const char *_citrus_memory_stream_matchline(
+ struct _citrus_memory_stream * __restrict,
+ const char * __restrict, size_t * __restrict, int);
+void *_citrus_memory_stream_chr(struct _citrus_memory_stream *,
+ struct _citrus_region *, char);
+void _citrus_memory_stream_skip_ws(struct _citrus_memory_stream *);
+__END_DECLS
+
+static __inline int
+_citrus_memory_stream_iseof(struct _citrus_memory_stream *ms)
+{
+
+ return (ms->ms_pos >= _citrus_region_size(&ms->ms_region));
+}
+
+static __inline void
+_citrus_memory_stream_bind(struct _citrus_memory_stream * __restrict ms,
+ const struct _citrus_region * __restrict r)
+{
+
+ ms->ms_region = *r;
+ ms->ms_pos = 0;
+}
+
+static __inline void
+_citrus_memory_stream_bind_ptr(struct _citrus_memory_stream * __restrict ms,
+ void *ptr, size_t sz)
+{
+ struct _citrus_region r;
+
+ _citrus_region_init(&r, ptr, sz);
+ _citrus_memory_stream_bind(ms, &r);
+}
+
+static __inline void
+_citrus_memory_stream_rewind(struct _citrus_memory_stream *ms)
+{
+
+ ms->ms_pos = 0;
+}
+
+static __inline size_t
+_citrus_memory_stream_tell(struct _citrus_memory_stream *ms)
+{
+
+ return (ms->ms_pos);
+}
+
+static __inline size_t
+_citrus_memory_stream_remainder(struct _citrus_memory_stream *ms)
+{
+ size_t sz;
+
+ sz = _citrus_region_size(&ms->ms_region);
+ if (ms->ms_pos>sz)
+ return (0);
+ return (sz-ms->ms_pos);
+}
+
+static __inline int
+_citrus_memory_stream_seek(struct _citrus_memory_stream *ms, size_t pos, int w)
+{
+ size_t sz;
+
+ sz = _citrus_region_size(&ms->ms_region);
+
+ switch (w) {
+ case SEEK_SET:
+ if (pos >= sz)
+ return (-1);
+ ms->ms_pos = pos;
+ break;
+ case SEEK_CUR:
+ pos += (ssize_t)ms->ms_pos;
+ if (pos >= sz)
+ return (-1);
+ ms->ms_pos = pos;
+ break;
+ case SEEK_END:
+ if (sz < pos)
+ return (-1);
+ ms->ms_pos = sz - pos;
+ break;
+ }
+ return (0);
+}
+
+static __inline int
+_citrus_memory_stream_getc(struct _citrus_memory_stream *ms)
+{
+
+ if (_citrus_memory_stream_iseof(ms))
+ return (EOF);
+ return (_citrus_region_peek8(&ms->ms_region, ms->ms_pos++));
+}
+
+static __inline void
+_citrus_memory_stream_ungetc(struct _citrus_memory_stream *ms, int ch)
+{
+
+ if (ch != EOF && ms->ms_pos > 0)
+ ms->ms_pos--;
+}
+
+static __inline int
+_citrus_memory_stream_peek(struct _citrus_memory_stream *ms)
+{
+
+ if (_citrus_memory_stream_iseof(ms))
+ return (EOF);
+ return (_citrus_region_peek8(&ms->ms_region, ms->ms_pos));
+}
+
+static __inline void *
+_citrus_memory_stream_getregion(struct _citrus_memory_stream *ms,
+ struct _citrus_region *r, size_t sz)
+{
+ void *ret;
+
+ if (ms->ms_pos + sz > _citrus_region_size(&ms->ms_region))
+ return (NULL);
+
+ ret = _citrus_region_offset(&ms->ms_region, ms->ms_pos);
+ ms->ms_pos += sz;
+ if (r)
+ _citrus_region_init(r, ret, sz);
+
+ return (ret);
+}
+
+static __inline int
+_citrus_memory_stream_get8(struct _citrus_memory_stream *ms, uint8_t *rval)
+{
+
+ if (ms->ms_pos + 1 > _citrus_region_size(&ms->ms_region))
+ return (-1);
+
+ *rval = _citrus_region_peek8(&ms->ms_region, ms->ms_pos);
+ ms->ms_pos += 2;
+
+ return (0);
+}
+
+static __inline int
+_citrus_memory_stream_get16(struct _citrus_memory_stream *ms, uint16_t *rval)
+{
+
+ if (ms->ms_pos + 2 > _citrus_region_size(&ms->ms_region))
+ return (-1);
+
+ *rval = _citrus_region_peek16(&ms->ms_region, ms->ms_pos);
+ ms->ms_pos += 2;
+
+ return (0);
+}
+
+static __inline int
+_citrus_memory_stream_get32(struct _citrus_memory_stream *ms, uint32_t *rval)
+{
+
+ if (ms->ms_pos + 4 > _citrus_region_size(&ms->ms_region))
+ return (-1);
+
+ *rval = _citrus_region_peek32(&ms->ms_region, ms->ms_pos);
+ ms->ms_pos += 4;
+
+ return (0);
+}
+
+static __inline int
+_citrus_memory_stream_getln_region(struct _citrus_memory_stream *ms,
+ struct _citrus_region *r)
+{
+ const char *ptr;
+ size_t sz;
+
+ ptr = _citrus_memory_stream_getln(ms, &sz);
+ if (ptr)
+ _citrus_region_init(r, __DECONST(void *, ptr), sz);
+
+ return (ptr == NULL);
+}
+
+#endif
diff --git a/lib/libc/iconv/citrus_mmap.c b/lib/libc/iconv/citrus_mmap.c
new file mode 100644
index 0000000..dd5d059
--- /dev/null
+++ b/lib/libc/iconv/citrus_mmap.c
@@ -0,0 +1,97 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mmap.c,v 1.3 2005/01/19 00:52:37 mycroft Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "citrus_namespace.h"
+#include "citrus_region.h"
+#include "citrus_mmap.h"
+
+int
+_citrus_map_file(struct _citrus_region * __restrict r,
+ const char * __restrict path)
+{
+ struct stat st;
+ void *head;
+ int fd, ret;
+
+ ret = 0;
+
+ _region_init(r, NULL, 0);
+
+ if ((fd = open(path, O_RDONLY)) == -1)
+ return (errno);
+ if (fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
+ ret = errno;
+ goto error;
+ }
+
+ if (fstat(fd, &st) == -1) {
+ ret = errno;
+ goto error;
+ }
+ if (!S_ISREG(st.st_mode)) {
+ ret = EOPNOTSUPP;
+ goto error;
+ }
+
+ head = mmap(NULL, (size_t)st.st_size, PROT_READ, MAP_FILE|MAP_PRIVATE,
+ fd, (off_t)0);
+ if (head == MAP_FAILED) {
+ ret = errno;
+ goto error;
+ }
+ _region_init(r, head, (size_t)st.st_size);
+
+error:
+ (void)close(fd);
+ return (ret);
+}
+
+void
+_citrus_unmap_file(struct _citrus_region *r)
+{
+
+ if (_region_head(r) != NULL) {
+ (void)munmap(_region_head(r), _region_size(r));
+ _region_init(r, NULL, 0);
+ }
+}
diff --git a/lib/libc/iconv/citrus_mmap.h b/lib/libc/iconv/citrus_mmap.h
new file mode 100644
index 0000000..590e7fb
--- /dev/null
+++ b/lib/libc/iconv/citrus_mmap.h
@@ -0,0 +1,40 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_mmap.h,v 1.1 2003/06/25 09:51:38 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_MMAP_H_
+#define _CITRUS_MMAP_H_
+
+__BEGIN_DECLS
+int _citrus_map_file(struct _citrus_region * __restrict,
+ const char * __restrict);
+void _citrus_unmap_file(struct _citrus_region *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_module.c b/lib/libc/iconv/citrus_module.c
new file mode 100644
index 0000000..32b7e6e
--- /dev/null
+++ b/lib/libc/iconv/citrus_module.c
@@ -0,0 +1,315 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_module.c,v 1.9 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c)1999, 2000, 2001, 2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Paul Kranenburg.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <dirent.h>
+#include <dlfcn.h>
+#include <errno.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#define I18NMODULE_MAJOR 4
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_module.h"
+#include "libc_private.h"
+
+static int _getdewey(int[], char *);
+static int _cmpndewey(int[], int, int[], int);
+static const char *_findshlib(char *, int *, int *);
+
+static const char *_pathI18nModule = NULL;
+
+/* from libexec/ld.aout_so/shlib.c */
+#undef major
+#undef minor
+#define MAXDEWEY 3 /*ELF*/
+
+static int
+_getdewey(int dewey[], char *cp)
+{
+ int i, n;
+
+ for (n = 0, i = 0; i < MAXDEWEY; i++) {
+ if (*cp == '\0')
+ break;
+
+ if (*cp == '.') cp++;
+ if (*cp < '0' || '9' < *cp)
+ return (0);
+
+ dewey[n++] = (int)_bcs_strtol(cp, &cp, 10);
+ }
+
+ return (n);
+}
+
+/*
+ * Compare two dewey arrays.
+ * Return -1 if `d1' represents a smaller value than `d2'.
+ * Return 1 if `d1' represents a greater value than `d2'.
+ * Return 0 if equal.
+ */
+static int
+_cmpndewey(int d1[], int n1, int d2[], int n2)
+{
+ int i;
+
+ for (i = 0; i < n1 && i < n2; i++) {
+ if (d1[i] < d2[i])
+ return (-1);
+ if (d1[i] > d2[i])
+ return (1);
+ }
+
+ if (n1 == n2)
+ return (0);
+
+ if (i == n1)
+ return (-1);
+
+ if (i == n2)
+ return (1);
+
+ /* cannot happen */
+ return (0);
+}
+
+static const char *
+_findshlib(char *name, int *majorp, int *minorp)
+{
+ char *lname;
+ const char *search_dirs[1];
+ static char path[PATH_MAX];
+ int dewey[MAXDEWEY], tmp[MAXDEWEY];
+ int i, len, major, minor, ndewey, n_search_dirs;
+
+ n_search_dirs = 1;
+ major = *majorp;
+ minor = *minorp;
+ path[0] = '\0';
+ search_dirs[0] = _pathI18nModule;
+ len = strlen(name);
+ lname = name;
+
+ ndewey = 0;
+
+ for (i = 0; i < n_search_dirs; i++) {
+ struct dirent *dp;
+ DIR *dd = opendir(search_dirs[i]);
+ int found_dot_a = 0, found_dot_so = 0;
+
+ if (dd == NULL)
+ break;
+
+ while ((dp = readdir(dd)) != NULL) {
+ int n;
+
+ if (dp->d_namlen < len + 4)
+ continue;
+ if (strncmp(dp->d_name, lname, (size_t)len) != 0)
+ continue;
+ if (strncmp(dp->d_name+len, ".so.", 4) != 0)
+ continue;
+
+ if ((n = _getdewey(tmp, dp->d_name+len+4)) == 0)
+ continue;
+
+ if (major != -1 && found_dot_a)
+ found_dot_a = 0;
+
+ /* XXX should verify the library is a.out/ELF? */
+
+ if (major == -1 && minor == -1)
+ goto compare_version;
+ else if (major != -1 && minor == -1) {
+ if (tmp[0] == major)
+ goto compare_version;
+ } else if (major != -1 && minor != -1) {
+ if (tmp[0] == major) {
+ if (n == 1 || tmp[1] >= minor)
+ goto compare_version;
+ }
+ }
+
+ /* else, this file does not qualify */
+ continue;
+
+ compare_version:
+ if (_cmpndewey(tmp, n, dewey, ndewey) <= 0)
+ continue;
+
+ /* We have a better version */
+ found_dot_so = 1;
+ snprintf(path, sizeof(path), "%s/%s", search_dirs[i],
+ dp->d_name);
+ found_dot_a = 0;
+ bcopy(tmp, dewey, sizeof(dewey));
+ ndewey = n;
+ *majorp = dewey[0];
+ *minorp = dewey[1];
+ }
+ closedir(dd);
+
+ if (found_dot_a || found_dot_so)
+ /*
+ * There's a lib in this dir; take it.
+ */
+ return (path[0] ? path : NULL);
+ }
+
+ return (path[0] ? path : NULL);
+}
+
+void *
+_citrus_find_getops(_citrus_module_t handle, const char *modname,
+ const char *ifname)
+{
+ char name[PATH_MAX];
+ void *p;
+
+ snprintf(name, sizeof(name), "_citrus_%s_%s_getops",
+ modname, ifname);
+ p = dlsym((void *)handle, name);
+ return (p);
+}
+
+int
+_citrus_load_module(_citrus_module_t *rhandle, const char *encname)
+{
+ const char *p;
+ char path[PATH_MAX];
+ void *handle;
+ int maj, min;
+
+ if (_pathI18nModule == NULL) {
+ p = getenv("PATH_I18NMODULE");
+ if (p != NULL && !issetugid()) {
+ _pathI18nModule = strdup(p);
+ if (_pathI18nModule == NULL)
+ return (ENOMEM);
+ } else
+ _pathI18nModule = _PATH_I18NMODULE;
+ }
+
+ (void)snprintf(path, sizeof(path), "lib%s", encname);
+ maj = I18NMODULE_MAJOR;
+ min = -1;
+ p = _findshlib(path, &maj, &min);
+ if (!p)
+ return (EINVAL);
+ handle = libc_dlopen(p, RTLD_LAZY);
+ if (!handle) {
+ printf("%s", dlerror());
+ return (EINVAL);
+ }
+
+ *rhandle = (_citrus_module_t)handle;
+
+ return (0);
+}
+
+void
+_citrus_unload_module(_citrus_module_t handle)
+{
+
+ if (handle)
+ dlclose((void *)handle);
+}
diff --git a/lib/libc/iconv/citrus_module.h b/lib/libc/iconv/citrus_module.h
new file mode 100644
index 0000000..b004b87
--- /dev/null
+++ b/lib/libc/iconv/citrus_module.h
@@ -0,0 +1,54 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_module.h,v 1.1 2002/03/17 22:14:20 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_MODULE_H_
+#define _CITRUS_MODULE_H_
+
+#define MATCH(x, act) \
+do { \
+ if (lenvar >= (sizeof(#x)-1) && \
+ _bcs_strncasecmp(p, #x, sizeof(#x)-1) == 0) { \
+ act; \
+ lenvar -= sizeof(#x)-1; \
+ p += sizeof(#x)-1; \
+ } \
+} while (0)
+
+typedef struct _citrus_module_rec *_citrus_module_t;
+
+__BEGIN_DECLS
+void *_citrus_find_getops(_citrus_module_t __restrict,
+ const char * __restrict, const char * __restrict);
+int _citrus_load_module(_citrus_module_t * __restrict,
+ const char * __restrict);
+void _citrus_unload_module(_citrus_module_t);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_namespace.h b/lib/libc/iconv/citrus_namespace.h
new file mode 100644
index 0000000..6e9ffe0
--- /dev/null
+++ b/lib/libc/iconv/citrus_namespace.h
@@ -0,0 +1,241 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_namespace.h,v 1.8 2009/01/11 02:46:24 christos Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include "citrus_bcs.h"
+
+#ifndef _CITRUS_NAMESPACE_H_
+#define _CITRUS_NAMESPACE_H_
+
+/* citrus_alias */
+#ifndef _CITRUS_ALIAS_NO_NAMESPACE
+#define _alias_lookup _citrus_alias_lookup
+#endif /* _CITRUS_ALIAS_NO_NAMESPACE */
+
+/* citrus_bcs */
+#ifndef _CITRUS_BCS_NO_NAMESPACE
+#define _bcs_isalnum _citrus_bcs_isalnum
+#define _bcs_isalpha _citrus_bcs_isalpha
+#define _bcs_isblank _citrus_bcs_isblank
+#define _bcs_isdigit _citrus_bcs_isdigit
+#define _bcs_islower _citrus_bcs_islower
+#define _bcs_iseol _citrus_bcs_iseol
+#define _bcs_isspace _citrus_bcs_isspace
+#define _bcs_isupper _citrus_bcs_isupper
+#define _bcs_isxdigit _citrus_bcs_isxdigit
+#define _bcs_skip_nonws _citrus_bcs_skip_nonws
+#define _bcs_skip_nonws_len _citrus_bcs_skip_nonws_len
+#define _bcs_skip_ws _citrus_bcs_skip_ws
+#define _bcs_skip_ws_len _citrus_bcs_skip_ws_len
+#define _bcs_strcasecmp _citrus_bcs_strcasecmp
+#define _bcs_strncasecmp _citrus_bcs_strncasecmp
+#define _bcs_tolower _citrus_bcs_tolower
+#define _bcs_toupper _citrus_bcs_toupper
+#define _bcs_trunc_rws_len _citrus_bcs_trunc_rws_len
+#define _bcs_convert_to_lower _citrus_bcs_convert_to_lower
+#define _bcs_convert_to_upper _citrus_bcs_convert_to_upper
+#define _bcs_strtol _citrus_bcs_strtol
+#define _bcs_strtoul _citrus_bcs_strtoul
+#endif /* _CITRUS_BCS_NO_NAMESPACE */
+
+/* citrus_csmapper */
+#ifndef _CITRUS_CSMAPPER_NO_NAMESPACE
+#define _csmapper _citrus_csmapper
+#define _csmapper_open _citrus_csmapper_open
+#define _csmapper_close _citrus_csmapper_close
+#define _csmapper_convert _citrus_csmapper_convert
+#define _csmapper_init_state _citrus_csmapper_init_state
+#define _csmapper_get_state_size _citrus_csmapper_get_state_size
+#define _csmapper_get_src_max _citrus_csmapper_get_src_max
+#define _csmapper_get_dst_max _citrus_csmapper_get_dst_max
+#define _CSMAPPER_F_PREVENT_PIVOT _CITRUS_CSMAPPER_F_PREVENT_PIVOT
+#endif /* _CITRUS_CSMAPPER_NO_NAMESPACE */
+
+/* citrus_db */
+#ifndef _CITRUS_DB_NO_NAMESPACE
+#define _db_open _citrus_db_open
+#define _db_close _citrus_db_close
+#define _db_lookup _citrus_db_lookup
+#define _db_lookup_by_s _citrus_db_lookup_by_string
+#define _db_lookup8_by_s _citrus_db_lookup8_by_string
+#define _db_lookup16_by_s _citrus_db_lookup16_by_string
+#define _db_lookup32_by_s _citrus_db_lookup32_by_string
+#define _db_lookupstr_by_s _citrus_db_lookup_string_by_string
+#define _db_hash_std _citrus_db_hash_std
+#define _db_get_num_entries _citrus_db_get_number_of_entries
+#define _db_get_entry _citrus_db_get_entry
+#define _db_locator _citrus_db_locator
+#define _db_locator_init _citrus_db_locator_init
+#endif /* _CITRUS_DB_NO_NAMESPACE */
+
+/* citrus_db_factory */
+#ifndef _CITRUS_DB_FACTORY_NO_NAMESPACE
+#define _db_factory _citrus_db_factory
+#define _db_factory_create _citrus_db_factory_create
+#define _db_factory_free _citrus_db_factory_free
+#define _db_factory_add _citrus_db_factory_add
+#define _db_factory_add_by_s _citrus_db_factory_add_by_string
+#define _db_factory_add8_by_s _citrus_db_factory_add8_by_string
+#define _db_factory_add16_by_s _citrus_db_factory_add16_by_string
+#define _db_factory_add32_by_s _citrus_db_factory_add32_by_string
+#define _db_factory_addstr_by_s _citrus_db_factory_add_string_by_string
+#define _db_factory_calc_size _citrus_db_factory_calc_size
+#define _db_factory_serialize _citrus_db_factory_serialize
+#endif /* _CITRUS_DB_FACTORY_NO_NAMESPACE */
+
+/* citrus_lookup */
+#ifndef _CITRUS_DB_NO_NAMESPACE
+#define _LOOKUP_CASE_SENSITIVE _CITRUS_LOOKUP_CASE_SENSITIVE
+#define _LOOKUP_CASE_IGNORE _CITRUS_LOOKUP_CASE_IGNORE
+#define _lookup _citrus_lookup
+#define _lookup_simple _citrus_lookup_simple
+#define _lookup_alias _citrus_lookup_alias
+#define _lookup_seq_open _citrus_lookup_seq_open
+#define _lookup_seq_rewind _citrus_lookup_seq_rewind
+#define _lookup_seq_next _citrus_lookup_seq_next
+#define _lookup_seq_lookup _citrus_lookup_seq_lookup
+#define _lookup_get_num_entries _citrus_lookup_get_number_of_entries
+#define _lookup_seq_close _citrus_lookup_seq_close
+#define _lookup_factory_convert _citrus_lookup_factory_convert
+#endif /* _CITRUS_DB_NO_NAMESPACE */
+
+/* citrus_esdb */
+#ifndef _CITRUS_ESDB_NO_NAMESPACE
+#define _esdb _citrus_esdb
+#define _esdb_charset _citrus_esdb_charset
+#define _esdb_open _citrus_esdb_open
+#define _esdb_close _citrus_esdb_close
+#define _esdb_get_list _citrus_esdb_get_list
+#define _esdb_free_list _citrus_esdb_free_list
+#endif /* _CITRUS_ESDB_NO_NAMESPACE */
+
+/* citrus_hash */
+#ifndef _CITRUS_HASH_NO_NAMESPACE
+#define _citrus_string_hash_func _string_hash_func
+#endif /* _CITRUS_HASH_NO_NAMESPACE */
+
+/* citrus_mapper */
+#ifndef _CITRUS_MAPPER_NO_NAMESPACE
+#define _mapper _citrus_mapper
+#define _mapper_ops _citrus_mapper_ops
+#define _mapper_traits _citrus_mapper_traits
+#define _mapper_open _citrus_mapper_open
+#define _mapper_open_direct _citrus_mapper_open_direct
+#define _mapper_close _citrus_mapper_close
+#define _MAPPER_CONVERT_SUCCESS _CITRUS_MAPPER_CONVERT_SUCCESS
+#define _MAPPER_CONVERT_NONIDENTICAL _CITRUS_MAPPER_CONVERT_NONIDENTICAL
+#define _MAPPER_CONVERT_SRC_MORE _CITRUS_MAPPER_CONVERT_SRC_MORE
+#define _MAPPER_CONVERT_DST_MORE _CITRUS_MAPPER_CONVERT_DST_MORE
+#define _MAPPER_CONVERT_ILSEQ _CITRUS_MAPPER_CONVERT_ILSEQ
+#define _MAPPER_CONVERT_FATAL _CITRUS_MAPPER_CONVERT_FATAL
+#define _mapper_convert _citrus_mapper_convert
+#define _mapper_init_state _citrus_mapper_init_state
+#define _mapper_get_state_size _citrus_mapper_get_state_size
+#define _mapper_get_src_max _citrus_mapper_get_src_max
+#define _mapper_get_dst_max _citrus_mapper_get_dst_max
+#define _mapper_set_persistent _citrus_mapper_set_persistent
+#endif /* _CITRUS_MAPPER_NO_NAMESPACE */
+
+/* citrus_memstream */
+#ifndef _CITRUS_MEMSTREAM_NO_NAMESPACE
+#define _memstream _citrus_memory_stream
+#define _memstream_getln _citrus_memory_stream_getln
+#define _memstream_matchline _citrus_memory_stream_matchline
+#define _memstream_chr _citrus_memory_stream_chr
+#define _memstream_skip_ws _citrus_memory_stream_skip_ws
+#define _memstream_iseof _citrus_memory_stream_iseof
+#define _memstream_bind _citrus_memory_stream_bind
+#define _memstream_bind_ptr _citrus_memory_stream_bind_ptr
+#define _memstream_seek _citrus_memory_stream_seek
+#define _memstream_rewind _citrus_memory_stream_rewind
+#define _memstream_tell _citrus_memory_stream_tell
+#define _memstream_remainder _citrus_memory_stream_remainder
+#define _memstream_getc _citrus_memory_stream_getc
+#define _memstream_ungetc _citrus_memory_stream_ungetc
+#define _memstream_peek _citrus_memory_stream_peek
+#define _memstream_getregion _citrus_memory_stream_getregion
+#define _memstream_getln_region _citrus_memory_stream_getln_region
+#endif /* _CITRUS_MEMSTREAM_NO_NAMESPACE */
+
+/* citrus_mmap */
+#ifndef _CITRUS_MMAP_NO_NAMESPACE
+#define _map_file _citrus_map_file
+#define _unmap_file _citrus_unmap_file
+#endif /* _CITRUS_MMAP_NO_NAMESPACE */
+
+#ifndef _CITRUS_PIVOT_NO_NAMESPACE
+#define _pivot_factory_convert _citrus_pivot_factory_convert
+#endif /* _CITRUS_PIVOT_NO_NAMESPACE */
+
+/* citrus_region.h */
+#ifndef _CITRUS_REGION_NO_NAMESPACE
+#define _region _citrus_region
+#define _region_init _citrus_region_init
+#define _region_head _citrus_region_head
+#define _region_size _citrus_region_size
+#define _region_check _citrus_region_check
+#define _region_offset _citrus_region_offset
+#define _region_peek8 _citrus_region_peek8
+#define _region_peek16 _citrus_region_peek16
+#define _region_peek32 _citrus_region_peek32
+#define _region_get_subregion _citrus_region_get_subregion
+#endif /* _CITRUS_REGION_NO_NAMESPACE */
+
+/* citrus_stdenc.h */
+#ifndef _CITRUS_STDENC_NO_NAMESPACE
+#define _stdenc _citrus_stdenc
+#define _stdenc_ops _citrus_stdenc_ops
+#define _stdenc_traits _citrus_stdenc_traits
+#define _stdenc_state_desc _citrus_stdenc_state_desc
+#define _stdenc_open _citrus_stdenc_open
+#define _stdenc_close _citrus_stdenc_close
+#define _stdenc_init_state _citrus_stdenc_init_state
+#define _stdenc_mbtocs _citrus_stdenc_mbtocs
+#define _stdenc_cstomb _citrus_stdenc_cstomb
+#define _stdenc_mbtowc _citrus_stdenc_mbtowc
+#define _stdenc_wctomb _citrus_stdenc_wctomb
+#define _stdenc_put_state_reset _citrus_stdenc_put_state_reset
+#define _stdenc_get_state_size _citrus_stdenc_get_state_size
+#define _stdenc_get_mb_cur_max _citrus_stdenc_get_mb_cur_max
+#define _stdenc_get_state_desc _citrus_stdenc_get_state_desc
+#define _STDENC_SDID_GENERIC _CITRUS_STDENC_SDID_GENERIC
+#define _STDENC_SDGEN_UNKNOWN _CITRUS_STDENC_SDGEN_UNKNOWN
+#define _STDENC_SDGEN_INITIAL _CITRUS_STDENC_SDGEN_INITIAL
+#define _STDENC_SDGEN_STABLE _CITRUS_STDENC_SDGEN_STABLE
+#define _STDENC_SDGEN_INCOMPLETE_CHAR _CITRUS_STDENC_SDGEN_INCOMPLETE_CHAR
+#define _STDENC_SDGEN_INCOMPLETE_SHIFT _CITRUS_STDENC_SDGEN_INCOMPLETE_SHIFT
+#endif /* _CITRUS_STDENC_NO_NAMESPACE */
+
+/* citrus_types.h */
+#ifndef _CITRUS_TYPES_NO_NAMESPACE
+#define _index_t _citrus_index_t
+#define _csid_t _citrus_csid_t
+#define _wc_t _citrus_wc_t
+#endif /* _CITRUS_TYPES_NO_NAMESPACE */
+
+#endif
diff --git a/lib/libc/iconv/citrus_none.c b/lib/libc/iconv/citrus_none.c
new file mode 100644
index 0000000..9ec4bd3
--- /dev/null
+++ b/lib/libc/iconv/citrus_none.c
@@ -0,0 +1,237 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_none.c,v 1.18 2008/06/14 16:01:07 tnozaki Exp $ */
+
+/*-
+ * Copyright (c) 2002 Citrus Project,
+ * Copyright (c) 2010 Gabor Kovesdan <gabor@FreeBSD.org>,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <iconv.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_none.h"
+#include "citrus_stdenc.h"
+
+_CITRUS_STDENC_DECLS(NONE);
+_CITRUS_STDENC_DEF_OPS(NONE);
+struct _citrus_stdenc_traits _citrus_NONE_stdenc_traits = {
+ 0, /* et_state_size */
+ 1, /* mb_cur_max */
+};
+
+static int
+_citrus_NONE_stdenc_init(struct _citrus_stdenc * __restrict ce,
+ const void *var __unused, size_t lenvar __unused,
+ struct _citrus_stdenc_traits * __restrict et)
+{
+
+ et->et_state_size = 0;
+ et->et_mb_cur_max = 1;
+
+ ce->ce_closure = NULL;
+
+ return (0);
+}
+
+static void
+_citrus_NONE_stdenc_uninit(struct _citrus_stdenc *ce __unused)
+{
+
+}
+
+static int
+_citrus_NONE_stdenc_init_state(struct _citrus_stdenc * __restrict ce __unused,
+ void * __restrict ps __unused)
+{
+
+ return (0);
+}
+
+static int
+_citrus_NONE_stdenc_mbtocs(struct _citrus_stdenc * __restrict ce __unused,
+ _csid_t *csid, _index_t *idx, char **s, size_t n,
+ void *ps __unused, size_t *nresult, struct iconv_hooks *hooks)
+{
+
+ if (n < 1) {
+ *nresult = (size_t)-2;
+ return (0);
+ }
+
+ *csid = 0;
+ *idx = (_index_t)(unsigned char)*(*s)++;
+ *nresult = *idx == 0 ? 0 : 1;
+
+ if ((hooks != NULL) && (hooks->uc_hook != NULL))
+ hooks->uc_hook((unsigned int)*idx, hooks->data);
+
+ return (0);
+}
+
+static int
+_citrus_NONE_stdenc_cstomb(struct _citrus_stdenc * __restrict ce __unused,
+ char *s, size_t n, _csid_t csid, _index_t idx, void *ps __unused,
+ size_t *nresult, struct iconv_hooks *hooks __unused)
+{
+
+ if (csid == _CITRUS_CSID_INVALID) {
+ *nresult = 0;
+ return (0);
+ }
+ if (csid != 0)
+ return (EILSEQ);
+
+ if ((idx & 0x000000FF) == idx) {
+ if (n < 1) {
+ *nresult = (size_t)-1;
+ return (E2BIG);
+ }
+ *s = (char)idx;
+ *nresult = 1;
+ } else if ((idx & 0x0000FFFF) == idx) {
+ if (n < 2) {
+ *nresult = (size_t)-1;
+ return (E2BIG);
+ }
+ s[0] = (char)idx;
+ /* XXX: might be endian dependent */
+ s[1] = (char)(idx >> 8);
+ *nresult = 2;
+ } else if ((idx & 0x00FFFFFF) == idx) {
+ if (n < 3) {
+ *nresult = (size_t)-1;
+ return (E2BIG);
+ }
+ s[0] = (char)idx;
+ /* XXX: might be endian dependent */
+ s[1] = (char)(idx >> 8);
+ s[2] = (char)(idx >> 16);
+ *nresult = 3;
+ } else {
+ if (n < 3) {
+ *nresult = (size_t)-1;
+ return (E2BIG);
+ }
+ s[0] = (char)idx;
+ /* XXX: might be endian dependent */
+ s[1] = (char)(idx >> 8);
+ s[2] = (char)(idx >> 16);
+ s[3] = (char)(idx >> 24);
+ *nresult = 4;
+ }
+
+ return (0);
+}
+
+static int
+_citrus_NONE_stdenc_mbtowc(struct _citrus_stdenc * __restrict ce __unused,
+ _wc_t * __restrict pwc, char ** __restrict s, size_t n,
+ void * __restrict pspriv __unused, size_t * __restrict nresult,
+ struct iconv_hooks *hooks)
+{
+
+ if (s == NULL) {
+ *nresult = 0;
+ return (0);
+ }
+ if (n == 0) {
+ *nresult = (size_t)-2;
+ return (0);
+ }
+
+ if (pwc != NULL)
+ *pwc = (_wc_t)(unsigned char) **s;
+
+ *nresult = *s == '\0' ? 0 : 1;
+
+ if ((hooks != NULL) && (hooks->wc_hook != NULL))
+ hooks->wc_hook(*pwc, hooks->data);
+
+ return (0);
+}
+
+static int
+_citrus_NONE_stdenc_wctomb(struct _citrus_stdenc * __restrict ce __unused,
+ char * __restrict s, size_t n, _wc_t wc,
+ void * __restrict pspriv __unused, size_t * __restrict nresult,
+ struct iconv_hooks *hooks __unused)
+{
+
+ if ((wc & ~0xFFU) != 0) {
+ *nresult = (size_t)-1;
+ return (EILSEQ);
+ }
+ if (n == 0) {
+ *nresult = (size_t)-1;
+ return (E2BIG);
+ }
+
+ *nresult = 1;
+ if (s != NULL && n > 0)
+ *s = (char)wc;
+
+ return (0);
+}
+
+static int
+_citrus_NONE_stdenc_put_state_reset(struct _citrus_stdenc * __restrict ce __unused,
+ char * __restrict s __unused, size_t n __unused,
+ void * __restrict pspriv __unused, size_t * __restrict nresult)
+{
+
+ *nresult = 0;
+
+ return (0);
+}
+
+static int
+_citrus_NONE_stdenc_get_state_desc(struct _stdenc * __restrict ce __unused,
+ void * __restrict ps __unused, int id,
+ struct _stdenc_state_desc * __restrict d)
+{
+ int ret = 0;
+
+ switch (id) {
+ case _STDENC_SDID_GENERIC:
+ d->u.generic.state = _STDENC_SDGEN_INITIAL;
+ break;
+ default:
+ ret = EOPNOTSUPP;
+ }
+
+ return (ret);
+}
diff --git a/lib/libc/iconv/citrus_none.h b/lib/libc/iconv/citrus_none.h
new file mode 100644
index 0000000..20d2791
--- /dev/null
+++ b/lib/libc/iconv/citrus_none.h
@@ -0,0 +1,36 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_none.h,v 1.3 2003/06/25 09:51:38 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2002 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_NONE_H_
+#define _CITRUS_NONE_H_
+
+extern struct _citrus_stdenc_ops _citrus_NONE_stdenc_ops;
+extern struct _citrus_stdenc_traits _citrus_NONE_stdenc_traits;
+
+#endif
diff --git a/lib/libc/iconv/citrus_pivot_factory.c b/lib/libc/iconv/citrus_pivot_factory.c
new file mode 100644
index 0000000..0f279b1
--- /dev/null
+++ b/lib/libc/iconv/citrus_pivot_factory.c
@@ -0,0 +1,225 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_pivot_factory.c,v 1.7 2009/04/12 14:20:19 lukem Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/queue.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_region.h"
+#include "citrus_bcs.h"
+#include "citrus_db_factory.h"
+#include "citrus_db_hash.h"
+#include "citrus_pivot_file.h"
+#include "citrus_pivot_factory.h"
+
+struct src_entry {
+ char *se_name;
+ struct _citrus_db_factory *se_df;
+ STAILQ_ENTRY(src_entry) se_entry;
+};
+STAILQ_HEAD(src_head, src_entry);
+
+static int
+find_src(struct src_head *sh, struct src_entry **rse, const char *name)
+{
+ int ret;
+ struct src_entry *se;
+
+ STAILQ_FOREACH(se, sh, se_entry) {
+ if (_bcs_strcasecmp(se->se_name, name) == 0) {
+ *rse = se;
+ return (0);
+ }
+ }
+ se = malloc(sizeof(*se));
+ if (se == NULL)
+ return (errno);
+ se->se_name = strdup(name);
+ if (se->se_name == NULL) {
+ ret = errno;
+ free(se);
+ return (ret);
+ }
+ ret = _db_factory_create(&se->se_df, &_db_hash_std, NULL);
+ if (ret) {
+ free(se->se_name);
+ free(se);
+ return (ret);
+ }
+ STAILQ_INSERT_TAIL(sh, se, se_entry);
+ *rse = se;
+
+ return (0);
+}
+
+static void
+free_src(struct src_head *sh)
+{
+ struct src_entry *se;
+
+ while ((se = STAILQ_FIRST(sh)) != NULL) {
+ STAILQ_REMOVE_HEAD(sh, se_entry);
+ _db_factory_free(se->se_df);
+ free(se->se_name);
+ free(se);
+ }
+}
+
+
+#define T_COMM '#'
+static int
+convert_line(struct src_head *sh, const char *line, size_t len)
+{
+ struct src_entry *se;
+ const char *p;
+ char key1[LINE_MAX], key2[LINE_MAX], data[LINE_MAX];
+ char *ep;
+ uint32_t val;
+ int ret;
+
+ se = NULL;
+
+ /* cut off trailing comment */
+ p = memchr(line, T_COMM, len);
+ if (p)
+ len = p - line;
+
+ /* key1 */
+ line = _bcs_skip_ws_len(line, &len);
+ if (len == 0)
+ return (0);
+ p = _bcs_skip_nonws_len(line, &len);
+ if (p == line)
+ return (0);
+ snprintf(key1, sizeof(key1), "%.*s", (int)(p - line), line);
+
+ /* key2 */
+ line = _bcs_skip_ws_len(p, &len);
+ if (len == 0)
+ return (0);
+ p = _bcs_skip_nonws_len(line, &len);
+ if (p == line)
+ return (0);
+ snprintf(key2, sizeof(key2), "%.*s", (int)(p - line), line);
+
+ /* data */
+ line = _bcs_skip_ws_len(p, &len);
+ _bcs_trunc_rws_len(line, &len);
+ snprintf(data, sizeof(data), "%.*s", (int)len, line);
+ val = strtoul(data, &ep, 0);
+ if (*ep != '\0')
+ return (EFTYPE);
+
+ /* insert to DB */
+ ret = find_src(sh, &se, key1);
+ if (ret)
+ return (ret);
+
+ return (_db_factory_add32_by_s(se->se_df, key2, val));
+}
+
+static int
+dump_db(struct src_head *sh, struct _region *r)
+{
+ struct _db_factory *df;
+ struct src_entry *se;
+ struct _region subr;
+ void *ptr;
+ size_t size;
+ int ret;
+
+ ret = _db_factory_create(&df, &_db_hash_std, NULL);
+ if (ret)
+ return (ret);
+
+ STAILQ_FOREACH(se, sh, se_entry) {
+ size = _db_factory_calc_size(se->se_df);
+ ptr = malloc(size);
+ if (ptr == NULL)
+ goto quit;
+ _region_init(&subr, ptr, size);
+ ret = _db_factory_serialize(se->se_df, _CITRUS_PIVOT_SUB_MAGIC,
+ &subr);
+ if (ret)
+ goto quit;
+ ret = _db_factory_add_by_s(df, se->se_name, &subr, 1);
+ if (ret)
+ goto quit;
+ }
+
+ size = _db_factory_calc_size(df);
+ ptr = malloc(size);
+ if (ptr == NULL)
+ goto quit;
+ _region_init(r, ptr, size);
+
+ ret = _db_factory_serialize(df, _CITRUS_PIVOT_MAGIC, r);
+ ptr = NULL;
+
+quit:
+ free(ptr);
+ _db_factory_free(df);
+ return (ret);
+}
+
+int
+_citrus_pivot_factory_convert(FILE *out, FILE *in)
+{
+ struct src_head sh;
+ struct _region r;
+ char *line;
+ size_t size;
+ int ret;
+
+ STAILQ_INIT(&sh);
+
+ while ((line = fgetln(in, &size)) != NULL)
+ if ((ret = convert_line(&sh, line, size))) {
+ free_src(&sh);
+ return (ret);
+ }
+
+ ret = dump_db(&sh, &r);
+ free_src(&sh);
+ if (ret)
+ return (ret);
+
+ if (fwrite(_region_head(&r), _region_size(&r), 1, out) != 1)
+ return (errno);
+
+ return (0);
+}
diff --git a/lib/libc/iconv/citrus_pivot_factory.h b/lib/libc/iconv/citrus_pivot_factory.h
new file mode 100644
index 0000000..76f0f70
--- /dev/null
+++ b/lib/libc/iconv/citrus_pivot_factory.h
@@ -0,0 +1,37 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_pivot_factory.h,v 1.1 2003/06/25 09:51:39 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_PIVOT_FACTORY_H_
+#define _CITRUS_PIVOT_FACTORY_H_
+
+__BEGIN_DECLS
+int _citrus_pivot_factory_convert(FILE *, FILE *);
+__END_DECLS
+
+#endif
diff --git a/lib/libc/iconv/citrus_pivot_file.h b/lib/libc/iconv/citrus_pivot_file.h
new file mode 100644
index 0000000..454e93a
--- /dev/null
+++ b/lib/libc/iconv/citrus_pivot_file.h
@@ -0,0 +1,36 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_pivot_file.h,v 1.1 2003/06/25 09:51:39 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef _CITRUS_PIVOT_FILE_H_
+#define _CITRUS_PIVOT_FILE_H_
+
+#define _CITRUS_PIVOT_MAGIC "CSPIVOT\0"
+#define _CITRUS_PIVOT_SUB_MAGIC "CSPIVSUB"
+
+#endif
diff --git a/lib/libc/iconv/citrus_prop.c b/lib/libc/iconv/citrus_prop.c
new file mode 100644
index 0000000..c2d4829
--- /dev/null
+++ b/lib/libc/iconv/citrus_prop.c
@@ -0,0 +1,444 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_prop.c,v 1.3 2006/11/22 23:47:21 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_bcs.h"
+#include "citrus_region.h"
+#include "citrus_memstream.h"
+#include "citrus_prop.h"
+
+typedef struct {
+ _citrus_prop_type_t type;
+ union {
+ const char *str;
+ int chr;
+ bool boolean;
+ uint64_t num;
+ } u;
+} _citrus_prop_object_t;
+
+static __inline void
+_citrus_prop_object_init(_citrus_prop_object_t *obj, _citrus_prop_type_t type)
+{
+
+ obj->type = type;
+ memset(&obj->u, 0, sizeof(obj->u));
+}
+
+static __inline void
+_citrus_prop_object_uninit(_citrus_prop_object_t *obj)
+{
+
+ if (obj->type == _CITRUS_PROP_STR)
+ free(__DECONST(void *, obj->u.str));
+}
+
+static const char *xdigit = "0123456789ABCDEF";
+
+#define _CITRUS_PROP_READ_UINT_COMMON(_func_, _type_, _max_) \
+static int \
+_citrus_prop_read_##_func_##_common(struct _memstream * __restrict ms, \
+ _type_ * __restrict result, int base) \
+{ \
+ _type_ acc, cutoff; \
+ int ch, cutlim, n; \
+ char *p; \
+ \
+ acc = (_type_)0; \
+ cutoff = _max_ / base; \
+ cutlim = _max_ % base; \
+ for (;;) { \
+ ch = _memstream_getc(ms); \
+ p = strchr(xdigit, _bcs_toupper(ch)); \
+ if (p == NULL || (n = (p - xdigit)) >= base) \
+ break; \
+ if (acc > cutoff || (acc == cutoff && n > cutlim)) \
+ break; \
+ acc *= base; \
+ acc += n; \
+ } \
+ _memstream_ungetc(ms, ch); \
+ *result = acc; \
+ return (0); \
+}
+_CITRUS_PROP_READ_UINT_COMMON(chr, int, UCHAR_MAX)
+_CITRUS_PROP_READ_UINT_COMMON(num, uint64_t, UINT64_MAX)
+#undef _CITRUS_PROP_READ_UINT_COMMON
+
+#define _CITRUS_PROP_READ_INT(_func_, _type_) \
+static int \
+_citrus_prop_read_##_func_(struct _memstream * __restrict ms, \
+ _citrus_prop_object_t * __restrict obj) \
+{ \
+ int base, ch, neg; \
+ \
+ _memstream_skip_ws(ms); \
+ ch = _memstream_getc(ms); \
+ neg = 0; \
+ switch (ch) { \
+ case '-': \
+ neg = 1; \
+ case '+': \
+ ch = _memstream_getc(ms); \
+ } \
+ base = 10; \
+ if (ch == '0') { \
+ base -= 2; \
+ ch = _memstream_getc(ms); \
+ if (ch == 'x' || ch == 'X') { \
+ ch = _memstream_getc(ms); \
+ if (_bcs_isxdigit(ch) == 0) { \
+ _memstream_ungetc(ms, ch); \
+ obj->u._func_ = 0; \
+ return (0); \
+ } \
+ base += 8; \
+ } \
+ } else if (_bcs_isdigit(ch) == 0) \
+ return (EINVAL); \
+ _memstream_ungetc(ms, ch); \
+ return (_citrus_prop_read_##_func_##_common \
+ (ms, &obj->u._func_, base)); \
+}
+_CITRUS_PROP_READ_INT(chr, int)
+_CITRUS_PROP_READ_INT(num, uint64_t)
+#undef _CITRUS_PROP_READ_INT
+
+static int
+_citrus_prop_read_character_common(struct _memstream * __restrict ms,
+ int * __restrict result)
+{
+ int base, ch;
+
+ ch = _memstream_getc(ms);
+ if (ch != '\\')
+ *result = ch;
+ else {
+ ch = _memstream_getc(ms);
+ base = 16;
+ switch (ch) {
+ case 'a':
+ *result = '\a';
+ break;
+ case 'b':
+ *result = '\b';
+ break;
+ case 'f':
+ *result = '\f';
+ break;
+ case 'n':
+ *result = '\n';
+ break;
+ case 'r':
+ *result = '\r';
+ break;
+ case 't':
+ *result = '\t';
+ break;
+ case 'v':
+ *result = '\v';
+ break;
+ case '0': case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ _memstream_ungetc(ms, ch);
+ base -= 8;
+ /*FALLTHROUGH*/
+ case 'x':
+ return (_citrus_prop_read_chr_common(ms, result, base));
+ /*NOTREACHED*/
+ default:
+ /* unknown escape */
+ *result = ch;
+ }
+ }
+ return (0);
+}
+
+static int
+_citrus_prop_read_character(struct _memstream * __restrict ms,
+ _citrus_prop_object_t * __restrict obj)
+{
+ int ch, errnum;
+
+ _memstream_skip_ws(ms);
+ ch = _memstream_getc(ms);
+ if (ch != '\'') {
+ _memstream_ungetc(ms, ch);
+ return (_citrus_prop_read_chr(ms, obj));
+ }
+ errnum = _citrus_prop_read_character_common(ms, &ch);
+ if (errnum != 0)
+ return (errnum);
+ obj->u.chr = ch;
+ ch = _memstream_getc(ms);
+ if (ch != '\'')
+ return (EINVAL);
+ return (0);
+}
+
+static int
+_citrus_prop_read_bool(struct _memstream * __restrict ms,
+ _citrus_prop_object_t * __restrict obj)
+{
+
+ _memstream_skip_ws(ms);
+ switch (_bcs_tolower(_memstream_getc(ms))) {
+ case 't':
+ if (_bcs_tolower(_memstream_getc(ms)) == 'r' &&
+ _bcs_tolower(_memstream_getc(ms)) == 'u' &&
+ _bcs_tolower(_memstream_getc(ms)) == 'e') {
+ obj->u.boolean = true;
+ return (0);
+ }
+ break;
+ case 'f':
+ if (_bcs_tolower(_memstream_getc(ms)) == 'a' &&
+ _bcs_tolower(_memstream_getc(ms)) == 'l' &&
+ _bcs_tolower(_memstream_getc(ms)) == 's' &&
+ _bcs_tolower(_memstream_getc(ms)) == 'e') {
+ obj->u.boolean = false;
+ return (0);
+ }
+ }
+ return (EINVAL);
+}
+
+static int
+_citrus_prop_read_str(struct _memstream * __restrict ms,
+ _citrus_prop_object_t * __restrict obj)
+{
+ int ch, errnum, quot;
+ char *s, *t;
+#define _CITRUS_PROP_STR_BUFSIZ 512
+ size_t m, n;
+
+ m = _CITRUS_PROP_STR_BUFSIZ;
+ s = malloc(m);
+ if (s == NULL)
+ return (ENOMEM);
+ n = 0;
+ _memstream_skip_ws(ms);
+ quot = _memstream_getc(ms);
+ switch (quot) {
+ case EOF:
+ goto done;
+ /*NOTREACHED*/
+ case '\\':
+ _memstream_ungetc(ms, quot);
+ quot = EOF;
+ /*FALLTHROUGH*/
+ case '\"': case '\'':
+ break;
+ default:
+ s[n] = quot;
+ ++n, --m;
+ quot = EOF;
+ }
+ for (;;) {
+ if (m < 1) {
+ m = _CITRUS_PROP_STR_BUFSIZ;
+ t = realloc(s, n + m);
+ if (t == NULL) {
+ free(s);
+ return (ENOMEM);
+ }
+ s = t;
+ }
+ ch = _memstream_getc(ms);
+ if (quot == ch || (quot == EOF &&
+ (ch == ';' || _bcs_isspace(ch)))) {
+done:
+ s[n] = '\0';
+ obj->u.str = (const char *)s;
+ return (0);
+ }
+ _memstream_ungetc(ms, ch);
+ errnum = _citrus_prop_read_character_common(ms, &ch);
+ if (errnum != 0)
+ return (errnum);
+ s[n] = ch;
+ ++n, --m;
+ }
+ free(s);
+ return (EINVAL);
+#undef _CITRUS_PROP_STR_BUFSIZ
+}
+
+typedef int (*_citrus_prop_read_type_t)(struct _memstream * __restrict,
+ _citrus_prop_object_t * __restrict);
+
+static const _citrus_prop_read_type_t readers[] = {
+ _citrus_prop_read_bool,
+ _citrus_prop_read_str,
+ _citrus_prop_read_character,
+ _citrus_prop_read_num,
+};
+
+static __inline int
+_citrus_prop_read_symbol(struct _memstream * __restrict ms,
+ char * __restrict s, size_t n)
+{
+ int ch;
+ size_t m;
+
+ for (m = 0; m < n; ++m) {
+ ch = _memstream_getc(ms);
+ if (ch != '_' && _bcs_isalnum(ch) == 0)
+ goto name_found;
+ s[m] = ch;
+ }
+ ch = _memstream_getc(ms);
+ if (ch == '_' || _bcs_isalnum(ch) != 0)
+ return (EINVAL);
+
+name_found:
+ _memstream_ungetc(ms, ch);
+ s[m] = '\0';
+
+ return (0);
+}
+
+static int
+_citrus_prop_parse_element(struct _memstream * __restrict ms,
+ const _citrus_prop_hint_t * __restrict hints, void ** __restrict context)
+{
+ int ch, errnum;
+#define _CITRUS_PROP_HINT_NAME_LEN_MAX 255
+ char name[_CITRUS_PROP_HINT_NAME_LEN_MAX + 1];
+ const _citrus_prop_hint_t *hint;
+ _citrus_prop_object_t ostart, oend;
+
+ errnum = _citrus_prop_read_symbol(ms, name, sizeof(name));
+ if (errnum != 0)
+ return (errnum);
+ for (hint = hints; hint->name != NULL; ++hint)
+ if (_citrus_bcs_strcasecmp(name, hint->name) == 0)
+ goto hint_found;
+ return (EINVAL);
+
+hint_found:
+ _memstream_skip_ws(ms);
+ ch = _memstream_getc(ms);
+ if (ch != '=' && ch != ':')
+ _memstream_ungetc(ms, ch);
+ do {
+ _citrus_prop_object_init(&ostart, hint->type);
+ _citrus_prop_object_init(&oend, hint->type);
+ errnum = (*readers[hint->type])(ms, &ostart);
+ if (errnum != 0)
+ return (errnum);
+ _memstream_skip_ws(ms);
+ ch = _memstream_getc(ms);
+ switch (hint->type) {
+ case _CITRUS_PROP_BOOL:
+ /*FALLTHROUGH*/
+ case _CITRUS_PROP_STR:
+ break;
+ default:
+ if (ch != '-')
+ break;
+ errnum = (*readers[hint->type])(ms, &oend);
+ if (errnum != 0)
+ return (errnum);
+ _memstream_skip_ws(ms);
+ ch = _memstream_getc(ms);
+ }
+#define CALL0(_func_) \
+do { \
+ errnum = (*hint->cb._func_.func)(context, \
+ hint->name, ostart.u._func_); \
+} while (0)
+#define CALL1(_func_) \
+do { \
+ errnum = (*hint->cb._func_.func)(context, \
+ hint->name, ostart.u._func_, oend.u._func_);\
+} while (0)
+ switch (hint->type) {
+ case _CITRUS_PROP_BOOL:
+ CALL0(boolean);
+ break;
+ case _CITRUS_PROP_STR:
+ CALL0(str);
+ break;
+ case _CITRUS_PROP_CHR:
+ CALL1(chr);
+ break;
+ case _CITRUS_PROP_NUM:
+ CALL1(num);
+ break;
+ default:
+ abort();
+ /*NOTREACHED*/
+ }
+#undef CALL0
+#undef CALL1
+ _citrus_prop_object_uninit(&ostart);
+ _citrus_prop_object_uninit(&oend);
+ if (errnum != 0)
+ return (errnum);
+ } while (ch == ',');
+ if (ch != ';')
+ _memstream_ungetc(ms, ch);
+ return (0);
+}
+
+int
+_citrus_prop_parse_variable(const _citrus_prop_hint_t * __restrict hints,
+ void * __restrict context, const void *var, size_t lenvar)
+{
+ struct _memstream ms;
+ int ch, errnum;
+
+ _memstream_bind_ptr(&ms, __DECONST(void *, var), lenvar);
+ for (;;) {
+ _memstream_skip_ws(&ms);
+ ch = _memstream_getc(&ms);
+ if (ch == EOF || ch == '\0')
+ break;
+ _memstream_ungetc(&ms, ch);
+ errnum = _citrus_prop_parse_element(
+ &ms, hints, (void ** __restrict)context);
+ if (errnum != 0)
+ return (errnum);
+ }
+ return (0);
+}
diff --git a/lib/libc/iconv/citrus_prop.h b/lib/libc/iconv/citrus_prop.h
new file mode 100644
index 0000000..db087a4
--- /dev/null
+++ b/lib/libc/iconv/citrus_prop.h
@@ -0,0 +1,92 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_prop.h,v 1.3 2006/11/23 13:59:03 tnozaki Exp $ */
+
+/*-
+ * Copyright (c)2006 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_PROP_H_
+#define _CITRUS_PROP_H_
+
+typedef enum {
+ _CITRUS_PROP_BOOL = 0,
+ _CITRUS_PROP_STR = 1,
+ _CITRUS_PROP_CHR = 2,
+ _CITRUS_PROP_NUM = 3,
+} _citrus_prop_type_t;
+
+typedef struct _citrus_prop_hint_t _citrus_prop_hint_t;
+
+#define _CITRUS_PROP_CB0_T(_func_, _type_) \
+typedef int (*_citrus_prop_##_func_##_cb_func_t) \
+ (void ** __restrict, const char *, _type_); \
+typedef struct { \
+ _citrus_prop_##_func_##_cb_func_t func; \
+} _citrus_prop_##_func_##_cb_t;
+_CITRUS_PROP_CB0_T(boolean, int)
+_CITRUS_PROP_CB0_T(str, const char *)
+#undef _CITRUS_PROP_CB0_T
+
+#define _CITRUS_PROP_CB1_T(_func_, _type_) \
+typedef int (*_citrus_prop_##_func_##_cb_func_t) \
+ (void ** __restrict, const char *, _type_, _type_); \
+typedef struct { \
+ _citrus_prop_##_func_##_cb_func_t func; \
+} _citrus_prop_##_func_##_cb_t;
+_CITRUS_PROP_CB1_T(chr, int)
+_CITRUS_PROP_CB1_T(num, uint64_t)
+#undef _CITRUS_PROP_CB1_T
+
+struct _citrus_prop_hint_t {
+ const char *name;
+ _citrus_prop_type_t type;
+#define _CITRUS_PROP_CB_T_OPS(_name_) \
+ _citrus_prop_##_name_##_cb_t _name_
+ union {
+ _CITRUS_PROP_CB_T_OPS(boolean);
+ _CITRUS_PROP_CB_T_OPS(str);
+ _CITRUS_PROP_CB_T_OPS(chr);
+ _CITRUS_PROP_CB_T_OPS(num);
+ } cb;
+};
+
+#define _CITRUS_PROP_HINT_BOOL(name, cb) \
+ { name, _CITRUS_PROP_BOOL, { .boolean = { cb } } }
+#define _CITRUS_PROP_HINT_STR(name, cb) \
+ { name, _CITRUS_PROP_STR, { .str = { cb } } }
+#define _CITRUS_PROP_HINT_CHR(name, cb) \
+ { name, _CITRUS_PROP_CHR, { .chr = { cb } } }
+#define _CITRUS_PROP_HINT_NUM(name, cb) \
+ { name, _CITRUS_PROP_NUM, { .num = { cb } } }
+#define _CITRUS_PROP_HINT_END \
+ { NULL, _CITRUS_PROP_NUM, { .num = { 0 } } }
+
+__BEGIN_DECLS
+int _citrus_prop_parse_variable(const _citrus_prop_hint_t * __restrict,
+ void * __restrict, const void *, size_t);
+__END_DECLS
+
+#endif /* !_CITRUS_PROP_H_ */
diff --git a/lib/libc/iconv/citrus_region.h b/lib/libc/iconv/citrus_region.h
new file mode 100644
index 0000000..8cecb40
--- /dev/null
+++ b/lib/libc/iconv/citrus_region.h
@@ -0,0 +1,113 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_region.h,v 1.7 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_REGION_H_
+#define _CITRUS_REGION_H_
+
+#include <sys/types.h>
+
+struct _citrus_region {
+ void *r_head;
+ size_t r_size;
+};
+
+static __inline void
+_citrus_region_init(struct _citrus_region *r, void *h, size_t sz)
+{
+
+ r->r_head = h;
+ r->r_size = sz;
+}
+
+static __inline void *
+_citrus_region_head(const struct _citrus_region *r)
+{
+
+ return (r->r_head);
+}
+
+static __inline size_t
+_citrus_region_size(const struct _citrus_region *r)
+{
+
+ return (r->r_size);
+}
+
+static __inline int
+_citrus_region_check(const struct _citrus_region *r, size_t ofs, size_t sz)
+{
+
+ return (r->r_size >= ofs + sz ? 0 : -1);
+}
+
+static __inline void *
+_citrus_region_offset(const struct _citrus_region *r, size_t pos)
+{
+
+ return ((void *)((uint8_t *)r->r_head + pos));
+}
+
+static __inline uint8_t
+_citrus_region_peek8(const struct _citrus_region *r, size_t pos)
+{
+
+ return (*(uint8_t *)_citrus_region_offset(r, pos));
+}
+
+static __inline uint16_t
+_citrus_region_peek16(const struct _citrus_region *r, size_t pos)
+{
+ uint16_t val;
+
+ memcpy(&val, _citrus_region_offset(r, pos), (size_t)2);
+ return (val);
+}
+
+static __inline uint32_t
+_citrus_region_peek32(const struct _citrus_region *r, size_t pos)
+{
+ uint32_t val;
+
+ memcpy(&val, _citrus_region_offset(r, pos), (size_t)4);
+ return (val);
+}
+
+static __inline int
+_citrus_region_get_subregion(struct _citrus_region *subr,
+ const struct _citrus_region *r, size_t ofs, size_t sz)
+{
+
+ if (_citrus_region_check(r, ofs, sz))
+ return (-1);
+ _citrus_region_init(subr, _citrus_region_offset(r, ofs), sz);
+ return (0);
+}
+
+#endif
diff --git a/lib/libc/iconv/citrus_stdenc.c b/lib/libc/iconv/citrus_stdenc.c
new file mode 100644
index 0000000..b6562f8
--- /dev/null
+++ b/lib/libc/iconv/citrus_stdenc.c
@@ -0,0 +1,145 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_stdenc.c,v 1.3 2005/10/29 18:02:04 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_namespace.h"
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_none.h"
+#include "citrus_stdenc.h"
+
+struct _citrus_stdenc _citrus_stdenc_default = {
+ &_citrus_NONE_stdenc_ops, /* ce_ops */
+ NULL, /* ce_closure */
+ NULL, /* ce_module */
+ &_citrus_NONE_stdenc_traits, /* ce_traits */
+};
+
+int
+_citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict rce,
+ char const * __restrict encname, const void * __restrict variable,
+ size_t lenvar)
+{
+ struct _citrus_stdenc *ce;
+ _citrus_module_t handle;
+ _citrus_stdenc_getops_t getops;
+ int ret;
+
+ if (!strcmp(encname, _CITRUS_DEFAULT_STDENC_NAME)) {
+ *rce = &_citrus_stdenc_default;
+ return (0);
+ }
+ ce = malloc(sizeof(*ce));
+ if (ce == NULL) {
+ ret = errno;
+ goto bad;
+ }
+ ce->ce_ops = NULL;
+ ce->ce_closure = NULL;
+ ce->ce_module = NULL;
+ ce->ce_traits = NULL;
+
+ ret = _citrus_load_module(&handle, encname);
+ if (ret)
+ goto bad;
+
+ ce->ce_module = handle;
+
+ getops = (_citrus_stdenc_getops_t)_citrus_find_getops(ce->ce_module,
+ encname, "stdenc");
+ if (getops == NULL) {
+ ret = EINVAL;
+ goto bad;
+ }
+
+ ce->ce_ops = (struct _citrus_stdenc_ops *)malloc(sizeof(*ce->ce_ops));
+ if (ce->ce_ops == NULL) {
+ ret = errno;
+ goto bad;
+ }
+
+ ret = (*getops)(ce->ce_ops, sizeof(*ce->ce_ops));
+ if (ret)
+ goto bad;
+
+ /* validation check */
+ if (ce->ce_ops->eo_init == NULL ||
+ ce->ce_ops->eo_uninit == NULL ||
+ ce->ce_ops->eo_init_state == NULL ||
+ ce->ce_ops->eo_mbtocs == NULL ||
+ ce->ce_ops->eo_cstomb == NULL ||
+ ce->ce_ops->eo_mbtowc == NULL ||
+ ce->ce_ops->eo_wctomb == NULL ||
+ ce->ce_ops->eo_get_state_desc == NULL)
+ goto bad;
+
+ /* allocate traits */
+ ce->ce_traits = malloc(sizeof(*ce->ce_traits));
+ if (ce->ce_traits == NULL) {
+ ret = errno;
+ goto bad;
+ }
+ /* init and get closure */
+ ret = (*ce->ce_ops->eo_init)(ce, variable, lenvar, ce->ce_traits);
+ if (ret)
+ goto bad;
+
+ *rce = ce;
+
+ return (0);
+
+bad:
+ _citrus_stdenc_close(ce);
+ return (ret);
+}
+
+void
+_citrus_stdenc_close(struct _citrus_stdenc *ce)
+{
+
+ if (ce == &_citrus_stdenc_default)
+ return;
+
+ if (ce->ce_module) {
+ if (ce->ce_ops) {
+ if (ce->ce_closure && ce->ce_ops->eo_uninit)
+ (*ce->ce_ops->eo_uninit)(ce);
+ free(ce->ce_ops);
+ }
+ free(ce->ce_traits);
+ _citrus_unload_module(ce->ce_module);
+ }
+ free(ce);
+}
diff --git a/lib/libc/iconv/citrus_stdenc.h b/lib/libc/iconv/citrus_stdenc.h
new file mode 100644
index 0000000..50f4dff
--- /dev/null
+++ b/lib/libc/iconv/citrus_stdenc.h
@@ -0,0 +1,124 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_stdenc.h,v 1.4 2005/10/29 18:02:04 tshiozak Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_STDENC_H_
+#define _CITRUS_STDENC_H_
+
+struct _citrus_stdenc;
+struct _citrus_stdenc_ops;
+struct _citrus_stdenc_traits;
+
+#define _CITRUS_STDENC_SDID_GENERIC 0
+struct _citrus_stdenc_state_desc
+{
+ union {
+ struct {
+ int state;
+#define _CITRUS_STDENC_SDGEN_UNKNOWN 0
+#define _CITRUS_STDENC_SDGEN_INITIAL 1
+#define _CITRUS_STDENC_SDGEN_STABLE 2
+#define _CITRUS_STDENC_SDGEN_INCOMPLETE_CHAR 3
+#define _CITRUS_STDENC_SDGEN_INCOMPLETE_SHIFT 4
+ } generic;
+ } u;
+};
+
+#include "citrus_stdenc_local.h"
+
+__BEGIN_DECLS
+int _citrus_stdenc_open(struct _citrus_stdenc * __restrict * __restrict,
+ char const * __restrict, const void * __restrict, size_t);
+void _citrus_stdenc_close(struct _citrus_stdenc *);
+__END_DECLS
+
+static __inline int
+_citrus_stdenc_init_state(struct _citrus_stdenc * __restrict ce,
+ void * __restrict ps)
+{
+
+ return ((*ce->ce_ops->eo_init_state)(ce, ps));
+}
+
+static __inline int
+_citrus_stdenc_mbtocs(struct _citrus_stdenc * __restrict ce,
+ _citrus_csid_t * __restrict csid, _citrus_index_t * __restrict idx,
+ char ** __restrict s, size_t n, void * __restrict ps,
+ size_t * __restrict nresult, struct iconv_hooks *hooks)
+{
+
+ return ((*ce->ce_ops->eo_mbtocs)(ce, csid, idx, s, n, ps, nresult,
+ hooks));
+}
+
+static __inline int
+_citrus_stdenc_cstomb(struct _citrus_stdenc * __restrict ce,
+ char * __restrict s, size_t n, _citrus_csid_t csid, _citrus_index_t idx,
+ void * __restrict ps, size_t * __restrict nresult,
+ struct iconv_hooks *hooks)
+{
+
+ return ((*ce->ce_ops->eo_cstomb)(ce, s, n, csid, idx, ps, nresult,
+ hooks));
+}
+
+static __inline int
+_citrus_stdenc_wctomb(struct _citrus_stdenc * __restrict ce,
+ char * __restrict s, size_t n, _citrus_wc_t wc, void * __restrict ps,
+ size_t * __restrict nresult, struct iconv_hooks *hooks)
+{
+
+ return ((*ce->ce_ops->eo_wctomb)(ce, s, n, wc, ps, nresult, hooks));
+}
+
+static __inline int
+_citrus_stdenc_put_state_reset(struct _citrus_stdenc * __restrict ce,
+ char * __restrict s, size_t n, void * __restrict ps,
+ size_t * __restrict nresult)
+{
+
+ return ((*ce->ce_ops->eo_put_state_reset)(ce, s, n, ps, nresult));
+}
+
+static __inline size_t
+_citrus_stdenc_get_state_size(struct _citrus_stdenc *ce)
+{
+
+ return (ce->ce_traits->et_state_size);
+}
+
+static __inline int
+_citrus_stdenc_get_state_desc(struct _citrus_stdenc * __restrict ce,
+ void * __restrict ps, int id,
+ struct _citrus_stdenc_state_desc * __restrict d)
+{
+
+ return ((*ce->ce_ops->eo_get_state_desc)(ce, ps, id, d));
+}
+#endif
diff --git a/lib/libc/iconv/citrus_stdenc_local.h b/lib/libc/iconv/citrus_stdenc_local.h
new file mode 100644
index 0000000..c55387a
--- /dev/null
+++ b/lib/libc/iconv/citrus_stdenc_local.h
@@ -0,0 +1,161 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_stdenc_local.h,v 1.4 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#ifndef _CITRUS_STDENC_LOCAL_H_
+#define _CITRUS_STDENC_LOCAL_H_
+
+#include <iconv.h>
+
+#include "citrus_module.h"
+
+#define _CITRUS_STDENC_GETOPS_FUNC_BASE(n) \
+ int n(struct _citrus_stdenc_ops *, size_t)
+#define _CITRUS_STDENC_GETOPS_FUNC(_e_) \
+ _CITRUS_STDENC_GETOPS_FUNC_BASE(_citrus_##_e_##_stdenc_getops)
+typedef _CITRUS_STDENC_GETOPS_FUNC_BASE((*_citrus_stdenc_getops_t));
+
+
+#define _CITRUS_STDENC_DECLS(_e_) \
+static int _citrus_##_e_##_stdenc_init \
+ (struct _citrus_stdenc * __restrict, \
+ const void * __restrict, size_t, \
+ struct _citrus_stdenc_traits * __restrict); \
+static void _citrus_##_e_##_stdenc_uninit(struct _citrus_stdenc *);\
+static int _citrus_##_e_##_stdenc_init_state \
+ (struct _citrus_stdenc * __restrict, \
+ void * __restrict); \
+static int _citrus_##_e_##_stdenc_mbtocs \
+ (struct _citrus_stdenc * __restrict, \
+ _citrus_csid_t * __restrict, \
+ _citrus_index_t * __restrict, \
+ char ** __restrict, size_t, \
+ void * __restrict, size_t * __restrict, \
+ struct iconv_hooks *); \
+static int _citrus_##_e_##_stdenc_cstomb \
+ (struct _citrus_stdenc * __restrict, \
+ char * __restrict, size_t, _citrus_csid_t, \
+ _citrus_index_t, void * __restrict, \
+ size_t * __restrict, struct iconv_hooks *); \
+static int _citrus_##_e_##_stdenc_mbtowc \
+ (struct _citrus_stdenc * __restrict, \
+ _citrus_wc_t * __restrict, \
+ char ** __restrict, size_t, \
+ void * __restrict, size_t * __restrict, \
+ struct iconv_hooks *); \
+static int _citrus_##_e_##_stdenc_wctomb \
+ (struct _citrus_stdenc * __restrict, \
+ char * __restrict, size_t, _citrus_wc_t, \
+ void * __restrict, size_t * __restrict, \
+ struct iconv_hooks *); \
+static int _citrus_##_e_##_stdenc_put_state_reset \
+ (struct _citrus_stdenc * __restrict, \
+ char * __restrict, size_t, void * __restrict, \
+ size_t * __restrict); \
+static int _citrus_##_e_##_stdenc_get_state_desc \
+ (struct _citrus_stdenc * __restrict, \
+ void * __restrict, int, \
+ struct _citrus_stdenc_state_desc * __restrict)
+
+#define _CITRUS_STDENC_DEF_OPS(_e_) \
+struct _citrus_stdenc_ops _citrus_##_e_##_stdenc_ops = { \
+ /* eo_init */ &_citrus_##_e_##_stdenc_init, \
+ /* eo_uninit */ &_citrus_##_e_##_stdenc_uninit, \
+ /* eo_init_state */ &_citrus_##_e_##_stdenc_init_state, \
+ /* eo_mbtocs */ &_citrus_##_e_##_stdenc_mbtocs, \
+ /* eo_cstomb */ &_citrus_##_e_##_stdenc_cstomb, \
+ /* eo_mbtowc */ &_citrus_##_e_##_stdenc_mbtowc, \
+ /* eo_wctomb */ &_citrus_##_e_##_stdenc_wctomb, \
+ /* eo_put_state_reset */&_citrus_##_e_##_stdenc_put_state_reset,\
+ /* eo_get_state_desc */ &_citrus_##_e_##_stdenc_get_state_desc \
+}
+
+typedef int (*_citrus_stdenc_init_t)
+ (struct _citrus_stdenc * __reatrict, const void * __restrict , size_t,
+ struct _citrus_stdenc_traits * __restrict);
+typedef void (*_citrus_stdenc_uninit_t)(struct _citrus_stdenc * __restrict);
+typedef int (*_citrus_stdenc_init_state_t)
+ (struct _citrus_stdenc * __restrict, void * __restrict);
+typedef int (*_citrus_stdenc_mbtocs_t)
+ (struct _citrus_stdenc * __restrict,
+ _citrus_csid_t * __restrict, _citrus_index_t * __restrict,
+ char ** __restrict, size_t,
+ void * __restrict, size_t * __restrict,
+ struct iconv_hooks *);
+typedef int (*_citrus_stdenc_cstomb_t)
+ (struct _citrus_stdenc *__restrict, char * __restrict, size_t,
+ _citrus_csid_t, _citrus_index_t, void * __restrict,
+ size_t * __restrict, struct iconv_hooks *);
+typedef int (*_citrus_stdenc_mbtowc_t)
+ (struct _citrus_stdenc * __restrict,
+ _citrus_wc_t * __restrict,
+ char ** __restrict, size_t,
+ void * __restrict, size_t * __restrict,
+ struct iconv_hooks *);
+typedef int (*_citrus_stdenc_wctomb_t)
+ (struct _citrus_stdenc *__restrict, char * __restrict, size_t,
+ _citrus_wc_t, void * __restrict, size_t * __restrict,
+ struct iconv_hooks *);
+typedef int (*_citrus_stdenc_put_state_reset_t)
+ (struct _citrus_stdenc *__restrict, char * __restrict, size_t,
+ void * __restrict, size_t * __restrict);
+typedef int (*_citrus_stdenc_get_state_desc_t)
+ (struct _citrus_stdenc * __restrict, void * __restrict, int,
+ struct _citrus_stdenc_state_desc * __restrict);
+
+struct _citrus_stdenc_ops {
+ _citrus_stdenc_init_t eo_init;
+ _citrus_stdenc_uninit_t eo_uninit;
+ _citrus_stdenc_init_state_t eo_init_state;
+ _citrus_stdenc_mbtocs_t eo_mbtocs;
+ _citrus_stdenc_cstomb_t eo_cstomb;
+ _citrus_stdenc_mbtowc_t eo_mbtowc;
+ _citrus_stdenc_wctomb_t eo_wctomb;
+ _citrus_stdenc_put_state_reset_t eo_put_state_reset;
+ /* version 0x00000002 */
+ _citrus_stdenc_get_state_desc_t eo_get_state_desc;
+};
+
+struct _citrus_stdenc_traits {
+ /* version 0x00000001 */
+ size_t et_state_size;
+ size_t et_mb_cur_max;
+};
+
+struct _citrus_stdenc {
+ /* version 0x00000001 */
+ struct _citrus_stdenc_ops *ce_ops;
+ void *ce_closure;
+ _citrus_module_t ce_module;
+ struct _citrus_stdenc_traits *ce_traits;
+};
+
+#define _CITRUS_DEFAULT_STDENC_NAME "NONE"
+
+#endif
diff --git a/lib/libc/iconv/citrus_stdenc_template.h b/lib/libc/iconv/citrus_stdenc_template.h
new file mode 100644
index 0000000..9a05fa7
--- /dev/null
+++ b/lib/libc/iconv/citrus_stdenc_template.h
@@ -0,0 +1,211 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_stdenc_template.h,v 1.4 2008/02/09 14:56:20 junyoung Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <iconv.h>
+
+/*
+ * CAUTION: THIS IS NOT STANDALONE FILE
+ *
+ * function templates of iconv standard encoding handler for each encodings.
+ *
+ */
+
+/*
+ * macros
+ */
+
+#undef _TO_EI
+#undef _CE_TO_EI
+#undef _TO_STATE
+#define _TO_EI(_cl_) ((_ENCODING_INFO*)(_cl_))
+#define _CE_TO_EI(_ce_) (_TO_EI((_ce_)->ce_closure))
+#define _TO_STATE(_ps_) ((_ENCODING_STATE*)(_ps_))
+
+/* ----------------------------------------------------------------------
+ * templates for public functions
+ */
+
+int
+_FUNCNAME(stdenc_getops)(struct _citrus_stdenc_ops *ops,
+ size_t lenops __unused)
+{
+
+ memcpy(ops, &_FUNCNAME(stdenc_ops), sizeof(_FUNCNAME(stdenc_ops)));
+
+ return (0);
+}
+
+static int
+_FUNCNAME(stdenc_init)(struct _citrus_stdenc * __restrict ce,
+ const void * __restrict var, size_t lenvar,
+ struct _citrus_stdenc_traits * __restrict et)
+{
+ _ENCODING_INFO *ei;
+ int ret;
+
+ ei = NULL;
+ if (sizeof(_ENCODING_INFO) > 0) {
+ ei = calloc(1, sizeof(_ENCODING_INFO));
+ if (ei == NULL)
+ return (errno);
+ }
+
+ ret = _FUNCNAME(encoding_module_init)(ei, var, lenvar);
+ if (ret) {
+ free((void *)ei);
+ return (ret);
+ }
+
+ ce->ce_closure = ei;
+ et->et_state_size = sizeof(_ENCODING_STATE);
+ et->et_mb_cur_max = _ENCODING_MB_CUR_MAX(_CE_TO_EI(ce));
+
+ return (0);
+}
+
+static void
+_FUNCNAME(stdenc_uninit)(struct _citrus_stdenc * __restrict ce)
+{
+
+ if (ce) {
+ _FUNCNAME(encoding_module_uninit)(_CE_TO_EI(ce));
+ free(ce->ce_closure);
+ }
+}
+
+static int
+_FUNCNAME(stdenc_init_state)(struct _citrus_stdenc * __restrict ce,
+ void * __restrict ps)
+{
+
+ _FUNCNAME(init_state)(_CE_TO_EI(ce), _TO_STATE(ps));
+
+ return (0);
+}
+
+static int
+_FUNCNAME(stdenc_mbtocs)(struct _citrus_stdenc * __restrict ce,
+ _citrus_csid_t * __restrict csid, _citrus_index_t * __restrict idx,
+ char ** __restrict s, size_t n, void * __restrict ps,
+ size_t * __restrict nresult, struct iconv_hooks *hooks)
+{
+ wchar_t wc;
+ int ret;
+
+ ret = _FUNCNAME(mbrtowc_priv)(_CE_TO_EI(ce), &wc, s, n,
+ _TO_STATE(ps), nresult);
+
+ if ((ret == 0) && *nresult != (size_t)-2)
+ ret = _FUNCNAME(stdenc_wctocs)(_CE_TO_EI(ce), csid, idx, wc);
+
+ if ((ret == 0) && (hooks != NULL) && (hooks->uc_hook != NULL))
+ hooks->uc_hook((unsigned int)*idx, hooks->data);
+ return (ret);
+}
+
+static int
+_FUNCNAME(stdenc_cstomb)(struct _citrus_stdenc * __restrict ce,
+ char * __restrict s, size_t n, _citrus_csid_t csid, _citrus_index_t idx,
+ void * __restrict ps, size_t * __restrict nresult,
+ struct iconv_hooks *hooks __unused)
+{
+ wchar_t wc;
+ int ret;
+
+ wc = ret = 0;
+
+ if (csid != _CITRUS_CSID_INVALID)
+ ret = _FUNCNAME(stdenc_cstowc)(_CE_TO_EI(ce), &wc, csid, idx);
+
+ if (ret == 0)
+ ret = _FUNCNAME(wcrtomb_priv)(_CE_TO_EI(ce), s, n, wc,
+ _TO_STATE(ps), nresult);
+ return (ret);
+}
+
+static int
+_FUNCNAME(stdenc_mbtowc)(struct _citrus_stdenc * __restrict ce,
+ _citrus_wc_t * __restrict wc, char ** __restrict s, size_t n,
+ void * __restrict ps, size_t * __restrict nresult,
+ struct iconv_hooks *hooks)
+{
+ int ret;
+
+ ret = _FUNCNAME(mbrtowc_priv)(_CE_TO_EI(ce), wc, s, n,
+ _TO_STATE(ps), nresult);
+ if ((ret == 0) && (hooks != NULL) && (hooks->wc_hook != NULL))
+ hooks->wc_hook(*wc, hooks->data);
+ return (ret);
+}
+
+static int
+_FUNCNAME(stdenc_wctomb)(struct _citrus_stdenc * __restrict ce,
+ char * __restrict s, size_t n, _citrus_wc_t wc, void * __restrict ps,
+ size_t * __restrict nresult, struct iconv_hooks *hooks __unused)
+{
+ int ret;
+
+ ret = _FUNCNAME(wcrtomb_priv)(_CE_TO_EI(ce), s, n, wc, _TO_STATE(ps),
+ nresult);
+ return (ret);
+}
+
+static int
+_FUNCNAME(stdenc_put_state_reset)(struct _citrus_stdenc * __restrict ce __unused,
+ char * __restrict s __unused, size_t n __unused,
+ void * __restrict ps __unused, size_t * __restrict nresult)
+{
+
+#if _ENCODING_IS_STATE_DEPENDENT
+ return ((_FUNCNAME(put_state_reset)(_CE_TO_EI(ce), s, n, _TO_STATE(ps),
+ nresult)));
+#else
+ *nresult = 0;
+ return (0);
+#endif
+}
+
+static int
+_FUNCNAME(stdenc_get_state_desc)(struct _citrus_stdenc * __restrict ce,
+ void * __restrict ps, int id,
+ struct _citrus_stdenc_state_desc * __restrict d)
+{
+ int ret;
+
+ switch (id) {
+ case _STDENC_SDID_GENERIC:
+ ret = _FUNCNAME(stdenc_get_state_desc_generic)(
+ _CE_TO_EI(ce), _TO_STATE(ps), &d->u.generic.state);
+ break;
+ default:
+ ret = EOPNOTSUPP;
+ }
+
+ return (ret);
+}
diff --git a/lib/libc/iconv/citrus_types.h b/lib/libc/iconv/citrus_types.h
new file mode 100644
index 0000000..5f9c4e3
--- /dev/null
+++ b/lib/libc/iconv/citrus_types.h
@@ -0,0 +1,40 @@
+/* $FreeBSD$ */
+/* $NetBSD: citrus_types.h,v 1.3 2003/10/27 00:12:42 lukem Exp $ */
+
+/*-
+ * Copyright (c)2003 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+
+#ifndef _CITRUS_TYPES_H_
+#define _CITRUS_TYPES_H_
+
+typedef uint32_t _citrus_wc_t;
+typedef uint32_t _citrus_index_t;
+typedef uint32_t _citrus_csid_t;
+#define _CITRUS_CSID_INVALID ((_citrus_csid_t)-1)
+
+#endif
diff --git a/lib/libc/iconv/iconv.3 b/lib/libc/iconv/iconv.3
new file mode 100644
index 0000000..939d442
--- /dev/null
+++ b/lib/libc/iconv/iconv.3
@@ -0,0 +1,305 @@
+.\" $FreeBSD$
+.\" $NetBSD: iconv.3,v 1.12 2004/08/02 13:38:21 tshiozak Exp $
+.\"
+.\" Copyright (c) 2003 Citrus Project,
+.\" Copyright (c) 2009, 2010 Gabor Kovesdan <gabor@FreeBSD.org>,
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.Dd June 16, 2010
+.Dt ICONV 3
+.Os
+.Sh NAME
+.Nm iconv_open ,
+.Nm iconv_open_into ,
+.Nm iconv_close ,
+.Nm iconv
+.Nd codeset conversion functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In iconv.h
+.Ft iconv_t
+.Fn iconv_open "const char *dstname" "const char *srcname"
+.Ft int
+.Fn iconv_open_into "const char *dstname" "const char *srcname" "iconv_allocation_t *ptr"
+.Ft int
+.Fn iconv_close "iconv_t cd"
+.Ft size_t
+.Fn iconv "iconv_t cd" "char ** restrict src" "size_t * restrict srcleft" "char ** restrict dst" "size_t * restrict dstleft"
+.Ft size_t
+.Fn __iconv "iconv_t cd" "const char ** restrict src" "size_t * restrict srcleft" "char ** restrict dst" "size_t * restrict dstleft" "uint32_t flags" "size_t invalids"
+.Sh DESCRIPTION
+The
+.Fn iconv_open
+function opens a converter from the codeset
+.Fa srcname
+to the codeset
+.Fa dstname
+and returns its descriptor.
+The arguments
+.Fa srcname
+and
+.Fa dstname
+accept "" and "char", which refer to the current locale encoding.
+.Pp
+The
+.Fn iconv_open_into
+creates a conversion descriptor on a preallocated space.
+The
+.Ft iconv_allocation_t
+is used as a spaceholder type when allocating such space.
+The
+.Fa dstname
+and
+.Fa srcname
+arguments are the same as in the case of
+.Fn iconv_open .
+The
+.Fa ptr
+argument is a pointer of
+.Ft iconv_allocation_t
+to the preallocated space.
+.Pp
+The
+.Fn iconv_close
+function closes the specified converter
+.Fa cd .
+.Pp
+The
+.Fn iconv
+function converts the string in the buffer
+.Fa *src
+of length
+.Fa *srcleft
+bytes and stores the converted string in the buffer
+.Fa *dst
+of size
+.Fa *dstleft
+bytes.
+After calling
+.Fn iconv ,
+the values pointed to by
+.Fa src ,
+.Fa srcleft ,
+.Fa dst ,
+and
+.Fa dstleft
+are updated as follows:
+.Bl -tag -width 01234567
+.It *src
+Pointer to the byte just after the last character fetched.
+.It *srcleft
+Number of remaining bytes in the source buffer.
+.It *dst
+Pointer to the byte just after the last character stored.
+.It *dstleft
+Number of remainder bytes in the destination buffer.
+.El
+.Pp
+If the string pointed to by
+.Fa *src
+contains a byte sequence which is not a valid character in the source
+codeset, the conversion stops just after the last successful conversion.
+If the output buffer is too small to store the converted
+character, the conversion also stops in the same way.
+In these cases, the values pointed to by
+.Fa src ,
+.Fa srcleft ,
+.Fa dst ,
+and
+.Fa dstleft
+are updated to the state just after the last successful conversion.
+.Pp
+If the string pointed to by
+.Fa *src
+contains a character which is valid under the source codeset but
+can not be converted to the destination codeset,
+the character is replaced by an
+.Dq invalid character
+which depends on the destination codeset, e.g.,
+.Sq \&? ,
+and the conversion is continued.
+.Fn iconv
+returns the number of such
+.Dq invalid conversions .
+.Pp
+There are two special cases of
+.Fn iconv :
+.Bl -tag -width 0123
+.It "src == NULL || *src == NULL"
+If the source and/or destination codesets are stateful,
+.Fn iconv
+places these into their initial state.
+.Pp
+If both
+.Fa dst
+and
+.Fa *dst
+are
+.No non- Ns Dv NULL ,
+.Fn iconv
+stores the shift sequence for the destination switching to the initial state
+in the buffer pointed to by
+.Fa *dst .
+The buffer size is specified by the value pointed to by
+.Fa dstleft
+as above.
+.Fn iconv
+will fail if the buffer is too small to store the shift sequence.
+.Pp
+On the other hand,
+.Fa dst
+or
+.Fa *dst
+may be
+.Dv NULL .
+In this case, the shift sequence for the destination switching
+to the initial state is discarded.
+.Pp
+.El
+The
+.Fn __iconv
+function works just like
+.Fn iconv
+but if
+.Fn iconv
+fails, the invalid character count is lost there.
+This is a not bug rather a limitation of
+.St -p1003.1-2008 ,
+so
+.Fn __iconv
+is provided as an alternative but non-standard interface.
+It also has a flags argument, where currently the following
+flags can be passed:
+.Bl -tag -width 0123
+.It __ICONV_F_HIDE_INVALID
+Skip invalid characters, instead of returning with an error.
+.El
+.Sh RETURN VALUES
+Upon successful completion of
+.Fn iconv_open ,
+it returns a conversion descriptor.
+Otherwise,
+.Fn iconv_open
+returns (iconv_t)\-1 and sets errno to indicate the error.
+.Pp
+Upon successful completion of
+.Fn iconv_open_into ,
+it returns 0.
+Otherwise,
+.Fn iconv_open_into
+returns \-1, and sets errno to indicate the error.
+.Pp
+Upon successful completion of
+.Fn iconv_close ,
+it returns 0.
+Otherwise,
+.Fn iconv_close
+returns \-1 and sets errno to indicate the error.
+.Pp
+Upon successful completion of
+.Fn iconv ,
+it returns the number of
+.Dq invalid
+conversions.
+Otherwise,
+.Fn iconv
+returns (size_t)\-1 and sets errno to indicate the error.
+.Sh ERRORS
+The
+.Fn iconv_open
+function may cause an error in the following cases:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+Memory is exhausted.
+.It Bq Er EINVAL
+There is no converter specified by
+.Fa srcname
+and
+.Fa dstname .
+.El
+The
+.Fn iconv_open_into
+function may cause an error in the following cases:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+There is no converter specified by
+.Fa srcname
+and
+.Fa dstname .
+.El
+.Pp
+The
+.Fn iconv_close
+function may cause an error in the following case:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The conversion descriptor specified by
+.Fa cd
+is invalid.
+.El
+.Pp
+The
+.Fn iconv
+function may cause an error in the following cases:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The conversion descriptor specified by
+.Fa cd
+is invalid.
+.It Bq Er EILSEQ
+The string pointed to by
+.Fa *src
+contains a byte sequence which does not describe a valid character of
+the source codeset.
+.It Bq Er E2BIG
+The output buffer pointed to by
+.Fa *dst
+is too small to store the result string.
+.It Bq Er EINVAL
+The string pointed to by
+.Fa *src
+terminates with an incomplete character or shift sequence.
+.El
+.Sh SEE ALSO
+.Xr iconv 1 ,
+.Xr mkcsmapper 1 ,
+.Xr mkesdb 1
+.Sh STANDARDS
+The
+.Fn iconv_open ,
+.Fn iconv_close ,
+and
+.Fn iconv
+functions conform to
+.St -p1003.1-2008 .
+.Pp
+The
+.Fn iconv_open_into
+function is a GNU-specific extension and it is not part of any standard,
+thus its use may break portability.
+The
+.Fn __iconv
+function is an own extension and it is not part of any standard,
+thus its use may break portability.
diff --git a/lib/libc/iconv/iconv.c b/lib/libc/iconv/iconv.c
new file mode 100644
index 0000000..d1e01e8
--- /dev/null
+++ b/lib/libc/iconv/iconv.c
@@ -0,0 +1,332 @@
+/* $FreeBSD$ */
+/* $NetBSD: iconv.c,v 1.11 2009/03/03 16:22:33 explorer Exp $ */
+
+/*-
+ * Copyright (c) 2003 Citrus Project,
+ * Copyright (c) 2009, 2010 Gabor Kovesdan <gabor@FreeBSD.org>,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <iconv.h>
+#include <limits.h>
+#include <paths.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "citrus_types.h"
+#include "citrus_module.h"
+#include "citrus_esdb.h"
+#include "citrus_hash.h"
+#include "citrus_iconv.h"
+
+#ifdef __weak_alias
+__weak_alias(libiconv, _iconv)
+__weak_alias(libiconv_open, _iconv_open)
+__weak_alias(libiconv_open_into, _iconv_open_into)
+__weak_alias(libiconv_close, _iconv_close)
+__weak_alias(libiconvlist, _iconvlist)
+__weak_alias(libiconvctl, _iconvctl)
+__weak_alias(libiconv_set_relocation_prefix, _iconv_set_relocation_prefix)
+__weak_alias(iconv_canonicalize, _iconv_canonicalize)
+#endif
+
+#define ISBADF(_h_) (!(_h_) || (_h_) == (iconv_t)-1)
+
+int _libiconv_version = _LIBICONV_VERSION;
+
+iconv_t _iconv_open(const char *out, const char *in,
+ struct _citrus_iconv *prealloc);
+
+iconv_t
+_iconv_open(const char *out, const char *in, struct _citrus_iconv *prealloc)
+{
+ struct _citrus_iconv *handle;
+ char *out_truncated, *p;
+ int ret;
+
+ handle = prealloc;
+
+ /*
+ * Remove anything following a //, as these are options (like
+ * //ignore, //translate, etc) and we just don't handle them.
+ * This is for compatibilty with software that uses thees
+ * blindly.
+ */
+ out_truncated = strdup(out);
+ if (out_truncated == NULL) {
+ errno = ENOMEM;
+ return ((iconv_t)-1);
+ }
+
+ p = out_truncated;
+ while (*p != 0) {
+ if (p[0] == '/' && p[1] == '/') {
+ *p = '\0';
+ break;
+ }
+ p++;
+ }
+
+ ret = _citrus_iconv_open(&handle, in, out_truncated);
+ free(out_truncated);
+ if (ret) {
+ errno = ret == ENOENT ? EINVAL : ret;
+ return ((iconv_t)-1);
+ }
+
+ handle->cv_shared->ci_discard_ilseq = strcasestr(out, "//IGNORE");
+ handle->cv_shared->ci_hooks = NULL;
+
+ return ((iconv_t)(void *)handle);
+}
+
+iconv_t
+libiconv_open(const char *out, const char *in)
+{
+
+ return (_iconv_open(out, in, NULL));
+}
+
+int
+libiconv_open_into(const char *out, const char *in, iconv_allocation_t *ptr)
+{
+ struct _citrus_iconv *handle;
+
+ handle = (struct _citrus_iconv *)ptr;
+ return ((_iconv_open(out, in, handle) == (iconv_t)-1) ? -1 : 0);
+}
+
+int
+libiconv_close(iconv_t handle)
+{
+
+ if (ISBADF(handle)) {
+ errno = EBADF;
+ return (-1);
+ }
+
+ _citrus_iconv_close((struct _citrus_iconv *)(void *)handle);
+
+ return (0);
+}
+
+size_t
+libiconv(iconv_t handle, char **in, size_t *szin, char **out, size_t *szout)
+{
+ size_t ret;
+ int err;
+
+ if (ISBADF(handle)) {
+ errno = EBADF;
+ return ((size_t)-1);
+ }
+
+ err = _citrus_iconv_convert((struct _citrus_iconv *)(void *)handle,
+ in, szin, out, szout, 0, &ret);
+ if (err) {
+ errno = err;
+ ret = (size_t)-1;
+ }
+
+ return (ret);
+}
+
+size_t
+__iconv(iconv_t handle, char **in, size_t *szin, char **out,
+ size_t *szout, uint32_t flags, size_t *invalids)
+{
+ size_t ret;
+ int err;
+
+ if (ISBADF(handle)) {
+ errno = EBADF;
+ return ((size_t)-1);
+ }
+
+ err = _citrus_iconv_convert((struct _citrus_iconv *)(void *)handle,
+ in, szin, out, szout, flags, &ret);
+ if (invalids)
+ *invalids = ret;
+ if (err) {
+ errno = err;
+ ret = (size_t)-1;
+ }
+
+ return (ret);
+}
+
+int
+__iconv_get_list(char ***rlist, size_t *rsz, bool sorted)
+{
+ int ret;
+
+ ret = _citrus_esdb_get_list(rlist, rsz, sorted);
+ if (ret) {
+ errno = ret;
+ return (-1);
+ }
+
+ return (0);
+}
+
+void
+__iconv_free_list(char **list, size_t sz)
+{
+
+ _citrus_esdb_free_list(list, sz);
+}
+
+/*
+ * GNU-compatibile non-standard interfaces.
+ */
+static int
+qsort_helper(const void *first, const void *second)
+{
+ const char * const *s1;
+ const char * const *s2;
+
+ s1 = first;
+ s2 = second;
+ return (strcmp(*s1, *s2));
+}
+
+void
+libiconvlist(int (*do_one) (unsigned int, const char * const *,
+ void *), void *data)
+{
+ char **list, **names;
+ const char * const *np;
+ char *curitem, *curkey, *slashpos;
+ size_t sz;
+ unsigned int i, j;
+
+ i = 0;
+
+ if (__iconv_get_list(&list, &sz, true))
+ list = NULL;
+ qsort((void *)list, sz, sizeof(char *), qsort_helper);
+ while (i < sz) {
+ j = 0;
+ slashpos = strchr(list[i], '/');
+ curkey = (char *)malloc(slashpos - list[i] + 2);
+ names = (char **)malloc(sz * sizeof(char *));
+ if ((curkey == NULL) || (names == NULL)) {
+ __iconv_free_list(list, sz);
+ return;
+ }
+ strlcpy(curkey, list[i], slashpos - list[i] + 1);
+ names[j++] = strdup(curkey);
+ for (; (i < sz) && (memcmp(curkey, list[i], strlen(curkey)) == 0); i++) {
+ slashpos = strchr(list[i], '/');
+ curitem = (char *)malloc(strlen(slashpos) + 1);
+ if (curitem == NULL) {
+ __iconv_free_list(list, sz);
+ return;
+ }
+ strlcpy(curitem, &slashpos[1], strlen(slashpos) + 1);
+ if (strcmp(curkey, curitem) == 0) {
+ continue;
+ }
+ names[j++] = strdup(curitem);
+ }
+ np = (const char * const *)names;
+ do_one(j, np, data);
+ free(names);
+ }
+
+ __iconv_free_list(list, sz);
+}
+
+__inline const char
+*iconv_canonicalize(const char *name)
+{
+
+ return (_citrus_iconv_canonicalize(name));
+}
+
+int
+libiconvctl(iconv_t cd, int request, void *argument)
+{
+ struct _citrus_iconv *cv;
+ struct iconv_hooks *hooks;
+ const char *convname;
+ char src[PATH_MAX], *dst;
+ int *i;
+
+ cv = (struct _citrus_iconv *)(void *)cd;
+ hooks = (struct iconv_hooks *)argument;
+ i = (int *)argument;
+
+ if (ISBADF(cd)) {
+ errno = EBADF;
+ return (-1);
+ }
+
+ switch (request) {
+ case ICONV_TRIVIALP:
+ convname = cv->cv_shared->ci_convname;
+ dst = strchr(convname, '/');
+
+ strlcpy(src, convname, dst - convname + 1);
+ dst++;
+ if ((convname == NULL) || (src == NULL) || (dst == NULL))
+ return (-1);
+ *i = strcmp(src, dst) == 0 ? 1 : 0;
+ return (0);
+ case ICONV_GET_TRANSLITERATE:
+ *i = 1;
+ return (0);
+ case ICONV_SET_TRANSLITERATE:
+ return ((*i == 1) ? 0 : -1);
+ case ICONV_GET_DISCARD_ILSEQ:
+ *i = cv->cv_shared->ci_discard_ilseq ? 1 : 0;
+ return (0);
+ case ICONV_SET_DISCARD_ILSEQ:
+ cv->cv_shared->ci_discard_ilseq = *i;
+ return (0);
+ case ICONV_SET_HOOKS:
+ cv->cv_shared->ci_hooks = hooks;
+ return (0);
+ case ICONV_SET_FALLBACKS:
+ errno = EOPNOTSUPP;
+ return (-1);
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+}
+
+void
+libiconv_set_relocation_prefix(const char *orig_prefix __unused,
+ const char *curr_prefix __unused)
+{
+
+}
diff --git a/lib/libc/iconv/iconv_canonicalize.3 b/lib/libc/iconv/iconv_canonicalize.3
new file mode 100644
index 0000000..3c52ae2
--- /dev/null
+++ b/lib/libc/iconv/iconv_canonicalize.3
@@ -0,0 +1,74 @@
+.\" Copyright (c) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 20, 2009
+.Dt ICONV_CANONICALIZE 3
+.Os
+.Sh NAME
+.Nm iconv_canonicalize
+.Nd resolving character encoding names to canonical form
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In iconv.h
+.Ft const char *
+.Fn iconv_canonicalize "const char *name"
+.Sh DESCRIPTION
+The
+.Fn iconv_canonicalize
+function resolves the character encoding name specified by the
+.Fa name
+argument to its canonical form.
+.Sh RETURN VALUES
+Upon successful completion
+.Fn iconv_canonicalize ,
+returns the canonical name of the given encoding.
+If the specified name is already a canonical name, the same
+value is returned.
+If the specified name is not an existing character encoding
+name, NULL is returned.
+.Sh SEE ALSO
+.Xr iconv 3
+.Sh STANDARDS
+The
+.Nm
+function is a non-standard extension, which appeared in
+the GNU implementation and was adopted in
+.Fx 9
+for compatibility's sake.
+.Sh AUTHORS
+This manual page was written by
+.An Gabor Kovesdan Aq gabor@FreeBSD.org .
diff --git a/lib/libc/iconv/iconvctl.3 b/lib/libc/iconv/iconvctl.3
new file mode 100644
index 0000000..f012157
--- /dev/null
+++ b/lib/libc/iconv/iconvctl.3
@@ -0,0 +1,164 @@
+.\" Copyright (c) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 7, 2009
+.Dt ICONVCTL 3
+.Os
+.Sh NAME
+.Nm iconvctl
+.Nd controlling and diagnostical facility for
+.Xr iconv 3
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In iconv.h
+.Ft int
+.Fn iconvctl "iconv_t cd" "int request" "void *argument"
+.Sh DESCRIPTION
+The
+.Fn iconvctl
+function can retrieve or set specific conversion
+setting from the
+.Fa cd
+conversion descriptor.
+The
+.Fa request
+parameter specifies the operation to accomplish and
+.Fa argument
+is an operation-specific argument.
+.Pp
+The possible operations are the following:
+.Bl -tag -width indent
+.It ICONV_TRIVIALP
+In this case
+.Fa argument
+is an
+.Ft int *
+variable, which is set to 1 if the encoding is trivial one, i.e.
+the input and output encodings are the same.
+Otherwise, the variable will be 0.
+.It ICONV_GET_TRANSLITERATE
+Determines if transliteration is enabled.
+The answer is stored in
+.Fa argument ,
+which is of
+.Ft int * .
+It will be set to 1 if this feature is enabled or set to 0 otherwise.
+.It ICONV_SET_TRANSLITERATE
+Enables transliteration if
+.Fa argument ,
+which is of
+.Ft int *
+set to 1 or disables it if
+.Fa argument
+is set to 0.
+.It ICONV_GET_DISCARD_ILSEQ
+Determines if illegal sequences are discarded or not.
+The answer is stored in
+.Fa argument ,
+which is of
+.Ft int * .
+It will be set to 1 if this feature is enabled or set to 0 otherwise.
+.It ICONV_SET_DISCARD_ILSEQ
+Sets whether illegal sequences are discarded or not.
+.Fa argument ,
+which is of
+.Ft int *
+set to 1 or disables it if
+.Fa argument
+is set to 0.
+.It ICONV_SET_HOOKS
+Sets callback functions, which will be called back after successful
+conversions.
+The callback functions are stored in a
+.Ft struct iconv_hooks
+variable, which is passed to
+.Nm
+via
+.Fa argument
+by its address.
+.El
+.\" XXX: fallbacks are unimplemented and trying to set them will always
+.\" return EOPNOTSUPP but definitions are provided for source-level
+.\" compatibility.
+.\".It ICONV_SET_FALLBACKS
+.\"Sets callback functions, which will be called back after failed
+.\"conversions.
+.\"The callback functions are stored in a
+.\".Ft struct iconv_fallbacks
+.\"variable, which is passed to
+.\".Nm
+.\"via
+.\".Fa argument
+.\"by its address.
+.Sh RETURN VALUES
+Upon successful completion
+.Fn iconvctl ,
+returns 0.
+Otherwise, \-1 is returned and errno is set to
+specify the kind of error.
+.Sh ERRORS
+The
+.Fn iconvctl
+function may cause an error in the following cases:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Unknown or unimplemented operation.
+.It Bq Er EBADF
+The conversion descriptor specified by
+.Fa cd
+is invalid.
+.El
+.Sh SEE ALSO
+.Xr iconv 1 ,
+.Xr iconv 3
+.Sh STANDARDS
+The
+.Nm
+facility is a non-standard extension, which appeared in
+the GNU implementation and was adopted in
+.Fx 9
+for compatibility's sake.
+.Sh AUTHORS
+This manual page was written by
+.An Gabor Kovesdan Aq gabor@FreeBSD.org .
+.Sh BUGS
+Transliteration is enabled in this implementation by default, so it
+is impossible by design to turn it off.
+Accordingly, trying to turn it off will always fail and \-1 will be
+returned.
+Getting the transliteration state will always succeed and indicate
+that it is turned on, though.
diff --git a/lib/libc/iconv/iconvlist.3 b/lib/libc/iconv/iconvlist.3
new file mode 100644
index 0000000..d474d9b
--- /dev/null
+++ b/lib/libc/iconv/iconvlist.3
@@ -0,0 +1,93 @@
+.\" Copyright (c) 2009 Gabor Kovesdan <gabor@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 20, 2009
+.Dt ICONVLIST 3
+.Os
+.Sh NAME
+.Nm iconvlist
+.Nd retrieving a list of character encodings supported by
+.Xr iconv 3
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In iconv.h
+.Ft void
+.Fo iconvlist
+.Fa "int \*[lp]*do_one\*[rp]\*[lp]unsigned int *count, const char * const *names, void *arg\*[rp]"
+.Fa "void *arg"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn iconvlist
+function obtains a list of character encodings that are supported by the
+.Xr iconv 3
+call.
+The
+.Fn do_one
+callback function will be called, where the
+.Fa count
+argument will be set to the number of the encoding names found, the
+.Fa names
+argument will be the list of the supported encoding names and the
+.Fa arg
+argument will be the \"outer\"
+.Fa arg
+argument of the
+.Fn iconvlist
+function.
+This argument can be used to interchange custom data between the caller of
+.Fn iconvlist
+and the callback function.
+.Pp
+If an error occurs,
+.Fa names
+will be NULL when calling
+.Fn do_one .
+.Sh SEE ALSO
+.Xr iconv 3 ,
+.Xr __iconv_get_list 3 ,
+.Xr __iconv_free_list 3
+.Sh STANDARDS
+The
+.Nm
+function is a non-standard extension, which appeared in
+the GNU implementation and was adopted in
+.Fx 9
+for compatibility's sake.
+.Sh AUTHORS
+This manual page was written by
+.An Gabor Kovesdan Aq gabor@FreeBSD.org .
diff --git a/lib/libc/include/compat.h b/lib/libc/include/compat.h
new file mode 100644
index 0000000..7694540
--- /dev/null
+++ b/lib/libc/include/compat.h
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2009 Advanced Computing Technologies LLC
+ * Written by: John H. Baldwin <jhb@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * This file defines compatiblity symbol versions for old system calls. It
+ * is included in all generated system call files.
+ */
+
+#ifndef __LIBC_COMPAT_H__
+#define __LIBC_COMPAT_H__
+
+#define __sym_compat(sym,impl,verid) \
+ .symver impl, sym@verid
+
+__sym_compat(__semctl, freebsd7___semctl, FBSD_1.0);
+__sym_compat(msgctl, freebsd7_msgctl, FBSD_1.0);
+__sym_compat(shmctl, freebsd7_shmctl, FBSD_1.0);
+
+#undef __sym_compat
+
+#endif /* __LIBC_COMPAT_H__ */
+
diff --git a/lib/libc/include/fpmath.h b/lib/libc/include/fpmath.h
new file mode 100644
index 0000000..697d582
--- /dev/null
+++ b/lib/libc/include/fpmath.h
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 2002 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/endian.h>
+#include "_fpmath.h"
+
+#ifndef _IEEE_WORD_ORDER
+#define _IEEE_WORD_ORDER _BYTE_ORDER
+#endif
+
+union IEEEf2bits {
+ float f;
+ struct {
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+ unsigned int man :23;
+ unsigned int exp :8;
+ unsigned int sign :1;
+#else /* _BIG_ENDIAN */
+ unsigned int sign :1;
+ unsigned int exp :8;
+ unsigned int man :23;
+#endif
+ } bits;
+};
+
+#define DBL_MANH_SIZE 20
+#define DBL_MANL_SIZE 32
+
+union IEEEd2bits {
+ double d;
+ struct {
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+#if _IEEE_WORD_ORDER == _LITTLE_ENDIAN
+ unsigned int manl :32;
+#endif
+ unsigned int manh :20;
+ unsigned int exp :11;
+ unsigned int sign :1;
+#if _IEEE_WORD_ORDER == _BIG_ENDIAN
+ unsigned int manl :32;
+#endif
+#else /* _BIG_ENDIAN */
+ unsigned int sign :1;
+ unsigned int exp :11;
+ unsigned int manh :20;
+ unsigned int manl :32;
+#endif
+ } bits;
+};
diff --git a/lib/libc/include/isc/eventlib.h b/lib/libc/include/isc/eventlib.h
new file mode 100644
index 0000000..5003823
--- /dev/null
+++ b/lib/libc/include/isc/eventlib.h
@@ -0,0 +1,206 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1995-1999 by Internet Software Consortium
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* eventlib.h - exported interfaces for eventlib
+ * vix 09sep95 [initial]
+ *
+ * $Id: eventlib.h,v 1.3.18.3 2008/01/23 02:12:01 marka Exp $
+ */
+
+#ifndef _EVENTLIB_H
+#define _EVENTLIB_H
+
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <sys/time.h>
+#include <stdio.h>
+
+#include <isc/platform.h>
+
+#ifndef __P
+# define __EVENTLIB_P_DEFINED
+# ifdef __STDC__
+# define __P(x) x
+# else
+# define __P(x) ()
+# endif
+#endif
+
+/* In the absence of branded types... */
+typedef struct { void *opaque; } evConnID;
+typedef struct { void *opaque; } evFileID;
+typedef struct { void *opaque; } evStreamID;
+typedef struct { void *opaque; } evTimerID;
+typedef struct { void *opaque; } evWaitID;
+typedef struct { void *opaque; } evContext;
+typedef struct { void *opaque; } evEvent;
+
+#define evInitID(id) ((id)->opaque = NULL)
+#define evTestID(id) ((id).opaque != NULL)
+
+typedef void (*evConnFunc)__P((evContext, void *, int, const void *, int,
+ const void *, int));
+typedef void (*evFileFunc)__P((evContext, void *, int, int));
+typedef void (*evStreamFunc)__P((evContext, void *, int, int));
+typedef void (*evTimerFunc)__P((evContext, void *,
+ struct timespec, struct timespec));
+typedef void (*evWaitFunc)__P((evContext, void *, const void *));
+
+typedef struct { unsigned char mask[256/8]; } evByteMask;
+#define EV_BYTEMASK_BYTE(b) ((b) / 8)
+#define EV_BYTEMASK_MASK(b) (1 << ((b) % 8))
+#define EV_BYTEMASK_SET(bm, b) \
+ ((bm).mask[EV_BYTEMASK_BYTE(b)] |= EV_BYTEMASK_MASK(b))
+#define EV_BYTEMASK_CLR(bm, b) \
+ ((bm).mask[EV_BYTEMASK_BYTE(b)] &= ~EV_BYTEMASK_MASK(b))
+#define EV_BYTEMASK_TST(bm, b) \
+ ((bm).mask[EV_BYTEMASK_BYTE(b)] & EV_BYTEMASK_MASK(b))
+
+#define EV_POLL 1
+#define EV_WAIT 2
+#define EV_NULL 4
+
+#define EV_READ 1
+#define EV_WRITE 2
+#define EV_EXCEPT 4
+
+#define EV_WASNONBLOCKING 8 /* Internal library use. */
+
+/* eventlib.c */
+#define evCreate __evCreate
+#define evSetDebug __evSetDebug
+#define evDestroy __evDestroy
+#define evGetNext __evGetNext
+#define evDispatch __evDispatch
+#define evDrop __evDrop
+#define evMainLoop __evMainLoop
+#define evHighestFD __evHighestFD
+#define evGetOption __evGetOption
+#define evSetOption __evSetOption
+
+int evCreate __P((evContext *));
+void evSetDebug __P((evContext, int, FILE *));
+int evDestroy __P((evContext));
+int evGetNext __P((evContext, evEvent *, int));
+int evDispatch __P((evContext, evEvent));
+void evDrop __P((evContext, evEvent));
+int evMainLoop __P((evContext));
+int evHighestFD __P((evContext));
+int evGetOption __P((evContext *, const char *, int *));
+int evSetOption __P((evContext *, const char *, int));
+
+/* ev_connects.c */
+#define evListen __evListen
+#define evConnect __evConnect
+#define evCancelConn __evCancelConn
+#define evHold __evHold
+#define evUnhold __evUnhold
+#define evTryAccept __evTryAccept
+
+int evListen __P((evContext, int, int, evConnFunc, void *, evConnID *));
+int evConnect __P((evContext, int, const void *, int,
+ evConnFunc, void *, evConnID *));
+int evCancelConn __P((evContext, evConnID));
+int evHold __P((evContext, evConnID));
+int evUnhold __P((evContext, evConnID));
+int evTryAccept __P((evContext, evConnID, int *));
+
+/* ev_files.c */
+#define evSelectFD __evSelectFD
+#define evDeselectFD __evDeselectFD
+
+int evSelectFD __P((evContext, int, int, evFileFunc, void *, evFileID *));
+int evDeselectFD __P((evContext, evFileID));
+
+/* ev_streams.c */
+#define evConsIovec __evConsIovec
+#define evWrite __evWrite
+#define evRead __evRead
+#define evTimeRW __evTimeRW
+#define evUntimeRW __evUntimeRW
+#define evCancelRW __evCancelRW
+
+struct iovec evConsIovec __P((void *, size_t));
+int evWrite __P((evContext, int, const struct iovec *, int,
+ evStreamFunc func, void *, evStreamID *));
+int evRead __P((evContext, int, const struct iovec *, int,
+ evStreamFunc func, void *, evStreamID *));
+int evTimeRW __P((evContext, evStreamID, evTimerID timer));
+int evUntimeRW __P((evContext, evStreamID));
+int evCancelRW __P((evContext, evStreamID));
+
+/* ev_timers.c */
+#define evConsTime __evConsTime
+#define evAddTime __evAddTime
+#define evSubTime __evSubTime
+#define evCmpTime __evCmpTime
+#define evTimeSpec __evTimeSpec
+#define evTimeVal __evTimeVal
+
+#define evNowTime __evNowTime
+#define evUTCTime __evUTCTime
+#define evLastEventTime __evLastEventTime
+#define evSetTimer __evSetTimer
+#define evClearTimer __evClearTimer
+#define evConfigTimer __evConfigTimer
+#define evResetTimer __evResetTimer
+#define evSetIdleTimer __evSetIdleTimer
+#define evClearIdleTimer __evClearIdleTimer
+#define evResetIdleTimer __evResetIdleTimer
+#define evTouchIdleTimer __evTouchIdleTimer
+
+struct timespec evConsTime __P((time_t sec, long nsec));
+struct timespec evAddTime __P((struct timespec, struct timespec));
+struct timespec evSubTime __P((struct timespec, struct timespec));
+struct timespec evNowTime __P((void));
+struct timespec evUTCTime __P((void));
+struct timespec evLastEventTime __P((evContext));
+struct timespec evTimeSpec __P((struct timeval));
+struct timeval evTimeVal __P((struct timespec));
+int evCmpTime __P((struct timespec, struct timespec));
+int evSetTimer __P((evContext, evTimerFunc, void *, struct timespec,
+ struct timespec, evTimerID *));
+int evClearTimer __P((evContext, evTimerID));
+int evConfigTimer __P((evContext, evTimerID, const char *param,
+ int value));
+int evResetTimer __P((evContext, evTimerID, evTimerFunc, void *,
+ struct timespec, struct timespec));
+int evSetIdleTimer __P((evContext, evTimerFunc, void *, struct timespec,
+ evTimerID *));
+int evClearIdleTimer __P((evContext, evTimerID));
+int evResetIdleTimer __P((evContext, evTimerID, evTimerFunc, void *,
+ struct timespec));
+int evTouchIdleTimer __P((evContext, evTimerID));
+
+/* ev_waits.c */
+#define evWaitFor __evWaitFor
+#define evDo __evDo
+#define evUnwait __evUnwait
+#define evDefer __evDefer
+
+int evWaitFor __P((evContext, const void *, evWaitFunc, void *, evWaitID *));
+int evDo __P((evContext, const void *));
+int evUnwait __P((evContext, evWaitID));
+int evDefer __P((evContext, evWaitFunc, void *));
+
+#ifdef __EVENTLIB_P_DEFINED
+# undef __P
+#endif
+
+#endif /*_EVENTLIB_H*/
+
+/*! \file */
diff --git a/lib/libc/include/isc/list.h b/lib/libc/include/isc/list.h
new file mode 100644
index 0000000..fef631b
--- /dev/null
+++ b/lib/libc/include/isc/list.h
@@ -0,0 +1,124 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1997,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $FreeBSD$ */
+
+#ifndef LIST_H
+#define LIST_H 1
+#ifdef _LIBC
+#include <assert.h>
+#define INSIST(cond) assert(cond)
+#else
+#include <isc/assertions.h>
+#endif
+
+#define LIST(type) struct { type *head, *tail; }
+#define INIT_LIST(list) \
+ do { (list).head = NULL; (list).tail = NULL; } while (0)
+
+#define LINK(type) struct { type *prev, *next; }
+#define INIT_LINK_TYPE(elt, link, type) \
+ do { \
+ (elt)->link.prev = (type *)(-1); \
+ (elt)->link.next = (type *)(-1); \
+ } while (0)
+#define INIT_LINK(elt, link) \
+ INIT_LINK_TYPE(elt, link, void)
+#define LINKED(elt, link) ((void *)((elt)->link.prev) != (void *)(-1))
+
+#define HEAD(list) ((list).head)
+#define TAIL(list) ((list).tail)
+#define EMPTY(list) ((list).head == NULL)
+
+#define PREPEND(list, elt, link) \
+ do { \
+ INSIST(!LINKED(elt, link));\
+ if ((list).head != NULL) \
+ (list).head->link.prev = (elt); \
+ else \
+ (list).tail = (elt); \
+ (elt)->link.prev = NULL; \
+ (elt)->link.next = (list).head; \
+ (list).head = (elt); \
+ } while (0)
+
+#define APPEND(list, elt, link) \
+ do { \
+ INSIST(!LINKED(elt, link));\
+ if ((list).tail != NULL) \
+ (list).tail->link.next = (elt); \
+ else \
+ (list).head = (elt); \
+ (elt)->link.prev = (list).tail; \
+ (elt)->link.next = NULL; \
+ (list).tail = (elt); \
+ } while (0)
+
+#define UNLINK_TYPE(list, elt, link, type) \
+ do { \
+ INSIST(LINKED(elt, link));\
+ if ((elt)->link.next != NULL) \
+ (elt)->link.next->link.prev = (elt)->link.prev; \
+ else { \
+ INSIST((list).tail == (elt)); \
+ (list).tail = (elt)->link.prev; \
+ } \
+ if ((elt)->link.prev != NULL) \
+ (elt)->link.prev->link.next = (elt)->link.next; \
+ else { \
+ INSIST((list).head == (elt)); \
+ (list).head = (elt)->link.next; \
+ } \
+ INIT_LINK_TYPE(elt, link, type); \
+ } while (0)
+#define UNLINK(list, elt, link) \
+ UNLINK_TYPE(list, elt, link, void)
+
+#define PREV(elt, link) ((elt)->link.prev)
+#define NEXT(elt, link) ((elt)->link.next)
+
+#define INSERT_BEFORE(list, before, elt, link) \
+ do { \
+ INSIST(!LINKED(elt, link));\
+ if ((before)->link.prev == NULL) \
+ PREPEND(list, elt, link); \
+ else { \
+ (elt)->link.prev = (before)->link.prev; \
+ (before)->link.prev = (elt); \
+ (elt)->link.prev->link.next = (elt); \
+ (elt)->link.next = (before); \
+ } \
+ } while (0)
+
+#define INSERT_AFTER(list, after, elt, link) \
+ do { \
+ INSIST(!LINKED(elt, link));\
+ if ((after)->link.next == NULL) \
+ APPEND(list, elt, link); \
+ else { \
+ (elt)->link.next = (after)->link.next; \
+ (after)->link.next = (elt); \
+ (elt)->link.next->link.prev = (elt); \
+ (elt)->link.prev = (after); \
+ } \
+ } while (0)
+
+#define ENQUEUE(list, elt, link) APPEND(list, elt, link)
+#define DEQUEUE(list, elt, link) UNLINK(list, elt, link)
+
+#endif /* LIST_H */
+/*! \file */
diff --git a/lib/libc/include/isc/platform.h b/lib/libc/include/isc/platform.h
new file mode 100644
index 0000000..a0513be
--- /dev/null
+++ b/lib/libc/include/isc/platform.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2008 Internet Systems Consortium, Inc. ("ISC")
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+ * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+ * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+ * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+ * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* $Id: platform.h.in,v 1.2.6.2 2008/01/23 02:15:02 tbox Exp $ */
+/* $FreeBSD$ */
+
+/*! \file */
+
+#ifndef ISC_PLATFORM_H
+#define ISC_PLATFORM_H
+
+/*
+ * Define if the OS does not define struct timespec.
+ */
+#undef ISC_PLATFORM_NEEDTIMESPEC
+#ifdef ISC_PLATFORM_NEEDTIMESPEC
+#include <time.h> /* For time_t */
+struct timespec {
+ time_t tv_sec; /* seconds */
+ long tv_nsec; /* nanoseconds */
+};
+#endif
+
+#endif
diff --git a/lib/libc/include/libc_private.h b/lib/libc/include/libc_private.h
new file mode 100644
index 0000000..2182f46
--- /dev/null
+++ b/lib/libc/include/libc_private.h
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ *
+ * Private definitions for libc, libc_r and libpthread.
+ *
+ */
+
+#ifndef _LIBC_PRIVATE_H_
+#define _LIBC_PRIVATE_H_
+#include <sys/_pthreadtypes.h>
+
+/*
+ * This global flag is non-zero when a process has created one
+ * or more threads. It is used to avoid calling locking functions
+ * when they are not required.
+ */
+extern int __isthreaded;
+
+/*
+ * Elf_Auxinfo *__elf_aux_vector, the pointer to the ELF aux vector
+ * provided by kernel. Either set for us by rtld, or found at runtime
+ * on stack for static binaries.
+ *
+ * Type is void to avoid polluting whole libc with ELF types.
+ */
+extern void *__elf_aux_vector;
+
+/*
+ * libc should use libc_dlopen internally, which respects a global
+ * flag where loading of new shared objects can be restricted.
+ */
+void *libc_dlopen(const char *, int);
+
+/*
+ * For dynamic linker.
+ */
+void _rtld_error(const char *fmt, ...);
+
+/*
+ * File lock contention is difficult to diagnose without knowing
+ * where locks were set. Allow a debug library to be built which
+ * records the source file and line number of each lock call.
+ */
+#ifdef _FLOCK_DEBUG
+#define _FLOCKFILE(x) _flockfile_debug(x, __FILE__, __LINE__)
+#else
+#define _FLOCKFILE(x) _flockfile(x)
+#endif
+
+/*
+ * Macros for locking and unlocking FILEs. These test if the
+ * process is threaded to avoid locking when not required.
+ */
+#define FLOCKFILE(fp) if (__isthreaded) _FLOCKFILE(fp)
+#define FUNLOCKFILE(fp) if (__isthreaded) _funlockfile(fp)
+
+struct _spinlock;
+extern struct _spinlock __stdio_thread_lock;
+#define STDIO_THREAD_LOCK() \
+do { \
+ if (__isthreaded) \
+ _SPINLOCK(&__stdio_thread_lock); \
+} while (0)
+#define STDIO_THREAD_UNLOCK() \
+do { \
+ if (__isthreaded) \
+ _SPINUNLOCK(&__stdio_thread_lock); \
+} while (0)
+
+/*
+ * Indexes into the pthread jump table.
+ *
+ * Warning! If you change this type, you must also change the threads
+ * libraries that reference it (libc_r, libpthread).
+ */
+typedef enum {
+ PJT_ATFORK,
+ PJT_ATTR_DESTROY,
+ PJT_ATTR_GETDETACHSTATE,
+ PJT_ATTR_GETGUARDSIZE,
+ PJT_ATTR_GETINHERITSCHED,
+ PJT_ATTR_GETSCHEDPARAM,
+ PJT_ATTR_GETSCHEDPOLICY,
+ PJT_ATTR_GETSCOPE,
+ PJT_ATTR_GETSTACKADDR,
+ PJT_ATTR_GETSTACKSIZE,
+ PJT_ATTR_INIT,
+ PJT_ATTR_SETDETACHSTATE,
+ PJT_ATTR_SETGUARDSIZE,
+ PJT_ATTR_SETINHERITSCHED,
+ PJT_ATTR_SETSCHEDPARAM,
+ PJT_ATTR_SETSCHEDPOLICY,
+ PJT_ATTR_SETSCOPE,
+ PJT_ATTR_SETSTACKADDR,
+ PJT_ATTR_SETSTACKSIZE,
+ PJT_CANCEL,
+ PJT_CLEANUP_POP,
+ PJT_CLEANUP_PUSH,
+ PJT_COND_BROADCAST,
+ PJT_COND_DESTROY,
+ PJT_COND_INIT,
+ PJT_COND_SIGNAL,
+ PJT_COND_TIMEDWAIT,
+ PJT_COND_WAIT,
+ PJT_DETACH,
+ PJT_EQUAL,
+ PJT_EXIT,
+ PJT_GETSPECIFIC,
+ PJT_JOIN,
+ PJT_KEY_CREATE,
+ PJT_KEY_DELETE,
+ PJT_KILL,
+ PJT_MAIN_NP,
+ PJT_MUTEXATTR_DESTROY,
+ PJT_MUTEXATTR_INIT,
+ PJT_MUTEXATTR_SETTYPE,
+ PJT_MUTEX_DESTROY,
+ PJT_MUTEX_INIT,
+ PJT_MUTEX_LOCK,
+ PJT_MUTEX_TRYLOCK,
+ PJT_MUTEX_UNLOCK,
+ PJT_ONCE,
+ PJT_RWLOCK_DESTROY,
+ PJT_RWLOCK_INIT,
+ PJT_RWLOCK_RDLOCK,
+ PJT_RWLOCK_TRYRDLOCK,
+ PJT_RWLOCK_TRYWRLOCK,
+ PJT_RWLOCK_UNLOCK,
+ PJT_RWLOCK_WRLOCK,
+ PJT_SELF,
+ PJT_SETCANCELSTATE,
+ PJT_SETCANCELTYPE,
+ PJT_SETSPECIFIC,
+ PJT_SIGMASK,
+ PJT_TESTCANCEL,
+ PJT_CLEANUP_POP_IMP,
+ PJT_CLEANUP_PUSH_IMP,
+ PJT_CANCEL_ENTER,
+ PJT_CANCEL_LEAVE,
+ PJT_MAX
+} pjt_index_t;
+
+typedef int (*pthread_func_t)(void);
+typedef pthread_func_t pthread_func_entry_t[2];
+
+extern pthread_func_entry_t __thr_jtable[];
+
+/*
+ * yplib internal interfaces
+ */
+#ifdef YP
+int _yp_check(char **);
+#endif
+
+/*
+ * Initialise TLS for static programs
+ */
+void _init_tls(void);
+
+/*
+ * Provides pthread_once()-like functionality for both single-threaded
+ * and multi-threaded applications.
+ */
+int _once(pthread_once_t *, void (*)(void));
+
+/*
+ * Set the TLS thread pointer
+ */
+void _set_tp(void *tp);
+
+/*
+ * This is a pointer in the C run-time startup code. It is used
+ * by getprogname() and setprogname().
+ */
+extern const char *__progname;
+
+/*
+ * This function is used by the threading libraries to notify malloc that a
+ * thread is exiting.
+ */
+void _malloc_thread_cleanup(void);
+
+/*
+ * These functions are used by the threading libraries in order to protect
+ * malloc across fork().
+ */
+void _malloc_prefork(void);
+void _malloc_postfork(void);
+
+/*
+ * Function to clean up streams, called from abort() and exit().
+ */
+extern void (*__cleanup)(void);
+
+/*
+ * Get kern.osreldate to detect ABI revisions. Explicitly
+ * ignores value of $OSVERSION and caches result. Prototypes
+ * for the wrapped "new" pad-less syscalls are here for now.
+ */
+extern int __getosreldate(void);
+#include <sys/_types.h>
+/* Without pad */
+extern __off_t __sys_lseek(int, __off_t, int);
+extern int __sys_ftruncate(int, __off_t);
+extern int __sys_truncate(const char *, __off_t);
+extern __ssize_t __sys_pread(int, void *, __size_t, __off_t);
+extern __ssize_t __sys_pwrite(int, const void *, __size_t, __off_t);
+extern void * __sys_mmap(void *, __size_t, int, int, int, __off_t);
+
+/* With pad */
+extern __off_t __sys_freebsd6_lseek(int, int, __off_t, int);
+extern int __sys_freebsd6_ftruncate(int, int, __off_t);
+extern int __sys_freebsd6_truncate(const char *, int, __off_t);
+extern __ssize_t __sys_freebsd6_pread(int, void *, __size_t, int, __off_t);
+extern __ssize_t __sys_freebsd6_pwrite(int, const void *, __size_t, int, __off_t);
+extern void * __sys_freebsd6_mmap(void *, __size_t, int, int, int, int, __off_t);
+
+/* Without back-compat translation */
+extern int __sys_fcntl(int, int, ...);
+
+/* execve() with PATH processing to implement posix_spawnp() */
+int _execvpe(const char *, char * const *, char * const *);
+
+int _elf_aux_info(int aux, void *buf, int buflen);
+struct dl_phdr_info;
+int __elf_phdr_match_addr(struct dl_phdr_info *, void *);
+void __init_elf_aux_vector(void);
+
+void _pthread_cancel_enter(int);
+void _pthread_cancel_leave(int);
+
+#endif /* _LIBC_PRIVATE_H_ */
diff --git a/lib/libc/include/namespace.h b/lib/libc/include/namespace.h
new file mode 100644
index 0000000..1e00030
--- /dev/null
+++ b/lib/libc/include/namespace.h
@@ -0,0 +1,265 @@
+/*
+ * Copyright (c) 2001 Daniel Eischen <deischen@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NAMESPACE_H_
+#define _NAMESPACE_H_
+
+/*
+ * Adjust names so that headers declare "hidden" names.
+ *
+ * README: When modifying this file don't forget to make the appropriate
+ * changes in un-namespace.h!!!
+ */
+
+/*
+ * ISO C (C90) section. Most names in libc aren't in ISO C, so they
+ * should be here. Most aren't here...
+ */
+#define err _err
+#define warn _warn
+#define nsdispatch _nsdispatch
+
+/*
+ * Prototypes for syscalls/functions that need to be overridden
+ * in libc_r/libpthread.
+ */
+#define accept _accept
+#define __acl_aclcheck_fd ___acl_aclcheck_fd
+#define __acl_delete_fd ___acl_delete_fd
+#define __acl_get_fd ___acl_get_fd
+#define __acl_set_fd ___acl_set_fd
+#define bind _bind
+#define __cap_get_fd ___cap_get_fd
+#define __cap_set_fd ___cap_set_fd
+#define close _close
+#define connect _connect
+#define dup _dup
+#define dup2 _dup2
+#define execve _execve
+#define fcntl _fcntl
+/*#define flock _flock */
+#define flockfile _flockfile
+#define fpathconf _fpathconf
+#define fstat _fstat
+#define fstatfs _fstatfs
+#define fsync _fsync
+#define funlockfile _funlockfile
+#define getdirentries _getdirentries
+#define getlogin _getlogin
+#define getpeername _getpeername
+#define getprogname _getprogname
+#define getsockname _getsockname
+#define getsockopt _getsockopt
+#define ioctl _ioctl
+/* #define kevent _kevent */
+#define listen _listen
+#define nanosleep _nanosleep
+#define open _open
+#define openat _openat
+#define poll _poll
+#define pthread_atfork _pthread_atfork
+#define pthread_attr_destroy _pthread_attr_destroy
+#define pthread_attr_get_np _pthread_attr_get_np
+#define pthread_attr_getaffinity_np _pthread_attr_getaffinity_np
+#define pthread_attr_getdetachstate _pthread_attr_getdetachstate
+#define pthread_attr_getguardsize _pthread_attr_getguardsize
+#define pthread_attr_getinheritsched _pthread_attr_getinheritsched
+#define pthread_attr_getschedparam _pthread_attr_getschedparam
+#define pthread_attr_getschedpolicy _pthread_attr_getschedpolicy
+#define pthread_attr_getscope _pthread_attr_getscope
+#define pthread_attr_getstack _pthread_attr_getstack
+#define pthread_attr_getstackaddr _pthread_attr_getstackaddr
+#define pthread_attr_getstacksize _pthread_attr_getstacksize
+#define pthread_attr_init _pthread_attr_init
+#define pthread_attr_setaffinity_np _pthread_attr_setaffinity_np
+#define pthread_attr_setcreatesuspend_np _pthread_attr_setcreatesuspend_np
+#define pthread_attr_setdetachstate _pthread_attr_setdetachstate
+#define pthread_attr_setguardsize _pthread_attr_setguardsize
+#define pthread_attr_setinheritsched _pthread_attr_setinheritsched
+#define pthread_attr_setschedparam _pthread_attr_setschedparam
+#define pthread_attr_setschedpolicy _pthread_attr_setschedpolicy
+#define pthread_attr_setscope _pthread_attr_setscope
+#define pthread_attr_setstack _pthread_attr_setstack
+#define pthread_attr_setstackaddr _pthread_attr_setstackaddr
+#define pthread_attr_setstacksize _pthread_attr_setstacksize
+#define pthread_barrier_destroy _pthread_barrier_destroy
+#define pthread_barrier_init _pthread_barrier_init
+#define pthread_barrier_wait _pthread_barrier_wait
+#define pthread_barrierattr_destroy _pthread_barrierattr_destroy
+#define pthread_barrierattr_getpshared _pthread_barrierattr_getpshared
+#define pthread_barrierattr_init _pthread_barrierattr_init
+#define pthread_barrierattr_setpshared _pthread_barrierattr_setpshared
+#define pthread_cancel _pthread_cancel
+#define pthread_cond_broadcast _pthread_cond_broadcast
+#define pthread_cond_destroy _pthread_cond_destroy
+#define pthread_cond_init _pthread_cond_init
+#define pthread_cond_signal _pthread_cond_signal
+#define pthread_cond_timedwait _pthread_cond_timedwait
+#define pthread_cond_wait _pthread_cond_wait
+#define pthread_condattr_destroy _pthread_condattr_destroy
+#define pthread_condattr_getclock _pthread_condattr_getclock
+#define pthread_condattr_getpshared _pthread_condattr_getpshared
+#define pthread_condattr_init _pthread_condattr_init
+#define pthread_condattr_setclock _pthread_condattr_setclock
+#define pthread_condattr_setpshared _pthread_condattr_setpshared
+#define pthread_create _pthread_create
+#define pthread_detach _pthread_detach
+#define pthread_equal _pthread_equal
+#define pthread_exit _pthread_exit
+#define pthread_getaffinity_np _pthread_getaffinity_np
+#define pthread_getconcurrency _pthread_getconcurrency
+#define pthread_getcpuclockid _pthread_getcpuclockid
+#define pthread_getprio _pthread_getprio
+#define pthread_getschedparam _pthread_getschedparam
+#define pthread_getspecific _pthread_getspecific
+#define pthread_getthreadid_np _pthread_getthreadid_np
+#define pthread_join _pthread_join
+#define pthread_key_create _pthread_key_create
+#define pthread_key_delete _pthread_key_delete
+#define pthread_kill _pthread_kill
+#define pthread_main_np _pthread_main_np
+#define pthread_multi_np _pthread_multi_np
+#define pthread_mutex_destroy _pthread_mutex_destroy
+#define pthread_mutex_getprioceiling _pthread_mutex_getprioceiling
+#define pthread_mutex_init _pthread_mutex_init
+#define pthread_mutex_isowned_np _pthread_mutex_isowned_np
+#define pthread_mutex_lock _pthread_mutex_lock
+#define pthread_mutex_setprioceiling _pthread_mutex_setprioceiling
+#define pthread_mutex_timedlock _pthread_mutex_timedlock
+#define pthread_mutex_trylock _pthread_mutex_trylock
+#define pthread_mutex_unlock _pthread_mutex_unlock
+#define pthread_mutexattr_destroy _pthread_mutexattr_destroy
+#define pthread_mutexattr_getkind_np _pthread_mutexattr_getkind_np
+#define pthread_mutexattr_getprioceiling _pthread_mutexattr_getprioceiling
+#define pthread_mutexattr_getprotocol _pthread_mutexattr_getprotocol
+#define pthread_mutexattr_getpshared _pthread_mutexattr_getpshared
+#define pthread_mutexattr_gettype _pthread_mutexattr_gettype
+#define pthread_mutexattr_init _pthread_mutexattr_init
+#define pthread_mutexattr_setkind_np _pthread_mutexattr_setkind_np
+#define pthread_mutexattr_setprioceiling _pthread_mutexattr_setprioceiling
+#define pthread_mutexattr_setprotocol _pthread_mutexattr_setprotocol
+#define pthread_mutexattr_setpshared _pthread_mutexattr_setpshared
+#define pthread_mutexattr_settype _pthread_mutexattr_settype
+#define pthread_once _pthread_once
+#define pthread_resume_all_np _pthread_resume_all_np
+#define pthread_resume_np _pthread_resume_np
+#define pthread_rwlock_destroy _pthread_rwlock_destroy
+#define pthread_rwlock_init _pthread_rwlock_init
+#define pthread_rwlock_rdlock _pthread_rwlock_rdlock
+#define pthread_rwlock_timedrdlock _pthread_rwlock_timedrdlock
+#define pthread_rwlock_timedwrlock _pthread_rwlock_timedwrlock
+#define pthread_rwlock_tryrdlock _pthread_rwlock_tryrdlock
+#define pthread_rwlock_trywrlock _pthread_rwlock_trywrlock
+#define pthread_rwlock_unlock _pthread_rwlock_unlock
+#define pthread_rwlock_wrlock _pthread_rwlock_wrlock
+#define pthread_rwlockattr_destroy _pthread_rwlockattr_destroy
+#define pthread_rwlockattr_getpshared _pthread_rwlockattr_getpshared
+#define pthread_rwlockattr_init _pthread_rwlockattr_init
+#define pthread_rwlockattr_setpshared _pthread_rwlockattr_setpshared
+#define pthread_self _pthread_self
+#define pthread_set_name_np _pthread_set_name_np
+#define pthread_setaffinity_np _pthread_setaffinity_np
+#define pthread_setcancelstate _pthread_setcancelstate
+#define pthread_setcanceltype _pthread_setcanceltype
+#define pthread_setconcurrency _pthread_setconcurrency
+#define pthread_setprio _pthread_setprio
+#define pthread_setschedparam _pthread_setschedparam
+#define pthread_setspecific _pthread_setspecific
+#define pthread_sigmask _pthread_sigmask
+#define pthread_single_np _pthread_single_np
+#define pthread_spin_destroy _pthread_spin_destroy
+#define pthread_spin_init _pthread_spin_init
+#define pthread_spin_lock _pthread_spin_lock
+#define pthread_spin_trylock _pthread_spin_trylock
+#define pthread_spin_unlock _pthread_spin_unlock
+#define pthread_suspend_all_np _pthread_suspend_all_np
+#define pthread_suspend_np _pthread_suspend_np
+#define pthread_switch_add_np _pthread_switch_add_np
+#define pthread_switch_delete_np _pthread_switch_delete_np
+#define pthread_testcancel _pthread_testcancel
+#define pthread_timedjoin_np _pthread_timedjoin_np
+#define pthread_yield _pthread_yield
+#define read _read
+#define readv _readv
+#define recvfrom _recvfrom
+#define recvmsg _recvmsg
+#define select _select
+#define sem_close _sem_close
+#define sem_destroy _sem_destroy
+#define sem_getvalue _sem_getvalue
+#define sem_init _sem_init
+#define sem_open _sem_open
+#define sem_post _sem_post
+#define sem_timedwait _sem_timedwait
+#define sem_trywait _sem_trywait
+#define sem_unlink _sem_unlink
+#define sem_wait _sem_wait
+#define sendmsg _sendmsg
+#define sendto _sendto
+#define setsockopt _setsockopt
+/*#define sigaction _sigaction*/
+#define sigprocmask _sigprocmask
+#define sigsuspend _sigsuspend
+#define socket _socket
+#define socketpair _socketpair
+#define usleep _usleep
+#define wait4 _wait4
+#define waitpid _waitpid
+#define write _write
+#define writev _writev
+
+
+/*
+ * Other hidden syscalls/functions that libc_r needs to override
+ * but are not used internally by libc.
+ *
+ * XXX - When modifying libc to use one of the following, remove
+ * the prototype from below and place it in the list above.
+ */
+#if 0
+#define creat _creat
+#define fchflags _fchflags
+#define fchmod _fchmod
+#define ftrylockfile _ftrylockfile
+#define msync _msync
+#define nfssvc _nfssvc
+#define pause _pause
+#define sched_yield _sched_yield
+#define sendfile _sendfile
+#define shutdown _shutdown
+#define sigaltstack _sigaltstack
+#define sigpending _sigpending
+#define sigreturn _sigreturn
+#define sigsetmask _sigsetmask
+#define sleep _sleep
+#define system _system
+#define tcdrain _tcdrain
+#define wait _wait
+#endif
+
+#endif /* _NAMESPACE_H_ */
diff --git a/lib/libc/include/nscache.h b/lib/libc/include/nscache.h
new file mode 100644
index 0000000..015c4ec
--- /dev/null
+++ b/lib/libc/include/nscache.h
@@ -0,0 +1,197 @@
+/*-
+ * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __NS_CACHE_H__
+#define __NS_CACHE_H__
+
+#include "nscachedcli.h"
+
+typedef int (*nss_cache_id_func_t)(char *, size_t *, va_list, void *);
+typedef int (*nss_cache_marshal_func_t)(char *, size_t *, void *, va_list,
+ void *);
+typedef int (*nss_cache_unmarshal_func_t)(char *, size_t, void *, va_list,
+ void *);
+
+typedef void (*nss_set_mp_ws_func_t)(cached_mp_write_session);
+typedef cached_mp_write_session (*nss_get_mp_ws_func_t)(void);
+
+typedef void (*nss_set_mp_rs_func_t)(cached_mp_read_session);
+typedef cached_mp_read_session (*nss_get_mp_rs_func_t)(void);
+
+typedef struct _nss_cache_info {
+ char *entry_name;
+ void *mdata;
+
+ /*
+ * These 3 functions should be implemented specifically for each
+ * nsswitch database.
+ */
+ nss_cache_id_func_t id_func; /* marshals the request parameters */
+ nss_cache_marshal_func_t marshal_func; /* marshals response */
+ nss_cache_unmarshal_func_t unmarshal_func; /* unmarshals response */
+
+ /*
+ * These 4 functions should be generated with NSS_MP_CACHE_HANDLING
+ * macro.
+ */
+ nss_set_mp_ws_func_t set_mp_ws_func; /* sets current write session */
+ nss_get_mp_ws_func_t get_mp_ws_func; /* gets current write session */
+
+ nss_set_mp_rs_func_t set_mp_rs_func; /* sets current read session */
+ nss_get_mp_rs_func_t get_mp_rs_func; /* gets current read session */
+} nss_cache_info;
+
+/*
+ * NSS_MP_CACHE_HANDLING implements the set_mp_ws, get_mp_ws, set_mp_rs,
+ * get_mp_rs functions, that are used in _nss_cache_info. It uses
+ * NSS_TLS_HANDLING macro to organize thread local storage.
+ */
+#define NSS_MP_CACHE_HANDLING(name) \
+struct name##_mp_state { \
+ cached_mp_write_session mp_write_session; \
+ cached_mp_read_session mp_read_session; \
+}; \
+ \
+static void \
+name##_mp_endstate(void *s) { \
+ struct name##_mp_state *mp_state; \
+ \
+ mp_state = (struct name##_mp_state *)s; \
+ if (mp_state->mp_write_session != INVALID_CACHED_MP_WRITE_SESSION)\
+ __abandon_cached_mp_write_session(mp_state->mp_write_session);\
+ \
+ if (mp_state->mp_read_session != INVALID_CACHED_MP_READ_SESSION)\
+ __close_cached_mp_read_session(mp_state->mp_read_session);\
+} \
+NSS_TLS_HANDLING(name##_mp); \
+ \
+static void \
+name##_set_mp_ws(cached_mp_write_session ws) \
+{ \
+ struct name##_mp_state *mp_state; \
+ int res; \
+ \
+ res = name##_mp_getstate(&mp_state); \
+ if (res != 0) \
+ return; \
+ \
+ mp_state->mp_write_session = ws; \
+} \
+ \
+static cached_mp_write_session \
+name##_get_mp_ws(void) \
+{ \
+ struct name##_mp_state *mp_state; \
+ int res; \
+ \
+ res = name##_mp_getstate(&mp_state); \
+ if (res != 0) \
+ return (INVALID_CACHED_MP_WRITE_SESSION); \
+ \
+ return (mp_state->mp_write_session); \
+} \
+ \
+static void \
+name##_set_mp_rs(cached_mp_read_session rs) \
+{ \
+ struct name##_mp_state *mp_state; \
+ int res; \
+ \
+ res = name##_mp_getstate(&mp_state); \
+ if (res != 0) \
+ return; \
+ \
+ mp_state->mp_read_session = rs; \
+} \
+ \
+static cached_mp_read_session \
+name##_get_mp_rs(void) \
+{ \
+ struct name##_mp_state *mp_state; \
+ int res; \
+ \
+ res = name##_mp_getstate(&mp_state); \
+ if (res != 0) \
+ return (INVALID_CACHED_MP_READ_SESSION); \
+ \
+ return (mp_state->mp_read_session); \
+}
+
+/*
+ * These macros should be used to initialize _nss_cache_info structure. For
+ * multipart queries in setXXXent and getXXXent functions mf and uf
+ * (marshal function and unmarshal function) should be both NULL.
+ */
+#define NS_COMMON_CACHE_INFO_INITIALIZER(name, mdata, if, mf, uf) \
+ {#name, mdata, if, mf, uf, NULL, NULL, NULL, NULL}
+#define NS_MP_CACHE_INFO_INITIALIZER(name, mdata, mf, uf) \
+ {#name, mdata, NULL, mf, uf, name##_set_mp_ws, name##_get_mp_ws,\
+ name##_set_mp_rs, name##_get_mp_rs }
+
+/*
+ * Analog of other XXX_CB macros. Has the pointer to _nss_cache_info
+ * structure as the only argument.
+ */
+#define NS_CACHE_CB(cinfo) {NSSRC_CACHE, __nss_cache_handler, (void *)(cinfo) },
+
+/* args are: current pointer, current buffer, initial buffer, pointer type */
+#define NS_APPLY_OFFSET(cp, cb, ib, p_type) \
+ if ((cp) != NULL) \
+ (cp) = (p_type)((char *)(cb) + (size_t)(cp) - (size_t)(ib))
+/*
+ * Gets new pointer from the marshalled buffer by uisng initial address
+ * and initial buffer address
+ */
+#define NS_GET_NEWP(cp, cb, ib) \
+ ((char *)(cb) + (size_t)(cp) - (size_t)(ib))
+
+typedef struct _nss_cache_data {
+ char *key;
+ size_t key_size;
+
+ nss_cache_info const *info;
+} nss_cache_data;
+
+__BEGIN_DECLS
+/* dummy function, which is needed to make nss_method_lookup happy */
+extern int __nss_cache_handler(void *, void *, va_list);
+
+#ifdef _NS_PRIVATE
+extern int __nss_common_cache_read(void *, void *, va_list);
+extern int __nss_common_cache_write(void *, void *, va_list);
+extern int __nss_common_cache_write_negative(void *);
+
+extern int __nss_mp_cache_read(void *, void *, va_list);
+extern int __nss_mp_cache_write(void *, void *, va_list);
+extern int __nss_mp_cache_write_submit(void *, void *, va_list);
+extern int __nss_mp_cache_end(void *, void *, va_list);
+#endif /* _NS_PRIVATE */
+
+__END_DECLS
+
+#endif
diff --git a/lib/libc/include/nscachedcli.h b/lib/libc/include/nscachedcli.h
new file mode 100644
index 0000000..b0f79bd
--- /dev/null
+++ b/lib/libc/include/nscachedcli.h
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 2004 Michael Bushkov <bushman@rsu.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef __NS_CACHED_CLI_H__
+#define __NS_CACHED_CLI_H__
+
+/*
+ * This file contains API for working with caching daemon
+ */
+
+enum comm_element_t {
+ CET_UNDEFINED = 0,
+ CET_WRITE_REQUEST = 1,
+ CET_WRITE_RESPONSE = 2,
+ CET_READ_REQUEST = 3,
+ CET_READ_RESPONSE = 4,
+ CET_TRANSFORM_REQUEST = 5,
+ CET_TRANSFORM_RESPONSE = 6,
+ CET_MP_WRITE_SESSION_REQUEST = 7,
+ CET_MP_WRITE_SESSION_RESPONSE = 8,
+ CET_MP_WRITE_SESSION_WRITE_REQUEST = 9,
+ CET_MP_WRITE_SESSION_WRITE_RESPONSE = 10,
+ CET_MP_WRITE_SESSION_CLOSE_NOTIFICATION = 11,
+ CET_MP_WRITE_SESSION_ABANDON_NOTIFICATION = 12,
+ CET_MP_READ_SESSION_REQUEST = 13,
+ CET_MP_READ_SESSION_RESPONSE = 14,
+ CET_MP_READ_SESSION_READ_REQUEST = 15,
+ CET_MP_READ_SESSION_READ_RESPONSE = 16,
+ CET_MP_READ_SESSION_CLOSE_NOTIFICATION = 17
+};
+
+struct cached_connection_params {
+ char *socket_path;
+ struct timeval timeout;
+};
+
+struct cached_connection_ {
+ int sockfd;
+ int read_queue;
+ int write_queue;
+
+ int mp_flag; /* shows if the connection is used for
+ * multipart operations */
+};
+
+/* simple abstractions for not to write "struct" every time */
+typedef struct cached_connection_ *cached_connection;
+typedef struct cached_connection_ *cached_mp_write_session;
+typedef struct cached_connection_ *cached_mp_read_session;
+
+#define INVALID_CACHED_CONNECTION (NULL)
+#define INVALID_CACHED_MP_WRITE_SESSION (NULL)
+#define INVALID_CACHED_MP_READ_SESSION (NULL)
+
+__BEGIN_DECLS
+
+/* initialization/destruction routines */
+extern cached_connection __open_cached_connection(
+ struct cached_connection_params const *);
+extern void __close_cached_connection(cached_connection);
+
+/* simple read/write operations */
+extern int __cached_write(cached_connection, const char *, const char *,
+ size_t, const char *, size_t);
+extern int __cached_read(cached_connection, const char *, const char *,
+ size_t, char *, size_t *);
+
+/* multipart read/write operations */
+extern cached_mp_write_session __open_cached_mp_write_session(
+ struct cached_connection_params const *, const char *);
+extern int __cached_mp_write(cached_mp_write_session, const char *, size_t);
+extern int __abandon_cached_mp_write_session(cached_mp_write_session);
+extern int __close_cached_mp_write_session(cached_mp_write_session);
+
+extern cached_mp_read_session __open_cached_mp_read_session(
+ struct cached_connection_params const *, const char *);
+extern int __cached_mp_read(cached_mp_read_session, char *, size_t *);
+extern int __close_cached_mp_read_session(cached_mp_read_session);
+
+__END_DECLS
+
+#endif
diff --git a/lib/libc/include/nss_tls.h b/lib/libc/include/nss_tls.h
new file mode 100644
index 0000000..13ab367
--- /dev/null
+++ b/lib/libc/include/nss_tls.h
@@ -0,0 +1,80 @@
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ *
+ * Macros which generate thread local storage handling code in NSS modules.
+ */
+#ifndef _NSS_TLS_H_
+#define _NSS_TLS_H_
+
+#define NSS_TLS_HANDLING(name) \
+static pthread_key_t name##_state_key; \
+static void name##_keyinit(void); \
+static int name##_getstate(struct name##_state **); \
+\
+static void \
+name##_keyinit(void) \
+{ \
+ (void)_pthread_key_create(&name##_state_key, name##_endstate); \
+} \
+\
+static int \
+name##_getstate(struct name##_state **p) \
+{ \
+ static struct name##_state st; \
+ static pthread_once_t keyinit = PTHREAD_ONCE_INIT; \
+ int rv; \
+ \
+ if (!__isthreaded || _pthread_main_np() != 0) { \
+ *p = &st; \
+ return (0); \
+ } \
+ rv = _pthread_once(&keyinit, name##_keyinit); \
+ if (rv != 0) \
+ return (rv); \
+ *p = _pthread_getspecific(name##_state_key); \
+ if (*p != NULL) \
+ return (0); \
+ *p = calloc(1, sizeof(**p)); \
+ if (*p == NULL) \
+ return (ENOMEM); \
+ rv = _pthread_setspecific(name##_state_key, *p); \
+ if (rv != 0) { \
+ free(*p); \
+ *p = NULL; \
+ } \
+ return (rv); \
+} \
+/* allow the macro invocation to end with a semicolon */ \
+struct _clashproof_bmVjdGFy
+
+#endif /* _NSS_TLS_H_ */
diff --git a/lib/libc/include/port_after.h b/lib/libc/include/port_after.h
new file mode 100644
index 0000000..94f3a64
--- /dev/null
+++ b/lib/libc/include/port_after.h
@@ -0,0 +1,11 @@
+/* $FreeBSD$ */
+
+#ifndef _PORT_AFTER_H_
+#define _PORT_AFTER_H_
+
+#define HAVE_SA_LEN 1
+#define HAS_INET6_STRUCTS 1
+#define HAVE_SIN6_SCOPE_ID 1
+#define HAVE_TIME_R 1
+
+#endif /* _PORT_AFTER_H_ */
diff --git a/lib/libc/include/port_before.h b/lib/libc/include/port_before.h
new file mode 100644
index 0000000..beef71d
--- /dev/null
+++ b/lib/libc/include/port_before.h
@@ -0,0 +1,22 @@
+/* $FreeBSD$ */
+
+#ifndef _PORT_BEFORE_H_
+#define _PORT_BEFORE_H_
+
+#define _LIBC 1
+#define DO_PTHREADS 1
+#define USE_KQUEUE 1
+
+#define ISC_SOCKLEN_T socklen_t
+#define ISC_FORMAT_PRINTF(fmt, args) \
+ __attribute__((__format__(__printf__, fmt, args)))
+#define DE_CONST(konst, var) \
+ do { \
+ union { const void *k; void *v; } _u; \
+ _u.k = konst; \
+ var = _u.v; \
+ } while (0)
+
+#define UNUSED(x) (x) = (x)
+
+#endif /* _PORT_BEFORE_H_ */
diff --git a/lib/libc/include/reentrant.h b/lib/libc/include/reentrant.h
new file mode 100644
index 0000000..22a2325
--- /dev/null
+++ b/lib/libc/include/reentrant.h
@@ -0,0 +1,128 @@
+/*-
+ * Copyright (c) 1997,98 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by J.T. Conklin.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Requirements:
+ *
+ * 1. The thread safe mechanism should be lightweight so the library can
+ * be used by non-threaded applications without unreasonable overhead.
+ *
+ * 2. There should be no dependency on a thread engine for non-threaded
+ * applications.
+ *
+ * 3. There should be no dependency on any particular thread engine.
+ *
+ * 4. The library should be able to be compiled without support for thread
+ * safety.
+ *
+ *
+ * Rationale:
+ *
+ * One approach for thread safety is to provide discrete versions of the
+ * library: one thread safe, the other not. The disadvantage of this is
+ * that libc is rather large, and two copies of a library which are 99%+
+ * identical is not an efficent use of resources.
+ *
+ * Another approach is to provide a single thread safe library. However,
+ * it should not add significant run time or code size overhead to non-
+ * threaded applications.
+ *
+ * Since the NetBSD C library is used in other projects, it should be
+ * easy to replace the mutual exclusion primitives with ones provided by
+ * another system. Similarly, it should also be easy to remove all
+ * support for thread safety completely if the target environment does
+ * not support threads.
+ *
+ *
+ * Implementation Details:
+ *
+ * The mutex primitives used by the library (mutex_t, mutex_lock, etc.)
+ * are macros which expand to the cooresponding primitives provided by
+ * the thread engine or to nothing. The latter is used so that code is
+ * not unreasonably cluttered with #ifdefs when all thread safe support
+ * is removed.
+ *
+ * The mutex macros can be directly mapped to the mutex primitives from
+ * pthreads, however it should be reasonably easy to wrap another mutex
+ * implementation so it presents a similar interface.
+ *
+ * Stub implementations of the mutex functions are provided with *weak*
+ * linkage. These functions simply return success. When linked with a
+ * thread library (i.e. -lpthread), the functions will override the
+ * stubs.
+ */
+
+#include <pthread.h>
+#include <pthread_np.h>
+#include "libc_private.h"
+
+#define mutex_t pthread_mutex_t
+#define cond_t pthread_cond_t
+#define rwlock_t pthread_rwlock_t
+#define once_t pthread_once_t
+
+#define thread_key_t pthread_key_t
+#define MUTEX_INITIALIZER PTHREAD_MUTEX_INITIALIZER
+#define RWLOCK_INITIALIZER PTHREAD_RWLOCK_INITIALIZER
+#define ONCE_INITIALIZER PTHREAD_ONCE_INIT
+
+#define mutex_init(m, a) _pthread_mutex_init(m, a)
+#define mutex_lock(m) if (__isthreaded) \
+ _pthread_mutex_lock(m)
+#define mutex_unlock(m) if (__isthreaded) \
+ _pthread_mutex_unlock(m)
+#define mutex_trylock(m) (__isthreaded ? 0 : _pthread_mutex_trylock(m))
+
+#define cond_init(c, a, p) _pthread_cond_init(c, a)
+#define cond_signal(m) if (__isthreaded) \
+ _pthread_cond_signal(m)
+#define cond_broadcast(m) if (__isthreaded) \
+ _pthread_cond_broadcast(m)
+#define cond_wait(c, m) if (__isthreaded) \
+ _pthread_cond_wait(c, m)
+
+#define rwlock_init(l, a) _pthread_rwlock_init(l, a)
+#define rwlock_rdlock(l) if (__isthreaded) \
+ _pthread_rwlock_rdlock(l)
+#define rwlock_wrlock(l) if (__isthreaded) \
+ _pthread_rwlock_wrlock(l)
+#define rwlock_unlock(l) if (__isthreaded) \
+ _pthread_rwlock_unlock(l)
+
+#define thr_keycreate(k, d) _pthread_key_create(k, d)
+#define thr_setspecific(k, p) _pthread_setspecific(k, p)
+#define thr_getspecific(k) _pthread_getspecific(k)
+#define thr_sigsetmask(f, n, o) _pthread_sigmask(f, n, o)
+
+#define thr_once(o, i) _pthread_once(o, i)
+#define thr_self() _pthread_self()
+#define thr_exit(x) _pthread_exit(x)
+#define thr_main() _pthread_main_np()
diff --git a/lib/libc/include/resolv_mt.h b/lib/libc/include/resolv_mt.h
new file mode 100644
index 0000000..27963a1
--- /dev/null
+++ b/lib/libc/include/resolv_mt.h
@@ -0,0 +1,47 @@
+#ifndef _RESOLV_MT_H
+#define _RESOLV_MT_H
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+/* Access functions for the libresolv private interface */
+
+int __res_enable_mt(void);
+int __res_disable_mt(void);
+
+/* Per-thread context */
+
+typedef struct {
+int no_hosts_fallback_private;
+int retry_save;
+int retry_private;
+char inet_nsap_ntoa_tmpbuf[255*3];
+char sym_ntos_unname[20];
+char sym_ntop_unname[20];
+char p_option_nbuf[40];
+char p_time_nbuf[40];
+char precsize_ntoa_retbuf[sizeof "90000000.00"];
+char loc_ntoa_tmpbuf[sizeof
+"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
+char p_secstodate_output[15];
+} mtctxres_t;
+
+/* Thread-specific data (TSD) */
+
+mtctxres_t *___mtctxres(void);
+#define mtctxres (___mtctxres())
+
+/* Various static data that should be TSD */
+
+#define sym_ntos_unname (mtctxres->sym_ntos_unname)
+#define sym_ntop_unname (mtctxres->sym_ntop_unname)
+#define inet_nsap_ntoa_tmpbuf (mtctxres->inet_nsap_ntoa_tmpbuf)
+#define p_option_nbuf (mtctxres->p_option_nbuf)
+#define p_time_nbuf (mtctxres->p_time_nbuf)
+#define precsize_ntoa_retbuf (mtctxres->precsize_ntoa_retbuf)
+#define loc_ntoa_tmpbuf (mtctxres->loc_ntoa_tmpbuf)
+#define p_secstodate_output (mtctxres->p_secstodate_output)
+
+#endif /* _RESOLV_MT_H */
diff --git a/lib/libc/include/spinlock.h b/lib/libc/include/spinlock.h
new file mode 100644
index 0000000..c9facc5
--- /dev/null
+++ b/lib/libc/include/spinlock.h
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ *
+ * Lock definitions used in both libc and libpthread.
+ *
+ */
+
+#ifndef _SPINLOCK_H_
+#define _SPINLOCK_H_
+#include <sys/cdefs.h>
+#include <sys/types.h>
+
+/*
+ * Lock structure with room for debugging information.
+ */
+struct _spinlock {
+ volatile long access_lock;
+ volatile long lock_owner;
+ volatile char *fname;
+ volatile int lineno;
+};
+typedef struct _spinlock spinlock_t;
+
+#define _SPINLOCK_INITIALIZER { 0, 0, 0, 0 }
+
+#define _SPINUNLOCK(_lck) _spinunlock(_lck);
+#ifdef _LOCK_DEBUG
+#define _SPINLOCK(_lck) _spinlock_debug(_lck, __FILE__, __LINE__)
+#else
+#define _SPINLOCK(_lck) _spinlock(_lck)
+#endif
+
+/*
+ * Thread function prototype definitions:
+ */
+__BEGIN_DECLS
+long _atomic_lock(volatile long *);
+void _spinlock(spinlock_t *);
+void _spinunlock(spinlock_t *);
+void _spinlock_debug(spinlock_t *, char *, int);
+__END_DECLS
+
+#endif /* _SPINLOCK_H_ */
diff --git a/lib/libc/include/un-namespace.h b/lib/libc/include/un-namespace.h
new file mode 100644
index 0000000..9c9ce97
--- /dev/null
+++ b/lib/libc/include/un-namespace.h
@@ -0,0 +1,255 @@
+/*
+ * Copyright (c) 2001 Daniel Eischen <deischen@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _UN_NAMESPACE_H_
+#define _UN_NAMESPACE_H_
+
+#undef accept
+#undef __acl_aclcheck_fd
+#undef __acl_delete_fd
+#undef __acl_get_fd
+#undef __acl_set_fd
+#undef bind
+#undef __cap_get_fd
+#undef __cap_set_fd
+#undef close
+#undef connect
+#undef dup
+#undef dup2
+#undef execve
+#undef fcntl
+#undef flock
+#undef flockfile
+#undef fpathconf
+#undef fstat
+#undef fstatfs
+#undef fsync
+#undef funlockfile
+#undef getdirentries
+#undef getlogin
+#undef getpeername
+#undef getprogname
+#undef getsockname
+#undef getsockopt
+#undef ioctl
+#undef kevent
+#undef listen
+#undef nanosleep
+#undef open
+#undef openat
+#undef poll
+#undef pthread_atfork
+#undef pthread_attr_destroy
+#undef pthread_attr_get_np
+#undef pthread_attr_getaffinity_np
+#undef pthread_attr_getdetachstate
+#undef pthread_attr_getguardsize
+#undef pthread_attr_getinheritsched
+#undef pthread_attr_getschedparam
+#undef pthread_attr_getschedpolicy
+#undef pthread_attr_getscope
+#undef pthread_attr_getstack
+#undef pthread_attr_getstackaddr
+#undef pthread_attr_getstacksize
+#undef pthread_attr_init
+#undef pthread_attr_setaffinity_np
+#undef pthread_attr_setcreatesuspend_np
+#undef pthread_attr_setdetachstate
+#undef pthread_attr_setguardsize
+#undef pthread_attr_setinheritsched
+#undef pthread_attr_setschedparam
+#undef pthread_attr_setschedpolicy
+#undef pthread_attr_setscope
+#undef pthread_attr_setstack
+#undef pthread_attr_setstackaddr
+#undef pthread_attr_setstacksize
+#undef pthread_barrier_destroy
+#undef pthread_barrier_init
+#undef pthread_barrier_wait
+#undef pthread_barrierattr_destroy
+#undef pthread_barrierattr_getpshared
+#undef pthread_barrierattr_init
+#undef pthread_barrierattr_setpshared
+#undef pthread_cancel
+#undef pthread_cond_broadcast
+#undef pthread_cond_destroy
+#undef pthread_cond_init
+#undef pthread_cond_signal
+#undef pthread_cond_timedwait
+#undef pthread_cond_wait
+#undef pthread_condattr_destroy
+#undef pthread_condattr_getclock
+#undef pthread_condattr_getpshared
+#undef pthread_condattr_init
+#undef pthread_condattr_setclock
+#undef pthread_condattr_setpshared
+#undef pthread_create
+#undef pthread_detach
+#undef pthread_equal
+#undef pthread_exit
+#undef pthread_getaffinity_np
+#undef pthread_getconcurrency
+#undef pthread_getcpuclockid
+#undef pthread_getprio
+#undef pthread_getschedparam
+#undef pthread_getspecific
+#undef pthread_getthreadid_np
+#undef pthread_join
+#undef pthread_key_create
+#undef pthread_key_delete
+#undef pthread_kill
+#undef pthread_main_np
+#undef pthread_multi_np
+#undef pthread_mutex_destroy
+#undef pthread_mutex_getprioceiling
+#undef pthread_mutex_init
+#undef pthread_mutex_isowned_np
+#undef pthread_mutex_lock
+#undef pthread_mutex_setprioceiling
+#undef pthread_mutex_timedlock
+#undef pthread_mutex_trylock
+#undef pthread_mutex_unlock
+#undef pthread_mutexattr_destroy
+#undef pthread_mutexattr_getkind_np
+#undef pthread_mutexattr_getprioceiling
+#undef pthread_mutexattr_getprotocol
+#undef pthread_mutexattr_getpshared
+#undef pthread_mutexattr_gettype
+#undef pthread_mutexattr_init
+#undef pthread_mutexattr_setkind_np
+#undef pthread_mutexattr_setprioceiling
+#undef pthread_mutexattr_setprotocol
+#undef pthread_mutexattr_setpshared
+#undef pthread_mutexattr_settype
+#undef pthread_once
+#undef pthread_resume_all_np
+#undef pthread_resume_np
+#undef pthread_rwlock_destroy
+#undef pthread_rwlock_init
+#undef pthread_rwlock_rdlock
+#undef pthread_rwlock_timedrdlock
+#undef pthread_rwlock_timedwrlock
+#undef pthread_rwlock_tryrdlock
+#undef pthread_rwlock_trywrlock
+#undef pthread_rwlock_unlock
+#undef pthread_rwlock_wrlock
+#undef pthread_rwlockattr_destroy
+#undef pthread_rwlockattr_getpshared
+#undef pthread_rwlockattr_init
+#undef pthread_rwlockattr_setpshared
+#undef pthread_self
+#undef pthread_set_name_np
+#undef pthread_setaffinity_np
+#undef pthread_setcancelstate
+#undef pthread_setcanceltype
+#undef pthread_setconcurrency
+#undef pthread_setprio
+#undef pthread_setschedparam
+#undef pthread_setspecific
+#undef pthread_sigmask
+#undef pthread_single_np
+#undef pthread_spin_destroy
+#undef pthread_spin_init
+#undef pthread_spin_lock
+#undef pthread_spin_trylock
+#undef pthread_spin_unlock
+#undef pthread_suspend_all_np
+#undef pthread_suspend_np
+#undef pthread_switch_add_np
+#undef pthread_switch_delete_np
+#undef pthread_testcancel
+#undef pthread_timedjoin_np
+#undef pthread_yield
+#undef read
+#undef readv
+#undef recvfrom
+#undef recvmsg
+#undef select
+#undef sem_close
+#undef sem_destroy
+#undef sem_getvalue
+#undef sem_init
+#undef sem_open
+#undef sem_post
+#undef sem_timedwait
+#undef sem_trywait
+#undef sem_unlink
+#undef sem_wait
+#undef sendmsg
+#undef sendto
+#undef setsockopt
+#undef sigaction
+#undef sigprocmask
+#undef sigsuspend
+#undef socket
+#undef socketpair
+#undef usleep
+#undef wait4
+#undef waitpid
+#undef write
+#undef writev
+
+#if 0
+#undef creat
+#undef fchflags
+#undef fchmod
+#undef ftrylockfile
+#undef msync
+#undef nfssvc
+#undef pause
+#undef sched_yield
+#undef sendfile
+#undef shutdown
+#undef sigaltstack
+#undef sigpending
+#undef sigreturn
+#undef sigsetmask
+#undef sleep
+#undef system
+#undef tcdrain
+#undef wait
+#endif /* 0 */
+
+#ifdef _SIGNAL_H_
+int _sigaction(int, const struct sigaction *, struct sigaction *);
+#endif
+
+#ifdef _SYS_EVENT_H_
+int _kevent(int, const struct kevent *, int, struct kevent *,
+ int, const struct timespec *);
+#endif
+
+#ifdef _SYS_FCNTL_H_
+int _flock(int, int);
+#endif
+
+#undef err
+#undef warn
+#undef nsdispatch
+
+#endif /* _UN_NAMESPACE_H_ */
diff --git a/lib/libc/inet/Makefile.inc b/lib/libc/inet/Makefile.inc
new file mode 100644
index 0000000..0e6cc39
--- /dev/null
+++ b/lib/libc/inet/Makefile.inc
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+# inet sources
+.PATH: ${.CURDIR}/inet
+
+SRCS+= inet_addr.c inet_cidr_ntop.c inet_cidr_pton.c inet_lnaof.c \
+ inet_makeaddr.c inet_net_ntop.c inet_net_pton.c inet_neta.c \
+ inet_netof.c inet_network.c inet_ntoa.c inet_ntop.c \
+ inet_pton.c nsap_addr.c
+
+SYM_MAPS+= ${.CURDIR}/inet/Symbol.map
diff --git a/lib/libc/inet/Symbol.map b/lib/libc/inet/Symbol.map
new file mode 100644
index 0000000..f188b13
--- /dev/null
+++ b/lib/libc/inet/Symbol.map
@@ -0,0 +1,38 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ __inet_addr;
+ __inet_aton;
+ inet_addr;
+ inet_aton;
+ __inet_cidr_ntop;
+ __inet_cidr_pton;
+ __inet_lnaof;
+ inet_lnaof;
+ __inet_makeaddr;
+ inet_makeaddr;
+ __inet_net_ntop;
+ inet_net_ntop;
+ __inet_net_pton;
+ inet_net_pton;
+ __inet_neta;
+ inet_neta;
+ __inet_netof;
+ inet_netof;
+ __inet_network;
+ inet_network;
+ __inet_ntoa;
+ inet_ntoa;
+ __inet_ntoa_r;
+ inet_ntoa_r;
+ __inet_ntop;
+ inet_ntop;
+ __inet_pton;
+ inet_pton;
+ __inet_nsap_addr;
+ __inet_nsap_ntoa;
+ inet_nsap_addr;
+ inet_nsap_ntoa;
+};
diff --git a/lib/libc/inet/inet_addr.c b/lib/libc/inet/inet_addr.c
new file mode 100644
index 0000000..e606d34
--- /dev/null
+++ b/lib/libc/inet/inet_addr.c
@@ -0,0 +1,215 @@
+/*
+ * Copyright (c) 1983, 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_addr.c 8.1 (Berkeley) 6/17/93";
+static const char rcsid[] = "$Id: inet_addr.c,v 1.4.18.1 2005/04/27 05:00:52 sra Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <ctype.h>
+
+#include "port_after.h"
+
+/*%
+ * Ascii internet address interpretation routine.
+ * The value returned is in network order.
+ */
+in_addr_t /* XXX should be struct in_addr :( */
+inet_addr(const char *cp) {
+ struct in_addr val;
+
+ if (inet_aton(cp, &val))
+ return (val.s_addr);
+ return (INADDR_NONE);
+}
+
+/*%
+ * Check whether "cp" is a valid ascii representation
+ * of an Internet address and convert to a binary address.
+ * Returns 1 if the address is valid, 0 if not.
+ * This replaces inet_addr, the return value from which
+ * cannot distinguish between failure and a local broadcast address.
+ */
+int
+inet_aton(const char *cp, struct in_addr *addr) {
+ u_long val;
+ int base, n;
+ char c;
+ u_int8_t parts[4];
+ u_int8_t *pp = parts;
+ int digit;
+
+ c = *cp;
+ for (;;) {
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, isdigit=decimal.
+ */
+ if (!isdigit((unsigned char)c))
+ return (0);
+ val = 0; base = 10; digit = 0;
+ if (c == '0') {
+ c = *++cp;
+ if (c == 'x' || c == 'X')
+ base = 16, c = *++cp;
+ else {
+ base = 8;
+ digit = 1 ;
+ }
+ }
+ for (;;) {
+ if (isascii(c) && isdigit((unsigned char)c)) {
+ if (base == 8 && (c == '8' || c == '9'))
+ return (0);
+ val = (val * base) + (c - '0');
+ c = *++cp;
+ digit = 1;
+ } else if (base == 16 && isascii(c) &&
+ isxdigit((unsigned char)c)) {
+ val = (val << 4) |
+ (c + 10 - (islower((unsigned char)c) ? 'a' : 'A'));
+ c = *++cp;
+ digit = 1;
+ } else
+ break;
+ }
+ if (c == '.') {
+ /*
+ * Internet format:
+ * a.b.c.d
+ * a.b.c (with c treated as 16 bits)
+ * a.b (with b treated as 24 bits)
+ */
+ if (pp >= parts + 3 || val > 0xffU)
+ return (0);
+ *pp++ = val;
+ c = *++cp;
+ } else
+ break;
+ }
+ /*
+ * Check for trailing characters.
+ */
+ if (c != '\0' && (!isascii(c) || !isspace((unsigned char)c)))
+ return (0);
+ /*
+ * Did we get a valid digit?
+ */
+ if (!digit)
+ return (0);
+ /*
+ * Concoct the address according to
+ * the number of parts specified.
+ */
+ n = pp - parts + 1;
+ switch (n) {
+ case 1: /*%< a -- 32 bits */
+ break;
+
+ case 2: /*%< a.b -- 8.24 bits */
+ if (val > 0xffffffU)
+ return (0);
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /*%< a.b.c -- 8.8.16 bits */
+ if (val > 0xffffU)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /*%< a.b.c.d -- 8.8.8.8 bits */
+ if (val > 0xffU)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+ if (addr != NULL)
+ addr->s_addr = htonl(val);
+ return (1);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_addr
+__weak_reference(__inet_addr, inet_addr);
+#undef inet_aton
+__weak_reference(__inet_aton, inet_aton);
+
+/*! \file */
diff --git a/lib/libc/inet/inet_cidr_ntop.c b/lib/libc/inet/inet_cidr_ntop.c
new file mode 100644
index 0000000..645b3cd
--- /dev/null
+++ b/lib/libc/inet/inet_cidr_ntop.c
@@ -0,0 +1,263 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1998,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_cidr_ntop.c,v 1.4.18.3 2006/10/11 02:32:47 marka Exp $";
+#endif
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static char *
+inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size);
+static char *
+inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size);
+
+/*%
+ * char *
+ * inet_cidr_ntop(af, src, bits, dst, size)
+ * convert network address from network to presentation format.
+ * "src"'s size is determined from its "af".
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * 192.5.5.1/28 has a nonzero host part, which means it isn't a network
+ * as called for by inet_net_ntop() but it can be a host address with
+ * an included netmask.
+ * author:
+ * Paul Vixie (ISC), October 1998
+ */
+char *
+inet_cidr_ntop(int af, const void *src, int bits, char *dst, size_t size) {
+ switch (af) {
+ case AF_INET:
+ return (inet_cidr_ntop_ipv4(src, bits, dst, size));
+ case AF_INET6:
+ return (inet_cidr_ntop_ipv6(src, bits, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+}
+
+static int
+decoct(const u_char *src, int bytes, char *dst, size_t size) {
+ char *odst = dst;
+ char *t;
+ int b;
+
+ for (b = 1; b <= bytes; b++) {
+ if (size < sizeof "255.")
+ return (0);
+ t = dst;
+ dst += SPRINTF((dst, "%u", *src++));
+ if (b != bytes) {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t)(dst - t);
+ }
+ return (dst - odst);
+}
+
+/*%
+ * static char *
+ * inet_cidr_ntop_ipv4(src, bits, dst, size)
+ * convert IPv4 network address from network to presentation format.
+ * "src"'s size is determined from its "af".
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), October 1998
+ */
+static char *
+inet_cidr_ntop_ipv4(const u_char *src, int bits, char *dst, size_t size) {
+ char *odst = dst;
+ size_t len = 4;
+ size_t b;
+ size_t bytes;
+
+ if ((bits < -1) || (bits > 32)) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /* Find number of significant bytes in address. */
+ if (bits == -1)
+ len = 4;
+ else
+ for (len = 1, b = 1 ; b < 4U; b++)
+ if (*(src + b))
+ len = b + 1;
+
+ /* Format whole octets plus nonzero trailing octets. */
+ bytes = (((bits <= 0) ? 1 : bits) + 7) / 8;
+ if (len > bytes)
+ bytes = len;
+ b = decoct(src, bytes, dst, size);
+ if (b == 0U)
+ goto emsgsize;
+ dst += b;
+ size -= b;
+
+ if (bits != -1) {
+ /* Format CIDR /width. */
+ if (size < sizeof "/32")
+ goto emsgsize;
+ dst += SPRINTF((dst, "/%u", bits));
+ }
+
+ return (odst);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
+
+static char *
+inet_cidr_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) {
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255/128"];
+ char *tp;
+ struct { int base, len; } best, cur;
+ u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+
+ if ((bits < -1) || (bits > 128)) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof words);
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ best.len = 0;
+ cur.base = -1;
+ cur.len = 0;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len)) {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 && (best.len == 6 ||
+ (best.len == 7 && words[7] != 0x0001) ||
+ (best.len == 5 && words[5] == 0xffff))) {
+ int n;
+
+ if (src[15] || bits == -1 || bits > 120)
+ n = 4;
+ else if (src[14] || bits > 112)
+ n = 3;
+ else
+ n = 2;
+ n = decoct(src+12, n, tp, sizeof tmp - (tp - tmp));
+ if (n == 0) {
+ errno = EMSGSIZE;
+ return (NULL);
+ }
+ tp += strlen(tp);
+ break;
+ }
+ tp += SPRINTF((tp, "%x", words[i]));
+ }
+
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) ==
+ (NS_IN6ADDRSZ / NS_INT16SZ))
+ *tp++ = ':';
+ *tp = '\0';
+
+ if (bits != -1)
+ tp += SPRINTF((tp, "/%u", bits));
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((size_t)(tp - tmp) > size) {
+ errno = EMSGSIZE;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
+
+/*! \file */
diff --git a/lib/libc/inet/inet_cidr_pton.c b/lib/libc/inet/inet_cidr_pton.c
new file mode 100644
index 0000000..b0586ff
--- /dev/null
+++ b/lib/libc/inet/inet_cidr_pton.c
@@ -0,0 +1,279 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1998,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_cidr_pton.c,v 1.5.18.1 2005/04/27 05:00:53 sra Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static int inet_cidr_pton_ipv4 __P((const char *src, u_char *dst,
+ int *bits, int ipv6));
+static int inet_cidr_pton_ipv6 __P((const char *src, u_char *dst,
+ int *bits));
+
+static int getbits(const char *, int ipv6);
+
+/*%
+ * int
+ * inet_cidr_pton(af, src, dst, *bits)
+ * convert network address from presentation to network format.
+ * accepts inet_pton()'s input for this "af" plus trailing "/CIDR".
+ * "dst" is assumed large enough for its "af". "bits" is set to the
+ * /CIDR prefix length, which can have defaults (like /32 for IPv4).
+ * return:
+ * -1 if an error occurred (inspect errno; ENOENT means bad format).
+ * 0 if successful conversion occurred.
+ * note:
+ * 192.5.5.1/28 has a nonzero host part, which means it isn't a network
+ * as called for by inet_net_pton() but it can be a host address with
+ * an included netmask.
+ * author:
+ * Paul Vixie (ISC), October 1998
+ */
+int
+inet_cidr_pton(int af, const char *src, void *dst, int *bits) {
+ switch (af) {
+ case AF_INET:
+ return (inet_cidr_pton_ipv4(src, dst, bits, 0));
+ case AF_INET6:
+ return (inet_cidr_pton_ipv6(src, dst, bits));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+}
+
+static const char digits[] = "0123456789";
+
+static int
+inet_cidr_pton_ipv4(const char *src, u_char *dst, int *pbits, int ipv6) {
+ const u_char *odst = dst;
+ int n, ch, tmp, bits;
+ size_t size = 4;
+
+ /* Get the mantissa. */
+ while (ch = *src++, (isascii(ch) && isdigit(ch))) {
+ tmp = 0;
+ do {
+ n = strchr(digits, ch) - digits;
+ assert(n >= 0 && n <= 9);
+ tmp *= 10;
+ tmp += n;
+ if (tmp > 255)
+ goto enoent;
+ } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
+ if (size-- == 0U)
+ goto emsgsize;
+ *dst++ = (u_char) tmp;
+ if (ch == '\0' || ch == '/')
+ break;
+ if (ch != '.')
+ goto enoent;
+ }
+
+ /* Get the prefix length if any. */
+ bits = -1;
+ if (ch == '/' && dst > odst) {
+ bits = getbits(src, ipv6);
+ if (bits == -2)
+ goto enoent;
+ } else if (ch != '\0')
+ goto enoent;
+
+ /* Prefix length can default to /32 only if all four octets spec'd. */
+ if (bits == -1) {
+ if (dst - odst == 4)
+ bits = ipv6 ? 128 : 32;
+ else
+ goto enoent;
+ }
+
+ /* If nothing was written to the destination, we found no address. */
+ if (dst == odst)
+ goto enoent;
+
+ /* If prefix length overspecifies mantissa, life is bad. */
+ if (((bits - (ipv6 ? 96 : 0)) / 8) > (dst - odst))
+ goto enoent;
+
+ /* Extend address to four octets. */
+ while (size-- > 0U)
+ *dst++ = 0;
+
+ *pbits = bits;
+ return (0);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+static int
+inet_cidr_pton_ipv6(const char *src, u_char *dst, int *pbits) {
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ u_int val;
+ int bits;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ bits = -1;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (val > 0xffff)
+ return (0);
+ saw_xdigit = 1;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ } else if (*src == '\0') {
+ return (0);
+ }
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ saw_xdigit = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_cidr_pton_ipv4(curtok, tp, &bits, 1) == 0) {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ break; /*%< '\\0' was seen by inet_pton4(). */
+ }
+ if (ch == '/') {
+ bits = getbits(src, 1);
+ if (bits == -2)
+ goto enoent;
+ break;
+ }
+ goto enoent;
+ }
+ if (saw_xdigit) {
+ if (tp + NS_INT16SZ > endp)
+ goto emsgsize;
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ if (tp == endp)
+ goto enoent;
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+
+ *pbits = bits;
+ return (0);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+static int
+getbits(const char *src, int ipv6) {
+ int bits = 0;
+ char *cp, ch;
+
+ if (*src == '\0') /*%< syntax */
+ return (-2);
+ do {
+ ch = *src++;
+ cp = strchr(digits, ch);
+ if (cp == NULL) /*%< syntax */
+ return (-2);
+ bits *= 10;
+ bits += cp - digits;
+ if (bits == 0 && *src != '\0') /*%< no leading zeros */
+ return (-2);
+ if (bits > (ipv6 ? 128 : 32)) /*%< range error */
+ return (-2);
+ } while (*src != '\0');
+
+ return (bits);
+}
+
+/*! \file */
diff --git a/lib/libc/inet/inet_lnaof.c b/lib/libc/inet/inet_lnaof.c
new file mode 100644
index 0000000..7cab894
--- /dev/null
+++ b/lib/libc/inet/inet_lnaof.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_lnaof.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "port_after.h"
+
+/*%
+ * Return the local network address portion of an
+ * internet address; handles class a/b/c network
+ * number formats.
+ */
+in_addr_t
+inet_lnaof(in)
+ struct in_addr in;
+{
+ in_addr_t i = ntohl(in.s_addr);
+
+ if (IN_CLASSA(i))
+ return ((i)&IN_CLASSA_HOST);
+ else if (IN_CLASSB(i))
+ return ((i)&IN_CLASSB_HOST);
+ else
+ return ((i)&IN_CLASSC_HOST);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_lnaof
+__weak_reference(__inet_lnaof, inet_lnaof);
+
+/*! \file */
diff --git a/lib/libc/inet/inet_makeaddr.c b/lib/libc/inet/inet_makeaddr.c
new file mode 100644
index 0000000..04a37a0
--- /dev/null
+++ b/lib/libc/inet/inet_makeaddr.c
@@ -0,0 +1,73 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_makeaddr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "port_after.h"
+
+/*%
+ * Formulate an Internet address from network + host. Used in
+ * building addresses stored in the ifnet structure.
+ */
+struct in_addr
+inet_makeaddr(net, host)
+ in_addr_t net, host;
+{
+ struct in_addr a;
+
+ if (net < 128U)
+ a.s_addr = (net << IN_CLASSA_NSHIFT) | (host & IN_CLASSA_HOST);
+ else if (net < 65536U)
+ a.s_addr = (net << IN_CLASSB_NSHIFT) | (host & IN_CLASSB_HOST);
+ else if (net < 16777216L)
+ a.s_addr = (net << IN_CLASSC_NSHIFT) | (host & IN_CLASSC_HOST);
+ else
+ a.s_addr = net | host;
+ a.s_addr = htonl(a.s_addr);
+ return (a);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_makeaddr
+__weak_reference(__inet_makeaddr, inet_makeaddr);
+
+/*! \file */
diff --git a/lib/libc/inet/inet_net_ntop.c b/lib/libc/inet/inet_net_ntop.c
new file mode 100644
index 0000000..867f441
--- /dev/null
+++ b/lib/libc/inet/inet_net_ntop.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_net_ntop.c,v 1.3.18.2 2006/06/20 02:51:32 marka Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+static char * inet_net_ntop_ipv4(const u_char *src, int bits, char *dst,
+ size_t size);
+static char * inet_net_ntop_ipv6(const u_char *src, int bits, char *dst,
+ size_t size);
+
+/*%
+ * char *
+ * inet_net_ntop(af, src, bits, dst, size)
+ * convert network number from network to presentation format.
+ * generates CIDR style result always.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+char *
+inet_net_ntop(af, src, bits, dst, size)
+ int af;
+ const void *src;
+ int bits;
+ char *dst;
+ size_t size;
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_net_ntop_ipv4(src, bits, dst, size));
+ case AF_INET6:
+ return (inet_net_ntop_ipv6(src, bits, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+}
+
+/*%
+ * static char *
+ * inet_net_ntop_ipv4(src, bits, dst, size)
+ * convert IPv4 network number from network to presentation format.
+ * generates CIDR style result always.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+static char *
+inet_net_ntop_ipv4(src, bits, dst, size)
+ const u_char *src;
+ int bits;
+ char *dst;
+ size_t size;
+{
+ char *odst = dst;
+ char *t;
+ u_int m;
+ int b;
+
+ if (bits < 0 || bits > 32) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (bits == 0) {
+ if (size < sizeof "0")
+ goto emsgsize;
+ *dst++ = '0';
+ size--;
+ *dst = '\0';
+ }
+
+ /* Format whole octets. */
+ for (b = bits / 8; b > 0; b--) {
+ if (size <= sizeof "255.")
+ goto emsgsize;
+ t = dst;
+ dst += SPRINTF((dst, "%u", *src++));
+ if (b > 1) {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t)(dst - t);
+ }
+
+ /* Format partial octet. */
+ b = bits % 8;
+ if (b > 0) {
+ if (size <= sizeof ".255")
+ goto emsgsize;
+ t = dst;
+ if (dst != odst)
+ *dst++ = '.';
+ m = ((1 << b) - 1) << (8 - b);
+ dst += SPRINTF((dst, "%u", *src & m));
+ size -= (size_t)(dst - t);
+ }
+
+ /* Format CIDR /width. */
+ if (size <= sizeof "/32")
+ goto emsgsize;
+ dst += SPRINTF((dst, "/%u", bits));
+ return (odst);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
+
+/*%
+ * static char *
+ * inet_net_ntop_ipv6(src, bits, fakebits, dst, size)
+ * convert IPv6 network number from network to presentation format.
+ * generates CIDR style result always. Picks the shortest representation
+ * unless the IP is really IPv4.
+ * always prints specified number of bits (bits).
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Vadim Kogan (UCB), June 2001
+ * Original version (IPv4) by Paul Vixie (ISC), July 1996
+ */
+
+static char *
+inet_net_ntop_ipv6(const u_char *src, int bits, char *dst, size_t size) {
+ u_int m;
+ int b;
+ int p;
+ int zero_s, zero_l, tmp_zero_s, tmp_zero_l;
+ int i;
+ int is_ipv4 = 0;
+ unsigned char inbuf[16];
+ char outbuf[sizeof("xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:255.255.255.255/128")];
+ char *cp;
+ int words;
+ u_char *s;
+
+ if (bits < 0 || bits > 128) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ cp = outbuf;
+
+ if (bits == 0) {
+ *cp++ = ':';
+ *cp++ = ':';
+ *cp = '\0';
+ } else {
+ /* Copy src to private buffer. Zero host part. */
+ p = (bits + 7) / 8;
+ memcpy(inbuf, src, p);
+ memset(inbuf + p, 0, 16 - p);
+ b = bits % 8;
+ if (b != 0) {
+ m = ~0 << (8 - b);
+ inbuf[p-1] &= m;
+ }
+
+ s = inbuf;
+
+ /* how many words need to be displayed in output */
+ words = (bits + 15) / 16;
+ if (words == 1)
+ words = 2;
+
+ /* Find the longest substring of zero's */
+ zero_s = zero_l = tmp_zero_s = tmp_zero_l = 0;
+ for (i = 0; i < (words * 2); i += 2) {
+ if ((s[i] | s[i+1]) == 0) {
+ if (tmp_zero_l == 0)
+ tmp_zero_s = i / 2;
+ tmp_zero_l++;
+ } else {
+ if (tmp_zero_l && zero_l < tmp_zero_l) {
+ zero_s = tmp_zero_s;
+ zero_l = tmp_zero_l;
+ tmp_zero_l = 0;
+ }
+ }
+ }
+
+ if (tmp_zero_l && zero_l < tmp_zero_l) {
+ zero_s = tmp_zero_s;
+ zero_l = tmp_zero_l;
+ }
+
+ if (zero_l != words && zero_s == 0 && ((zero_l == 6) ||
+ ((zero_l == 5 && s[10] == 0xff && s[11] == 0xff) ||
+ ((zero_l == 7 && s[14] != 0 && s[15] != 1)))))
+ is_ipv4 = 1;
+
+ /* Format whole words. */
+ for (p = 0; p < words; p++) {
+ if (zero_l != 0 && p >= zero_s && p < zero_s + zero_l) {
+ /* Time to skip some zeros */
+ if (p == zero_s)
+ *cp++ = ':';
+ if (p == words - 1)
+ *cp++ = ':';
+ s++;
+ s++;
+ continue;
+ }
+
+ if (is_ipv4 && p > 5 ) {
+ *cp++ = (p == 6) ? ':' : '.';
+ cp += SPRINTF((cp, "%u", *s++));
+ /* we can potentially drop the last octet */
+ if (p != 7 || bits > 120) {
+ *cp++ = '.';
+ cp += SPRINTF((cp, "%u", *s++));
+ }
+ } else {
+ if (cp != outbuf)
+ *cp++ = ':';
+ cp += SPRINTF((cp, "%x", *s * 256 + s[1]));
+ s += 2;
+ }
+ }
+ }
+ /* Format CIDR /width. */
+ sprintf(cp, "/%u", bits);
+ if (strlen(outbuf) + 1 > size)
+ goto emsgsize;
+ strcpy(dst, outbuf);
+
+ return (dst);
+
+emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_net_ntop
+__weak_reference(__inet_net_ntop, inet_net_ntop);
+
+/*! \file */
diff --git a/lib/libc/inet/inet_net_pton.c b/lib/libc/inet/inet_net_pton.c
new file mode 100644
index 0000000..74df38b9
--- /dev/null
+++ b/lib/libc/inet/inet_net_pton.c
@@ -0,0 +1,416 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_net_pton.c,v 1.7.18.2 2008/08/26 04:42:43 marka Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/*%
+ * static int
+ * inet_net_pton_ipv4(src, dst, size)
+ * convert IPv4 network number from presentation to network format.
+ * accepts hex octets, hex strings, decimal octets, and /CIDR.
+ * "size" is in bytes and describes "dst".
+ * return:
+ * number of bits, either imputed classfully or specified with /CIDR,
+ * or -1 if some failure occurred (check errno). ENOENT means it was
+ * not an IPv4 network specification.
+ * note:
+ * network byte order assumed. this means 192.5.5.240/28 has
+ * 0b11110000 in its fourth octet.
+ * author:
+ * Paul Vixie (ISC), June 1996
+ */
+static int
+inet_net_pton_ipv4(const char *src, u_char *dst, size_t size) {
+ static const char xdigits[] = "0123456789abcdef";
+ static const char digits[] = "0123456789";
+ int n, ch, tmp = 0, dirty, bits;
+ const u_char *odst = dst;
+
+ ch = *src++;
+ if (ch == '0' && (src[0] == 'x' || src[0] == 'X')
+ && isascii((unsigned char)(src[1]))
+ && isxdigit((unsigned char)(src[1]))) {
+ /* Hexadecimal: Eat nybble string. */
+ if (size <= 0U)
+ goto emsgsize;
+ dirty = 0;
+ src++; /*%< skip x or X. */
+ while ((ch = *src++) != '\0' && isascii(ch) && isxdigit(ch)) {
+ if (isupper(ch))
+ ch = tolower(ch);
+ n = strchr(xdigits, ch) - xdigits;
+ assert(n >= 0 && n <= 15);
+ if (dirty == 0)
+ tmp = n;
+ else
+ tmp = (tmp << 4) | n;
+ if (++dirty == 2) {
+ if (size-- <= 0U)
+ goto emsgsize;
+ *dst++ = (u_char) tmp;
+ dirty = 0;
+ }
+ }
+ if (dirty) { /*%< Odd trailing nybble? */
+ if (size-- <= 0U)
+ goto emsgsize;
+ *dst++ = (u_char) (tmp << 4);
+ }
+ } else if (isascii(ch) && isdigit(ch)) {
+ /* Decimal: eat dotted digit string. */
+ for (;;) {
+ tmp = 0;
+ do {
+ n = strchr(digits, ch) - digits;
+ assert(n >= 0 && n <= 9);
+ tmp *= 10;
+ tmp += n;
+ if (tmp > 255)
+ goto enoent;
+ } while ((ch = *src++) != '\0' &&
+ isascii(ch) && isdigit(ch));
+ if (size-- <= 0U)
+ goto emsgsize;
+ *dst++ = (u_char) tmp;
+ if (ch == '\0' || ch == '/')
+ break;
+ if (ch != '.')
+ goto enoent;
+ ch = *src++;
+ if (!isascii(ch) || !isdigit(ch))
+ goto enoent;
+ }
+ } else
+ goto enoent;
+
+ bits = -1;
+ if (ch == '/' && isascii((unsigned char)(src[0])) &&
+ isdigit((unsigned char)(src[0])) && dst > odst) {
+ /* CIDR width specifier. Nothing can follow it. */
+ ch = *src++; /*%< Skip over the /. */
+ bits = 0;
+ do {
+ n = strchr(digits, ch) - digits;
+ assert(n >= 0 && n <= 9);
+ bits *= 10;
+ bits += n;
+ if (bits > 32)
+ goto enoent;
+ } while ((ch = *src++) != '\0' && isascii(ch) && isdigit(ch));
+ if (ch != '\0')
+ goto enoent;
+ }
+
+ /* Firey death and destruction unless we prefetched EOS. */
+ if (ch != '\0')
+ goto enoent;
+
+ /* If nothing was written to the destination, we found no address. */
+ if (dst == odst)
+ goto enoent;
+ /* If no CIDR spec was given, infer width from net class. */
+ if (bits == -1) {
+ if (*odst >= 240) /*%< Class E */
+ bits = 32;
+ else if (*odst >= 224) /*%< Class D */
+ bits = 8;
+ else if (*odst >= 192) /*%< Class C */
+ bits = 24;
+ else if (*odst >= 128) /*%< Class B */
+ bits = 16;
+ else /*%< Class A */
+ bits = 8;
+ /* If imputed mask is narrower than specified octets, widen. */
+ if (bits < ((dst - odst) * 8))
+ bits = (dst - odst) * 8;
+ /*
+ * If there are no additional bits specified for a class D
+ * address adjust bits to 4.
+ */
+ if (bits == 8 && *odst == 224)
+ bits = 4;
+ }
+ /* Extend network to cover the actual mask. */
+ while (bits > ((dst - odst) * 8)) {
+ if (size-- <= 0U)
+ goto emsgsize;
+ *dst++ = '\0';
+ }
+ return (bits);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+static int
+getbits(const char *src, int *bitsp) {
+ static const char digits[] = "0123456789";
+ int n;
+ int val;
+ char ch;
+
+ val = 0;
+ n = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ pch = strchr(digits, ch);
+ if (pch != NULL) {
+ if (n++ != 0 && val == 0) /*%< no leading zeros */
+ return (0);
+ val *= 10;
+ val += (pch - digits);
+ if (val > 128) /*%< range */
+ return (0);
+ continue;
+ }
+ return (0);
+ }
+ if (n == 0)
+ return (0);
+ *bitsp = val;
+ return (1);
+}
+
+static int
+getv4(const char *src, u_char *dst, int *bitsp) {
+ static const char digits[] = "0123456789";
+ u_char *odst = dst;
+ int n;
+ u_int val;
+ char ch;
+
+ val = 0;
+ n = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ pch = strchr(digits, ch);
+ if (pch != NULL) {
+ if (n++ != 0 && val == 0) /*%< no leading zeros */
+ return (0);
+ val *= 10;
+ val += (pch - digits);
+ if (val > 255) /*%< range */
+ return (0);
+ continue;
+ }
+ if (ch == '.' || ch == '/') {
+ if (dst - odst > 3) /*%< too many octets? */
+ return (0);
+ *dst++ = val;
+ if (ch == '/')
+ return (getbits(src, bitsp));
+ val = 0;
+ n = 0;
+ continue;
+ }
+ return (0);
+ }
+ if (n == 0)
+ return (0);
+ if (dst - odst > 3) /*%< too many octets? */
+ return (0);
+ *dst++ = val;
+ return (1);
+}
+
+static int
+inet_net_pton_ipv6(const char *src, u_char *dst, size_t size) {
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, saw_xdigit;
+ u_int val;
+ int digits;
+ int bits;
+ size_t bytes;
+ int words;
+ int ipv4;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ goto enoent;
+ curtok = src;
+ saw_xdigit = 0;
+ val = 0;
+ digits = 0;
+ bits = -1;
+ ipv4 = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (++digits > 4)
+ goto enoent;
+ saw_xdigit = 1;
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!saw_xdigit) {
+ if (colonp)
+ goto enoent;
+ colonp = tp;
+ continue;
+ } else if (*src == '\0')
+ goto enoent;
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ saw_xdigit = 0;
+ digits = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ getv4(curtok, tp, &bits) > 0) {
+ tp += NS_INADDRSZ;
+ saw_xdigit = 0;
+ ipv4 = 1;
+ break; /*%< '\\0' was seen by inet_pton4(). */
+ }
+ if (ch == '/' && getbits(src, &bits) > 0)
+ break;
+ goto enoent;
+ }
+ if (saw_xdigit) {
+ if (tp + NS_INT16SZ > endp)
+ goto enoent;
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+ if (bits == -1)
+ bits = 128;
+
+ words = (bits + 15) / 16;
+ if (words < 2)
+ words = 2;
+ if (ipv4)
+ words = 8;
+ endp = tmp + 2 * words;
+
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ if (tp == endp)
+ goto enoent;
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ goto enoent;
+
+ bytes = (bits + 7) / 8;
+ if (bytes > size)
+ goto emsgsize;
+ memcpy(dst, tmp, bytes);
+ return (bits);
+
+ enoent:
+ errno = ENOENT;
+ return (-1);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (-1);
+}
+
+/*%
+ * int
+ * inet_net_pton(af, src, dst, size)
+ * convert network number from presentation to network format.
+ * accepts hex octets, hex strings, decimal octets, and /CIDR.
+ * "size" is in bytes and describes "dst".
+ * return:
+ * number of bits, either imputed classfully or specified with /CIDR,
+ * or -1 if some failure occurred (check errno). ENOENT means it was
+ * not a valid network specification.
+ * author:
+ * Paul Vixie (ISC), June 1996
+ */
+int
+inet_net_pton(int af, const char *src, void *dst, size_t size) {
+ switch (af) {
+ case AF_INET:
+ return (inet_net_pton_ipv4(src, dst, size));
+ case AF_INET6:
+ return (inet_net_pton_ipv6(src, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_net_pton
+__weak_reference(__inet_net_pton, inet_net_pton);
+
+/*! \file */
diff --git a/lib/libc/inet/inet_neta.c b/lib/libc/inet/inet_neta.c
new file mode 100644
index 0000000..72ac549
--- /dev/null
+++ b/lib/libc/inet/inet_neta.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_neta.c,v 1.2.18.1 2005/04/27 05:00:53 sra Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/*%
+ * char *
+ * inet_neta(src, dst, size)
+ * format an in_addr_t network number into presentation format.
+ * return:
+ * pointer to dst, or NULL if an error occurred (check errno).
+ * note:
+ * format of ``src'' is as for inet_network().
+ * author:
+ * Paul Vixie (ISC), July 1996
+ */
+char *
+inet_neta(src, dst, size)
+ in_addr_t src;
+ char *dst;
+ size_t size;
+{
+ char *odst = dst;
+ char *tp;
+
+ while (src & 0xffffffff) {
+ u_char b = (src & 0xff000000) >> 24;
+
+ src <<= 8;
+ if (b) {
+ if (size < sizeof "255.")
+ goto emsgsize;
+ tp = dst;
+ dst += SPRINTF((dst, "%u", b));
+ if (src != 0L) {
+ *dst++ = '.';
+ *dst = '\0';
+ }
+ size -= (size_t)(dst - tp);
+ }
+ }
+ if (dst == odst) {
+ if (size < sizeof "0.0.0.0")
+ goto emsgsize;
+ strcpy(dst, "0.0.0.0");
+ }
+ return (odst);
+
+ emsgsize:
+ errno = EMSGSIZE;
+ return (NULL);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_neta
+__weak_reference(__inet_neta, inet_neta);
+
+/*! \file */
diff --git a/lib/libc/inet/inet_netof.c b/lib/libc/inet/inet_netof.c
new file mode 100644
index 0000000..8931c30
--- /dev/null
+++ b/lib/libc/inet/inet_netof.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_netof.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include "port_after.h"
+
+/*%
+ * Return the network number from an internet
+ * address; handles class a/b/c network #'s.
+ */
+in_addr_t
+inet_netof(in)
+ struct in_addr in;
+{
+ in_addr_t i = ntohl(in.s_addr);
+
+ if (IN_CLASSA(i))
+ return (((i)&IN_CLASSA_NET) >> IN_CLASSA_NSHIFT);
+ else if (IN_CLASSB(i))
+ return (((i)&IN_CLASSB_NET) >> IN_CLASSB_NSHIFT);
+ else
+ return (((i)&IN_CLASSC_NET) >> IN_CLASSC_NSHIFT);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_netof
+__weak_reference(__inet_netof, inet_netof);
+
+/*! \file */
diff --git a/lib/libc/inet/inet_network.c b/lib/libc/inet/inet_network.c
new file mode 100644
index 0000000..254db41
--- /dev/null
+++ b/lib/libc/inet/inet_network.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_network.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <ctype.h>
+
+#include "port_after.h"
+
+/*%
+ * Internet network address interpretation routine.
+ * The library routines call this routine to interpret
+ * network numbers.
+ */
+in_addr_t
+inet_network(cp)
+ const char *cp;
+{
+ in_addr_t val, base, n;
+ char c;
+ in_addr_t parts[4], *pp = parts;
+ int i, digit;
+
+again:
+ val = 0; base = 10; digit = 0;
+ if (*cp == '0')
+ digit = 1, base = 8, cp++;
+ if (*cp == 'x' || *cp == 'X')
+ base = 16, cp++;
+ while ((c = *cp) != 0) {
+ if (isdigit((unsigned char)c)) {
+ if (base == 8U && (c == '8' || c == '9'))
+ return (INADDR_NONE);
+ val = (val * base) + (c - '0');
+ cp++;
+ digit = 1;
+ continue;
+ }
+ if (base == 16U && isxdigit((unsigned char)c)) {
+ val = (val << 4) +
+ (c + 10 - (islower((unsigned char)c) ? 'a' : 'A'));
+ cp++;
+ digit = 1;
+ continue;
+ }
+ break;
+ }
+ if (!digit)
+ return (INADDR_NONE);
+ if (pp >= parts + 4 || val > 0xffU)
+ return (INADDR_NONE);
+ if (*cp == '.') {
+ *pp++ = val, cp++;
+ goto again;
+ }
+ if (*cp && !isspace(*cp&0xff))
+ return (INADDR_NONE);
+ *pp++ = val;
+ n = pp - parts;
+ if (n > 4U)
+ return (INADDR_NONE);
+ for (val = 0, i = 0; i < n; i++) {
+ val <<= 8;
+ val |= parts[i] & 0xff;
+ }
+ return (val);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_network
+__weak_reference(__inet_network, inet_network);
+
+/*! \file */
diff --git a/lib/libc/inet/inet_ntoa.c b/lib/libc/inet/inet_ntoa.c
new file mode 100644
index 0000000..f5d69fa
--- /dev/null
+++ b/lib/libc/inet/inet_ntoa.c
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)inet_ntoa.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: inet_ntoa.c,v 1.1.352.1 2005/04/27 05:00:54 sra Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "port_after.h"
+
+/*%
+ * Convert network-format internet address
+ * to base 256 d.d.d.d representation.
+ */
+/*const*/ char *
+inet_ntoa(struct in_addr in) {
+ static char ret[18];
+
+ strcpy(ret, "[inet_ntoa error]");
+ (void) inet_ntop(AF_INET, &in, ret, sizeof ret);
+ return (ret);
+}
+
+char *
+inet_ntoa_r(struct in_addr in, char *buf, socklen_t size)
+{
+
+ (void) inet_ntop(AF_INET, &in, buf, size);
+ return (buf);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_ntoa
+__weak_reference(__inet_ntoa, inet_ntoa);
+__weak_reference(__inet_ntoa_r, inet_ntoa_r);
+
+/*! \file */
diff --git a/lib/libc/inet/inet_ntop.c b/lib/libc/inet/inet_ntop.c
new file mode 100644
index 0000000..6d21027
--- /dev/null
+++ b/lib/libc/inet/inet_ntop.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_ntop.c,v 1.3.18.2 2005/11/03 23:02:22 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "port_after.h"
+
+/*%
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static const char *inet_ntop4(const u_char *src, char *dst, socklen_t size);
+static const char *inet_ntop6(const u_char *src, char *dst, socklen_t size);
+
+/* char *
+ * inet_ntop(af, src, dst, size)
+ * convert a network format address to presentation format.
+ * return:
+ * pointer to presentation format address (`dst'), or NULL (see errno).
+ * author:
+ * Paul Vixie, 1996.
+ */
+const char *
+inet_ntop(int af, const void * __restrict src, char * __restrict dst,
+ socklen_t size)
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_ntop4(src, dst, size));
+ case AF_INET6:
+ return (inet_ntop6(src, dst, size));
+ default:
+ errno = EAFNOSUPPORT;
+ return (NULL);
+ }
+ /* NOTREACHED */
+}
+
+/* const char *
+ * inet_ntop4(src, dst, size)
+ * format an IPv4 address
+ * return:
+ * `dst' (as a const)
+ * notes:
+ * (1) uses no statics
+ * (2) takes a u_char* not an in_addr as input
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop4(const u_char *src, char *dst, socklen_t size)
+{
+ static const char fmt[] = "%u.%u.%u.%u";
+ char tmp[sizeof "255.255.255.255"];
+ int l;
+
+ l = snprintf(tmp, sizeof(tmp), fmt, src[0], src[1], src[2], src[3]);
+ if (l <= 0 || (socklen_t) l >= size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strlcpy(dst, tmp, size);
+ return (dst);
+}
+
+/* const char *
+ * inet_ntop6(src, dst, size)
+ * convert IPv6 binary address into presentation (printable) format
+ * author:
+ * Paul Vixie, 1996.
+ */
+static const char *
+inet_ntop6(const u_char *src, char *dst, socklen_t size)
+{
+ /*
+ * Note that int32_t and int16_t need only be "at least" large enough
+ * to contain a value of the specified size. On some systems, like
+ * Crays, there is no such thing as an integer variable with 16 bits.
+ * Keep this in mind if you think this function should have been coded
+ * to use pointer overlays. All the world's not a VAX.
+ */
+ char tmp[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255"], *tp;
+ struct { int base, len; } best, cur;
+ u_int words[NS_IN6ADDRSZ / NS_INT16SZ];
+ int i;
+
+ /*
+ * Preprocess:
+ * Copy the input (bytewise) array into a wordwise array.
+ * Find the longest run of 0x00's in src[] for :: shorthanding.
+ */
+ memset(words, '\0', sizeof words);
+ for (i = 0; i < NS_IN6ADDRSZ; i++)
+ words[i / 2] |= (src[i] << ((1 - (i % 2)) << 3));
+ best.base = -1;
+ best.len = 0;
+ cur.base = -1;
+ cur.len = 0;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ if (words[i] == 0) {
+ if (cur.base == -1)
+ cur.base = i, cur.len = 1;
+ else
+ cur.len++;
+ } else {
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ cur.base = -1;
+ }
+ }
+ }
+ if (cur.base != -1) {
+ if (best.base == -1 || cur.len > best.len)
+ best = cur;
+ }
+ if (best.base != -1 && best.len < 2)
+ best.base = -1;
+
+ /*
+ * Format the result.
+ */
+ tp = tmp;
+ for (i = 0; i < (NS_IN6ADDRSZ / NS_INT16SZ); i++) {
+ /* Are we inside the best run of 0x00's? */
+ if (best.base != -1 && i >= best.base &&
+ i < (best.base + best.len)) {
+ if (i == best.base)
+ *tp++ = ':';
+ continue;
+ }
+ /* Are we following an initial run of 0x00s or any real hex? */
+ if (i != 0)
+ *tp++ = ':';
+ /* Is this address an encapsulated IPv4? */
+ if (i == 6 && best.base == 0 && (best.len == 6 ||
+ (best.len == 7 && words[7] != 0x0001) ||
+ (best.len == 5 && words[5] == 0xffff))) {
+ if (!inet_ntop4(src+12, tp, sizeof tmp - (tp - tmp)))
+ return (NULL);
+ tp += strlen(tp);
+ break;
+ }
+ tp += sprintf(tp, "%x", words[i]);
+ }
+ /* Was it a trailing run of 0x00's? */
+ if (best.base != -1 && (best.base + best.len) ==
+ (NS_IN6ADDRSZ / NS_INT16SZ))
+ *tp++ = ':';
+ *tp++ = '\0';
+
+ /*
+ * Check for overflow, copy, and we're done.
+ */
+ if ((socklen_t)(tp - tmp) > size) {
+ errno = ENOSPC;
+ return (NULL);
+ }
+ strcpy(dst, tmp);
+ return (dst);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_ntop
+__weak_reference(__inet_ntop, inet_ntop);
+
+/*! \file */
diff --git a/lib/libc/inet/inet_pton.c b/lib/libc/inet/inet_pton.c
new file mode 100644
index 0000000..ae65099
--- /dev/null
+++ b/lib/libc/inet/inet_pton.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: inet_pton.c,v 1.3.18.2 2005/07/28 07:38:07 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <string.h>
+#include <errno.h>
+#include "port_after.h"
+
+/*%
+ * WARNING: Don't even consider trying to compile this on a system where
+ * sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
+ */
+
+static int inet_pton4(const char *src, u_char *dst);
+static int inet_pton6(const char *src, u_char *dst);
+
+/* int
+ * inet_pton(af, src, dst)
+ * convert from presentation format (which usually means ASCII printable)
+ * to network format (which is usually some kind of binary format).
+ * return:
+ * 1 if the address was valid for the specified address family
+ * 0 if the address wasn't valid (`dst' is untouched in this case)
+ * -1 if some other error occurred (`dst' is untouched in this case, too)
+ * author:
+ * Paul Vixie, 1996.
+ */
+int
+inet_pton(int af, const char * __restrict src, void * __restrict dst)
+{
+ switch (af) {
+ case AF_INET:
+ return (inet_pton4(src, dst));
+ case AF_INET6:
+ return (inet_pton6(src, dst));
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+ /* NOTREACHED */
+}
+
+/* int
+ * inet_pton4(src, dst)
+ * like inet_aton() but without all the hexadecimal and shorthand.
+ * return:
+ * 1 if `src' is a valid dotted quad, else 0.
+ * notice:
+ * does not touch `dst' unless it's returning 1.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton4(const char *src, u_char *dst)
+{
+ static const char digits[] = "0123456789";
+ int saw_digit, octets, ch;
+ u_char tmp[NS_INADDRSZ], *tp;
+
+ saw_digit = 0;
+ octets = 0;
+ *(tp = tmp) = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr(digits, ch)) != NULL) {
+ u_int new = *tp * 10 + (pch - digits);
+
+ if (saw_digit && *tp == 0)
+ return (0);
+ if (new > 255)
+ return (0);
+ *tp = new;
+ if (!saw_digit) {
+ if (++octets > 4)
+ return (0);
+ saw_digit = 1;
+ }
+ } else if (ch == '.' && saw_digit) {
+ if (octets == 4)
+ return (0);
+ *++tp = 0;
+ saw_digit = 0;
+ } else
+ return (0);
+ }
+ if (octets < 4)
+ return (0);
+ memcpy(dst, tmp, NS_INADDRSZ);
+ return (1);
+}
+
+/* int
+ * inet_pton6(src, dst)
+ * convert presentation level address to network order binary form.
+ * return:
+ * 1 if `src' is a valid [RFC1884 2.2] address, else 0.
+ * notice:
+ * (1) does not touch `dst' unless it's returning 1.
+ * (2) :: in a full address is silently ignored.
+ * credit:
+ * inspired by Mark Andrews.
+ * author:
+ * Paul Vixie, 1996.
+ */
+static int
+inet_pton6(const char *src, u_char *dst)
+{
+ static const char xdigits_l[] = "0123456789abcdef",
+ xdigits_u[] = "0123456789ABCDEF";
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
+ const char *xdigits, *curtok;
+ int ch, seen_xdigits;
+ u_int val;
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
+ colonp = NULL;
+ /* Leading :: requires some special handling. */
+ if (*src == ':')
+ if (*++src != ':')
+ return (0);
+ curtok = src;
+ seen_xdigits = 0;
+ val = 0;
+ while ((ch = *src++) != '\0') {
+ const char *pch;
+
+ if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
+ pch = strchr((xdigits = xdigits_u), ch);
+ if (pch != NULL) {
+ val <<= 4;
+ val |= (pch - xdigits);
+ if (++seen_xdigits > 4)
+ return (0);
+ continue;
+ }
+ if (ch == ':') {
+ curtok = src;
+ if (!seen_xdigits) {
+ if (colonp)
+ return (0);
+ colonp = tp;
+ continue;
+ } else if (*src == '\0') {
+ return (0);
+ }
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ seen_xdigits = 0;
+ val = 0;
+ continue;
+ }
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp) > 0) {
+ tp += NS_INADDRSZ;
+ seen_xdigits = 0;
+ break; /*%< '\\0' was seen by inet_pton4(). */
+ }
+ return (0);
+ }
+ if (seen_xdigits) {
+ if (tp + NS_INT16SZ > endp)
+ return (0);
+ *tp++ = (u_char) (val >> 8) & 0xff;
+ *tp++ = (u_char) val & 0xff;
+ }
+ if (colonp != NULL) {
+ /*
+ * Since some memmove()'s erroneously fail to handle
+ * overlapping regions, we'll do the shift by hand.
+ */
+ const int n = tp - colonp;
+ int i;
+
+ if (tp == endp)
+ return (0);
+ for (i = 1; i <= n; i++) {
+ endp[- i] = colonp[n - i];
+ colonp[n - i] = 0;
+ }
+ tp = endp;
+ }
+ if (tp != endp)
+ return (0);
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
+ return (1);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_pton
+__weak_reference(__inet_pton, inet_pton);
+
+/*! \file */
diff --git a/lib/libc/inet/nsap_addr.c b/lib/libc/inet/nsap_addr.c
new file mode 100644
index 0000000..2947472
--- /dev/null
+++ b/lib/libc/inet/nsap_addr.c
@@ -0,0 +1,122 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: nsap_addr.c,v 1.3.18.2 2005/07/28 07:38:08 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <resolv.h>
+#include <resolv_mt.h>
+
+#include "port_after.h"
+
+static char
+xtob(int c) {
+ return (c - (((c >= '0') && (c <= '9')) ? '0' : '7'));
+}
+
+u_int
+inet_nsap_addr(const char *ascii, u_char *binary, int maxlen) {
+ u_char c, nib;
+ u_int len = 0;
+
+ if (ascii[0] != '0' || (ascii[1] != 'x' && ascii[1] != 'X'))
+ return (0);
+ ascii += 2;
+
+ while ((c = *ascii++) != '\0' && len < (u_int)maxlen) {
+ if (c == '.' || c == '+' || c == '/')
+ continue;
+ if (!isascii(c))
+ return (0);
+ if (islower(c))
+ c = toupper(c);
+ if (isxdigit(c)) {
+ nib = xtob(c);
+ c = *ascii++;
+ if (c != '\0') {
+ c = toupper(c);
+ if (isxdigit(c)) {
+ *binary++ = (nib << 4) | xtob(c);
+ len++;
+ } else
+ return (0);
+ }
+ else
+ return (0);
+ }
+ else
+ return (0);
+ }
+ return (len);
+}
+
+char *
+inet_nsap_ntoa(int binlen, const u_char *binary, char *ascii) {
+ int nib;
+ int i;
+ char *tmpbuf = inet_nsap_ntoa_tmpbuf;
+ char *start;
+
+ if (ascii)
+ start = ascii;
+ else {
+ ascii = tmpbuf;
+ start = tmpbuf;
+ }
+
+ *ascii++ = '0';
+ *ascii++ = 'x';
+
+ if (binlen > 255)
+ binlen = 255;
+
+ for (i = 0; i < binlen; i++) {
+ nib = *binary >> 4;
+ *ascii++ = nib + (nib < 10 ? '0' : '7');
+ nib = *binary++ & 0x0f;
+ *ascii++ = nib + (nib < 10 ? '0' : '7');
+ if (((i % 2) == 0 && (i + 1) < binlen))
+ *ascii++ = '.';
+ }
+ *ascii = '\0';
+ return (start);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <arpa/inet.h>.
+ */
+#undef inet_nsap_addr
+__weak_reference(__inet_nsap_addr, inet_nsap_addr);
+#undef inet_nsap_ntoa
+__weak_reference(__inet_nsap_ntoa, inet_nsap_ntoa);
+
+/*! \file */
diff --git a/lib/libc/isc/Makefile.inc b/lib/libc/isc/Makefile.inc
new file mode 100644
index 0000000..48c90f7
--- /dev/null
+++ b/lib/libc/isc/Makefile.inc
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+# isc sources
+.PATH: ${.CURDIR}/isc
+
+SRCS+= ev_streams.c ev_timers.c
diff --git a/lib/libc/isc/ev_streams.c b/lib/libc/isc/ev_streams.c
new file mode 100644
index 0000000..06bdfad
--- /dev/null
+++ b/lib/libc/isc/ev_streams.c
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* ev_streams.c - implement asynch stream file IO for the eventlib
+ * vix 04mar96 [initial]
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: ev_streams.c,v 1.4.18.1 2005/04/27 05:01:06 sra Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+#ifndef _LIBC
+#include "fd_setsize.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/uio.h>
+
+#include <errno.h>
+
+#include <isc/eventlib.h>
+#ifndef _LIBC
+#include <isc/assertions.h>
+#endif
+#include "eventlib_p.h"
+
+#include "port_after.h"
+
+#ifndef _LIBC
+static int copyvec(evStream *str, const struct iovec *iov, int iocnt);
+static void consume(evStream *str, size_t bytes);
+static void done(evContext opaqueCtx, evStream *str);
+static void writable(evContext opaqueCtx, void *uap, int fd, int evmask);
+static void readable(evContext opaqueCtx, void *uap, int fd, int evmask);
+#endif
+
+struct iovec
+evConsIovec(void *buf, size_t cnt) {
+ struct iovec ret;
+
+ memset(&ret, 0xf5, sizeof ret);
+ ret.iov_base = buf;
+ ret.iov_len = cnt;
+ return (ret);
+}
+
+#ifndef _LIBC
+int
+evWrite(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt,
+ evStreamFunc func, void *uap, evStreamID *id)
+{
+ evContext_p *ctx = opaqueCtx.opaque;
+ evStream *new;
+ int save;
+
+ OKNEW(new);
+ new->func = func;
+ new->uap = uap;
+ new->fd = fd;
+ new->flags = 0;
+ if (evSelectFD(opaqueCtx, fd, EV_WRITE, writable, new, &new->file) < 0)
+ goto free;
+ if (copyvec(new, iov, iocnt) < 0)
+ goto free;
+ new->prevDone = NULL;
+ new->nextDone = NULL;
+ if (ctx->streams != NULL)
+ ctx->streams->prev = new;
+ new->prev = NULL;
+ new->next = ctx->streams;
+ ctx->streams = new;
+ if (id != NULL)
+ id->opaque = new;
+ return (0);
+ free:
+ save = errno;
+ FREE(new);
+ errno = save;
+ return (-1);
+}
+
+int
+evRead(evContext opaqueCtx, int fd, const struct iovec *iov, int iocnt,
+ evStreamFunc func, void *uap, evStreamID *id)
+{
+ evContext_p *ctx = opaqueCtx.opaque;
+ evStream *new;
+ int save;
+
+ OKNEW(new);
+ new->func = func;
+ new->uap = uap;
+ new->fd = fd;
+ new->flags = 0;
+ if (evSelectFD(opaqueCtx, fd, EV_READ, readable, new, &new->file) < 0)
+ goto free;
+ if (copyvec(new, iov, iocnt) < 0)
+ goto free;
+ new->prevDone = NULL;
+ new->nextDone = NULL;
+ if (ctx->streams != NULL)
+ ctx->streams->prev = new;
+ new->prev = NULL;
+ new->next = ctx->streams;
+ ctx->streams = new;
+ if (id)
+ id->opaque = new;
+ return (0);
+ free:
+ save = errno;
+ FREE(new);
+ errno = save;
+ return (-1);
+}
+
+int
+evTimeRW(evContext opaqueCtx, evStreamID id, evTimerID timer) /*ARGSUSED*/ {
+ evStream *str = id.opaque;
+
+ UNUSED(opaqueCtx);
+
+ str->timer = timer;
+ str->flags |= EV_STR_TIMEROK;
+ return (0);
+}
+
+int
+evUntimeRW(evContext opaqueCtx, evStreamID id) /*ARGSUSED*/ {
+ evStream *str = id.opaque;
+
+ UNUSED(opaqueCtx);
+
+ str->flags &= ~EV_STR_TIMEROK;
+ return (0);
+}
+
+int
+evCancelRW(evContext opaqueCtx, evStreamID id) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ evStream *old = id.opaque;
+
+ /*
+ * The streams list is doubly threaded. First, there's ctx->streams
+ * that's used by evDestroy() to find and cancel all streams. Second,
+ * there's ctx->strDone (head) and ctx->strLast (tail) which thread
+ * through the potentially smaller number of "IO completed" streams,
+ * used in evGetNext() to avoid scanning the entire list.
+ */
+
+ /* Unlink from ctx->streams. */
+ if (old->prev != NULL)
+ old->prev->next = old->next;
+ else
+ ctx->streams = old->next;
+ if (old->next != NULL)
+ old->next->prev = old->prev;
+
+ /*
+ * If 'old' is on the ctx->strDone list, remove it. Update
+ * ctx->strLast if necessary.
+ */
+ if (old->prevDone == NULL && old->nextDone == NULL) {
+ /*
+ * Either 'old' is the only item on the done list, or it's
+ * not on the done list. If the former, then we unlink it
+ * from the list. If the latter, we leave the list alone.
+ */
+ if (ctx->strDone == old) {
+ ctx->strDone = NULL;
+ ctx->strLast = NULL;
+ }
+ } else {
+ if (old->prevDone != NULL)
+ old->prevDone->nextDone = old->nextDone;
+ else
+ ctx->strDone = old->nextDone;
+ if (old->nextDone != NULL)
+ old->nextDone->prevDone = old->prevDone;
+ else
+ ctx->strLast = old->prevDone;
+ }
+
+ /* Deallocate the stream. */
+ if (old->file.opaque)
+ evDeselectFD(opaqueCtx, old->file);
+ memput(old->iovOrig, sizeof (struct iovec) * old->iovOrigCount);
+ FREE(old);
+ return (0);
+}
+
+/* Copy a scatter/gather vector and initialize a stream handler's IO. */
+static int
+copyvec(evStream *str, const struct iovec *iov, int iocnt) {
+ int i;
+
+ str->iovOrig = (struct iovec *)memget(sizeof(struct iovec) * iocnt);
+ if (str->iovOrig == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ str->ioTotal = 0;
+ for (i = 0; i < iocnt; i++) {
+ str->iovOrig[i] = iov[i];
+ str->ioTotal += iov[i].iov_len;
+ }
+ str->iovOrigCount = iocnt;
+ str->iovCur = str->iovOrig;
+ str->iovCurCount = str->iovOrigCount;
+ str->ioDone = 0;
+ return (0);
+}
+
+/* Pull off or truncate lead iovec(s). */
+static void
+consume(evStream *str, size_t bytes) {
+ while (bytes > 0U) {
+ if (bytes < (size_t)str->iovCur->iov_len) {
+ str->iovCur->iov_len -= bytes;
+ str->iovCur->iov_base = (void *)
+ ((u_char *)str->iovCur->iov_base + bytes);
+ str->ioDone += bytes;
+ bytes = 0;
+ } else {
+ bytes -= str->iovCur->iov_len;
+ str->ioDone += str->iovCur->iov_len;
+ str->iovCur++;
+ str->iovCurCount--;
+ }
+ }
+}
+
+/* Add a stream to Done list and deselect the FD. */
+static void
+done(evContext opaqueCtx, evStream *str) {
+ evContext_p *ctx = opaqueCtx.opaque;
+
+ if (ctx->strLast != NULL) {
+ str->prevDone = ctx->strLast;
+ ctx->strLast->nextDone = str;
+ ctx->strLast = str;
+ } else {
+ INSIST(ctx->strDone == NULL);
+ ctx->strDone = ctx->strLast = str;
+ }
+ evDeselectFD(opaqueCtx, str->file);
+ str->file.opaque = NULL;
+ /* evDrop() will call evCancelRW() on us. */
+}
+
+/* Dribble out some bytes on the stream. (Called by evDispatch().) */
+static void
+writable(evContext opaqueCtx, void *uap, int fd, int evmask) {
+ evStream *str = uap;
+ int bytes;
+
+ UNUSED(evmask);
+
+ bytes = writev(fd, str->iovCur, str->iovCurCount);
+ if (bytes > 0) {
+ if ((str->flags & EV_STR_TIMEROK) != 0)
+ evTouchIdleTimer(opaqueCtx, str->timer);
+ consume(str, bytes);
+ } else {
+ if (bytes < 0 && errno != EINTR) {
+ str->ioDone = -1;
+ str->ioErrno = errno;
+ }
+ }
+ if (str->ioDone == -1 || str->ioDone == str->ioTotal)
+ done(opaqueCtx, str);
+}
+
+/* Scoop up some bytes from the stream. (Called by evDispatch().) */
+static void
+readable(evContext opaqueCtx, void *uap, int fd, int evmask) {
+ evStream *str = uap;
+ int bytes;
+
+ UNUSED(evmask);
+
+ bytes = readv(fd, str->iovCur, str->iovCurCount);
+ if (bytes > 0) {
+ if ((str->flags & EV_STR_TIMEROK) != 0)
+ evTouchIdleTimer(opaqueCtx, str->timer);
+ consume(str, bytes);
+ } else {
+ if (bytes == 0)
+ str->ioDone = 0;
+ else {
+ if (errno != EINTR) {
+ str->ioDone = -1;
+ str->ioErrno = errno;
+ }
+ }
+ }
+ if (str->ioDone <= 0 || str->ioDone == str->ioTotal)
+ done(opaqueCtx, str);
+}
+#endif
+
+/*! \file */
diff --git a/lib/libc/isc/ev_timers.c b/lib/libc/isc/ev_timers.c
new file mode 100644
index 0000000..66fc186
--- /dev/null
+++ b/lib/libc/isc/ev_timers.c
@@ -0,0 +1,515 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1995-1999 by Internet Software Consortium
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/* ev_timers.c - implement timers for the eventlib
+ * vix 09sep95 [initial]
+ */
+
+#if !defined(LINT) && !defined(CODECENTER)
+static const char rcsid[] = "$Id: ev_timers.c,v 1.5.18.1 2005/04/27 05:01:06 sra Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* Import. */
+
+#include "port_before.h"
+#ifndef _LIBC
+#include "fd_setsize.h"
+#endif
+
+#include <errno.h>
+
+#ifndef _LIBC
+#include <isc/assertions.h>
+#endif
+#include <isc/eventlib.h>
+#include "eventlib_p.h"
+
+#include "port_after.h"
+
+/* Constants. */
+
+#define MILLION 1000000
+#define BILLION 1000000000
+
+/* Forward. */
+
+#ifdef _LIBC
+static int __evOptMonoTime;
+#else
+static int due_sooner(void *, void *);
+static void set_index(void *, int);
+static void free_timer(void *, void *);
+static void print_timer(void *, void *);
+static void idle_timeout(evContext, void *, struct timespec, struct timespec);
+
+/* Private type. */
+
+typedef struct {
+ evTimerFunc func;
+ void * uap;
+ struct timespec lastTouched;
+ struct timespec max_idle;
+ evTimer * timer;
+} idle_timer;
+#endif
+
+/* Public. */
+
+struct timespec
+evConsTime(time_t sec, long nsec) {
+ struct timespec x;
+
+ x.tv_sec = sec;
+ x.tv_nsec = nsec;
+ return (x);
+}
+
+struct timespec
+evAddTime(struct timespec addend1, struct timespec addend2) {
+ struct timespec x;
+
+ x.tv_sec = addend1.tv_sec + addend2.tv_sec;
+ x.tv_nsec = addend1.tv_nsec + addend2.tv_nsec;
+ if (x.tv_nsec >= BILLION) {
+ x.tv_sec++;
+ x.tv_nsec -= BILLION;
+ }
+ return (x);
+}
+
+struct timespec
+evSubTime(struct timespec minuend, struct timespec subtrahend) {
+ struct timespec x;
+
+ x.tv_sec = minuend.tv_sec - subtrahend.tv_sec;
+ if (minuend.tv_nsec >= subtrahend.tv_nsec)
+ x.tv_nsec = minuend.tv_nsec - subtrahend.tv_nsec;
+ else {
+ x.tv_nsec = BILLION - subtrahend.tv_nsec + minuend.tv_nsec;
+ x.tv_sec--;
+ }
+ return (x);
+}
+
+int
+evCmpTime(struct timespec a, struct timespec b) {
+ long x = a.tv_sec - b.tv_sec;
+
+ if (x == 0L)
+ x = a.tv_nsec - b.tv_nsec;
+ return (x < 0L ? (-1) : x > 0L ? (1) : (0));
+}
+
+struct timespec
+evNowTime() {
+ struct timeval now;
+#ifdef CLOCK_REALTIME
+ struct timespec tsnow;
+ int m = CLOCK_REALTIME;
+
+#ifdef CLOCK_MONOTONIC
+ if (__evOptMonoTime)
+ m = CLOCK_MONOTONIC;
+#endif
+ if (clock_gettime(m, &tsnow) == 0)
+ return (tsnow);
+#endif
+ if (gettimeofday(&now, NULL) < 0)
+ return (evConsTime(0, 0));
+ return (evTimeSpec(now));
+}
+
+struct timespec
+evUTCTime() {
+ struct timeval now;
+#ifdef CLOCK_REALTIME
+ struct timespec tsnow;
+ if (clock_gettime(CLOCK_REALTIME, &tsnow) == 0)
+ return (tsnow);
+#endif
+ if (gettimeofday(&now, NULL) < 0)
+ return (evConsTime(0, 0));
+ return (evTimeSpec(now));
+}
+
+#ifndef _LIBC
+struct timespec
+evLastEventTime(evContext opaqueCtx) {
+ evContext_p *ctx = opaqueCtx.opaque;
+
+ return (ctx->lastEventTime);
+}
+#endif
+
+struct timespec
+evTimeSpec(struct timeval tv) {
+ struct timespec ts;
+
+ ts.tv_sec = tv.tv_sec;
+ ts.tv_nsec = tv.tv_usec * 1000;
+ return (ts);
+}
+
+#if !defined(USE_KQUEUE) || !defined(_LIBC)
+struct timeval
+evTimeVal(struct timespec ts) {
+ struct timeval tv;
+
+ tv.tv_sec = ts.tv_sec;
+ tv.tv_usec = ts.tv_nsec / 1000;
+ return (tv);
+}
+#endif
+
+#ifndef _LIBC
+int
+evSetTimer(evContext opaqueCtx,
+ evTimerFunc func,
+ void *uap,
+ struct timespec due,
+ struct timespec inter,
+ evTimerID *opaqueID
+) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ evTimer *id;
+
+ evPrintf(ctx, 1,
+"evSetTimer(ctx %p, func %p, uap %p, due %ld.%09ld, inter %ld.%09ld)\n",
+ ctx, func, uap,
+ (long)due.tv_sec, due.tv_nsec,
+ (long)inter.tv_sec, inter.tv_nsec);
+
+#ifdef __hpux
+ /*
+ * tv_sec and tv_nsec are unsigned.
+ */
+ if (due.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+
+ if (inter.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+#else
+ if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+
+ if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+#endif
+
+ /* due={0,0} is a magic cookie meaning "now." */
+ if (due.tv_sec == (time_t)0 && due.tv_nsec == 0L)
+ due = evNowTime();
+
+ /* Allocate and fill. */
+ OKNEW(id);
+ id->func = func;
+ id->uap = uap;
+ id->due = due;
+ id->inter = inter;
+
+ if (heap_insert(ctx->timers, id) < 0)
+ return (-1);
+
+ /* Remember the ID if the caller provided us a place for it. */
+ if (opaqueID)
+ opaqueID->opaque = id;
+
+ if (ctx->debug > 7) {
+ evPrintf(ctx, 7, "timers after evSetTimer:\n");
+ (void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
+ }
+
+ return (0);
+}
+
+int
+evClearTimer(evContext opaqueCtx, evTimerID id) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ evTimer *del = id.opaque;
+
+ if (ctx->cur != NULL &&
+ ctx->cur->type == Timer &&
+ ctx->cur->u.timer.this == del) {
+ evPrintf(ctx, 8, "deferring delete of timer (executing)\n");
+ /*
+ * Setting the interval to zero ensures that evDrop() will
+ * clean up the timer.
+ */
+ del->inter = evConsTime(0, 0);
+ return (0);
+ }
+
+ if (heap_element(ctx->timers, del->index) != del)
+ EV_ERR(ENOENT);
+
+ if (heap_delete(ctx->timers, del->index) < 0)
+ return (-1);
+ FREE(del);
+
+ if (ctx->debug > 7) {
+ evPrintf(ctx, 7, "timers after evClearTimer:\n");
+ (void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
+ }
+
+ return (0);
+}
+
+int
+evConfigTimer(evContext opaqueCtx,
+ evTimerID id,
+ const char *param,
+ int value
+) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ evTimer *timer = id.opaque;
+ int result=0;
+
+ UNUSED(value);
+
+ if (heap_element(ctx->timers, timer->index) != timer)
+ EV_ERR(ENOENT);
+
+ if (strcmp(param, "rate") == 0)
+ timer->mode |= EV_TMR_RATE;
+ else if (strcmp(param, "interval") == 0)
+ timer->mode &= ~EV_TMR_RATE;
+ else
+ EV_ERR(EINVAL);
+
+ return (result);
+}
+
+int
+evResetTimer(evContext opaqueCtx,
+ evTimerID id,
+ evTimerFunc func,
+ void *uap,
+ struct timespec due,
+ struct timespec inter
+) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ evTimer *timer = id.opaque;
+ struct timespec old_due;
+ int result=0;
+
+ if (heap_element(ctx->timers, timer->index) != timer)
+ EV_ERR(ENOENT);
+
+#ifdef __hpux
+ /*
+ * tv_sec and tv_nsec are unsigned.
+ */
+ if (due.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+
+ if (inter.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+#else
+ if (due.tv_sec < 0 || due.tv_nsec < 0 || due.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+
+ if (inter.tv_sec < 0 || inter.tv_nsec < 0 || inter.tv_nsec >= BILLION)
+ EV_ERR(EINVAL);
+#endif
+
+ old_due = timer->due;
+
+ timer->func = func;
+ timer->uap = uap;
+ timer->due = due;
+ timer->inter = inter;
+
+ switch (evCmpTime(due, old_due)) {
+ case -1:
+ result = heap_increased(ctx->timers, timer->index);
+ break;
+ case 0:
+ result = 0;
+ break;
+ case 1:
+ result = heap_decreased(ctx->timers, timer->index);
+ break;
+ }
+
+ if (ctx->debug > 7) {
+ evPrintf(ctx, 7, "timers after evResetTimer:\n");
+ (void) heap_for_each(ctx->timers, print_timer, (void *)ctx);
+ }
+
+ return (result);
+}
+
+int
+evSetIdleTimer(evContext opaqueCtx,
+ evTimerFunc func,
+ void *uap,
+ struct timespec max_idle,
+ evTimerID *opaqueID
+) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ idle_timer *tt;
+
+ /* Allocate and fill. */
+ OKNEW(tt);
+ tt->func = func;
+ tt->uap = uap;
+ tt->lastTouched = ctx->lastEventTime;
+ tt->max_idle = max_idle;
+
+ if (evSetTimer(opaqueCtx, idle_timeout, tt,
+ evAddTime(ctx->lastEventTime, max_idle),
+ max_idle, opaqueID) < 0) {
+ FREE(tt);
+ return (-1);
+ }
+
+ tt->timer = opaqueID->opaque;
+
+ return (0);
+}
+
+int
+evClearIdleTimer(evContext opaqueCtx, evTimerID id) {
+ evTimer *del = id.opaque;
+ idle_timer *tt = del->uap;
+
+ FREE(tt);
+ return (evClearTimer(opaqueCtx, id));
+}
+
+int
+evResetIdleTimer(evContext opaqueCtx,
+ evTimerID opaqueID,
+ evTimerFunc func,
+ void *uap,
+ struct timespec max_idle
+) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ evTimer *timer = opaqueID.opaque;
+ idle_timer *tt = timer->uap;
+
+ tt->func = func;
+ tt->uap = uap;
+ tt->lastTouched = ctx->lastEventTime;
+ tt->max_idle = max_idle;
+
+ return (evResetTimer(opaqueCtx, opaqueID, idle_timeout, tt,
+ evAddTime(ctx->lastEventTime, max_idle),
+ max_idle));
+}
+
+int
+evTouchIdleTimer(evContext opaqueCtx, evTimerID id) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ evTimer *t = id.opaque;
+ idle_timer *tt = t->uap;
+
+ tt->lastTouched = ctx->lastEventTime;
+
+ return (0);
+}
+
+/* Public to the rest of eventlib. */
+
+heap_context
+evCreateTimers(const evContext_p *ctx) {
+
+ UNUSED(ctx);
+
+ return (heap_new(due_sooner, set_index, 2048));
+}
+
+void
+evDestroyTimers(const evContext_p *ctx) {
+ (void) heap_for_each(ctx->timers, free_timer, NULL);
+ (void) heap_free(ctx->timers);
+}
+
+/* Private. */
+
+static int
+due_sooner(void *a, void *b) {
+ evTimer *a_timer, *b_timer;
+
+ a_timer = a;
+ b_timer = b;
+ return (evCmpTime(a_timer->due, b_timer->due) < 0);
+}
+
+static void
+set_index(void *what, int index) {
+ evTimer *timer;
+
+ timer = what;
+ timer->index = index;
+}
+
+static void
+free_timer(void *what, void *uap) {
+ evTimer *t = what;
+
+ UNUSED(uap);
+
+ FREE(t);
+}
+
+static void
+print_timer(void *what, void *uap) {
+ evTimer *cur = what;
+ evContext_p *ctx = uap;
+
+ cur = what;
+ evPrintf(ctx, 7,
+ " func %p, uap %p, due %ld.%09ld, inter %ld.%09ld\n",
+ cur->func, cur->uap,
+ (long)cur->due.tv_sec, cur->due.tv_nsec,
+ (long)cur->inter.tv_sec, cur->inter.tv_nsec);
+}
+
+static void
+idle_timeout(evContext opaqueCtx,
+ void *uap,
+ struct timespec due,
+ struct timespec inter
+) {
+ evContext_p *ctx = opaqueCtx.opaque;
+ idle_timer *this = uap;
+ struct timespec idle;
+
+ UNUSED(due);
+ UNUSED(inter);
+
+ idle = evSubTime(ctx->lastEventTime, this->lastTouched);
+ if (evCmpTime(idle, this->max_idle) >= 0) {
+ (this->func)(opaqueCtx, this->uap, this->timer->due,
+ this->max_idle);
+ /*
+ * Setting the interval to zero will cause the timer to
+ * be cleaned up in evDrop().
+ */
+ this->timer->inter = evConsTime(0, 0);
+ FREE(this);
+ } else {
+ /* evDrop() will reschedule the timer. */
+ this->timer->inter = evSubTime(this->max_idle, idle);
+ }
+}
+#endif
+
+/*! \file */
diff --git a/lib/libc/isc/eventlib_p.h b/lib/libc/isc/eventlib_p.h
new file mode 100644
index 0000000..951af00
--- /dev/null
+++ b/lib/libc/isc/eventlib_p.h
@@ -0,0 +1,290 @@
+/*
+ * Copyright (c) 2005 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1995-1999 by Internet Software Consortium
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*! \file
+ * \brief private interfaces for eventlib
+ * \author vix 09sep95 [initial]
+ *
+ * $Id: eventlib_p.h,v 1.5.18.4 2006/03/10 00:20:08 marka Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _EVENTLIB_P_H
+#define _EVENTLIB_P_H
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <sys/un.h>
+
+#define EVENTLIB_DEBUG 1
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _LIBC
+#include <isc/list.h>
+#include <isc/heap.h>
+#include <isc/memcluster.h>
+#endif
+
+#define EV_MASK_ALL (EV_READ | EV_WRITE | EV_EXCEPT)
+#define EV_ERR(e) return (errno = (e), -1)
+#define OK(x) if ((x) < 0) EV_ERR(errno); else (void)NULL
+#define OKFREE(x, y) if ((x) < 0) { FREE((y)); EV_ERR(errno); } \
+ else (void)NULL
+
+#define NEW(p) if (((p) = memget(sizeof *(p))) != NULL) \
+ FILL(p); \
+ else \
+ (void)NULL;
+#define OKNEW(p) if (!((p) = memget(sizeof *(p)))) { \
+ errno = ENOMEM; \
+ return (-1); \
+ } else \
+ FILL(p)
+#define FREE(p) memput((p), sizeof *(p))
+
+#if EVENTLIB_DEBUG
+#define FILL(p) memset((p), 0xF5, sizeof *(p))
+#else
+#define FILL(p)
+#endif
+
+#ifdef USE_POLL
+#ifdef HAVE_STROPTS_H
+#include <stropts.h>
+#endif
+#include <poll.h>
+#endif /* USE_POLL */
+
+typedef struct evConn {
+ evConnFunc func;
+ void * uap;
+ int fd;
+ int flags;
+#define EV_CONN_LISTEN 0x0001 /*%< Connection is a listener. */
+#define EV_CONN_SELECTED 0x0002 /*%< evSelectFD(conn->file). */
+#define EV_CONN_BLOCK 0x0004 /*%< Listener fd was blocking. */
+ evFileID file;
+ struct evConn * prev;
+ struct evConn * next;
+} evConn;
+
+#ifndef _LIBC
+typedef struct evAccept {
+ int fd;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+#ifndef NO_SOCKADDR_UN
+ struct sockaddr_un un;
+#endif
+ } la;
+ ISC_SOCKLEN_T lalen;
+ union {
+ struct sockaddr sa;
+ struct sockaddr_in in;
+#ifndef NO_SOCKADDR_UN
+ struct sockaddr_un un;
+#endif
+ } ra;
+ ISC_SOCKLEN_T ralen;
+ int ioErrno;
+ evConn * conn;
+ LINK(struct evAccept) link;
+} evAccept;
+
+typedef struct evFile {
+ evFileFunc func;
+ void * uap;
+ int fd;
+ int eventmask;
+ int preemptive;
+ struct evFile * prev;
+ struct evFile * next;
+ struct evFile * fdprev;
+ struct evFile * fdnext;
+} evFile;
+
+typedef struct evStream {
+ evStreamFunc func;
+ void * uap;
+ evFileID file;
+ evTimerID timer;
+ int flags;
+#define EV_STR_TIMEROK 0x0001 /*%< IFF timer valid. */
+ int fd;
+ struct iovec * iovOrig;
+ int iovOrigCount;
+ struct iovec * iovCur;
+ int iovCurCount;
+ int ioTotal;
+ int ioDone;
+ int ioErrno;
+ struct evStream *prevDone, *nextDone;
+ struct evStream *prev, *next;
+} evStream;
+
+typedef struct evTimer {
+ evTimerFunc func;
+ void * uap;
+ struct timespec due, inter;
+ int index;
+ int mode;
+#define EV_TMR_RATE 1
+} evTimer;
+
+typedef struct evWait {
+ evWaitFunc func;
+ void * uap;
+ const void * tag;
+ struct evWait * next;
+} evWait;
+
+typedef struct evWaitList {
+ evWait * first;
+ evWait * last;
+ struct evWaitList * prev;
+ struct evWaitList * next;
+} evWaitList;
+
+typedef struct evEvent_p {
+ enum { Accept, File, Stream, Timer, Wait, Free, Null } type;
+ union {
+ struct { evAccept *this; } accept;
+ struct { evFile *this; int eventmask; } file;
+ struct { evStream *this; } stream;
+ struct { evTimer *this; } timer;
+ struct { evWait *this; } wait;
+ struct { struct evEvent_p *next; } free;
+ struct { const void *placeholder; } null;
+ } u;
+} evEvent_p;
+#endif
+
+#ifdef USE_POLL
+typedef struct {
+ void *ctx; /* pointer to the evContext_p */
+ uint32_t type; /* READ, WRITE, EXCEPT, nonblk */
+ uint32_t result; /* 1 => revents, 0 => events */
+} __evEmulMask;
+
+#define emulMaskInit(ctx, field, ev, lastnext) \
+ ctx->field.ctx = ctx; \
+ ctx->field.type = ev; \
+ ctx->field.result = lastnext;
+
+extern short *__fd_eventfield(int fd, __evEmulMask *maskp);
+extern short __poll_event(__evEmulMask *maskp);
+extern void __fd_clr(int fd, __evEmulMask *maskp);
+extern void __fd_set(int fd, __evEmulMask *maskp);
+
+#undef FD_ZERO
+#define FD_ZERO(maskp)
+
+#undef FD_SET
+#define FD_SET(fd, maskp) \
+ __fd_set(fd, maskp)
+
+#undef FD_CLR
+#define FD_CLR(fd, maskp) \
+ __fd_clr(fd, maskp)
+
+#undef FD_ISSET
+#define FD_ISSET(fd, maskp) \
+ ((*__fd_eventfield(fd, maskp) & __poll_event(maskp)) != 0)
+
+#endif /* USE_POLL */
+
+#ifndef _LIBC
+typedef struct {
+ /* Global. */
+ const evEvent_p *cur;
+ /* Debugging. */
+ int debug;
+ FILE *output;
+ /* Connections. */
+ evConn *conns;
+ LIST(evAccept) accepts;
+ /* Files. */
+ evFile *files, *fdNext;
+#ifndef USE_POLL
+ fd_set rdLast, rdNext;
+ fd_set wrLast, wrNext;
+ fd_set exLast, exNext;
+ fd_set nonblockBefore;
+ int fdMax, fdCount, highestFD;
+ evFile *fdTable[FD_SETSIZE];
+#else
+ struct pollfd *pollfds; /* Allocated as needed */
+ evFile **fdTable; /* Ditto */
+ int maxnfds; /* # elements in above */
+ int firstfd; /* First active fd */
+ int fdMax; /* Last active fd */
+ int fdCount; /* # fd:s with I/O */
+ int highestFD; /* max fd allowed by OS */
+ __evEmulMask rdLast, rdNext;
+ __evEmulMask wrLast, wrNext;
+ __evEmulMask exLast, exNext;
+ __evEmulMask nonblockBefore;
+#endif /* USE_POLL */
+#ifdef EVENTLIB_TIME_CHECKS
+ struct timespec lastSelectTime;
+ int lastFdCount;
+#endif
+ /* Streams. */
+ evStream *streams;
+ evStream *strDone, *strLast;
+ /* Timers. */
+ struct timespec lastEventTime;
+ heap_context timers;
+ /* Waits. */
+ evWaitList *waitLists;
+ evWaitList waitDone;
+} evContext_p;
+
+/* eventlib.c */
+#define evPrintf __evPrintf
+void evPrintf(const evContext_p *ctx, int level, const char *fmt, ...)
+ ISC_FORMAT_PRINTF(3, 4);
+
+#ifdef USE_POLL
+extern int evPollfdRealloc(evContext_p *ctx, int pollfd_chunk_size, int fd);
+#endif /* USE_POLL */
+
+/* ev_timers.c */
+#define evCreateTimers __evCreateTimers
+heap_context evCreateTimers(const evContext_p *);
+#define evDestroyTimers __evDestroyTimers
+void evDestroyTimers(const evContext_p *);
+
+/* ev_waits.c */
+#define evFreeWait __evFreeWait
+evWait *evFreeWait(evContext_p *ctx, evWait *old);
+#endif
+
+/* Global options */
+#ifndef _LIBC
+extern int __evOptMonoTime;
+#endif
+
+#endif /*_EVENTLIB_P_H*/
diff --git a/lib/libc/locale/DESIGN.xlocale b/lib/libc/locale/DESIGN.xlocale
new file mode 100644
index 0000000..5d998d3
--- /dev/null
+++ b/lib/libc/locale/DESIGN.xlocale
@@ -0,0 +1,159 @@
+$FreeBSD$
+
+Design of xlocale
+=================
+
+The xlocale APIs come from Darwin, although a subset is now part of POSIX 2008.
+They fall into two broad categories:
+
+- Manipulation of per-thread locales (POSIX)
+- Locale-aware functions taking an explicit locale argument (Darwin)
+
+This document describes the implementation of these APIs for FreeBSD.
+
+Goals
+-----
+
+The overall goal of this implementation is to be compatible with the Darwin
+version. Additionally, it should include minimal changes to the existing
+locale code. A lot of the existing locale code originates with 4BSD or earlier
+and has had over a decade of testing. Replacing this code, unless absolutely
+necessary, gives us the potential for more bugs without much benefit.
+
+With this in mind, various libc-private functions have been modified to take a
+locale_t parameter. This causes a compiler error if they are accidentally
+called without a locale. This approach was taken, rather than adding _l
+variants of these functions, to make it harder for accidental uses of the
+global-locale versions to slip in.
+
+Locale Objects
+--------------
+
+A locale is encapsulated in a `locale_t`, which is an opaque type: a pointer to
+a `struct _xlocale`. The name `_xlocale` is unfortunate, as it does not fit
+well with existing conventions, but is used because this is the name the Darwin
+implementation gives to this structure and so may be used by existing (bad) code.
+
+This structure should include all of the information corresponding to a locale.
+A locale_t is almost immutable after creation. There are no functions that modify it,
+and it can therefore be used without locking. It is the responsibility of the
+caller to ensure that a locale is not deallocated during a call that uses it.
+
+Each locale contains a number of components, one for each of the categories
+supported by `setlocale()`. These are likewise immutable after creation. This
+differs from the Darwin implementation, which includes a deprecated
+`setinvalidrune()` function that can modify the rune locale.
+
+The exception to these mutability rules is a set of `mbstate_t` flags stored
+with each locale. These are used by various functions that previously had a
+static local `mbstate_t` variable.
+
+The components are reference counted, and so can be aliased between locale
+objects. This makes copying locales very cheap.
+
+The Global Locale
+-----------------
+
+All locales and locale components are reference counted. The global locale,
+however, is special. It, and all of its components, are static and so no
+malloc() memory is required when using a single locale.
+
+This means that threads using the global locale are subject to the same
+constraints as with the pre-xlocale libc. Calls to any locale-aware functions
+in threads using the global locale, while modifying the global locale, have
+undefined behaviour.
+
+Because of this, we have to ensure that we always copy the components of the
+global locale, rather than alias them.
+
+It would be cleaner to simply remove the special treatment of the global locale
+and have a locale_t lazily allocated for the global context. This would cost a
+little more `malloc()` memory, so is not done in the initial version.
+
+Caching
+-------
+
+The existing locale implementation included several ad-hoc caching layers.
+None of these were thread safe. Caching is only really of use for supporting
+the pattern where the locale is briefly changed to something and then changed
+back.
+
+The current xlocale implementation removes the caching entirely. This pattern
+is not one that should be encouraged. If you need to make some calls with a
+modified locale, then you should use the _l suffix versions of the calls,
+rather than switch the global locale. If you do need to temporarily switch the
+locale and then switch it back, `uselocale()` provides a way of doing this very
+easily: It returns the old locale, which can then be passed to a subsequent
+call to `uselocale()` to restore it, without the need to load any locale data
+from the disk.
+
+If, in the future, it is determined that caching is beneficial, it can be added
+quite easily in xlocale.c. Given, however, that any locale-aware call is going
+to be a preparation for presenting data to the user, and so is invariably going
+to be part of an I/O operation, this seems like a case of premature
+optimisation.
+
+localeconv
+----------
+
+The `localeconv()` function is an exception to the immutable-after-creation
+rule. In the classic implementation, this function returns a pointer to some
+global storage, which is initialised with the data from the current locale.
+This is not possible in a multithreaded environment, with multiple locales.
+
+Instead, each locale contains a `struct lconv` that is lazily initialised on
+calls to `localeconv()`. This is not protected by any locking, however this is
+still safe on any machine where word-sized stores are atomic: two concurrent
+calls will write the same data into the structure.
+
+Explicit Locale Calls
+---------------------
+
+A large number of functions have been modified to take an explicit `locale_t`
+parameter. The old APIs are then reimplemented with a call to `__get_locale()`
+to supply the `locale_t` parameter. This is in line with the Darwin public
+APIs, but also simplifies the modifications to these functions. The
+`__get_locale()` function is now the only way to access the current locale
+within libc. All of the old globals have gone, so there is now a linker error
+if any functions attempt to use them.
+
+The ctype.h functions are a little different. These are not implemented in
+terms of their locale-aware versions, for performance reasons. Each of these
+is implemented as a short inline function.
+
+Differences to Darwin APIs
+--------------------------
+
+`strtoq_l()` and `strtouq_l() `are not provided. These are extensions to
+deprecated functions - we should not be encouraging people to use deprecated
+interfaces.
+
+Locale Placeholders
+-------------------
+
+The pointer values 0 and -1 have special meanings as `locale_t` values. Any
+public function that accepts a `locale_t` parameter must use the `FIX_LOCALE()`
+macro on it before using it. For efficiency, this can be emitted in functions
+which *only* use their locale parameter as an argument to another public
+function, as the callee will do the `FIX_LOCALE()` itself.
+
+Potential Improvements
+----------------------
+
+Currently, the current rune set is accessed via a function call. This makes it
+fairly expensive to use any of the ctype.h functions. We could improve this
+quite a lot by storing the rune locale data in a __thread-qualified variable.
+
+Several of the existing FreeBSD locale-aware functions appear to be wrong. For
+example, most of the `strto*()` family should probably use `digittoint_l()`,
+but instead they assume ASCII. These will break if using a character encoding
+that does not put numbers and the letters A-F in the same location as ASCII.
+Some functions, like `strcoll()` only work on single-byte encodings. No
+attempt has been made to fix existing limitations in the libc functions other
+than to add support for xlocale.
+
+Intuitively, setting a thread-local locale should ensure that all locale-aware
+functions can be used safely from that thread. In fact, this is not the case
+in either this implementation or the Darwin one. You must call `duplocale()`
+or `newlocale()` before calling `uselocale()`. This is a bit ugly, and it
+would be better if libc ensure that every thread had its own locale object.
diff --git a/lib/libc/locale/Makefile.inc b/lib/libc/locale/Makefile.inc
new file mode 100644
index 0000000..adae8bd
--- /dev/null
+++ b/lib/libc/locale/Makefile.inc
@@ -0,0 +1,63 @@
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+# locale sources
+.PATH: ${.CURDIR}/${LIBC_ARCH}/locale ${.CURDIR}/locale
+
+SRCS+= ascii.c big5.c btowc.c collate.c collcmp.c euc.c fix_grouping.c \
+ gb18030.c gb2312.c gbk.c ctype.c isctype.c iswctype.c \
+ ldpart.c lmessages.c lmonetary.c lnumeric.c localeconv.c mblen.c \
+ mbrlen.c \
+ mbrtowc.c mbsinit.c mbsnrtowcs.c \
+ mbsrtowcs.c mbtowc.c mbstowcs.c \
+ mskanji.c nextwctype.c nl_langinfo.c nomacros.c none.c rpmatch.c \
+ rune.c \
+ runetype.c setlocale.c setrunelocale.c \
+ table.c \
+ tolower.c toupper.c utf8.c wcrtomb.c wcsnrtombs.c \
+ wcsrtombs.c wcsftime.c \
+ wcstof.c wcstod.c \
+ wcstoimax.c wcstol.c wcstold.c wcstoll.c \
+ wcstombs.c \
+ wcstoul.c wcstoull.c wcstoumax.c wctob.c wctomb.c wctrans.c wctype.c \
+ wcwidth.c\
+ xlocale.c
+
+SYM_MAPS+=${.CURDIR}/locale/Symbol.map
+
+MAN+= btowc.3 \
+ ctype_l.3 \
+ ctype.3 digittoint.3 isalnum.3 isalpha.3 isascii.3 isblank.3 iscntrl.3 \
+ isdigit.3 isgraph.3 isideogram.3 islower.3 isphonogram.3 isprint.3 \
+ ispunct.3 isrune.3 isspace.3 isspecial.3 \
+ isupper.3 iswalnum.3 isxdigit.3 localeconv.3 mblen.3 mbrlen.3 \
+ mbrtowc.3 \
+ mbsinit.3 \
+ mbsrtowcs.3 mbstowcs.3 mbtowc.3 multibyte.3 \
+ nextwctype.3 nl_langinfo.3 rpmatch.3 \
+ setlocale.3 toascii.3 tolower.3 toupper.3 towlower.3 towupper.3 \
+ wcsftime.3 \
+ wcrtomb.3 \
+ wcsrtombs.3 wcstod.3 wcstol.3 wcstombs.3 wctomb.3 \
+ wctrans.3 wctype.3 wcwidth.3 \
+ duplocale.3 freelocale.3 newlocale.3 querylocale.3 uselocale.3 xlocale.3
+
+MAN+= big5.5 euc.5 gb18030.5 gb2312.5 gbk.5 mskanji.5 utf8.5
+
+MLINKS+=btowc.3 wctob.3
+MLINKS+=isdigit.3 isnumber.3
+MLINKS+=iswalnum.3 iswalpha.3 iswalnum.3 iswascii.3 iswalnum.3 iswblank.3 \
+ iswalnum.3 iswcntrl.3 iswalnum.3 iswdigit.3 iswalnum.3 iswgraph.3 \
+ iswalnum.3 iswhexnumber.3 \
+ iswalnum.3 iswideogram.3 iswalnum.3 iswlower.3 iswalnum.3 iswnumber.3 \
+ iswalnum.3 iswphonogram.3 iswalnum.3 iswprint.3 iswalnum.3 iswpunct.3 \
+ iswalnum.3 iswrune.3 iswalnum.3 iswspace.3 iswalnum.3 iswspecial.3 \
+ iswalnum.3 iswupper.3 iswalnum.3 iswxdigit.3
+MLINKS+=isxdigit.3 ishexnumber.3
+MLINKS+=mbsrtowcs.3 mbsnrtowcs.3
+MLINKS+=wcsrtombs.3 wcsnrtombs.3
+MLINKS+=wcstod.3 wcstof.3 wcstod.3 wcstold.3
+MLINKS+=wcstol.3 wcstoul.3 wcstol.3 wcstoll.3 wcstol.3 wcstoull.3 \
+ wcstol.3 wcstoimax.3 wcstol.3 wcstoumax.3
+MLINKS+=wctrans.3 towctrans.3
+MLINKS+=wctype.3 iswctype.3
diff --git a/lib/libc/locale/Symbol.map b/lib/libc/locale/Symbol.map
new file mode 100644
index 0000000..f6367da
--- /dev/null
+++ b/lib/libc/locale/Symbol.map
@@ -0,0 +1,209 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ btowc;
+ digittoint;
+ isalnum;
+ isalpha;
+ isascii;
+ isblank;
+ iscntrl;
+ isdigit;
+ isgraph;
+ ishexnumber;
+ isideogram;
+ islower;
+ isnumber;
+ isphonogram;
+ isprint;
+ ispunct;
+ isrune;
+ isspace;
+ isspecial;
+ isupper;
+ isxdigit;
+ toascii;
+ tolower;
+ toupper;
+ iswalnum;
+ iswalpha;
+ iswascii;
+ iswblank;
+ iswcntrl;
+ iswdigit;
+ iswgraph;
+ iswhexnumber;
+ iswideogram;
+ iswlower;
+ iswnumber;
+ iswphonogram;
+ iswprint;
+ iswpunct;
+ iswrune;
+ iswspace;
+ iswspecial;
+ iswupper;
+ iswxdigit;
+ towlower;
+ towupper;
+ localeconv;
+ mblen;
+ mbrlen;
+ mbrtowc;
+ mbsinit;
+ mbsnrtowcs;
+ mbsrtowcs;
+ mbstowcs;
+ mbtowc;
+ nextwctype;
+ nl_langinfo;
+ __maskrune;
+ __sbmaskrune;
+ __istype;
+ __sbistype;
+ __isctype;
+ __toupper;
+ __sbtoupper;
+ __tolower;
+ __sbtolower;
+ __wcwidth;
+ __mb_cur_max;
+ __mb_sb_limit;
+ rpmatch;
+ ___runetype;
+ setlocale;
+ _DefaultRuneLocale;
+ _CurrentRuneLocale;
+ ___tolower;
+ ___toupper;
+ wcrtomb;
+ wcsftime;
+ wcsnrtombs;
+ wcsrtombs;
+ wcstod;
+ wcstof;
+ wcstoimax;
+ wcstol;
+ wcstold;
+ wcstoll;
+ wcstombs;
+ wcstoul;
+ wcstoull;
+ wcstoumax;
+ wctob;
+ wctomb;
+ towctrans;
+ wctrans;
+ iswctype;
+ wctype;
+ wcwidth;
+};
+
+FBSD_1.3 {
+ newlocale;
+ duplocale;
+ freelocale;
+ querylocale;
+ uselocale;
+ __getCurrentRuneLocale;
+ btowc_l;
+ localeconv_l;
+ mblen_l;
+ mbrlen_l;
+ mbrtowc_l;
+ mbsinit_l;
+ mbsnrtowcs_l;
+ mbsrtowcs_l;
+ mbstowcs_l;
+ mbtowc_l;
+ nl_langinfo_l;
+ strcoll_l;
+ strfmon_l;
+ strftime_l;
+ strptime_l;
+ strxfrm_l;
+ wcrtomb_l;
+ wcscoll_l;
+ wcsnrtombs_l;
+ wcsrtombs_l;
+ wcstombs_l;
+ wcsxfrm_l;
+ wctob_l;
+ wctomb_l;
+ ___tolower_l;
+ ___toupper_l;
+ ___runetype_l;
+ digittoint_l;
+ isalnum_l;
+ isalpha_l;
+ isblank_l;
+ iscntrl_l;
+ isdigit_l;
+ isgraph_l;
+ ishexnumber_l;
+ isideogram_l;
+ islower_l;
+ isnumber_l;
+ isphonogram_l;
+ isprint_l;
+ ispunct_l;
+ isrune_l;
+ isspace_l;
+ isspecial_l;
+ isupper_l;
+ isxdigit_l;
+ tolower_l;
+ toupper_l;
+ iswalnum_l;
+ iswalpha_l;
+ iswblank_l;
+ iswcntrl_l;
+ iswdigit_l;
+ iswgraph_l;
+ iswhexnumber_l;
+ iswideogram_l;
+ iswlower_l;
+ iswnumber_l;
+ iswphonogram_l;
+ iswprint_l;
+ iswpunct_l;
+ iswrune_l;
+ iswspace_l;
+ iswspecial_l;
+ iswupper_l;
+ iswxdigit_l;
+ towlower_l;
+ towupper_l;
+ iswctype_l;
+ wctype_l;
+ nextwctype_l;
+ ___mb_cur_max;
+ ___mb_cur_max_l;
+ towctrans_l;
+ wctrans_l;
+ wcsftime_l;
+ wcstod_l;
+ wcstof_l;
+ wcstoimax_l;
+ wcstol_l;
+ wcstold_l;
+ wcstoll_l;
+ wcstoul_l;
+ wcstoull_l;
+ wcstoumax_l;
+ __sbistype_l;
+ __maskrune_l;
+ __sbmaskrune_l;
+ __istype_l;
+ __runes_for_locale;
+ _ThreadRuneLocale;
+};
+
+FBSDprivate_1.0 {
+ _PathLocale;
+ __detect_path_locale;
+ __collate_load_error;
+ __collate_range_cmp;
+};
diff --git a/lib/libc/locale/ascii.c b/lib/libc/locale/ascii.c
new file mode 100644
index 0000000..784814d
--- /dev/null
+++ b/lib/libc/locale/ascii.c
@@ -0,0 +1,192 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <runetype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+static size_t _ascii_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _ascii_mbsinit(const mbstate_t *);
+static size_t _ascii_mbsnrtowcs(wchar_t * __restrict dst,
+ const char ** __restrict src, size_t nms, size_t len,
+ mbstate_t * __restrict ps __unused);
+static size_t _ascii_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+static size_t _ascii_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
+ size_t, size_t, mbstate_t * __restrict);
+
+int
+_ascii_init(struct xlocale_ctype *l,_RuneLocale *rl)
+{
+
+ l->__mbrtowc = _ascii_mbrtowc;
+ l->__mbsinit = _ascii_mbsinit;
+ l->__mbsnrtowcs = _ascii_mbsnrtowcs;
+ l->__wcrtomb = _ascii_wcrtomb;
+ l->__wcsnrtombs = _ascii_wcsnrtombs;
+ l->runes = rl;
+ l->__mb_cur_max = 1;
+ l->__mb_sb_limit = 128;
+ return(0);
+}
+
+static int
+_ascii_mbsinit(const mbstate_t *ps __unused)
+{
+
+ /*
+ * Encoding is not state dependent - we are always in the
+ * initial state.
+ */
+ return (1);
+}
+
+static size_t
+_ascii_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
+ mbstate_t * __restrict ps __unused)
+{
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (0);
+ if (n == 0)
+ /* Incomplete multibyte sequence */
+ return ((size_t)-2);
+ if (*s & 0x80) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ if (pwc != NULL)
+ *pwc = (unsigned char)*s;
+ return (*s == '\0' ? 0 : 1);
+}
+
+static size_t
+_ascii_wcrtomb(char * __restrict s, wchar_t wc,
+ mbstate_t * __restrict ps __unused)
+{
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (1);
+ if (wc < 0 || wc > 127) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ *s = (unsigned char)wc;
+ return (1);
+}
+
+static size_t
+_ascii_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps __unused)
+{
+ const char *s;
+ size_t nchr;
+
+ if (dst == NULL) {
+ for (s = *src; nms > 0 && *s != '\0'; s++, nms--) {
+ if (*s & 0x80) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ }
+ return (s - *src);
+ }
+
+ s = *src;
+ nchr = 0;
+ while (len-- > 0 && nms-- > 0) {
+ if (*s & 0x80) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ if ((*dst++ = (unsigned char)*s++) == L'\0') {
+ *src = NULL;
+ return (nchr);
+ }
+ nchr++;
+ }
+ *src = s;
+ return (nchr);
+}
+
+static size_t
+_ascii_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
+ size_t nwc, size_t len, mbstate_t * __restrict ps __unused)
+{
+ const wchar_t *s;
+ size_t nchr;
+
+ if (dst == NULL) {
+ for (s = *src; nwc > 0 && *s != L'\0'; s++, nwc--) {
+ if (*s < 0 || *s > 127) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ }
+ return (s - *src);
+ }
+
+ s = *src;
+ nchr = 0;
+ while (len-- > 0 && nwc-- > 0) {
+ if (*s < 0 || *s > 127) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ if ((*dst++ = *s++) == '\0') {
+ *src = NULL;
+ return (nchr);
+ }
+ nchr++;
+ }
+ *src = s;
+ return (nchr);
+}
+
diff --git a/lib/libc/locale/big5.5 b/lib/libc/locale/big5.5
new file mode 100644
index 0000000..13d0c7b
--- /dev/null
+++ b/lib/libc/locale/big5.5
@@ -0,0 +1,51 @@
+.\" Copyright (c) 2002, 2003 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 7, 2003
+.Dt BIG5 5
+.Os
+.Sh NAME
+.Nm big5
+.Nd
+.Dq "Big Five"
+encoding for Traditional Chinese text
+.Sh SYNOPSIS
+.Nm ENCODING
+.Qq BIG5
+.Sh DESCRIPTION
+.Dq Big Five
+is the de facto standard for encoding Traditional Chinese text.
+Each character is represented by either one or two bytes.
+Characters from the
+.Tn ASCII
+character set are represented as single bytes in the range 0x00 - 0x7F.
+Traditional Chinese characters are represented by two bytes:
+the first in the range 0xA1 - 0xFE, the second in the range
+0x40 - 0xFE.
+.Sh SEE ALSO
+.Xr euc 5 ,
+.Xr gb18030 5 ,
+.Xr utf8 5
diff --git a/lib/libc/locale/big5.c b/lib/libc/locale/big5.c
new file mode 100644
index 0000000..4b37265
--- /dev/null
+++ b/lib/libc/locale/big5.c
@@ -0,0 +1,180 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)big5.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <errno.h>
+#include <runetype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+extern int __mb_sb_limit;
+
+static size_t _BIG5_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _BIG5_mbsinit(const mbstate_t *);
+static size_t _BIG5_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+
+typedef struct {
+ wchar_t ch;
+} _BIG5State;
+
+int
+_BIG5_init(struct xlocale_ctype *l, _RuneLocale *rl)
+{
+
+ l->__mbrtowc = _BIG5_mbrtowc;
+ l->__wcrtomb = _BIG5_wcrtomb;
+ l->__mbsinit = _BIG5_mbsinit;
+ l->runes = rl;
+ l->__mb_cur_max = 2;
+ l->__mb_sb_limit = 128;
+ return (0);
+}
+
+static int
+_BIG5_mbsinit(const mbstate_t *ps)
+{
+
+ return (ps == NULL || ((const _BIG5State *)ps)->ch == 0);
+}
+
+static __inline int
+_big5_check(u_int c)
+{
+
+ c &= 0xff;
+ return ((c >= 0xa1 && c <= 0xfe) ? 2 : 1);
+}
+
+static size_t
+_BIG5_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
+ mbstate_t * __restrict ps)
+{
+ _BIG5State *bs;
+ wchar_t wc;
+ size_t len;
+
+ bs = (_BIG5State *)ps;
+
+ if ((bs->ch & ~0xFF) != 0) {
+ /* Bad conversion state. */
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL) {
+ s = "";
+ n = 1;
+ pwc = NULL;
+ }
+
+ if (n == 0)
+ /* Incomplete multibyte sequence */
+ return ((size_t)-2);
+
+ if (bs->ch != 0) {
+ if (*s == '\0') {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ wc = (bs->ch << 8) | (*s & 0xFF);
+ if (pwc != NULL)
+ *pwc = wc;
+ bs->ch = 0;
+ return (1);
+ }
+
+ len = (size_t)_big5_check(*s);
+ wc = *s++ & 0xff;
+ if (len == 2) {
+ if (n < 2) {
+ /* Incomplete multibyte sequence */
+ bs->ch = wc;
+ return ((size_t)-2);
+ }
+ if (*s == '\0') {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ wc = (wc << 8) | (*s++ & 0xff);
+ if (pwc != NULL)
+ *pwc = wc;
+ return (2);
+ } else {
+ if (pwc != NULL)
+ *pwc = wc;
+ return (wc == L'\0' ? 0 : 1);
+ }
+}
+
+static size_t
+_BIG5_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
+{
+ _BIG5State *bs;
+
+ bs = (_BIG5State *)ps;
+
+ if (bs->ch != 0) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (1);
+ if (wc & 0x8000) {
+ *s++ = (wc >> 8) & 0xff;
+ *s = wc & 0xff;
+ return (2);
+ }
+ *s = wc & 0xff;
+ return (1);
+}
diff --git a/lib/libc/locale/btowc.3 b/lib/libc/locale/btowc.3
new file mode 100644
index 0000000..d9c3e9c
--- /dev/null
+++ b/lib/libc/locale/btowc.3
@@ -0,0 +1,88 @@
+.\" Copyright (c) 2002 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 13, 2012
+.Dt BTOWC 3
+.Os
+.Sh NAME
+.Nm btowc ,
+.Nm wctob
+.Nd "convert between wide and single-byte characters"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft wint_t
+.Fn btowc "int c"
+.Ft int
+.Fn wctob "wint_t c"
+.In wchar.h
+.In xlocale.h
+.Ft wint_t
+.Fn btowc "int c"
+.Ft int
+.Fn wctob "wint_t c"
+.Sh DESCRIPTION
+The
+.Fn btowc
+function converts a single-byte character into a corresponding wide character.
+If the character is
+.Dv EOF
+or not valid in the initial shift state,
+.Fn btowc
+returns
+.Dv WEOF .
+.Pp
+The
+.Fn wctob
+function converts a wide character into a corresponding single-byte character.
+If the wide character is
+.Dv WEOF
+or not able to be represented as a single byte in the initial shift state,
+.Fn wctob
+returns
+.Dv EOF .
+.Pp
+The _l-suffixed versions take an explicit locale argument, while the
+non-suffixed versions use the current global or per-thread locale.
+.Sh SEE ALSO
+.Xr mbrtowc 3 ,
+.Xr multibyte 3 ,
+.Xr wcrtomb 3
+.Sh STANDARDS
+The
+.Fn btowc
+and
+.Fn wctob
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn btowc
+and
+.Fn wctob
+functions first appeared in
+.Fx 5.0 .
diff --git a/lib/libc/locale/btowc.c b/lib/libc/locale/btowc.c
new file mode 100644
index 0000000..72507bc
--- /dev/null
+++ b/lib/libc/locale/btowc.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 2002, 2003 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+wint_t
+btowc_l(int c, locale_t l)
+{
+ static const mbstate_t initial;
+ mbstate_t mbs = initial;
+ char cc;
+ wchar_t wc;
+ FIX_LOCALE(l);
+
+ if (c == EOF)
+ return (WEOF);
+ /*
+ * We expect mbrtowc() to return 0 or 1, hence the check for n > 1
+ * which detects error return values as well as "impossible" byte
+ * counts.
+ */
+ cc = (char)c;
+ if (XLOCALE_CTYPE(l)->__mbrtowc(&wc, &cc, 1, &mbs) > 1)
+ return (WEOF);
+ return (wc);
+}
+wint_t
+btowc(int c)
+{
+ return btowc_l(c, __get_locale());
+}
diff --git a/lib/libc/locale/collate.c b/lib/libc/locale/collate.c
new file mode 100644
index 0000000..448e605
--- /dev/null
+++ b/lib/libc/locale/collate.c
@@ -0,0 +1,343 @@
+/*-
+ * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
+ * at Electronni Visti IA, Kiev, Ukraine.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <arpa/inet.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sysexits.h>
+#include "un-namespace.h"
+
+#include "collate.h"
+#include "setlocale.h"
+#include "ldpart.h"
+
+#include "libc_private.h"
+
+/*
+ * To avoid modifying the original (single-threaded) code too much, we'll just
+ * define the old globals as fields inside the table.
+ *
+ * We also modify the collation table test functions to search the thread-local
+ * table first and the global table second.
+ */
+#define __collate_load_error (table->__collate_load_error)
+#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial)
+#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr)
+#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr)
+#define __collate_chain_pri_table (table->__collate_chain_pri_table)
+
+
+struct xlocale_collate __xlocale_global_collate = {
+ {{0}, "C"}, 1, 0
+};
+
+ struct xlocale_collate __xlocale_C_collate = {
+ {{0}, "C"}, 1, 0
+};
+
+void __collate_err(int ex, const char *f) __dead2;
+
+int
+__collate_load_tables_l(const char *encoding, struct xlocale_collate *table);
+
+static void
+destruct_collate(void *t)
+{
+ struct xlocale_collate *table = t;
+ if (__collate_chain_pri_table) {
+ free(__collate_chain_pri_table);
+ }
+ free(t);
+}
+
+void *
+__collate_load(const char *encoding, locale_t unused)
+{
+ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) {
+ return &__xlocale_C_collate;
+ }
+ struct xlocale_collate *table = calloc(sizeof(struct xlocale_collate), 1);
+ table->header.header.destructor = destruct_collate;
+ // FIXME: Make sure that _LDP_CACHE is never returned. We should be doing
+ // the caching outside of this section
+ if (__collate_load_tables_l(encoding, table) != _LDP_LOADED) {
+ xlocale_release(table);
+ return NULL;
+ }
+ return table;
+}
+
+/**
+ * Load the collation tables for the specified encoding into the global table.
+ */
+int
+__collate_load_tables(const char *encoding)
+{
+ return __collate_load_tables_l(encoding, &__xlocale_global_collate);
+}
+
+int
+__collate_load_tables_l(const char *encoding, struct xlocale_collate *table)
+{
+ FILE *fp;
+ int i, saverr, chains;
+ uint32_t u32;
+ char strbuf[STR_LEN], buf[PATH_MAX];
+ void *TMP_substitute_table, *TMP_char_pri_table, *TMP_chain_pri_table;
+
+ /* 'encoding' must be already checked. */
+ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) {
+ __collate_load_error = 1;
+ return (_LDP_CACHE);
+ }
+
+ /* 'PathLocale' must be already set & checked. */
+ /* Range checking not needed, encoding has fixed size */
+ (void)strcpy(buf, _PathLocale);
+ (void)strcat(buf, "/");
+ (void)strcat(buf, encoding);
+ (void)strcat(buf, "/LC_COLLATE");
+ if ((fp = fopen(buf, "r")) == NULL)
+ return (_LDP_ERROR);
+
+ if (fread(strbuf, sizeof(strbuf), 1, fp) != 1) {
+ saverr = errno;
+ (void)fclose(fp);
+ errno = saverr;
+ return (_LDP_ERROR);
+ }
+ chains = -1;
+ if (strcmp(strbuf, COLLATE_VERSION) == 0)
+ chains = 0;
+ else if (strcmp(strbuf, COLLATE_VERSION1_2) == 0)
+ chains = 1;
+ if (chains < 0) {
+ (void)fclose(fp);
+ errno = EFTYPE;
+ return (_LDP_ERROR);
+ }
+ if (chains) {
+ if (fread(&u32, sizeof(u32), 1, fp) != 1) {
+ saverr = errno;
+ (void)fclose(fp);
+ errno = saverr;
+ return (_LDP_ERROR);
+ }
+ if ((chains = (int)ntohl(u32)) < 1) {
+ (void)fclose(fp);
+ errno = EFTYPE;
+ return (_LDP_ERROR);
+ }
+ } else
+ chains = TABLE_SIZE;
+
+ if ((TMP_substitute_table =
+ malloc(sizeof(__collate_substitute_table))) == NULL) {
+ saverr = errno;
+ (void)fclose(fp);
+ errno = saverr;
+ return (_LDP_ERROR);
+ }
+ if ((TMP_char_pri_table =
+ malloc(sizeof(__collate_char_pri_table))) == NULL) {
+ saverr = errno;
+ free(TMP_substitute_table);
+ (void)fclose(fp);
+ errno = saverr;
+ return (_LDP_ERROR);
+ }
+ if ((TMP_chain_pri_table =
+ malloc(sizeof(*__collate_chain_pri_table) * chains)) == NULL) {
+ saverr = errno;
+ free(TMP_substitute_table);
+ free(TMP_char_pri_table);
+ (void)fclose(fp);
+ errno = saverr;
+ return (_LDP_ERROR);
+ }
+
+#define FREAD(a, b, c, d) \
+{ \
+ if (fread(a, b, c, d) != c) { \
+ saverr = errno; \
+ free(TMP_substitute_table); \
+ free(TMP_char_pri_table); \
+ free(TMP_chain_pri_table); \
+ (void)fclose(d); \
+ errno = saverr; \
+ return (_LDP_ERROR); \
+ } \
+}
+
+ FREAD(TMP_substitute_table, sizeof(__collate_substitute_table), 1, fp);
+ FREAD(TMP_char_pri_table, sizeof(__collate_char_pri_table), 1, fp);
+ FREAD(TMP_chain_pri_table,
+ sizeof(*__collate_chain_pri_table), chains, fp);
+ (void)fclose(fp);
+
+ if (__collate_substitute_table_ptr != NULL)
+ free(__collate_substitute_table_ptr);
+ __collate_substitute_table_ptr = TMP_substitute_table;
+ if (__collate_char_pri_table_ptr != NULL)
+ free(__collate_char_pri_table_ptr);
+ __collate_char_pri_table_ptr = TMP_char_pri_table;
+ for (i = 0; i < UCHAR_MAX + 1; i++) {
+ __collate_char_pri_table[i].prim =
+ ntohl(__collate_char_pri_table[i].prim);
+ __collate_char_pri_table[i].sec =
+ ntohl(__collate_char_pri_table[i].sec);
+ }
+ if (__collate_chain_pri_table != NULL)
+ free(__collate_chain_pri_table);
+ __collate_chain_pri_table = TMP_chain_pri_table;
+ for (i = 0; i < chains; i++) {
+ __collate_chain_pri_table[i].prim =
+ ntohl(__collate_chain_pri_table[i].prim);
+ __collate_chain_pri_table[i].sec =
+ ntohl(__collate_chain_pri_table[i].sec);
+ }
+ __collate_substitute_nontrivial = 0;
+ for (i = 0; i < UCHAR_MAX + 1; i++) {
+ if (__collate_substitute_table[i][0] != i ||
+ __collate_substitute_table[i][1] != 0) {
+ __collate_substitute_nontrivial = 1;
+ break;
+ }
+ }
+ __collate_load_error = 0;
+
+ return (_LDP_LOADED);
+}
+
+u_char *
+__collate_substitute(struct xlocale_collate *table, const u_char *s)
+{
+ int dest_len, len, nlen;
+ int delta = strlen(s);
+ u_char *dest_str = NULL;
+
+ if (s == NULL || *s == '\0')
+ return (__collate_strdup(""));
+ delta += delta / 8;
+ dest_str = malloc(dest_len = delta);
+ if (dest_str == NULL)
+ __collate_err(EX_OSERR, __func__);
+ len = 0;
+ while (*s) {
+ nlen = len + strlen(__collate_substitute_table[*s]);
+ if (dest_len <= nlen) {
+ dest_str = reallocf(dest_str, dest_len = nlen + delta);
+ if (dest_str == NULL)
+ __collate_err(EX_OSERR, __func__);
+ }
+ (void)strcpy(dest_str + len, __collate_substitute_table[*s++]);
+ len = nlen;
+ }
+ return (dest_str);
+}
+
+void
+__collate_lookup(struct xlocale_collate *table, const u_char *t, int *len, int *prim, int *sec)
+{
+ struct __collate_st_chain_pri *p2;
+
+ *len = 1;
+ *prim = *sec = 0;
+ for (p2 = __collate_chain_pri_table; p2->str[0] != '\0'; p2++) {
+ if (*t == p2->str[0] &&
+ strncmp(t, p2->str, strlen(p2->str)) == 0) {
+ *len = strlen(p2->str);
+ *prim = p2->prim;
+ *sec = p2->sec;
+ return;
+ }
+ }
+ *prim = __collate_char_pri_table[*t].prim;
+ *sec = __collate_char_pri_table[*t].sec;
+}
+
+u_char *
+__collate_strdup(u_char *s)
+{
+ u_char *t = strdup(s);
+
+ if (t == NULL)
+ __collate_err(EX_OSERR, __func__);
+ return (t);
+}
+
+void
+__collate_err(int ex, const char *f)
+{
+ const char *s;
+ int serrno = errno;
+
+ s = _getprogname();
+ _write(STDERR_FILENO, s, strlen(s));
+ _write(STDERR_FILENO, ": ", 2);
+ s = f;
+ _write(STDERR_FILENO, s, strlen(s));
+ _write(STDERR_FILENO, ": ", 2);
+ s = strerror(serrno);
+ _write(STDERR_FILENO, s, strlen(s));
+ _write(STDERR_FILENO, "\n", 1);
+ exit(ex);
+}
+
+#ifdef COLLATE_DEBUG
+void
+__collate_print_tables()
+{
+ int i;
+ struct __collate_st_chain_pri *p2;
+
+ printf("Substitute table:\n");
+ for (i = 0; i < UCHAR_MAX + 1; i++)
+ if (i != *__collate_substitute_table[i])
+ printf("\t'%c' --> \"%s\"\n", i,
+ __collate_substitute_table[i]);
+ printf("Chain priority table:\n");
+ for (p2 = __collate_chain_pri_table; p2->str[0] != '\0'; p2++)
+ printf("\t\"%s\" : %d %d\n", p2->str, p2->prim, p2->sec);
+ printf("Char priority table:\n");
+ for (i = 0; i < UCHAR_MAX + 1; i++)
+ printf("\t'%c' : %d %d\n", i, __collate_char_pri_table[i].prim,
+ __collate_char_pri_table[i].sec);
+}
+#endif
diff --git a/lib/libc/locale/collate.h b/lib/libc/locale/collate.h
new file mode 100644
index 0000000..ad034d4
--- /dev/null
+++ b/lib/libc/locale/collate.h
@@ -0,0 +1,81 @@
+/*-
+ * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
+ * at Electronni Visti IA, Kiev, Ukraine.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _COLLATE_H_
+#define _COLLATE_H_
+
+#include <sys/cdefs.h>
+#include <sys/types.h>
+#include <limits.h>
+#include "xlocale_private.h"
+
+#define STR_LEN 10
+#define TABLE_SIZE 100
+#define COLLATE_VERSION "1.0\n"
+#define COLLATE_VERSION1_2 "1.2\n"
+
+struct __collate_st_char_pri {
+ int prim, sec;
+};
+struct __collate_st_chain_pri {
+ u_char str[STR_LEN];
+ int prim, sec;
+};
+
+#define __collate_substitute_table (*__collate_substitute_table_ptr)
+#define __collate_char_pri_table (*__collate_char_pri_table_ptr)
+
+struct xlocale_collate {
+ struct xlocale_component header;
+ int __collate_load_error;
+ int __collate_substitute_nontrivial;
+
+ u_char (*__collate_substitute_table_ptr)[UCHAR_MAX + 1][STR_LEN];
+ struct __collate_st_char_pri (*__collate_char_pri_table_ptr)[UCHAR_MAX + 1];
+ struct __collate_st_chain_pri *__collate_chain_pri_table;
+};
+
+
+__BEGIN_DECLS
+u_char *__collate_strdup(u_char *);
+u_char *__collate_substitute(struct xlocale_collate *, const u_char *);
+int __collate_load_tables(const char *);
+void __collate_lookup(struct xlocale_collate *, const u_char *, int *, int *, int *);
+int __collate_range_cmp(struct xlocale_collate *, int, int);
+#ifdef COLLATE_DEBUG
+void __collate_print_tables(void);
+#endif
+__END_DECLS
+
+#endif /* !_COLLATE_H_ */
diff --git a/lib/libc/locale/collcmp.c b/lib/libc/locale/collcmp.c
new file mode 100644
index 0000000..aa17afd
--- /dev/null
+++ b/lib/libc/locale/collcmp.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 1996 by Andrey A. Chernov, Moscow, Russia.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+#include <xlocale.h>
+#include "collate.h"
+
+/*
+ * Compare two characters using collate
+ */
+
+int __collate_range_cmp(struct xlocale_collate *table, int c1, int c2)
+{
+ static char s1[2], s2[2];
+
+ s1[0] = c1;
+ s2[0] = c2;
+ struct _xlocale l = {{0}};
+ l.components[XLC_COLLATE] = (struct xlocale_component *)table;
+ return (strcoll_l(s1, s2, &l));
+}
diff --git a/lib/libc/locale/ctype.3 b/lib/libc/locale/ctype.3
new file mode 100644
index 0000000..62ec05f
--- /dev/null
+++ b/lib/libc/locale/ctype.3
@@ -0,0 +1,151 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)ctype.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd March 30, 2004
+.Dt CTYPE 3
+.Os
+.Sh NAME
+.Nm digittoint ,
+.Nm isalnum ,
+.Nm isalpha ,
+.Nm isascii ,
+.Nm isblank ,
+.Nm iscntrl ,
+.Nm isdigit ,
+.Nm isgraph ,
+.Nm ishexnumber ,
+.Nm isideogram ,
+.Nm islower ,
+.Nm isnumber ,
+.Nm isphonogram ,
+.Nm isprint ,
+.Nm ispunct ,
+.Nm isrune ,
+.Nm isspace ,
+.Nm isspecial ,
+.Nm isupper ,
+.Nm isxdigit ,
+.Nm toascii ,
+.Nm tolower ,
+.Nm toupper
+.Nd character classification functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn digittoint "int c"
+.Ft int
+.Fn isalnum "int c"
+.Ft int
+.Fn isalpha "int c"
+.Ft int
+.Fn isascii "int c"
+.Ft int
+.Fn iscntrl "int c"
+.Ft int
+.Fn isdigit "int c"
+.Ft int
+.Fn isgraph "int c"
+.Ft int
+.Fn ishexnumber "int c"
+.Ft int
+.Fn isideogram "int c"
+.Ft int
+.Fn islower "int c"
+.Ft int
+.Fn isnumber "int c"
+.Ft int
+.Fn isphonogram "int c"
+.Ft int
+.Fn isspecial "int c"
+.Ft int
+.Fn isprint "int c"
+.Ft int
+.Fn ispunct "int c"
+.Ft int
+.Fn isrune "int c"
+.Ft int
+.Fn isspace "int c"
+.Ft int
+.Fn isupper "int c"
+.Ft int
+.Fn isxdigit "int c"
+.Ft int
+.Fn toascii "int c"
+.Ft int
+.Fn tolower "int c"
+.Ft int
+.Fn toupper "int c"
+.Sh DESCRIPTION
+The above functions perform character tests and conversions on the integer
+.Fa c .
+They are available as macros, defined in the include file
+.In ctype.h ,
+or as true functions in the C library.
+See the specific manual pages for more information.
+.Sh SEE ALSO
+.Xr digittoint 3 ,
+.Xr isalnum 3 ,
+.Xr isalpha 3 ,
+.Xr isascii 3 ,
+.Xr isblank 3 ,
+.Xr iscntrl 3 ,
+.Xr isdigit 3 ,
+.Xr isgraph 3 ,
+.Xr isideogram 3 ,
+.Xr islower 3 ,
+.Xr isphonogram 3 ,
+.Xr isprint 3 ,
+.Xr ispunct 3 ,
+.Xr isrune 3 ,
+.Xr isspace 3 ,
+.Xr isspecial 3 ,
+.Xr isupper 3 ,
+.Xr isxdigit 3 ,
+.Xr toascii 3 ,
+.Xr tolower 3 ,
+.Xr toupper 3 ,
+.Xr wctype 3 ,
+.Xr ascii 7
+.Sh STANDARDS
+These functions, except for
+.Fn digittoint ,
+.Fn isascii ,
+.Fn ishexnumber ,
+.Fn isideogram ,
+.Fn isnumber ,
+.Fn isphonogram ,
+.Fn isrune ,
+.Fn isspecial
+and
+.Fn toascii ,
+conform to
+.St -isoC .
diff --git a/lib/libc/locale/ctype.c b/lib/libc/locale/ctype.c
new file mode 100644
index 0000000..f0ec3f6
--- /dev/null
+++ b/lib/libc/locale/ctype.c
@@ -0,0 +1,33 @@
+/*-
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by David Chisnall under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions * are met:
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation
+ * and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#define _XLOCALE_INLINE
+#include <ctype.h>
+#include <wctype.h>
+#include <xlocale.h>
diff --git a/lib/libc/locale/ctype_l.3 b/lib/libc/locale/ctype_l.3
new file mode 100644
index 0000000..385125e
--- /dev/null
+++ b/lib/libc/locale/ctype_l.3
@@ -0,0 +1,138 @@
+.\" Copyright (c) 2011 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This documentation was written by David Chisnall under sponsorship from
+.\" the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 6, 2012
+.Dt CTYPE_L 3
+.Os
+.Sh NAME
+.Nm digittoint_l ,
+.Nm isalnum_l ,
+.Nm isalpha_l ,
+.Nm isascii_l ,
+.Nm isblank_l ,
+.Nm iscntrl_l ,
+.Nm isdigit_l ,
+.Nm isgraph_l ,
+.Nm ishexnumber_l ,
+.Nm isideogram_l ,
+.Nm islower_l ,
+.Nm isnumber_l ,
+.Nm isphonogram_l ,
+.Nm isprint_l ,
+.Nm ispunct_l ,
+.Nm isrune_l ,
+.Nm isspace_l ,
+.Nm isspecial_l ,
+.Nm isupper_l ,
+.Nm isxdigit_l ,
+.Nm tolower_l ,
+.Nm toupper_l
+.Nd character classification functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn digittoint_l "int c" "locale_t loc"
+.Ft int
+.Fn isalnum_l "int c" "locale_t loc"
+.Ft int
+.Fn isalpha_l "int c" "locale_t loc"
+.Ft int
+.Fn isascii_l "int c" "locale_t loc"
+.Ft int
+.Fn iscntrl_l "int c" "locale_t loc"
+.Ft int
+.Fn isdigit_l "int c" "locale_t loc"
+.Ft int
+.Fn isgraph_l "int c" "locale_t loc"
+.Ft int
+.Fn ishexnumber_l "int c" "locale_t loc"
+.Ft int
+.Fn isideogram_l "int c" "locale_t loc"
+.Ft int
+.Fn islower_l "int c" "locale_t loc"
+.Ft int
+.Fn isnumber_l "int c" "locale_t loc"
+.Ft int
+.Fn isphonogram_l "int c" "locale_t loc"
+.Ft int
+.Fn isspecial_l "int c" "locale_t loc"
+.Ft int
+.Fn isprint_l "int c" "locale_t loc"
+.Ft int
+.Fn ispunct_l "int c" "locale_t loc"
+.Ft int
+.Fn isrune_l "int c" "locale_t loc"
+.Ft int
+.Fn isspace_l "int c" "locale_t loc"
+.Ft int
+.Fn isupper_l "int c" "locale_t loc"
+.Ft int
+.Fn isxdigit_l "int c" "locale_t loc"
+.Ft int
+.Fn tolower_l "int c" "locale_t loc"
+.Ft int
+.Fn toupper_l "int c" "locale_t loc"
+.Sh DESCRIPTION
+The above functions perform character tests and conversions on the integer
+.Fa c
+in the locale
+.Fa loc .
+They behave in the same way as the versions without the _l suffix, but use the
+specified locale rather than the global or per-thread locale.
+.In ctype.h ,
+or as true functions in the C library.
+See the specific manual pages for more information.
+.Sh SEE ALSO
+.Xr digittoint 3 ,
+.Xr isalnum 3 ,
+.Xr isalpha 3 ,
+.Xr isascii 3 ,
+.Xr isblank 3 ,
+.Xr iscntrl 3 ,
+.Xr isdigit 3 ,
+.Xr isgraph 3 ,
+.Xr isideogram 3 ,
+.Xr islower 3 ,
+.Xr isphonogram 3 ,
+.Xr isprint 3 ,
+.Xr ispunct 3 ,
+.Xr isrune 3 ,
+.Xr isspace 3 ,
+.Xr isspecial 3 ,
+.Xr isupper 3 ,
+.Xr isxdigit 3 ,
+.Xr tolower 3 ,
+.Xr toupper 3 ,
+.Xr wctype 3 ,
+.Xr xlocale 3
+.Sh STANDARDS
+These functions conform to
+.St -p1003.1-2008 .
diff --git a/lib/libc/locale/digittoint.3 b/lib/libc/locale/digittoint.3
new file mode 100644
index 0000000..4a7f2e2
--- /dev/null
+++ b/lib/libc/locale/digittoint.3
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)digittoint.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd April 6, 2001
+.Dt DIGITTOINT 3
+.Os
+.Sh NAME
+.Nm digittoint
+.Nd convert a numeric character to its integer value
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn digittoint "int c"
+.Ft int
+.Fn digittoint_l "int c" "locale_t loc"
+.Sh DESCRIPTION
+The
+.Fn digittoint
+function converts a numeric character to its corresponding integer value.
+The character can be any decimal digit or hexadecimal digit.
+With hexadecimal characters, the case of the values does not matter.
+.Pp
+The
+.Fn digittoint_l
+function takes an explicit locale argument, whereas the
+.Fn digittoint
+function use the current global or per-thread locale.
+.Sh RETURN VALUES
+The
+.Fn digittoint
+function always returns an integer from the range of 0 to 15.
+If the given character was not a digit as defined by
+.Xr isxdigit 3 ,
+the function will return 0.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr isdigit 3 ,
+.Xr isxdigit 3,
+.Xr xlocale 3
diff --git a/lib/libc/locale/duplocale.3 b/lib/libc/locale/duplocale.3
new file mode 100644
index 0000000..73c0b3e
--- /dev/null
+++ b/lib/libc/locale/duplocale.3
@@ -0,0 +1,79 @@
+.\" Copyright (c) 2011 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This documentation was written by David Chisnall under sponsorship from
+.\" the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 17 2011
+.Dt DUPLOCALE 3
+.Os
+.Sh NAME
+.Nm duplocale
+.Nd duplicate an locale
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In xlocale.h
+.Ft locale_t
+.Fn duplocale "locale_t locale"
+.Sh DESCRIPTION
+Duplicates an existing
+.Fa locale_t
+returning a new
+.Fa locale_t
+that refers to the same locale values but has independent internal state.
+Various functions, such as
+.Xr mblen 3
+require presistent state.
+These functions formerly used static variables and calls to them from multiple
+threads had undefined behavior.
+They now use fields in the
+.Fa locale_t
+associated with the current thread by
+.Xr uselocale 3 .
+These calls are therefore only thread safe on threads with a unique per-thread
+locale.
+The locale returned by this call must be freed with
+.Xr freelocale 3 .
+.Sh SEE ALSO
+.Xr freelocale 3 ,
+.Xr localeconv 3 ,
+.Xr newlocale 3 ,
+.Xr querylocale 3 ,
+.Xr uselocale 3 ,
+.Xr xlocale 3
+.Sh STANDARDS
+This function, conforms to
+.St -p1003.1-2008
+.Sh BUGS
+Ideally,
+.Xr uselocale 3
+should make a copy of the
+.Fa locale_t
+implicitly to ensure thread safety,
+and a copy of the global locale should be installed lazily on each thread.
+The FreeBSD implementation does not do this,
+for compatibility with Darwin.
diff --git a/lib/libc/locale/euc.5 b/lib/libc/locale/euc.5
new file mode 100644
index 0000000..b438ede
--- /dev/null
+++ b/lib/libc/locale/euc.5
@@ -0,0 +1,134 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Paul Borman at Krystal Technologies.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)euc.4 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd November 8, 2003
+.Dt EUC 5
+.Os
+.Sh NAME
+.Nm euc
+.Nd EUC encoding of wide characters
+.Sh SYNOPSIS
+.Nm ENCODING
+.Qq EUC
+.Pp
+.Nm VARIABLE
+.Ar len1
+.Ar mask1
+.Ar len2
+.Ar mask2
+.Ar len3
+.Ar mask3
+.Ar len4
+.Ar mask4
+.Ar mask
+.Sh DESCRIPTION
+.\"The
+.\".Nm EUC
+.\"encoding is provided for compatibility with
+.\".Ux
+.\"based systems.
+.\"See
+.\".Xr mklocale 1
+.\"for a complete description of the
+.\".Ev LC_CTYPE
+.\"source file format.
+.\".Pp
+.Nm EUC
+implements a system of 4 multibyte codesets.
+A multibyte character in the first codeset consists of
+.Ar len1
+bytes starting with a byte in the range of 0x00 to 0x7f.
+To allow use of
+.Tn ASCII ,
+.Ar len1
+is always 1.
+A multibyte character in the second codeset consists of
+.Ar len2
+bytes starting with a byte in the range of 0x80-0xff excluding 0x8e and 0x8f.
+A multibyte character in the third codeset consists of
+.Ar len3
+bytes starting with the byte 0x8e.
+A multibyte character in the fourth codeset consists of
+.Ar len4
+bytes starting with the byte 0x8f.
+.Pp
+The
+.Vt wchar_t
+encoding of
+.Nm EUC
+multibyte characters is dependent on the
+.Ar len
+and
+.Ar mask
+arguments.
+First, the bytes are moved into a
+.Vt wchar_t
+as follows:
+.Bd -literal
+byte0 << ((\fIlen\fPN-1) * 8) | byte1 << ((\fIlen\fPN-2) * 8) | ... | byte\fIlen\fPN-1
+.Ed
+.Pp
+The result is then ANDed with
+.Ar ~mask
+and ORed with
+.Ar maskN .
+Codesets 2 and 3 are special in that the leading byte (0x8e or 0x8f) is
+first removed and the
+.Ar lenN
+argument is reduced by 1.
+.Pp
+For example, the
+.Li ja_JP.eucJP
+locale has the following
+.Va VARIABLE
+line:
+.Bd -literal
+VARIABLE 1 0x0000 2 0x8080 2 0x0080 3 0x8000 0x8080
+.Ed
+.Pp
+Codeset 1 consists of the values 0x0000 - 0x007f.
+.Pp
+Codeset 2 consists of the values who have the bits 0x8080 set.
+.Pp
+Codeset 3 consists of the values 0x0080 - 0x00ff.
+.Pp
+Codeset 4 consists of the values 0x8000 - 0xff7f excluding the values
+which have the 0x0080 bit set.
+.Pp
+Notice that the global
+.Ar mask
+is set to 0x8080, this implies that from those 2 bits the codeset can
+be determined.
+.Sh SEE ALSO
+.Xr mklocale 1 ,
+.Xr setlocale 3
diff --git a/lib/libc/locale/euc.c b/lib/libc/locale/euc.c
new file mode 100644
index 0000000..26ad413
--- /dev/null
+++ b/lib/libc/locale/euc.c
@@ -0,0 +1,273 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)euc.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/param.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <runetype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+extern int __mb_sb_limit;
+
+static size_t _EUC_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _EUC_mbsinit(const mbstate_t *);
+static size_t _EUC_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+
+typedef struct {
+ int count[4];
+ wchar_t bits[4];
+ wchar_t mask;
+} _EucInfo;
+
+typedef struct {
+ wchar_t ch;
+ int set;
+ int want;
+} _EucState;
+
+int
+_EUC_init(struct xlocale_ctype *l, _RuneLocale *rl)
+{
+ _EucInfo *ei;
+ int x, new__mb_cur_max;
+ char *v, *e;
+
+ if (rl->__variable == NULL)
+ return (EFTYPE);
+
+ v = (char *)rl->__variable;
+
+ while (*v == ' ' || *v == '\t')
+ ++v;
+
+ if ((ei = malloc(sizeof(_EucInfo))) == NULL)
+ return (errno == 0 ? ENOMEM : errno);
+
+ new__mb_cur_max = 0;
+ for (x = 0; x < 4; ++x) {
+ ei->count[x] = (int)strtol(v, &e, 0);
+ if (v == e || !(v = e)) {
+ free(ei);
+ return (EFTYPE);
+ }
+ if (new__mb_cur_max < ei->count[x])
+ new__mb_cur_max = ei->count[x];
+ while (*v == ' ' || *v == '\t')
+ ++v;
+ ei->bits[x] = (int)strtol(v, &e, 0);
+ if (v == e || !(v = e)) {
+ free(ei);
+ return (EFTYPE);
+ }
+ while (*v == ' ' || *v == '\t')
+ ++v;
+ }
+ ei->mask = (int)strtol(v, &e, 0);
+ if (v == e || !(v = e)) {
+ free(ei);
+ return (EFTYPE);
+ }
+ rl->__variable = ei;
+ rl->__variable_len = sizeof(_EucInfo);
+ l->runes = rl;
+ l->__mb_cur_max = new__mb_cur_max;
+ l->__mbrtowc = _EUC_mbrtowc;
+ l->__wcrtomb = _EUC_wcrtomb;
+ l->__mbsinit = _EUC_mbsinit;
+ l->__mb_sb_limit = 256;
+ return (0);
+}
+
+static int
+_EUC_mbsinit(const mbstate_t *ps)
+{
+
+ return (ps == NULL || ((const _EucState *)ps)->want == 0);
+}
+
+#define CEI ((_EucInfo *)(_CurrentRuneLocale->__variable))
+
+#define _SS2 0x008e
+#define _SS3 0x008f
+
+#define GR_BITS 0x80808080 /* XXX: to be fixed */
+
+static __inline int
+_euc_set(u_int c)
+{
+
+ c &= 0xff;
+ return ((c & 0x80) ? c == _SS3 ? 3 : c == _SS2 ? 2 : 1 : 0);
+}
+
+static size_t
+_EUC_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
+ mbstate_t * __restrict ps)
+{
+ _EucState *es;
+ int i, set, want;
+ wchar_t wc;
+ const char *os;
+
+ es = (_EucState *)ps;
+
+ if (es->want < 0 || es->want > MB_CUR_MAX || es->set < 0 ||
+ es->set > 3) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL) {
+ s = "";
+ n = 1;
+ pwc = NULL;
+ }
+
+ if (n == 0)
+ /* Incomplete multibyte sequence */
+ return ((size_t)-2);
+
+ os = s;
+
+ if (es->want == 0) {
+ want = CEI->count[set = _euc_set(*s)];
+ if (set == 2 || set == 3) {
+ --want;
+ if (--n == 0) {
+ /* Incomplete multibyte sequence */
+ es->set = set;
+ es->want = want;
+ es->ch = 0;
+ return ((size_t)-2);
+ }
+ ++s;
+ if (*s == '\0') {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ }
+ wc = (unsigned char)*s++;
+ } else {
+ set = es->set;
+ want = es->want;
+ wc = es->ch;
+ }
+ for (i = (es->want == 0) ? 1 : 0; i < MIN(want, n); i++) {
+ if (*s == '\0') {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ wc = (wc << 8) | (unsigned char)*s++;
+ }
+ if (i < want) {
+ /* Incomplete multibyte sequence */
+ es->set = set;
+ es->want = want - i;
+ es->ch = wc;
+ return ((size_t)-2);
+ }
+ wc = (wc & ~CEI->mask) | CEI->bits[set];
+ if (pwc != NULL)
+ *pwc = wc;
+ es->want = 0;
+ return (wc == L'\0' ? 0 : s - os);
+}
+
+static size_t
+_EUC_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
+{
+ _EucState *es;
+ wchar_t m, nm;
+ int i, len;
+
+ es = (_EucState *)ps;
+
+ if (es->want != 0) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (1);
+
+ m = wc & CEI->mask;
+ nm = wc & ~m;
+
+ if (m == CEI->bits[1]) {
+CodeSet1:
+ /* Codeset 1: The first byte must have 0x80 in it. */
+ i = len = CEI->count[1];
+ while (i-- > 0)
+ *s++ = (nm >> (i << 3)) | 0x80;
+ } else {
+ if (m == CEI->bits[0])
+ i = len = CEI->count[0];
+ else if (m == CEI->bits[2]) {
+ i = len = CEI->count[2];
+ *s++ = _SS2;
+ --i;
+ /* SS2 designates G2 into GR */
+ nm |= GR_BITS;
+ } else if (m == CEI->bits[3]) {
+ i = len = CEI->count[3];
+ *s++ = _SS3;
+ --i;
+ /* SS3 designates G3 into GR */
+ nm |= GR_BITS;
+ } else
+ goto CodeSet1; /* Bletch */
+ while (i-- > 0)
+ *s++ = (nm >> (i << 3)) & 0xff;
+ }
+ return (len);
+}
diff --git a/lib/libc/locale/fix_grouping.c b/lib/libc/locale/fix_grouping.c
new file mode 100644
index 0000000..2e5bc04
--- /dev/null
+++ b/lib/libc/locale/fix_grouping.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <limits.h>
+#include <stddef.h>
+
+static const char nogrouping[] = { CHAR_MAX, '\0' };
+
+/*
+ * Internal helper used to convert grouping sequences from string
+ * representation into POSIX specified form, i.e.
+ *
+ * "3;3;-1" -> "\003\003\177\000"
+ */
+
+const char *
+__fix_locale_grouping_str(const char *str)
+{
+ char *src, *dst;
+ char n;
+
+ if (str == NULL || *str == '\0') {
+ return nogrouping;
+ }
+
+ for (src = (char*)str, dst = (char*)str; *src != '\0'; src++) {
+
+ /* input string examples: "3;3", "3;2;-1" */
+ if (*src == ';')
+ continue;
+
+ if (*src == '-' && *(src+1) == '1') {
+ *dst++ = CHAR_MAX;
+ src++;
+ continue;
+ }
+
+ if (!isdigit((unsigned char)*src)) {
+ /* broken grouping string */
+ return nogrouping;
+ }
+
+ /* assume all numbers <= 99 */
+ n = *src - '0';
+ if (isdigit((unsigned char)*(src+1))) {
+ src++;
+ n *= 10;
+ n += *src - '0';
+ }
+
+ *dst = n;
+ /* NOTE: assume all input started with "0" as 'no grouping' */
+ if (*dst == '\0')
+ return (dst == (char*)str) ? nogrouping : str;
+ dst++;
+ }
+ *dst = '\0';
+ return str;
+}
diff --git a/lib/libc/locale/freelocale.3 b/lib/libc/locale/freelocale.3
new file mode 100644
index 0000000..8401803
--- /dev/null
+++ b/lib/libc/locale/freelocale.3
@@ -0,0 +1,61 @@
+.\" Copyright (c) 2011 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This documentation was written by David Chisnall under sponsorship from
+.\" the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.Dd September 17 2011
+.Dt FREELOCALE 3
+.Os
+.Sh NAME
+.Nm freelocale
+.Nd Frees a locale created with
+.Xr duplocale 3
+or
+.Xr newlocale 3 .
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In xlocale.h
+.Ft int
+.Fn freelocale "locale_t locale"
+.Sh DESCRIPTION
+Frees a
+.Fa locale_t .
+This relinquishes any resources held exclusively by this locale.
+Note that locales share reference-counted components,
+so a call to this function is not guaranteed to free all of the components.
+.Sh RETURN VALUES
+Returns 0 on success or -1 on error.
+.Sh SEE ALSO
+.Xr duplocale 3 ,
+.Xr localeconv 3 ,
+.Xr newlocale 3 ,
+.Xr querylocale 3 ,
+.Xr uselocale 3 ,
+.Xr xlocale 3
+.Sh STANDARDS
+This function, conforms to
+.St -p1003.1-2008 .
diff --git a/lib/libc/locale/gb18030.5 b/lib/libc/locale/gb18030.5
new file mode 100644
index 0000000..3a296c0
--- /dev/null
+++ b/lib/libc/locale/gb18030.5
@@ -0,0 +1,78 @@
+.\" Copyright (c) 2002, 2003 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 10, 2003
+.Dt GB18030 5
+.Os
+.Sh NAME
+.Nm gb18030
+.Nd "GB 18030 encoding method for Chinese text"
+.Sh SYNOPSIS
+.Nm ENCODING
+.Qq GB18030
+.Sh DESCRIPTION
+The
+.Nm GB18030
+encoding implements GB 18030-2000, a PRC national standard for the encoding of
+Chinese characters.
+It is a superset of the older GB\ 2312-1980 and GBK encodings,
+and incorporates Unicode's Unihan Extension A completely.
+It also provides code space for all Unicode 3.0 code points.
+.Pp
+Multibyte characters in the
+.Nm GB18030
+encoding can be one byte, two bytes, or
+four bytes long.
+There are a total of over 1.5 million code positions.
+.Pp
+.No GB\ 11383-1981 Pq Tn ASCII
+characters are represented by single bytes in the range 0x00 to 0x7F.
+.Pp
+Chinese characters are represented as either two bytes or four bytes.
+Characters that are represented by two bytes begin with a byte in the range
+0x81-0xFE and end with a byte either in the range 0x40-0x7E or 0x80-0xFE.
+.Pp
+Characters that are represented by four bytes begin with a byte in the range
+0x81-0xFE, have a second byte in the range 0x30-0x39, a third byte in the range
+0x81-0xFE and a fourth byte in the range 0x30-0x39.
+.Sh SEE ALSO
+.Xr euc 5 ,
+.Xr gb2312 5 ,
+.Xr gbk 5 ,
+.Xr utf8 5
+.Rs
+.%T "Chinese National Standard GB 18030-2000: Information Technology -- Chinese ideograms coded character set for information interchange -- Extension for the basic set"
+.%D "March 2000"
+.Re
+.Rs
+.%Q "The Unicode Consortium"
+.%T "The Unicode Standard, Version 3.0"
+.%D "2000"
+.Re
+.Sh STANDARDS
+The
+.Nm GB18030
+encoding is believed to be compatible with GB 18030-2000.
diff --git a/lib/libc/locale/gb18030.c b/lib/libc/locale/gb18030.c
new file mode 100644
index 0000000..9214385
--- /dev/null
+++ b/lib/libc/locale/gb18030.c
@@ -0,0 +1,224 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * PRC National Standard GB 18030-2000 encoding of Chinese text.
+ *
+ * See gb18030(5) for details.
+ */
+
+#include <sys/param.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <runetype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+static size_t _GB18030_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _GB18030_mbsinit(const mbstate_t *);
+static size_t _GB18030_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+
+typedef struct {
+ int count;
+ u_char bytes[4];
+} _GB18030State;
+
+int
+_GB18030_init(struct xlocale_ctype *l, _RuneLocale *rl)
+{
+
+ l->__mbrtowc = _GB18030_mbrtowc;
+ l->__wcrtomb = _GB18030_wcrtomb;
+ l->__mbsinit = _GB18030_mbsinit;
+ l->runes = rl;
+ l->__mb_cur_max = 4;
+ l->__mb_sb_limit = 128;
+
+ return (0);
+}
+
+static int
+_GB18030_mbsinit(const mbstate_t *ps)
+{
+
+ return (ps == NULL || ((const _GB18030State *)ps)->count == 0);
+}
+
+static size_t
+_GB18030_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
+ size_t n, mbstate_t * __restrict ps)
+{
+ _GB18030State *gs;
+ wchar_t wch;
+ int ch, len, ocount;
+ size_t ncopy;
+
+ gs = (_GB18030State *)ps;
+
+ if (gs->count < 0 || gs->count > sizeof(gs->bytes)) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL) {
+ s = "";
+ n = 1;
+ pwc = NULL;
+ }
+
+ ncopy = MIN(MIN(n, MB_CUR_MAX), sizeof(gs->bytes) - gs->count);
+ memcpy(gs->bytes + gs->count, s, ncopy);
+ ocount = gs->count;
+ gs->count += ncopy;
+ s = (char *)gs->bytes;
+ n = gs->count;
+
+ if (n == 0)
+ /* Incomplete multibyte sequence */
+ return ((size_t)-2);
+
+ /*
+ * Single byte: [00-7f]
+ * Two byte: [81-fe][40-7e,80-fe]
+ * Four byte: [81-fe][30-39][81-fe][30-39]
+ */
+ ch = (unsigned char)*s++;
+ if (ch <= 0x7f) {
+ len = 1;
+ wch = ch;
+ } else if (ch >= 0x81 && ch <= 0xfe) {
+ wch = ch;
+ if (n < 2)
+ return ((size_t)-2);
+ ch = (unsigned char)*s++;
+ if ((ch >= 0x40 && ch <= 0x7e) || (ch >= 0x80 && ch <= 0xfe)) {
+ wch = (wch << 8) | ch;
+ len = 2;
+ } else if (ch >= 0x30 && ch <= 0x39) {
+ /*
+ * Strip high bit off the wide character we will
+ * eventually output so that it is positive when
+ * cast to wint_t on 32-bit twos-complement machines.
+ */
+ wch = ((wch & 0x7f) << 8) | ch;
+ if (n < 3)
+ return ((size_t)-2);
+ ch = (unsigned char)*s++;
+ if (ch < 0x81 || ch > 0xfe)
+ goto ilseq;
+ wch = (wch << 8) | ch;
+ if (n < 4)
+ return ((size_t)-2);
+ ch = (unsigned char)*s++;
+ if (ch < 0x30 || ch > 0x39)
+ goto ilseq;
+ wch = (wch << 8) | ch;
+ len = 4;
+ } else
+ goto ilseq;
+ } else
+ goto ilseq;
+
+ if (pwc != NULL)
+ *pwc = wch;
+ gs->count = 0;
+ return (wch == L'\0' ? 0 : len - ocount);
+ilseq:
+ errno = EILSEQ;
+ return ((size_t)-1);
+}
+
+static size_t
+_GB18030_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
+{
+ _GB18030State *gs;
+ size_t len;
+ int c;
+
+ gs = (_GB18030State *)ps;
+
+ if (gs->count != 0) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (1);
+ if ((wc & ~0x7fffffff) != 0)
+ goto ilseq;
+ if (wc & 0x7f000000) {
+ /* Replace high bit that mbrtowc() removed. */
+ wc |= 0x80000000;
+ c = (wc >> 24) & 0xff;
+ if (c < 0x81 || c > 0xfe)
+ goto ilseq;
+ *s++ = c;
+ c = (wc >> 16) & 0xff;
+ if (c < 0x30 || c > 0x39)
+ goto ilseq;
+ *s++ = c;
+ c = (wc >> 8) & 0xff;
+ if (c < 0x81 || c > 0xfe)
+ goto ilseq;
+ *s++ = c;
+ c = wc & 0xff;
+ if (c < 0x30 || c > 0x39)
+ goto ilseq;
+ *s++ = c;
+ len = 4;
+ } else if (wc & 0x00ff0000)
+ goto ilseq;
+ else if (wc & 0x0000ff00) {
+ c = (wc >> 8) & 0xff;
+ if (c < 0x81 || c > 0xfe)
+ goto ilseq;
+ *s++ = c;
+ c = wc & 0xff;
+ if (c < 0x40 || c == 0x7f || c == 0xff)
+ goto ilseq;
+ *s++ = c;
+ len = 2;
+ } else if (wc <= 0x7f) {
+ *s++ = wc;
+ len = 1;
+ } else
+ goto ilseq;
+
+ return (len);
+ilseq:
+ errno = EILSEQ;
+ return ((size_t)-1);
+}
diff --git a/lib/libc/locale/gb2312.5 b/lib/libc/locale/gb2312.5
new file mode 100644
index 0000000..5f1f712
--- /dev/null
+++ b/lib/libc/locale/gb2312.5
@@ -0,0 +1,57 @@
+.\" Copyright (c) 2003 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 7, 2003
+.Dt GB2312 5
+.Os
+.Sh NAME
+.Nm gb2312
+.Nd "GB2312 encoding method for Chinese text"
+.Sh SYNOPSIS
+.Nm ENCODING
+.Qq GB2312
+.Sh DESCRIPTION
+The
+.Nm GB2312
+encoding implements GB\ 2312-1980, a PRC national standard
+for the encoding of simplified Chinese characters.
+.Pp
+Multibyte characters in the GB2312
+encoding can be one byte or two bytes long.
+.No GB\ 11383-1981 Pq Tn ASCII
+characters are represented by single bytes in the range 0x00 to 0x7F.
+Simplified Chinese characters are represented by two bytes, both in
+the range 0xA1-0xFE.
+.Sh SEE ALSO
+.Xr euc 5 ,
+.Xr gb18030 5 ,
+.Xr gbk 5
+.Sh STANDARDS
+The
+.Nm GB2312
+encoding is believed to be compatible with GB\ 2312-1980.
+This standard has been superseded by GB\ 18030-2000, but is still
+in wide use.
diff --git a/lib/libc/locale/gb2312.c b/lib/libc/locale/gb2312.c
new file mode 100644
index 0000000..5fbc07d
--- /dev/null
+++ b/lib/libc/locale/gb2312.c
@@ -0,0 +1,160 @@
+/*-
+ * Copyright (c) 2004 Tim J. Robbins. All rights reserved.
+ * Copyright (c) 2003 David Xu <davidxu@freebsd.org>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <runetype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+static size_t _GB2312_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _GB2312_mbsinit(const mbstate_t *);
+static size_t _GB2312_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+
+typedef struct {
+ int count;
+ u_char bytes[2];
+} _GB2312State;
+
+int
+_GB2312_init(struct xlocale_ctype *l, _RuneLocale *rl)
+{
+
+ l->runes = rl;
+ l->__mbrtowc = _GB2312_mbrtowc;
+ l->__wcrtomb = _GB2312_wcrtomb;
+ l->__mbsinit = _GB2312_mbsinit;
+ l->__mb_cur_max = 2;
+ l->__mb_sb_limit = 128;
+ return (0);
+}
+
+static int
+_GB2312_mbsinit(const mbstate_t *ps)
+{
+
+ return (ps == NULL || ((const _GB2312State *)ps)->count == 0);
+}
+
+static __inline int
+_GB2312_check(const char *str, size_t n)
+{
+ const u_char *s = (const u_char *)str;
+
+ if (n == 0)
+ /* Incomplete multibyte sequence */
+ return (-2);
+ if (s[0] >= 0xa1 && s[0] <= 0xfe) {
+ if (n < 2)
+ /* Incomplete multibyte sequence */
+ return (-2);
+ if (s[1] < 0xa1 || s[1] > 0xfe)
+ /* Invalid multibyte sequence */
+ return (-1);
+ return (2);
+ } else if (s[0] & 0x80) {
+ /* Invalid multibyte sequence */
+ return (-1);
+ }
+ return (1);
+}
+
+static size_t
+_GB2312_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
+ mbstate_t * __restrict ps)
+{
+ _GB2312State *gs;
+ wchar_t wc;
+ int i, len, ocount;
+ size_t ncopy;
+
+ gs = (_GB2312State *)ps;
+
+ if (gs->count < 0 || gs->count > sizeof(gs->bytes)) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL) {
+ s = "";
+ n = 1;
+ pwc = NULL;
+ }
+
+ ncopy = MIN(MIN(n, MB_CUR_MAX), sizeof(gs->bytes) - gs->count);
+ memcpy(gs->bytes + gs->count, s, ncopy);
+ ocount = gs->count;
+ gs->count += ncopy;
+ s = (char *)gs->bytes;
+ n = gs->count;
+
+ if ((len = _GB2312_check(s, n)) < 0)
+ return ((size_t)len);
+ wc = 0;
+ i = len;
+ while (i-- > 0)
+ wc = (wc << 8) | (unsigned char)*s++;
+ if (pwc != NULL)
+ *pwc = wc;
+ gs->count = 0;
+ return (wc == L'\0' ? 0 : len - ocount);
+}
+
+static size_t
+_GB2312_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
+{
+ _GB2312State *gs;
+
+ gs = (_GB2312State *)ps;
+
+ if (gs->count != 0) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (1);
+ if (wc & 0x8000) {
+ *s++ = (wc >> 8) & 0xff;
+ *s = wc & 0xff;
+ return (2);
+ }
+ *s = wc & 0xff;
+ return (1);
+}
diff --git a/lib/libc/locale/gbk.5 b/lib/libc/locale/gbk.5
new file mode 100644
index 0000000..cec22c6
--- /dev/null
+++ b/lib/libc/locale/gbk.5
@@ -0,0 +1,63 @@
+.\" Copyright (c) 2003 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 10, 2003
+.Dt GBK 5
+.Os
+.Sh NAME
+.Nm gbk
+.Nd "Guojia biaozhun kuozhan (GBK) encoding method for Chinese text"
+.Sh SYNOPSIS
+.Nm ENCODING
+.Qq GBK
+.Sh DESCRIPTION
+GBK is a backwards-compatible extension of the GB\ 2312-1980 encoding
+method for Chinese text, which adds the characters defined in the
+Unified Han portion of the Unicode 2.1 standard.
+.Pp
+Multibyte characters in the GBK
+encoding can be one byte or two bytes long.
+.No GB\ 11383-1981 Pq Tn ASCII
+characters are represented by single bytes in the range 0x00 to 0x7F.
+Chinese characters are represented by two bytes, beginning with a byte in
+the range 0x80-0xFE and ending with a byte in the range 0x40-0xFE.
+.Sh SEE ALSO
+.Xr euc 5 ,
+.Xr gb18030 5 ,
+.Xr gb2312 5 ,
+.Xr utf8 5
+.Rs
+.%Q "The Unicode Consortium"
+.%T "The Unicode Standard, Version 2.1"
+.%D "1999"
+.Re
+.Rs
+.%T "Chinese National Standard GB 18030-2000: Information Technology -- Chinese ideograms coded character set for information interchange -- Extension for the basic set"
+.%D "March 2000"
+.Re
+.Sh STANDARDS
+GBK is not a standard, but has been superseded by
+GB\ 18030-2000.
diff --git a/lib/libc/locale/gbk.c b/lib/libc/locale/gbk.c
new file mode 100644
index 0000000..43269c7
--- /dev/null
+++ b/lib/libc/locale/gbk.c
@@ -0,0 +1,173 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <errno.h>
+#include <runetype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+extern int __mb_sb_limit;
+
+static size_t _GBK_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _GBK_mbsinit(const mbstate_t *);
+static size_t _GBK_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+
+typedef struct {
+ wchar_t ch;
+} _GBKState;
+
+int
+_GBK_init(struct xlocale_ctype *l, _RuneLocale *rl)
+{
+
+ l->__mbrtowc = _GBK_mbrtowc;
+ l->__wcrtomb = _GBK_wcrtomb;
+ l->__mbsinit = _GBK_mbsinit;
+ l->runes = rl;
+ l->__mb_cur_max = 2;
+ l->__mb_sb_limit = 128;
+ return (0);
+}
+
+static int
+_GBK_mbsinit(const mbstate_t *ps)
+{
+
+ return (ps == NULL || ((const _GBKState *)ps)->ch == 0);
+}
+
+static __inline int
+_gbk_check(u_int c)
+{
+
+ c &= 0xff;
+ return ((c >= 0x81 && c <= 0xfe) ? 2 : 1);
+}
+
+static size_t
+_GBK_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
+ mbstate_t * __restrict ps)
+{
+ _GBKState *gs;
+ wchar_t wc;
+ size_t len;
+
+ gs = (_GBKState *)ps;
+
+ if ((gs->ch & ~0xFF) != 0) {
+ /* Bad conversion state. */
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL) {
+ s = "";
+ n = 1;
+ pwc = NULL;
+ }
+
+ if (n == 0)
+ /* Incomplete multibyte sequence */
+ return ((size_t)-2);
+
+ if (gs->ch != 0) {
+ if (*s == '\0') {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ wc = (gs->ch << 8) | (*s & 0xFF);
+ if (pwc != NULL)
+ *pwc = wc;
+ gs->ch = 0;
+ return (1);
+ }
+
+ len = (size_t)_gbk_check(*s);
+ wc = *s++ & 0xff;
+ if (len == 2) {
+ if (n < 2) {
+ /* Incomplete multibyte sequence */
+ gs->ch = wc;
+ return ((size_t)-2);
+ }
+ if (*s == '\0') {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ wc = (wc << 8) | (*s++ & 0xff);
+ if (pwc != NULL)
+ *pwc = wc;
+ return (2);
+ } else {
+ if (pwc != NULL)
+ *pwc = wc;
+ return (wc == L'\0' ? 0 : 1);
+ }
+}
+
+static size_t
+_GBK_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
+{
+ _GBKState *gs;
+
+ gs = (_GBKState *)ps;
+
+ if (gs->ch != 0) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (1);
+ if (wc & 0x8000) {
+ *s++ = (wc >> 8) & 0xff;
+ *s = wc & 0xff;
+ return (2);
+ }
+ *s = wc & 0xff;
+ return (1);
+}
diff --git a/lib/libc/locale/isalnum.3 b/lib/libc/locale/isalnum.3
new file mode 100644
index 0000000..8161917
--- /dev/null
+++ b/lib/libc/locale/isalnum.3
@@ -0,0 +1,115 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)isalnum.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd July 17, 2005
+.Dt ISALNUM 3
+.Os
+.Sh NAME
+.Nm isalnum
+.Nd alphanumeric character test
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn isalnum "int c"
+.Ft int
+.Fn isalnum_l "int c" "locale_t loc"
+.Sh DESCRIPTION
+The
+.Fn isalnum
+function tests for any character for which
+.Xr isalpha 3
+or
+.Xr isdigit 3
+is true.
+The value of the argument must be representable as an
+.Vt "unsigned char"
+or the value of
+.Dv EOF .
+.Pp
+In the ASCII character set, this includes the following characters
+(with their numeric values shown in octal):
+.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
+.It "\&060\ ``0''" Ta "061\ ``1''" Ta "062\ ``2''" Ta "063\ ``3''" Ta "064\ ``4''"
+.It "\&065\ ``5''" Ta "066\ ``6''" Ta "067\ ``7''" Ta "070\ ``8''" Ta "071\ ``9''"
+.It "\&101\ ``A''" Ta "102\ ``B''" Ta "103\ ``C''" Ta "104\ ``D''" Ta "105\ ``E''"
+.It "\&106\ ``F''" Ta "107\ ``G''" Ta "110\ ``H''" Ta "111\ ``I''" Ta "112\ ``J''"
+.It "\&113\ ``K''" Ta "114\ ``L''" Ta "115\ ``M''" Ta "116\ ``N''" Ta "117\ ``O''"
+.It "\&120\ ``P''" Ta "121\ ``Q''" Ta "122\ ``R''" Ta "123\ ``S''" Ta "124\ ``T''"
+.It "\&125\ ``U''" Ta "126\ ``V''" Ta "127\ ``W''" Ta "130\ ``X''" Ta "131\ ``Y''"
+.It "\&132\ ``Z''" Ta "141\ ``a''" Ta "142\ ``b''" Ta "143\ ``c''" Ta "144\ ``d''"
+.It "\&145\ ``e''" Ta "146\ ``f''" Ta "147\ ``g''" Ta "150\ ``h''" Ta "151\ ``i''"
+.It "\&152\ ``j''" Ta "153\ ``k''" Ta "154\ ``l''" Ta "155\ ``m''" Ta "156\ ``n''"
+.It "\&157\ ``o''" Ta "160\ ``p''" Ta "161\ ``q''" Ta "162\ ``r''" Ta "163\ ``s''"
+.It "\&164\ ``t''" Ta "165\ ``u''" Ta "166\ ``v''" Ta "167\ ``w''" Ta "170\ ``x''"
+.It "\&171\ ``y''" Ta "172\ ``z''" Ta \& Ta \& Ta \&
+.El
+.Pp
+The
+.Fn isalnum_l
+function takes an explicit locale argument, whereas the
+.Fn isalnum
+function uses the current global or per-thread locale.
+.Sh RETURN VALUES
+The
+.Fn isalnum
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh COMPATIBILITY
+The
+.Bx 4.4
+extension of accepting arguments outside of the range of the
+.Vt "unsigned char"
+type in locales with large character sets is considered obsolete
+and may not be supported in future releases.
+The
+.Fn iswalnum
+function should be used instead.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr isalpha 3 ,
+.Xr isdigit 3 ,
+.Xr iswalnum 3 ,
+.Xr xlocale 3 ,
+.Xr ascii 7
+.Sh STANDARDS
+The
+.Fn isalnum
+function conforms to
+.St -isoC .
+The
+.Fn isalnum_l
+function conforms to
+.St -p1003.1-2008 .
diff --git a/lib/libc/locale/isalpha.3 b/lib/libc/locale/isalpha.3
new file mode 100644
index 0000000..0ea3a88
--- /dev/null
+++ b/lib/libc/locale/isalpha.3
@@ -0,0 +1,113 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)isalpha.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd July 17, 2005
+.Dt ISALPHA 3
+.Os
+.Sh NAME
+.Nm isalpha
+.Nd alphabetic character test
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn isalpha "int c"
+.Ft int
+.Fn isalpha_l "int c" "locale_t loc"
+.Sh DESCRIPTION
+The
+.Fn isalpha
+function tests for any character for which
+.Xr isupper 3
+or
+.Xr islower 3
+is true.
+The value of the argument must be representable as an
+.Vt "unsigned char"
+or the value of
+.Dv EOF .
+.Pp
+In the ASCII character set, this includes the following characters
+(with their numeric values shown in octal):
+.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
+.It "\&101\ ``A''" Ta "102\ ``B''" Ta "103\ ``C''" Ta "104\ ``D''" Ta "105\ ``E''"
+.It "\&106\ ``F''" Ta "107\ ``G''" Ta "110\ ``H''" Ta "111\ ``I''" Ta "112\ ``J''"
+.It "\&113\ ``K''" Ta "114\ ``L''" Ta "115\ ``M''" Ta "116\ ``N''" Ta "117\ ``O''"
+.It "\&120\ ``P''" Ta "121\ ``Q''" Ta "122\ ``R''" Ta "123\ ``S''" Ta "124\ ``T''"
+.It "\&125\ ``U''" Ta "126\ ``V''" Ta "127\ ``W''" Ta "130\ ``X''" Ta "131\ ``Y''"
+.It "\&132\ ``Z''" Ta "141\ ``a''" Ta "142\ ``b''" Ta "143\ ``c''" Ta "144\ ``d''"
+.It "\&145\ ``e''" Ta "146\ ``f''" Ta "147\ ``g''" Ta "150\ ``h''" Ta "151\ ``i''"
+.It "\&152\ ``j''" Ta "153\ ``k''" Ta "154\ ``l''" Ta "155\ ``m''" Ta "156\ ``n''"
+.It "\&157\ ``o''" Ta "160\ ``p''" Ta "161\ ``q''" Ta "162\ ``r''" Ta "163\ ``s''"
+.It "\&164\ ``t''" Ta "165\ ``u''" Ta "166\ ``v''" Ta "167\ ``w''" Ta "170\ ``x''"
+.It "\&171\ ``y''" Ta "172\ ``z''" Ta \& Ta \& Ta \&
+.El
+.Pp
+The
+.Fn isalpha_l
+function takes an explicit locale argument, whereas the
+.Fn isalpha
+function uses the current global or per-thread locale.
+.Sh RETURN VALUES
+The
+.Fn isalpha
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh COMPATIBILITY
+The
+.Bx 4.4
+extension of accepting arguments outside of the range of the
+.Vt "unsigned char"
+type in locales with large character sets is considered obsolete
+and may not be supported in future releases.
+The
+.Fn iswalpha
+function should be used instead.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr islower 3 ,
+.Xr isupper 3 ,
+.Xr iswalpha 3 ,
+.Xr xlocale 3 ,
+.Xr ascii 7
+.Sh STANDARDS
+The
+.Fn isalpha
+function conforms to
+.St -isoC .
+The
+.Fn isalpha_l
+function conforms to
+.St -p1003.1-2008 .
diff --git a/lib/libc/locale/isascii.3 b/lib/libc/locale/isascii.3
new file mode 100644
index 0000000..f7e1325
--- /dev/null
+++ b/lib/libc/locale/isascii.3
@@ -0,0 +1,53 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)isascii.3 8.2 (Berkeley) 12/11/93
+.\" $FreeBSD$
+.\"
+.Dd October 6, 2002
+.Dt ISASCII 3
+.Os
+.Sh NAME
+.Nm isascii
+.Nd test for ASCII character
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn isascii "int c"
+.Sh DESCRIPTION
+The
+.Fn isascii
+function tests for an
+.Tn ASCII
+character, which is any character
+between 0 and octal 0177 inclusive.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr iswascii 3 ,
+.Xr ascii 7
diff --git a/lib/libc/locale/isblank.3 b/lib/libc/locale/isblank.3
new file mode 100644
index 0000000..5542280
--- /dev/null
+++ b/lib/libc/locale/isblank.3
@@ -0,0 +1,96 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)isblank.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd July 17, 2005
+.Dt ISBLANK 3
+.Os
+.Sh NAME
+.Nm isblank
+.Nd space or tab character test
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn isblank "int c"
+.Ft int
+.Fn isblank "int c" "locale_t loc"
+.Sh DESCRIPTION
+The
+.Fn isblank
+function tests for a space or tab character.
+For any locale, this includes the following standard characters:
+.Bl -column XXXX
+.It Do \et Dc Ta Dq " "
+.El
+.Pp
+In the "C" locale, a successful
+.Fn isblank
+test is limited to these characters only.
+The value of the argument must be representable as an
+.Vt "unsigned char"
+or the value of
+.Dv EOF .
+.Pp
+The
+.Fn isblank_l
+function takes an explicit locale argument, whereas the
+.Fn isblank
+function uses the current global or per-thread locale.
+.Sh RETURN VALUES
+The
+.Fn isblank
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh COMPATIBILITY
+The
+.Bx 4.4
+extension of accepting arguments outside of the range of the
+.Vt "unsigned char"
+type in locales with large character sets is considered obsolete
+and may not be supported in future releases.
+The
+.Fn iswblank
+function should be used instead.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr iswblank 3 ,
+.Xr xlocale 3 ,
+.Xr ascii 7
+.Sh STANDARDS
+The
+.Fn isblank
+function
+conforms to
+.St -isoC-99 .
+The
+.Fn isblank_l
+function conforms to
+.St -p1003.1-2008 .
diff --git a/lib/libc/locale/iscntrl.3 b/lib/libc/locale/iscntrl.3
new file mode 100644
index 0000000..e973f20
--- /dev/null
+++ b/lib/libc/locale/iscntrl.3
@@ -0,0 +1,103 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)iscntrl.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd July 17, 2005
+.Dt ISCNTRL 3
+.Os
+.Sh NAME
+.Nm iscntrl
+.Nd control character test
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn iscntrl "int c"
+.Ft int
+.Fn iscntrl_l "int c" "locale_t loc"
+.Sh DESCRIPTION
+The
+.Fn iscntrl
+function tests for any control character.
+The value of the argument must be representable as an
+.Vt "unsigned char"
+or the value of
+.Dv EOF .
+.Pp
+In the ASCII character set, this includes the following characters
+(with their numeric values shown in octal):
+.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
+.It "\&000\ NUL" Ta "001\ SOH" Ta "002\ STX" Ta "003\ ETX" Ta "004\ EOT"
+.It "\&005\ ENQ" Ta "006\ ACK" Ta "007\ BEL" Ta "010\ BS" Ta "011\ HT"
+.It "\&012\ NL" Ta "013\ VT" Ta "014\ NP" Ta "015\ CR" Ta "016\ SO"
+.It "\&017\ SI" Ta "020\ DLE" Ta "021\ DC1" Ta "022\ DC2" Ta "023\ DC3"
+.It "\&024\ DC4" Ta "025\ NAK" Ta "026\ SYN" Ta "027\ ETB" Ta "030\ CAN"
+.It "\&031\ EM" Ta "032\ SUB" Ta "033\ ESC" Ta "034\ FS" Ta "035\ GS"
+.It "\&036\ RS" Ta "037\ US" Ta "177\ DEL" Ta \& Ta \&
+.El
+.Pp
+The
+.Fn iscntrl_l
+function takes an explicit locale argument, whereas the
+.Fn iscntrl
+function uses the current global or per-thread locale.
+.Sh RETURN VALUES
+The
+.Fn iscntrl
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh COMPATIBILITY
+The
+.Bx 4.4
+extension of accepting arguments outside of the range of the
+.Vt "unsigned char"
+type in locales with large character sets is considered obsolete
+and may not be supported in future releases.
+The
+.Fn iswcntrl
+function should be used instead.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr iswcntrl 3 ,
+.Xr xlocale 3 ,
+.Xr ascii 7
+.Sh STANDARDS
+The
+.Fn iscntrl
+function conforms to
+.St -isoC .
+The
+.Fn iscntrl_l
+function conforms to
+.St -p1003.1-2008 .
diff --git a/lib/libc/locale/isctype.c b/lib/libc/locale/isctype.c
new file mode 100644
index 0000000..be1b091
--- /dev/null
+++ b/lib/libc/locale/isctype.c
@@ -0,0 +1,229 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)isctype.c 8.3 (Berkeley) 2/24/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+
+#undef digittoint
+int
+digittoint(c)
+ int c;
+{
+ return (__sbmaskrune(c, 0xFF));
+}
+
+#undef isalnum
+int
+isalnum(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_A|_CTYPE_D));
+}
+
+#undef isalpha
+int
+isalpha(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_A));
+}
+
+#undef isascii
+int
+isascii(c)
+ int c;
+{
+ return ((c & ~0x7F) == 0);
+}
+
+#undef isblank
+int
+isblank(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_B));
+}
+
+#undef iscntrl
+int
+iscntrl(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_C));
+}
+
+#undef isdigit
+int
+isdigit(c)
+ int c;
+{
+ return (__isctype(c, _CTYPE_D));
+}
+
+#undef isgraph
+int
+isgraph(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_G));
+}
+
+#undef ishexnumber
+int
+ishexnumber(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_X));
+}
+
+#undef isideogram
+int
+isideogram(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_I));
+}
+
+#undef islower
+int
+islower(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_L));
+}
+
+#undef isnumber
+int
+isnumber(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_D));
+}
+
+#undef isphonogram
+int
+isphonogram(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_Q));
+}
+
+#undef isprint
+int
+isprint(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_R));
+}
+
+#undef ispunct
+int
+ispunct(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_P));
+}
+
+#undef isrune
+int
+isrune(c)
+ int c;
+{
+ return (__sbistype(c, 0xFFFFFF00L));
+}
+
+#undef isspace
+int
+isspace(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_S));
+}
+
+#undef isspecial
+int
+isspecial(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_T));
+}
+
+#undef isupper
+int
+isupper(c)
+ int c;
+{
+ return (__sbistype(c, _CTYPE_U));
+}
+
+#undef isxdigit
+int
+isxdigit(c)
+ int c;
+{
+ return (__isctype(c, _CTYPE_X));
+}
+
+#undef toascii
+int
+toascii(c)
+ int c;
+{
+ return (c & 0x7F);
+}
+
+#undef tolower
+int
+tolower(c)
+ int c;
+{
+ return (__sbtolower(c));
+}
+
+#undef toupper
+int
+toupper(c)
+ int c;
+{
+ return (__sbtoupper(c));
+}
+
diff --git a/lib/libc/locale/isdigit.3 b/lib/libc/locale/isdigit.3
new file mode 100644
index 0000000..a648ced
--- /dev/null
+++ b/lib/libc/locale/isdigit.3
@@ -0,0 +1,113 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)isdigit.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd May 4, 2007
+.Dt ISDIGIT 3
+.Os
+.Sh NAME
+.Nm isdigit, isnumber
+.Nd decimal-digit character test
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn isdigit "int c"
+.Ft int
+.Fn isnumber "int c"
+.Ft int
+.Fn isdigit_l "int c" "locale_t loc"
+.Ft int
+.Fn isnumber_l "int c" "locale_t loc"
+.Sh DESCRIPTION
+The
+.Fn isdigit
+function tests for a decimal digit character.
+Regardless of locale, this includes the following characters only:
+.Bl -column \&``0''______ \&``0''______ \&``0''______ \&``0''______ \&``0''______
+.It "\&``0''" Ta "``1''" Ta "``2''" Ta "``3''" Ta "``4''"
+.It "\&``5''" Ta "``6''" Ta "``7''" Ta "``8''" Ta "``9''"
+.El
+.Pp
+The
+.Fn isnumber
+function behaves similarly to
+.Fn isdigit ,
+but may recognize additional characters, depending on the current locale
+setting.
+.Pp
+The value of the argument must be representable as an
+.Vt "unsigned char"
+or the value of
+.Dv EOF .
+.Pp
+The _l-suffixed versions take an explicit locale argument, whereas the
+non-suffixed versions use the current global or per-thread locale.
+.Sh RETURN VALUES
+The
+.Fn isdigit
+and
+.Fn isnumber
+functions return zero if the character tests false and
+return non-zero if the character tests true.
+.Sh COMPATIBILITY
+The
+.Bx 4.4
+extension of accepting arguments outside of the range of the
+.Vt "unsigned char"
+type in locales with large character sets is considered obsolete
+and may not be supported in future releases.
+The
+.Fn iswdigit
+function should be used instead.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr iswdigit 3 ,
+.Xr multibyte 3 ,
+.Xr xlocale 3 ,
+.Xr ascii 7
+.Sh STANDARDS
+The
+.Fn isdigit
+function conforms to
+.St -isoC .
+The
+.Fn isdigit_l
+function conforms to
+.St -p1003.1-2008 .
+.Sh HISTORY
+The
+.Fn isnumber
+function appeared in
+.Bx 4.4 .
diff --git a/lib/libc/locale/isgraph.3 b/lib/libc/locale/isgraph.3
new file mode 100644
index 0000000..bedf31e
--- /dev/null
+++ b/lib/libc/locale/isgraph.3
@@ -0,0 +1,105 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)isgraph.3 8.2 (Berkeley) 12/11/93
+.\" $FreeBSD$
+.\"
+.Dd July 17, 2005
+.Dt ISGRAPH 3
+.Os
+.Sh NAME
+.Nm isgraph
+.Nd printing character test (space character exclusive)
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn isgraph "int c"
+.Sh DESCRIPTION
+The
+.Fn isgraph
+function tests for any printing character except space
+.Pq Ql "\~"
+and other
+locale-specific space-like characters.
+The value of the argument must be representable as an
+.Vt "unsigned char"
+or the value of
+.Dv EOF .
+.Pp
+In the ASCII character set, this includes the following characters
+(with their numeric values shown in octal):
+.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
+.It "\&041\ ``!''" Ta "042\ ``""''" Ta "043\ ``#''" Ta "044\ ``$''" Ta "045\ ``%''"
+.It "\&046\ ``&''" Ta "047\ ``'''" Ta "050\ ``(''" Ta "051\ ``)''" Ta "052\ ``*''"
+.It "\&053\ ``+''" Ta "054\ ``,''" Ta "055\ ``-''" Ta "056\ ``.''" Ta "057\ ``/''"
+.It "\&060\ ``0''" Ta "061\ ``1''" Ta "062\ ``2''" Ta "063\ ``3''" Ta "064\ ``4''"
+.It "\&065\ ``5''" Ta "066\ ``6''" Ta "067\ ``7''" Ta "070\ ``8''" Ta "071\ ``9''"
+.It "\&072\ ``:''" Ta "073\ ``;''" Ta "074\ ``<''" Ta "075\ ``=''" Ta "076\ ``>''"
+.It "\&077\ ``?''" Ta "100\ ``@''" Ta "101\ ``A''" Ta "102\ ``B''" Ta "103\ ``C''"
+.It "\&104\ ``D''" Ta "105\ ``E''" Ta "106\ ``F''" Ta "107\ ``G''" Ta "110\ ``H''"
+.It "\&111\ ``I''" Ta "112\ ``J''" Ta "113\ ``K''" Ta "114\ ``L''" Ta "115\ ``M''"
+.It "\&116\ ``N''" Ta "117\ ``O''" Ta "120\ ``P''" Ta "121\ ``Q''" Ta "122\ ``R''"
+.It "\&123\ ``S''" Ta "124\ ``T''" Ta "125\ ``U''" Ta "126\ ``V''" Ta "127\ ``W''"
+.It "\&130\ ``X''" Ta "131\ ``Y''" Ta "132\ ``Z''" Ta "133\ ``[''" Ta "134\ ``\e\|''"
+.It "\&135\ ``]''" Ta "136\ ``^''" Ta "137\ ``_''" Ta "140\ ```''" Ta "141\ ``a''"
+.It "\&142\ ``b''" Ta "143\ ``c''" Ta "144\ ``d''" Ta "145\ ``e''" Ta "146\ ``f''"
+.It "\&147\ ``g''" Ta "150\ ``h''" Ta "151\ ``i''" Ta "152\ ``j''" Ta "153\ ``k''"
+.It "\&154\ ``l''" Ta "155\ ``m''" Ta "156\ ``n''" Ta "157\ ``o''" Ta "160\ ``p''"
+.It "\&161\ ``q''" Ta "162\ ``r''" Ta "163\ ``s''" Ta "164\ ``t''" Ta "165\ ``u''"
+.It "\&166\ ``v''" Ta "167\ ``w''" Ta "170\ ``x''" Ta "171\ ``y''" Ta "172\ ``z''"
+.It "\&173\ ``{''" Ta "174\ ``|''" Ta "175\ ``}''" Ta "176\ ``~''" Ta \&
+.El
+.Sh RETURN VALUES
+The
+.Fn isgraph
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh COMPATIBILITY
+The
+.Bx 4.4
+extension of accepting arguments outside of the range of the
+.Vt "unsigned char"
+type in locales with large character sets is considered obsolete
+and may not be supported in future releases.
+The
+.Fn iswgraph
+function should be used instead.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr iswgraph 3 ,
+.Xr ascii 7
+.Sh STANDARDS
+The
+.Fn isgraph
+function conforms to
+.St -isoC .
diff --git a/lib/libc/locale/isideogram.3 b/lib/libc/locale/isideogram.3
new file mode 100644
index 0000000..cbaa625
--- /dev/null
+++ b/lib/libc/locale/isideogram.3
@@ -0,0 +1,57 @@
+.\"
+.\" Copyright (c) 2004 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 30, 2004
+.Dt ISIDEOGRAM 3
+.Os
+.Sh NAME
+.Nm isideogram
+.Nd ideographic character test
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn isideogram "int c"
+.Sh DESCRIPTION
+The
+.Fn isideogram
+function tests for an ideographic character.
+.Sh RETURN VALUES
+The
+.Fn isideogram
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr isphonogram 3 ,
+.Xr iswideogram 3
+.Sh HISTORY
+The
+.Fn isideogram
+function appeared in
+.Bx 4.4 .
diff --git a/lib/libc/locale/islower.3 b/lib/libc/locale/islower.3
new file mode 100644
index 0000000..987ff59
--- /dev/null
+++ b/lib/libc/locale/islower.3
@@ -0,0 +1,90 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)islower.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd July 17, 2005
+.Dt ISLOWER 3
+.Os
+.Sh NAME
+.Nm islower
+.Nd lower-case character test
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn islower "int c"
+.Sh DESCRIPTION
+The
+.Fn islower
+function tests for any lower-case letters.
+The value of the argument must be representable as an
+.Vt "unsigned char"
+or the value of
+.Dv EOF .
+.Pp
+In the ASCII character set, this includes the following characters
+(with their numeric values shown in octal):
+.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
+.It "\&141\ ``a''" Ta "142\ ``b''" Ta "143\ ``c''" Ta "144\ ``d''" Ta "145\ ``e''"
+.It "\&146\ ``f''" Ta "147\ ``g''" Ta "150\ ``h''" Ta "151\ ``i''" Ta "152\ ``j''"
+.It "\&153\ ``k''" Ta "154\ ``l''" Ta "155\ ``m''" Ta "156\ ``n''" Ta "157\ ``o''"
+.It "\&160\ ``p''" Ta "161\ ``q''" Ta "162\ ``r''" Ta "163\ ``s''" Ta "164\ ``t''"
+.It "\&165\ ``u''" Ta "166\ ``v''" Ta "167\ ``w''" Ta "170\ ``x''" Ta "171\ ``y''"
+.It "\&172\ ``z''" Ta \& Ta \& Ta \& Ta \&
+.El
+.Sh RETURN VALUES
+The
+.Fn islower
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh COMPATIBILITY
+The
+.Bx 4.4
+extension of accepting arguments outside of the range of the
+.Vt "unsigned char"
+type in locales with large character sets is considered obsolete
+and may not be supported in future releases.
+The
+.Fn iswlower
+function should be used instead.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr iswlower 3 ,
+.Xr tolower 3 ,
+.Xr ascii 7
+.Sh STANDARDS
+The
+.Fn islower
+function conforms to
+.St -isoC .
diff --git a/lib/libc/locale/isphonogram.3 b/lib/libc/locale/isphonogram.3
new file mode 100644
index 0000000..b0d82c4
--- /dev/null
+++ b/lib/libc/locale/isphonogram.3
@@ -0,0 +1,57 @@
+.\"
+.\" Copyright (c) 2004 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 30, 2004
+.Dt ISPHONOGRAM 3
+.Os
+.Sh NAME
+.Nm isphonogram
+.Nd phonographic character test
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn isphonogram "int c"
+.Sh DESCRIPTION
+The
+.Fn isphonogram
+function tests for a phonographic character.
+.Sh RETURN VALUES
+The
+.Fn isphonogram
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr isideogram 3 ,
+.Xr iswphonogram 3
+.Sh HISTORY
+The
+.Fn isphonogram
+function appeared in
+.Bx 4.4 .
diff --git a/lib/libc/locale/isprint.3 b/lib/libc/locale/isprint.3
new file mode 100644
index 0000000..e752c03
--- /dev/null
+++ b/lib/libc/locale/isprint.3
@@ -0,0 +1,103 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)isprint.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd July 17, 2005
+.Dt ISPRINT 3
+.Os
+.Sh NAME
+.Nm isprint
+.Nd printing character test (space character inclusive)
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn isprint "int c"
+.Sh DESCRIPTION
+The
+.Fn isprint
+function tests for any printing character, including space
+.Pq Ql "\ " .
+The value of the argument must be representable as an
+.Vt "unsigned char"
+or the value of
+.Dv EOF .
+.Pp
+In the ASCII character set, this includes the following characters
+(with their numeric values shown in octal):
+.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
+.It "\&040\ sp" Ta "041\ ``!''" Ta "042\ ``""''" Ta "043\ ``#''" Ta "044\ ``$''"
+.It "\&045\ ``%''" Ta "046\ ``&''" Ta "047\ ``'''" Ta "050\ ``(''" Ta "051\ ``)''"
+.It "\&052\ ``*''" Ta "053\ ``+''" Ta "054\ ``,''" Ta "055\ ``-''" Ta "056\ ``.''"
+.It "\&057\ ``/''" Ta "060\ ``0''" Ta "061\ ``1''" Ta "062\ ``2''" Ta "063\ ``3''"
+.It "\&064\ ``4''" Ta "065\ ``5''" Ta "066\ ``6''" Ta "067\ ``7''" Ta "070\ ``8''"
+.It "\&071\ ``9''" Ta "072\ ``:''" Ta "073\ ``;''" Ta "074\ ``<''" Ta "075\ ``=''"
+.It "\&076\ ``>''" Ta "077\ ``?''" Ta "100\ ``@''" Ta "101\ ``A''" Ta "102\ ``B''"
+.It "\&103\ ``C''" Ta "104\ ``D''" Ta "105\ ``E''" Ta "106\ ``F''" Ta "107\ ``G''"
+.It "\&110\ ``H''" Ta "111\ ``I''" Ta "112\ ``J''" Ta "113\ ``K''" Ta "114\ ``L''"
+.It "\&115\ ``M''" Ta "116\ ``N''" Ta "117\ ``O''" Ta "120\ ``P''" Ta "121\ ``Q''"
+.It "\&122\ ``R''" Ta "123\ ``S''" Ta "124\ ``T''" Ta "125\ ``U''" Ta "126\ ``V''"
+.It "\&127\ ``W''" Ta "130\ ``X''" Ta "131\ ``Y''" Ta "132\ ``Z''" Ta "133\ ``[''"
+.It "\&134\ ``\e\|''" Ta "135\ ``]''" Ta "136\ ``^''" Ta "137\ ``_''" Ta "140\ ```''"
+.It "\&141\ ``a''" Ta "142\ ``b''" Ta "143\ ``c''" Ta "144\ ``d''" Ta "145\ ``e''"
+.It "\&146\ ``f''" Ta "147\ ``g''" Ta "150\ ``h''" Ta "151\ ``i''" Ta "152\ ``j''"
+.It "\&153\ ``k''" Ta "154\ ``l''" Ta "155\ ``m''" Ta "156\ ``n''" Ta "157\ ``o''"
+.It "\&160\ ``p''" Ta "161\ ``q''" Ta "162\ ``r''" Ta "163\ ``s''" Ta "164\ ``t''"
+.It "\&165\ ``u''" Ta "166\ ``v''" Ta "167\ ``w''" Ta "170\ ``x''" Ta "171\ ``y''"
+.It "\&172\ ``z''" Ta "173\ ``{''" Ta "174\ ``|''" Ta "175\ ``}''" Ta "176\ ``~''"
+.El
+.Sh RETURN VALUES
+The
+.Fn isprint
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh COMPATIBILITY
+The
+.Bx 4.4
+extension of accepting arguments outside of the range of the
+.Vt "unsigned char"
+type in locales with large character sets is considered obsolete
+and may not be supported in future releases.
+The
+.Fn iswprint
+function should be used instead.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr iswprint 3 ,
+.Xr ascii 7
+.Sh STANDARDS
+The
+.Fn isprint
+function conforms to
+.St -isoC .
diff --git a/lib/libc/locale/ispunct.3 b/lib/libc/locale/ispunct.3
new file mode 100644
index 0000000..8fcfe54
--- /dev/null
+++ b/lib/libc/locale/ispunct.3
@@ -0,0 +1,95 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)ispunct.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd July 17, 2005
+.Dt ISPUNCT 3
+.Os
+.Sh NAME
+.Nm ispunct
+.Nd punctuation character test
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn ispunct "int c"
+.Sh DESCRIPTION
+The
+.Fn ispunct
+function tests for any printing character except for space
+.Pq Ql "\ "
+or a
+character for which
+.Xr isalnum 3
+is true.
+The value of the argument must be representable as an
+.Vt "unsigned char"
+or the value of
+.Dv EOF .
+.Pp
+In the ASCII character set, this includes the following characters
+(with their numeric values shown in octal):
+.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
+.It "\&041\ ``!''" Ta "042\ ``""''" Ta "043\ ``#''" Ta "044\ ``$''" Ta "045\ ``%''"
+.It "\&046\ ``&''" Ta "047\ ``'''" Ta "050\ ``(''" Ta "051\ ``)''" Ta "052\ ``*''"
+.It "\&053\ ``+''" Ta "054\ ``,''" Ta "055\ ``-''" Ta "056\ ``.''" Ta "057\ ``/''"
+.It "\&072\ ``:''" Ta "073\ ``;''" Ta "074\ ``<''" Ta "075\ ``=''" Ta "076\ ``>''"
+.It "\&077\ ``?''" Ta "100\ ``@''" Ta "133\ ``[''" Ta "134\ ``\e\|''" Ta "135\ ``]''"
+.It "\&136\ ``^''" Ta "137\ ``_''" Ta "140\ ```''" Ta "173\ ``{''" Ta "174\ ``|''"
+.It "\&175\ ``}''" Ta "176\ ``~''" Ta \& Ta \& Ta \&
+.El
+.Sh RETURN VALUES
+The
+.Fn ispunct
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh COMPATIBILITY
+The
+.Bx 4.4
+extension of accepting arguments outside of the range of the
+.Vt "unsigned char"
+type in locales with large character sets is considered obsolete
+and may not be supported in future releases.
+The
+.Fn iswpunct
+function should be used instead.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr iswpunct 3 ,
+.Xr ascii 7
+.Sh STANDARDS
+The
+.Fn ispunct
+function conforms to
+.St -isoC .
diff --git a/lib/libc/locale/isrune.3 b/lib/libc/locale/isrune.3
new file mode 100644
index 0000000..424c367
--- /dev/null
+++ b/lib/libc/locale/isrune.3
@@ -0,0 +1,63 @@
+.\"
+.\" Copyright (c) 2004 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 30, 2004
+.Dt ISRUNE 3
+.Os
+.Sh NAME
+.Nm isrune
+.Nd valid character test
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn isrune "int c"
+.Sh DESCRIPTION
+The
+.Fn isrune
+function tests for any character that is valid in the current
+character set.
+In the
+.Tn ASCII
+character set, this is equivalent to
+.Fn isascii .
+.Sh RETURN VALUES
+The
+.Fn isrune
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr isascii 3 ,
+.Xr iswrune 3 ,
+.Xr ascii 7
+.Sh HISTORY
+The
+.Fn isrune
+function appeared in
+.Bx 4.4 .
diff --git a/lib/libc/locale/isspace.3 b/lib/libc/locale/isspace.3
new file mode 100644
index 0000000..6dfeb5f
--- /dev/null
+++ b/lib/libc/locale/isspace.3
@@ -0,0 +1,87 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)isspace.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd July 17, 2005
+.Dt ISSPACE 3
+.Os
+.Sh NAME
+.Nm isspace
+.Nd white-space character test
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn isspace "int c"
+.Sh DESCRIPTION
+The
+.Fn isspace
+function tests for white-space characters.
+For any locale, this includes the following standard characters:
+.Bl -column \&`\et''___ \&``\et''___ \&``\et''___ \&``\et''___ \&``\et''___ \&``\et''___
+.It "\&``\et''" Ta "``\en''" Ta "``\ev''" Ta "``\ef''" Ta "``\er''" Ta "`` ''"
+.El
+.Pp
+In the "C" locale,
+.Fn isspace
+returns non-zero for these characters only.
+The value of the argument must be representable as an
+.Vt "unsigned char"
+or the value of
+.Dv EOF .
+.Sh RETURN VALUES
+The
+.Fn isspace
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh COMPATIBILITY
+The
+.Bx 4.4
+extension of accepting arguments outside of the range of the
+.Vt "unsigned char"
+type in locales with large character sets is considered obsolete
+and may not be supported in future releases.
+The
+.Fn iswspace
+function should be used instead.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr iswspace 3 ,
+.Xr multibyte 3 ,
+.Xr ascii 7
+.Sh STANDARDS
+The
+.Fn isspace
+function conforms to
+.St -isoC .
diff --git a/lib/libc/locale/isspecial.3 b/lib/libc/locale/isspecial.3
new file mode 100644
index 0000000..de361d2
--- /dev/null
+++ b/lib/libc/locale/isspecial.3
@@ -0,0 +1,56 @@
+.\"
+.\" Copyright (c) 2004 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 30, 2004
+.Dt ISSPECIAL 3
+.Os
+.Sh NAME
+.Nm isspecial
+.Nd special character test
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn isspecial "int c"
+.Sh DESCRIPTION
+The
+.Fn isspecial
+function tests for a special character.
+.Sh RETURN VALUES
+The
+.Fn isspecial
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr iswspecial 3
+.Sh HISTORY
+The
+.Fn isspecial
+function appeared in
+.Bx 4.4 .
diff --git a/lib/libc/locale/isupper.3 b/lib/libc/locale/isupper.3
new file mode 100644
index 0000000..570e076
--- /dev/null
+++ b/lib/libc/locale/isupper.3
@@ -0,0 +1,90 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)isupper.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd July 17, 2005
+.Dt ISUPPER 3
+.Os
+.Sh NAME
+.Nm isupper
+.Nd upper-case character test
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn isupper "int c"
+.Sh DESCRIPTION
+The
+.Fn isupper
+function tests for any upper-case letter.
+The value of the argument must be representable as an
+.Vt "unsigned char"
+or the value of
+.Dv EOF .
+.Pp
+In the ASCII character set, this includes the following characters
+(with their numeric values shown in octal):
+.Bl -column \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__ \&000_``0''__
+.It "\&101\ ``A''" Ta "102\ ``B''" Ta "103\ ``C''" Ta "104\ ``D''" Ta "105\ ``E''"
+.It "\&106\ ``F''" Ta "107\ ``G''" Ta "110\ ``H''" Ta "111\ ``I''" Ta "112\ ``J''"
+.It "\&113\ ``K''" Ta "114\ ``L''" Ta "115\ ``M''" Ta "116\ ``N''" Ta "117\ ``O''"
+.It "\&120\ ``P''" Ta "121\ ``Q''" Ta "122\ ``R''" Ta "123\ ``S''" Ta "124\ ``T''"
+.It "\&125\ ``U''" Ta "126\ ``V''" Ta "127\ ``W''" Ta "130\ ``X''" Ta "131\ ``Y''"
+.It "\&132\ ``Z''" Ta \& Ta \& Ta \& Ta \&
+.El
+.Sh RETURN VALUES
+The
+.Fn isupper
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh COMPATIBILITY
+The
+.Bx 4.4
+extension of accepting arguments outside of the range of the
+.Vt "unsigned char"
+type in locales with large character sets is considered obsolete
+and may not be supported in future releases.
+The
+.Fn iswupper
+function should be used instead.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr iswupper 3 ,
+.Xr toupper 3 ,
+.Xr ascii 7
+.Sh STANDARDS
+The
+.Fn isupper
+function conforms to
+.St -isoC .
diff --git a/lib/libc/locale/iswalnum.3 b/lib/libc/locale/iswalnum.3
new file mode 100644
index 0000000..8996097
--- /dev/null
+++ b/lib/libc/locale/iswalnum.3
@@ -0,0 +1,158 @@
+.\" $NetBSD: iswalnum.3,v 1.5 2002/07/10 14:46:10 yamt Exp $
+.\"
+.\" Copyright (c) 1991 The Regents of the University of California.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)isalnum.3 5.2 (Berkeley) 6/29/91
+.\" $FreeBSD$
+.\"
+.Dd October 3, 2002
+.Dt ISWALNUM 3
+.Os
+.Sh NAME
+.Nm iswalnum ,
+.Nm iswalpha ,
+.Nm iswascii ,
+.Nm iswblank ,
+.Nm iswcntrl ,
+.Nm iswdigit ,
+.Nm iswgraph ,
+.Nm iswhexnumber ,
+.Nm iswideogram ,
+.Nm iswlower ,
+.Nm iswnumber ,
+.Nm iswphonogram ,
+.Nm iswprint ,
+.Nm iswpunct ,
+.Nm iswrune ,
+.Nm iswspace ,
+.Nm iswspecial ,
+.Nm iswupper ,
+.Nm iswxdigit
+.Nd wide character classification utilities
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wctype.h
+.Ft int
+.Fn iswalnum "wint_t wc"
+.Ft int
+.Fn iswalpha "wint_t wc"
+.Ft int
+.Fn iswascii "wint_t wc"
+.Ft int
+.Fn iswblank "wint_t wc"
+.Ft int
+.Fn iswcntrl "wint_t wc"
+.Ft int
+.Fn iswdigit "wint_t wc"
+.Ft int
+.Fn iswgraph "wint_t wc"
+.Ft int
+.Fn iswhexnumber "wint_t wc"
+.Ft int
+.Fn iswideogram "wint_t wc"
+.Ft int
+.Fn iswlower "wint_t wc"
+.Ft int
+.Fn iswnumber "wint_t wc"
+.Ft int
+.Fn iswphonogram "wint_t wc"
+.Ft int
+.Fn iswprint "wint_t wc"
+.Ft int
+.Fn iswpunct "wint_t wc"
+.Ft int
+.Fn iswrune "wint_t wc"
+.Ft int
+.Fn iswspace "wint_t wc"
+.Ft int
+.Fn iswspecial "wint_t wc"
+.Ft int
+.Fn iswupper "wint_t wc"
+.Ft int
+.Fn iswxdigit "wint_t wc"
+.Sh DESCRIPTION
+The above functions are character classification utility functions,
+for use with wide characters
+.Vt ( wchar_t
+or
+.Vt wint_t ) .
+See the description for the similarly-named single byte classification
+functions (like
+.Xr isalnum 3 ) ,
+for details.
+.Sh RETURN VALUES
+The functions return zero if the character tests false and
+return non-zero if the character tests true.
+.Sh SEE ALSO
+.Xr isalnum 3 ,
+.Xr isalpha 3 ,
+.Xr isascii 3 ,
+.Xr isblank 3 ,
+.Xr iscntrl 3 ,
+.Xr isdigit 3 ,
+.Xr isgraph 3 ,
+.Xr ishexnumber 3 ,
+.Xr isideogram 3 ,
+.Xr islower 3 ,
+.Xr isnumber 3 ,
+.Xr isphonogram 3 ,
+.Xr isprint 3 ,
+.Xr ispunct 3 ,
+.Xr isrune 3 ,
+.Xr isspace 3 ,
+.Xr isspecial 3 ,
+.Xr isupper 3 ,
+.Xr isxdigit 3 ,
+.Xr wctype 3
+.Sh STANDARDS
+These functions conform to
+.St -p1003.1-2001 ,
+except
+.Fn iswascii ,
+.Fn iswhexnumber ,
+.Fn iswideogram ,
+.Fn iswnumber ,
+.Fn iswphonogram ,
+.Fn iswrune
+and
+.Fn iswspecial ,
+which are
+.Fx
+extensions.
+.Sh CAVEATS
+The result of these functions is undefined unless
+the argument is
+.Dv WEOF
+or a valid
+.Vt wchar_t
+value for the current locale.
diff --git a/lib/libc/locale/iswctype.c b/lib/libc/locale/iswctype.c
new file mode 100644
index 0000000..eaa1bf3
--- /dev/null
+++ b/lib/libc/locale/iswctype.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wctype.h>
+
+#undef iswalnum
+int
+iswalnum(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_A|_CTYPE_D));
+}
+
+#undef iswalpha
+int
+iswalpha(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_A));
+}
+
+#undef iswascii
+int
+iswascii(wc)
+ wint_t wc;
+{
+ return ((wc & ~0x7F) == 0);
+}
+
+#undef iswblank
+int
+iswblank(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_B));
+}
+
+#undef iswcntrl
+int
+iswcntrl(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_C));
+}
+
+#undef iswdigit
+int
+iswdigit(wc)
+ wint_t wc;
+{
+ return (__isctype(wc, _CTYPE_D));
+}
+
+#undef iswgraph
+int
+iswgraph(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_G));
+}
+
+#undef iswhexnumber
+int
+iswhexnumber(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_X));
+}
+
+#undef iswideogram
+int
+iswideogram(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_I));
+}
+
+#undef iswlower
+int
+iswlower(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_L));
+}
+
+#undef iswnumber
+int
+iswnumber(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_D));
+}
+
+#undef iswphonogram
+int
+iswphonogram(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_Q));
+}
+
+#undef iswprint
+int
+iswprint(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_R));
+}
+
+#undef iswpunct
+int
+iswpunct(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_P));
+}
+
+#undef iswrune
+int
+iswrune(wc)
+ wint_t wc;
+{
+ return (__istype(wc, 0xFFFFFF00L));
+}
+
+#undef iswspace
+int
+iswspace(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_S));
+}
+
+#undef iswspecial
+int
+iswspecial(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_T));
+}
+
+#undef iswupper
+int
+iswupper(wc)
+ wint_t wc;
+{
+ return (__istype(wc, _CTYPE_U));
+}
+
+#undef iswxdigit
+int
+iswxdigit(wc)
+ wint_t wc;
+{
+ return (__isctype(wc, _CTYPE_X));
+}
+
+#undef towlower
+wint_t
+towlower(wc)
+ wint_t wc;
+{
+ return (__tolower(wc));
+}
+
+#undef towupper
+wint_t
+towupper(wc)
+ wint_t wc;
+{
+ return (__toupper(wc));
+}
+
diff --git a/lib/libc/locale/isxdigit.3 b/lib/libc/locale/isxdigit.3
new file mode 100644
index 0000000..eb9f8d5
--- /dev/null
+++ b/lib/libc/locale/isxdigit.3
@@ -0,0 +1,101 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)isxdigit.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd July 17, 2005
+.Dt ISXDIGIT 3
+.Os
+.Sh NAME
+.Nm isxdigit, ishexnumber
+.Nd hexadecimal-digit character test
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn isxdigit "int c"
+.Ft int
+.Fn ishexnumber "int c"
+.Sh DESCRIPTION
+The
+.Fn isxdigit
+function tests for any hexadecimal-digit character.
+Regardless of locale, this includes the following characters only:
+.Bl -column \&``0''______ \&``0''______ \&``0''______ \&``0''______ \&``0''______
+.It "\&``0''" Ta "``1''" Ta "``2''" Ta "``3''" Ta "``4''"
+.It "\&``5''" Ta "``6''" Ta "``7''" Ta "``8''" Ta "``9''"
+.It "\&``A''" Ta "``B''" Ta "``C''" Ta "``D''" Ta "``E''"
+.It "\&``F''" Ta "``a''" Ta "``b''" Ta "``c''" Ta "``d''"
+.It "\&``e''" Ta "``f''" Ta \& Ta \& Ta \&
+.El
+.Pp
+The
+.Fn ishexnumber
+function behaves similarly to
+.Fn isxdigit ,
+but may recognize additional characters,
+depending on the current locale setting.
+.Pp
+The value of the argument must be representable as an
+.Vt "unsigned char"
+or the value of
+.Dv EOF .
+.Sh RETURN VALUES
+The
+.Fn isxdigit
+function returns zero if the character tests false and
+returns non-zero if the character tests true.
+.Sh COMPATIBILITY
+The
+.Bx 4.4
+extension of accepting arguments outside of the range of the
+.Vt "unsigned char"
+type in locales with large character sets is considered obsolete
+and may not be supported in future releases.
+The
+.Fn iswxdigit
+function should be used instead.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr iswxdigit 3 ,
+.Xr ascii 7
+.Sh STANDARDS
+The
+.Fn isxdigit
+function conforms to
+.St -isoC .
+.Sh HISTORY
+The
+.Fn ishexnumber
+function appeared in
+.Bx 4.4 .
diff --git a/lib/libc/locale/ldpart.c b/lib/libc/locale/ldpart.c
new file mode 100644
index 0000000..ea7b388
--- /dev/null
+++ b/lib/libc/locale/ldpart.c
@@ -0,0 +1,166 @@
+/*
+ * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "ldpart.h"
+#include "setlocale.h"
+
+static int split_lines(char *, const char *);
+
+int
+__part_load_locale(const char *name,
+ int *using_locale,
+ char **locale_buf,
+ const char *category_filename,
+ int locale_buf_size_max,
+ int locale_buf_size_min,
+ const char **dst_localebuf)
+{
+ int saverr, fd, i, num_lines;
+ char *lbuf, *p;
+ const char *plim;
+ char filename[PATH_MAX];
+ struct stat st;
+ size_t namesize, bufsize;
+
+ /* 'name' must be already checked. */
+ if (strcmp(name, "C") == 0 || strcmp(name, "POSIX") == 0) {
+ *using_locale = 0;
+ return (_LDP_CACHE);
+ }
+
+ /*
+ * If the locale name is the same as our cache, use the cache.
+ */
+ if (*locale_buf != NULL && strcmp(name, *locale_buf) == 0) {
+ *using_locale = 1;
+ return (_LDP_CACHE);
+ }
+
+ /*
+ * Slurp the locale file into the cache.
+ */
+ namesize = strlen(name) + 1;
+
+ /* 'PathLocale' must be already set & checked. */
+
+ /* Range checking not needed, 'name' size is limited */
+ strcpy(filename, _PathLocale);
+ strcat(filename, "/");
+ strcat(filename, name);
+ strcat(filename, "/");
+ strcat(filename, category_filename);
+ if ((fd = _open(filename, O_RDONLY)) < 0)
+ return (_LDP_ERROR);
+ if (_fstat(fd, &st) != 0)
+ goto bad_locale;
+ if (st.st_size <= 0) {
+ errno = EFTYPE;
+ goto bad_locale;
+ }
+ bufsize = namesize + st.st_size;
+ if ((lbuf = malloc(bufsize)) == NULL) {
+ errno = ENOMEM;
+ goto bad_locale;
+ }
+ (void)strcpy(lbuf, name);
+ p = lbuf + namesize;
+ plim = p + st.st_size;
+ if (_read(fd, p, (size_t) st.st_size) != st.st_size)
+ goto bad_lbuf;
+ /*
+ * Parse the locale file into localebuf.
+ */
+ if (plim[-1] != '\n') {
+ errno = EFTYPE;
+ goto bad_lbuf;
+ }
+ num_lines = split_lines(p, plim);
+ if (num_lines >= locale_buf_size_max)
+ num_lines = locale_buf_size_max;
+ else if (num_lines >= locale_buf_size_min)
+ num_lines = locale_buf_size_min;
+ else {
+ errno = EFTYPE;
+ goto bad_lbuf;
+ }
+ (void)_close(fd);
+ /*
+ * Record the successful parse in the cache.
+ */
+ if (*locale_buf != NULL)
+ free(*locale_buf);
+ *locale_buf = lbuf;
+ for (p = *locale_buf, i = 0; i < num_lines; i++)
+ dst_localebuf[i] = (p += strlen(p) + 1);
+ for (i = num_lines; i < locale_buf_size_max; i++)
+ dst_localebuf[i] = NULL;
+ *using_locale = 1;
+
+ return (_LDP_LOADED);
+
+bad_lbuf:
+ saverr = errno;
+ free(lbuf);
+ errno = saverr;
+bad_locale:
+ saverr = errno;
+ (void)_close(fd);
+ errno = saverr;
+
+ return (_LDP_ERROR);
+}
+
+static int
+split_lines(char *p, const char *plim)
+{
+ int i;
+
+ i = 0;
+ while (p < plim) {
+ if (*p == '\n') {
+ *p = '\0';
+ i++;
+ }
+ p++;
+ }
+ return (i);
+}
+
diff --git a/lib/libc/locale/ldpart.h b/lib/libc/locale/ldpart.h
new file mode 100644
index 0000000..45f7339
--- /dev/null
+++ b/lib/libc/locale/ldpart.h
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LDPART_H_
+#define _LDPART_H_
+
+#define _LDP_LOADED 0
+#define _LDP_ERROR (-1)
+#define _LDP_CACHE 1
+
+int __part_load_locale(const char *, int*, char **, const char *,
+ int, int, const char **);
+
+#endif /* !_LDPART_H_ */
diff --git a/lib/libc/locale/lmessages.c b/lib/libc/locale/lmessages.c
new file mode 100644
index 0000000..a0664d0
--- /dev/null
+++ b/lib/libc/locale/lmessages.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stddef.h>
+
+#include "ldpart.h"
+#include "lmessages.h"
+
+#define LCMESSAGES_SIZE_FULL (sizeof(struct lc_messages_T) / sizeof(char *))
+#define LCMESSAGES_SIZE_MIN \
+ (offsetof(struct lc_messages_T, yesstr) / sizeof(char *))
+
+struct xlocale_messages {
+ struct xlocale_component header;
+ char *buffer;
+ struct lc_messages_T locale;
+};
+
+struct xlocale_messages __xlocale_global_messages;
+
+static char empty[] = "";
+
+static const struct lc_messages_T _C_messages_locale = {
+ "^[yY]" , /* yesexpr */
+ "^[nN]" , /* noexpr */
+ "yes" , /* yesstr */
+ "no" /* nostr */
+};
+
+static void destruct_messages(void *v)
+{
+ struct xlocale_messages *l = v;
+ if (l->buffer)
+ free(l->buffer);
+ free(l);
+}
+
+static int
+messages_load_locale(struct xlocale_messages *loc, int *using_locale, const char *name)
+{
+ int ret;
+ struct lc_messages_T *l = &loc->locale;
+
+ ret = __part_load_locale(name, using_locale,
+ &loc->buffer, "LC_MESSAGES",
+ LCMESSAGES_SIZE_FULL, LCMESSAGES_SIZE_MIN,
+ (const char **)l);
+ if (ret == _LDP_LOADED) {
+ if (l->yesstr == NULL)
+ l->yesstr = empty;
+ if (l->nostr == NULL)
+ l->nostr = empty;
+ }
+ return (ret);
+}
+int
+__messages_load_locale(const char *name)
+{
+ return messages_load_locale(&__xlocale_global_messages,
+ &__xlocale_global_locale.using_messages_locale, name);
+}
+void *
+__messages_load(const char *name, locale_t l)
+{
+ struct xlocale_messages *new = calloc(sizeof(struct xlocale_messages), 1);
+ new->header.header.destructor = destruct_messages;
+ if (messages_load_locale(new, &l->using_messages_locale, name) == _LDP_ERROR) {
+ xlocale_release(new);
+ return NULL;
+ }
+ return new;
+}
+
+struct lc_messages_T *
+__get_current_messages_locale(locale_t loc)
+{
+ return (loc->using_messages_locale
+ ? &((struct xlocale_messages *)loc->components[XLC_MESSAGES])->locale
+ : (struct lc_messages_T *)&_C_messages_locale);
+}
+
+#ifdef LOCALE_DEBUG
+void
+msgdebug() {
+printf( "yesexpr = %s\n"
+ "noexpr = %s\n"
+ "yesstr = %s\n"
+ "nostr = %s\n",
+ _messages_locale.yesexpr,
+ _messages_locale.noexpr,
+ _messages_locale.yesstr,
+ _messages_locale.nostr
+);
+}
+#endif /* LOCALE_DEBUG */
diff --git a/lib/libc/locale/lmessages.h b/lib/libc/locale/lmessages.h
new file mode 100644
index 0000000..ea9c57e
--- /dev/null
+++ b/lib/libc/locale/lmessages.h
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LMESSAGES_H_
+#define _LMESSAGES_H_
+
+#include "xlocale_private.h"
+
+struct lc_messages_T {
+ const char *yesexpr;
+ const char *noexpr;
+ const char *yesstr;
+ const char *nostr;
+};
+
+struct lc_messages_T *__get_current_messages_locale(locale_t);
+int __messages_load_locale(const char *);
+
+#endif /* !_LMESSAGES_H_ */
diff --git a/lib/libc/locale/lmonetary.c b/lib/libc/locale/lmonetary.c
new file mode 100644
index 0000000..a9d67d3
--- /dev/null
+++ b/lib/libc/locale/lmonetary.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+#include "ldpart.h"
+#include "lmonetary.h"
+
+extern const char * __fix_locale_grouping_str(const char *);
+
+#define LCMONETARY_SIZE_FULL (sizeof(struct lc_monetary_T) / sizeof(char *))
+#define LCMONETARY_SIZE_MIN \
+ (offsetof(struct lc_monetary_T, int_p_cs_precedes) / \
+ sizeof(char *))
+
+static char empty[] = "";
+static char numempty[] = { CHAR_MAX, '\0'};
+
+static const struct lc_monetary_T _C_monetary_locale = {
+ empty, /* int_curr_symbol */
+ empty, /* currency_symbol */
+ empty, /* mon_decimal_point */
+ empty, /* mon_thousands_sep */
+ numempty, /* mon_grouping */
+ empty, /* positive_sign */
+ empty, /* negative_sign */
+ numempty, /* int_frac_digits */
+ numempty, /* frac_digits */
+ numempty, /* p_cs_precedes */
+ numempty, /* p_sep_by_space */
+ numempty, /* n_cs_precedes */
+ numempty, /* n_sep_by_space */
+ numempty, /* p_sign_posn */
+ numempty, /* n_sign_posn */
+ numempty, /* int_p_cs_precedes */
+ numempty, /* int_n_cs_precedes */
+ numempty, /* int_p_sep_by_space */
+ numempty, /* int_n_sep_by_space */
+ numempty, /* int_p_sign_posn */
+ numempty /* int_n_sign_posn */
+};
+
+struct xlocale_monetary __xlocale_global_monetary;
+
+static char
+cnv(const char *str)
+{
+ int i = strtol(str, NULL, 10);
+
+ if (i == -1)
+ i = CHAR_MAX;
+ return ((char)i);
+}
+
+static void
+destruct_monetary(void *v)
+{
+ struct xlocale_monetary *l = v;
+ if (l->buffer)
+ free(l->buffer);
+ free(l);
+}
+
+static int
+monetary_load_locale_l(struct xlocale_monetary *loc, int *using_locale,
+ int *changed, const char *name)
+{
+ int ret;
+ struct lc_monetary_T *l = &loc->locale;
+
+ ret = __part_load_locale(name, using_locale,
+ &loc->buffer, "LC_MONETARY",
+ LCMONETARY_SIZE_FULL, LCMONETARY_SIZE_MIN,
+ (const char **)l);
+ if (ret != _LDP_ERROR)
+ *changed = 1;
+ if (ret == _LDP_LOADED) {
+ l->mon_grouping =
+ __fix_locale_grouping_str(l->mon_grouping);
+
+#define M_ASSIGN_CHAR(NAME) (((char *)l->NAME)[0] = \
+ cnv(l->NAME))
+
+ M_ASSIGN_CHAR(int_frac_digits);
+ M_ASSIGN_CHAR(frac_digits);
+ M_ASSIGN_CHAR(p_cs_precedes);
+ M_ASSIGN_CHAR(p_sep_by_space);
+ M_ASSIGN_CHAR(n_cs_precedes);
+ M_ASSIGN_CHAR(n_sep_by_space);
+ M_ASSIGN_CHAR(p_sign_posn);
+ M_ASSIGN_CHAR(n_sign_posn);
+
+ /*
+ * The six additional C99 international monetary formatting
+ * parameters default to the national parameters when
+ * reading FreeBSD LC_MONETARY data files.
+ */
+#define M_ASSIGN_ICHAR(NAME) \
+ do { \
+ if (l->int_##NAME == NULL) \
+ l->int_##NAME = \
+ l->NAME; \
+ else \
+ M_ASSIGN_CHAR(int_##NAME); \
+ } while (0)
+
+ M_ASSIGN_ICHAR(p_cs_precedes);
+ M_ASSIGN_ICHAR(n_cs_precedes);
+ M_ASSIGN_ICHAR(p_sep_by_space);
+ M_ASSIGN_ICHAR(n_sep_by_space);
+ M_ASSIGN_ICHAR(p_sign_posn);
+ M_ASSIGN_ICHAR(n_sign_posn);
+ }
+ return (ret);
+}
+int
+__monetary_load_locale(const char *name)
+{
+ return monetary_load_locale_l(&__xlocale_global_monetary,
+ &__xlocale_global_locale.using_monetary_locale,
+ &__xlocale_global_locale.monetary_locale_changed, name);
+}
+void* __monetary_load(const char *name, locale_t l)
+{
+ struct xlocale_monetary *new = calloc(sizeof(struct xlocale_monetary), 1);
+ new->header.header.destructor = destruct_monetary;
+ if (monetary_load_locale_l(new, &l->using_monetary_locale,
+ &l->monetary_locale_changed, name) == _LDP_ERROR)
+ {
+ xlocale_release(new);
+ return NULL;
+ }
+ return new;
+}
+
+
+struct lc_monetary_T *
+__get_current_monetary_locale(locale_t loc)
+{
+ return (loc->using_monetary_locale
+ ? &((struct xlocale_monetary*)loc->components[XLC_MONETARY])->locale
+ : (struct lc_monetary_T *)&_C_monetary_locale);
+}
+
+#ifdef LOCALE_DEBUG
+void
+monetdebug() {
+printf( "int_curr_symbol = %s\n"
+ "currency_symbol = %s\n"
+ "mon_decimal_point = %s\n"
+ "mon_thousands_sep = %s\n"
+ "mon_grouping = %s\n"
+ "positive_sign = %s\n"
+ "negative_sign = %s\n"
+ "int_frac_digits = %d\n"
+ "frac_digits = %d\n"
+ "p_cs_precedes = %d\n"
+ "p_sep_by_space = %d\n"
+ "n_cs_precedes = %d\n"
+ "n_sep_by_space = %d\n"
+ "p_sign_posn = %d\n"
+ "n_sign_posn = %d\n",
+ "int_p_cs_precedes = %d\n"
+ "int_p_sep_by_space = %d\n"
+ "int_n_cs_precedes = %d\n"
+ "int_n_sep_by_space = %d\n"
+ "int_p_sign_posn = %d\n"
+ "int_n_sign_posn = %d\n",
+ _monetary_locale.int_curr_symbol,
+ _monetary_locale.currency_symbol,
+ _monetary_locale.mon_decimal_point,
+ _monetary_locale.mon_thousands_sep,
+ _monetary_locale.mon_grouping,
+ _monetary_locale.positive_sign,
+ _monetary_locale.negative_sign,
+ _monetary_locale.int_frac_digits[0],
+ _monetary_locale.frac_digits[0],
+ _monetary_locale.p_cs_precedes[0],
+ _monetary_locale.p_sep_by_space[0],
+ _monetary_locale.n_cs_precedes[0],
+ _monetary_locale.n_sep_by_space[0],
+ _monetary_locale.p_sign_posn[0],
+ _monetary_locale.n_sign_posn[0],
+ _monetary_locale.int_p_cs_precedes[0],
+ _monetary_locale.int_p_sep_by_space[0],
+ _monetary_locale.int_n_cs_precedes[0],
+ _monetary_locale.int_n_sep_by_space[0],
+ _monetary_locale.int_p_sign_posn[0],
+ _monetary_locale.int_n_sign_posn[0]
+);
+}
+#endif /* LOCALE_DEBUG */
diff --git a/lib/libc/locale/lmonetary.h b/lib/libc/locale/lmonetary.h
new file mode 100644
index 0000000..b606862
--- /dev/null
+++ b/lib/libc/locale/lmonetary.h
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LMONETARY_H_
+#define _LMONETARY_H_
+#include "xlocale_private.h"
+
+struct lc_monetary_T {
+ const char *int_curr_symbol;
+ const char *currency_symbol;
+ const char *mon_decimal_point;
+ const char *mon_thousands_sep;
+ const char *mon_grouping;
+ const char *positive_sign;
+ const char *negative_sign;
+ const char *int_frac_digits;
+ const char *frac_digits;
+ const char *p_cs_precedes;
+ const char *p_sep_by_space;
+ const char *n_cs_precedes;
+ const char *n_sep_by_space;
+ const char *p_sign_posn;
+ const char *n_sign_posn;
+ const char *int_p_cs_precedes;
+ const char *int_n_cs_precedes;
+ const char *int_p_sep_by_space;
+ const char *int_n_sep_by_space;
+ const char *int_p_sign_posn;
+ const char *int_n_sign_posn;
+};
+struct xlocale_monetary {
+ struct xlocale_component header;
+ char *buffer;
+ struct lc_monetary_T locale;
+};
+
+struct lc_monetary_T *__get_current_monetary_locale(locale_t loc);
+int __monetary_load_locale(const char *);
+
+#endif /* !_LMONETARY_H_ */
diff --git a/lib/libc/locale/lnumeric.c b/lib/libc/locale/lnumeric.c
new file mode 100644
index 0000000..a2468f4
--- /dev/null
+++ b/lib/libc/locale/lnumeric.c
@@ -0,0 +1,127 @@
+/*
+ * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+
+#include "ldpart.h"
+#include "lnumeric.h"
+
+extern const char *__fix_locale_grouping_str(const char *);
+
+#define LCNUMERIC_SIZE (sizeof(struct lc_numeric_T) / sizeof(char *))
+
+static char numempty[] = { CHAR_MAX, '\0' };
+
+static const struct lc_numeric_T _C_numeric_locale = {
+ ".", /* decimal_point */
+ "", /* thousands_sep */
+ numempty /* grouping */
+};
+
+static void
+destruct_numeric(void *v)
+{
+ struct xlocale_numeric *l = v;
+ if (l->buffer)
+ free(l->buffer);
+ free(l);
+}
+
+struct xlocale_numeric __xlocale_global_numeric;
+
+static int
+numeric_load_locale(struct xlocale_numeric *loc, int *using_locale, int *changed,
+ const char *name)
+{
+ int ret;
+ struct lc_numeric_T *l = &loc->locale;
+
+ ret = __part_load_locale(name, using_locale,
+ &loc->buffer, "LC_NUMERIC",
+ LCNUMERIC_SIZE, LCNUMERIC_SIZE,
+ (const char**)l);
+ if (ret != _LDP_ERROR)
+ *changed= 1;
+ if (ret == _LDP_LOADED) {
+ /* Can't be empty according to C99 */
+ if (*l->decimal_point == '\0')
+ l->decimal_point =
+ _C_numeric_locale.decimal_point;
+ l->grouping =
+ __fix_locale_grouping_str(l->grouping);
+ }
+ return (ret);
+}
+
+int
+__numeric_load_locale(const char *name)
+{
+ return numeric_load_locale(&__xlocale_global_numeric,
+ &__xlocale_global_locale.using_numeric_locale,
+ &__xlocale_global_locale.numeric_locale_changed, name);
+}
+void *
+__numeric_load(const char *name, locale_t l)
+{
+ struct xlocale_numeric *new = calloc(sizeof(struct xlocale_numeric), 1);
+ new->header.header.destructor = destruct_numeric;
+ if (numeric_load_locale(new, &l->using_numeric_locale,
+ &l->numeric_locale_changed, name) == _LDP_ERROR)
+ {
+ xlocale_release(new);
+ return NULL;
+ }
+ return new;
+}
+
+struct lc_numeric_T *
+__get_current_numeric_locale(locale_t loc)
+{
+ return (loc->using_numeric_locale
+ ? &((struct xlocale_numeric *)loc->components[XLC_NUMERIC])->locale
+ : (struct lc_numeric_T *)&_C_numeric_locale);
+}
+
+#ifdef LOCALE_DEBUG
+void
+numericdebug(void) {
+printf( "decimal_point = %s\n"
+ "thousands_sep = %s\n"
+ "grouping = %s\n",
+ _numeric_locale.decimal_point,
+ _numeric_locale.thousands_sep,
+ _numeric_locale.grouping
+);
+}
+#endif /* LOCALE_DEBUG */
diff --git a/lib/libc/locale/lnumeric.h b/lib/libc/locale/lnumeric.h
new file mode 100644
index 0000000..5088dd4
--- /dev/null
+++ b/lib/libc/locale/lnumeric.h
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2000, 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LNUMERIC_H_
+#define _LNUMERIC_H_
+#include "xlocale_private.h"
+
+struct lc_numeric_T {
+ const char *decimal_point;
+ const char *thousands_sep;
+ const char *grouping;
+};
+struct xlocale_numeric {
+ struct xlocale_component header;
+ char *buffer;
+ struct lc_numeric_T locale;
+};
+
+struct lc_numeric_T *__get_current_numeric_locale(locale_t loc);
+int __numeric_load_locale(const char *);
+
+#endif /* !_LNUMERIC_H_ */
diff --git a/lib/libc/locale/localeconv.3 b/lib/libc/locale/localeconv.3
new file mode 100644
index 0000000..c831bf5
--- /dev/null
+++ b/lib/libc/locale/localeconv.3
@@ -0,0 +1,237 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Donn Seeley at BSDI.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From @(#)setlocale.3 8.1 (Berkeley) 6/9/93
+.\" From FreeBSD: src/lib/libc/locale/setlocale.3,v 1.28 2003/11/15 02:26:04 tjr Exp
+.\" $FreeBSD$
+.\"
+.Dd November 21, 2003
+.Dt LOCALECONV 3
+.Os
+.Sh NAME
+.Nm localeconv
+.Nd natural language formatting for C
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In locale.h
+.Ft struct lconv *
+.Fn localeconv "void"
+.In xlocale.h
+.Ft struct lconv *
+.Fn localeconv_l "locale_t locale"
+.Sh DESCRIPTION
+The
+.Fn localeconv
+function returns a pointer to a structure
+which provides parameters for formatting numbers,
+especially currency values:
+.Bd -literal -offset indent
+struct lconv {
+ char *decimal_point;
+ char *thousands_sep;
+ char *grouping;
+ char *int_curr_symbol;
+ char *currency_symbol;
+ char *mon_decimal_point;
+ char *mon_thousands_sep;
+ char *mon_grouping;
+ char *positive_sign;
+ char *negative_sign;
+ char int_frac_digits;
+ char frac_digits;
+ char p_cs_precedes;
+ char p_sep_by_space;
+ char n_cs_precedes;
+ char n_sep_by_space;
+ char p_sign_posn;
+ char n_sign_posn;
+ char int_p_cs_precedes;
+ char int_n_cs_precedes;
+ char int_p_sep_by_space;
+ char int_n_sep_by_space;
+ char int_p_sign_posn;
+ char int_n_sign_posn;
+};
+.Ed
+.Pp
+The individual fields have the following meanings:
+.Bl -tag -width mon_decimal_point
+.It Va decimal_point
+The decimal point character, except for currency values,
+cannot be an empty string.
+.It Va thousands_sep
+The separator between groups of digits
+before the decimal point, except for currency values.
+.It Va grouping
+The sizes of the groups of digits, except for currency values.
+This is a pointer to a vector of integers, each of size
+.Vt char ,
+representing group size from low order digit groups
+to high order (right to left).
+The list may be terminated with 0 or
+.Dv CHAR_MAX .
+If the list is terminated with 0,
+the last group size before the 0 is repeated to account for all the digits.
+If the list is terminated with
+.Dv CHAR_MAX ,
+no more grouping is performed.
+.It Va int_curr_symbol
+The standardized international currency symbol.
+.It Va currency_symbol
+The local currency symbol.
+.It Va mon_decimal_point
+The decimal point character for currency values.
+.It Va mon_thousands_sep
+The separator for digit groups in currency values.
+.It Va mon_grouping
+Like
+.Va grouping
+but for currency values.
+.It Va positive_sign
+The character used to denote nonnegative currency values,
+usually the empty string.
+.It Va negative_sign
+The character used to denote negative currency values,
+usually a minus sign.
+.It Va int_frac_digits
+The number of digits after the decimal point
+in an international-style currency value.
+.It Va frac_digits
+The number of digits after the decimal point
+in the local style for currency values.
+.It Va p_cs_precedes
+1 if the currency symbol precedes the currency value
+for nonnegative values, 0 if it follows.
+.It Va p_sep_by_space
+1 if a space is inserted between the currency symbol
+and the currency value for nonnegative values, 0 otherwise.
+.It Va n_cs_precedes
+Like
+.Va p_cs_precedes
+but for negative values.
+.It Va n_sep_by_space
+Like
+.Va p_sep_by_space
+but for negative values.
+.It Va p_sign_posn
+The location of the
+.Va positive_sign
+with respect to a nonnegative quantity and the
+.Va currency_symbol ,
+coded as follows:
+.Pp
+.Bl -tag -width 3n -compact
+.It Li 0
+Parentheses around the entire string.
+.It Li 1
+Before the string.
+.It Li 2
+After the string.
+.It Li 3
+Just before
+.Va currency_symbol .
+.It Li 4
+Just after
+.Va currency_symbol .
+.El
+.It Va n_sign_posn
+Like
+.Va p_sign_posn
+but for negative currency values.
+.It Va int_p_cs_precedes
+Same as
+.Va p_cs_precedes ,
+but for internationally formatted monetary quantities.
+.It Va int_n_cs_precedes
+Same as
+.Va n_cs_precedes ,
+but for internationally formatted monetary quantities.
+.It Va int_p_sep_by_space
+Same as
+.Va p_sep_by_space ,
+but for internationally formatted monetary quantities.
+.It Va int_n_sep_by_space
+Same as
+.Va n_sep_by_space ,
+but for internationally formatted monetary quantities.
+.It Va int_p_sign_posn
+Same as
+.Va p_sign_posn ,
+but for internationally formatted monetary quantities.
+.It Va int_n_sign_posn
+Same as
+.Va n_sign_posn ,
+but for internationally formatted monetary quantities.
+.El
+.Pp
+Unless mentioned above,
+an empty string as a value for a field
+indicates a zero length result or
+a value that is not in the current locale.
+A
+.Dv CHAR_MAX
+result similarly denotes an unavailable value.
+.Pp
+The
+.Fn localeconv_l
+function takes an explicit locale parameter. For more information, see
+.Xr xlocale 3 .
+.Sh RETURN VALUES
+The
+.Fn localeconv
+function returns a pointer to a static object
+which may be altered by later calls to
+.Xr setlocale 3
+or
+.Fn localeconv .
+The return value for
+.Fn localeconv_l
+is stored with the locale.
+It will remain valid until a subsequent call to
+.Xr freelocale 3 .
+If a thread-local locale is in effect then the return value from
+.Fn localeconv
+will remain valid until the locale is destroyed.
+.Sh ERRORS
+No errors are defined.
+.Sh SEE ALSO
+.Xr setlocale 3 ,
+.Xr strfmon 3
+.Sh STANDARDS
+The
+.Fn localeconv
+function conforms to
+.St -isoC-99 .
+.Sh HISTORY
+The
+.Fn localeconv
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/locale/localeconv.c b/lib/libc/locale/localeconv.c
new file mode 100644
index 0000000..4b19160
--- /dev/null
+++ b/lib/libc/locale/localeconv.c
@@ -0,0 +1,117 @@
+/*
+ * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)localeconv.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <locale.h>
+
+#include "lmonetary.h"
+#include "lnumeric.h"
+
+/*
+ * The localeconv() function constructs a struct lconv from the current
+ * monetary and numeric locales.
+ *
+ * Because localeconv() may be called many times (especially by library
+ * routines like printf() & strtod()), the approprate members of the
+ * lconv structure are computed only when the monetary or numeric
+ * locale has been changed.
+ */
+
+/*
+ * Return the current locale conversion.
+ */
+struct lconv *
+localeconv_l(locale_t loc)
+{
+ FIX_LOCALE(loc);
+ struct lconv *ret = &loc->lconv;
+
+ if (loc->monetary_locale_changed) {
+ /* LC_MONETARY part */
+ struct lc_monetary_T * mptr;
+
+#define M_ASSIGN_STR(NAME) (ret->NAME = (char*)mptr->NAME)
+#define M_ASSIGN_CHAR(NAME) (ret->NAME = mptr->NAME[0])
+
+ mptr = __get_current_monetary_locale(loc);
+ M_ASSIGN_STR(int_curr_symbol);
+ M_ASSIGN_STR(currency_symbol);
+ M_ASSIGN_STR(mon_decimal_point);
+ M_ASSIGN_STR(mon_thousands_sep);
+ M_ASSIGN_STR(mon_grouping);
+ M_ASSIGN_STR(positive_sign);
+ M_ASSIGN_STR(negative_sign);
+ M_ASSIGN_CHAR(int_frac_digits);
+ M_ASSIGN_CHAR(frac_digits);
+ M_ASSIGN_CHAR(p_cs_precedes);
+ M_ASSIGN_CHAR(p_sep_by_space);
+ M_ASSIGN_CHAR(n_cs_precedes);
+ M_ASSIGN_CHAR(n_sep_by_space);
+ M_ASSIGN_CHAR(p_sign_posn);
+ M_ASSIGN_CHAR(n_sign_posn);
+ M_ASSIGN_CHAR(int_p_cs_precedes);
+ M_ASSIGN_CHAR(int_n_cs_precedes);
+ M_ASSIGN_CHAR(int_p_sep_by_space);
+ M_ASSIGN_CHAR(int_n_sep_by_space);
+ M_ASSIGN_CHAR(int_p_sign_posn);
+ M_ASSIGN_CHAR(int_n_sign_posn);
+ loc->monetary_locale_changed = 0;
+ }
+
+ if (loc->numeric_locale_changed) {
+ /* LC_NUMERIC part */
+ struct lc_numeric_T * nptr;
+
+#define N_ASSIGN_STR(NAME) (ret->NAME = (char*)nptr->NAME)
+
+ nptr = __get_current_numeric_locale(loc);
+ N_ASSIGN_STR(decimal_point);
+ N_ASSIGN_STR(thousands_sep);
+ N_ASSIGN_STR(grouping);
+ loc->numeric_locale_changed = 0;
+ }
+
+ return ret;
+}
+struct lconv *
+localeconv(void)
+{
+ return localeconv_l(__get_locale());
+}
diff --git a/lib/libc/locale/mblen.3 b/lib/libc/locale/mblen.3
new file mode 100644
index 0000000..f142f39
--- /dev/null
+++ b/lib/libc/locale/mblen.3
@@ -0,0 +1,106 @@
+.\" Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Donn Seeley of BSDI.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
+.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
+.\" $FreeBSD$
+.\"
+.Dd April 11, 2004
+.Dt MBLEN 3
+.Os
+.Sh NAME
+.Nm mblen
+.Nd get number of bytes in a character
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fn mblen "const char *mbchar" "size_t nbytes"
+.Sh DESCRIPTION
+The
+.Fn mblen
+function computes the length in bytes
+of a multibyte character
+.Fa mbchar
+according to the current conversion state.
+Up to
+.Fa nbytes
+bytes are examined.
+.Pp
+A call with a null
+.Fa mbchar
+pointer returns nonzero if the current locale requires shift states,
+zero otherwise;
+if shift states are required, the shift state is reset to the initial state.
+.Sh RETURN VALUES
+If
+.Fa mbchar
+is
+.Dv NULL ,
+the
+.Fn mblen
+function returns nonzero if shift states are supported,
+zero otherwise.
+.Pp
+Otherwise, if
+.Fa mbchar
+is not a null pointer,
+.Fn mblen
+either returns 0 if
+.Fa mbchar
+represents the null wide character, or returns
+the number of bytes processed in
+.Fa mbchar ,
+or returns \-1 if no multibyte character
+could be recognized or converted.
+In this case,
+.Fn mblen Ns 's
+internal conversion state is undefined.
+.Sh ERRORS
+The
+.Fn mblen
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EILSEQ
+An invalid multibyte sequence was detected.
+.It Bq Er EINVAL
+The internal conversion state is not valid.
+.El
+.Sh SEE ALSO
+.Xr mbrlen 3 ,
+.Xr mbtowc 3 ,
+.Xr multibyte 3
+.Sh STANDARDS
+The
+.Fn mblen
+function conforms to
+.St -isoC-99 .
diff --git a/lib/libc/locale/mblen.c b/lib/libc/locale/mblen.c
new file mode 100644
index 0000000..1bacf3e
--- /dev/null
+++ b/lib/libc/locale/mblen.c
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+int
+mblen_l(const char *s, size_t n, locale_t locale)
+{
+ static const mbstate_t initial;
+ size_t rval;
+ FIX_LOCALE(locale);
+
+ if (s == NULL) {
+ /* No support for state dependent encodings. */
+ locale->mblen = initial;
+ return (0);
+ }
+ rval = XLOCALE_CTYPE(locale)->__mbrtowc(NULL, s, n, &locale->mblen);
+ if (rval == (size_t)-1 || rval == (size_t)-2)
+ return (-1);
+ return ((int)rval);
+}
+
+int
+mblen(const char *s, size_t n)
+{
+ return mblen_l(s, n, __get_locale());
+}
diff --git a/lib/libc/locale/mblocal.h b/lib/libc/locale/mblocal.h
new file mode 100644
index 0000000..d172764
--- /dev/null
+++ b/lib/libc/locale/mblocal.h
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _MBLOCAL_H_
+#define _MBLOCAL_H_
+
+#include <runetype.h>
+#include "xlocale_private.h"
+
+
+/*
+ * Conversion function pointers for current encoding.
+ */
+struct xlocale_ctype {
+ struct xlocale_component header;
+ _RuneLocale *runes;
+ size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+ int (*__mbsinit)(const mbstate_t *);
+ size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict,
+ size_t, size_t, mbstate_t * __restrict);
+ size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict);
+ size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
+ size_t, size_t, mbstate_t * __restrict);
+ int __mb_cur_max;
+ int __mb_sb_limit;
+};
+#define XLOCALE_CTYPE(x) ((struct xlocale_ctype*)(x)->components[XLC_CTYPE])
+extern struct xlocale_ctype __xlocale_global_ctype;
+
+/*
+ * Rune initialization function prototypes.
+ */
+int _none_init(struct xlocale_ctype *, _RuneLocale *);
+int _ascii_init(struct xlocale_ctype *, _RuneLocale *);
+int _UTF8_init(struct xlocale_ctype *, _RuneLocale *);
+int _EUC_init(struct xlocale_ctype *, _RuneLocale *);
+int _GB18030_init(struct xlocale_ctype *, _RuneLocale *);
+int _GB2312_init(struct xlocale_ctype *, _RuneLocale *);
+int _GBK_init(struct xlocale_ctype *, _RuneLocale *);
+int _BIG5_init(struct xlocale_ctype *, _RuneLocale *);
+int _MSKanji_init(struct xlocale_ctype *, _RuneLocale *);
+
+extern size_t __mbsnrtowcs_std(wchar_t * __restrict, const char ** __restrict,
+ size_t, size_t, mbstate_t * __restrict);
+extern size_t __wcsnrtombs_std(char * __restrict, const wchar_t ** __restrict,
+ size_t, size_t, mbstate_t * __restrict);
+
+#endif /* _MBLOCAL_H_ */
diff --git a/lib/libc/locale/mbrlen.3 b/lib/libc/locale/mbrlen.3
new file mode 100644
index 0000000..524d2c7
--- /dev/null
+++ b/lib/libc/locale/mbrlen.3
@@ -0,0 +1,145 @@
+.\" Copyright (c) 2002-2004 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 7, 2004
+.Dt MBRLEN 3
+.Os
+.Sh NAME
+.Nm mbrlen
+.Nd "get number of bytes in a character (restartable)"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft size_t
+.Fn mbrlen "const char * restrict s" "size_t n" "mbstate_t * restrict ps"
+.Sh DESCRIPTION
+The
+.Fn mbrlen
+function inspects at most
+.Fa n
+bytes pointed to by
+.Fa s
+to determine the number of bytes needed to complete the next
+multibyte character.
+.Pp
+The
+.Vt mbstate_t
+argument,
+.Fa ps ,
+is used to keep track of the shift state.
+If it is
+.Dv NULL ,
+.Fn mbrlen
+uses an internal, static
+.Vt mbstate_t
+object, which is initialized to the initial conversion state
+at program startup.
+.Pp
+It is equivalent to:
+.Pp
+.Dl "mbrtowc(NULL, s, n, ps);"
+.Pp
+Except that when
+.Fa ps
+is a
+.Dv NULL
+pointer,
+.Fn mbrlen
+uses its own static, internal
+.Vt mbstate_t
+object to keep track of the shift state.
+.Sh RETURN VALUES
+The
+.Fn mbrlen
+functions returns:
+.Bl -tag -width indent
+.It 0
+The next
+.Fa n
+or fewer bytes
+represent the null wide character
+.Pq Li "L'\e0'" .
+.It >0
+The next
+.Fa n
+or fewer bytes
+represent a valid character,
+.Fn mbrlen
+returns the number of bytes used to complete the multibyte character.
+.It Po Vt size_t Pc Ns \-2
+The next
+.Fa n
+contribute to, but do not complete, a valid multibyte character sequence,
+and all
+.Fa n
+bytes have been processed.
+.It Po Vt size_t Pc Ns \-1
+An encoding error has occurred.
+The next
+.Fa n
+or fewer bytes do not contribute to a valid multibyte character.
+.El
+.Sh EXAMPLES
+A function that calculates the number of characters in a multibyte
+character string:
+.Bd -literal -offset indent
+size_t
+nchars(const char *s)
+{
+ size_t charlen, chars;
+ mbstate_t mbs;
+
+ chars = 0;
+ memset(&mbs, 0, sizeof(mbs));
+ while ((charlen = mbrlen(s, MB_CUR_MAX, &mbs)) != 0 &&
+ charlen != (size_t)-1 && charlen != (size_t)-2) {
+ s += charlen;
+ chars++;
+ }
+
+ return (chars);
+}
+.Ed
+.Sh ERRORS
+The
+.Fn mbrlen
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EILSEQ
+An invalid multibyte sequence was detected.
+.It Bq Er EINVAL
+The conversion state is invalid.
+.El
+.Sh SEE ALSO
+.Xr mblen 3 ,
+.Xr mbrtowc 3 ,
+.Xr multibyte 3
+.Sh STANDARDS
+The
+.Fn mbrlen
+function conforms to
+.St -isoC-99 .
diff --git a/lib/libc/locale/mbrlen.c b/lib/libc/locale/mbrlen.c
new file mode 100644
index 0000000..9ce0bc0
--- /dev/null
+++ b/lib/libc/locale/mbrlen.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+mbrlen_l(const char * __restrict s, size_t n, mbstate_t * __restrict ps, locale_t locale)
+{
+ FIX_LOCALE(locale);
+ if (ps == NULL)
+ ps = &locale->mbrlen;
+ return (XLOCALE_CTYPE(locale)->__mbrtowc(NULL, s, n, ps));
+}
+
+size_t
+mbrlen(const char * __restrict s, size_t n, mbstate_t * __restrict ps)
+{
+ return mbrlen_l(s, n, ps, __get_locale());
+}
diff --git a/lib/libc/locale/mbrtowc.3 b/lib/libc/locale/mbrtowc.3
new file mode 100644
index 0000000..10160d1
--- /dev/null
+++ b/lib/libc/locale/mbrtowc.3
@@ -0,0 +1,139 @@
+.\" Copyright (c) 2002-2004 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 8, 2004
+.Dt MBRTOWC 3
+.Os
+.Sh NAME
+.Nm mbrtowc
+.Nd "convert a character to a wide-character code (restartable)"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft size_t
+.Fo mbrtowc
+.Fa "wchar_t * restrict pwc" "const char * restrict s" "size_t n"
+.Fa "mbstate_t * restrict ps"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn mbrtowc
+function inspects at most
+.Fa n
+bytes pointed to by
+.Fa s
+to determine the number of bytes needed to complete the next multibyte
+character.
+If a character can be completed, and
+.Fa pwc
+is not
+.Dv NULL ,
+the wide character which is represented by
+.Fa s
+is stored in the
+.Vt wchar_t
+it points to.
+.Pp
+If
+.Fa s
+is
+.Dv NULL ,
+.Fn mbrtowc
+behaves as if
+.Fa pwc
+was
+.Dv NULL ,
+.Fa s
+was an empty string
+.Pq Qq
+and
+.Fa n
+was 1.
+.Pp
+The
+.Vt mbstate_t
+argument,
+.Fa ps ,
+is used to keep track of the shift state.
+If it is
+.Dv NULL ,
+.Fn mbrtowc
+uses an internal, static
+.Vt mbstate_t
+object, which is initialized to the initial conversion state
+at program startup.
+.Sh RETURN VALUES
+The
+.Fn mbrtowc
+functions returns:
+.Bl -tag -width indent
+.It 0
+The next
+.Fa n
+or fewer bytes
+represent the null wide character
+.Pq Li "L'\e0'" .
+.It >0
+The next
+.Fa n
+or fewer bytes
+represent a valid character,
+.Fn mbrtowc
+returns the number of bytes used to complete the multibyte character.
+.It Po Vt size_t Pc Ns \-2
+The next
+.Fa n
+contribute to, but do not complete, a valid multibyte character sequence,
+and all
+.Fa n
+bytes have been processed.
+.It Po Vt size_t Pc Ns \-1
+An encoding error has occurred.
+The next
+.Fa n
+or fewer bytes do not contribute to a valid multibyte character.
+.El
+.Sh ERRORS
+The
+.Fn mbrtowc
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EILSEQ
+An invalid multibyte sequence was detected.
+.It Bq Er EINVAL
+The conversion state is invalid.
+.El
+.Sh SEE ALSO
+.Xr mbtowc 3 ,
+.Xr multibyte 3 ,
+.Xr setlocale 3 ,
+.Xr wcrtomb 3
+.Sh STANDARDS
+The
+.Fn mbrtowc
+function conforms to
+.St -isoC-99 .
diff --git a/lib/libc/locale/mbrtowc.c b/lib/libc/locale/mbrtowc.c
new file mode 100644
index 0000000..8f1aebd
--- /dev/null
+++ b/lib/libc/locale/mbrtowc.c
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+mbrtowc_l(wchar_t * __restrict pwc, const char * __restrict s,
+ size_t n, mbstate_t * __restrict ps, locale_t locale)
+{
+ FIX_LOCALE(locale);
+ if (ps == NULL)
+ ps = &locale->mbrtowc;
+ return (XLOCALE_CTYPE(locale)->__mbrtowc(pwc, s, n, ps));
+}
+
+size_t
+mbrtowc(wchar_t * __restrict pwc, const char * __restrict s,
+ size_t n, mbstate_t * __restrict ps)
+{
+ return mbrtowc_l(pwc, s, n, ps, __get_locale());
+}
diff --git a/lib/libc/locale/mbsinit.3 b/lib/libc/locale/mbsinit.3
new file mode 100644
index 0000000..afc2500
--- /dev/null
+++ b/lib/libc/locale/mbsinit.3
@@ -0,0 +1,67 @@
+.\" Copyright (c) 2002-2004 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 8, 2004
+.Dt MBSINIT 3
+.Os
+.Sh NAME
+.Nm mbsinit
+.Nd "determine conversion object status"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft int
+.Fn mbsinit "const mbstate_t *ps"
+.Sh DESCRIPTION
+The
+.Fn mbsinit
+function determines whether the
+.Vt mbstate_t
+object pointed to by
+.Fa ps
+describes an initial conversion state.
+.Sh RETURN VALUES
+The
+.Fn mbsinit
+function returns non-zero if
+.Fa ps
+is
+.Dv NULL
+or describes an initial conversion state,
+otherwise it returns zero.
+.Sh SEE ALSO
+.Xr mbrlen 3 ,
+.Xr mbrtowc 3 ,
+.Xr mbsrtowcs 3 ,
+.Xr multibyte 3 ,
+.Xr wcrtomb 3 ,
+.Xr wcsrtombs 3
+.Sh STANDARDS
+The
+.Fn mbsinit
+function conforms to
+.St -isoC-99 .
diff --git a/lib/libc/locale/mbsinit.c b/lib/libc/locale/mbsinit.c
new file mode 100644
index 0000000..be44fe5
--- /dev/null
+++ b/lib/libc/locale/mbsinit.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+#include "mblocal.h"
+
+int
+mbsinit_l(const mbstate_t *ps, locale_t locale)
+{
+ FIX_LOCALE(locale);
+ return (XLOCALE_CTYPE(locale)->__mbsinit(ps));
+}
+int
+mbsinit(const mbstate_t *ps)
+{
+ return mbsinit_l(ps, __get_locale());
+}
diff --git a/lib/libc/locale/mbsnrtowcs.c b/lib/libc/locale/mbsnrtowcs.c
new file mode 100644
index 0000000..15b48dd7
--- /dev/null
+++ b/lib/libc/locale/mbsnrtowcs.c
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+mbsnrtowcs_l(wchar_t * __restrict dst, const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps, locale_t locale)
+{
+ FIX_LOCALE(locale);
+ if (ps == NULL)
+ ps = &locale->mbsnrtowcs;
+ return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(dst, src, nms, len, ps));
+}
+size_t
+mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps)
+{
+ return mbsnrtowcs_l(dst, src, nms, len, ps, __get_locale());
+}
+
+size_t
+__mbsnrtowcs_std(wchar_t * __restrict dst, const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps)
+{
+ const char *s;
+ size_t nchr;
+ wchar_t wc;
+ size_t nb;
+ struct xlocale_ctype *ct = XLOCALE_CTYPE(__get_locale());
+
+ s = *src;
+ nchr = 0;
+
+ if (dst == NULL) {
+ for (;;) {
+ if ((nb = ct->__mbrtowc(&wc, s, nms, ps)) == (size_t)-1)
+ /* Invalid sequence - mbrtowc() sets errno. */
+ return ((size_t)-1);
+ else if (nb == 0 || nb == (size_t)-2)
+ return (nchr);
+ s += nb;
+ nms -= nb;
+ nchr++;
+ }
+ /*NOTREACHED*/
+ }
+
+ while (len-- > 0) {
+ if ((nb = ct->__mbrtowc(dst, s, nms, ps)) == (size_t)-1) {
+ *src = s;
+ return ((size_t)-1);
+ } else if (nb == (size_t)-2) {
+ *src = s + nms;
+ return (nchr);
+ } else if (nb == 0) {
+ *src = NULL;
+ return (nchr);
+ }
+ s += nb;
+ nms -= nb;
+ nchr++;
+ dst++;
+ }
+ *src = s;
+ return (nchr);
+}
diff --git a/lib/libc/locale/mbsrtowcs.3 b/lib/libc/locale/mbsrtowcs.3
new file mode 100644
index 0000000..eaf9f90
--- /dev/null
+++ b/lib/libc/locale/mbsrtowcs.3
@@ -0,0 +1,135 @@
+.\" Copyright (c) 2002-2004 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.Dd July 21, 2004
+.Dt MBSRTOWCS 3
+.Os
+.Sh NAME
+.Nm mbsrtowcs ,
+.Nm mbsnrtowcs
+.Nd "convert a character string to a wide-character string (restartable)"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft size_t
+.Fo mbsrtowcs
+.Fa "wchar_t * restrict dst" "const char ** restrict src" "size_t len"
+.Fa "mbstate_t * restrict ps"
+.Fc
+.Ft size_t
+.Fo mbsnrtowcs
+.Fa "wchar_t * restrict dst" "const char ** restrict src" "size_t nms"
+.Fa "size_t len" "mbstate_t * restrict ps"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn mbsrtowcs
+function converts a sequence of multibyte characters pointed to indirectly by
+.Fa src
+into a sequence of corresponding wide characters and stores at most
+.Fa len
+of them in the
+.Vt wchar_t
+array pointed to by
+.Fa dst ,
+until it encounters a terminating null character
+.Pq Li '\e0' .
+.Pp
+If
+.Fa dst
+is
+.Dv NULL ,
+no characters are stored.
+.Pp
+If
+.Fa dst
+is not
+.Dv NULL ,
+the pointer pointed to by
+.Fa src
+is updated to point to the character after the one that conversion stopped at.
+If conversion stops because a null character is encountered,
+.Fa *src
+is set to
+.Dv NULL .
+.Pp
+The
+.Vt mbstate_t
+argument,
+.Fa ps ,
+is used to keep track of the shift state.
+If it is
+.Dv NULL ,
+.Fn mbsrtowcs
+uses an internal, static
+.Vt mbstate_t
+object, which is initialized to the initial conversion state
+at program startup.
+.Pp
+The
+.Fn mbsnrtowcs
+function behaves identically to
+.Fn mbsrtowcs ,
+except that conversion stops after reading at most
+.Fa nms
+bytes from the buffer pointed to by
+.Fa src .
+.Sh RETURN VALUES
+The
+.Fn mbsrtowcs
+and
+.Fn mbsnrtowcs
+functions return the number of wide characters stored in
+the array pointed to by
+.Fa dst
+if successful, otherwise it returns
+.Po Vt size_t Pc Ns \-1 .
+.Sh ERRORS
+The
+.Fn mbsrtowcs
+and
+.Fn mbsnrtowcs
+functions will fail if:
+.Bl -tag -width Er
+.It Bq Er EILSEQ
+An invalid multibyte character sequence was encountered.
+.It Bq Er EINVAL
+The conversion state is invalid.
+.El
+.Sh SEE ALSO
+.Xr mbrtowc 3 ,
+.Xr mbstowcs 3 ,
+.Xr multibyte 3 ,
+.Xr wcsrtombs 3
+.Sh STANDARDS
+The
+.Fn mbsrtowcs
+function conforms to
+.St -isoC-99 .
+.Pp
+The
+.Fn mbsnrtowcs
+function is an extension to the standard.
diff --git a/lib/libc/locale/mbsrtowcs.c b/lib/libc/locale/mbsrtowcs.c
new file mode 100644
index 0000000..9032b94
--- /dev/null
+++ b/lib/libc/locale/mbsrtowcs.c
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+mbsrtowcs_l(wchar_t * __restrict dst, const char ** __restrict src, size_t len,
+ mbstate_t * __restrict ps, locale_t locale)
+{
+ FIX_LOCALE(locale);
+ if (ps == NULL)
+ ps = &locale->mbsrtowcs;
+ return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(dst, src, SIZE_T_MAX, len, ps));
+}
+size_t
+mbsrtowcs(wchar_t * __restrict dst, const char ** __restrict src, size_t len,
+ mbstate_t * __restrict ps)
+{
+ return mbsrtowcs_l(dst, src, len, ps, __get_locale());
+}
diff --git a/lib/libc/locale/mbstowcs.3 b/lib/libc/locale/mbstowcs.3
new file mode 100644
index 0000000..fb91683
--- /dev/null
+++ b/lib/libc/locale/mbstowcs.3
@@ -0,0 +1,87 @@
+.\" Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Donn Seeley of BSDI.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
+.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
+.\" $FreeBSD$
+.\"
+.Dd April 8, 2004
+.Dt MBSTOWCS 3
+.Os
+.Sh NAME
+.Nm mbstowcs
+.Nd convert a character string to a wide-character string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft size_t
+.Fo mbstowcs
+.Fa "wchar_t * restrict wcstring" "const char * restrict mbstring"
+.Fa "size_t nwchars"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn mbstowcs
+function converts a multibyte character string
+.Fa mbstring
+beginning in the initial conversion state
+into a wide character string
+.Fa wcstring .
+No more than
+.Fa nwchars
+wide characters are stored.
+A terminating null wide character is appended if there is room.
+.Sh RETURN VALUES
+The
+.Fn mbstowcs
+function returns the number of wide characters converted,
+not counting any terminating null wide character, or \-1
+if an invalid multibyte character was encountered.
+.Sh ERRORS
+The
+.Fn mbstowcs
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EILSEQ
+An invalid multibyte sequence was detected.
+.It Bq Er EINVAL
+The conversion state is invalid.
+.El
+.Sh SEE ALSO
+.Xr mbsrtowcs 3 ,
+.Xr mbtowc 3 ,
+.Xr multibyte 3
+.Sh STANDARDS
+The
+.Fn mbstowcs
+function conforms to
+.St -isoC-99 .
diff --git a/lib/libc/locale/mbstowcs.c b/lib/libc/locale/mbstowcs.c
new file mode 100644
index 0000000..6905d2e
--- /dev/null
+++ b/lib/libc/locale/mbstowcs.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+mbstowcs_l(wchar_t * __restrict pwcs, const char * __restrict s, size_t n, locale_t locale)
+{
+ static const mbstate_t initial;
+ mbstate_t mbs;
+ const char *sp;
+ FIX_LOCALE(locale);
+
+ mbs = initial;
+ sp = s;
+ return (XLOCALE_CTYPE(locale)->__mbsnrtowcs(pwcs, &sp, SIZE_T_MAX, n, &mbs));
+}
+size_t
+mbstowcs(wchar_t * __restrict pwcs, const char * __restrict s, size_t n)
+{
+ return mbstowcs_l(pwcs, s, n, __get_locale());
+}
diff --git a/lib/libc/locale/mbtowc.3 b/lib/libc/locale/mbtowc.3
new file mode 100644
index 0000000..b59dbf4
--- /dev/null
+++ b/lib/libc/locale/mbtowc.3
@@ -0,0 +1,114 @@
+.\" Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Donn Seeley of BSDI.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
+.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
+.\" $FreeBSD$
+.\"
+.Dd April 11, 2004
+.Dt MBTOWC 3
+.Os
+.Sh NAME
+.Nm mbtowc
+.Nd convert a character to a wide-character code
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fo mbtowc
+.Fa "wchar_t * restrict wcharp" "const char * restrict mbchar"
+.Fa "size_t nbytes"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn mbtowc
+function converts a multibyte character
+.Fa mbchar
+into a wide character according to the current conversion state,
+and stores the result
+in the object pointed to by
+.Fa wcharp .
+Up to
+.Fa nbytes
+bytes are examined.
+.Pp
+A call with a null
+.Fa mbchar
+pointer returns nonzero if the current encoding requires shift states,
+zero otherwise;
+if shift states are required, the shift state is reset to the initial state.
+.Sh RETURN VALUES
+If
+.Fa mbchar
+is
+.Dv NULL ,
+the
+.Fn mbtowc
+function returns nonzero if shift states are supported,
+zero otherwise.
+.Pp
+Otherwise, if
+.Fa mbchar
+is not a null pointer,
+.Fn mbtowc
+either returns 0 if
+.Fa mbchar
+represents the null wide character, or returns
+the number of bytes processed in
+.Fa mbchar ,
+or returns \-1 if no multibyte character
+could be recognized or converted.
+In this case,
+.Fn mbtowc Ns 's
+internal conversion state is undefined.
+.Sh ERRORS
+The
+.Fn mbtowc
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EILSEQ
+An invalid multibyte sequence was detected.
+.It Bq Er EINVAL
+The internal conversion state is invalid.
+.El
+.Sh SEE ALSO
+.Xr btowc 3 ,
+.Xr mblen 3 ,
+.Xr mbrtowc 3 ,
+.Xr mbstowcs 3 ,
+.Xr multibyte 3 ,
+.Xr wctomb 3
+.Sh STANDARDS
+The
+.Fn mbtowc
+function conforms to
+.St -isoC-99 .
diff --git a/lib/libc/locale/mbtowc.c b/lib/libc/locale/mbtowc.c
new file mode 100644
index 0000000..70fc19e
--- /dev/null
+++ b/lib/libc/locale/mbtowc.c
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+int
+mbtowc_l(wchar_t * __restrict pwc, const char * __restrict s, size_t n, locale_t locale)
+{
+ static const mbstate_t initial;
+ size_t rval;
+ FIX_LOCALE(locale);
+
+ if (s == NULL) {
+ /* No support for state dependent encodings. */
+ locale->mbtowc = initial;
+ return (0);
+ }
+ rval = XLOCALE_CTYPE(locale)->__mbrtowc(pwc, s, n, &locale->mbtowc);
+ if (rval == (size_t)-1 || rval == (size_t)-2)
+ return (-1);
+ return ((int)rval);
+}
+int
+mbtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n)
+{
+ return mbtowc_l(pwc, s, n, __get_locale());
+}
diff --git a/lib/libc/locale/mskanji.5 b/lib/libc/locale/mskanji.5
new file mode 100644
index 0000000..8ebaccd
--- /dev/null
+++ b/lib/libc/locale/mskanji.5
@@ -0,0 +1,70 @@
+.\" Copyright (c) 2002, 2003 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 7, 2003
+.Dt MSKANJI 5
+.Os
+.Sh NAME
+.Nm mskanji
+.Nd "Shift-JIS (MS Kanji) encoding for Japanese text"
+.Sh SYNOPSIS
+.Nm ENCODING
+.Qq MSKanji
+.Sh DESCRIPTION
+Shift-JIS, also known as MS Kanji or SJIS, is an encoding system for
+Japanese characters, developed by Microsoft Corporation.
+It encodes the characters from the
+.Tn JIS
+X 0201 (ASCII/JIS-Roman) and
+.Tn JIS
+X 0208 (Japanese) character sets as sequences of either one or two bytes.
+.Pp
+Characters from the
+.Tn ASCII Ns
+/JIS-Roman character set are encoded as single bytes between 0x00 and 0x7F
+(ASCII) or 0xA1 and 0xDF (Half-width katakana).
+.Pp
+Characters from the
+.Tn JIS
+X 0208 character set are encoded as two bytes.
+The first ranges from
+0x81 - 0x9F, 0xE0 - 0xEA, 0xED - 0xEE (not
+.Tn JIS :
+.Tn NEC Ns - Ns
+selected
+.Tn IBM
+extended characters),
+0xF0 - 0xF9 (not
+.Tn JIS :
+user defined),
+or 0xFA - 0xFC (not
+.Tn JIS :
+.Tn IBM
+extended characters).
+The second byte ranges from 0x40 - 0xFC, excluding 0x7F (delete).
+.Sh SEE ALSO
+.Xr euc 5 ,
+.Xr utf8 5
diff --git a/lib/libc/locale/mskanji.c b/lib/libc/locale/mskanji.c
new file mode 100644
index 0000000..9fdd080
--- /dev/null
+++ b/lib/libc/locale/mskanji.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
+ *
+ * ja_JP.SJIS locale table for BSD4.4/rune
+ * version 1.0
+ * (C) Sin'ichiro MIYATANI / Phase One, Inc
+ * May 12, 1995
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Phase One, Inc.
+ * 4. The name of Phase One, Inc. may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)mskanji.c 1.0 (Phase One) 5/5/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <errno.h>
+#include <runetype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+extern int __mb_sb_limit;
+
+static size_t _MSKanji_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _MSKanji_mbsinit(const mbstate_t *);
+static size_t _MSKanji_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+
+typedef struct {
+ wchar_t ch;
+} _MSKanjiState;
+
+int
+_MSKanji_init(struct xlocale_ctype *l, _RuneLocale *rl)
+{
+
+ l->__mbrtowc = _MSKanji_mbrtowc;
+ l->__wcrtomb = _MSKanji_wcrtomb;
+ l->__mbsinit = _MSKanji_mbsinit;
+ l->runes = rl;
+ l->__mb_cur_max = 2;
+ l->__mb_sb_limit = 256;
+ return (0);
+}
+
+static int
+_MSKanji_mbsinit(const mbstate_t *ps)
+{
+
+ return (ps == NULL || ((const _MSKanjiState *)ps)->ch == 0);
+}
+
+static size_t
+_MSKanji_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
+ mbstate_t * __restrict ps)
+{
+ _MSKanjiState *ms;
+ wchar_t wc;
+
+ ms = (_MSKanjiState *)ps;
+
+ if ((ms->ch & ~0xFF) != 0) {
+ /* Bad conversion state. */
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL) {
+ s = "";
+ n = 1;
+ pwc = NULL;
+ }
+
+ if (n == 0)
+ /* Incomplete multibyte sequence */
+ return ((size_t)-2);
+
+ if (ms->ch != 0) {
+ if (*s == '\0') {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ wc = (ms->ch << 8) | (*s & 0xFF);
+ if (pwc != NULL)
+ *pwc = wc;
+ ms->ch = 0;
+ return (1);
+ }
+ wc = *s++ & 0xff;
+ if ((wc > 0x80 && wc < 0xa0) || (wc >= 0xe0 && wc < 0xfd)) {
+ if (n < 2) {
+ /* Incomplete multibyte sequence */
+ ms->ch = wc;
+ return ((size_t)-2);
+ }
+ if (*s == '\0') {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ wc = (wc << 8) | (*s++ & 0xff);
+ if (pwc != NULL)
+ *pwc = wc;
+ return (2);
+ } else {
+ if (pwc != NULL)
+ *pwc = wc;
+ return (wc == L'\0' ? 0 : 1);
+ }
+}
+
+static size_t
+_MSKanji_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
+{
+ _MSKanjiState *ms;
+ int len, i;
+
+ ms = (_MSKanjiState *)ps;
+
+ if (ms->ch != 0) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (1);
+ len = (wc > 0x100) ? 2 : 1;
+ for (i = len; i-- > 0; )
+ *s++ = wc >> (i << 3);
+ return (len);
+}
diff --git a/lib/libc/locale/multibyte.3 b/lib/libc/locale/multibyte.3
new file mode 100644
index 0000000..465bf66
--- /dev/null
+++ b/lib/libc/locale/multibyte.3
@@ -0,0 +1,142 @@
+.\" Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Donn Seeley of BSDI.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)multibyte.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd April 8, 2004
+.Dt MULTIBYTE 3
+.Os
+.Sh NAME
+.Nm multibyte
+.Nd multibyte and wide character manipulation functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In limits.h
+.In stdlib.h
+.In wchar.h
+.Sh DESCRIPTION
+The basic elements of some written natural languages, such as Chinese,
+cannot be represented uniquely with single C
+.Vt char Ns s .
+The C standard supports two different ways of dealing with
+extended natural language encodings:
+wide characters and
+multibyte characters.
+Wide characters are an internal representation
+which allows each basic element to map
+to a single object of type
+.Vt wchar_t .
+Multibyte characters are used for input and output
+and code each basic element as a sequence of C
+.Vt char Ns s .
+Individual basic elements may map into one or more
+(up to
+.Dv MB_LEN_MAX )
+bytes in a multibyte character.
+.Pp
+The current locale
+.Pq Xr setlocale 3
+governs the interpretation of wide and multibyte characters.
+The locale category
+.Dv LC_CTYPE
+specifically controls this interpretation.
+The
+.Vt wchar_t
+type is wide enough to hold the largest value
+in the wide character representations for all locales.
+.Pp
+Multibyte strings may contain
+.Sq shift
+indicators to switch to and from
+particular modes within the given representation.
+If explicit bytes are used to signal shifting,
+these are not recognized as separate characters
+but are lumped with a neighboring character.
+There is always a distinguished
+.Sq initial
+shift state.
+Some functions (e.g.,
+.Xr mblen 3 ,
+.Xr mbtowc 3
+and
+.Xr wctomb 3 )
+maintain static shift state internally, whereas
+others store it in an
+.Vt mbstate_t
+object passed by the caller.
+Shift states are undefined after a call to
+.Xr setlocale 3
+with the
+.Dv LC_CTYPE
+or
+.Dv LC_ALL
+categories.
+.Pp
+For convenience in processing,
+the wide character with value 0
+(the null wide character)
+is recognized as the wide character string terminator,
+and the character with value 0
+(the null byte)
+is recognized as the multibyte character string terminator.
+Null bytes are not permitted within multibyte characters.
+.Pp
+The C library provides the following functions for dealing with
+multibyte characters:
+.Bl -column "Description"
+.It Sy "Function Description"
+.It Xr mblen 3 Ta "get number of bytes in a character"
+.It Xr mbrlen 3 Ta "get number of bytes in a character (restartable)"
+.It Xr mbrtowc 3 Ta "convert a character to a wide-character code (restartable)"
+.It Xr mbsrtowcs 3 Ta "convert a character string to a wide-character string (restartable)"
+.It Xr mbstowcs 3 Ta "convert a character string to a wide-character string"
+.It Xr mbtowc 3 Ta "convert a character to a wide-character code"
+.It Xr wcrtomb 3 Ta "convert a wide-character code to a character (restartable)"
+.It Xr wcstombs 3 Ta "convert a wide-character string to a character string"
+.It Xr wcsrtombs 3 Ta "convert a wide-character string to a character string (restartable)"
+.It Xr wctomb 3 Ta "convert a wide-character code to a character"
+.El
+.Sh SEE ALSO
+.Xr mklocale 1 ,
+.Xr setlocale 3 ,
+.Xr stdio 3 ,
+.Xr big5 5 ,
+.Xr euc 5 ,
+.Xr gb18030 5 ,
+.Xr gb2312 5 ,
+.Xr gbk 5 ,
+.Xr mskanji 5 ,
+.Xr utf8 5
+.Sh STANDARDS
+These functions conform to
+.St -isoC-99 .
diff --git a/lib/libc/locale/newlocale.3 b/lib/libc/locale/newlocale.3
new file mode 100644
index 0000000..599f148
--- /dev/null
+++ b/lib/libc/locale/newlocale.3
@@ -0,0 +1,112 @@
+.\" Copyright (c) 2011 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This documentation was written by David Chisnall under sponsorship from
+.\" the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.Dd September 17 2011
+.Dt NEWLOCALE 3
+.Os
+.Sh NAME
+.Nm newlocale
+.Nd Creates a new locale
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In xlocale
+.Ft locale_t
+.Fn newlocale "int mask" "const char * locale" "locale_t base"
+.Sh DESCRIPTION
+Creates a new locale, inheriting some properties from an existing locale.
+The
+.Fa mask
+defines the components that the new locale will have set to the locale with the
+name specified in the
+.Fa locale
+parameter.
+Any other components will be inherited from
+.Fa base .
+The
+.Fa mask
+is either
+.Fa LC_ALL_MASK,
+indicating all possible locale components,
+or the logical OR of some combination of the following:
+.Bl -tag -width "LC_MESSAGES_MASK" -offset indent
+.It LC_COLLATE_MASK
+The locale for string collation routines.
+This controls alphabetic ordering in
+.Xr strcoll 3
+ and
+.Xr strxfrm 3 .
+.It LC_CTYPE_MASK
+The locale for the
+.Xr ctype 3
+and
+.Xr multibyte 3
+functions.
+This controls recognition of upper and lower case, alphabetic or
+non-alphabetic characters, and so on.
+.It LC_MESSAGES_MASK
+Set a locale for message catalogs, see
+.Xr catopen 3
+function.
+.It LC_MONETARY_MASK
+Set a locale for formatting monetary values; this affects
+the
+.Xr localeconv 3
+function.
+.It LC_NUMERIC_MASK
+Set a locale for formatting numbers.
+This controls the formatting of decimal points in input and output of floating
+point numbers in functions such as
+.Xr printf 3
+and
+.Xr scanf 3 ,
+as well as values returned by
+.Xr localeconv 3 .
+.It LC_TIME_MASK
+Set a locale for formatting dates and times using the
+.Xr strftime 3
+function.
+.El
+This function uses the same rules for loading locale components as
+.Xr setlocale 3 .
+.Sh RETURN VALUES
+Returns a new, valid,
+.Fa locale_t
+or NULL if an error occurs.
+You must free the returned locale with
+.Xr freelocale 3 .
+.Sh SEE ALSO
+.Xr duplocale 3 ,
+.Xr freelocale 3 ,
+.Xr localeconv 3 ,
+.Xr querylocale 3 ,
+.Xr uselocale 3 ,
+.Xr xlocale 3
+.Sh STANDARDS
+This function, conforms to
+.St -p1003.1-2008
diff --git a/lib/libc/locale/nextwctype.3 b/lib/libc/locale/nextwctype.3
new file mode 100644
index 0000000..0f6f880
--- /dev/null
+++ b/lib/libc/locale/nextwctype.3
@@ -0,0 +1,67 @@
+.\"
+.\" Copyright (c) 2004 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 21, 2005
+.Dt NEXTWCTYPE 3
+.Os
+.Sh NAME
+.Nm nextwctype
+.Nd "iterate through character classes"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wctype.h
+.Ft wint_t
+.Fn nextwctype "wint_t ch" "wctype_t wct"
+.Sh DESCRIPTION
+The
+.Fn nextwctype
+function determines the next character after
+.Fa ch
+that is a member of character class
+.Fa wct .
+If
+.Fa ch
+is \-1, the search begins at the first member of
+.Fa wct .
+.Sh RETURN VALUES
+The
+.Fn nextwctype
+function returns the next character, or \-1 if there are no more.
+.Sh COMPATIBILITY
+This function is a non-standard
+.Fx
+extension and should not be used where the standard
+.Fn iswctype
+function would suffice.
+.Sh SEE ALSO
+.Xr wctype 3
+.Sh HISTORY
+The
+.Fn nextwctype
+function appeared in
+.Fx 5.4 .
diff --git a/lib/libc/locale/nextwctype.c b/lib/libc/locale/nextwctype.c
new file mode 100644
index 0000000..9fc8ce0
--- /dev/null
+++ b/lib/libc/locale/nextwctype.c
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (c) 2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <runetype.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "mblocal.h"
+
+wint_t
+nextwctype_l(wint_t wc, wctype_t wct, locale_t locale)
+{
+ size_t lim;
+ FIX_LOCALE(locale);
+ _RuneLocale *runes = XLOCALE_CTYPE(locale)->runes;
+ _RuneRange *rr = &runes->__runetype_ext;
+ _RuneEntry *base, *re;
+ int noinc;
+
+ noinc = 0;
+ if (wc < _CACHED_RUNES) {
+ wc++;
+ while (wc < _CACHED_RUNES) {
+ if (runes->__runetype[wc] & wct)
+ return (wc);
+ wc++;
+ }
+ wc--;
+ }
+ if (rr->__ranges != NULL && wc < rr->__ranges[0].__min) {
+ wc = rr->__ranges[0].__min;
+ noinc = 1;
+ }
+
+ /* Binary search -- see bsearch.c for explanation. */
+ base = rr->__ranges;
+ for (lim = rr->__nranges; lim != 0; lim >>= 1) {
+ re = base + (lim >> 1);
+ if (re->__min <= wc && wc <= re->__max)
+ goto found;
+ else if (wc > re->__max) {
+ base = re + 1;
+ lim--;
+ }
+ }
+ return (-1);
+found:
+ if (!noinc)
+ wc++;
+ if (re->__min <= wc && wc <= re->__max) {
+ if (re->__types != NULL) {
+ for (; wc <= re->__max; wc++)
+ if (re->__types[wc - re->__min] & wct)
+ return (wc);
+ } else if (re->__map & wct)
+ return (wc);
+ }
+ while (++re < rr->__ranges + rr->__nranges) {
+ wc = re->__min;
+ if (re->__types != NULL) {
+ for (; wc <= re->__max; wc++)
+ if (re->__types[wc - re->__min] & wct)
+ return (wc);
+ } else if (re->__map & wct)
+ return (wc);
+ }
+ return (-1);
+}
+wint_t
+nextwctype(wint_t wc, wctype_t wct)
+{
+ return nextwctype_l(wc, wct, __get_locale());
+}
diff --git a/lib/libc/locale/nl_langinfo.3 b/lib/libc/locale/nl_langinfo.3
new file mode 100644
index 0000000..789cac2
--- /dev/null
+++ b/lib/libc/locale/nl_langinfo.3
@@ -0,0 +1,90 @@
+.\" Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd May 3, 2001
+.Dt NL_LANGINFO 3
+.Os
+.Sh NAME
+.Nm nl_langinfo
+.Nd language information
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In langinfo.h
+.Ft char *
+.Fn nl_langinfo "nl_item item"
+.Sh DESCRIPTION
+The
+.Fn nl_langinfo
+function returns a pointer to a string containing information relevant to
+the particular language or cultural area defined in the program's locale.
+The manifest constant names and values of
+.Fa item
+are defined in
+.In langinfo.h .
+.Pp
+Calls to
+.Fn setlocale
+with a category corresponding to the category of
+.Fa item ,
+or to the
+category
+.Dv LC_ALL ,
+may overwrite the buffer pointed to by the return value.
+.Sh RETURN VALUES
+In a locale where langinfo data is not defined,
+.Fn nl_langinfo
+returns a pointer to the corresponding string in the
+.Tn POSIX
+locale.
+In all locales,
+.Fn nl_langinfo
+returns a pointer to an empty string if
+.Fa item
+contains an invalid setting.
+.Sh EXAMPLES
+For example:
+.Pp
+.Dl nl_langinfo(ABDAY_1)
+.Pp
+would return a pointer to the string
+.Qq Li Dom
+if the identified language was
+Portuguese, and
+.Qq Li Sun
+if the identified language was English.
+.Sh SEE ALSO
+.Xr setlocale 3
+.Sh STANDARDS
+The
+.Fn nl_langinfo
+function conforms to
+.St -susv2 .
+.Sh HISTORY
+The
+.Fn nl_langinfo
+function first appeared in
+.Fx 4.6 .
diff --git a/lib/libc/locale/nl_langinfo.c b/lib/libc/locale/nl_langinfo.c
new file mode 100644
index 0000000..3e8fe7c
--- /dev/null
+++ b/lib/libc/locale/nl_langinfo.c
@@ -0,0 +1,193 @@
+/*-
+ * Copyright (c) 2001, 2003 Alexey Zelkin <phantom@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <langinfo.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "lnumeric.h"
+#include "lmessages.h"
+#include "lmonetary.h"
+#include "../stdtime/timelocal.h"
+
+#define _REL(BASE) ((int)item-BASE)
+
+char *
+nl_langinfo_l(nl_item item, locale_t loc)
+{
+ char *ret, *cs;
+ const char *s;
+ FIX_LOCALE(loc);
+
+ switch (item) {
+ case CODESET:
+ ret = "";
+ if ((s = querylocale(LC_CTYPE_MASK, loc)) != NULL) {
+ if ((cs = strchr(s, '.')) != NULL)
+ ret = cs + 1;
+ else if (strcmp(s, "C") == 0 ||
+ strcmp(s, "POSIX") == 0)
+ ret = "US-ASCII";
+ }
+ break;
+ case D_T_FMT:
+ ret = (char *) __get_current_time_locale(loc)->c_fmt;
+ break;
+ case D_FMT:
+ ret = (char *) __get_current_time_locale(loc)->x_fmt;
+ break;
+ case T_FMT:
+ ret = (char *) __get_current_time_locale(loc)->X_fmt;
+ break;
+ case T_FMT_AMPM:
+ ret = (char *) __get_current_time_locale(loc)->ampm_fmt;
+ break;
+ case AM_STR:
+ ret = (char *) __get_current_time_locale(loc)->am;
+ break;
+ case PM_STR:
+ ret = (char *) __get_current_time_locale(loc)->pm;
+ break;
+ case DAY_1: case DAY_2: case DAY_3:
+ case DAY_4: case DAY_5: case DAY_6: case DAY_7:
+ ret = (char*) __get_current_time_locale(loc)->weekday[_REL(DAY_1)];
+ break;
+ case ABDAY_1: case ABDAY_2: case ABDAY_3:
+ case ABDAY_4: case ABDAY_5: case ABDAY_6: case ABDAY_7:
+ ret = (char*) __get_current_time_locale(loc)->wday[_REL(ABDAY_1)];
+ break;
+ case MON_1: case MON_2: case MON_3: case MON_4:
+ case MON_5: case MON_6: case MON_7: case MON_8:
+ case MON_9: case MON_10: case MON_11: case MON_12:
+ ret = (char*) __get_current_time_locale(loc)->month[_REL(MON_1)];
+ break;
+ case ABMON_1: case ABMON_2: case ABMON_3: case ABMON_4:
+ case ABMON_5: case ABMON_6: case ABMON_7: case ABMON_8:
+ case ABMON_9: case ABMON_10: case ABMON_11: case ABMON_12:
+ ret = (char*) __get_current_time_locale(loc)->mon[_REL(ABMON_1)];
+ break;
+ case ALTMON_1: case ALTMON_2: case ALTMON_3: case ALTMON_4:
+ case ALTMON_5: case ALTMON_6: case ALTMON_7: case ALTMON_8:
+ case ALTMON_9: case ALTMON_10: case ALTMON_11: case ALTMON_12:
+ ret = (char*)
+ __get_current_time_locale(loc)->alt_month[_REL(ALTMON_1)];
+ break;
+ case ERA:
+ /* XXX: need to be implemented */
+ ret = "";
+ break;
+ case ERA_D_FMT:
+ /* XXX: need to be implemented */
+ ret = "";
+ break;
+ case ERA_D_T_FMT:
+ /* XXX: need to be implemented */
+ ret = "";
+ break;
+ case ERA_T_FMT:
+ /* XXX: need to be implemented */
+ ret = "";
+ break;
+ case ALT_DIGITS:
+ /* XXX: need to be implemented */
+ ret = "";
+ break;
+ case RADIXCHAR:
+ ret = (char*) __get_current_numeric_locale(loc)->decimal_point;
+ break;
+ case THOUSEP:
+ ret = (char*) __get_current_numeric_locale(loc)->thousands_sep;
+ break;
+ case YESEXPR:
+ ret = (char*) __get_current_messages_locale(loc)->yesexpr;
+ break;
+ case NOEXPR:
+ ret = (char*) __get_current_messages_locale(loc)->noexpr;
+ break;
+ /*
+ * YESSTR and NOSTR items marked with LEGACY are available, but not
+ * recomended by SUSv2 to be used in portable applications since
+ * they're subject to remove in future specification editions.
+ */
+ case YESSTR: /* LEGACY */
+ ret = (char*) __get_current_messages_locale(loc)->yesstr;
+ break;
+ case NOSTR: /* LEGACY */
+ ret = (char*) __get_current_messages_locale(loc)->nostr;
+ break;
+ /*
+ * SUSv2 special formatted currency string
+ */
+ case CRNCYSTR:
+ ret = "";
+ cs = (char*) __get_current_monetary_locale(loc)->currency_symbol;
+ if (*cs != '\0') {
+ char pos = localeconv_l(loc)->p_cs_precedes;
+
+ if (pos == localeconv_l(loc)->n_cs_precedes) {
+ char psn = '\0';
+
+ if (pos == CHAR_MAX) {
+ if (strcmp(cs, __get_current_monetary_locale(loc)->mon_decimal_point) == 0)
+ psn = '.';
+ } else
+ psn = pos ? '-' : '+';
+ if (psn != '\0') {
+ int clen = strlen(cs);
+
+ if ((loc->csym = reallocf(loc->csym, clen + 2)) != NULL) {
+ *loc->csym = psn;
+ strcpy(loc->csym + 1, cs);
+ ret = loc->csym;
+ }
+ }
+ }
+ }
+ break;
+ case D_MD_ORDER: /* FreeBSD local extension */
+ ret = (char *) __get_current_time_locale(loc)->md_order;
+ break;
+ default:
+ ret = "";
+ }
+ return (ret);
+}
+
+char *
+nl_langinfo(nl_item item)
+{
+ return nl_langinfo_l(item, __get_locale());
+}
diff --git a/lib/libc/locale/nomacros.c b/lib/libc/locale/nomacros.c
new file mode 100644
index 0000000..66cf40e
--- /dev/null
+++ b/lib/libc/locale/nomacros.c
@@ -0,0 +1,18 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Tell <ctype.h> to generate extern versions of all its inline
+ * functions. The extern versions get called if the system doesn't
+ * support inlines or the user defines _DONT_USE_CTYPE_INLINE_
+ * before including <ctype.h>.
+ */
+#define _EXTERNALIZE_CTYPE_INLINES_
+
+/*
+ * Also make sure <runetype.h> does not generate an inline definition
+ * of __getCurrentRuneLocale().
+ */
+#define __RUNETYPE_INTERNAL
+
+#include <ctype.h>
diff --git a/lib/libc/locale/none.c b/lib/libc/locale/none.c
new file mode 100644
index 0000000..75adffa
--- /dev/null
+++ b/lib/libc/locale/none.c
@@ -0,0 +1,222 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)none.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <runetype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+static size_t _none_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _none_mbsinit(const mbstate_t *);
+static size_t _none_mbsnrtowcs(wchar_t * __restrict dst,
+ const char ** __restrict src, size_t nms, size_t len,
+ mbstate_t * __restrict ps __unused);
+static size_t _none_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+static size_t _none_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
+ size_t, size_t, mbstate_t * __restrict);
+
+/* setup defaults */
+
+int __mb_cur_max = 1;
+int __mb_sb_limit = 256; /* Expected to be <= _CACHED_RUNES */
+
+int
+_none_init(struct xlocale_ctype *l, _RuneLocale *rl)
+{
+
+ l->__mbrtowc = _none_mbrtowc;
+ l->__mbsinit = _none_mbsinit;
+ l->__mbsnrtowcs = _none_mbsnrtowcs;
+ l->__wcrtomb = _none_wcrtomb;
+ l->__wcsnrtombs = _none_wcsnrtombs;
+ l->runes = rl;
+ l->__mb_cur_max = 1;
+ l->__mb_sb_limit = 256;
+ return(0);
+}
+
+static int
+_none_mbsinit(const mbstate_t *ps __unused)
+{
+
+ /*
+ * Encoding is not state dependent - we are always in the
+ * initial state.
+ */
+ return (1);
+}
+
+static size_t
+_none_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
+ mbstate_t * __restrict ps __unused)
+{
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (0);
+ if (n == 0)
+ /* Incomplete multibyte sequence */
+ return ((size_t)-2);
+ if (pwc != NULL)
+ *pwc = (unsigned char)*s;
+ return (*s == '\0' ? 0 : 1);
+}
+
+static size_t
+_none_wcrtomb(char * __restrict s, wchar_t wc,
+ mbstate_t * __restrict ps __unused)
+{
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (1);
+ if (wc < 0 || wc > UCHAR_MAX) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ *s = (unsigned char)wc;
+ return (1);
+}
+
+static size_t
+_none_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps __unused)
+{
+ const char *s;
+ size_t nchr;
+
+ if (dst == NULL) {
+ s = memchr(*src, '\0', nms);
+ return (s != NULL ? s - *src : nms);
+ }
+
+ s = *src;
+ nchr = 0;
+ while (len-- > 0 && nms-- > 0) {
+ if ((*dst++ = (unsigned char)*s++) == L'\0') {
+ *src = NULL;
+ return (nchr);
+ }
+ nchr++;
+ }
+ *src = s;
+ return (nchr);
+}
+
+static size_t
+_none_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
+ size_t nwc, size_t len, mbstate_t * __restrict ps __unused)
+{
+ const wchar_t *s;
+ size_t nchr;
+
+ if (dst == NULL) {
+ for (s = *src; nwc > 0 && *s != L'\0'; s++, nwc--) {
+ if (*s < 0 || *s > UCHAR_MAX) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ }
+ return (s - *src);
+ }
+
+ s = *src;
+ nchr = 0;
+ while (len-- > 0 && nwc-- > 0) {
+ if (*s < 0 || *s > UCHAR_MAX) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ if ((*dst++ = *s++) == '\0') {
+ *src = NULL;
+ return (nchr);
+ }
+ nchr++;
+ }
+ *src = s;
+ return (nchr);
+}
+
+/* setup defaults */
+
+size_t (*__mbrtowc)(wchar_t * __restrict, const char * __restrict, size_t,
+ mbstate_t * __restrict) = _none_mbrtowc;
+int (*__mbsinit)(const mbstate_t *) = _none_mbsinit;
+size_t (*__mbsnrtowcs)(wchar_t * __restrict, const char ** __restrict,
+ size_t, size_t, mbstate_t * __restrict) = _none_mbsnrtowcs;
+size_t (*__wcrtomb)(char * __restrict, wchar_t, mbstate_t * __restrict) =
+ _none_wcrtomb;
+size_t (*__wcsnrtombs)(char * __restrict, const wchar_t ** __restrict,
+ size_t, size_t, mbstate_t * __restrict) = _none_wcsnrtombs;
+
+struct xlocale_ctype __xlocale_global_ctype = {
+ {{0}, "C"},
+ (_RuneLocale*)&_DefaultRuneLocale,
+ _none_mbrtowc,
+ _none_mbsinit,
+ _none_mbsnrtowcs,
+ _none_wcrtomb,
+ _none_wcsnrtombs,
+ 1, /* __mb_cur_max, */
+ 256 /* __mb_sb_limit */
+};
+
+const struct xlocale_ctype __xlocale_C_ctype = {
+ {{0}, "C"},
+ (_RuneLocale*)&_DefaultRuneLocale,
+ _none_mbrtowc,
+ _none_mbsinit,
+ _none_mbsnrtowcs,
+ _none_wcrtomb,
+ _none_wcsnrtombs,
+ 1, /* __mb_cur_max, */
+ 256 /* __mb_sb_limit */
+};
diff --git a/lib/libc/locale/querylocale.3 b/lib/libc/locale/querylocale.3
new file mode 100644
index 0000000..a9d0182
--- /dev/null
+++ b/lib/libc/locale/querylocale.3
@@ -0,0 +1,57 @@
+.\" Copyright (c) 2011 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This documentation was written by David Chisnall under sponsorship from
+.\" the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 17 2011
+.Dt QUERYLOCALE 3
+.Os
+.Sh NAME
+.Nm querylocale
+.Nd Look up the locale name for a specified category.
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In xlocale.h
+.Ft const char *
+.Fn querylocale "int mask" "locale_t locale"
+.Sh DESCRIPTION
+Returns the name of the locale for the category specified by
+.Fa mask.
+This possible values for the mask are the same as those in
+.Xr newlocale 3 .
+If more than one bit in the mask is set, the returned value is undefined.
+.Sh SEE ALSO
+.Xr duplocale 3 ,
+.Xr freelocale 3 ,
+.Xr localeconv 3 ,
+.Xr newlocale 3 ,
+.Xr uselocale 3 ,
+.Xr xlocale 3
+.Sh STANDARDS
+This function, conforms to
+.St -p1003.1-2008
diff --git a/lib/libc/locale/rpmatch.3 b/lib/libc/locale/rpmatch.3
new file mode 100644
index 0000000..b34c5bf
--- /dev/null
+++ b/lib/libc/locale/rpmatch.3
@@ -0,0 +1,66 @@
+.\"
+.\" Copyright (c) 2005 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 21, 2005
+.Dt RPMATCH 3
+.Os
+.Sh NAME
+.Nm rpmatch
+.Nd "determine whether the response to a question is affirmative or negative"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fn rpmatch "const char *response"
+.Sh DESCRIPTION
+The
+.Fn rpmatch
+function determines whether the
+.Fa response
+argument is an affirmative or negative response to a question
+according to the current locale.
+.Sh RETURN VALUES
+The
+.Fn rpmatch
+functions returns:
+.Bl -tag -width indent
+.It 1
+The response is affirmative.
+.It 0
+The response is negative.
+.It \&-1
+The response is not recognized.
+.El
+.Sh SEE ALSO
+.Xr nl_langinfo 3 ,
+.Xr setlocale 3
+.Sh HISTORY
+The
+.Fn rpmatch
+function appeared in
+.Fx 6.0 .
diff --git a/lib/libc/locale/rpmatch.c b/lib/libc/locale/rpmatch.c
new file mode 100644
index 0000000..4d90eb8
--- /dev/null
+++ b/lib/libc/locale/rpmatch.c
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2004-2005 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <langinfo.h>
+#include <regex.h>
+#include <stdlib.h>
+
+int
+rpmatch(const char *response)
+{
+ regex_t yes, no;
+ int ret;
+
+ if (regcomp(&yes, nl_langinfo(YESEXPR), REG_EXTENDED|REG_NOSUB) != 0)
+ return (-1);
+ if (regcomp(&no, nl_langinfo(NOEXPR), REG_EXTENDED|REG_NOSUB) != 0) {
+ regfree(&yes);
+ return (-1);
+ }
+ if (regexec(&yes, response, 0, NULL, 0) == 0)
+ ret = 1;
+ else if (regexec(&no, response, 0, NULL, 0) == 0)
+ ret = 0;
+ else
+ ret = -1;
+ regfree(&yes);
+ regfree(&no);
+ return (ret);
+}
diff --git a/lib/libc/locale/rune.c b/lib/libc/locale/rune.c
new file mode 100644
index 0000000..f72ba74
--- /dev/null
+++ b/lib/libc/locale/rune.c
@@ -0,0 +1,286 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rune.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <arpa/inet.h>
+#include <errno.h>
+#include <runetype.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include "un-namespace.h"
+
+#include "runefile.h"
+
+_RuneLocale *_Read_RuneMagi(FILE *);
+
+_RuneLocale *
+_Read_RuneMagi(FILE *fp)
+{
+ char *fdata, *data;
+ void *lastp;
+ _FileRuneLocale *frl;
+ _RuneLocale *rl;
+ _FileRuneEntry *frr;
+ _RuneEntry *rr;
+ struct stat sb;
+ int x, saverr;
+ void *variable;
+ _FileRuneEntry *runetype_ext_ranges;
+ _FileRuneEntry *maplower_ext_ranges;
+ _FileRuneEntry *mapupper_ext_ranges;
+ int runetype_ext_len = 0;
+
+ if (_fstat(fileno(fp), &sb) < 0)
+ return (NULL);
+
+ if ((size_t)sb.st_size < sizeof(_FileRuneLocale)) {
+ errno = EFTYPE;
+ return (NULL);
+ }
+
+ if ((fdata = malloc(sb.st_size)) == NULL)
+ return (NULL);
+
+ errno = 0;
+ rewind(fp); /* Someone might have read the magic number once already */
+ if (errno) {
+ saverr = errno;
+ free(fdata);
+ errno = saverr;
+ return (NULL);
+ }
+
+ if (fread(fdata, sb.st_size, 1, fp) != 1) {
+ saverr = errno;
+ free(fdata);
+ errno = saverr;
+ return (NULL);
+ }
+
+ frl = (_FileRuneLocale *)fdata;
+ lastp = fdata + sb.st_size;
+
+ variable = frl + 1;
+
+ if (memcmp(frl->magic, _FILE_RUNE_MAGIC_1, sizeof(frl->magic))) {
+ free(fdata);
+ errno = EFTYPE;
+ return (NULL);
+ }
+
+ frl->variable_len = ntohl(frl->variable_len);
+ frl->runetype_ext_nranges = ntohl(frl->runetype_ext_nranges);
+ frl->maplower_ext_nranges = ntohl(frl->maplower_ext_nranges);
+ frl->mapupper_ext_nranges = ntohl(frl->mapupper_ext_nranges);
+
+ for (x = 0; x < _CACHED_RUNES; ++x) {
+ frl->runetype[x] = ntohl(frl->runetype[x]);
+ frl->maplower[x] = ntohl(frl->maplower[x]);
+ frl->mapupper[x] = ntohl(frl->mapupper[x]);
+ }
+
+ runetype_ext_ranges = (_FileRuneEntry *)variable;
+ variable = runetype_ext_ranges + frl->runetype_ext_nranges;
+ if (variable > lastp) {
+ free(fdata);
+ errno = EFTYPE;
+ return (NULL);
+ }
+
+ maplower_ext_ranges = (_FileRuneEntry *)variable;
+ variable = maplower_ext_ranges + frl->maplower_ext_nranges;
+ if (variable > lastp) {
+ free(fdata);
+ errno = EFTYPE;
+ return (NULL);
+ }
+
+ mapupper_ext_ranges = (_FileRuneEntry *)variable;
+ variable = mapupper_ext_ranges + frl->mapupper_ext_nranges;
+ if (variable > lastp) {
+ free(fdata);
+ errno = EFTYPE;
+ return (NULL);
+ }
+
+ frr = runetype_ext_ranges;
+ for (x = 0; x < frl->runetype_ext_nranges; ++x) {
+ uint32_t *types;
+
+ frr[x].min = ntohl(frr[x].min);
+ frr[x].max = ntohl(frr[x].max);
+ frr[x].map = ntohl(frr[x].map);
+ if (frr[x].map == 0) {
+ int len = frr[x].max - frr[x].min + 1;
+ types = variable;
+ variable = types + len;
+ runetype_ext_len += len;
+ if (variable > lastp) {
+ free(fdata);
+ errno = EFTYPE;
+ return (NULL);
+ }
+ while (len-- > 0)
+ types[len] = ntohl(types[len]);
+ }
+ }
+
+ frr = maplower_ext_ranges;
+ for (x = 0; x < frl->maplower_ext_nranges; ++x) {
+ frr[x].min = ntohl(frr[x].min);
+ frr[x].max = ntohl(frr[x].max);
+ frr[x].map = ntohl(frr[x].map);
+ }
+
+ frr = mapupper_ext_ranges;
+ for (x = 0; x < frl->mapupper_ext_nranges; ++x) {
+ frr[x].min = ntohl(frr[x].min);
+ frr[x].max = ntohl(frr[x].max);
+ frr[x].map = ntohl(frr[x].map);
+ }
+ if ((char *)variable + frl->variable_len > (char *)lastp) {
+ free(fdata);
+ errno = EFTYPE;
+ return (NULL);
+ }
+
+ /*
+ * Convert from disk format to host format.
+ */
+ data = malloc(sizeof(_RuneLocale) +
+ (frl->runetype_ext_nranges + frl->maplower_ext_nranges +
+ frl->mapupper_ext_nranges) * sizeof(_RuneEntry) +
+ runetype_ext_len * sizeof(*rr->__types) +
+ frl->variable_len);
+ if (data == NULL) {
+ saverr = errno;
+ free(fdata);
+ errno = saverr;
+ return (NULL);
+ }
+
+ rl = (_RuneLocale *)data;
+ rl->__variable = rl + 1;
+
+ memcpy(rl->__magic, _RUNE_MAGIC_1, sizeof(rl->__magic));
+ memcpy(rl->__encoding, frl->encoding, sizeof(rl->__encoding));
+ rl->__invalid_rune = 0;
+
+ rl->__variable_len = frl->variable_len;
+ rl->__runetype_ext.__nranges = frl->runetype_ext_nranges;
+ rl->__maplower_ext.__nranges = frl->maplower_ext_nranges;
+ rl->__mapupper_ext.__nranges = frl->mapupper_ext_nranges;
+
+ for (x = 0; x < _CACHED_RUNES; ++x) {
+ rl->__runetype[x] = frl->runetype[x];
+ rl->__maplower[x] = frl->maplower[x];
+ rl->__mapupper[x] = frl->mapupper[x];
+ }
+
+ rl->__runetype_ext.__ranges = (_RuneEntry *)rl->__variable;
+ rl->__variable = rl->__runetype_ext.__ranges +
+ rl->__runetype_ext.__nranges;
+
+ rl->__maplower_ext.__ranges = (_RuneEntry *)rl->__variable;
+ rl->__variable = rl->__maplower_ext.__ranges +
+ rl->__maplower_ext.__nranges;
+
+ rl->__mapupper_ext.__ranges = (_RuneEntry *)rl->__variable;
+ rl->__variable = rl->__mapupper_ext.__ranges +
+ rl->__mapupper_ext.__nranges;
+
+ variable = mapupper_ext_ranges + frl->mapupper_ext_nranges;
+ frr = runetype_ext_ranges;
+ rr = rl->__runetype_ext.__ranges;
+ for (x = 0; x < rl->__runetype_ext.__nranges; ++x) {
+ uint32_t *types;
+
+ rr[x].__min = frr[x].min;
+ rr[x].__max = frr[x].max;
+ rr[x].__map = frr[x].map;
+ if (rr[x].__map == 0) {
+ int len = rr[x].__max - rr[x].__min + 1;
+ types = variable;
+ variable = types + len;
+ rr[x].__types = rl->__variable;
+ rl->__variable = rr[x].__types + len;
+ while (len-- > 0)
+ rr[x].__types[len] = types[len];
+ } else
+ rr[x].__types = NULL;
+ }
+
+ frr = maplower_ext_ranges;
+ rr = rl->__maplower_ext.__ranges;
+ for (x = 0; x < rl->__maplower_ext.__nranges; ++x) {
+ rr[x].__min = frr[x].min;
+ rr[x].__max = frr[x].max;
+ rr[x].__map = frr[x].map;
+ }
+
+ frr = mapupper_ext_ranges;
+ rr = rl->__mapupper_ext.__ranges;
+ for (x = 0; x < rl->__mapupper_ext.__nranges; ++x) {
+ rr[x].__min = frr[x].min;
+ rr[x].__max = frr[x].max;
+ rr[x].__map = frr[x].map;
+ }
+
+ memcpy(rl->__variable, variable, rl->__variable_len);
+ free(fdata);
+
+ /*
+ * Go out and zero pointers that should be zero.
+ */
+ if (!rl->__variable_len)
+ rl->__variable = NULL;
+
+ if (!rl->__runetype_ext.__nranges)
+ rl->__runetype_ext.__ranges = NULL;
+
+ if (!rl->__maplower_ext.__nranges)
+ rl->__maplower_ext.__ranges = NULL;
+
+ if (!rl->__mapupper_ext.__nranges)
+ rl->__mapupper_ext.__ranges = NULL;
+
+ return (rl);
+}
diff --git a/lib/libc/locale/runefile.h b/lib/libc/locale/runefile.h
new file mode 100644
index 0000000..ce1e47e
--- /dev/null
+++ b/lib/libc/locale/runefile.h
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 2005 Ruslan Ermilov
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _RUNEFILE_H_
+#define _RUNEFILE_H_
+
+#include <sys/types.h>
+
+#ifndef _CACHED_RUNES
+#define _CACHED_RUNES (1 << 8)
+#endif
+
+typedef struct {
+ int32_t min;
+ int32_t max;
+ int32_t map;
+} _FileRuneEntry;
+
+typedef struct {
+ char magic[8];
+ char encoding[32];
+
+ uint32_t runetype[_CACHED_RUNES];
+ int32_t maplower[_CACHED_RUNES];
+ int32_t mapupper[_CACHED_RUNES];
+
+ int32_t runetype_ext_nranges;
+ int32_t maplower_ext_nranges;
+ int32_t mapupper_ext_nranges;
+
+ int32_t variable_len;
+} _FileRuneLocale;
+
+#define _FILE_RUNE_MAGIC_1 "RuneMag1"
+
+#endif /* !_RUNEFILE_H_ */
diff --git a/lib/libc/locale/runetype.c b/lib/libc/locale/runetype.c
new file mode 100644
index 0000000..a0da47b
--- /dev/null
+++ b/lib/libc/locale/runetype.c
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <stdio.h>
+#include <runetype.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+unsigned long
+___runetype_l(__ct_rune_t c, locale_t locale)
+{
+ size_t lim;
+ FIX_LOCALE(locale);
+ _RuneRange *rr = &(XLOCALE_CTYPE(locale)->runes->__runetype_ext);
+ _RuneEntry *base, *re;
+
+ if (c < 0 || c == EOF)
+ return(0L);
+
+ /* Binary search -- see bsearch.c for explanation. */
+ base = rr->__ranges;
+ for (lim = rr->__nranges; lim != 0; lim >>= 1) {
+ re = base + (lim >> 1);
+ if (re->__min <= c && c <= re->__max) {
+ if (re->__types)
+ return(re->__types[c - re->__min]);
+ else
+ return(re->__map);
+ } else if (c > re->__max) {
+ base = re + 1;
+ lim--;
+ }
+ }
+
+ return(0L);
+}
+unsigned long
+___runetype(__ct_rune_t c)
+{
+ return ___runetype_l(c, __get_locale());
+}
+
+int ___mb_cur_max(void)
+{
+ return XLOCALE_CTYPE(__get_locale())->__mb_cur_max;
+}
+int ___mb_cur_max_l(locale_t locale)
+{
+ FIX_LOCALE(locale);
+ return XLOCALE_CTYPE(locale)->__mb_cur_max;
+}
diff --git a/lib/libc/locale/setlocale.3 b/lib/libc/locale/setlocale.3
new file mode 100644
index 0000000..e0d06e8
--- /dev/null
+++ b/lib/libc/locale/setlocale.3
@@ -0,0 +1,173 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Donn Seeley at BSDI.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)setlocale.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd November 21, 2003
+.Dt SETLOCALE 3
+.Os
+.Sh NAME
+.Nm setlocale
+.Nd natural language formatting for C
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In locale.h
+.Ft char *
+.Fn setlocale "int category" "const char *locale"
+.Sh DESCRIPTION
+The
+.Fn setlocale
+function sets the C library's notion
+of natural language formatting style
+for particular sets of routines.
+Each such style is called a
+.Sq locale
+and is invoked using an appropriate name passed as a C string.
+.Pp
+The
+.Fn setlocale
+function recognizes several categories of routines.
+These are the categories and the sets of routines they select:
+.Bl -tag -width LC_MONETARY
+.It Dv LC_ALL
+Set the entire locale generically.
+.It Dv LC_COLLATE
+Set a locale for string collation routines.
+This controls alphabetic ordering in
+.Fn strcoll
+and
+.Fn strxfrm .
+.It Dv LC_CTYPE
+Set a locale for the
+.Xr ctype 3
+and
+.Xr multibyte 3
+functions.
+This controls recognition of upper and lower case,
+alphabetic or non-alphabetic characters,
+and so on.
+.It Dv LC_MESSAGES
+Set a locale for message catalogs, see
+.Xr catopen 3
+function.
+.It Dv LC_MONETARY
+Set a locale for formatting monetary values;
+this affects the
+.Fn localeconv
+function.
+.It Dv LC_NUMERIC
+Set a locale for formatting numbers.
+This controls the formatting of decimal points
+in input and output of floating point numbers
+in functions such as
+.Fn printf
+and
+.Fn scanf ,
+as well as values returned by
+.Fn localeconv .
+.It Dv LC_TIME
+Set a locale for formatting dates and times using the
+.Fn strftime
+function.
+.El
+.Pp
+Only three locales are defined by default,
+the empty string
+.Li \&"\|"
+which denotes the native environment, and the
+.Li \&"C"
+and
+.Li \&"POSIX"
+locales, which denote the C language environment.
+A
+.Fa locale
+argument of
+.Dv NULL
+causes
+.Fn setlocale
+to return the current locale.
+By default, C programs start in the
+.Li \&"C"
+locale.
+The only function in the library that sets the locale is
+.Fn setlocale ;
+the locale is never changed as a side effect of some other routine.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn setlocale
+returns the string associated with the specified
+.Fa category
+for the requested
+.Fa locale .
+The
+.Fn setlocale
+function returns
+.Dv NULL
+and fails to change the locale
+if the given combination of
+.Fa category
+and
+.Fa locale
+makes no sense.
+.Sh FILES
+.Bl -tag -width /usr/share/locale/locale/category -compact
+.It Pa $PATH_LOCALE/ Ns Em locale/category
+.It Pa /usr/share/locale/ Ns Em locale/category
+locale file for the locale
+.Em locale
+and the category
+.Em category .
+.El
+.Sh ERRORS
+No errors are defined.
+.Sh SEE ALSO
+.Xr colldef 1 ,
+.Xr mklocale 1 ,
+.Xr catopen 3 ,
+.Xr ctype 3 ,
+.Xr localeconv 3 ,
+.Xr multibyte 3 ,
+.Xr strcoll 3 ,
+.Xr strxfrm 3 ,
+.Xr euc 5 ,
+.Xr utf8 5 ,
+.Xr environ 7
+.Sh STANDARDS
+The
+.Fn setlocale
+function conforms to
+.St -isoC-99 .
+.Sh HISTORY
+The
+.Fn setlocale
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/locale/setlocale.c b/lib/libc/locale/setlocale.c
new file mode 100644
index 0000000..0322af2
--- /dev/null
+++ b/lib/libc/locale/setlocale.c
@@ -0,0 +1,333 @@
+/*
+ * Copyright (c) 1996 - 2002 FreeBSD Project
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setlocale.c 8.1 (Berkeley) 7/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <paths.h> /* for _PATH_LOCALE */
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "collate.h"
+#include "lmonetary.h" /* for __monetary_load_locale() */
+#include "lnumeric.h" /* for __numeric_load_locale() */
+#include "lmessages.h" /* for __messages_load_locale() */
+#include "setlocale.h"
+#include "ldpart.h"
+#include "../stdtime/timelocal.h" /* for __time_load_locale() */
+
+/*
+ * Category names for getenv()
+ */
+static const char categories[_LC_LAST][12] = {
+ "LC_ALL",
+ "LC_COLLATE",
+ "LC_CTYPE",
+ "LC_MONETARY",
+ "LC_NUMERIC",
+ "LC_TIME",
+ "LC_MESSAGES",
+};
+
+/*
+ * Current locales for each category
+ */
+static char current_categories[_LC_LAST][ENCODING_LEN + 1] = {
+ "C",
+ "C",
+ "C",
+ "C",
+ "C",
+ "C",
+ "C",
+};
+
+/*
+ * Path to locale storage directory
+ */
+char *_PathLocale;
+
+/*
+ * The locales we are going to try and load
+ */
+static char new_categories[_LC_LAST][ENCODING_LEN + 1];
+static char saved_categories[_LC_LAST][ENCODING_LEN + 1];
+
+static char current_locale_string[_LC_LAST * (ENCODING_LEN + 1/*"/"*/ + 1)];
+
+static char *currentlocale(void);
+static char *loadlocale(int);
+const char *__get_locale_env(int);
+
+char *
+setlocale(category, locale)
+ int category;
+ const char *locale;
+{
+ int i, j, len, saverr;
+ const char *env, *r;
+
+ if (category < LC_ALL || category >= _LC_LAST) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (locale == NULL)
+ return (category != LC_ALL ?
+ current_categories[category] : currentlocale());
+
+ /*
+ * Default to the current locale for everything.
+ */
+ for (i = 1; i < _LC_LAST; ++i)
+ (void)strcpy(new_categories[i], current_categories[i]);
+
+ /*
+ * Now go fill up new_categories from the locale argument
+ */
+ if (!*locale) {
+ if (category == LC_ALL) {
+ for (i = 1; i < _LC_LAST; ++i) {
+ env = __get_locale_env(i);
+ if (strlen(env) > ENCODING_LEN) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ (void)strcpy(new_categories[i], env);
+ }
+ } else {
+ env = __get_locale_env(category);
+ if (strlen(env) > ENCODING_LEN) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ (void)strcpy(new_categories[category], env);
+ }
+ } else if (category != LC_ALL) {
+ if (strlen(locale) > ENCODING_LEN) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ (void)strcpy(new_categories[category], locale);
+ } else {
+ if ((r = strchr(locale, '/')) == NULL) {
+ if (strlen(locale) > ENCODING_LEN) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ for (i = 1; i < _LC_LAST; ++i)
+ (void)strcpy(new_categories[i], locale);
+ } else {
+ for (i = 1; r[1] == '/'; ++r)
+ ;
+ if (!r[1]) {
+ errno = EINVAL;
+ return (NULL); /* Hmm, just slashes... */
+ }
+ do {
+ if (i == _LC_LAST)
+ break; /* Too many slashes... */
+ if ((len = r - locale) > ENCODING_LEN) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ (void)strlcpy(new_categories[i], locale,
+ len + 1);
+ i++;
+ while (*r == '/')
+ r++;
+ locale = r;
+ while (*r && *r != '/')
+ r++;
+ } while (*locale);
+ while (i < _LC_LAST) {
+ (void)strcpy(new_categories[i],
+ new_categories[i-1]);
+ i++;
+ }
+ }
+ }
+
+ if (category != LC_ALL)
+ return (loadlocale(category));
+
+ for (i = 1; i < _LC_LAST; ++i) {
+ (void)strcpy(saved_categories[i], current_categories[i]);
+ if (loadlocale(i) == NULL) {
+ saverr = errno;
+ for (j = 1; j < i; j++) {
+ (void)strcpy(new_categories[j],
+ saved_categories[j]);
+ if (loadlocale(j) == NULL) {
+ (void)strcpy(new_categories[j], "C");
+ (void)loadlocale(j);
+ }
+ }
+ errno = saverr;
+ return (NULL);
+ }
+ }
+ return (currentlocale());
+}
+
+static char *
+currentlocale()
+{
+ int i;
+
+ (void)strcpy(current_locale_string, current_categories[1]);
+
+ for (i = 2; i < _LC_LAST; ++i)
+ if (strcmp(current_categories[1], current_categories[i])) {
+ for (i = 2; i < _LC_LAST; ++i) {
+ (void)strcat(current_locale_string, "/");
+ (void)strcat(current_locale_string,
+ current_categories[i]);
+ }
+ break;
+ }
+ return (current_locale_string);
+}
+
+static char *
+loadlocale(category)
+ int category;
+{
+ char *new = new_categories[category];
+ char *old = current_categories[category];
+ int (*func)(const char *);
+ int saved_errno;
+
+ if ((new[0] == '.' &&
+ (new[1] == '\0' || (new[1] == '.' && new[2] == '\0'))) ||
+ strchr(new, '/') != NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ saved_errno = errno;
+ errno = __detect_path_locale();
+ if (errno != 0)
+ return (NULL);
+ errno = saved_errno;
+
+ switch (category) {
+ case LC_CTYPE:
+ func = __wrap_setrunelocale;
+ break;
+ case LC_COLLATE:
+ func = __collate_load_tables;
+ break;
+ case LC_TIME:
+ func = __time_load_locale;
+ break;
+ case LC_NUMERIC:
+ func = __numeric_load_locale;
+ break;
+ case LC_MONETARY:
+ func = __monetary_load_locale;
+ break;
+ case LC_MESSAGES:
+ func = __messages_load_locale;
+ break;
+ default:
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if (strcmp(new, old) == 0)
+ return (old);
+
+ if (func(new) != _LDP_ERROR) {
+ (void)strcpy(old, new);
+ (void)strcpy(__xlocale_global_locale.components[category-1]->locale, new);
+ return (old);
+ }
+
+ return (NULL);
+}
+
+const char *
+__get_locale_env(category)
+ int category;
+{
+ const char *env;
+
+ /* 1. check LC_ALL. */
+ env = getenv(categories[0]);
+
+ /* 2. check LC_* */
+ if (env == NULL || !*env)
+ env = getenv(categories[category]);
+
+ /* 3. check LANG */
+ if (env == NULL || !*env)
+ env = getenv("LANG");
+
+ /* 4. if none is set, fall to "C" */
+ if (env == NULL || !*env)
+ env = "C";
+
+ return (env);
+}
+
+/*
+ * Detect locale storage location and store its value to _PathLocale variable
+ */
+int
+__detect_path_locale(void)
+{
+ if (_PathLocale == NULL) {
+ char *p = getenv("PATH_LOCALE");
+
+ if (p != NULL && !issetugid()) {
+ if (strlen(p) + 1/*"/"*/ + ENCODING_LEN +
+ 1/*"/"*/ + CATEGORY_LEN >= PATH_MAX)
+ return (ENAMETOOLONG);
+ _PathLocale = strdup(p);
+ if (_PathLocale == NULL)
+ return (errno == 0 ? ENOMEM : errno);
+ } else
+ _PathLocale = _PATH_LOCALE;
+ }
+ return (0);
+}
+
diff --git a/lib/libc/locale/setlocale.h b/lib/libc/locale/setlocale.h
new file mode 100644
index 0000000..33b4b6e
--- /dev/null
+++ b/lib/libc/locale/setlocale.h
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (C) 1997 by Andrey A. Chernov, Moscow, Russia.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _SETLOCALE_H_
+#define _SETLOCALE_H_
+
+#define ENCODING_LEN 31
+#define CATEGORY_LEN 11
+
+extern char *_PathLocale;
+
+int __detect_path_locale(void);
+int __wrap_setrunelocale(const char *);
+
+#endif /* !_SETLOCALE_H_ */
diff --git a/lib/libc/locale/setrunelocale.c b/lib/libc/locale/setrunelocale.c
new file mode 100644
index 0000000..bc04e9e
--- /dev/null
+++ b/lib/libc/locale/setrunelocale.c
@@ -0,0 +1,210 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define __RUNETYPE_INTERNAL 1
+
+#include <runetype.h>
+#include <errno.h>
+#include <limits.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <wchar.h>
+#include "ldpart.h"
+#include "mblocal.h"
+#include "setlocale.h"
+
+#undef _CurrentRuneLocale
+extern _RuneLocale const *_CurrentRuneLocale;
+#ifndef __NO_TLS
+/*
+ * A cached version of the runes for this thread. Used by ctype.h
+ */
+_Thread_local const _RuneLocale *_ThreadRuneLocale;
+#endif
+
+extern int __mb_sb_limit;
+
+extern _RuneLocale *_Read_RuneMagi(FILE *);
+
+static int __setrunelocale(struct xlocale_ctype *l, const char *);
+
+#define __collate_load_error (table->__collate_load_error)
+#define __collate_substitute_nontrivial (table->__collate_substitute_nontrivial)
+#define __collate_substitute_table_ptr (table->__collate_substitute_table_ptr)
+#define __collate_char_pri_table_ptr (table->__collate_char_pri_table_ptr)
+#define __collate_chain_pri_table (table->__collate_chain_pri_table)
+
+
+static void destruct_ctype(void *v)
+{
+ struct xlocale_ctype *l = v;
+ if (strcmp(l->runes->__encoding, "EUC") == 0)
+ free(l->runes->__variable);
+ if (&_DefaultRuneLocale != l->runes)
+ free(l->runes);
+ free(l);
+}
+
+const _RuneLocale *__getCurrentRuneLocale(void)
+{
+ return XLOCALE_CTYPE(__get_locale())->runes;
+}
+
+static int
+__setrunelocale(struct xlocale_ctype *l, const char *encoding)
+{
+ FILE *fp;
+ char name[PATH_MAX];
+ _RuneLocale *rl;
+ int saverr, ret;
+ struct xlocale_ctype saved = *l;
+
+ /*
+ * The "C" and "POSIX" locale are always here.
+ */
+ if (strcmp(encoding, "C") == 0 || strcmp(encoding, "POSIX") == 0) {
+ (void) _none_init(l, (_RuneLocale*)&_DefaultRuneLocale);
+ return (0);
+ }
+
+ /* Range checking not needed, encoding length already checked before */
+ (void) strcpy(name, _PathLocale);
+ (void) strcat(name, "/");
+ (void) strcat(name, encoding);
+ (void) strcat(name, "/LC_CTYPE");
+
+ if ((fp = fopen(name, "r")) == NULL)
+ return (errno == 0 ? ENOENT : errno);
+
+ if ((rl = _Read_RuneMagi(fp)) == NULL) {
+ saverr = (errno == 0 ? EFTYPE : errno);
+ (void)fclose(fp);
+ return (saverr);
+ }
+ (void)fclose(fp);
+
+ l->__mbrtowc = NULL;
+ l->__mbsinit = NULL;
+ l->__mbsnrtowcs = __mbsnrtowcs_std;
+ l->__wcrtomb = NULL;
+ l->__wcsnrtombs = __wcsnrtombs_std;
+
+ rl->__sputrune = NULL;
+ rl->__sgetrune = NULL;
+ if (strcmp(rl->__encoding, "NONE") == 0)
+ ret = _none_init(l, rl);
+ else if (strcmp(rl->__encoding, "ASCII") == 0)
+ ret = _ascii_init(l, rl);
+ else if (strcmp(rl->__encoding, "UTF-8") == 0)
+ ret = _UTF8_init(l, rl);
+ else if (strcmp(rl->__encoding, "EUC") == 0)
+ ret = _EUC_init(l, rl);
+ else if (strcmp(rl->__encoding, "GB18030") == 0)
+ ret = _GB18030_init(l, rl);
+ else if (strcmp(rl->__encoding, "GB2312") == 0)
+ ret = _GB2312_init(l, rl);
+ else if (strcmp(rl->__encoding, "GBK") == 0)
+ ret = _GBK_init(l, rl);
+ else if (strcmp(rl->__encoding, "BIG5") == 0)
+ ret = _BIG5_init(l, rl);
+ else if (strcmp(rl->__encoding, "MSKanji") == 0)
+ ret = _MSKanji_init(l, rl);
+ else
+ ret = EFTYPE;
+
+ if (ret == 0) {
+ /* Free the old runes if it exists. */
+ /* FIXME: The "EUC" check here is a hideous abstraction violation. */
+ if ((saved.runes != &_DefaultRuneLocale) && (saved.runes)) {
+ if (strcmp(saved.runes->__encoding, "EUC") == 0) {
+ free(saved.runes->__variable);
+ }
+ free(saved.runes);
+ }
+ } else {
+ /* Restore the saved version if this failed. */
+ memcpy(l, &saved, sizeof(struct xlocale_ctype));
+ free(rl);
+ }
+
+ return (ret);
+}
+
+int
+__wrap_setrunelocale(const char *locale)
+{
+ int ret = __setrunelocale(&__xlocale_global_ctype, locale);
+
+ if (ret != 0) {
+ errno = ret;
+ return (_LDP_ERROR);
+ }
+ __mb_cur_max = __xlocale_global_ctype.__mb_cur_max;
+ __mb_sb_limit = __xlocale_global_ctype.__mb_sb_limit;
+ _CurrentRuneLocale = __xlocale_global_ctype.runes;
+ return (_LDP_LOADED);
+}
+
+#ifndef __NO_TLS
+void
+__set_thread_rune_locale(locale_t loc) {
+
+ if (loc == NULL) {
+ _ThreadRuneLocale = &_DefaultRuneLocale;
+ } else {
+ _ThreadRuneLocale = XLOCALE_CTYPE(loc)->runes;
+ }
+}
+#endif
+
+void *
+__ctype_load(const char *locale, locale_t unused)
+{
+ struct xlocale_ctype *l = calloc(sizeof(struct xlocale_ctype), 1);
+ l->header.header.destructor = destruct_ctype;
+ if (__setrunelocale(l, locale))
+ {
+ free(l);
+ return NULL;
+ }
+ return l;
+}
diff --git a/lib/libc/locale/table.c b/lib/libc/locale/table.c
new file mode 100644
index 0000000..e89d479
--- /dev/null
+++ b/lib/libc/locale/table.c
@@ -0,0 +1,263 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)table.c 8.1 (Berkeley) 6/27/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <runetype.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+const _RuneLocale _DefaultRuneLocale = {
+ _RUNE_MAGIC_1,
+ "NONE",
+ NULL,
+ NULL,
+ 0xFFFD,
+
+ { /*00*/ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ /*08*/ _CTYPE_C,
+ _CTYPE_C|_CTYPE_S|_CTYPE_B,
+ _CTYPE_C|_CTYPE_S,
+ _CTYPE_C|_CTYPE_S,
+ _CTYPE_C|_CTYPE_S,
+ _CTYPE_C|_CTYPE_S,
+ _CTYPE_C,
+ _CTYPE_C,
+ /*10*/ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ /*18*/ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ _CTYPE_C,
+ /*20*/ _CTYPE_S|_CTYPE_B|_CTYPE_R,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ /*28*/ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ /*30*/ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|0,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|1,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|2,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|3,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|4,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|5,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|6,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|7,
+ /*38*/ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|8,
+ _CTYPE_D|_CTYPE_R|_CTYPE_G|_CTYPE_X|9,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ /*40*/ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_U|_CTYPE_X|_CTYPE_R|_CTYPE_G|_CTYPE_A|10,
+ _CTYPE_U|_CTYPE_X|_CTYPE_R|_CTYPE_G|_CTYPE_A|11,
+ _CTYPE_U|_CTYPE_X|_CTYPE_R|_CTYPE_G|_CTYPE_A|12,
+ _CTYPE_U|_CTYPE_X|_CTYPE_R|_CTYPE_G|_CTYPE_A|13,
+ _CTYPE_U|_CTYPE_X|_CTYPE_R|_CTYPE_G|_CTYPE_A|14,
+ _CTYPE_U|_CTYPE_X|_CTYPE_R|_CTYPE_G|_CTYPE_A|15,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ /*48*/ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ /*50*/ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ /*58*/ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_U|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ /*60*/ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_L|_CTYPE_X|_CTYPE_R|_CTYPE_G|_CTYPE_A|10,
+ _CTYPE_L|_CTYPE_X|_CTYPE_R|_CTYPE_G|_CTYPE_A|11,
+ _CTYPE_L|_CTYPE_X|_CTYPE_R|_CTYPE_G|_CTYPE_A|12,
+ _CTYPE_L|_CTYPE_X|_CTYPE_R|_CTYPE_G|_CTYPE_A|13,
+ _CTYPE_L|_CTYPE_X|_CTYPE_R|_CTYPE_G|_CTYPE_A|14,
+ _CTYPE_L|_CTYPE_X|_CTYPE_R|_CTYPE_G|_CTYPE_A|15,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ /*68*/ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ /*70*/ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ /*78*/ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_L|_CTYPE_R|_CTYPE_G|_CTYPE_A,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_P|_CTYPE_R|_CTYPE_G,
+ _CTYPE_C,
+ },
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 'a', 'b', 'c', 'd', 'e', 'f', 'g',
+ 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o',
+ 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
+ 'x', 'y', 'z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+ },
+ { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
+ 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
+ 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f,
+ 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
+ 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d, 0x2e, 0x2f,
+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
+ 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d, 0x3e, 0x3f,
+ 0x40, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', 0x5b, 0x5c, 0x5d, 0x5e, 0x5f,
+ 0x60, 'A', 'B', 'C', 'D', 'E', 'F', 'G',
+ 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O',
+ 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W',
+ 'X', 'Y', 'Z', 0x7b, 0x7c, 0x7d, 0x7e, 0x7f,
+ 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x8b, 0x8c, 0x8d, 0x8e, 0x8f,
+ 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
+ 0x98, 0x99, 0x9a, 0x9b, 0x9c, 0x9d, 0x9e, 0x9f,
+ 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xab, 0xac, 0xad, 0xae, 0xaf,
+ 0xb0, 0xb1, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7,
+ 0xb8, 0xb9, 0xba, 0xbb, 0xbc, 0xbd, 0xbe, 0xbf,
+ 0xc0, 0xc1, 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7,
+ 0xc8, 0xc9, 0xca, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
+ 0xd0, 0xd1, 0xd2, 0xd3, 0xd4, 0xd5, 0xd6, 0xd7,
+ 0xd8, 0xd9, 0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf,
+ 0xe0, 0xe1, 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7,
+ 0xe8, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef,
+ 0xf0, 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7,
+ 0xf8, 0xf9, 0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff,
+ },
+};
+
+#undef _CurrentRuneLocale
+const _RuneLocale *_CurrentRuneLocale = &_DefaultRuneLocale;
+
+_RuneLocale *
+__runes_for_locale(locale_t locale, int *mb_sb_limit)
+{
+ FIX_LOCALE(locale);
+ struct xlocale_ctype *c = XLOCALE_CTYPE(locale);
+ *mb_sb_limit = c->__mb_sb_limit;
+ return c->runes;
+}
diff --git a/lib/libc/locale/toascii.3 b/lib/libc/locale/toascii.3
new file mode 100644
index 0000000..97243cb
--- /dev/null
+++ b/lib/libc/locale/toascii.3
@@ -0,0 +1,69 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)toascii.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt TOASCII 3
+.Os
+.Sh NAME
+.Nm toascii
+.Nd convert a byte to 7-bit ASCII
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn toascii "int c"
+.Sh DESCRIPTION
+The
+.Fn toascii
+function strips all but the low 7 bits from a letter,
+including parity or other marker bits.
+.Sh RETURN VALUES
+The
+.Fn toascii
+function always returns a valid ASCII character.
+.Sh SEE ALSO
+.Xr digittoint 3 ,
+.Xr isalnum 3 ,
+.Xr isalpha 3 ,
+.Xr isascii 3 ,
+.Xr iscntrl 3 ,
+.Xr isdigit 3 ,
+.Xr isgraph 3 ,
+.Xr islower 3 ,
+.Xr isprint 3 ,
+.Xr ispunct 3 ,
+.Xr isspace 3 ,
+.Xr isupper 3 ,
+.Xr isxdigit 3 ,
+.Xr stdio 3 ,
+.Xr tolower 3 ,
+.Xr toupper 3 ,
+.Xr ascii 7
diff --git a/lib/libc/locale/tolower.3 b/lib/libc/locale/tolower.3
new file mode 100644
index 0000000..a5cb819
--- /dev/null
+++ b/lib/libc/locale/tolower.3
@@ -0,0 +1,79 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)tolower.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd July 25, 2010
+.Dt TOLOWER 3
+.Os
+.Sh NAME
+.Nm tolower
+.Nd upper case to lower case letter conversion
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn tolower "int c"
+.Sh DESCRIPTION
+The
+.Fn tolower
+function converts an upper-case letter to the corresponding lower-case
+letter.
+The argument must be representable as an
+.Vt "unsigned char"
+or the value of
+.Dv EOF .
+.Sh RETURN VALUES
+If the argument is an upper-case letter, the
+.Fn tolower
+function returns the corresponding lower-case letter if there is
+one; otherwise, the argument is returned unchanged.
+.Sh COMPATIBILITY
+The
+.Bx 4.4
+extension of accepting arguments outside of the range of the
+.Vt "unsigned char"
+type in locales with large character sets is considered obsolete
+and may not be supported in future releases.
+The
+.Fn towlower
+function should be used instead.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr islower 3 ,
+.Xr towlower 3
+.Sh STANDARDS
+The
+.Fn tolower
+function conforms to
+.St -isoC .
diff --git a/lib/libc/locale/tolower.c b/lib/libc/locale/tolower.c
new file mode 100644
index 0000000..f2eb483
--- /dev/null
+++ b/lib/libc/locale/tolower.c
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <stdio.h>
+#include <runetype.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+__ct_rune_t
+___tolower_l(c, l)
+ __ct_rune_t c;
+ locale_t l;
+{
+ size_t lim;
+ FIX_LOCALE(l);
+ _RuneRange *rr = &XLOCALE_CTYPE(l)->runes->__maplower_ext;
+ _RuneEntry *base, *re;
+
+ if (c < 0 || c == EOF)
+ return(c);
+
+ /* Binary search -- see bsearch.c for explanation. */
+ base = rr->__ranges;
+ for (lim = rr->__nranges; lim != 0; lim >>= 1) {
+ re = base + (lim >> 1);
+ if (re->__min <= c && c <= re->__max)
+ return (re->__map + c - re->__min);
+ else if (c > re->__max) {
+ base = re + 1;
+ lim--;
+ }
+ }
+
+ return(c);
+}
+__ct_rune_t
+___tolower(c)
+ __ct_rune_t c;
+{
+ return ___tolower_l(c, __get_locale());
+}
diff --git a/lib/libc/locale/toupper.3 b/lib/libc/locale/toupper.3
new file mode 100644
index 0000000..0fd3cbb
--- /dev/null
+++ b/lib/libc/locale/toupper.3
@@ -0,0 +1,79 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)toupper.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd July 25, 2010
+.Dt TOUPPER 3
+.Os
+.Sh NAME
+.Nm toupper
+.Nd lower case to upper case letter conversion
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In ctype.h
+.Ft int
+.Fn toupper "int c"
+.Sh DESCRIPTION
+The
+.Fn toupper
+function converts a lower-case letter to the corresponding
+upper-case letter.
+The argument must be representable as an
+.Vt "unsigned char"
+or the value of
+.Dv EOF .
+.Sh RETURN VALUES
+If the argument is a lower-case letter, the
+.Fn toupper
+function returns the corresponding upper-case letter if there is
+one; otherwise, the argument is returned unchanged.
+.Sh COMPATIBILITY
+The
+.Bx 4.4
+extension of accepting arguments outside of the range of the
+.Vt "unsigned char"
+type in locales with large character sets is considered obsolete
+and may not be supported in future releases.
+The
+.Fn towupper
+function should be used instead.
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr isupper 3 ,
+.Xr towupper 3
+.Sh STANDARDS
+The
+.Fn toupper
+function conforms to
+.St -isoC .
diff --git a/lib/libc/locale/toupper.c b/lib/libc/locale/toupper.c
new file mode 100644
index 0000000..d3a4fa3
--- /dev/null
+++ b/lib/libc/locale/toupper.c
@@ -0,0 +1,81 @@
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <stdio.h>
+#include <runetype.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+__ct_rune_t
+___toupper_l(c, l)
+ __ct_rune_t c;
+ locale_t l;
+{
+ size_t lim;
+ FIX_LOCALE(l);
+ _RuneRange *rr = &XLOCALE_CTYPE(l)->runes->__maplower_ext;
+ _RuneEntry *base, *re;
+
+ if (c < 0 || c == EOF)
+ return(c);
+
+ /* Binary search -- see bsearch.c for explanation. */
+ base = rr->__ranges;
+ for (lim = rr->__nranges; lim != 0; lim >>= 1) {
+ re = base + (lim >> 1);
+ if (re->__min <= c && c <= re->__max)
+ {
+ return (re->__map + c - re->__min);
+ }
+ else if (c > re->__max) {
+ base = re + 1;
+ lim--;
+ }
+ }
+
+ return(c);
+}
+__ct_rune_t
+___toupper(c)
+ __ct_rune_t c;
+{
+ return ___toupper_l(c, __get_locale());
+}
diff --git a/lib/libc/locale/towlower.3 b/lib/libc/locale/towlower.3
new file mode 100644
index 0000000..96e2951
--- /dev/null
+++ b/lib/libc/locale/towlower.3
@@ -0,0 +1,66 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)tolower.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd October 3, 2002
+.Dt TOWLOWER 3
+.Os
+.Sh NAME
+.Nm towlower
+.Nd "upper case to lower case letter conversion (wide character version)"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wctype.h
+.Ft wint_t
+.Fn towlower "wint_t wc"
+.Sh DESCRIPTION
+The
+.Fn towlower
+function converts an upper-case letter to the corresponding lower-case
+letter.
+.Sh RETURN VALUES
+If the argument is an upper-case letter, the
+.Fn towlower
+function returns the corresponding lower-case letter if there is
+one; otherwise the argument is returned unchanged.
+.Sh SEE ALSO
+.Xr iswlower 3 ,
+.Xr tolower 3 ,
+.Xr towupper 3 ,
+.Xr wctrans 3
+.Sh STANDARDS
+The
+.Fn towlower
+function conforms to
+.St -isoC-99 .
diff --git a/lib/libc/locale/towupper.3 b/lib/libc/locale/towupper.3
new file mode 100644
index 0000000..0521670
--- /dev/null
+++ b/lib/libc/locale/towupper.3
@@ -0,0 +1,66 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)toupper.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd October 3, 2002
+.Dt TOWUPPER 3
+.Os
+.Sh NAME
+.Nm towupper
+.Nd "lower case to upper case letter conversion (wide character version)"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wctype.h
+.Ft wint_t
+.Fn towupper "wint_t wc"
+.Sh DESCRIPTION
+The
+.Fn towupper
+function converts a lower-case letter to the corresponding
+upper-case letter.
+.Sh RETURN VALUES
+If the argument is a lower-case letter, the
+.Fn towupper
+function returns the corresponding upper-case letter if there is
+one; otherwise the argument is returned unchanged.
+.Sh SEE ALSO
+.Xr iswupper 3 ,
+.Xr toupper 3 ,
+.Xr towlower 3 ,
+.Xr wctrans 3
+.Sh STANDARDS
+The
+.Fn towupper
+function conforms to
+.St -isoC-99 .
diff --git a/lib/libc/locale/uselocale.3 b/lib/libc/locale/uselocale.3
new file mode 100644
index 0000000..72847b3
--- /dev/null
+++ b/lib/libc/locale/uselocale.3
@@ -0,0 +1,60 @@
+.\" Copyright (c) 2011 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This documentation was written by David Chisnall under sponsorship from
+.\" the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 17 2011
+.Dt USELOCALE 3
+.Os
+.Sh NAME
+.Nm uselocale
+.Nd Sets a thread-local locale.
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In xlocale.h
+.Ft locale_t
+.Fn uselocale "locale_t locale"
+.Sh DESCRIPTION
+Specifies the locale for this thread to use.
+Specifying
+.Fa LC_GLOBAL_LOCALE
+disables the per-thread locale,
+while NULL returns the current locale without setting a new one.
+.Sh RETURN VALUES
+Returns the previous locale,
+or LC_GLOBAL_LOCALE if this thread has no locale associated with it.
+.Sh SEE ALSO
+.Xr duplocale 3 ,
+.Xr freelocale 3 ,
+.Xr localeconv 3 ,
+.Xr newlocale 3 ,
+.Xr querylocale 3 ,
+.Xr xlocale 3
+.Sh STANDARDS
+This function conforms to
+.St -p1003.1-2008
diff --git a/lib/libc/locale/utf8.5 b/lib/libc/locale/utf8.5
new file mode 100644
index 0000000..c11aa01
--- /dev/null
+++ b/lib/libc/locale/utf8.5
@@ -0,0 +1,102 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Paul Borman at Krystal Technologies.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)utf2.4 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd April 7, 2004
+.Dt UTF8 5
+.Os
+.Sh NAME
+.Nm utf8
+.Nd "UTF-8, a transformation format of ISO 10646"
+.Sh SYNOPSIS
+.Nm ENCODING
+.Qq UTF-8
+.Sh DESCRIPTION
+The
+.Nm UTF-8
+encoding represents UCS-4 characters as a sequence of octets, using
+between 1 and 6 for each character.
+It is backwards compatible with
+.Tn ASCII ,
+so 0x00-0x7f refer to the
+.Tn ASCII
+character set.
+The multibyte encoding of
+.No non- Ns Tn ASCII
+characters
+consist entirely of bytes whose high order bit is set.
+The actual
+encoding is represented by the following table:
+.Bd -literal
+[0x00000000 - 0x0000007f] [00000000.0bbbbbbb] -> 0bbbbbbb
+[0x00000080 - 0x000007ff] [00000bbb.bbbbbbbb] -> 110bbbbb, 10bbbbbb
+[0x00000800 - 0x0000ffff] [bbbbbbbb.bbbbbbbb] ->
+ 1110bbbb, 10bbbbbb, 10bbbbbb
+[0x00010000 - 0x001fffff] [00000000.000bbbbb.bbbbbbbb.bbbbbbbb] ->
+ 11110bbb, 10bbbbbb, 10bbbbbb, 10bbbbbb
+[0x00200000 - 0x03ffffff] [000000bb.bbbbbbbb.bbbbbbbb.bbbbbbbb] ->
+ 111110bb, 10bbbbbb, 10bbbbbb, 10bbbbbb, 10bbbbbb
+[0x04000000 - 0x7fffffff] [0bbbbbbb.bbbbbbbb.bbbbbbbb.bbbbbbbb] ->
+ 1111110b, 10bbbbbb, 10bbbbbb, 10bbbbbb, 10bbbbbb, 10bbbbbb
+.Ed
+.Pp
+If more than a single representation of a value exists (for example,
+0x00; 0xC0 0x80; 0xE0 0x80 0x80) the shortest representation is always
+used.
+Longer ones are detected as an error as they pose a potential
+security risk, and destroy the 1:1 character:octet sequence mapping.
+.Sh SEE ALSO
+.Xr euc 5
+.Rs
+.%A "Rob Pike"
+.%A "Ken Thompson"
+.%T "Hello World"
+.%J "Proceedings of the Winter 1993 USENIX Technical Conference"
+.%Q "USENIX Association"
+.%D "January 1993"
+.Re
+.Rs
+.%A "F. Yergeau"
+.%T "UTF-8, a transformation format of ISO 10646"
+.%O "RFC 2279"
+.%D "January 1998"
+.Re
+.Rs
+.%Q "The Unicode Consortium"
+.%T "The Unicode Standard, Version 3.0"
+.%D "2000"
+.%O "as amended by the Unicode Standard Annex #27: Unicode 3.1 and by the Unicode Standard Annex #28: Unicode 3.2"
+.Re
+.Sh STANDARDS
+The
+.Nm
+encoding is compatible with RFC 2279 and Unicode 3.2.
diff --git a/lib/libc/locale/utf8.c b/lib/libc/locale/utf8.c
new file mode 100644
index 0000000..40f0e17
--- /dev/null
+++ b/lib/libc/locale/utf8.c
@@ -0,0 +1,434 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <runetype.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+extern int __mb_sb_limit;
+
+static size_t _UTF8_mbrtowc(wchar_t * __restrict, const char * __restrict,
+ size_t, mbstate_t * __restrict);
+static int _UTF8_mbsinit(const mbstate_t *);
+static size_t _UTF8_mbsnrtowcs(wchar_t * __restrict,
+ const char ** __restrict, size_t, size_t,
+ mbstate_t * __restrict);
+static size_t _UTF8_wcrtomb(char * __restrict, wchar_t,
+ mbstate_t * __restrict);
+static size_t _UTF8_wcsnrtombs(char * __restrict, const wchar_t ** __restrict,
+ size_t, size_t, mbstate_t * __restrict);
+
+typedef struct {
+ wchar_t ch;
+ int want;
+ wchar_t lbound;
+} _UTF8State;
+
+int
+_UTF8_init(struct xlocale_ctype *l, _RuneLocale *rl)
+{
+
+ l->__mbrtowc = _UTF8_mbrtowc;
+ l->__wcrtomb = _UTF8_wcrtomb;
+ l->__mbsinit = _UTF8_mbsinit;
+ l->__mbsnrtowcs = _UTF8_mbsnrtowcs;
+ l->__wcsnrtombs = _UTF8_wcsnrtombs;
+ l->runes = rl;
+ l->__mb_cur_max = 6;
+ /*
+ * UCS-4 encoding used as the internal representation, so
+ * slots 0x0080-0x00FF are occuped and must be excluded
+ * from the single byte ctype by setting the limit.
+ */
+ l->__mb_sb_limit = 128;
+
+ return (0);
+}
+
+static int
+_UTF8_mbsinit(const mbstate_t *ps)
+{
+
+ return (ps == NULL || ((const _UTF8State *)ps)->want == 0);
+}
+
+static size_t
+_UTF8_mbrtowc(wchar_t * __restrict pwc, const char * __restrict s, size_t n,
+ mbstate_t * __restrict ps)
+{
+ _UTF8State *us;
+ int ch, i, mask, want;
+ wchar_t lbound, wch;
+
+ us = (_UTF8State *)ps;
+
+ if (us->want < 0 || us->want > 6) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL) {
+ s = "";
+ n = 1;
+ pwc = NULL;
+ }
+
+ if (n == 0)
+ /* Incomplete multibyte sequence */
+ return ((size_t)-2);
+
+ if (us->want == 0 && ((ch = (unsigned char)*s) & ~0x7f) == 0) {
+ /* Fast path for plain ASCII characters. */
+ if (pwc != NULL)
+ *pwc = ch;
+ return (ch != '\0' ? 1 : 0);
+ }
+
+ if (us->want == 0) {
+ /*
+ * Determine the number of octets that make up this character
+ * from the first octet, and a mask that extracts the
+ * interesting bits of the first octet. We already know
+ * the character is at least two bytes long.
+ *
+ * We also specify a lower bound for the character code to
+ * detect redundant, non-"shortest form" encodings. For
+ * example, the sequence C0 80 is _not_ a legal representation
+ * of the null character. This enforces a 1-to-1 mapping
+ * between character codes and their multibyte representations.
+ */
+ ch = (unsigned char)*s;
+ if ((ch & 0x80) == 0) {
+ mask = 0x7f;
+ want = 1;
+ lbound = 0;
+ } else if ((ch & 0xe0) == 0xc0) {
+ mask = 0x1f;
+ want = 2;
+ lbound = 0x80;
+ } else if ((ch & 0xf0) == 0xe0) {
+ mask = 0x0f;
+ want = 3;
+ lbound = 0x800;
+ } else if ((ch & 0xf8) == 0xf0) {
+ mask = 0x07;
+ want = 4;
+ lbound = 0x10000;
+ } else if ((ch & 0xfc) == 0xf8) {
+ mask = 0x03;
+ want = 5;
+ lbound = 0x200000;
+ } else if ((ch & 0xfe) == 0xfc) {
+ mask = 0x01;
+ want = 6;
+ lbound = 0x4000000;
+ } else {
+ /*
+ * Malformed input; input is not UTF-8.
+ */
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ } else {
+ want = us->want;
+ lbound = us->lbound;
+ }
+
+ /*
+ * Decode the octet sequence representing the character in chunks
+ * of 6 bits, most significant first.
+ */
+ if (us->want == 0)
+ wch = (unsigned char)*s++ & mask;
+ else
+ wch = us->ch;
+ for (i = (us->want == 0) ? 1 : 0; i < MIN(want, n); i++) {
+ if ((*s & 0xc0) != 0x80) {
+ /*
+ * Malformed input; bad characters in the middle
+ * of a character.
+ */
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ wch <<= 6;
+ wch |= *s++ & 0x3f;
+ }
+ if (i < want) {
+ /* Incomplete multibyte sequence. */
+ us->want = want - i;
+ us->lbound = lbound;
+ us->ch = wch;
+ return ((size_t)-2);
+ }
+ if (wch < lbound) {
+ /*
+ * Malformed input; redundant encoding.
+ */
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ if (pwc != NULL)
+ *pwc = wch;
+ us->want = 0;
+ return (wch == L'\0' ? 0 : want);
+}
+
+static size_t
+_UTF8_mbsnrtowcs(wchar_t * __restrict dst, const char ** __restrict src,
+ size_t nms, size_t len, mbstate_t * __restrict ps)
+{
+ _UTF8State *us;
+ const char *s;
+ size_t nchr;
+ wchar_t wc;
+ size_t nb;
+
+ us = (_UTF8State *)ps;
+
+ s = *src;
+ nchr = 0;
+
+ if (dst == NULL) {
+ /*
+ * The fast path in the loop below is not safe if an ASCII
+ * character appears as anything but the first byte of a
+ * multibyte sequence. Check now to avoid doing it in the loop.
+ */
+ if (nms > 0 && us->want > 0 && (signed char)*s > 0) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ for (;;) {
+ if (nms > 0 && (signed char)*s > 0)
+ /*
+ * Fast path for plain ASCII characters
+ * excluding NUL.
+ */
+ nb = 1;
+ else if ((nb = _UTF8_mbrtowc(&wc, s, nms, ps)) ==
+ (size_t)-1)
+ /* Invalid sequence - mbrtowc() sets errno. */
+ return ((size_t)-1);
+ else if (nb == 0 || nb == (size_t)-2)
+ return (nchr);
+ s += nb;
+ nms -= nb;
+ nchr++;
+ }
+ /*NOTREACHED*/
+ }
+
+ /*
+ * The fast path in the loop below is not safe if an ASCII
+ * character appears as anything but the first byte of a
+ * multibyte sequence. Check now to avoid doing it in the loop.
+ */
+ if (nms > 0 && len > 0 && us->want > 0 && (signed char)*s > 0) {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+ while (len-- > 0) {
+ if (nms > 0 && (signed char)*s > 0) {
+ /*
+ * Fast path for plain ASCII characters
+ * excluding NUL.
+ */
+ *dst = (wchar_t)*s;
+ nb = 1;
+ } else if ((nb = _UTF8_mbrtowc(dst, s, nms, ps)) ==
+ (size_t)-1) {
+ *src = s;
+ return ((size_t)-1);
+ } else if (nb == (size_t)-2) {
+ *src = s + nms;
+ return (nchr);
+ } else if (nb == 0) {
+ *src = NULL;
+ return (nchr);
+ }
+ s += nb;
+ nms -= nb;
+ nchr++;
+ dst++;
+ }
+ *src = s;
+ return (nchr);
+}
+
+static size_t
+_UTF8_wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
+{
+ _UTF8State *us;
+ unsigned char lead;
+ int i, len;
+
+ us = (_UTF8State *)ps;
+
+ if (us->want != 0) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ if (s == NULL)
+ /* Reset to initial shift state (no-op) */
+ return (1);
+
+ if ((wc & ~0x7f) == 0) {
+ /* Fast path for plain ASCII characters. */
+ *s = (char)wc;
+ return (1);
+ }
+
+ /*
+ * Determine the number of octets needed to represent this character.
+ * We always output the shortest sequence possible. Also specify the
+ * first few bits of the first octet, which contains the information
+ * about the sequence length.
+ */
+ if ((wc & ~0x7f) == 0) {
+ lead = 0;
+ len = 1;
+ } else if ((wc & ~0x7ff) == 0) {
+ lead = 0xc0;
+ len = 2;
+ } else if ((wc & ~0xffff) == 0) {
+ lead = 0xe0;
+ len = 3;
+ } else if ((wc & ~0x1fffff) == 0) {
+ lead = 0xf0;
+ len = 4;
+ } else if ((wc & ~0x3ffffff) == 0) {
+ lead = 0xf8;
+ len = 5;
+ } else if ((wc & ~0x7fffffff) == 0) {
+ lead = 0xfc;
+ len = 6;
+ } else {
+ errno = EILSEQ;
+ return ((size_t)-1);
+ }
+
+ /*
+ * Output the octets representing the character in chunks
+ * of 6 bits, least significant last. The first octet is
+ * a special case because it contains the sequence length
+ * information.
+ */
+ for (i = len - 1; i > 0; i--) {
+ s[i] = (wc & 0x3f) | 0x80;
+ wc >>= 6;
+ }
+ *s = (wc & 0xff) | lead;
+
+ return (len);
+}
+
+static size_t
+_UTF8_wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src,
+ size_t nwc, size_t len, mbstate_t * __restrict ps)
+{
+ _UTF8State *us;
+ char buf[MB_LEN_MAX];
+ const wchar_t *s;
+ size_t nbytes;
+ size_t nb;
+
+ us = (_UTF8State *)ps;
+
+ if (us->want != 0) {
+ errno = EINVAL;
+ return ((size_t)-1);
+ }
+
+ s = *src;
+ nbytes = 0;
+
+ if (dst == NULL) {
+ while (nwc-- > 0) {
+ if (0 <= *s && *s < 0x80)
+ /* Fast path for plain ASCII characters. */
+ nb = 1;
+ else if ((nb = _UTF8_wcrtomb(buf, *s, ps)) ==
+ (size_t)-1)
+ /* Invalid character - wcrtomb() sets errno. */
+ return ((size_t)-1);
+ if (*s == L'\0')
+ return (nbytes + nb - 1);
+ s++;
+ nbytes += nb;
+ }
+ return (nbytes);
+ }
+
+ while (len > 0 && nwc-- > 0) {
+ if (0 <= *s && *s < 0x80) {
+ /* Fast path for plain ASCII characters. */
+ nb = 1;
+ *dst = *s;
+ } else if (len > (size_t)MB_CUR_MAX) {
+ /* Enough space to translate in-place. */
+ if ((nb = _UTF8_wcrtomb(dst, *s, ps)) == (size_t)-1) {
+ *src = s;
+ return ((size_t)-1);
+ }
+ } else {
+ /*
+ * May not be enough space; use temp. buffer.
+ */
+ if ((nb = _UTF8_wcrtomb(buf, *s, ps)) == (size_t)-1) {
+ *src = s;
+ return ((size_t)-1);
+ }
+ if (nb > (int)len)
+ /* MB sequence for character won't fit. */
+ break;
+ memcpy(dst, buf, nb);
+ }
+ if (*s == L'\0') {
+ *src = NULL;
+ return (nbytes + nb - 1);
+ }
+ s++;
+ dst += nb;
+ len -= nb;
+ nbytes += nb;
+ }
+ *src = s;
+ return (nbytes);
+}
diff --git a/lib/libc/locale/wcrtomb.3 b/lib/libc/locale/wcrtomb.3
new file mode 100644
index 0000000..c89614e
--- /dev/null
+++ b/lib/libc/locale/wcrtomb.3
@@ -0,0 +1,105 @@
+.\" Copyright (c) 2002-2004 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 8, 2004
+.Dt WCRTOMB 3
+.Os
+.Sh NAME
+.Nm wcrtomb
+.Nd "convert a wide-character code to a character (restartable)"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft size_t
+.Fn wcrtomb "char * restrict s" "wchar_t wc" "mbstate_t * restrict ps"
+.Sh DESCRIPTION
+The
+.Fn wcrtomb
+function stores a multibyte sequence representing the
+wide character
+.Fa wc ,
+including any necessary shift sequences, to the
+character array
+.Fa s ,
+storing a maximum of
+.Dv MB_CUR_MAX
+bytes.
+.Pp
+If
+.Fa s
+is
+.Dv NULL ,
+.Fn wcrtomb
+behaves as if
+.Fa s
+pointed to an internal buffer and
+.Fa wc
+was a null wide character (L'\e0').
+.Pp
+The
+.Ft mbstate_t
+argument,
+.Fa ps ,
+is used to keep track of the shift state.
+If it is
+.Dv NULL ,
+.Fn wcrtomb
+uses an internal, static
+.Vt mbstate_t
+object, which is initialized to the initial conversion state
+at program startup.
+.Sh RETURN VALUES
+The
+.Fn wcrtomb
+functions returns the length (in bytes) of the multibyte sequence
+needed to represent
+.Fa wc ,
+or
+.Po Vt size_t Pc Ns \-1
+if
+.Fa wc
+is not a valid wide character code.
+.Sh ERRORS
+The
+.Fn wcrtomb
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EILSEQ
+An invalid wide character code was specified.
+.It Bq Er EINVAL
+The conversion state is invalid.
+.El
+.Sh SEE ALSO
+.Xr mbrtowc 3 ,
+.Xr multibyte 3 ,
+.Xr setlocale 3 ,
+.Xr wctomb 3
+.Sh STANDARDS
+The
+.Fn wcrtomb
+function conforms to
+.St -isoC-99 .
diff --git a/lib/libc/locale/wcrtomb.c b/lib/libc/locale/wcrtomb.c
new file mode 100644
index 0000000..32d4df2
--- /dev/null
+++ b/lib/libc/locale/wcrtomb.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+wcrtomb_l(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps,
+ locale_t locale)
+{
+ FIX_LOCALE(locale);
+ if (ps == NULL)
+ ps = &locale->wcrtomb;
+ return (XLOCALE_CTYPE(locale)->__wcrtomb(s, wc, ps));
+}
+
+size_t
+wcrtomb(char * __restrict s, wchar_t wc, mbstate_t * __restrict ps)
+{
+ return wcrtomb_l(s, wc, ps, __get_locale());
+}
diff --git a/lib/libc/locale/wcsftime.3 b/lib/libc/locale/wcsftime.3
new file mode 100644
index 0000000..92aee93
--- /dev/null
+++ b/lib/libc/locale/wcsftime.3
@@ -0,0 +1,66 @@
+.\" Copyright (c) 2002 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 8, 2002
+.Dt WCSFTIME 3
+.Os
+.Sh NAME
+.Nm wcsftime
+.Nd "convert date and time to a wide-character string"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft size_t
+.Fo wcsftime
+.Fa "wchar_t * restrict wcs" "size_t maxsize"
+.Fa "const wchar_t * restrict format" "const struct tm * restrict timeptr"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn wcsftime
+function is equivalent to the
+.Fn strftime
+function except for the types of its arguments.
+Refer to
+.Xr strftime 3
+for a detailed description.
+.Sh COMPATIBILITY
+Some early implementations of
+.Fn wcsftime
+had a
+.Fa format
+argument with type
+.Vt "const char *"
+instead of
+.Vt "const wchar_t *" .
+.Sh SEE ALSO
+.Xr strftime 3
+.Sh STANDARDS
+The
+.Fn wcsftime
+function conforms to
+.St -isoC-99 .
diff --git a/lib/libc/locale/wcsftime.c b/lib/libc/locale/wcsftime.c
new file mode 100644
index 0000000..c4f6b2e
--- /dev/null
+++ b/lib/libc/locale/wcsftime.c
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <time.h>
+#include <wchar.h>
+#include "xlocale_private.h"
+
+/*
+ * Convert date and time to a wide-character string.
+ *
+ * This is the wide-character counterpart of strftime(). So that we do not
+ * have to duplicate the code of strftime(), we convert the format string to
+ * multibyte, call strftime(), then convert the result back into wide
+ * characters.
+ *
+ * This technique loses in the presence of stateful multibyte encoding if any
+ * of the conversions in the format string change conversion state. When
+ * stateful encoding is implemented, we will need to reset the state between
+ * format specifications in the format string.
+ */
+size_t
+wcsftime_l(wchar_t * __restrict wcs, size_t maxsize,
+ const wchar_t * __restrict format, const struct tm * __restrict timeptr,
+ locale_t locale)
+{
+ static const mbstate_t initial;
+ mbstate_t mbs;
+ char *dst, *sformat;
+ const char *dstp;
+ const wchar_t *formatp;
+ size_t n, sflen;
+ int sverrno;
+ FIX_LOCALE(locale);
+
+ sformat = dst = NULL;
+
+ /*
+ * Convert the supplied format string to a multibyte representation
+ * for strftime(), which only handles single-byte characters.
+ */
+ mbs = initial;
+ formatp = format;
+ sflen = wcsrtombs_l(NULL, &formatp, 0, &mbs, locale);
+ if (sflen == (size_t)-1)
+ goto error;
+ if ((sformat = malloc(sflen + 1)) == NULL)
+ goto error;
+ mbs = initial;
+ wcsrtombs_l(sformat, &formatp, sflen + 1, &mbs, locale);
+
+ /*
+ * Allocate memory for longest multibyte sequence that will fit
+ * into the caller's buffer and call strftime() to fill it.
+ * Then, copy and convert the result back into wide characters in
+ * the caller's buffer.
+ */
+ if (SIZE_T_MAX / MB_CUR_MAX <= maxsize) {
+ /* maxsize is prepostorously large - avoid int. overflow. */
+ errno = EINVAL;
+ goto error;
+ }
+ if ((dst = malloc(maxsize * MB_CUR_MAX)) == NULL)
+ goto error;
+ if (strftime_l(dst, maxsize, sformat, timeptr, locale) == 0)
+ goto error;
+ dstp = dst;
+ mbs = initial;
+ n = mbsrtowcs_l(wcs, &dstp, maxsize, &mbs, locale);
+ if (n == (size_t)-2 || n == (size_t)-1 || dstp != NULL)
+ goto error;
+
+ free(sformat);
+ free(dst);
+ return (n);
+
+error:
+ sverrno = errno;
+ free(sformat);
+ free(dst);
+ errno = sverrno;
+ return (0);
+}
+size_t
+wcsftime(wchar_t * __restrict wcs, size_t maxsize,
+ const wchar_t * __restrict format, const struct tm * __restrict timeptr)
+{
+ return wcsftime_l(wcs, maxsize, format, timeptr, __get_locale());
+}
diff --git a/lib/libc/locale/wcsnrtombs.c b/lib/libc/locale/wcsnrtombs.c
new file mode 100644
index 0000000..2f3bf1e
--- /dev/null
+++ b/lib/libc/locale/wcsnrtombs.c
@@ -0,0 +1,123 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+wcsnrtombs_l(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc,
+ size_t len, mbstate_t * __restrict ps, locale_t locale)
+{
+ FIX_LOCALE(locale);
+ if (ps == NULL)
+ ps = &locale->wcsnrtombs;
+ return (XLOCALE_CTYPE(locale)->__wcsnrtombs(dst, src, nwc, len, ps));
+}
+size_t
+wcsnrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t nwc,
+ size_t len, mbstate_t * __restrict ps)
+{
+ return wcsnrtombs_l(dst, src, nwc, len, ps, __get_locale());
+}
+
+
+size_t
+__wcsnrtombs_std(char * __restrict dst, const wchar_t ** __restrict src,
+ size_t nwc, size_t len, mbstate_t * __restrict ps)
+{
+ mbstate_t mbsbak;
+ char buf[MB_LEN_MAX];
+ const wchar_t *s;
+ size_t nbytes;
+ size_t nb;
+ struct xlocale_ctype *l = XLOCALE_CTYPE(__get_locale());
+
+ s = *src;
+ nbytes = 0;
+
+ if (dst == NULL) {
+ while (nwc-- > 0) {
+ if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1)
+ /* Invalid character - wcrtomb() sets errno. */
+ return ((size_t)-1);
+ else if (*s == L'\0')
+ return (nbytes + nb - 1);
+ s++;
+ nbytes += nb;
+ }
+ return (nbytes);
+ }
+
+ while (len > 0 && nwc-- > 0) {
+ if (len > (size_t)MB_CUR_MAX) {
+ /* Enough space to translate in-place. */
+ if ((nb = l->__wcrtomb(dst, *s, ps)) == (size_t)-1) {
+ *src = s;
+ return ((size_t)-1);
+ }
+ } else {
+ /*
+ * May not be enough space; use temp. buffer.
+ *
+ * We need to save a copy of the conversion state
+ * here so we can restore it if the multibyte
+ * character is too long for the buffer.
+ */
+ mbsbak = *ps;
+ if ((nb = l->__wcrtomb(buf, *s, ps)) == (size_t)-1) {
+ *src = s;
+ return ((size_t)-1);
+ }
+ if (nb > (int)len) {
+ /* MB sequence for character won't fit. */
+ *ps = mbsbak;
+ break;
+ }
+ memcpy(dst, buf, nb);
+ }
+ if (*s == L'\0') {
+ *src = NULL;
+ return (nbytes + nb - 1);
+ }
+ s++;
+ dst += nb;
+ len -= nb;
+ nbytes += nb;
+ }
+ *src = s;
+ return (nbytes);
+}
diff --git a/lib/libc/locale/wcsrtombs.3 b/lib/libc/locale/wcsrtombs.3
new file mode 100644
index 0000000..ff607c2
--- /dev/null
+++ b/lib/libc/locale/wcsrtombs.3
@@ -0,0 +1,134 @@
+.\" Copyright (c) 2002-2004 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 21, 2004
+.Dt WCSRTOMBS 3
+.Os
+.Sh NAME
+.Nm wcsrtombs ,
+.Nm wcsnrtombs
+.Nd "convert a wide-character string to a character string (restartable)"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft size_t
+.Fo wcsrtombs
+.Fa "char * restrict dst" "const wchar_t ** restrict src"
+.Fa "size_t len" "mbstate_t * restrict ps"
+.Fc
+.Ft size_t
+.Fo wcsnrtombs
+.Fa "char * restrict dst" "const wchar_t ** restrict src" "size_t nwc"
+.Fa "size_t len" "mbstate_t * restrict ps"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn wcsrtombs
+function converts a string of wide characters indirectly pointed to by
+.Fa src
+to a corresponding multibyte character string stored in the array
+pointed to by
+.Fa dst .
+No more than
+.Fa len
+bytes are written to
+.Fa dst .
+.Pp
+If
+.Fa dst
+is
+.Dv NULL ,
+no characters are stored.
+.Pp
+If
+.Fa dst
+is not
+.Dv NULL ,
+the pointer pointed to by
+.Fa src
+is updated to point to the character after the one that conversion stopped at.
+If conversion stops because a null character is encountered,
+.Fa *src
+is set to
+.Dv NULL .
+.Pp
+The
+.Vt mbstate_t
+argument,
+.Fa ps ,
+is used to keep track of the shift state.
+If it is
+.Dv NULL ,
+.Fn wcsrtombs
+uses an internal, static
+.Vt mbstate_t
+object, which is initialized to the initial conversion state
+at program startup.
+.Pp
+The
+.Fn wcsnrtombs
+function behaves identically to
+.Fn wcsrtombs ,
+except that conversion stops after reading at most
+.Fa nwc
+characters from the buffer pointed to by
+.Fa src .
+.Sh RETURN VALUES
+The
+.Fn wcsrtombs
+and
+.Fn wcsnrtombs
+functions return the number of bytes stored in
+the array pointed to by
+.Fa dst
+(not including any terminating null), if successful, otherwise it returns
+.Po Vt size_t Pc Ns \-1 .
+.Sh ERRORS
+The
+.Fn wcsrtombs
+and
+.Fn wcsnrtombs
+functions will fail if:
+.Bl -tag -width Er
+.It Bq Er EILSEQ
+An invalid wide character was encountered.
+.It Bq Er EINVAL
+The conversion state is invalid.
+.El
+.Sh SEE ALSO
+.Xr mbsrtowcs 3 ,
+.Xr wcrtomb 3 ,
+.Xr wcstombs 3
+.Sh STANDARDS
+The
+.Fn wcsrtombs
+function conforms to
+.St -isoC-99 .
+.Pp
+The
+.Fn wcsnrtombs
+function is an extension to the standard.
diff --git a/lib/libc/locale/wcsrtombs.c b/lib/libc/locale/wcsrtombs.c
new file mode 100644
index 0000000..f6d1ca0
--- /dev/null
+++ b/lib/libc/locale/wcsrtombs.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+wcsrtombs_l(char * __restrict dst, const wchar_t ** __restrict src, size_t len,
+ mbstate_t * __restrict ps, locale_t locale)
+{
+ FIX_LOCALE(locale);
+ if (ps == NULL)
+ ps = &locale->wcsrtombs;
+ return (XLOCALE_CTYPE(locale)->__wcsnrtombs(dst, src, SIZE_T_MAX, len, ps));
+}
+
+size_t
+wcsrtombs(char * __restrict dst, const wchar_t ** __restrict src, size_t len,
+ mbstate_t * __restrict ps)
+{
+ return wcsrtombs_l(dst, src, len, ps, __get_locale());
+}
diff --git a/lib/libc/locale/wcstod.3 b/lib/libc/locale/wcstod.3
new file mode 100644
index 0000000..f8c5135
--- /dev/null
+++ b/lib/libc/locale/wcstod.3
@@ -0,0 +1,73 @@
+.\" Copyright (c) 2002, 2003 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 22, 2003
+.Dt WCSTOD 3
+.Os
+.Sh NAME
+.Nm wcstof ,
+.Nm wcstod ,
+.Nm wcstold
+.Nd convert string to
+.Vt float , double
+or
+.Vt "long double"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft float
+.Fn wcstof "const wchar_t * restrict nptr" "wchar_t ** restrict endptr"
+.Ft "long double"
+.Fn wcstold "const wchar_t * restrict nptr" "wchar_t ** restrict endptr"
+.Ft double
+.Fn wcstod "const wchar_t * restrict nptr" "wchar_t ** restrict endptr"
+.Sh DESCRIPTION
+The
+.Fn wcstof ,
+.Fn wcstod
+and
+.Fn wcstold
+functions are the wide-character versions of the
+.Fn strtof ,
+.Fn strtod
+and
+.Fn strtold
+functions.
+Refer to
+.Xr strtod 3
+for details.
+.Sh SEE ALSO
+.Xr strtod 3 ,
+.Xr wcstol 3
+.Sh STANDARDS
+The
+.Fn wcstof ,
+.Fn wcstod
+and
+.Fn wcstold
+functions conform to
+.St -isoC-99 .
diff --git a/lib/libc/locale/wcstod.c b/lib/libc/locale/wcstod.c
new file mode 100644
index 0000000..8bc46a7
--- /dev/null
+++ b/lib/libc/locale/wcstod.c
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "xlocale_private.h"
+
+/*
+ * Convert a string to a double-precision number.
+ *
+ * This is the wide-character counterpart of strtod(). So that we do not
+ * have to duplicate the code of strtod() here, we convert the supplied
+ * wide character string to multibyte and call strtod() on the result.
+ * This assumes that the multibyte encoding is compatible with ASCII
+ * for at least the digits, radix character and letters.
+ */
+double
+wcstod_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+ locale_t locale)
+{
+ static const mbstate_t initial;
+ mbstate_t mbs;
+ double val;
+ char *buf, *end;
+ const wchar_t *wcp = nptr;
+ size_t len;
+ size_t spaces = 0;
+ FIX_LOCALE(locale);
+
+ while (iswspace_l(*wcp, locale)) {
+ wcp++;
+ spaces++;
+ }
+
+ /*
+ * Convert the supplied numeric wide char. string to multibyte.
+ *
+ * We could attempt to find the end of the numeric portion of the
+ * wide char. string to avoid converting unneeded characters but
+ * choose not to bother; optimising the uncommon case where
+ * the input string contains a lot of text after the number
+ * duplicates a lot of strtod()'s functionality and slows down the
+ * most common cases.
+ */
+ mbs = initial;
+ if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) {
+ if (endptr != NULL)
+ *endptr = (wchar_t *)nptr;
+ return (0.0);
+ }
+ if ((buf = malloc(len + 1)) == NULL)
+ return (0.0);
+ mbs = initial;
+ wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale);
+
+ /* Let strtod() do most of the work for us. */
+ val = strtod_l(buf, &end, locale);
+
+ /*
+ * We only know where the number ended in the _multibyte_
+ * representation of the string. If the caller wants to know
+ * where it ended, count multibyte characters to find the
+ * corresponding position in the wide char string.
+ */
+ if (endptr != NULL) {
+ /* XXX Assume each wide char is one byte. */
+ *endptr = (wchar_t *)nptr + (end - buf);
+ if (buf != end)
+ *endptr += spaces;
+ }
+
+
+ free(buf);
+
+ return (val);
+}
+double
+wcstod(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
+{
+ return wcstod_l(nptr, endptr, __get_locale());
+}
diff --git a/lib/libc/locale/wcstof.c b/lib/libc/locale/wcstof.c
new file mode 100644
index 0000000..93a5af8
--- /dev/null
+++ b/lib/libc/locale/wcstof.c
@@ -0,0 +1,83 @@
+/*-
+ * Copyright (c) 2002, 2003 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "xlocale_private.h"
+
+/*
+ * See wcstod() for comments as to the logic used.
+ */
+float
+wcstof_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+ locale_t locale)
+{
+ static const mbstate_t initial;
+ mbstate_t mbs;
+ float val;
+ char *buf, *end;
+ const wchar_t *wcp;
+ size_t len;
+ FIX_LOCALE(locale);
+
+ while (iswspace_l(*nptr, locale))
+ nptr++;
+
+ wcp = nptr;
+ mbs = initial;
+ if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) {
+ if (endptr != NULL)
+ *endptr = (wchar_t *)nptr;
+ return (0.0);
+ }
+ if ((buf = malloc(len + 1)) == NULL)
+ return (0.0);
+ mbs = initial;
+ wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale);
+
+ val = strtof_l(buf, &end, locale);
+
+ if (endptr != NULL)
+ *endptr = (wchar_t *)nptr + (end - buf);
+
+ free(buf);
+
+ return (val);
+}
+float
+wcstof(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
+{
+ return wcstof_l(nptr, endptr, __get_locale());
+}
diff --git a/lib/libc/locale/wcstoimax.c b/lib/libc/locale/wcstoimax.c
new file mode 100644
index 0000000..ce066a5
--- /dev/null
+++ b/lib/libc/locale/wcstoimax.c
@@ -0,0 +1,137 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "from @(#)strtol.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoimax.c,v 1.8 2002/09/06 11:23:59 tjr Exp ");
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "xlocale_private.h"
+
+/*
+ * Convert a wide character string to an intmax_t integer.
+ */
+intmax_t
+wcstoimax_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+ int base, locale_t locale)
+{
+ const wchar_t *s;
+ uintmax_t acc;
+ wchar_t c;
+ uintmax_t cutoff;
+ int neg, any, cutlim;
+ FIX_LOCALE(locale);
+
+ /*
+ * See strtoimax for comments as to the logic used.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (iswspace_l(c, locale));
+ if (c == L'-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == L'+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == L'0' && (*s == L'x' || *s == L'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == L'0' ? 8 : 10;
+ acc = any = 0;
+ if (base < 2 || base > 36)
+ goto noconv;
+
+ cutoff = neg ? (uintmax_t)-(INTMAX_MIN + INTMAX_MAX) + INTMAX_MAX
+ : INTMAX_MAX;
+ cutlim = cutoff % base;
+ cutoff /= base;
+ for ( ; ; c = *s++) {
+#ifdef notyet
+ if (iswdigit_l(c, locale))
+ c = digittoint_l(c, locale);
+ else
+#endif
+ if (c >= L'0' && c <= L'9')
+ c -= L'0';
+ else if (c >= L'A' && c <= L'Z')
+ c -= L'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= L'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? INTMAX_MIN : INTMAX_MAX;
+ errno = ERANGE;
+ } else if (!any) {
+noconv:
+ errno = EINVAL;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != NULL)
+ *endptr = (wchar_t *)(any ? s - 1 : nptr);
+ return (acc);
+}
+intmax_t
+wcstoimax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+ int base)
+{
+ return wcstoimax_l(nptr, endptr, base, __get_locale());
+}
diff --git a/lib/libc/locale/wcstol.3 b/lib/libc/locale/wcstol.3
new file mode 100644
index 0000000..e69a726
--- /dev/null
+++ b/lib/libc/locale/wcstol.3
@@ -0,0 +1,94 @@
+.\" Copyright (c) 2002 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 7, 2002
+.Dt WCSTOL 3
+.Os
+.Sh NAME
+.Nm wcstol , wcstoul ,
+.Nm wcstoll , wcstoull ,
+.Nm wcstoimax , wcstoumax
+.Nd "convert a wide character string value to a"
+.Vt long ,
+.Vt "unsigned long" ,
+.Vt "long long" ,
+.Vt "unsigned long long" ,
+.Vt intmax_t
+or
+.Vt uintmax_t
+integer
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft long
+.Fn wcstol "const wchar_t * restrict nptr" "wchar_t ** restrict endptr" "int base"
+.Ft "unsigned long"
+.Fn wcstoul "const wchar_t * restrict nptr" "wchar_t ** restrict endptr" "int base"
+.Ft "long long"
+.Fn wcstoll "const wchar_t * restrict nptr" "wchar_t ** restrict endptr" "int base"
+.Ft "unsigned long long"
+.Fn wcstoull "const wchar_t * restrict nptr" "wchar_t ** restrict endptr" "int base"
+.In inttypes.h
+.Ft intmax_t
+.Fn wcstoimax "const wchar_t * restrict nptr" "wchar_t ** restrict endptr" "int base"
+.Ft uintmax_t
+.Fn wcstoumax "const wchar_t * restrict nptr" "wchar_t ** restrict endptr" "int base"
+.Sh DESCRIPTION
+The
+.Fn wcstol ,
+.Fn wcstoul ,
+.Fn wcstoll ,
+.Fn wcstoull ,
+.Fn wcstoimax
+and
+.Fn wcstoumax
+functions are wide-character versions of the
+.Fn strtol ,
+.Fn strtoul ,
+.Fn strtoll ,
+.Fn strtoull ,
+.Fn strtoimax
+and
+.Fn strtoumax
+functions, respectively.
+Refer to their manual pages (for example
+.Xr strtol 3 )
+for details.
+.Sh SEE ALSO
+.Xr strtol 3 ,
+.Xr strtoul 3
+.Sh STANDARDS
+The
+.Fn wcstol ,
+.Fn wcstoul ,
+.Fn wcstoll ,
+.Fn wcstoull ,
+.Fn wcstoimax
+and
+.Fn wcstoumax
+functions conform to
+.St -isoC-99 .
diff --git a/lib/libc/locale/wcstol.c b/lib/libc/locale/wcstol.c
new file mode 100644
index 0000000..2b21d12
--- /dev/null
+++ b/lib/libc/locale/wcstol.c
@@ -0,0 +1,130 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "xlocale_private.h"
+
+/*
+ * Convert a string to a long integer.
+ */
+long
+wcstol_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int
+ base, locale_t locale)
+{
+ const wchar_t *s;
+ unsigned long acc;
+ wchar_t c;
+ unsigned long cutoff;
+ int neg, any, cutlim;
+ FIX_LOCALE(locale);
+
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (iswspace_l(c, locale));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == L'+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == L'0' && (*s == L'x' || *s == L'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == L'0' ? 8 : 10;
+ acc = any = 0;
+ if (base < 2 || base > 36)
+ goto noconv;
+
+ cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX
+ : LONG_MAX;
+ cutlim = cutoff % base;
+ cutoff /= base;
+ for ( ; ; c = *s++) {
+#ifdef notyet
+ if (iswdigit_l(c, locale))
+ c = digittoint_l(c, locale);
+ else
+#endif
+ if (c >= L'0' && c <= L'9')
+ c -= L'0';
+ else if (c >= L'A' && c <= L'Z')
+ c -= L'A' - 10;
+ else if (c >= L'a' && c <= L'z')
+ c -= L'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_MIN : LONG_MAX;
+ errno = ERANGE;
+ } else if (!any) {
+noconv:
+ errno = EINVAL;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != NULL)
+ *endptr = (wchar_t *)(any ? s - 1 : nptr);
+ return (acc);
+}
+long
+wcstol(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
+{
+ return wcstol_l(nptr, endptr, base, __get_locale());
+}
diff --git a/lib/libc/locale/wcstold.c b/lib/libc/locale/wcstold.c
new file mode 100644
index 0000000..fcfd48f
--- /dev/null
+++ b/lib/libc/locale/wcstold.c
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 2002, 2003 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "xlocale_private.h"
+
+/*
+ * See wcstod() for comments as to the logic used.
+ */
+long double
+wcstold_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+ locale_t locale)
+{
+ static const mbstate_t initial;
+ mbstate_t mbs;
+ long double val;
+ char *buf, *end;
+ const wchar_t *wcp = nptr;
+ size_t len;
+ size_t spaces = 0;
+ FIX_LOCALE(locale);
+
+ while (iswspace_l(*wcp, locale)) {
+ wcp++;
+ spaces++;
+ }
+
+ wcp = nptr;
+ mbs = initial;
+ if ((len = wcsrtombs_l(NULL, &wcp, 0, &mbs, locale)) == (size_t)-1) {
+ if (endptr != NULL)
+ *endptr = (wchar_t *)nptr;
+ return (0.0);
+ }
+ if ((buf = malloc(len + 1)) == NULL)
+ return (0.0);
+ mbs = initial;
+ wcsrtombs_l(buf, &wcp, len + 1, &mbs, locale);
+
+ val = strtold_l(buf, &end, locale);
+
+ if (endptr != NULL) {
+ /* XXX Assume each wide char is one byte. */
+ *endptr = (wchar_t *)nptr + (end - buf);
+ if (buf != end)
+ *endptr += spaces;
+ }
+
+ free(buf);
+
+ return (val);
+}
+long double
+wcstold(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr)
+{
+ return wcstold_l(nptr, endptr, __get_locale());
+}
diff --git a/lib/libc/locale/wcstoll.c b/lib/libc/locale/wcstoll.c
new file mode 100644
index 0000000..f246502
--- /dev/null
+++ b/lib/libc/locale/wcstoll.c
@@ -0,0 +1,136 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoll.c,v 1.19 2002/09/06 11:23:59 tjr Exp ");
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "xlocale_private.h"
+
+/*
+ * Convert a wide character string to a long long integer.
+ */
+long long
+wcstoll_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+ int base, locale_t locale)
+{
+ const wchar_t *s;
+ unsigned long long acc;
+ wchar_t c;
+ unsigned long long cutoff;
+ int neg, any, cutlim;
+ FIX_LOCALE(locale);
+
+ /*
+ * See strtoll for comments as to the logic used.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (iswspace_l(c, locale));
+ if (c == L'-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == L'+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == L'0' && (*s == L'x' || *s == L'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == L'0' ? 8 : 10;
+ acc = any = 0;
+ if (base < 2 || base > 36)
+ goto noconv;
+
+ cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX
+ : LLONG_MAX;
+ cutlim = cutoff % base;
+ cutoff /= base;
+ for ( ; ; c = *s++) {
+#ifdef notyet
+ if (iswdigit_l(c, locale))
+ c = digittoint_l(c, locale);
+ else
+#endif
+ if (c >= L'0' && c <= L'9')
+ c -= L'0';
+ else if (c >= L'A' && c <= L'Z')
+ c -= L'A' - 10;
+ else if (c >= L'a' && c <= L'z')
+ c -= L'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LLONG_MIN : LLONG_MAX;
+ errno = ERANGE;
+ } else if (!any) {
+noconv:
+ errno = EINVAL;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != NULL)
+ *endptr = (wchar_t *)(any ? s - 1 : nptr);
+ return (acc);
+}
+long long
+wcstoll(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
+{
+ return wcstoll_l(nptr, endptr, base, __get_locale());
+}
diff --git a/lib/libc/locale/wcstombs.3 b/lib/libc/locale/wcstombs.3
new file mode 100644
index 0000000..723ae80
--- /dev/null
+++ b/lib/libc/locale/wcstombs.3
@@ -0,0 +1,90 @@
+.\" Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Donn Seeley of BSDI.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
+.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
+.\" $FreeBSD$
+.\"
+.Dd April 8, 2004
+.Dt WCSTOMBS 3
+.Os
+.Sh NAME
+.Nm wcstombs
+.Nd convert a wide-character string to a character string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft size_t
+.Fo wcstombs
+.Fa "char * restrict mbstring" "const wchar_t * restrict wcstring"
+.Fa "size_t nbytes"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn wcstombs
+function converts a wide character string
+.Fa wcstring
+into a multibyte character string,
+.Fa mbstring ,
+beginning in the initial conversion state.
+Up to
+.Fa nbytes
+bytes are stored in
+.Fa mbstring .
+Partial multibyte characters at the end of the string are not stored.
+The multibyte character string is null terminated if there is room.
+.Sh RETURN VALUES
+The
+.Fn wcstombs
+function returns the number of bytes converted
+(not including any terminating null), if successful, otherwise it returns
+.Po Vt size_t Pc Ns \-1 .
+.Sh ERRORS
+The
+.Fn wcstombs
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EILSEQ
+An invalid wide character was encountered.
+.It Bq Er EINVAL
+The conversion state is invalid.
+.El
+.Sh SEE ALSO
+.Xr mbstowcs 3 ,
+.Xr multibyte 3 ,
+.Xr wcsrtombs 3 ,
+.Xr wctomb 3
+.Sh STANDARDS
+The
+.Fn wcstombs
+function conforms to
+.St -isoC-99 .
diff --git a/lib/libc/locale/wcstombs.c b/lib/libc/locale/wcstombs.c
new file mode 100644
index 0000000..8d4ae1c
--- /dev/null
+++ b/lib/libc/locale/wcstombs.c
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+size_t
+wcstombs_l(char * __restrict s, const wchar_t * __restrict pwcs, size_t n,
+ locale_t locale)
+{
+ static const mbstate_t initial;
+ mbstate_t mbs;
+ const wchar_t *pwcsp;
+ FIX_LOCALE(locale);
+
+ mbs = initial;
+ pwcsp = pwcs;
+ return (XLOCALE_CTYPE(locale)->__wcsnrtombs(s, &pwcsp, SIZE_T_MAX, n, &mbs));
+}
+size_t
+wcstombs(char * __restrict s, const wchar_t * __restrict pwcs, size_t n)
+{
+ return wcstombs_l(s, pwcs, n, __get_locale());
+}
+
diff --git a/lib/libc/locale/wcstoul.c b/lib/libc/locale/wcstoul.c
new file mode 100644
index 0000000..54e6b4f
--- /dev/null
+++ b/lib/libc/locale/wcstoul.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "xlocale_private.h"
+
+/*
+ * Convert a wide character string to an unsigned long integer.
+ */
+unsigned long
+wcstoul_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+ int base, locale_t locale)
+{
+ const wchar_t *s;
+ unsigned long acc;
+ wchar_t c;
+ unsigned long cutoff;
+ int neg, any, cutlim;
+ FIX_LOCALE(locale);
+
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (iswspace_l(c, locale));
+ if (c == L'-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == L'+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == L'0' && (*s == L'x' || *s == L'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == L'0' ? 8 : 10;
+ acc = any = 0;
+ if (base < 2 || base > 36)
+ goto noconv;
+
+ cutoff = ULONG_MAX / base;
+ cutlim = ULONG_MAX % base;
+ for ( ; ; c = *s++) {
+#ifdef notyet
+ if (iswdigit_l(c, locale))
+ c = digittoint_l(c, locale);
+ else
+#endif
+ if (c >= L'0' && c <= L'9')
+ c -= L'0';
+ else if (c >= L'A' && c <= L'Z')
+ c -= L'A' - 10;
+ else if (c >= L'a' && c <= L'z')
+ c -= L'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULONG_MAX;
+ errno = ERANGE;
+ } else if (!any) {
+noconv:
+ errno = EINVAL;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != NULL)
+ *endptr = (wchar_t *)(any ? s - 1 : nptr);
+ return (acc);
+}
+unsigned long
+wcstoul(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr, int base)
+{
+ return wcstoul_l(nptr, endptr, base, __get_locale());
+}
diff --git a/lib/libc/locale/wcstoull.c b/lib/libc/locale/wcstoull.c
new file mode 100644
index 0000000..c56ee77
--- /dev/null
+++ b/lib/libc/locale/wcstoull.c
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoull.c,v 1.18 2002/09/06 11:23:59 tjr Exp ");
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "xlocale_private.h"
+
+/*
+ * Convert a wide character string to an unsigned long long integer.
+ */
+unsigned long long
+wcstoull_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+ int base, locale_t locale)
+{
+ const wchar_t *s;
+ unsigned long long acc;
+ wchar_t c;
+ unsigned long long cutoff;
+ int neg, any, cutlim;
+ FIX_LOCALE(locale);
+
+ /*
+ * See strtoull for comments as to the logic used.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (iswspace_l(c, locale));
+ if (c == L'-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == L'+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == L'0' && (*s == L'x' || *s == L'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == L'0' ? 8 : 10;
+ acc = any = 0;
+ if (base < 2 || base > 36)
+ goto noconv;
+
+ cutoff = ULLONG_MAX / base;
+ cutlim = ULLONG_MAX % base;
+ for ( ; ; c = *s++) {
+#ifdef notyet
+ if (iswdigit_l(c, locale))
+ c = digittoint_l(c, locale);
+ else
+#endif
+ if (c >= L'0' && c <= L'9')
+ c -= L'0';
+ else if (c >= L'A' && c <= L'Z')
+ c -= L'A' - 10;
+ else if (c >= L'a' && c <= L'z')
+ c -= L'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULLONG_MAX;
+ errno = ERANGE;
+ } else if (!any) {
+noconv:
+ errno = EINVAL;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != NULL)
+ *endptr = (wchar_t *)(any ? s - 1 : nptr);
+ return (acc);
+}
+unsigned long long
+wcstoull(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+ int base)
+{
+ return wcstoull_l(nptr, endptr, base, __get_locale());
+}
diff --git a/lib/libc/locale/wcstoumax.c b/lib/libc/locale/wcstoumax.c
new file mode 100644
index 0000000..397c1e3
--- /dev/null
+++ b/lib/libc/locale/wcstoumax.c
@@ -0,0 +1,135 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "from @(#)strtoul.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+__FBSDID("FreeBSD: src/lib/libc/stdlib/strtoumax.c,v 1.8 2002/09/06 11:23:59 tjr Exp ");
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "xlocale_private.h"
+
+/*
+ * Convert a wide character string to a uintmax_t integer.
+ */
+uintmax_t
+wcstoumax_l(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+ int base, locale_t locale)
+{
+ const wchar_t *s;
+ uintmax_t acc;
+ wchar_t c;
+ uintmax_t cutoff;
+ int neg, any, cutlim;
+ FIX_LOCALE(locale);
+
+ /*
+ * See strtoimax for comments as to the logic used.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (iswspace_l(c, locale));
+ if (c == L'-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == L'+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == L'0' && (*s == L'x' || *s == L'X')) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == L'0' ? 8 : 10;
+ acc = any = 0;
+ if (base < 2 || base > 36)
+ goto noconv;
+
+ cutoff = UINTMAX_MAX / base;
+ cutlim = UINTMAX_MAX % base;
+ for ( ; ; c = *s++) {
+#ifdef notyet
+ if (iswdigit_l(c, locale))
+ c = digittoint_l(c, locale);
+ else
+#endif
+ if (c >= L'0' && c <= L'9')
+ c -= L'0';
+ else if (c >= L'A' && c <= L'Z')
+ c -= L'A' - 10;
+ else if (c >= L'a' && c <= L'z')
+ c -= L'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = UINTMAX_MAX;
+ errno = ERANGE;
+ } else if (!any) {
+noconv:
+ errno = EINVAL;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != NULL)
+ *endptr = (wchar_t *)(any ? s - 1 : nptr);
+ return (acc);
+}
+uintmax_t
+wcstoumax(const wchar_t * __restrict nptr, wchar_t ** __restrict endptr,
+ int base)
+{
+ return wcstoumax_l(nptr, endptr, base, __get_locale());
+}
diff --git a/lib/libc/locale/wctob.c b/lib/libc/locale/wctob.c
new file mode 100644
index 0000000..96e8b73
--- /dev/null
+++ b/lib/libc/locale/wctob.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include <stdio.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+int
+wctob_l(wint_t c, locale_t locale)
+{
+ static const mbstate_t initial;
+ mbstate_t mbs = initial;
+ char buf[MB_LEN_MAX];
+ FIX_LOCALE(locale);
+
+ if (c == WEOF || XLOCALE_CTYPE(locale)->__wcrtomb(buf, c, &mbs) != 1)
+ return (EOF);
+ return ((unsigned char)*buf);
+}
+int
+wctob(wint_t c)
+{
+ return wctob_l(c, __get_locale());
+}
diff --git a/lib/libc/locale/wctomb.3 b/lib/libc/locale/wctomb.3
new file mode 100644
index 0000000..fe08d83
--- /dev/null
+++ b/lib/libc/locale/wctomb.3
@@ -0,0 +1,108 @@
+.\" Copyright (c) 2002-2004 Tim J. Robbins. All rights reserved.
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Donn Seeley of BSDI.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From @(#)multibyte.3 8.1 (Berkeley) 6/4/93
+.\" From FreeBSD: src/lib/libc/locale/multibyte.3,v 1.22 2003/11/08 03:23:11 tjr Exp
+.\" $FreeBSD$
+.\"
+.Dd April 8, 2004
+.Dt WCTOMB 3
+.Os
+.Sh NAME
+.Nm wctomb
+.Nd convert a wide-character code to a character
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fn wctomb "char *mbchar" "wchar_t wchar"
+.Sh DESCRIPTION
+The
+.Fn wctomb
+function converts a wide character
+.Fa wchar
+into a multibyte character and stores
+the result in
+.Fa mbchar .
+The object pointed to by
+.Fa mbchar
+must be large enough to accommodate the multibyte character, which
+may be up to
+.Dv MB_LEN_MAX
+bytes.
+.Pp
+A call with a null
+.Fa mbchar
+pointer returns nonzero if the current locale requires shift states,
+zero otherwise;
+if shift states are required, the shift state is reset to the initial state.
+.Sh RETURN VALUES
+If
+.Fa mbchar
+is
+.Dv NULL ,
+the
+.Fn wctomb
+function returns nonzero if shift states are supported,
+zero otherwise.
+If
+.Fa mbchar
+is valid,
+.Fn wctomb
+returns
+the number of bytes processed in
+.Fa mbchar ,
+or \-1 if no multibyte character
+could be recognized or converted.
+In this case,
+.Fn wctomb Ns 's
+internal conversion state is undefined.
+.Sh ERRORS
+The
+.Fn wctomb
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EILSEQ
+An invalid multibyte sequence was detected.
+.It Bq Er EINVAL
+The internal conversion state is invalid.
+.El
+.Sh SEE ALSO
+.Xr mbtowc 3 ,
+.Xr wcrtomb 3 ,
+.Xr wcstombs 3 ,
+.Xr wctob 3
+.Sh STANDARDS
+The
+.Fn wctomb
+function conforms to
+.St -isoC-99 .
diff --git a/lib/libc/locale/wctomb.c b/lib/libc/locale/wctomb.c
new file mode 100644
index 0000000..da3d263
--- /dev/null
+++ b/lib/libc/locale/wctomb.c
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <wchar.h>
+#include "mblocal.h"
+
+int
+wctomb_l(char *s, wchar_t wchar, locale_t locale)
+{
+ static const mbstate_t initial;
+ size_t rval;
+ FIX_LOCALE(locale);
+
+ if (s == NULL) {
+ /* No support for state dependent encodings. */
+ locale->wctomb = initial;
+ return (0);
+ }
+ if ((rval = XLOCALE_CTYPE(locale)->__wcrtomb(s, wchar, &locale->wctomb)) == (size_t)-1)
+ return (-1);
+ return ((int)rval);
+}
+int
+wctomb(char *s, wchar_t wchar)
+{
+ return wctomb_l(s, wchar, __get_locale());
+}
diff --git a/lib/libc/locale/wctrans.3 b/lib/libc/locale/wctrans.3
new file mode 100644
index 0000000..ce3e68c
--- /dev/null
+++ b/lib/libc/locale/wctrans.3
@@ -0,0 +1,122 @@
+.\" Copyright (c) 2002 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 3, 2002
+.Dt WCTRANS 3
+.Os
+.Sh NAME
+.Nm towctrans , wctrans
+.Nd "wide character mapping functions"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wctype.h
+.Ft wint_t
+.Fn towctrans "wint_t wc" "wctrans_t desc"
+.Ft wctrans_t
+.Fn wctrans "const char *charclass"
+.Sh DESCRIPTION
+The
+.Fn wctrans
+function returns a value of type
+.Vt wctrans_t
+which represents the requested wide character mapping operation and
+may be used as the second argument for calls to
+.Fn towctrans .
+.Pp
+The following character mapping names are recognised:
+.Bl -column -offset indent ".Li tolower" ".Li toupper"
+.It Li "tolower toupper"
+.El
+.Pp
+The
+.Fn towctrans
+function transliterates the wide character
+.Fa wc
+according to the mapping described by
+.Fa desc .
+.Sh RETURN VALUES
+The
+.Fn towctrans
+function returns the transliterated character if successful, otherwise
+it returns the character unchanged and sets
+.Va errno .
+.Pp
+The
+.Fn wctrans
+function returns non-zero if successful, otherwise it returns zero
+and sets
+.Va errno .
+.Sh EXAMPLES
+Reimplement
+.Fn towupper
+in terms of
+.Fn towctrans
+and
+.Fn wctrans :
+.Bd -literal -offset indent
+wint_t
+mytowupper(wint_t wc)
+{
+ return (towctrans(wc, wctrans("toupper")));
+}
+.Ed
+.Sh ERRORS
+The
+.Fn towctrans
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The supplied
+.Fa desc
+argument is invalid.
+.El
+.Pp
+The
+.Fn wctrans
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The requested mapping name is invalid.
+.El
+.Sh SEE ALSO
+.Xr tolower 3 ,
+.Xr toupper 3 ,
+.Xr wctype 3
+.Sh STANDARDS
+The
+.Fn towctrans
+and
+.Fn wctrans
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn towctrans
+and
+.Fn wctrans
+functions first appeared in
+.Fx 5.0 .
diff --git a/lib/libc/locale/wctrans.c b/lib/libc/locale/wctrans.c
new file mode 100644
index 0000000..0831146
--- /dev/null
+++ b/lib/libc/locale/wctrans.c
@@ -0,0 +1,101 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <string.h>
+#include <wctype.h>
+#include "xlocale_private.h"
+
+enum {
+ _WCT_ERROR = 0,
+ _WCT_TOLOWER = 1,
+ _WCT_TOUPPER = 2
+};
+
+wint_t
+towctrans_l(wint_t wc, wctrans_t desc, locale_t locale)
+{
+ switch (desc) {
+ case _WCT_TOLOWER:
+ wc = towlower_l(wc, locale);
+ break;
+ case _WCT_TOUPPER:
+ wc = towupper_l(wc, locale);
+ break;
+ case _WCT_ERROR:
+ default:
+ errno = EINVAL;
+ break;
+ }
+
+ return (wc);
+}
+wint_t
+towctrans(wint_t wc, wctrans_t desc)
+{
+ return towctrans_l(wc, desc, __get_locale());
+}
+
+/*
+ * wctrans() calls this will a 0 locale. If this is ever modified to actually
+ * use the locale, wctrans() must be modified to call __get_locale().
+ */
+wctrans_t
+wctrans_l(const char *charclass, locale_t locale)
+{
+ struct {
+ const char *name;
+ wctrans_t trans;
+ } ccls[] = {
+ { "tolower", _WCT_TOLOWER },
+ { "toupper", _WCT_TOUPPER },
+ { NULL, _WCT_ERROR }, /* Default */
+ };
+ int i;
+
+ i = 0;
+ while (ccls[i].name != NULL && strcmp(ccls[i].name, charclass) != 0)
+ i++;
+
+ if (ccls[i].trans == _WCT_ERROR)
+ errno = EINVAL;
+ return (ccls[i].trans);
+}
+
+wctrans_t
+wctrans(const char *charclass)
+{
+ return wctrans_l(charclass, 0);
+}
+
diff --git a/lib/libc/locale/wctype.3 b/lib/libc/locale/wctype.3
new file mode 100644
index 0000000..099631d
--- /dev/null
+++ b/lib/libc/locale/wctype.3
@@ -0,0 +1,119 @@
+.\" Copyright (c) 2002 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 27, 2004
+.Dt WCTYPE 3
+.Os
+.Sh NAME
+.Nm iswctype , wctype
+.Nd "wide character class functions"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wctype.h
+.Ft int
+.Fn iswctype "wint_t wc" "wctype_t charclass"
+.Ft wctype_t
+.Fn wctype "const char *property"
+.Sh DESCRIPTION
+The
+.Fn wctype
+function returns a value of type
+.Vt wctype_t
+which represents the requested wide character class and
+may be used as the second argument for calls to
+.Fn iswctype .
+.Pp
+The following character class names are recognised:
+.Bl -column -offset indent ".Li alnum" ".Li cntrl" ".Li ideogram" ".Li print" ".Li space"
+.It Li "alnum cntrl ideogram print space xdigit"
+.It Li "alpha digit lower punct special"
+.It Li "blank graph phonogram rune upper"
+.El
+.Pp
+The
+.Fn iswctype
+function checks whether the wide character
+.Fa wc
+is in the character class
+.Fa charclass .
+.Sh RETURN VALUES
+The
+.Fn iswctype
+function returns non-zero if and only if
+.Fa wc
+has the property described by
+.Fa charclass ,
+or
+.Fa charclass
+is zero.
+.Pp
+The
+.Fn wctype
+function returns 0 if
+.Fa property
+is invalid, otherwise it returns a value of type
+.Vt wctype_t
+that can be used in subsequent calls to
+.Fn iswctype .
+.Sh EXAMPLES
+Reimplement
+.Xr iswalpha 3
+in terms of
+.Fn iswctype
+and
+.Fn wctype :
+.Bd -literal -offset indent
+int
+myiswalpha(wint_t wc)
+{
+ return (iswctype(wc, wctype("alpha")));
+}
+.Ed
+.Sh SEE ALSO
+.Xr ctype 3 ,
+.Xr nextwctype 3
+.Sh STANDARDS
+The
+.Fn iswctype
+and
+.Fn wctype
+functions conform to
+.St -p1003.1-2001 .
+The
+.Dq Li ideogram ,
+.Dq Li phonogram ,
+.Dq Li special ,
+and
+.Dq Li rune
+character classes are extensions.
+.Sh HISTORY
+The
+.Fn iswctype
+and
+.Fn wctype
+functions first appeared in
+.Fx 5.0 .
diff --git a/lib/libc/locale/wctype.c b/lib/libc/locale/wctype.c
new file mode 100644
index 0000000..de880b4
--- /dev/null
+++ b/lib/libc/locale/wctype.c
@@ -0,0 +1,113 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <string.h>
+#include <wctype.h>
+#include <xlocale.h>
+
+#undef iswctype
+int
+iswctype(wint_t wc, wctype_t charclass)
+{
+ return (__istype(wc, charclass));
+}
+int
+iswctype_l(wint_t wc, wctype_t charclass, locale_t locale)
+{
+ return __istype_l(wc, charclass, locale);
+}
+
+/*
+ * IMPORTANT: The 0 in the call to this function in wctype() must be changed to
+ * __get_locale() if wctype_l() is ever modified to actually use the locale
+ * parameter.
+ */
+wctype_t
+wctype_l(const char *property, locale_t locale)
+{
+ const char *propnames =
+ "alnum\0"
+ "alpha\0"
+ "blank\0"
+ "cntrl\0"
+ "digit\0"
+ "graph\0"
+ "lower\0"
+ "print\0"
+ "punct\0"
+ "space\0"
+ "upper\0"
+ "xdigit\0"
+ "ideogram\0" /* BSD extension */
+ "special\0" /* BSD extension */
+ "phonogram\0" /* BSD extension */
+ "rune\0"; /* BSD extension */
+ static const wctype_t propmasks[] = {
+ _CTYPE_A|_CTYPE_D,
+ _CTYPE_A,
+ _CTYPE_B,
+ _CTYPE_C,
+ _CTYPE_D,
+ _CTYPE_G,
+ _CTYPE_L,
+ _CTYPE_R,
+ _CTYPE_P,
+ _CTYPE_S,
+ _CTYPE_U,
+ _CTYPE_X,
+ _CTYPE_I,
+ _CTYPE_T,
+ _CTYPE_Q,
+ 0xFFFFFF00L
+ };
+ size_t len1, len2;
+ const char *p;
+ const wctype_t *q;
+
+ len1 = strlen(property);
+ q = propmasks;
+ for (p = propnames; (len2 = strlen(p)) != 0; p += len2 + 1) {
+ if (len1 == len2 && memcmp(property, p, len1) == 0)
+ return (*q);
+ q++;
+ }
+
+ return (0UL);
+}
+
+wctype_t wctype(const char *property)
+{
+ return wctype_l(property, 0);
+}
diff --git a/lib/libc/locale/wcwidth.3 b/lib/libc/locale/wcwidth.3
new file mode 100644
index 0000000..0c7c74f
--- /dev/null
+++ b/lib/libc/locale/wcwidth.3
@@ -0,0 +1,87 @@
+.\" Copyright (c) 2002 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 17, 2004
+.Dt WCWIDTH 3
+.Os
+.Sh NAME
+.Nm wcwidth
+.Nd "number of column positions of a wide-character code"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft int
+.Fn wcwidth "wchar_t wc"
+.Sh DESCRIPTION
+The
+.Fn wcwidth
+function determines the number of column positions required to
+display the wide character
+.Fa wc .
+.Sh RETURN VALUES
+The
+.Fn wcwidth
+function returns 0 if the
+.Fa wc
+argument is a null wide character (L'\e0'),
+\-1 if
+.Fa wc
+is not printable,
+otherwise it returns the number of column positions the
+character occupies.
+.Sh EXAMPLES
+This code fragment reads text from standard input and
+breaks lines that are more than 20 column positions wide,
+similar to the
+.Xr fold 1
+utility:
+.Bd -literal -offset indent
+wint_t ch;
+int column, w;
+
+column = 0;
+while ((ch = getwchar()) != WEOF) {
+ w = wcwidth(ch);
+ if (w > 0 && column + w >= 20) {
+ putwchar(L'\en');
+ column = 0;
+ }
+ putwchar(ch);
+ if (ch == L'\en')
+ column = 0;
+ else if (w > 0)
+ column += w;
+}
+.Ed
+.Sh SEE ALSO
+.Xr iswprint 3 ,
+.Xr wcswidth 3
+.Sh STANDARDS
+The
+.Fn wcwidth
+function conforms to
+.St -p1003.1-2001 .
diff --git a/lib/libc/locale/wcwidth.c b/lib/libc/locale/wcwidth.c
new file mode 100644
index 0000000..9e74217
--- /dev/null
+++ b/lib/libc/locale/wcwidth.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+#include <wctype.h>
+#include <xlocale.h>
+
+#undef wcwidth
+
+int
+wcwidth(wchar_t wc)
+{
+ return (__wcwidth(wc));
+}
+int
+wcwidth_l(wchar_t wc, locale_t locale)
+{
+ return (__wcwidth_l(wc, locale));
+}
diff --git a/lib/libc/locale/xlocale.3 b/lib/libc/locale/xlocale.3
new file mode 100644
index 0000000..11a392d
--- /dev/null
+++ b/lib/libc/locale/xlocale.3
@@ -0,0 +1,280 @@
+.\" Copyright (c) 2011 The FreeBSD Foundation
+.\" All rights reserved.
+.\"
+.\" This documentation was written by David Chisnall under sponsorship from
+.\" the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 17 2011
+.Dt XLOCALE 3
+.Os
+.Sh NAME
+.Nm xlocale
+.Nd Thread-safe extended locale support.
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In xlocale.h
+.Sh DESCRIPTION
+The extended locale support includes a set of functions for setting
+thread-local locales,
+as well convenience functions for performing locale-aware
+calls with a specified locale.
+.Pp
+The core of the xlocale API is the
+.Fa locale_t
+type.
+This is an opaque type encapsulating a locale.
+Instances of this can be either set as the locale for a specific thread or
+passed directly to the
+.Fa _l
+suffixed variants of various standard C functions.
+Two special
+.Fa locale_t
+values are available:
+.Bl -bullet -offset indent
+.It
+NULL refers to the current locale for the thread,
+or to the global locale if no locale has been set for this thread.
+.It
+LC_GLOBAL_LOCALE refers to the global locale.
+.El
+.Pp
+The global locale is the locale set with the
+.Xr setlocale 3
+function.
+.Sh SEE ALSO
+.Xr duplocale 3 ,
+.Xr freelocale 3 ,
+.Xr localeconv 3 ,
+.Xr newlocale 3 ,
+.Xr querylocale 3 ,
+.Xr uselocale 3 ,
+.Sh CONVENIENCE FUNCTIONS
+The xlocale API includes a number of
+.Fa _l
+suffixed convenience functions.
+These are variants of standard C functions
+that have been modified to take an explicit
+.Fa locale_t
+parameter as the final argument or, in the case of variadic functions,
+as an additional argument directly before the format string.
+Each of these functions accepts either NULL or LC_GLOBAL_LOCALE.
+In these functions, NULL refers to the C locale,
+rather than the thread's current locale.
+If you wish to use the thread's current locale,
+then use the unsuffixed version of the function.
+.Pp
+These functions are exposed by including
+.In xlocale.h
+.Em after
+including the relevant headers for the standard variant.
+For example, the
+.Xr strtol_l 3
+function is exposed by including
+.In xlocale.h
+after
+.In stdlib.h ,
+which defines
+.Xr strtol 3 .
+.Pp
+For reference,
+a complete list of the locale-aware functions that are available in this form,
+along with the headers that expose them, is provided here:
+.Bl -tag -width "<monetary.h> "
+.It In wctype.h
+.Xr iswalnum_l 3 ,
+.Xr iswalpha_l 3 ,
+.Xr iswcntrl_l 3 ,
+.Xr iswctype_l 3 ,
+.Xr iswdigit_l 3 ,
+.Xr iswgraph_l 3 ,
+.Xr iswlower_l 3 ,
+.Xr iswprint_l 3 ,
+.Xr iswpunct_l 3 ,
+.Xr iswspace_l 3 ,
+.Xr iswupper_l 3 ,
+.Xr iswxdigit_l 3 ,
+.Xr towlower_l 3 ,
+.Xr towupper_l 3 ,
+.Xr wctype_l 3 ,
+.It In ctype.h
+.Xr digittoint_l 3 ,
+.Xr isalnum_l 3 ,
+.Xr isalpha_l 3 ,
+.Xr isblank_l 3 ,
+.Xr iscntrl_l 3 ,
+.Xr isdigit_l 3 ,
+.Xr isgraph_l 3 ,
+.Xr ishexnumber_l 3 ,
+.Xr isideogram_l 3 ,
+.Xr islower_l 3 ,
+.Xr isnumber_l 3 ,
+.Xr isphonogram_l 3 ,
+.Xr isprint_l 3 ,
+.Xr ispunct_l 3 ,
+.Xr isrune_l 3 ,
+.Xr isspace_l 3 ,
+.Xr isspecial_l 3 ,
+.Xr isupper_l 3 ,
+.Xr isxdigit_l 3 ,
+.Xr tolower_l 3 ,
+.Xr toupper_l 3
+.It In inttypes.h
+.Xr strtoimax_l 3 ,
+.Xr strtoumax_l 3 ,
+.Xr wcstoimax_l 3 ,
+.Xr wcstoumax_l 3
+.It In langinfo.h
+.Xr nl_langinfo_l 3
+.It In monetary.h
+.Xr strfmon_l 3
+.It In stdio.h
+.Xr asprintf_l 3 ,
+.Xr fprintf_l 3 ,
+.Xr fscanf_l 3 ,
+.Xr printf_l 3 ,
+.Xr scanf_l 3 ,
+.Xr snprintf_l 3 ,
+.Xr sprintf_l 3 ,
+.Xr sscanf_l 3 ,
+.Xr vasprintf_l 3 ,
+.Xr vfprintf_l 3 ,
+.Xr vfscanf_l 3 ,
+.Xr vprintf_l 3 ,
+.Xr vscanf_l 3 ,
+.Xr vsnprintf_l 3 ,
+.Xr vsprintf_l 3 ,
+.Xr vsscanf_l 3
+.It In stdlib.h
+.Xr atof_l 3 ,
+.Xr atoi_l 3 ,
+.Xr atol_l 3 ,
+.Xr atoll_l 3 ,
+.Xr mblen_l 3 ,
+.Xr mbstowcs_l 3 ,
+.Xr mbtowc_l 3 ,
+.Xr strtod_l 3 ,
+.Xr strtof_l 3 ,
+.Xr strtol_l 3 ,
+.Xr strtold_l 3 ,
+.Xr strtoll_l 3 ,
+.Xr strtoq_l 3 ,
+.Xr strtoul_l 3 ,
+.Xr strtoull_l 3 ,
+.Xr strtouq_l 3 ,
+.Xr wcstombs_l 3 ,
+.Xr wctomb_l 3
+.It In string.h
+.Xr strcoll_l 3 ,
+.Xr strxfrm_l 3 ,
+.Xr strcasecmp_l 3 ,
+.Xr strcasestr_l 3 ,
+.Xr strncasecmp_l 3
+.It In time.h
+.Xr strftime_l 3
+.Xr strptime_l 3
+.It In wchar.h
+.Xr btowc_l 3 ,
+.Xr fgetwc_l 3 ,
+.Xr fgetws_l 3 ,
+.Xr fputwc_l 3 ,
+.Xr fputws_l 3 ,
+.Xr fwprintf_l 3 ,
+.Xr fwscanf_l 3 ,
+.Xr getwc_l 3 ,
+.Xr getwchar_l 3 ,
+.Xr mbrlen_l 3 ,
+.Xr mbrtowc_l 3 ,
+.Xr mbsinit_l 3 ,
+.Xr mbsnrtowcs_l 3 ,
+.Xr mbsrtowcs_l 3 ,
+.Xr putwc_l 3 ,
+.Xr putwchar_l 3 ,
+.Xr swprintf_l 3 ,
+.Xr swscanf_l 3 ,
+.Xr ungetwc_l 3 ,
+.Xr vfwprintf_l 3 ,
+.Xr vfwscanf_l 3 ,
+.Xr vswprintf_l 3 ,
+.Xr vswscanf_l 3 ,
+.Xr vwprintf_l 3 ,
+.Xr vwscanf_l 3 ,
+.Xr wcrtomb_l 3 ,
+.Xr wcscoll_l 3 ,
+.Xr wcsftime_l 3 ,
+.Xr wcsnrtombs_l 3 ,
+.Xr wcsrtombs_l 3 ,
+.Xr wcstod_l 3 ,
+.Xr wcstof_l 3 ,
+.Xr wcstol_l 3 ,
+.Xr wcstold_l 3 ,
+.Xr wcstoll_l 3 ,
+.Xr wcstoul_l 3 ,
+.Xr wcstoull_l 3 ,
+.Xr wcswidth_l 3 ,
+.Xr wcsxfrm_l 3 ,
+.Xr wctob_l 3 ,
+.Xr wcwidth_l 3 ,
+.Xr wprintf_l 3 ,
+.Xr wscanf_l 3
+.It In wctype.h
+.Xr iswblank_l 3 ,
+.Xr iswhexnumber_l 3 ,
+.Xr iswideogram_l 3 ,
+.Xr iswnumber_l 3 ,
+.Xr iswphonogram_l 3 ,
+.Xr iswrune_l 3 ,
+.Xr iswspecial_l 3 ,
+.Xr nextwctype_l 3 ,
+.Xr towctrans_l 3 ,
+.Xr wctrans_l 3
+.It In xlocale.h
+.Xr localeconv_l 3
+.El
+.Sh STANDARDS
+The functions
+conform to
+.St -p1003.1-2008 .
+.Sh HISTORY
+The xlocale APIs first appeared in Darwin 8.0.
+This implementation was written by David Chisnall,
+under sponsorship from the FreeBSD Foundation and first appeared in
+.Fx 9.1 .
+.Sh CAVEATS
+The
+.Xr setlocale 3
+function, and others in the family, refer to the global locale.
+Other functions that depend on the locale, however,
+will take the thread-local locale if one has been set.
+This means that the idiom of setting the locale using
+.Xr setlocale 3 ,
+calling a locale-dependent function,
+and then restoring the locale will not
+have the expected behavior if the current thread has had a locale set using
+.Xr uselocale 3 .
+You should avoid this idiom and prefer to use the
+.Fa _l
+suffixed versions instead.
diff --git a/lib/libc/locale/xlocale.c b/lib/libc/locale/xlocale.c
new file mode 100644
index 0000000..e114bac
--- /dev/null
+++ b/lib/libc/locale/xlocale.c
@@ -0,0 +1,371 @@
+/*-
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by David Chisnall under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <pthread.h>
+#include <stdio.h>
+#include <string.h>
+#include <runetype.h>
+#include "libc_private.h"
+#include "xlocale_private.h"
+
+/**
+ * Each locale loader declares a global component. This is used by setlocale()
+ * and also by xlocale with LC_GLOBAL_LOCALE..
+ */
+extern struct xlocale_component __xlocale_global_collate;
+extern struct xlocale_component __xlocale_global_ctype;
+extern struct xlocale_component __xlocale_global_monetary;
+extern struct xlocale_component __xlocale_global_numeric;
+extern struct xlocale_component __xlocale_global_time;
+extern struct xlocale_component __xlocale_global_messages;
+/*
+ * And another version for the statically-allocated C locale. We only have
+ * components for the parts that are expected to be sensible.
+ */
+extern struct xlocale_component __xlocale_C_collate;
+extern struct xlocale_component __xlocale_C_ctype;
+
+#ifndef __NO_TLS
+/*
+ * The locale for this thread.
+ */
+_Thread_local locale_t __thread_locale;
+#endif
+/*
+ * Flag indicating that one or more per-thread locales exist.
+ */
+int __has_thread_locale;
+/*
+ * Private functions in setlocale.c.
+ */
+const char *
+__get_locale_env(int category);
+int
+__detect_path_locale(void);
+
+struct _xlocale __xlocale_global_locale = {
+ {0},
+ {
+ &__xlocale_global_collate,
+ &__xlocale_global_ctype,
+ &__xlocale_global_monetary,
+ &__xlocale_global_numeric,
+ &__xlocale_global_time,
+ &__xlocale_global_messages
+ },
+ 1,
+ 0,
+ 1,
+ 0
+};
+
+struct _xlocale __xlocale_C_locale = {
+ {0},
+ {
+ &__xlocale_C_collate,
+ &__xlocale_C_ctype,
+ 0, 0, 0, 0
+ },
+ 1,
+ 0,
+ 1,
+ 0
+};
+
+static void*(*constructors[])(const char*, locale_t) =
+{
+ __collate_load,
+ __ctype_load,
+ __monetary_load,
+ __numeric_load,
+ __time_load,
+ __messages_load
+};
+
+static pthread_key_t locale_info_key;
+static int fake_tls;
+static locale_t thread_local_locale;
+
+static void init_key(void)
+{
+
+ pthread_key_create(&locale_info_key, xlocale_release);
+ pthread_setspecific(locale_info_key, (void*)42);
+ if (pthread_getspecific(locale_info_key) == (void*)42) {
+ pthread_setspecific(locale_info_key, 0);
+ } else {
+ fake_tls = 1;
+ }
+ /* At least one per-thread locale has now been set. */
+ __has_thread_locale = 1;
+ __detect_path_locale();
+}
+
+static pthread_once_t once_control = PTHREAD_ONCE_INIT;
+
+static locale_t
+get_thread_locale(void)
+{
+
+ _once(&once_control, init_key);
+
+ return (fake_tls ? thread_local_locale :
+ pthread_getspecific(locale_info_key));
+}
+
+#ifdef __NO_TLS
+locale_t
+__get_locale(void)
+{
+ locale_t l = get_thread_locale();
+ return (l ? l : &__xlocale_global_locale);
+
+}
+#endif
+
+static void
+set_thread_locale(locale_t loc)
+{
+
+ _once(&once_control, init_key);
+
+ if (NULL != loc) {
+ xlocale_retain((struct xlocale_refcounted*)loc);
+ }
+ locale_t old = pthread_getspecific(locale_info_key);
+ if ((NULL != old) && (loc != old)) {
+ xlocale_release((struct xlocale_refcounted*)old);
+ }
+ if (fake_tls) {
+ thread_local_locale = loc;
+ } else {
+ pthread_setspecific(locale_info_key, loc);
+ }
+#ifndef __NO_TLS
+ __thread_locale = loc;
+ __set_thread_rune_locale(loc);
+#endif
+}
+
+/**
+ * Clean up a locale, once its reference count reaches zero. This function is
+ * called by xlocale_release(), it should not be called directly.
+ */
+static void
+destruct_locale(void *l)
+{
+ locale_t loc = l;
+
+ for (int type=0 ; type<XLC_LAST ; type++) {
+ if (loc->components[type]) {
+ xlocale_release(loc->components[type]);
+ }
+ }
+ if (loc->csym) {
+ free(loc->csym);
+ }
+ free(l);
+}
+
+/**
+ * Allocates a new, uninitialised, locale.
+ */
+static locale_t
+alloc_locale(void)
+{
+ locale_t new = calloc(sizeof(struct _xlocale), 1);
+
+ new->header.destructor = destruct_locale;
+ new->monetary_locale_changed = 1;
+ new->numeric_locale_changed = 1;
+ return (new);
+}
+static void
+copyflags(locale_t new, locale_t old)
+{
+ new->using_monetary_locale = old->using_monetary_locale;
+ new->using_numeric_locale = old->using_numeric_locale;
+ new->using_time_locale = old->using_time_locale;
+ new->using_messages_locale = old->using_messages_locale;
+}
+
+static int dupcomponent(int type, locale_t base, locale_t new)
+{
+ /* Always copy from the global locale, since it has mutable components.
+ */
+ struct xlocale_component *src = base->components[type];
+
+ if (&__xlocale_global_locale == base) {
+ new->components[type] = constructors[type](src->locale, new);
+ if (new->components[type]) {
+ strncpy(new->components[type]->locale, src->locale,
+ ENCODING_LEN);
+ }
+ } else if (base->components[type]) {
+ new->components[type] = xlocale_retain(base->components[type]);
+ } else {
+ /* If the component was NULL, return success - if base is a
+ * valid locale then the flag indicating that this isn't
+ * present should be set. If it isn't a valid locale, then
+ * we're stuck anyway. */
+ return 1;
+ }
+ return (0 != new->components[type]);
+}
+
+/*
+ * Public interfaces. These are the five public functions described by the
+ * xlocale interface.
+ */
+
+locale_t newlocale(int mask, const char *locale, locale_t base)
+{
+ int type;
+ const char *realLocale = locale;
+ int useenv = 0;
+ int success = 1;
+
+ _once(&once_control, init_key);
+
+ locale_t new = alloc_locale();
+ if (NULL == new) {
+ return (NULL);
+ }
+
+ FIX_LOCALE(base);
+ copyflags(new, base);
+
+ if (NULL == locale) {
+ realLocale = "C";
+ } else if ('\0' == locale[0]) {
+ useenv = 1;
+ }
+
+ for (type=0 ; type<XLC_LAST ; type++) {
+ if (mask & 1) {
+ if (useenv) {
+ realLocale = __get_locale_env(type);
+ }
+ new->components[type] =
+ constructors[type](realLocale, new);
+ if (new->components[type]) {
+ strncpy(new->components[type]->locale,
+ realLocale, ENCODING_LEN);
+ } else {
+ success = 0;
+ break;
+ }
+ } else {
+ if (!dupcomponent(type, base, new)) {
+ success = 0;
+ break;
+ }
+ }
+ mask >>= 1;
+ }
+ if (0 == success) {
+ xlocale_release(new);
+ new = NULL;
+ }
+
+ return (new);
+}
+
+locale_t duplocale(locale_t base)
+{
+ locale_t new = alloc_locale();
+ int type;
+
+ _once(&once_control, init_key);
+
+ if (NULL == new) {
+ return (NULL);
+ }
+
+ FIX_LOCALE(base);
+ copyflags(new, base);
+
+ for (type=0 ; type<XLC_LAST ; type++) {
+ dupcomponent(type, base, new);
+ }
+
+ return (new);
+}
+
+/*
+ * Free a locale_t. This is quite a poorly named function. It actually
+ * disclaims a reference to a locale_t, rather than freeing it.
+ */
+int
+freelocale(locale_t loc)
+{
+ /* Fail if we're passed something that isn't a locale. */
+ if ((NULL == loc) || (LC_GLOBAL_LOCALE == loc)) {
+ return (-1);
+ }
+ /* If we're passed the global locale, pretend that we freed it but don't
+ * actually do anything. */
+ if (&__xlocale_global_locale == loc) {
+ return (0);
+ }
+ xlocale_release(loc);
+ return (0);
+}
+
+/*
+ * Returns the name of the locale for a particular component of a locale_t.
+ */
+const char *querylocale(int mask, locale_t loc)
+{
+ int type = ffs(mask) - 1;
+ FIX_LOCALE(loc);
+ if (type >= XLC_LAST)
+ return (NULL);
+ if (loc->components[type])
+ return (loc->components[type]->locale);
+ return ("C");
+}
+
+/*
+ * Installs the specified locale_t as this thread's locale.
+ */
+locale_t uselocale(locale_t loc)
+{
+ locale_t old = get_thread_locale();
+ if (NULL != loc) {
+ if (LC_GLOBAL_LOCALE == loc) {
+ loc = NULL;
+ }
+ set_thread_locale(loc);
+ }
+ return (old ? old : LC_GLOBAL_LOCALE);
+}
+
diff --git a/lib/libc/locale/xlocale_private.h b/lib/libc/locale/xlocale_private.h
new file mode 100644
index 0000000..813f719
--- /dev/null
+++ b/lib/libc/locale/xlocale_private.h
@@ -0,0 +1,224 @@
+/*-
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ *
+ * This software was developed by David Chisnall under sponsorship from
+ * the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _XLOCALE_PRIVATE__H_
+#define _XLOCALE_PRIVATE__H_
+
+#include <xlocale.h>
+#include <locale.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <sys/types.h>
+#include <machine/atomic.h>
+#include "setlocale.h"
+
+enum {
+ XLC_COLLATE = 0,
+ XLC_CTYPE,
+ XLC_MONETARY,
+ XLC_NUMERIC,
+ XLC_TIME,
+ XLC_MESSAGES,
+ XLC_LAST
+};
+
+
+/**
+ * Header used for objects that are reference counted. Objects may optionally
+ * have a destructor associated, which is responsible for destroying the
+ * structure. Global / static versions of the structure should have no
+ * destructor set - they can then have their reference counts manipulated as
+ * normal, but will not do anything with them.
+ *
+ * The header stores a retain count - objects are assumed to have a reference
+ * count of 1 when they are created, but the retain count is 0. When the
+ * retain count is less than 0, they are freed.
+ */
+struct xlocale_refcounted {
+ /** Number of references to this component. */
+ long retain_count;
+ /** Function used to destroy this component, if one is required*/
+ void(*destructor)(void*);
+};
+/**
+ * Header for a locale component. All locale components must begin with this
+ * header.
+ */
+struct xlocale_component {
+ struct xlocale_refcounted header;
+ /** Name of the locale used for this component. */
+ char locale[ENCODING_LEN+1];
+};
+
+/**
+ * xlocale structure, stores per-thread locale information.
+ */
+struct _xlocale {
+ struct xlocale_refcounted header;
+ /** Components for the locale. */
+ struct xlocale_component *components[XLC_LAST];
+ /** Flag indicating if components[XLC_MONETARY] has changed since the
+ * last call to localeconv_l() with this locale. */
+ int monetary_locale_changed;
+ /** Flag indicating whether this locale is actually using a locale for
+ * LC_MONETARY (1), or if it should use the C default instead (0). */
+ int using_monetary_locale;
+ /** Flag indicating if components[XLC_NUMERIC] has changed since the
+ * last call to localeconv_l() with this locale. */
+ int numeric_locale_changed;
+ /** Flag indicating whether this locale is actually using a locale for
+ * LC_NUMERIC (1), or if it should use the C default instead (0). */
+ int using_numeric_locale;
+ /** Flag indicating whether this locale is actually using a locale for
+ * LC_TIME (1), or if it should use the C default instead (0). */
+ int using_time_locale;
+ /** Flag indicating whether this locale is actually using a locale for
+ * LC_MESSAGES (1), or if it should use the C default instead (0). */
+ int using_messages_locale;
+ /** The structure to be returned from localeconv_l() for this locale. */
+ struct lconv lconv;
+ /** Persistent state used by mblen() calls. */
+ __mbstate_t mblen;
+ /** Persistent state used by mbrlen() calls. */
+ __mbstate_t mbrlen;
+ /** Persistent state used by mbrtowc() calls. */
+ __mbstate_t mbrtowc;
+ /** Persistent state used by mbsnrtowcs() calls. */
+ __mbstate_t mbsnrtowcs;
+ /** Persistent state used by mbsrtowcs() calls. */
+ __mbstate_t mbsrtowcs;
+ /** Persistent state used by mbtowc() calls. */
+ __mbstate_t mbtowc;
+ /** Persistent state used by wcrtomb() calls. */
+ __mbstate_t wcrtomb;
+ /** Persistent state used by wcsnrtombs() calls. */
+ __mbstate_t wcsnrtombs;
+ /** Persistent state used by wcsrtombs() calls. */
+ __mbstate_t wcsrtombs;
+ /** Persistent state used by wctomb() calls. */
+ __mbstate_t wctomb;
+ /** Buffer used by nl_langinfo_l() */
+ char *csym;
+};
+
+/**
+ * Increments the reference count of a reference-counted structure.
+ */
+__attribute__((unused)) static void*
+xlocale_retain(void *val)
+{
+ struct xlocale_refcounted *obj = val;
+ atomic_add_long(&(obj->retain_count), 1);
+ return (val);
+}
+/**
+ * Decrements the reference count of a reference-counted structure, freeing it
+ * if this is the last reference, calling its destructor if it has one.
+ */
+__attribute__((unused)) static void
+xlocale_release(void *val)
+{
+ struct xlocale_refcounted *obj = val;
+ long count = atomic_fetchadd_long(&(obj->retain_count), -1) - 1;
+ if (count < 0) {
+ if (0 != obj->destructor) {
+ obj->destructor(obj);
+ }
+ }
+}
+
+/**
+ * Load functions. Each takes the name of a locale and a pointer to the data
+ * to be initialised as arguments. Two special values are allowed for the
+ */
+extern void* __collate_load(const char*, locale_t);
+extern void* __ctype_load(const char*, locale_t);
+extern void* __messages_load(const char*, locale_t);
+extern void* __monetary_load(const char*, locale_t);
+extern void* __numeric_load(const char*, locale_t);
+extern void* __time_load(const char*, locale_t);
+
+extern struct _xlocale __xlocale_global_locale;
+extern struct _xlocale __xlocale_C_locale;
+
+/**
+ * Caches the rune table in TLS for fast access.
+ */
+void __set_thread_rune_locale(locale_t loc);
+/**
+ * Flag indicating whether a per-thread locale has been set. If no per-thread
+ * locale has ever been set, then we always use the global locale.
+ */
+extern int __has_thread_locale;
+#ifndef __NO_TLS
+/**
+ * The per-thread locale. Avoids the need to use pthread lookup functions when
+ * getting the per-thread locale.
+ */
+extern _Thread_local locale_t __thread_locale;
+
+/**
+ * Returns the current locale for this thread, or the global locale if none is
+ * set. The caller does not have to free the locale. The return value from
+ * this call is not guaranteed to remain valid after the locale changes. As
+ * such, this should only be called within libc functions.
+ */
+static inline locale_t __get_locale(void)
+{
+
+ if (!__has_thread_locale) {
+ return (&__xlocale_global_locale);
+ }
+ return (__thread_locale ? __thread_locale : &__xlocale_global_locale);
+}
+#else
+locale_t __get_locale(void);
+#endif
+
+/**
+ * Two magic values are allowed for locale_t objects. NULL and -1. This
+ * function maps those to the real locales that they represent.
+ */
+static inline locale_t get_real_locale(locale_t locale)
+{
+ switch ((intptr_t)locale) {
+ case 0: return (&__xlocale_C_locale);
+ case -1: return (&__xlocale_global_locale);
+ default: return (locale);
+ }
+}
+
+/**
+ * Replace a placeholder locale with the real global or thread-local locale_t.
+ */
+#define FIX_LOCALE(l) (l = get_real_locale(l))
+
+#endif
diff --git a/lib/libc/mips/Makefile.inc b/lib/libc/mips/Makefile.inc
new file mode 100644
index 0000000..a02ca01
--- /dev/null
+++ b/lib/libc/mips/Makefile.inc
@@ -0,0 +1,7 @@
+# $NetBSD: Makefile.inc,v 1.7 2005/09/17 11:49:39 tsutsui Exp $
+# $FreeBSD$
+
+CFLAGS+=-DSOFTFLOAT
+
+MDSRCS+= machdep_ldisd.c
+SYM_MAPS+= ${.CURDIR}/mips/Symbol.map
diff --git a/lib/libc/mips/SYS.h b/lib/libc/mips/SYS.h
new file mode 100644
index 0000000..10205b8
--- /dev/null
+++ b/lib/libc/mips/SYS.h
@@ -0,0 +1,137 @@
+/* $NetBSD: SYS.h,v 1.19 2009/12/14 01:07:41 matt Exp $ */
+/* $FreeBSD$ */
+
+/*-
+ * Copyright (c) 1996 Jonathan Stone
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Jonathan Stone for
+ * the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: @(#)SYS.h 8.1 (Berkeley) 6/4/93
+ */
+
+#include <sys/syscall.h>
+
+#include <machine/asm.h>
+
+/*
+ * If compiling for shared libs, Emit sysV ABI PIC segment pseudo-ops.
+ *
+ * i) Emit .abicalls before .LEAF entrypoint, and .cpload/.cprestore after.
+ * ii) Do interprocedure jumps indirectly via t9, with the side-effect of
+ * preserving the callee's entry address in t9.
+ */
+#ifdef __ABICALLS__
+ .abicalls
+# if defined(__mips_o32) || defined(__mips_o64)
+# define PIC_PROLOGUE(x) SETUP_GP
+# define PIC_TAILCALL(l) PTR_LA t9, _C_LABEL(l); jr t9
+# define PIC_RETURN() j ra
+# else
+# define PIC_PROLOGUE(x) SETUP_GP64(t3, x)
+# define PIC_TAILCALL(l) PTR_LA t9, _C_LABEL(l); RESTORE_GP64; jr t9
+# define PIC_RETURN() RESTORE_GP64; j ra
+# endif
+#else
+# define PIC_PROLOGUE(x)
+# define PIC_TAILCALL(l) j _C_LABEL(l)
+# define PIC_RETURN() j ra
+#endif /* __ABICALLS__ */
+
+# define SYSTRAP(x) li v0,SYS_ ## x; syscall;
+
+/*
+ * Do a syscall that cannot fail (sync, get{p,u,g,eu,eg)id)
+ */
+#define RSYSCALL_NOERROR(x) \
+ PSEUDO_NOERROR(x)
+
+/*
+ * Do a normal syscall.
+ */
+#define RSYSCALL(x) \
+ PSEUDO(x)
+
+/*
+ * Do a renamed or pseudo syscall (e.g., _exit()), where the entrypoint
+ * and syscall name are not the same.
+ */
+#define PSEUDO_NOERROR(x) \
+LEAF(__sys_ ## x); \
+ .weak _C_LABEL(x); \
+ _C_LABEL(x) = _C_LABEL(__CONCAT(__sys_,x)); \
+ .weak _C_LABEL(__CONCAT(_,x)); \
+ _C_LABEL(__CONCAT(_,x)) = _C_LABEL(__CONCAT(__sys_,x)); \
+ SYSTRAP(x); \
+ j ra; \
+ END(__sys_ ## x)
+
+#define PSEUDO(x) \
+LEAF(__sys_ ## x); \
+ .weak _C_LABEL(x); \
+ _C_LABEL(x) = _C_LABEL(__CONCAT(__sys_,x)); \
+ .weak _C_LABEL(__CONCAT(_,x)); \
+ _C_LABEL(__CONCAT(_,x)) = _C_LABEL(__CONCAT(__sys_,x)); \
+ PIC_PROLOGUE(__sys_ ## x); \
+ SYSTRAP(x); \
+ bne a3,zero,err; \
+ PIC_RETURN(); \
+err: \
+ PIC_TAILCALL(__cerror); \
+END(__sys_ ## x)
diff --git a/lib/libc/mips/Symbol.map b/lib/libc/mips/Symbol.map
new file mode 100644
index 0000000..d7fbd0a
--- /dev/null
+++ b/lib/libc/mips/Symbol.map
@@ -0,0 +1,77 @@
+/*
+ * $FreeBSD$
+ */
+
+/*
+ * This only needs to contain symbols that are not listed in
+ * symbol maps from other parts of libc (i.e., not found in
+ * stdlib/Symbol.map, string/Symbol.map, sys/Symbol.map, ...).
+ */
+FBSD_1.0 {
+ /* PSEUDO syscalls */
+ _exit;
+
+ _setjmp;
+ _longjmp;
+ alloca;
+ fabs;
+ __infinity;
+ __nan;
+ makecontext;
+ setjmp;
+ longjmp;
+ sigsetjmp;
+ siglongjmp;
+ htonl;
+ htons;
+ ntohl;
+ ntohs;
+ vfork;
+ brk;
+ cerror; /* XXX - Should this be .cerror (see sys/cerror.S)? */
+ sbrk;
+};
+
+FBSDprivate_1.0 {
+ /* PSEUDO syscalls */
+ __sys_getlogin;
+ _getlogin;
+ __sys_exit;
+
+ _set_tp;
+ ___longjmp;
+ __umodsi3;
+ __modsi3;
+ __udivsi3;
+ __divsi3;
+ __makecontext;
+ __longjmp;
+ signalcontext;
+ _signalcontext;
+ __siglongjmp;
+ __sys_vfork;
+ _vfork;
+ _end;
+ __curbrk;
+ minbrk;
+ _brk;
+ _sbrk;
+
+ /* softfloat */
+ __addsf3;
+ __adddf3;
+ __subsf3;
+ __subdf3;
+ __mulsf3;
+ __muldf3;
+ __divsf3;
+ __divdf3;
+ __floatsisf;
+ __floatsidf;
+ __fixsfsi;
+ __fixdfsi;
+ __fixunssfsi;
+ __fixunsdfsi;
+ __extendsfdf2;
+ __truncdfsf2;
+};
diff --git a/lib/libc/mips/_fpmath.h b/lib/libc/mips/_fpmath.h
new file mode 100644
index 0000000..f006a58
--- /dev/null
+++ b/lib/libc/mips/_fpmath.h
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+union IEEEl2bits {
+ long double e;
+ struct {
+#ifndef __MIPSEB__
+ unsigned int manl :32;
+ unsigned int manh :20;
+ unsigned int exp :11;
+ unsigned int sign :1;
+#else
+ unsigned int sign :1;
+ unsigned int exp :11;
+ unsigned int manh :20;
+ unsigned int manl :32;
+#endif
+ } bits;
+};
+
+#define LDBL_NBIT 0
+#define mask_nbit_l(u) ((void)0)
+#define LDBL_IMPLICIT_NBIT
+
+#define LDBL_MANH_SIZE 20
+#define LDBL_MANL_SIZE 32
+
+#define LDBL_TO_ARRAY32(u, a) do { \
+ (a)[0] = (uint32_t)(u).bits.manl; \
+ (a)[1] = (uint32_t)(u).bits.manh; \
+} while(0)
diff --git a/lib/libc/mips/arith.h b/lib/libc/mips/arith.h
new file mode 100644
index 0000000..02d6d2e
--- /dev/null
+++ b/lib/libc/mips/arith.h
@@ -0,0 +1,29 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * NOTE: The definitions in this file must be correct or strtod(3) and
+ * floating point formats in printf(3) will break! The file can be
+ * generated by running contrib/gdtoa/arithchk.c on the target
+ * architecture. See contrib/gdtoa/gdtoaimp.h for details.
+ */
+#include <machine/endian.h>
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define IEEE_MC68k
+#define Arith_Kind_ASL 2
+#define Double_Align
+#else
+/* TODO: Generate these values on a LE machine */
+/* Current values were stolen from ia64 except the
+ * Xpointer define.
+ */
+#define IEEE_8087
+#define Arith_Kind_ASL 1
+#define Long int
+#define Intcast (int)(long)
+#define Double_Align
+#endif
diff --git a/lib/libc/mips/gd_qnan.h b/lib/libc/mips/gd_qnan.h
new file mode 100644
index 0000000..69eeaf9
--- /dev/null
+++ b/lib/libc/mips/gd_qnan.h
@@ -0,0 +1,48 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * This file can be generated by compiling and running contrib/gdtoa/qnan.c
+ * on the target architecture after arith.h has been generated.
+ *
+ * $FreeBSD$
+ */
+
+
+#include <machine/endian.h>
+
+#if BYTE_ORDER == BIG_ENDIAN
+/* These values were gained on a running
+ * Octeon in Big Endian order. They were gotten
+ * by running ./qnan after arithchk was ran and
+ * got us the proper values for arith.h.
+ */
+#define f_QNAN 0x7f900000
+#define d_QNAN0 0x7ff80000
+#define d_QNAN1 0x0
+#define ld_QNAN0 0x7ff80000
+#define ld_QNAN1 0x0
+#define ld_QNAN2 0x0
+#define ld_QNAN3 0x0
+#define ldus_QNAN0 0x7ff8
+#define ldus_QNAN1 0x0
+#define ldus_QNAN2 0x0
+#define ldus_QNAN3 0x0
+#define ldus_QNAN4 0x0
+#else
+/* FIX FIX, need to run this on a Little Endian
+ * machine and get the proper values, these here
+ * were stolen fromn i386/gd_qnan.h
+ */
+#define f_QNAN 0x7fc00000
+#define d_QNAN0 0x0
+#define d_QNAN1 0x7ff80000
+#define ld_QNAN0 0x0
+#define ld_QNAN1 0xc0000000
+#define ld_QNAN2 0x7fff
+#define ld_QNAN3 0x0
+#define ldus_QNAN0 0x0
+#define ldus_QNAN1 0x0
+#define ldus_QNAN2 0x0
+#define ldus_QNAN3 0xc000
+#define ldus_QNAN4 0x7fff
+#endif
diff --git a/lib/libc/mips/gdtoa/Makefile.inc b/lib/libc/mips/gdtoa/Makefile.inc
new file mode 100644
index 0000000..dd6268c
--- /dev/null
+++ b/lib/libc/mips/gdtoa/Makefile.inc
@@ -0,0 +1,4 @@
+# $NetBSD: Makefile.inc,v 1.1 2006/03/15 17:35:18 kleink Exp $
+# $FreeBSD$
+
+SRCS+= strtof.c
diff --git a/lib/libc/mips/gdtoa/arith.h b/lib/libc/mips/gdtoa/arith.h
new file mode 100644
index 0000000..8b700f8
--- /dev/null
+++ b/lib/libc/mips/gdtoa/arith.h
@@ -0,0 +1,10 @@
+/* $NetBSD: arith.h,v 1.1 2006/01/25 15:33:28 kleink Exp $ */
+/* $FreeBSD$ */
+
+#include <machine/endian.h>
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define IEEE_BIG_ENDIAN
+#else
+#define IEEE_LITTLE_ENDIAN
+#endif
diff --git a/lib/libc/mips/gen/Makefile.inc b/lib/libc/mips/gen/Makefile.inc
new file mode 100644
index 0000000..9d9cc7a
--- /dev/null
+++ b/lib/libc/mips/gen/Makefile.inc
@@ -0,0 +1,10 @@
+# $NetBSD: Makefile.inc,v 1.27 2005/10/07 17:16:40 tsutsui Exp $
+# $FreeBSD$
+
+SRCS+= infinity.c fabs.c ldexp.c
+
+# SRCS+= flt_rounds.c fpgetmask.c fpgetround.c fpgetsticky.c fpsetmask.c \
+# fpsetround.c fpsetsticky.c
+
+SRCS+= _ctx_start.S _set_tp.c _setjmp.S getcontextx.c makecontext.c \
+ setjmp.S signalcontext.c sigsetjmp.S
diff --git a/lib/libc/mips/gen/_ctx_start.S b/lib/libc/mips/gen/_ctx_start.S
new file mode 100644
index 0000000..5d754a9
--- /dev/null
+++ b/lib/libc/mips/gen/_ctx_start.S
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2010 Juli Mallett.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * XXX gp?
+ */
+ENTRY(_ctx_start)
+ jalr t9
+
+ move a0, s0
+ PTR_LA t9, _ctx_done
+ jalr t9
+
+ break 0
+END(_ctx_start)
diff --git a/lib/libc/mips/gen/_set_tp.c b/lib/libc/mips/gen/_set_tp.c
new file mode 100644
index 0000000..0bf04b52
--- /dev/null
+++ b/lib/libc/mips/gen/_set_tp.c
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <string.h>
+#include <stdint.h>
+
+#include <machine/sysarch.h>
+
+void
+_set_tp(void *tp)
+{
+
+ sysarch(MIPS_SET_TLS, tp);
+}
diff --git a/lib/libc/mips/gen/_setjmp.S b/lib/libc/mips/gen/_setjmp.S
new file mode 100644
index 0000000..3918407
--- /dev/null
+++ b/lib/libc/mips/gen/_setjmp.S
@@ -0,0 +1,126 @@
+/* $NetBSD: _setjmp.S,v 1.20.34.5 2010/02/03 23:46:47 matt Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include <machine/regnum.h>
+
+#include "SYS.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+ RCSID("from: @(#)_setjmp.s 8.1 (Berkeley) 6/4/93")
+#else
+ RCSID("$NetBSD: _setjmp.S,v 1.20.34.5 2010/02/03 23:46:47 matt Exp $")
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * C library -- _setjmp, _longjmp
+ *
+ * _longjmp(a,v)
+ * will generate a "return(v)" from
+ * the last call to
+ * _setjmp(a)
+ * by restoring registers from the stack,
+ * The previous signal state is NOT restored.
+ */
+
+ .set noreorder
+
+LEAF(_setjmp)
+ REG_PROLOGUE
+ REG_LI v0, _JB_MAGIC__SETJMP
+ REG_S v0, (_JB_MAGIC * SZREG)(a0)
+ REG_S ra, (_JB_REG_RA * SZREG)(a0)
+ REG_S s0, (_JB_REG_S0 * SZREG)(a0)
+ REG_S s1, (_JB_REG_S1 * SZREG)(a0)
+ REG_S s2, (_JB_REG_S2 * SZREG)(a0)
+ REG_S s3, (_JB_REG_S3 * SZREG)(a0)
+ REG_S s4, (_JB_REG_S4 * SZREG)(a0)
+ REG_S s5, (_JB_REG_S5 * SZREG)(a0)
+ REG_S s6, (_JB_REG_S6 * SZREG)(a0)
+ REG_S s7, (_JB_REG_S7 * SZREG)(a0)
+ REG_S s8, (_JB_REG_S8 * SZREG)(a0)
+#if defined(__mips_n32) || defined(__mips_n64)
+ REG_S gp, (_JB_REG_GP * SZREG)(a0) # newabi gp is callee-saved
+#endif
+ REG_S sp, (_JB_REG_SP * SZREG)(a0)
+ REG_EPILOGUE
+
+ j ra
+ move v0, zero
+END(_setjmp)
+
+LEAF(_longjmp)
+ PIC_PROLOGUE(_longjmp)
+ PTR_SUBU sp, sp, CALLFRAME_SIZ
+ SAVE_GP(CALLFRAME_GP)
+
+ REG_PROLOGUE
+ REG_L v0, (_JB_MAGIC * SZREG)(a0) # get magic number
+ REG_L ra, (_JB_REG_RA * SZREG)(a0)
+ REG_LI t0, _JB_MAGIC__SETJMP
+ bne v0, t0, botch # jump if error
+ PTR_ADDU sp, sp, CALLFRAME_SIZ # does not matter, sanity
+ REG_L s0, (_JB_REG_S0 * SZREG)(a0)
+ REG_L s1, (_JB_REG_S1 * SZREG)(a0)
+ REG_L s2, (_JB_REG_S2 * SZREG)(a0)
+ REG_L s3, (_JB_REG_S3 * SZREG)(a0)
+ REG_L s4, (_JB_REG_S4 * SZREG)(a0)
+ REG_L s5, (_JB_REG_S5 * SZREG)(a0)
+ REG_L s6, (_JB_REG_S6 * SZREG)(a0)
+ REG_L s7, (_JB_REG_S7 * SZREG)(a0)
+#if defined(__mips_n32) || defined(__mips_n64)
+ REG_L gp, (_JB_REG_GP * SZREG)(a0)
+#endif
+ REG_L sp, (_JB_REG_SP * SZREG)(a0)
+ REG_L s8, (_JB_REG_S8 * SZREG)(a0)
+
+ REG_EPILOGUE
+ move v0, a1 # get return value in 1st arg
+ j ra
+ nop
+
+botch:
+ /*
+ * We know we aren't returning so we don't care about restoring
+ * our caller's GP.
+ */
+ PTR_LA t9, _C_LABEL(longjmperror)
+ jalr t9
+ nop
+
+ PIC_TAILCALL(abort)
+END(_longjmp)
diff --git a/lib/libc/mips/gen/fabs.S b/lib/libc/mips/gen/fabs.S
new file mode 100644
index 0000000..3b79249
--- /dev/null
+++ b/lib/libc/mips/gen/fabs.S
@@ -0,0 +1,58 @@
+/* $NetBSD: fabs.S,v 1.7 2003/08/07 16:42:15 agc Exp $ */
+
+/*-
+ * Copyright (c) 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)fabs.s 8.1 (Berkeley) 2/16/94")
+ ASMSTR("$NetBSD: fabs.S,v 1.7 2003/08/07 16:42:15 agc Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+
+#ifdef __ABICALLS__
+ .abicalls
+#endif
+ .set noreorder
+
+/*
+ * fabs(x)
+ * double x;
+ *
+ * Return absolute value of x.
+ */
+LEAF(fabs)
+ j ra
+ abs.d $f0, $f12 # compute absolute value of x
+END(fabs)
diff --git a/lib/libc/mips/gen/fabs.c b/lib/libc/mips/gen/fabs.c
new file mode 100644
index 0000000..8bb1502
--- /dev/null
+++ b/lib/libc/mips/gen/fabs.c
@@ -0,0 +1,46 @@
+/* $NetBSD: fabs.c,v 1.2 2002/05/26 11:48:01 wiz Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * fabs(x) returns the absolute value of x.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+double
+fabs(double x)
+{
+ if (x < 0)
+ x = -x;
+ return(x);
+}
diff --git a/lib/libc/mips/gen/flt_rounds.c b/lib/libc/mips/gen/flt_rounds.c
new file mode 100644
index 0000000..9fc64a5
--- /dev/null
+++ b/lib/libc/mips/gen/flt_rounds.c
@@ -0,0 +1,30 @@
+/* $NetBSD: flt_rounds.c,v 1.5 2005/12/24 23:10:08 perry Exp $ */
+
+/*
+ * Written by J.T. Conklin, Apr 11, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: flt_rounds.c,v 1.5 2005/12/24 23:10:08 perry Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include <machine/float.h>
+
+static const int map[] = {
+ 1, /* round to nearest */
+ 0, /* round to zero */
+ 2, /* round to positive infinity */
+ 3 /* round to negative infinity */
+};
+
+int
+__flt_rounds()
+{
+ int x;
+
+ __asm("cfc1 %0,$31" : "=r" (x));
+ return map[x & 0x03];
+}
diff --git a/lib/libc/mips/gen/getcontextx.c b/lib/libc/mips/gen/getcontextx.c
new file mode 100644
index 0000000..307978a
--- /dev/null
+++ b/lib/libc/mips/gen/getcontextx.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int
+__getcontextx_size(void)
+{
+
+ return (sizeof(ucontext_t));
+}
+
+int
+__fillcontextx(char *ctx)
+{
+ ucontext_t *ucp;
+
+ ucp = (ucontext_t *)ctx;
+ return (getcontext(ucp));
+}
+
+__weak_reference(__getcontextx, getcontextx);
+
+ucontext_t *
+__getcontextx(void)
+{
+ char *ctx;
+ int error;
+
+ ctx = malloc(__getcontextx_size());
+ if (ctx == NULL)
+ return (NULL);
+ if (__fillcontextx(ctx) == -1) {
+ error = errno;
+ free(ctx);
+ errno = error;
+ return (NULL);
+ }
+ return ((ucontext_t *)ctx);
+}
diff --git a/lib/libc/mips/gen/hardfloat/fpgetmask.c b/lib/libc/mips/gen/hardfloat/fpgetmask.c
new file mode 100644
index 0000000..505a74c
--- /dev/null
+++ b/lib/libc/mips/gen/hardfloat/fpgetmask.c
@@ -0,0 +1,29 @@
+/* $NetBSD: fpgetmask.c,v 1.5 2005/12/24 23:10:08 perry Exp $ */
+
+/*
+ * Written by J.T. Conklin, Apr 11, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: fpgetmask.c,v 1.5 2005/12/24 23:10:08 perry Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "namespace.h"
+
+#include <ieeefp.h>
+
+#ifdef __weak_alias
+__weak_alias(fpgetmask,_fpgetmask)
+#endif
+
+fp_except_t
+fpgetmask()
+{
+ int x;
+
+ __asm("cfc1 %0,$31" : "=r" (x));
+ return (x >> 7) & 0x1f;
+}
diff --git a/lib/libc/mips/gen/hardfloat/fpgetround.c b/lib/libc/mips/gen/hardfloat/fpgetround.c
new file mode 100644
index 0000000..6d0f11a
--- /dev/null
+++ b/lib/libc/mips/gen/hardfloat/fpgetround.c
@@ -0,0 +1,29 @@
+/* $NetBSD: fpgetround.c,v 1.5 2005/12/24 23:10:08 perry Exp $ */
+
+/*
+ * Written by J.T. Conklin, Apr 11, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: fpgetround.c,v 1.5 2005/12/24 23:10:08 perry Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "namespace.h"
+
+#include <ieeefp.h>
+
+#ifdef __weak_alias
+__weak_alias(fpgetround,_fpgetround)
+#endif
+
+fp_rnd_t
+fpgetround()
+{
+ int x;
+
+ __asm("cfc1 %0,$31" : "=r" (x));
+ return x & 0x03;
+}
diff --git a/lib/libc/mips/gen/hardfloat/fpgetsticky.c b/lib/libc/mips/gen/hardfloat/fpgetsticky.c
new file mode 100644
index 0000000..8028261
--- /dev/null
+++ b/lib/libc/mips/gen/hardfloat/fpgetsticky.c
@@ -0,0 +1,29 @@
+/* $NetBSD: fpgetsticky.c,v 1.5 2005/12/24 23:10:08 perry Exp $ */
+
+/*
+ * Written by J.T. Conklin, Apr 11, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: fpgetsticky.c,v 1.5 2005/12/24 23:10:08 perry Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "namespace.h"
+
+#include <ieeefp.h>
+
+#ifdef __weak_alias
+__weak_alias(fpgetsticky,_fpgetsticky)
+#endif
+
+fp_except_t
+fpgetsticky()
+{
+ int x;
+
+ __asm("cfc1 %0,$31" : "=r" (x));
+ return (x >> 2) & 0x1f;
+}
diff --git a/lib/libc/mips/gen/hardfloat/fpsetmask.c b/lib/libc/mips/gen/hardfloat/fpsetmask.c
new file mode 100644
index 0000000..7abb3fd
--- /dev/null
+++ b/lib/libc/mips/gen/hardfloat/fpsetmask.c
@@ -0,0 +1,38 @@
+/* $NetBSD: fpsetmask.c,v 1.5 2005/12/24 23:10:08 perry Exp $ */
+
+/*
+ * Written by J.T. Conklin, Apr 11, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: fpsetmask.c,v 1.5 2005/12/24 23:10:08 perry Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "namespace.h"
+
+#include <ieeefp.h>
+
+#ifdef __weak_alias
+__weak_alias(fpsetmask,_fpsetmask)
+#endif
+
+fp_except_t
+fpsetmask(mask)
+ fp_except_t mask;
+{
+ fp_except_t old;
+ fp_except_t new;
+
+ __asm("cfc1 %0,$31" : "=r" (old));
+
+ new = old;
+ new &= ~(0x1f << 7);
+ new |= ((mask & 0x1f) << 7);
+
+ __asm("ctc1 %0,$31" : : "r" (new));
+
+ return (old >> 7) & 0x1f;
+}
diff --git a/lib/libc/mips/gen/hardfloat/fpsetround.c b/lib/libc/mips/gen/hardfloat/fpsetround.c
new file mode 100644
index 0000000..0205161
--- /dev/null
+++ b/lib/libc/mips/gen/hardfloat/fpsetround.c
@@ -0,0 +1,37 @@
+/* $NetBSD: fpsetround.c,v 1.5 2005/12/24 23:10:08 perry Exp $ */
+
+/*
+ * Written by J.T. Conklin, Apr 11, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: fpsetround.c,v 1.5 2005/12/24 23:10:08 perry Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "namespace.h"
+
+#include <ieeefp.h>
+
+#ifdef __weak_alias
+__weak_alias(fpsetround,_fpsetround)
+#endif
+
+fp_rnd_t
+fpsetround(fp_rnd_t rnd_dir)
+{
+ fp_rnd_t old;
+ fp_rnd_t new;
+
+ __asm("cfc1 %0,$31" : "=r" (old));
+
+ new = old;
+ new &= ~0x03;
+ new |= (rnd_dir & 0x03);
+
+ __asm("ctc1 %0,$31" : : "r" (new));
+
+ return old & 0x03;
+}
diff --git a/lib/libc/mips/gen/hardfloat/fpsetsticky.c b/lib/libc/mips/gen/hardfloat/fpsetsticky.c
new file mode 100644
index 0000000..e433671
--- /dev/null
+++ b/lib/libc/mips/gen/hardfloat/fpsetsticky.c
@@ -0,0 +1,38 @@
+/* $NetBSD: fpsetsticky.c,v 1.5 2005/12/24 23:10:08 perry Exp $ */
+
+/*
+ * Written by J.T. Conklin, Apr 11, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: fpsetsticky.c,v 1.5 2005/12/24 23:10:08 perry Exp $");
+#endif /* LIBC_SCCS and not lint */
+
+#include "namespace.h"
+
+#include <ieeefp.h>
+
+#ifdef __weak_alias
+__weak_alias(fpsetsticky,_fpsetsticky)
+#endif
+
+fp_except
+fpsetsticky(sticky)
+ fp_except sticky;
+{
+ fp_except old;
+ fp_except new;
+
+ __asm("cfc1 %0,$31" : "=r" (old));
+
+ new = old;
+ new &= ~(0x1f << 2);
+ new |= ((sticky & 0x1f) << 2);
+
+ __asm("ctc1 %0,$31" : : "r" (new));
+
+ return (old >> 2) & 0x1f;
+}
diff --git a/lib/libc/mips/gen/infinity.c b/lib/libc/mips/gen/infinity.c
new file mode 100644
index 0000000..55cf25f
--- /dev/null
+++ b/lib/libc/mips/gen/infinity.c
@@ -0,0 +1,26 @@
+/*
+ * infinity.c
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <math.h>
+
+/* bytes for +Infinity on a 387 */
+const union __infinity_un __infinity = {
+#if BYTE_ORDER == BIG_ENDIAN
+ { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 }
+#else
+ { 0, 0, 0, 0, 0, 0, 0xf0, 0x7f }
+#endif
+};
+
+/* bytes for NaN */
+const union __nan_un __nan = {
+#if BYTE_ORDER == BIG_ENDIAN
+ {0x7f, 0xa0, 0, 0}
+#else
+ { 0, 0, 0xa0, 0x7f }
+#endif
+};
diff --git a/lib/libc/mips/gen/ldexp.S b/lib/libc/mips/gen/ldexp.S
new file mode 100644
index 0000000..caee703
--- /dev/null
+++ b/lib/libc/mips/gen/ldexp.S
@@ -0,0 +1,219 @@
+/* $NetBSD: ldexp.S,v 1.8 2003/08/07 16:42:15 agc Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)ldexp.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: ldexp.S,v 1.8 2003/08/07 16:42:15 agc Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef __ABICALLS__
+ .abicalls
+#endif
+
+#define DEXP_INF 0x7ff
+#define DEXP_BIAS 1023
+#define DEXP_MIN -1022
+#define DEXP_MAX 1023
+#define DFRAC_BITS 52
+#define DIMPL_ONE 0x00100000
+#define DLEAD_ZEROS 31 - 20
+#define STICKYBIT 1
+#define GUARDBIT 0x80000000
+#define DSIGNAL_NAN 0x00040000
+#define DQUIET_NAN0 0x0007ffff
+#define DQUIET_NAN1 0xffffffff
+
+/*
+ * double ldexp(x, N)
+ * double x; int N;
+ *
+ * Return x * (2**N), for integer values N.
+ */
+LEAF(ldexp)
+ mfc1 v1, $f13 # get MSW of x
+ mfc1 t3, $f12 # get LSW of x
+ sll t1, v1, 1 # get x exponent
+ srl t1, t1, 32 - 11
+ beq t1, DEXP_INF, 9f # is it a NAN or infinity?
+ beq t1, zero, 1f # zero or denormalized number?
+ addu t1, t1, a2 # scale exponent
+ sll v0, a2, 20 # position N for addition
+ bge t1, DEXP_INF, 8f # overflow?
+ addu v0, v0, v1 # multiply by (2**N)
+ ble t1, zero, 4f # underflow?
+ mtc1 v0, $f1 # save MSW of result
+ mtc1 t3, $f0 # save LSW of result
+ j ra
+1:
+ sll t2, v1, 32 - 20 # get x fraction
+ srl t2, t2, 32 - 20
+ srl t0, v1, 31 # get x sign
+ bne t2, zero, 1f
+ beq t3, zero, 9f # result is zero
+1:
+/*
+ * Find out how many leading zero bits are in t2,t3 and put in t9.
+ */
+ move v0, t2
+ move t9, zero
+ bne t2, zero, 1f
+ move v0, t3
+ addu t9, 32
+1:
+ srl ta0, v0, 16
+ bne ta0, zero, 1f
+ addu t9, 16
+ sll v0, 16
+1:
+ srl ta0, v0, 24
+ bne ta0, zero, 1f
+ addu t9, 8
+ sll v0, 8
+1:
+ srl ta0, v0, 28
+ bne ta0, zero, 1f
+ addu t9, 4
+ sll v0, 4
+1:
+ srl ta0, v0, 30
+ bne ta0, zero, 1f
+ addu t9, 2
+ sll v0, 2
+1:
+ srl ta0, v0, 31
+ bne ta0, zero, 1f
+ addu t9, 1
+/*
+ * Now shift t2,t3 the correct number of bits.
+ */
+1:
+ subu t9, t9, DLEAD_ZEROS # dont count normal leading zeros
+ li t1, DEXP_MIN + DEXP_BIAS
+ subu t1, t1, t9 # adjust exponent
+ addu t1, t1, a2 # scale exponent
+ li v0, 32
+ blt t9, v0, 1f
+ subu t9, t9, v0 # shift fraction left >= 32 bits
+ sll t2, t3, t9
+ move t3, zero
+ b 2f
+1:
+ subu v0, v0, t9 # shift fraction left < 32 bits
+ sll t2, t2, t9
+ srl ta0, t3, v0
+ or t2, t2, ta0
+ sll t3, t3, t9
+2:
+ bge t1, DEXP_INF, 8f # overflow?
+ ble t1, zero, 4f # underflow?
+ sll t2, t2, 32 - 20 # clear implied one bit
+ srl t2, t2, 32 - 20
+3:
+ sll t1, t1, 31 - 11 # reposition exponent
+ sll t0, t0, 31 # reposition sign
+ or t0, t0, t1 # put result back together
+ or t0, t0, t2
+ mtc1 t0, $f1 # save MSW of result
+ mtc1 t3, $f0 # save LSW of result
+ j ra
+4:
+ li v0, 0x80000000
+ ble t1, -52, 7f # is result too small for denorm?
+ sll t2, v1, 31 - 20 # clear exponent, extract fraction
+ or t2, t2, v0 # set implied one bit
+ blt t1, -30, 2f # will all bits in t3 be shifted out?
+ srl t2, t2, 31 - 20 # shift fraction back to normal position
+ subu t1, t1, 1
+ sll ta0, t2, t1 # shift right t2,t3 based on exponent
+ srl t8, t3, t1 # save bits shifted out
+ negu t1
+ srl t3, t3, t1
+ or t3, t3, ta0
+ srl t2, t2, t1
+ bge t8, zero, 1f # does result need to be rounded?
+ addu t3, t3, 1 # round result
+ sltu ta0, t3, 1
+ sll t8, t8, 1
+ addu t2, t2, ta0
+ bne t8, zero, 1f # round result to nearest
+ and t3, t3, ~1
+1:
+ mtc1 t3, $f0 # save denormalized result (LSW)
+ mtc1 t2, $f1 # save denormalized result (MSW)
+ bge v1, zero, 1f # should result be negative?
+ neg.d $f0, $f0 # negate result
+1:
+ j ra
+2:
+ mtc1 zero, $f1 # exponent and upper fraction
+ addu t1, t1, 20 # compute amount to shift right by
+ sll t8, t2, t1 # save bits shifted out
+ negu t1
+ srl t3, t2, t1
+ bge t8, zero, 1f # does result need to be rounded?
+ addu t3, t3, 1 # round result
+ sltu ta0, t3, 1
+ sll t8, t8, 1
+ mtc1 ta0, $f1 # exponent and upper fraction
+ bne t8, zero, 1f # round result to nearest
+ and t3, t3, ~1
+1:
+ mtc1 t3, $f0
+ bge v1, zero, 1f # is result negative?
+ neg.d $f0, $f0 # negate result
+1:
+ j ra
+7:
+ mtc1 zero, $f0 # result is zero
+ mtc1 zero, $f1
+ beq t0, zero, 1f # is result positive?
+ neg.d $f0, $f0 # negate result
+1:
+ j ra
+8:
+ li t1, 0x7ff00000 # result is infinity (MSW)
+ mtc1 t1, $f1
+ mtc1 zero, $f0 # result is infinity (LSW)
+ bge v1, zero, 1f # should result be negative infinity?
+ neg.d $f0, $f0 # result is negative infinity
+1:
+ add.d $f0, $f0 # cause overflow faults if enabled
+ j ra
+9:
+ mov.d $f0, $f12 # yes, result is just x
+ j ra
+END(ldexp)
diff --git a/lib/libc/mips/gen/longjmp.c b/lib/libc/mips/gen/longjmp.c
new file mode 100644
index 0000000..ee01ad5
--- /dev/null
+++ b/lib/libc/mips/gen/longjmp.c
@@ -0,0 +1,110 @@
+/* $NetBSD: longjmp.c,v 1.1 2005/09/17 11:49:39 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 2003 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christian Limpach and Matt Thomas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include "namespace.h"
+#include <sys/types.h>
+#include <ucontext.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <machine/regnum.h>
+
+void
+__longjmp14(jmp_buf env, int val)
+{
+ struct sigcontext *sc = (void *)env;
+ ucontext_t uc;
+
+ /* Ensure non-zero SP and sigcontext magic number is present */
+ if (sc->sc_regs[_R_SP] == 0 || sc->sc_regs[_R_ZERO] != 0xACEDBADE)
+ goto err;
+
+ /* Ensure non-zero return value */
+ if (val == 0)
+ val = 1;
+
+ /*
+ * Set _UC_{SET,CLR}STACK according to SS_ONSTACK.
+ *
+ * Restore the signal mask with sigprocmask() instead of _UC_SIGMASK,
+ * since libpthread may want to interpose on signal handling.
+ */
+ uc.uc_flags = _UC_CPU | (sc->sc_onstack ? _UC_SETSTACK : _UC_CLRSTACK);
+
+ sigprocmask(SIG_SETMASK, &sc->sc_mask, NULL);
+
+ /* Clear uc_link */
+ uc.uc_link = 0;
+
+ /* Save return value in context */
+ uc.uc_mcontext.__gregs[_R_V0] = val;
+
+ /* Copy saved registers */
+ uc.uc_mcontext.__gregs[_REG_S0] = sc->sc_regs[_R_S0];
+ uc.uc_mcontext.__gregs[_REG_S1] = sc->sc_regs[_R_S1];
+ uc.uc_mcontext.__gregs[_REG_S2] = sc->sc_regs[_R_S2];
+ uc.uc_mcontext.__gregs[_REG_S3] = sc->sc_regs[_R_S3];
+ uc.uc_mcontext.__gregs[_REG_S4] = sc->sc_regs[_R_S4];
+ uc.uc_mcontext.__gregs[_REG_S5] = sc->sc_regs[_R_S5];
+ uc.uc_mcontext.__gregs[_REG_S6] = sc->sc_regs[_R_S6];
+ uc.uc_mcontext.__gregs[_REG_S7] = sc->sc_regs[_R_S7];
+ uc.uc_mcontext.__gregs[_REG_S8] = sc->sc_regs[_R_S8];
+ uc.uc_mcontext.__gregs[_REG_SP] = sc->sc_regs[_R_SP];
+ uc.uc_mcontext.__gregs[_REG_RA] = sc->sc_regs[_R_RA];
+ uc.uc_mcontext.__gregs[_REG_EPC] = sc->sc_pc;
+
+ /* Copy FP state */
+ if (sc->sc_fpused) {
+ /* FP saved regs are $f20 .. $f31 */
+ memcpy(&uc.uc_mcontext.__fpregs.__fp_r.__fp_regs[20],
+ &sc->sc_fpregs[20], 32 - 20);
+ uc.uc_mcontext.__fpregs.__fp_csr =
+ sc->sc_fpregs[_R_FSR - _FPBASE];
+ /* XXX sc_fp_control */
+ uc.uc_flags |= _UC_FPU;
+ }
+
+ setcontext(&uc);
+ err:
+ longjmperror();
+ abort();
+ /* NOTREACHED */
+}
diff --git a/lib/libc/mips/gen/makecontext.c b/lib/libc/mips/gen/makecontext.c
new file mode 100644
index 0000000..f2a826e
--- /dev/null
+++ b/lib/libc/mips/gen/makecontext.c
@@ -0,0 +1,123 @@
+/* $NetBSD: makecontext.c,v 1.5 2009/12/14 01:07:42 matt Exp $ */
+
+/*-
+ * Copyright (c) 2001 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Klaus Klein.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: makecontext.c,v 1.5 2009/12/14 01:07:42 matt Exp $");
+#endif
+
+#include <sys/param.h>
+#include <machine/regnum.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ucontext.h>
+
+__weak_reference(__makecontext, makecontext);
+
+void _ctx_done(ucontext_t *);
+void _ctx_start(void);
+
+void
+__makecontext(ucontext_t *ucp, void (*func)(void), int argc, ...)
+{
+ mcontext_t *mc;
+ register_t *sp;
+ int i;
+ va_list ap;
+
+ /*
+ * XXX/juli
+ * We need an mc_len or mc_flags like other architectures
+ * so that we can mark a context as invalid. Store it in
+ * mc->mc_regs[ZERO] perhaps?
+ */
+ if (argc < 0 || argc > 6 || ucp == NULL ||
+ ucp->uc_stack.ss_sp == NULL ||
+ ucp->uc_stack.ss_size < MINSIGSTKSZ)
+ return;
+ mc = &ucp->uc_mcontext;
+
+ sp = (register_t *)
+ ((uintptr_t)ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size);
+#if defined(__mips_o32) || defined(__mips_o64)
+ sp -= (argc >= 4 ? argc : 4); /* Make room for >=4 arguments. */
+ sp = (register_t *)
+ ((uintptr_t)sp & ~0x7); /* Align on double-word boundary. */
+#elif defined(__mips_n32) || defined(__mips_n64)
+ sp -= (argc > 8 ? argc - 8 : 0); /* Make room for > 8 arguments. */
+ sp = (register_t *)
+ ((uintptr_t)sp & ~0xf); /* Align on quad-word boundary. */
+#endif
+
+ mc->mc_regs[SP] = (intptr_t)sp;
+ mc->mc_regs[S0] = (intptr_t)ucp;
+ mc->mc_regs[T9] = (intptr_t)func;
+ mc->mc_pc = (intptr_t)_ctx_start;
+
+ /* Construct argument list. */
+ va_start(ap, argc);
+#if defined(__mips_o32) || defined(__mips_o64)
+ /* Up to the first four arguments are passed in $a0-3. */
+ for (i = 0; i < argc && i < 4; i++)
+ /* LINTED register_t is safe */
+ mc->mc_regs[A0 + i] = va_arg(ap, register_t);
+ /* Pass remaining arguments on the stack above the $a0-3 gap. */
+ sp += i;
+#endif
+#if defined(__mips_n32) || defined(__mips_n64)
+ /* Up to the first 8 arguments are passed in $a0-7. */
+ for (i = 0; i < argc && i < 8; i++)
+ /* LINTED register_t is safe */
+ mc->mc_regs[A0 + i] = va_arg(ap, register_t);
+ /* Pass remaining arguments on the stack above the $a0-3 gap. */
+#endif
+ /* Pass remaining arguments on the stack above the $a0-3 gap. */
+ for (; i < argc; i++)
+ /* LINTED uintptr_t is safe */
+ *sp++ = va_arg(ap, register_t);
+ va_end(ap);
+}
+
+void
+_ctx_done(ucontext_t *ucp)
+{
+
+ if (ucp->uc_link == NULL)
+ exit(0);
+ else {
+ setcontext((const ucontext_t *)ucp->uc_link);
+ abort();
+ }
+}
diff --git a/lib/libc/mips/gen/setjmp.S b/lib/libc/mips/gen/setjmp.S
new file mode 100644
index 0000000..deeb892
--- /dev/null
+++ b/lib/libc/mips/gen/setjmp.S
@@ -0,0 +1,164 @@
+/* $NetBSD: setjmp.S,v 1.17 2005/09/17 11:49:39 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include <machine/regnum.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)setjmp.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: setjmp.S,v 1.17 2005/09/17 11:49:39 tsutsui Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+#include "SYS.h"
+
+#ifdef __ABICALLS__
+ .abicalls
+#endif
+
+/*
+ * C library -- setjmp, longjmp
+ *
+ * longjmp(a,v)
+ * will generate a "return(v)" from
+ * the last call to
+ * setjmp(a)
+ * by restoring registers from the stack,
+ * and a struct sigcontext, see <signal.h>
+ */
+
+#define SETJMP_FRAME_SIZE (CALLFRAME_SIZ + (SZREG * 2))
+
+
+NESTED(setjmp, SETJMP_FRAME_SIZE, ra)
+ .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
+ SETUP_GP
+ PTR_SUBU sp, sp, SETJMP_FRAME_SIZE # allocate stack frame
+ SAVE_GP(CALLFRAME_GP)
+ SETUP_GP64(CALLFRAME_GP, setjmp)
+
+ REG_S ra, CALLFRAME_RA(sp) # save RA
+ REG_S a0, CALLFRAME_SIZ(sp) # store env
+
+ /* Get the signal mask. */
+ PTR_ADDU a2, a0, _JB_SIGMASK * SZREG # &oenv
+ li a0, 1 # SIG_SETBLOCK
+ move a1, zero # &env == 0
+ PTR_LA t9, _C_LABEL(sigprocmask) # get current signal mask
+ jalr t9
+
+ RESTORE_GP64
+ REG_L a0, CALLFRAME_SIZ(sp) # restore env pointer
+ REG_L ra, CALLFRAME_RA(sp) # restore RA
+ PTR_ADDU sp, sp, SETJMP_FRAME_SIZE # pop stack frame
+
+ REG_LI v0, _JB_MAGIC_SETJMP
+ REG_S v0, (_JB_MAGIC * SZREG)(a0)
+ REG_S ra, (_JB_REG_RA * SZREG)(a0)
+ REG_S s0, (_JB_REG_S0 * SZREG)(a0)
+ REG_S s1, (_JB_REG_S1 * SZREG)(a0)
+ REG_S s2, (_JB_REG_S2 * SZREG)(a0)
+ REG_S s3, (_JB_REG_S3 * SZREG)(a0)
+ REG_S s4, (_JB_REG_S4 * SZREG)(a0)
+ REG_S s5, (_JB_REG_S5 * SZREG)(a0)
+ REG_S s6, (_JB_REG_S6 * SZREG)(a0)
+ REG_S s7, (_JB_REG_S7 * SZREG)(a0)
+ REG_S sp, (_JB_REG_SP * SZREG)(a0)
+ REG_S s8, (_JB_REG_S8 * SZREG)(a0)
+#if defined(__mips_n32) || defined(__mips_n64)
+ REG_S gp, (_JB_REG_GP * SZREG)(a0)
+#endif
+
+ move v0, zero
+ jr ra
+END(setjmp)
+
+#define LONGJMP_FRAME_SIZE (CALLFRAME_SIZ + (SZREG * 2))
+
+NESTED(longjmp, LONGJMP_FRAME_SIZE, ra)
+ .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
+ PIC_PROLOGUE(longjmp)
+ PTR_SUBU sp, sp, LONGJMP_FRAME_SIZE # allocate stack frame
+ SAVE_GP(CALLFRAME_GP)
+
+ REG_S ra, CALLFRAME_RA(sp) # save RA
+ REG_L v0, (_JB_MAGIC * SZREG)(a0)
+ REG_LI t0, _JB_MAGIC_SETJMP
+ bne v0, t0, botch # jump if error
+ nop
+
+ REG_S a0, CALLFRAME_SIZ(sp) # save env
+ REG_S a1, (CALLFRAME_SIZ + SZREG)(sp) # save return value
+
+ # set sigmask
+ PTR_ADDU a1, a0, _JB_SIGMASK * SZREG # &set
+ move a2, zero # &oset == NULL
+ li a0, 3 # SIG_SETMASK
+ PTR_LA t9,_C_LABEL(sigprocmask) # set current signal mask
+ jal t9
+ nop
+
+ REG_L a0, CALLFRAME_SIZ(sp) # restore env
+ REG_L a1, (CALLFRAME_SIZ + SZREG)(sp) # restore return value
+
+ REG_L ra, (_JB_REG_RA * SZREG)(a0)
+ REG_L s0, (_JB_REG_S0 * SZREG)(a0)
+ REG_L s1, (_JB_REG_S1 * SZREG)(a0)
+ REG_L s2, (_JB_REG_S2 * SZREG)(a0)
+ REG_L s3, (_JB_REG_S3 * SZREG)(a0)
+ REG_L s4, (_JB_REG_S4 * SZREG)(a0)
+ REG_L s5, (_JB_REG_S5 * SZREG)(a0)
+ REG_L s6, (_JB_REG_S6 * SZREG)(a0)
+ REG_L s7, (_JB_REG_S7 * SZREG)(a0)
+ REG_L sp, (_JB_REG_SP * SZREG)(a0)
+ REG_L s8, (_JB_REG_S8 * SZREG)(a0)
+#if defined(__mips_n32) || defined(__mips_n64)
+ REG_L gp, (_JB_REG_GP * SZREG)(a0)
+#endif
+
+ move v0, a1
+ j ra
+ nop
+
+botch:
+ /*
+ * We know we aren't returning so we don't care about restoring
+ * our caller's GP.
+ */
+ PTR_LA t9, _C_LABEL(longjmperror)
+ jalr t9
+ nop
+
+ PIC_TAILCALL(abort)
+END(longjmp)
diff --git a/lib/libc/mips/gen/signalcontext.c b/lib/libc/mips/gen/signalcontext.c
new file mode 100644
index 0000000..694468c
--- /dev/null
+++ b/lib/libc/mips/gen/signalcontext.c
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2004 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/signal.h>
+#include <sys/ucontext.h>
+
+#include <machine/frame.h>
+#include <machine/sigframe.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <strings.h>
+#include <signal.h>
+
+__weak_reference(__signalcontext, signalcontext);
+
+extern void _ctx_start(void);
+
+int
+__signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func)
+{
+ /* XXXMIPS: Implement me */
+ return (0);
+}
diff --git a/lib/libc/mips/gen/sigsetjmp.S b/lib/libc/mips/gen/sigsetjmp.S
new file mode 100644
index 0000000..7705c29
--- /dev/null
+++ b/lib/libc/mips/gen/sigsetjmp.S
@@ -0,0 +1,77 @@
+/* $NetBSD: sigsetjmp.S,v 1.8 2005/09/17 11:49:39 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993, 1995,
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Havard Eidnes.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include <machine/regnum.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)setjmp.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: sigsetjmp.S,v 1.8 2005/09/17 11:49:39 tsutsui Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+#include "SYS.h"
+
+#ifdef __ABICALLS__
+ .abicalls
+#endif
+
+/*
+ * C library -- sigsetjmp, siglongjmp
+ *
+ * siglongjmp(a,v)
+ * will generate a "return(v)" from
+ * the last call to
+ * sigsetjmp(a, savemask)
+ * by restoring registers from the stack,
+ * and dependent on savemask restores the
+ * signal mask.
+ */
+
+LEAF(sigsetjmp)
+ PIC_PROLOGUE(sigsetjmp)
+
+ bne a1, 0x0, 1f # do saving of signal mask?
+ PIC_TAILCALL(_setjmp)
+
+1: PIC_TAILCALL(setjmp)
+END(sigsetjmp)
+
+LEAF(siglongjmp)
+ PIC_PROLOGUE(siglongjmp)
+ REG_L t0, (_JB_MAGIC * SZREG)(a0)
+ REG_LI t1, _JB_MAGIC__SETJMP
+ bne t0, t1, 1f # setjmp or _setjmp magic?
+ PIC_TAILCALL(_longjmp)
+1: PIC_TAILCALL(longjmp)
+END(siglongjmp)
diff --git a/lib/libc/mips/net/Makefile.inc b/lib/libc/mips/net/Makefile.inc
new file mode 100644
index 0000000..304d5ca
--- /dev/null
+++ b/lib/libc/mips/net/Makefile.inc
@@ -0,0 +1,4 @@
+# $NetBSD: Makefile.inc,v 1.3 2003/08/01 17:03:51 lukem Exp $
+# $FreeBSD$
+
+SRCS+= htonl.S ntohl.S htons.S ntohs.S
diff --git a/lib/libc/mips/net/htonl.S b/lib/libc/mips/net/htonl.S
new file mode 100644
index 0000000..8588920
--- /dev/null
+++ b/lib/libc/mips/net/htonl.S
@@ -0,0 +1,58 @@
+/* $NetBSD: byte_swap_4.S,v 1.2 2006/02/08 21:52:36 simonb Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD$");
+
+LEAF(htonl) # a0 = 0x11223344, return 0x44332211
+#ifdef __MIPSEB__
+ move v0, a0
+#else
+ srl v1, a0, 24 # v1 = 0x00000011
+ sll v0, a0, 24 # v0 = 0x44000000
+ or v0, v0, v1
+ and v1, a0, 0xff00
+ sll v1, v1, 8 # v1 = 0x00330000
+ or v0, v0, v1
+ srl v1, a0, 8
+ and v1, v1, 0xff00 # v1 = 0x00002200
+ or v0, v0, v1
+#endif
+ j ra
+END(htonl)
diff --git a/lib/libc/mips/net/htons.S b/lib/libc/mips/net/htons.S
new file mode 100644
index 0000000..592c44e
--- /dev/null
+++ b/lib/libc/mips/net/htons.S
@@ -0,0 +1,54 @@
+/* $NetBSD: byte_swap_2.S,v 1.2 2006/02/08 21:52:36 simonb Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD$");
+
+LEAF(htons)
+#ifdef __MIPSEB__
+ move v0, a0
+#else
+ srl v0, a0, 8
+ and v0, v0, 0xff
+ sll v1, a0, 8
+ and v1, v1, 0xff00
+ or v0, v0, v1
+#endif
+ j ra
+END(htons)
diff --git a/lib/libc/mips/net/ntohl.S b/lib/libc/mips/net/ntohl.S
new file mode 100644
index 0000000..bacda3e
--- /dev/null
+++ b/lib/libc/mips/net/ntohl.S
@@ -0,0 +1,58 @@
+/* $NetBSD: byte_swap_4.S,v 1.2 2006/02/08 21:52:36 simonb Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+__FBSDID("$FreeBSD$");
+
+LEAF(ntohl) # a0 = 0x11223344, return 0x44332211
+#ifdef __MIPSEB__
+ move v0, a0
+#else
+ srl v1, a0, 24 # v1 = 0x00000011
+ sll v0, a0, 24 # v0 = 0x44000000
+ or v0, v0, v1
+ and v1, a0, 0xff00
+ sll v1, v1, 8 # v1 = 0x00330000
+ or v0, v0, v1
+ srl v1, a0, 8
+ and v1, v1, 0xff00 # v1 = 0x00002200
+ or v0, v0, v1
+#endif
+ j ra
+END(ntohl)
diff --git a/lib/libc/mips/net/ntohs.S b/lib/libc/mips/net/ntohs.S
new file mode 100644
index 0000000..28aac3d
--- /dev/null
+++ b/lib/libc/mips/net/ntohs.S
@@ -0,0 +1,53 @@
+/* $NetBSD: byte_swap_2.S,v 1.2 2006/02/08 21:52:36 simonb Exp $ */
+
+/*-
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Charles M. Hannum.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+LEAF(ntohs)
+#ifdef __MIPSEB__
+ move v0, a0
+#else
+ srl v0, a0, 8
+ and v0, v0, 0xff
+ sll v1, a0, 8
+ and v1, v1, 0xff00
+ or v0, v0, v1
+#endif
+ j ra
+END(ntohs)
diff --git a/lib/libc/mips/softfloat/milieu.h b/lib/libc/mips/softfloat/milieu.h
new file mode 100644
index 0000000..e04b266
--- /dev/null
+++ b/lib/libc/mips/softfloat/milieu.h
@@ -0,0 +1,48 @@
+/* $FreeBSD$ */
+
+/*
+===============================================================================
+
+This C header file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+Include common integer types and flags.
+-------------------------------------------------------------------------------
+*/
+#include "mips-gcc.h"
+
+/*
+-------------------------------------------------------------------------------
+Symbolic Boolean literals.
+-------------------------------------------------------------------------------
+*/
+enum {
+ FALSE = 0,
+ TRUE = 1
+};
diff --git a/lib/libc/mips/softfloat/mips-gcc.h b/lib/libc/mips/softfloat/mips-gcc.h
new file mode 100644
index 0000000..c8ec07c
--- /dev/null
+++ b/lib/libc/mips/softfloat/mips-gcc.h
@@ -0,0 +1,91 @@
+/* $NetBSD: arm-gcc.h,v 1.2 2001/02/21 18:09:25 bjh21 Exp $ */
+/* $FreeBSD$ */
+
+/*
+-------------------------------------------------------------------------------
+One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined.
+-------------------------------------------------------------------------------
+*/
+#ifdef __MIPSEB__
+#define BIGENDIAN
+#else
+#define LITTLEENDIAN
+#endif
+
+/*
+-------------------------------------------------------------------------------
+The macro `BITS64' can be defined to indicate that 64-bit integer types are
+supported by the compiler.
+-------------------------------------------------------------------------------
+*/
+#define BITS64
+
+/*
+-------------------------------------------------------------------------------
+Each of the following `typedef's defines the most convenient type that holds
+integers of at least as many bits as specified. For example, `uint8' should
+be the most convenient type that can hold unsigned integers of as many as
+8 bits. The `flag' type must be able to hold either a 0 or 1. For most
+implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
+to the same as `int'.
+-------------------------------------------------------------------------------
+*/
+typedef int flag;
+typedef int uint8;
+typedef int int8;
+typedef int uint16;
+typedef int int16;
+typedef unsigned int uint32;
+typedef signed int int32;
+#ifdef BITS64
+typedef unsigned long long int uint64;
+typedef signed long long int int64;
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Each of the following `typedef's defines a type that holds integers
+of _exactly_ the number of bits specified. For instance, for most
+implementation of C, `bits16' and `sbits16' should be `typedef'ed to
+`unsigned short int' and `signed short int' (or `short int'), respectively.
+-------------------------------------------------------------------------------
+*/
+typedef unsigned char bits8;
+typedef signed char sbits8;
+typedef unsigned short int bits16;
+typedef signed short int sbits16;
+typedef unsigned int bits32;
+typedef signed int sbits32;
+#ifdef BITS64
+typedef unsigned long long int bits64;
+typedef signed long long int sbits64;
+#endif
+
+#ifdef BITS64
+/*
+-------------------------------------------------------------------------------
+The `LIT64' macro takes as its argument a textual integer literal and
+if necessary ``marks'' the literal as having a 64-bit integer type.
+For example, the GNU C Compiler (`gcc') requires that 64-bit literals be
+appended with the letters `LL' standing for `long long', which is `gcc's
+name for the 64-bit integer type. Some compilers may allow `LIT64' to be
+defined as the identity macro: `#define LIT64( a ) a'.
+-------------------------------------------------------------------------------
+*/
+#define LIT64( a ) a##LL
+#endif
+
+/*
+-------------------------------------------------------------------------------
+The macro `INLINE' can be used before functions that should be inlined. If
+a compiler does not support explicit inlining, this macro should be defined
+to be `static'.
+-------------------------------------------------------------------------------
+*/
+#define INLINE static __inline
+
+#if defined(SOFTFLOAT_FOR_GCC)
+/* XXXMIPS: check this one */
+#define FLOAT64_DEMANGLE(a) (a)
+#define FLOAT64_MANGLE(a) (a)
+#endif
diff --git a/lib/libc/mips/softfloat/softfloat.h b/lib/libc/mips/softfloat/softfloat.h
new file mode 100644
index 0000000..6aef499
--- /dev/null
+++ b/lib/libc/mips/softfloat/softfloat.h
@@ -0,0 +1,315 @@
+/* $NetBSD: softfloat.h,v 1.6 2002/05/12 13:12:46 bjh21 Exp $ */
+/* $FreeBSD$ */
+
+/* This is a derivative work. */
+
+/*
+===============================================================================
+
+This C header file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+The macro `FLOATX80' must be defined to enable the extended double-precision
+floating-point format `floatx80'. If this macro is not defined, the
+`floatx80' type will not be defined, and none of the functions that either
+input or output the `floatx80' type will be defined. The same applies to
+the `FLOAT128' macro and the quadruple-precision format `float128'.
+-------------------------------------------------------------------------------
+*/
+/* #define FLOATX80 */
+/* #define FLOAT128 */
+
+#include <fenv.h>
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point types.
+-------------------------------------------------------------------------------
+*/
+typedef unsigned int float32;
+typedef unsigned long long float64;
+#ifdef FLOATX80
+typedef struct {
+ unsigned short high;
+ unsigned long long low;
+} floatx80;
+#endif
+#ifdef FLOAT128
+typedef struct {
+ unsigned long long high, low;
+} float128;
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point underflow tininess-detection mode.
+-------------------------------------------------------------------------------
+*/
+#ifndef SOFTFLOAT_FOR_GCC
+extern int float_detect_tininess;
+#endif
+enum {
+ float_tininess_after_rounding = 0,
+ float_tininess_before_rounding = 1
+};
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point rounding mode.
+-------------------------------------------------------------------------------
+*/
+extern int float_rounding_mode;
+enum {
+ float_round_nearest_even = FE_TONEAREST,
+ float_round_to_zero = FE_TOWARDZERO,
+ float_round_down = FE_DOWNWARD,
+ float_round_up = FE_UPWARD
+};
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point exception flags.
+-------------------------------------------------------------------------------
+*/
+extern int float_exception_flags;
+extern int float_exception_mask;
+enum {
+ float_flag_inexact = FE_INEXACT,
+ float_flag_underflow = FE_UNDERFLOW,
+ float_flag_overflow = FE_OVERFLOW,
+ float_flag_divbyzero = FE_DIVBYZERO,
+ float_flag_invalid = FE_INVALID
+};
+
+/*
+-------------------------------------------------------------------------------
+Routine to raise any or all of the software IEC/IEEE floating-point
+exception flags.
+-------------------------------------------------------------------------------
+*/
+void float_raise( int );
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE integer-to-floating-point conversion routines.
+-------------------------------------------------------------------------------
+*/
+float32 int32_to_float32( int );
+float64 int32_to_float64( int );
+#ifdef FLOATX80
+floatx80 int32_to_floatx80( int );
+#endif
+#ifdef FLOAT128
+float128 int32_to_float128( int );
+#endif
+#ifndef SOFTFLOAT_FOR_GCC /* __floatdi?f is in libgcc2.c */
+float32 int64_to_float32( long long );
+float64 int64_to_float64( long long );
+#ifdef FLOATX80
+floatx80 int64_to_floatx80( long long );
+#endif
+#ifdef FLOAT128
+float128 int64_to_float128( long long );
+#endif
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE single-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float32_to_int32( float32 );
+int float32_to_int32_round_to_zero( float32 );
+#if defined(SOFTFLOAT_FOR_GCC) && defined(SOFTFLOAT_NEED_FIXUNS)
+unsigned int float32_to_uint32_round_to_zero( float32 );
+#endif
+#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */
+long long float32_to_int64( float32 );
+long long float32_to_int64_round_to_zero( float32 );
+#endif
+float64 float32_to_float64( float32 );
+#ifdef FLOATX80
+floatx80 float32_to_floatx80( float32 );
+#endif
+#ifdef FLOAT128
+float128 float32_to_float128( float32 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE single-precision operations.
+-------------------------------------------------------------------------------
+*/
+float32 float32_round_to_int( float32 );
+float32 float32_add( float32, float32 );
+float32 float32_sub( float32, float32 );
+float32 float32_mul( float32, float32 );
+float32 float32_div( float32, float32 );
+float32 float32_rem( float32, float32 );
+float32 float32_sqrt( float32 );
+int float32_eq( float32, float32 );
+int float32_le( float32, float32 );
+int float32_lt( float32, float32 );
+int float32_eq_signaling( float32, float32 );
+int float32_le_quiet( float32, float32 );
+int float32_lt_quiet( float32, float32 );
+#ifndef SOFTFLOAT_FOR_GCC
+int float32_is_signaling_nan( float32 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE double-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float64_to_int32( float64 );
+int float64_to_int32_round_to_zero( float64 );
+#if defined(SOFTFLOAT_FOR_GCC) && defined(SOFTFLOAT_NEED_FIXUNS)
+unsigned int float64_to_uint32_round_to_zero( float64 );
+#endif
+#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */
+long long float64_to_int64( float64 );
+long long float64_to_int64_round_to_zero( float64 );
+#endif
+float32 float64_to_float32( float64 );
+#ifdef FLOATX80
+floatx80 float64_to_floatx80( float64 );
+#endif
+#ifdef FLOAT128
+float128 float64_to_float128( float64 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE double-precision operations.
+-------------------------------------------------------------------------------
+*/
+float64 float64_round_to_int( float64 );
+float64 float64_add( float64, float64 );
+float64 float64_sub( float64, float64 );
+float64 float64_mul( float64, float64 );
+float64 float64_div( float64, float64 );
+float64 float64_rem( float64, float64 );
+float64 float64_sqrt( float64 );
+int float64_eq( float64, float64 );
+int float64_le( float64, float64 );
+int float64_lt( float64, float64 );
+int float64_eq_signaling( float64, float64 );
+int float64_le_quiet( float64, float64 );
+int float64_lt_quiet( float64, float64 );
+#ifndef SOFTFLOAT_FOR_GCC
+int float64_is_signaling_nan( float64 );
+#endif
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int floatx80_to_int32( floatx80 );
+int floatx80_to_int32_round_to_zero( floatx80 );
+long long floatx80_to_int64( floatx80 );
+long long floatx80_to_int64_round_to_zero( floatx80 );
+float32 floatx80_to_float32( floatx80 );
+float64 floatx80_to_float64( floatx80 );
+#ifdef FLOAT128
+float128 floatx80_to_float128( floatx80 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision rounding precision. Valid
+values are 32, 64, and 80.
+-------------------------------------------------------------------------------
+*/
+extern int floatx80_rounding_precision;
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision operations.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_round_to_int( floatx80 );
+floatx80 floatx80_add( floatx80, floatx80 );
+floatx80 floatx80_sub( floatx80, floatx80 );
+floatx80 floatx80_mul( floatx80, floatx80 );
+floatx80 floatx80_div( floatx80, floatx80 );
+floatx80 floatx80_rem( floatx80, floatx80 );
+floatx80 floatx80_sqrt( floatx80 );
+int floatx80_eq( floatx80, floatx80 );
+int floatx80_le( floatx80, floatx80 );
+int floatx80_lt( floatx80, floatx80 );
+int floatx80_eq_signaling( floatx80, floatx80 );
+int floatx80_le_quiet( floatx80, floatx80 );
+int floatx80_lt_quiet( floatx80, floatx80 );
+int floatx80_is_signaling_nan( floatx80 );
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE quadruple-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float128_to_int32( float128 );
+int float128_to_int32_round_to_zero( float128 );
+long long float128_to_int64( float128 );
+long long float128_to_int64_round_to_zero( float128 );
+float32 float128_to_float32( float128 );
+float64 float128_to_float64( float128 );
+#ifdef FLOATX80
+floatx80 float128_to_floatx80( float128 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE quadruple-precision operations.
+-------------------------------------------------------------------------------
+*/
+float128 float128_round_to_int( float128 );
+float128 float128_add( float128, float128 );
+float128 float128_sub( float128, float128 );
+float128 float128_mul( float128, float128 );
+float128 float128_div( float128, float128 );
+float128 float128_rem( float128, float128 );
+float128 float128_sqrt( float128 );
+int float128_eq( float128, float128 );
+int float128_le( float128, float128 );
+int float128_lt( float128, float128 );
+int float128_eq_signaling( float128, float128 );
+int float128_le_quiet( float128, float128 );
+int float128_lt_quiet( float128, float128 );
+int float128_is_signaling_nan( float128 );
+
+#endif
+
diff --git a/lib/libc/mips/string/Makefile.inc b/lib/libc/mips/string/Makefile.inc
new file mode 100644
index 0000000..f37b9af
--- /dev/null
+++ b/lib/libc/mips/string/Makefile.inc
@@ -0,0 +1,8 @@
+# $NetBSD: Makefile.inc,v 1.2 2000/10/10 21:51:54 jeffs Exp $
+# $FreeBSD$
+
+SRCS+= bcmp.S bcopy.S bzero.S ffs.S memchr.c memcmp.c memset.c \
+ memcpy.S memmove.S \
+ strcat.c strchr.S strcmp.S strcpy.c strcspn.c strlen.S \
+ strncat.c strncmp.c strncpy.c strrchr.S strpbrk.c strsep.c \
+ strspn.c strstr.c swab.c
diff --git a/lib/libc/mips/string/bcmp.S b/lib/libc/mips/string/bcmp.S
new file mode 100644
index 0000000..ffcaeeb
--- /dev/null
+++ b/lib/libc/mips/string/bcmp.S
@@ -0,0 +1,130 @@
+/* $NetBSD: bcmp.S,v 1.9 2009/12/14 01:07:42 matt Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#define _LOCORE /* XXX not really, just assembly-code source */
+#include <machine/endian.h> /* LWLO/LWHI, SWLO/SWHI */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+ ASMSTR("from: @(#)bcmp.s 8.1 (Berkeley) 6/4/93")
+#else
+ ASMSTR("$NetBSD: bcmp.S,v 1.9 2009/12/14 01:07:42 matt Exp $")
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef __ABICALLS__
+ .abicalls
+#endif
+
+/* bcmp(s1, s2, n) */
+
+
+LEAF(bcmp)
+ .set noreorder
+ blt a2, 16, small # is it worth any trouble?
+ xor v0, a0, a1 # compare low two bits of addresses
+ and v0, v0, 3
+ PTR_SUBU a3, zero, a1 # compute # bytes to word align address
+ bne v0, zero, unaligned # not possible to align addresses
+ and a3, a3, 3
+
+ beq a3, zero, 1f
+ PTR_SUBU a2, a2, a3 # subtract from remaining count
+ move v0, v1 # init v0,v1 so unmodified bytes match
+ LWHI v0, 0(a0) # read 1, 2, or 3 bytes
+ LWHI v1, 0(a1)
+ PTR_ADDU a1, a1, a3
+ bne v0, v1, nomatch
+ PTR_ADDU a0, a0, a3
+1:
+ and a3, a2, ~3 # compute number of whole words left
+ PTR_SUBU a2, a2, a3 # which has to be >= (16-3) & ~3
+ PTR_ADDU a3, a3, a0 # compute ending address
+2:
+ lw v0, 0(a0) # compare words
+ lw v1, 0(a1)
+ PTR_ADDU a0, a0, 4
+ bne v0, v1, nomatch
+ PTR_ADDU a1, a1, 4
+ bne a0, a3, 2b
+ nop
+ b small # finish remainder
+ nop
+unaligned:
+ beq a3, zero, 2f
+ PTR_SUBU a2, a2, a3 # subtract from remaining count
+ PTR_ADDU a3, a3, a0 # compute ending address
+1:
+ lbu v0, 0(a0) # compare bytes until a1 word aligned
+ lbu v1, 0(a1)
+ PTR_ADDU a0, a0, 1
+ bne v0, v1, nomatch
+ PTR_ADDU a1, a1, 1
+ bne a0, a3, 1b
+ nop
+2:
+ and a3, a2, ~3 # compute number of whole words left
+ PTR_SUBU a2, a2, a3 # which has to be >= (16-3) & ~3
+ PTR_ADDU a3, a3, a0 # compute ending address
+3:
+ LWHI v0, 0(a0) # compare words a0 unaligned, a1 aligned
+ LWLO v0, 3(a0)
+ lw v1, 0(a1)
+ PTR_ADDU a0, a0, 4
+ bne v0, v1, nomatch
+ PTR_ADDU a1, a1, 4
+ bne a0, a3, 3b
+ nop
+small:
+ ble a2, zero, match
+ PTR_ADDU a3, a2, a0 # compute ending address
+1:
+ lbu v0, 0(a0)
+ lbu v1, 0(a1)
+ PTR_ADDU a0, a0, 1
+ bne v0, v1, nomatch
+ PTR_ADDU a1, a1, 1
+ bne a0, a3, 1b
+ nop
+match:
+ j ra
+ move v0, zero
+nomatch:
+ j ra
+ li v0, 1
+ .set reorder
+END(bcmp)
diff --git a/lib/libc/mips/string/bcopy.S b/lib/libc/mips/string/bcopy.S
new file mode 100644
index 0000000..bc227e0
--- /dev/null
+++ b/lib/libc/mips/string/bcopy.S
@@ -0,0 +1,297 @@
+/* $NetBSD: bcopy.S,v 1.3 2009/12/14 00:39:00 matt Exp $ */
+
+/*
+ * Mach Operating System
+ * Copyright (c) 1993 Carnegie Mellon University
+ * All Rights Reserved.
+ *
+ * Permission to use, copy, modify and distribute this software and its
+ * documentation is hereby granted, provided that both the copyright
+ * notice and this permission notice appear in all copies of the
+ * software, derivative works or modified versions, and any portions
+ * thereof, and that both notices appear in supporting documentation.
+ *
+ * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
+ * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
+ * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
+ *
+ * Carnegie Mellon requests users of this software to return to
+ *
+ * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU
+ * School of Computer Science
+ * Carnegie Mellon University
+ * Pittsburgh PA 15213-3890
+ *
+ * any improvements or extensions that they make and grant Carnegie Mellon
+ * the rights to redistribute these changes.
+ */
+
+/*
+ * File: mips_bcopy.s
+ * Author: Chris Maeda
+ * Date: June 1993
+ *
+ * Fast copy routine. Derived from aligned_block_copy.
+ */
+
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#define _LOCORE /* XXX not really, just assembly-code source */
+#include <machine/endian.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+ ASMSTR("from: @(#)mips_bcopy.s 2.2 CMU 18/06/93")
+#else
+ ASMSTR("$NetBSD: bcopy.S,v 1.3 2009/12/14 00:39:00 matt Exp $")
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef __ABICALLS__
+ .abicalls
+#endif
+
+/*
+ * bcopy(caddr_t src, caddr_t dst, unsigned int len)
+ *
+ * a0 src address
+ * a1 dst address
+ * a2 length
+ */
+
+#if defined(MEMCOPY) || defined(MEMMOVE)
+#ifdef MEMCOPY
+#define FUNCTION memcpy
+#else
+#define FUNCTION memmove
+#endif
+#define SRCREG a1
+#define DSTREG a0
+#else
+#define FUNCTION bcopy
+#define SRCREG a0
+#define DSTREG a1
+#endif
+
+#define SIZEREG a2
+
+LEAF(FUNCTION)
+ .set noat
+ .set noreorder
+
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ /* set up return value, while we still can */
+ move v0,DSTREG
+#endif
+ /*
+ * Make sure we can copy forwards.
+ */
+ sltu t0,SRCREG,DSTREG # t0 == SRCREG < DSTREG
+ bne t0,zero,6f # copy backwards
+
+ /*
+ * There are four alignment cases (with frequency)
+ * (Based on measurements taken with a DECstation 5000/200
+ * inside a Mach kernel.)
+ *
+ * aligned -> aligned (mostly)
+ * unaligned -> aligned (sometimes)
+ * aligned,unaligned -> unaligned (almost never)
+ *
+ * Note that we could add another case that checks if
+ * the destination and source are unaligned but the
+ * copy is alignable. eg if src and dest are both
+ * on a halfword boundary.
+ */
+ andi t1,DSTREG,(SZREG-1) # get last bits of dest
+ bne t1,zero,3f # dest unaligned
+ andi t0,SRCREG,(SZREG-1) # get last bits of src
+ bne t0,zero,5f
+
+ /*
+ * Forward aligned->aligned copy, 8 words at a time.
+ */
+98:
+ li AT,-(SZREG*8)
+ and t0,SIZEREG,AT # count truncated to multiples
+ PTR_ADDU a3,SRCREG,t0 # run fast loop up to this addr
+ sltu AT,SRCREG,a3 # any work to do?
+ beq AT,zero,2f
+ PTR_SUBU SIZEREG,t0
+
+ /*
+ * loop body
+ */
+1: # cp
+ REG_L t3,(0*SZREG)(SRCREG)
+ REG_L v1,(1*SZREG)(SRCREG)
+ REG_L t0,(2*SZREG)(SRCREG)
+ REG_L t1,(3*SZREG)(SRCREG)
+ PTR_ADDU SRCREG,SZREG*8
+ REG_S t3,(0*SZREG)(DSTREG)
+ REG_S v1,(1*SZREG)(DSTREG)
+ REG_S t0,(2*SZREG)(DSTREG)
+ REG_S t1,(3*SZREG)(DSTREG)
+ REG_L t1,(-1*SZREG)(SRCREG)
+ REG_L t0,(-2*SZREG)(SRCREG)
+ REG_L v1,(-3*SZREG)(SRCREG)
+ REG_L t3,(-4*SZREG)(SRCREG)
+ PTR_ADDU DSTREG,SZREG*8
+ REG_S t1,(-1*SZREG)(DSTREG)
+ REG_S t0,(-2*SZREG)(DSTREG)
+ REG_S v1,(-3*SZREG)(DSTREG)
+ bne SRCREG,a3,1b
+ REG_S t3,(-4*SZREG)(DSTREG)
+
+ /*
+ * Copy a word at a time, no loop unrolling.
+ */
+2: # wordcopy
+ andi t2,SIZEREG,(SZREG-1) # get byte count / SZREG
+ PTR_SUBU t2,SIZEREG,t2 # t2 = words to copy * SZREG
+ beq t2,zero,3f
+ PTR_ADDU t0,SRCREG,t2 # stop at t0
+ PTR_SUBU SIZEREG,SIZEREG,t2
+1:
+ REG_L t3,0(SRCREG)
+ PTR_ADDU SRCREG,SZREG
+ REG_S t3,0(DSTREG)
+ bne SRCREG,t0,1b
+ PTR_ADDU DSTREG,SZREG
+
+3: # bytecopy
+ beq SIZEREG,zero,4f # nothing left to do?
+ nop
+1:
+ lb t3,0(SRCREG)
+ PTR_ADDU SRCREG,1
+ sb t3,0(DSTREG)
+ PTR_SUBU SIZEREG,1
+ bgtz SIZEREG,1b
+ PTR_ADDU DSTREG,1
+
+4: # copydone
+ j ra
+ nop
+
+ /*
+ * Copy from unaligned source to aligned dest.
+ */
+5: # destaligned
+ andi t0,SIZEREG,(SZREG-1) # t0 = bytecount mod SZREG
+ PTR_SUBU a3,SIZEREG,t0 # number of words to transfer
+ beq a3,zero,3b
+ nop
+ move SIZEREG,t0 # this many to do after we are done
+ PTR_ADDU a3,SRCREG,a3 # stop point
+
+1:
+ REG_LHI t3,0(SRCREG)
+ REG_LLO t3,SZREG-1(SRCREG)
+ PTR_ADDI SRCREG,SZREG
+ REG_S t3,0(DSTREG)
+ bne SRCREG,a3,1b
+ PTR_ADDI DSTREG,SZREG
+
+ b 3b
+ nop
+
+6: # backcopy -- based on above
+ PTR_ADDU SRCREG,SIZEREG
+ PTR_ADDU DSTREG,SIZEREG
+ andi t1,DSTREG,SZREG-1 # get last 3 bits of dest
+ bne t1,zero,3f
+ andi t0,SRCREG,SZREG-1 # get last 3 bits of src
+ bne t0,zero,5f
+
+ /*
+ * Forward aligned->aligned copy, 8*4 bytes at a time.
+ */
+ li AT,(-8*SZREG)
+ and t0,SIZEREG,AT # count truncated to multiple of 32
+ beq t0,zero,2f # any work to do?
+ PTR_SUBU SIZEREG,t0
+ PTR_SUBU a3,SRCREG,t0
+
+ /*
+ * loop body
+ */
+1: # cp
+ REG_L t3,(-4*SZREG)(SRCREG)
+ REG_L v1,(-3*SZREG)(SRCREG)
+ REG_L t0,(-2*SZREG)(SRCREG)
+ REG_L t1,(-1*SZREG)(SRCREG)
+ PTR_SUBU SRCREG,8*SZREG
+ REG_S t3,(-4*SZREG)(DSTREG)
+ REG_S v1,(-3*SZREG)(DSTREG)
+ REG_S t0,(-2*SZREG)(DSTREG)
+ REG_S t1,(-1*SZREG)(DSTREG)
+ REG_L t1,(3*SZREG)(SRCREG)
+ REG_L t0,(2*SZREG)(SRCREG)
+ REG_L v1,(1*SZREG)(SRCREG)
+ REG_L t3,(0*SZREG)(SRCREG)
+ PTR_SUBU DSTREG,8*SZREG
+ REG_S t1,(3*SZREG)(DSTREG)
+ REG_S t0,(2*SZREG)(DSTREG)
+ REG_S v1,(1*SZREG)(DSTREG)
+ bne SRCREG,a3,1b
+ REG_S t3,(0*SZREG)(DSTREG)
+
+ /*
+ * Copy a word at a time, no loop unrolling.
+ */
+2: # wordcopy
+ andi t2,SIZEREG,SZREG-1 # get byte count / 4
+ PTR_SUBU t2,SIZEREG,t2 # t2 = number of words to copy
+ beq t2,zero,3f
+ PTR_SUBU t0,SRCREG,t2 # stop at t0
+ PTR_SUBU SIZEREG,SIZEREG,t2
+1:
+ REG_L t3,-SZREG(SRCREG)
+ PTR_SUBU SRCREG,SZREG
+ REG_S t3,-SZREG(DSTREG)
+ bne SRCREG,t0,1b
+ PTR_SUBU DSTREG,SZREG
+
+3: # bytecopy
+ beq SIZEREG,zero,4f # nothing left to do?
+ nop
+1:
+ lb t3,-1(SRCREG)
+ PTR_SUBU SRCREG,1
+ sb t3,-1(DSTREG)
+ PTR_SUBU SIZEREG,1
+ bgtz SIZEREG,1b
+ PTR_SUBU DSTREG,1
+
+4: # copydone
+ j ra
+ nop
+
+ /*
+ * Copy from unaligned source to aligned dest.
+ */
+5: # destaligned
+ andi t0,SIZEREG,SZREG-1 # t0 = bytecount mod 4
+ PTR_SUBU a3,SIZEREG,t0 # number of words to transfer
+ beq a3,zero,3b
+ nop
+ move SIZEREG,t0 # this many to do after we are done
+ PTR_SUBU a3,SRCREG,a3 # stop point
+
+1:
+ REG_LHI t3,-SZREG(SRCREG)
+ REG_LLO t3,-1(SRCREG)
+ PTR_SUBU SRCREG,SZREG
+ REG_S t3,-SZREG(DSTREG)
+ bne SRCREG,a3,1b
+ PTR_SUBU DSTREG,SZREG
+
+ b 3b
+ nop
+
+ .set reorder
+ .set at
+ END(FUNCTION)
diff --git a/lib/libc/mips/string/bzero.S b/lib/libc/mips/string/bzero.S
new file mode 100644
index 0000000..83e54ba
--- /dev/null
+++ b/lib/libc/mips/string/bzero.S
@@ -0,0 +1,83 @@
+/* $NetBSD: bzero.S,v 1.10 2009/12/14 02:53:52 matt Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+ ASMSTR("from: @(#)bzero.s 8.1 (Berkeley) 6/4/93")
+#else
+ ASMSTR("$NetBSD: bzero.S,v 1.10 2009/12/14 02:53:52 matt Exp $")
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#define _LOCORE /* XXX not really, just assembly-code source */
+#include <machine/endian.h>
+
+#ifdef __ABICALLS__
+ .abicalls
+#endif
+
+/* bzero(s1, n) */
+
+LEAF(bzero)
+ .set noreorder
+ blt a1, 3*SZREG, smallclr # small amount to clear?
+ PTR_SUBU a3, zero, a0 # compute # bytes to word align address
+ and a3, a3, SZREG-1
+ beq a3, zero, 1f # skip if word aligned
+ PTR_SUBU a1, a1, a3 # subtract from remaining count
+ REG_SHI zero, 0(a0) # clear 1, 2, or 3 bytes to align
+ PTR_ADDU a0, a0, a3
+1:
+ and v0, a1, SZREG-1 # compute number of words left
+ PTR_SUBU a3, a1, v0
+ move a1, v0
+ PTR_ADDU a3, a3, a0 # compute ending address
+2:
+ PTR_ADDU a0, a0, SZREG # clear words
+ bne a0, a3, 2b # unrolling loop doesnt help
+ REG_S zero, -SZREG(a0) # since we are limited by memory speed
+smallclr:
+ ble a1, zero, 2f
+ PTR_ADDU a3, a1, a0 # compute ending address
+1:
+ PTR_ADDU a0, a0, 1 # clear bytes
+ bne a0, a3, 1b
+ sb zero, -1(a0)
+2:
+ j ra
+ nop
+END(bzero)
diff --git a/lib/libc/mips/string/ffs.S b/lib/libc/mips/string/ffs.S
new file mode 100644
index 0000000..17e509c
--- /dev/null
+++ b/lib/libc/mips/string/ffs.S
@@ -0,0 +1,59 @@
+/* $NetBSD: ffs.S,v 1.2 2009/12/14 00:39:00 matt Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)ffs.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: ffs.S,v 1.2 2009/12/14 00:39:00 matt Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef __ABICALLS__
+ .abicalls
+#endif
+
+/* bit = ffs(value) */
+
+LEAF(ffs)
+ move v0, zero
+ beq a0, zero, done
+1:
+ and v1, a0, 1 # bit set?
+ addu v0, v0, 1
+ srl a0, a0, 1
+ beq v1, zero, 1b # no, continue
+done:
+ j ra
+END(ffs)
diff --git a/lib/libc/mips/string/memcpy.S b/lib/libc/mips/string/memcpy.S
new file mode 100644
index 0000000..8d3c0db
--- /dev/null
+++ b/lib/libc/mips/string/memcpy.S
@@ -0,0 +1,7 @@
+/* $NetBSD: memcpy.S,v 1.1 2005/12/20 19:28:50 christos Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#define MEMCOPY
+#include "bcopy.S"
diff --git a/lib/libc/mips/string/memmove.S b/lib/libc/mips/string/memmove.S
new file mode 100644
index 0000000..29d9e70
--- /dev/null
+++ b/lib/libc/mips/string/memmove.S
@@ -0,0 +1,7 @@
+/* $NetBSD: memmove.S,v 1.1 2005/12/20 19:28:50 christos Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#define MEMMOVE
+#include "bcopy.S"
diff --git a/lib/libc/mips/string/strchr.S b/lib/libc/mips/string/strchr.S
new file mode 100644
index 0000000..198366f
--- /dev/null
+++ b/lib/libc/mips/string/strchr.S
@@ -0,0 +1,61 @@
+/* $NetBSD: index.S,v 1.8 2005/04/22 06:59:00 simonb Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)index.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: index.S,v 1.8 2005/04/22 06:59:00 simonb Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef __ABICALLS__
+ .abicalls
+#endif
+
+LEAF(strchr)
+1:
+ lbu a2, 0(a0) # get a byte
+ PTR_ADDU a0, a0, 1
+ beq a2, a1, fnd
+ bne a2, zero, 1b
+notfnd:
+ move v0, zero
+ j ra
+fnd:
+ PTR_SUBU v0, a0, 1
+ j ra
+END(strchr)
+
+WEAK_ALIAS(index, strchr)
diff --git a/lib/libc/mips/string/strcmp.S b/lib/libc/mips/string/strcmp.S
new file mode 100644
index 0000000..8a99056
--- /dev/null
+++ b/lib/libc/mips/string/strcmp.S
@@ -0,0 +1,68 @@
+/* $NetBSD: strcmp.S,v 1.2 2009/12/14 00:39:00 matt Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)strcmp.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: strcmp.S,v 1.2 2009/12/14 00:39:00 matt Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef __ABICALLS__
+ .abicalls
+#endif
+
+/*
+ * NOTE: this version assumes unsigned chars in order to be "8 bit clean".
+ */
+LEAF(strcmp)
+1:
+ lbu t0, 0(a0) # get two bytes and compare them
+ lbu t1, 0(a1)
+ beq t0, zero, LessOrEq # end of first string?
+ bne t0, t1, NotEq
+ lbu t0, 1(a0) # unroll loop
+ lbu t1, 1(a1)
+ PTR_ADD a0, a0, 2
+ beq t0, zero, LessOrEq # end of first string?
+ PTR_ADD a1, a1, 2
+ beq t0, t1, 1b
+NotEq:
+ subu v0, t0, t1
+ j ra
+LessOrEq:
+ subu v0, zero, t1
+ j ra
+END(strcmp)
diff --git a/lib/libc/mips/string/strlen.S b/lib/libc/mips/string/strlen.S
new file mode 100644
index 0000000..3b46ccc
--- /dev/null
+++ b/lib/libc/mips/string/strlen.S
@@ -0,0 +1,55 @@
+/* $NetBSD: strlen.S,v 1.2 2009/12/14 00:39:00 matt Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)strlen.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: strlen.S,v 1.2 2009/12/14 00:39:00 matt Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef __ABICALLS__
+ .abicalls
+#endif
+
+LEAF(strlen)
+ PTR_ADDU v1, a0, 1
+1:
+ lb v0, 0(a0) # get byte from string
+ PTR_ADDU a0, a0, 1 # increment pointer
+ bne v0, zero, 1b # continue if not end
+ PTR_SUBU v0, a0, v1 # compute length - 1 for '\0' char
+ j ra
+END(strlen)
diff --git a/lib/libc/mips/string/strrchr.S b/lib/libc/mips/string/strrchr.S
new file mode 100644
index 0000000..5a88a42
--- /dev/null
+++ b/lib/libc/mips/string/strrchr.S
@@ -0,0 +1,59 @@
+/* $NetBSD: rindex.S,v 1.7 2003/08/07 16:42:16 agc Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)rindex.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: rindex.S,v 1.7 2003/08/07 16:42:16 agc Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+#ifdef __ABICALLS__
+ .abicalls
+#endif
+
+LEAF(strrchr)
+ move v0, zero # default if not found
+1:
+ lbu a3, 0(a0) # get a byte
+ PTR_ADDU a0, a0, 1
+ bne a3, a1, 2f
+ PTR_SUBU v0, a0, 1 # save address of last match
+2:
+ bne a3, zero, 1b # continue if not end
+ j ra
+END(strrchr)
+
+WEAK_ALIAS(rindex, strrchr)
diff --git a/lib/libc/mips/sys/Makefile.inc b/lib/libc/mips/sys/Makefile.inc
new file mode 100644
index 0000000..3601909
--- /dev/null
+++ b/lib/libc/mips/sys/Makefile.inc
@@ -0,0 +1,13 @@
+# $FreeBSD$
+
+MDASM= Ovfork.S brk.S cerror.S exect.S \
+ fork.S pipe.S ptrace.S sbrk.S syscall.S
+
+# Don't generate default code for these syscalls:
+NOASM= break.o exit.o ftruncate.o getlogin.o lseek.o mmap.o \
+ openbsd_poll.o pread.o pwrite.o sstk.o truncate.o vfork.o yield.o
+
+PSEUDO= _exit.o _getlogin.o
+.if !defined(WITHOUT_SYSCALL_COMPAT)
+PSEUDO+= _pread.o _pwrite.o _lseek.o _mmap.o _ftruncate.o _truncate.o
+.endif
diff --git a/lib/libc/mips/sys/Ovfork.S b/lib/libc/mips/sys/Ovfork.S
new file mode 100644
index 0000000..9df93ea
--- /dev/null
+++ b/lib/libc/mips/sys/Ovfork.S
@@ -0,0 +1,64 @@
+/* $NetBSD: compat_Ovfork.S,v 1.1 2005/09/17 11:49:39 tsutsui Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)Ovfork.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: compat_Ovfork.S,v 1.1 2005/09/17 11:49:39 tsutsui Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+/*
+ * pid = vfork();
+ *
+ * v1 == 0 in parent process, v1 == 1 in child process.
+ * v0 == pid of child in parent, v0 == pid of parent in child.
+ */
+
+LEAF(__sys_vfork)
+ WEAK_ALIAS(vfork, __sys_vfork)
+ WEAK_ALIAS(_vfork, __sys_vfork)
+ PIC_PROLOGUE(__sys_vfork)
+ li v0, SYS_vfork # system call number for vfork
+ syscall
+ beq a3, zero, 1f # jump if no errors
+ PIC_TAILCALL(__cerror)
+1:
+ beq v1, zero, 2f # parent process ?
+ move v0, zero # return zero in child
+2:
+ PIC_RETURN()
+END(__sys_vfork)
diff --git a/lib/libc/mips/sys/brk.S b/lib/libc/mips/sys/brk.S
new file mode 100644
index 0000000..68f0bd4
--- /dev/null
+++ b/lib/libc/mips/sys/brk.S
@@ -0,0 +1,71 @@
+/* $NetBSD: brk.S,v 1.16 2003/08/07 16:42:17 agc Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)brk.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: brk.S,v 1.16 2003/08/07 16:42:17 agc Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+ .globl _C_LABEL(minbrk)
+ .globl _C_LABEL(__curbrk)
+ .globl _C_LABEL(_end)
+
+ .data
+_C_LABEL(minbrk):
+ PTR_WORD _C_LABEL(_end)
+
+ .text
+LEAF(__sys_brk)
+ WEAK_ALIAS(brk, __sys_brk)
+ WEAK_ALIAS(_brk, __sys_brk)
+ PIC_PROLOGUE(__sys_brk)
+ PTR_LA v0, _C_LABEL(minbrk)
+ PTR_L v0, 0(v0)
+ bgeu a0, v0, 1f
+ move a0, v0 # dont allow break < minbrk
+1:
+ li v0, SYS_break
+ syscall
+ bne a3, zero, 2f
+ PTR_LA t0, _C_LABEL(__curbrk)
+ PTR_S a0, 0(t0)
+ move v0, zero
+ PIC_RETURN()
+2:
+ PIC_TAILCALL(__cerror)
+END(__sys_brk)
diff --git a/lib/libc/mips/sys/cerror.S b/lib/libc/mips/sys/cerror.S
new file mode 100644
index 0000000..c504d73
--- /dev/null
+++ b/lib/libc/mips/sys/cerror.S
@@ -0,0 +1,72 @@
+/* $NetBSD: cerror.S,v 1.14 2009/12/14 01:07:42 matt Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+ RCSID("from: @(#)cerror.s 8.1 (Berkeley) 6/16/93")
+#else
+ RCSID("$NetBSD: cerror.S,v 1.14 2009/12/14 01:07:42 matt Exp $")
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+ .globl _C_LABEL(__error)
+NESTED_NOPROFILE(__cerror, CALLFRAME_SIZ, ra)
+ .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
+ SETUP_GP
+ PTR_SUBU sp, sp, CALLFRAME_SIZ
+ SETUP_GP64(CALLFRAME_GP, __cerror)
+ SAVE_GP(CALLFRAME_GP)
+
+ PTR_S ra, CALLFRAME_RA(sp)
+ REG_S v0, CALLFRAME_S0(sp) # save errno value
+
+ PTR_LA t9, _C_LABEL(__error) # locate address of errno
+ jalr t9
+
+ REG_L t0, CALLFRAME_S0(sp)
+ PTR_L ra, CALLFRAME_RA(sp)
+ INT_S t0, 0(v0) # update errno value
+
+ RESTORE_GP64
+ PTR_ADDU sp, sp, CALLFRAME_SIZ
+
+ li v0, -1
+ li v1, -1
+
+ j ra
+END(__cerror)
diff --git a/lib/libc/mips/sys/exect.S b/lib/libc/mips/sys/exect.S
new file mode 100644
index 0000000..613d47c
--- /dev/null
+++ b/lib/libc/mips/sys/exect.S
@@ -0,0 +1,51 @@
+/* $NetBSD: exect.S,v 1.9 2003/08/07 16:42:17 agc Exp $ */
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)exect.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: exect.S,v 1.9 2003/08/07 16:42:17 agc Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+LEAF(exect)
+ PIC_PROLOGUE(exect)
+ li v0, SYS_execve
+ syscall
+ bne a3, zero, 1f
+ PIC_RETURN()
+1:
+ PIC_TAILCALL(__cerror)
+END(exect)
diff --git a/lib/libc/mips/sys/fork.S b/lib/libc/mips/sys/fork.S
new file mode 100644
index 0000000..7636bd3
--- /dev/null
+++ b/lib/libc/mips/sys/fork.S
@@ -0,0 +1,57 @@
+/* $NetBSD: fork.S,v 1.11 2003/08/07 16:42:17 agc Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)fork.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: fork.S,v 1.11 2003/08/07 16:42:17 agc Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+LEAF(__sys_fork)
+ WEAK_ALIAS(fork, __sys_fork)
+ WEAK_ALIAS(_fork, __sys_fork)
+ PIC_PROLOGUE(__sys_fork)
+ li v0, SYS_fork # pid = fork()
+ syscall
+ bne a3, zero, 2f
+ beq v1, zero, 1f # v1 == 0 in parent, 1 in child
+ move v0, zero
+1:
+ PIC_RETURN()
+2:
+ PIC_TAILCALL(__cerror)
+END(__sys_fork)
diff --git a/lib/libc/mips/sys/pipe.S b/lib/libc/mips/sys/pipe.S
new file mode 100644
index 0000000..0146532
--- /dev/null
+++ b/lib/libc/mips/sys/pipe.S
@@ -0,0 +1,57 @@
+/* $NetBSD: pipe.S,v 1.11 2005/04/22 06:58:01 simonb Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)pipe.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: pipe.S,v 1.11 2005/04/22 06:58:01 simonb Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+LEAF(__sys_pipe)
+ WEAK_ALIAS(pipe, __sys_pipe)
+ WEAK_ALIAS(_pipe, __sys_pipe)
+ PIC_PROLOGUE(__sys_pipe)
+ li v0, SYS_pipe # pipe(fildes) int fildes[2];
+ syscall
+ bne a3, zero, 1f
+ sw v0, 0(a0) # store the two file descriptors
+ sw v1, 4(a0)
+ move v0, zero
+ PIC_RETURN()
+1:
+ PIC_TAILCALL(__cerror)
+END(__sys_pipe)
diff --git a/lib/libc/mips/sys/ptrace.S b/lib/libc/mips/sys/ptrace.S
new file mode 100644
index 0000000..8cf984a9
--- /dev/null
+++ b/lib/libc/mips/sys/ptrace.S
@@ -0,0 +1,71 @@
+/* $NetBSD: ptrace.S,v 1.9 2003/08/07 16:42:17 agc Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)ptrace.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: ptrace.S,v 1.9 2003/08/07 16:42:17 agc Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+NESTED_NOPROFILE(ptrace, CALLFRAME_SIZ, ra)
+ .mask 0x80000000, (CALLFRAME_RA - CALLFRAME_SIZ)
+ SETUP_GP
+ PTR_SUBU sp, sp, CALLFRAME_SIZ
+ SETUP_GP64(CALLFRAME_GP, ptrace)
+ SAVE_GP(CALLFRAME_GP)
+
+ PTR_S ra, CALLFRAME_RA(sp)
+
+ PTR_LA t9, _C_LABEL(__error) # locate address of errno
+ jalr t9
+
+ PTR_L ra, CALLFRAME_RA(sp)
+ INT_S zero, 0(v0) # update errno value
+
+ li v0, SYS_ptrace
+ syscall
+
+ # Load __cerror's address using our gp, then restore it.
+ PTR_LA t9, __cerror
+ RESTORE_GP64
+ PTR_ADDU sp, sp, CALLFRAME_SIZ
+
+ bne a3, zero, 1f
+
+ j ra
+1: j t9
+END(ptrace)
diff --git a/lib/libc/mips/sys/sbrk.S b/lib/libc/mips/sys/sbrk.S
new file mode 100644
index 0000000..0989493
--- /dev/null
+++ b/lib/libc/mips/sys/sbrk.S
@@ -0,0 +1,73 @@
+/* $NetBSD: sbrk.S,v 1.16 2005/04/22 06:58:01 simonb Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)sbrk.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: sbrk.S,v 1.16 2005/04/22 06:58:01 simonb Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+ .globl _C_LABEL(__curbrk)
+ .globl _C_LABEL(_end)
+
+ .data
+_C_LABEL(__curbrk):
+ PTR_WORD _C_LABEL(_end)
+ .text
+
+LEAF(__sys_sbrk)
+ WEAK_ALIAS(sbrk, __sys_sbrk)
+ WEAK_ALIAS(_sbrk, __sys_sbrk)
+ PIC_PROLOGUE(__sys_sbrk)
+ PTR_LA t0, _C_LABEL(__curbrk)
+ PTR_L t0, 0(t0)
+ PTR_ADDU a0, a0, t0
+
+ li v0, SYS_break
+ syscall
+
+ bne a3, zero, 1f
+ nop
+ move v0, t0 # return old val of curbrk from above
+ PTR_LA t0, _C_LABEL(__curbrk)
+ PTR_S a0, 0(t0) # save current val of curbrk from above
+ PIC_RETURN()
+ j ra
+
+1:
+ PIC_TAILCALL(__cerror)
+END(__sys_sbrk)
diff --git a/lib/libc/mips/sys/shmat.S b/lib/libc/mips/sys/shmat.S
new file mode 100644
index 0000000..d81f6bf
--- /dev/null
+++ b/lib/libc/mips/sys/shmat.S
@@ -0,0 +1,7 @@
+/* $NetBSD: shmat.S,v 1.1 2000/07/07 08:20:52 itohy Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+RSYSCALL(shmat)
diff --git a/lib/libc/mips/sys/syscall.S b/lib/libc/mips/sys/syscall.S
new file mode 100644
index 0000000..b3c6708
--- /dev/null
+++ b/lib/libc/mips/sys/syscall.S
@@ -0,0 +1,44 @@
+/* $NetBSD: syscall.S,v 1.5 2003/08/07 16:42:18 agc Exp $ */
+
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ralph Campbell.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+#include "SYS.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ ASMSTR("from: @(#)syscall.s 8.1 (Berkeley) 6/4/93")
+ ASMSTR("$NetBSD: syscall.S,v 1.5 2003/08/07 16:42:18 agc Exp $")
+#endif /* LIBC_SCCS and not lint */
+
+RSYSCALL(syscall)
diff --git a/lib/libc/nameser/Makefile.inc b/lib/libc/nameser/Makefile.inc
new file mode 100644
index 0000000..05b4f55
--- /dev/null
+++ b/lib/libc/nameser/Makefile.inc
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+# nameser sources
+.PATH: ${.CURDIR}/nameser
+
+SRCS+= ns_name.c ns_netint.c ns_parse.c ns_print.c ns_samedomain.c ns_ttl.c
+
+SYM_MAPS+= ${.CURDIR}/nameser/Symbol.map
diff --git a/lib/libc/nameser/Symbol.map b/lib/libc/nameser/Symbol.map
new file mode 100644
index 0000000..190a59f
--- /dev/null
+++ b/lib/libc/nameser/Symbol.map
@@ -0,0 +1,31 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ __ns_makecanon;
+ __ns_msg_getflag;
+ __ns_name_ntol;
+ __ns_name_ntop;
+ __ns_name_pton;
+ __ns_name_unpack;
+ __ns_name_pack;
+ __ns_name_uncompress;
+ __ns_name_compress;
+ __ns_name_rollback;
+ __ns_name_skip;
+ __ns_get16;
+ __ns_get32;
+ __ns_put16;
+ __ns_put32;
+ __ns_initparse;
+ __ns_parserr;
+ _ns_flagdata;
+ __ns_samedomain;
+ __ns_samename;
+ __ns_skiprr;
+ __ns_sprintrr;
+ __ns_sprintrrf;
+ __ns_format_ttl;
+ __ns_parse_ttl;
+};
diff --git a/lib/libc/nameser/ns_name.c b/lib/libc/nameser/ns_name.c
new file mode 100644
index 0000000..31dee36
--- /dev/null
+++ b/lib/libc/nameser/ns_name.c
@@ -0,0 +1,973 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_name.c,v 1.8.18.2 2005/04/27 05:01:08 sra Exp $";
+#endif
+
+#include "port_before.h"
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include <limits.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+#define NS_TYPE_ELT 0x40 /*%< EDNS0 extended label type */
+#define DNS_LABELTYPE_BITSTRING 0x41
+
+/* Data. */
+
+static const char digits[] = "0123456789";
+
+static const char digitvalue[256] = {
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*16*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*32*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*48*/
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, -1, -1, -1, -1, -1, /*64*/
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*80*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*96*/
+ -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*112*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*128*/
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /*256*/
+};
+
+/* Forward. */
+
+static int special(int);
+static int printable(int);
+static int dn_find(const u_char *, const u_char *,
+ const u_char * const *,
+ const u_char * const *);
+static int encode_bitsring(const char **, const char *,
+ unsigned char **, unsigned char **,
+ unsigned const char *);
+static int labellen(const u_char *);
+static int decode_bitstring(const unsigned char **,
+ char *, const char *);
+
+/* Public. */
+
+/*%
+ * Convert an encoded domain name to printable ascii as per RFC1035.
+
+ * return:
+ *\li Number of bytes written to buffer, or -1 (with errno set)
+ *
+ * notes:
+ *\li The root is returned as "."
+ *\li All other domains are returned in non absolute form
+ */
+int
+ns_name_ntop(const u_char *src, char *dst, size_t dstsiz)
+{
+ const u_char *cp;
+ char *dn, *eom;
+ u_char c;
+ u_int n;
+ int l;
+
+ cp = src;
+ dn = dst;
+ eom = dst + dstsiz;
+
+ while ((n = *cp++) != 0) {
+ if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ /* Some kind of compression pointer. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (dn != dst) {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '.';
+ }
+ if ((l = labellen(cp - 1)) < 0) {
+ errno = EMSGSIZE; /*%< XXX */
+ return(-1);
+ }
+ if (dn + l >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if ((n & NS_CMPRSFLGS) == NS_TYPE_ELT) {
+ int m;
+
+ if (n != DNS_LABELTYPE_BITSTRING) {
+ /* XXX: labellen should reject this case */
+ errno = EINVAL;
+ return(-1);
+ }
+ if ((m = decode_bitstring(&cp, dn, eom)) < 0)
+ {
+ errno = EMSGSIZE;
+ return(-1);
+ }
+ dn += m;
+ continue;
+ }
+ for ((void)NULL; l > 0; l--) {
+ c = *cp++;
+ if (special(c)) {
+ if (dn + 1 >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\\';
+ *dn++ = (char)c;
+ } else if (!printable(c)) {
+ if (dn + 3 >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\\';
+ *dn++ = digits[c / 100];
+ *dn++ = digits[(c % 100) / 10];
+ *dn++ = digits[c % 10];
+ } else {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = (char)c;
+ }
+ }
+ }
+ if (dn == dst) {
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '.';
+ }
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = '\0';
+ return (dn - dst);
+}
+
+/*%
+ * Convert a ascii string into an encoded domain name as per RFC1035.
+ *
+ * return:
+ *
+ *\li -1 if it fails
+ *\li 1 if string was fully qualified
+ *\li 0 is string was not fully qualified
+ *
+ * notes:
+ *\li Enforces label and domain length limits.
+ */
+
+int
+ns_name_pton(const char *src, u_char *dst, size_t dstsiz)
+{
+ u_char *label, *bp, *eom;
+ int c, n, escaped, e = 0;
+ char *cp;
+
+ escaped = 0;
+ bp = dst;
+ eom = dst + dstsiz;
+ label = bp++;
+
+ while ((c = *src++) != 0) {
+ if (escaped) {
+ if (c == '[') { /*%< start a bit string label */
+ if ((cp = strchr(src, ']')) == NULL) {
+ errno = EINVAL; /*%< ??? */
+ return(-1);
+ }
+ if ((e = encode_bitsring(&src, cp + 2,
+ &label, &bp, eom))
+ != 0) {
+ errno = e;
+ return(-1);
+ }
+ escaped = 0;
+ label = bp++;
+ if ((c = *src++) == 0)
+ goto done;
+ else if (c != '.') {
+ errno = EINVAL;
+ return(-1);
+ }
+ continue;
+ }
+ else if ((cp = strchr(digits, c)) != NULL) {
+ n = (cp - digits) * 100;
+ if ((c = *src++) == 0 ||
+ (cp = strchr(digits, c)) == NULL) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ n += (cp - digits) * 10;
+ if ((c = *src++) == 0 ||
+ (cp = strchr(digits, c)) == NULL) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ n += (cp - digits);
+ if (n > 255) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ c = n;
+ }
+ escaped = 0;
+ } else if (c == '\\') {
+ escaped = 1;
+ continue;
+ } else if (c == '.') {
+ c = (bp - label - 1);
+ if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (label >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *label = c;
+ /* Fully qualified ? */
+ if (*src == '\0') {
+ if (c != 0) {
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = '\0';
+ }
+ if ((bp - dst) > MAXCDNAME) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return (1);
+ }
+ if (c == 0 || *src == '.') {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ label = bp++;
+ continue;
+ }
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = (u_char)c;
+ }
+ c = (bp - label - 1);
+ if ((c & NS_CMPRSFLGS) != 0) { /*%< Label too big. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ done:
+ if (label >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *label = c;
+ if (c != 0) {
+ if (bp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *bp++ = 0;
+ }
+ if ((bp - dst) > MAXCDNAME) { /*%< src too big */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return (0);
+}
+
+/*%
+ * Convert a network strings labels into all lowercase.
+ *
+ * return:
+ *\li Number of bytes written to buffer, or -1 (with errno set)
+ *
+ * notes:
+ *\li Enforces label and domain length limits.
+ */
+
+int
+ns_name_ntol(const u_char *src, u_char *dst, size_t dstsiz)
+{
+ const u_char *cp;
+ u_char *dn, *eom;
+ u_char c;
+ u_int n;
+ int l;
+
+ cp = src;
+ dn = dst;
+ eom = dst + dstsiz;
+
+ if (dn >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ while ((n = *cp++) != 0) {
+ if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ /* Some kind of compression pointer. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *dn++ = n;
+ if ((l = labellen(cp - 1)) < 0) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (dn + l >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ for ((void)NULL; l > 0; l--) {
+ c = *cp++;
+ if (isupper(c))
+ *dn++ = tolower(c);
+ else
+ *dn++ = c;
+ }
+ }
+ *dn++ = '\0';
+ return (dn - dst);
+}
+
+/*%
+ * Unpack a domain name from a message, source may be compressed.
+ *
+ * return:
+ *\li -1 if it fails, or consumed octets if it succeeds.
+ */
+int
+ns_name_unpack(const u_char *msg, const u_char *eom, const u_char *src,
+ u_char *dst, size_t dstsiz)
+{
+ const u_char *srcp, *dstlim;
+ u_char *dstp;
+ int n, len, checked, l;
+
+ len = -1;
+ checked = 0;
+ dstp = dst;
+ srcp = src;
+ dstlim = dst + dstsiz;
+ if (srcp < msg || srcp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ /* Fetch next label in domain name. */
+ while ((n = *srcp++) != 0) {
+ /* Check for indirection. */
+ switch (n & NS_CMPRSFLGS) {
+ case 0:
+ case NS_TYPE_ELT:
+ /* Limit checks. */
+ if ((l = labellen(srcp - 1)) < 0) {
+ errno = EMSGSIZE;
+ return(-1);
+ }
+ if (dstp + l + 1 >= dstlim || srcp + l >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ checked += l + 1;
+ *dstp++ = n;
+ memcpy(dstp, srcp, l);
+ dstp += l;
+ srcp += l;
+ break;
+
+ case NS_CMPRSFLGS:
+ if (srcp >= eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (len < 0)
+ len = srcp - src + 1;
+ srcp = msg + (((n & 0x3f) << 8) | (*srcp & 0xff));
+ if (srcp < msg || srcp >= eom) { /*%< Out of range. */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ checked += 2;
+ /*
+ * Check for loops in the compressed name;
+ * if we've looked at the whole message,
+ * there must be a loop.
+ */
+ if (checked >= eom - msg) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ break;
+
+ default:
+ errno = EMSGSIZE;
+ return (-1); /*%< flag error */
+ }
+ }
+ *dstp = '\0';
+ if (len < 0)
+ len = srcp - src;
+ return (len);
+}
+
+/*%
+ * Pack domain name 'domain' into 'comp_dn'.
+ *
+ * return:
+ *\li Size of the compressed name, or -1.
+ *
+ * notes:
+ *\li 'dnptrs' is an array of pointers to previous compressed names.
+ *\li dnptrs[0] is a pointer to the beginning of the message. The array
+ * ends with NULL.
+ *\li 'lastdnptr' is a pointer to the end of the array pointed to
+ * by 'dnptrs'.
+ *
+ * Side effects:
+ *\li The list of pointers in dnptrs is updated for labels inserted into
+ * the message as we compress the name. If 'dnptr' is NULL, we don't
+ * try to compress names. If 'lastdnptr' is NULL, we don't update the
+ * list.
+ */
+int
+ns_name_pack(const u_char *src, u_char *dst, int dstsiz,
+ const u_char **dnptrs, const u_char **lastdnptr)
+{
+ u_char *dstp;
+ const u_char **cpp, **lpp, *eob, *msg;
+ const u_char *srcp;
+ int n, l, first = 1;
+
+ srcp = src;
+ dstp = dst;
+ eob = dstp + dstsiz;
+ lpp = cpp = NULL;
+ if (dnptrs != NULL) {
+ if ((msg = *dnptrs++) != NULL) {
+ for (cpp = dnptrs; *cpp != NULL; cpp++)
+ (void)NULL;
+ lpp = cpp; /*%< end of list to search */
+ }
+ } else
+ msg = NULL;
+
+ /* make sure the domain we are about to add is legal */
+ l = 0;
+ do {
+ int l0;
+
+ n = *srcp;
+ if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if ((l0 = labellen(srcp)) < 0) {
+ errno = EINVAL;
+ return(-1);
+ }
+ l += l0 + 1;
+ if (l > MAXCDNAME) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ srcp += l0 + 1;
+ } while (n != 0);
+
+ /* from here on we need to reset compression pointer array on error */
+ srcp = src;
+ do {
+ /* Look to see if we can use pointers. */
+ n = *srcp;
+ if (n != 0 && msg != NULL) {
+ l = dn_find(srcp, msg, (const u_char * const *)dnptrs,
+ (const u_char * const *)lpp);
+ if (l >= 0) {
+ if (dstp + 1 >= eob) {
+ goto cleanup;
+ }
+ *dstp++ = (l >> 8) | NS_CMPRSFLGS;
+ *dstp++ = l % 256;
+ return (dstp - dst);
+ }
+ /* Not found, save it. */
+ if (lastdnptr != NULL && cpp < lastdnptr - 1 &&
+ (dstp - msg) < 0x4000 && first) {
+ *cpp++ = dstp;
+ *cpp = NULL;
+ first = 0;
+ }
+ }
+ /* copy label to buffer */
+ if ((n & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ /* Should not happen. */
+ goto cleanup;
+ }
+ n = labellen(srcp);
+ if (dstp + 1 + n >= eob) {
+ goto cleanup;
+ }
+ memcpy(dstp, srcp, n + 1);
+ srcp += n + 1;
+ dstp += n + 1;
+ } while (n != 0);
+
+ if (dstp > eob) {
+cleanup:
+ if (msg != NULL)
+ *lpp = NULL;
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ return (dstp - dst);
+}
+
+/*%
+ * Expand compressed domain name to presentation format.
+ *
+ * return:
+ *\li Number of bytes read out of `src', or -1 (with errno set).
+ *
+ * note:
+ *\li Root domain returns as "." not "".
+ */
+int
+ns_name_uncompress(const u_char *msg, const u_char *eom, const u_char *src,
+ char *dst, size_t dstsiz)
+{
+ u_char tmp[NS_MAXCDNAME];
+ int n;
+
+ if ((n = ns_name_unpack(msg, eom, src, tmp, sizeof tmp)) == -1)
+ return (-1);
+ if (ns_name_ntop(tmp, dst, dstsiz) == -1)
+ return (-1);
+ return (n);
+}
+
+/*%
+ * Compress a domain name into wire format, using compression pointers.
+ *
+ * return:
+ *\li Number of bytes consumed in `dst' or -1 (with errno set).
+ *
+ * notes:
+ *\li 'dnptrs' is an array of pointers to previous compressed names.
+ *\li dnptrs[0] is a pointer to the beginning of the message.
+ *\li The list ends with NULL. 'lastdnptr' is a pointer to the end of the
+ * array pointed to by 'dnptrs'. Side effect is to update the list of
+ * pointers for labels inserted into the message as we compress the name.
+ *\li If 'dnptr' is NULL, we don't try to compress names. If 'lastdnptr'
+ * is NULL, we don't update the list.
+ */
+int
+ns_name_compress(const char *src, u_char *dst, size_t dstsiz,
+ const u_char **dnptrs, const u_char **lastdnptr)
+{
+ u_char tmp[NS_MAXCDNAME];
+
+ if (ns_name_pton(src, tmp, sizeof tmp) == -1)
+ return (-1);
+ return (ns_name_pack(tmp, dst, dstsiz, dnptrs, lastdnptr));
+}
+
+/*%
+ * Reset dnptrs so that there are no active references to pointers at or
+ * after src.
+ */
+void
+ns_name_rollback(const u_char *src, const u_char **dnptrs,
+ const u_char **lastdnptr)
+{
+ while (dnptrs < lastdnptr && *dnptrs != NULL) {
+ if (*dnptrs >= src) {
+ *dnptrs = NULL;
+ break;
+ }
+ dnptrs++;
+ }
+}
+
+/*%
+ * Advance *ptrptr to skip over the compressed name it points at.
+ *
+ * return:
+ *\li 0 on success, -1 (with errno set) on failure.
+ */
+int
+ns_name_skip(const u_char **ptrptr, const u_char *eom)
+{
+ const u_char *cp;
+ u_int n;
+ int l;
+
+ cp = *ptrptr;
+ while (cp < eom && (n = *cp++) != 0) {
+ /* Check for indirection. */
+ switch (n & NS_CMPRSFLGS) {
+ case 0: /*%< normal case, n == len */
+ cp += n;
+ continue;
+ case NS_TYPE_ELT: /*%< EDNS0 extended label */
+ if ((l = labellen(cp - 1)) < 0) {
+ errno = EMSGSIZE; /*%< XXX */
+ return(-1);
+ }
+ cp += l;
+ continue;
+ case NS_CMPRSFLGS: /*%< indirection */
+ cp++;
+ break;
+ default: /*%< illegal type */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ break;
+ }
+ if (cp > eom) {
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ *ptrptr = cp;
+ return (0);
+}
+
+/* Private. */
+
+/*%
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * is this characted special ("in need of quoting") ?
+ *
+ * return:
+ *\li boolean.
+ */
+static int
+special(int ch) {
+ switch (ch) {
+ case 0x22: /*%< '"' */
+ case 0x2E: /*%< '.' */
+ case 0x3B: /*%< ';' */
+ case 0x5C: /*%< '\\' */
+ case 0x28: /*%< '(' */
+ case 0x29: /*%< ')' */
+ /* Special modifiers in zone files. */
+ case 0x40: /*%< '@' */
+ case 0x24: /*%< '$' */
+ return (1);
+ default:
+ return (0);
+ }
+}
+
+/*%
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * is this character visible and not a space when printed ?
+ *
+ * return:
+ *\li boolean.
+ */
+static int
+printable(int ch) {
+ return (ch > 0x20 && ch < 0x7f);
+}
+
+/*%
+ * Thinking in noninternationalized USASCII (per the DNS spec),
+ * convert this character to lower case if it's upper case.
+ */
+static int
+mklower(int ch) {
+ if (ch >= 0x41 && ch <= 0x5A)
+ return (ch + 0x20);
+ return (ch);
+}
+
+/*%
+ * Search for the counted-label name in an array of compressed names.
+ *
+ * return:
+ *\li offset from msg if found, or -1.
+ *
+ * notes:
+ *\li dnptrs is the pointer to the first name on the list,
+ *\li not the pointer to the start of the message.
+ */
+static int
+dn_find(const u_char *domain, const u_char *msg,
+ const u_char * const *dnptrs,
+ const u_char * const *lastdnptr)
+{
+ const u_char *dn, *cp, *sp;
+ const u_char * const *cpp;
+ u_int n;
+
+ for (cpp = dnptrs; cpp < lastdnptr; cpp++) {
+ sp = *cpp;
+ /*
+ * terminate search on:
+ * root label
+ * compression pointer
+ * unusable offset
+ */
+ while (*sp != 0 && (*sp & NS_CMPRSFLGS) == 0 &&
+ (sp - msg) < 0x4000) {
+ dn = domain;
+ cp = sp;
+ while ((n = *cp++) != 0) {
+ /*
+ * check for indirection
+ */
+ switch (n & NS_CMPRSFLGS) {
+ case 0: /*%< normal case, n == len */
+ n = labellen(cp - 1); /*%< XXX */
+ if (n != *dn++)
+ goto next;
+
+ for ((void)NULL; n > 0; n--)
+ if (mklower(*dn++) !=
+ mklower(*cp++))
+ goto next;
+ /* Is next root for both ? */
+ if (*dn == '\0' && *cp == '\0')
+ return (sp - msg);
+ if (*dn)
+ continue;
+ goto next;
+ case NS_CMPRSFLGS: /*%< indirection */
+ cp = msg + (((n & 0x3f) << 8) | *cp);
+ break;
+
+ default: /*%< illegal type */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ }
+ next: ;
+ sp += *sp + 1;
+ }
+ }
+ errno = ENOENT;
+ return (-1);
+}
+
+static int
+decode_bitstring(const unsigned char **cpp, char *dn, const char *eom)
+{
+ const unsigned char *cp = *cpp;
+ char *beg = dn, tc;
+ int b, blen, plen, i;
+
+ if ((blen = (*cp & 0xff)) == 0)
+ blen = 256;
+ plen = (blen + 3) / 4;
+ plen += sizeof("\\[x/]") + (blen > 99 ? 3 : (blen > 9) ? 2 : 1);
+ if (dn + plen >= eom)
+ return(-1);
+
+ cp++;
+ i = SPRINTF((dn, "\\[x"));
+ if (i < 0)
+ return (-1);
+ dn += i;
+ for (b = blen; b > 7; b -= 8, cp++) {
+ i = SPRINTF((dn, "%02x", *cp & 0xff));
+ if (i < 0)
+ return (-1);
+ dn += i;
+ }
+ if (b > 4) {
+ tc = *cp++;
+ i = SPRINTF((dn, "%02x", tc & (0xff << (8 - b))));
+ if (i < 0)
+ return (-1);
+ dn += i;
+ } else if (b > 0) {
+ tc = *cp++;
+ i = SPRINTF((dn, "%1x",
+ ((tc >> 4) & 0x0f) & (0x0f << (4 - b))));
+ if (i < 0)
+ return (-1);
+ dn += i;
+ }
+ i = SPRINTF((dn, "/%d]", blen));
+ if (i < 0)
+ return (-1);
+ dn += i;
+
+ *cpp = cp;
+ return(dn - beg);
+}
+
+static int
+encode_bitsring(const char **bp, const char *end, unsigned char **labelp,
+ unsigned char ** dst, unsigned const char *eom)
+{
+ int afterslash = 0;
+ const char *cp = *bp;
+ unsigned char *tp;
+ char c;
+ const char *beg_blen;
+ char *end_blen = NULL;
+ int value = 0, count = 0, tbcount = 0, blen = 0;
+
+ beg_blen = end_blen = NULL;
+
+ /* a bitstring must contain at least 2 characters */
+ if (end - cp < 2)
+ return(EINVAL);
+
+ /* XXX: currently, only hex strings are supported */
+ if (*cp++ != 'x')
+ return(EINVAL);
+ if (!isxdigit((*cp) & 0xff)) /*%< reject '\[x/BLEN]' */
+ return(EINVAL);
+
+ for (tp = *dst + 1; cp < end && tp < eom; cp++) {
+ switch((c = *cp)) {
+ case ']': /*%< end of the bitstring */
+ if (afterslash) {
+ if (beg_blen == NULL)
+ return(EINVAL);
+ blen = (int)strtol(beg_blen, &end_blen, 10);
+ if (*end_blen != ']')
+ return(EINVAL);
+ }
+ if (count)
+ *tp++ = ((value << 4) & 0xff);
+ cp++; /*%< skip ']' */
+ goto done;
+ case '/':
+ afterslash = 1;
+ break;
+ default:
+ if (afterslash) {
+ if (!isdigit(c&0xff))
+ return(EINVAL);
+ if (beg_blen == NULL) {
+
+ if (c == '0') {
+ /* blen never begings with 0 */
+ return(EINVAL);
+ }
+ beg_blen = cp;
+ }
+ } else {
+ if (!isxdigit(c&0xff))
+ return(EINVAL);
+ value <<= 4;
+ value += digitvalue[(int)c];
+ count += 4;
+ tbcount += 4;
+ if (tbcount > 256)
+ return(EINVAL);
+ if (count == 8) {
+ *tp++ = value;
+ count = 0;
+ }
+ }
+ break;
+ }
+ }
+ done:
+ if (cp >= end || tp >= eom)
+ return(EMSGSIZE);
+
+ /*
+ * bit length validation:
+ * If a <length> is present, the number of digits in the <bit-data>
+ * MUST be just sufficient to contain the number of bits specified
+ * by the <length>. If there are insignificant bits in a final
+ * hexadecimal or octal digit, they MUST be zero.
+ * RFC2673, Section 3.2.
+ */
+ if (blen > 0) {
+ int traillen;
+
+ if (((blen + 3) & ~3) != tbcount)
+ return(EINVAL);
+ traillen = tbcount - blen; /*%< between 0 and 3 */
+ if (((value << (8 - traillen)) & 0xff) != 0)
+ return(EINVAL);
+ }
+ else
+ blen = tbcount;
+ if (blen == 256)
+ blen = 0;
+
+ /* encode the type and the significant bit fields */
+ **labelp = DNS_LABELTYPE_BITSTRING;
+ **dst = blen;
+
+ *bp = cp;
+ *dst = tp;
+
+ return(0);
+}
+
+static int
+labellen(const u_char *lp)
+{
+ int bitlen;
+ u_char l = *lp;
+
+ if ((l & NS_CMPRSFLGS) == NS_CMPRSFLGS) {
+ /* should be avoided by the caller */
+ return(-1);
+ }
+
+ if ((l & NS_CMPRSFLGS) == NS_TYPE_ELT) {
+ if (l == DNS_LABELTYPE_BITSTRING) {
+ if ((bitlen = *(lp + 1)) == 0)
+ bitlen = 256;
+ return((bitlen + 7 ) / 8 + 1);
+ }
+ return(-1); /*%< unknwon ELT */
+ }
+ return(l);
+}
+
+/*! \file */
diff --git a/lib/libc/nameser/ns_netint.c b/lib/libc/nameser/ns_netint.c
new file mode 100644
index 0000000..b08c58b
--- /dev/null
+++ b/lib/libc/nameser/ns_netint.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_netint.c,v 1.2.18.1 2005/04/27 05:01:08 sra Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <arpa/nameser.h>
+
+#include "port_after.h"
+
+/* Public. */
+
+u_int
+ns_get16(const u_char *src) {
+ u_int dst;
+
+ NS_GET16(dst, src);
+ return (dst);
+}
+
+u_long
+ns_get32(const u_char *src) {
+ u_long dst;
+
+ NS_GET32(dst, src);
+ return (dst);
+}
+
+void
+ns_put16(u_int src, u_char *dst) {
+ NS_PUT16(src, dst);
+}
+
+void
+ns_put32(u_long src, u_char *dst) {
+ NS_PUT32(src, dst);
+}
+
+/*! \file */
diff --git a/lib/libc/nameser/ns_parse.c b/lib/libc/nameser/ns_parse.c
new file mode 100644
index 0000000..c4658d8
--- /dev/null
+++ b/lib/libc/nameser/ns_parse.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_parse.c,v 1.5.18.4 2007/08/27 03:34:24 marka Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+
+#include "port_after.h"
+
+/* Forward. */
+
+static void setsection(ns_msg *msg, ns_sect sect);
+
+/* Macros. */
+
+#if !defined(SOLARIS2) || defined(__COVERITY__)
+#define RETERR(err) do { errno = (err); return (-1); } while (0)
+#else
+#define RETERR(err) \
+ do { errno = (err); if (errno == errno) return (-1); } while (0)
+#endif
+
+/* Public. */
+
+/* These need to be in the same order as the nres.h:ns_flag enum. */
+struct _ns_flagdata _ns_flagdata[16] = {
+ { 0x8000, 15 }, /*%< qr. */
+ { 0x7800, 11 }, /*%< opcode. */
+ { 0x0400, 10 }, /*%< aa. */
+ { 0x0200, 9 }, /*%< tc. */
+ { 0x0100, 8 }, /*%< rd. */
+ { 0x0080, 7 }, /*%< ra. */
+ { 0x0040, 6 }, /*%< z. */
+ { 0x0020, 5 }, /*%< ad. */
+ { 0x0010, 4 }, /*%< cd. */
+ { 0x000f, 0 }, /*%< rcode. */
+ { 0x0000, 0 }, /*%< expansion (1/6). */
+ { 0x0000, 0 }, /*%< expansion (2/6). */
+ { 0x0000, 0 }, /*%< expansion (3/6). */
+ { 0x0000, 0 }, /*%< expansion (4/6). */
+ { 0x0000, 0 }, /*%< expansion (5/6). */
+ { 0x0000, 0 }, /*%< expansion (6/6). */
+};
+
+int ns_msg_getflag(ns_msg handle, int flag) {
+ return(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift);
+}
+
+int
+ns_skiprr(const u_char *ptr, const u_char *eom, ns_sect section, int count) {
+ const u_char *optr = ptr;
+
+ for ((void)NULL; count > 0; count--) {
+ int b, rdlength;
+
+ b = dn_skipname(ptr, eom);
+ if (b < 0)
+ RETERR(EMSGSIZE);
+ ptr += b/*Name*/ + NS_INT16SZ/*Type*/ + NS_INT16SZ/*Class*/;
+ if (section != ns_s_qd) {
+ if (ptr + NS_INT32SZ + NS_INT16SZ > eom)
+ RETERR(EMSGSIZE);
+ ptr += NS_INT32SZ/*TTL*/;
+ NS_GET16(rdlength, ptr);
+ ptr += rdlength/*RData*/;
+ }
+ }
+ if (ptr > eom)
+ RETERR(EMSGSIZE);
+ return (ptr - optr);
+}
+
+int
+ns_initparse(const u_char *msg, int msglen, ns_msg *handle) {
+ const u_char *eom = msg + msglen;
+ int i;
+
+ memset(handle, 0x5e, sizeof *handle);
+ handle->_msg = msg;
+ handle->_eom = eom;
+ if (msg + NS_INT16SZ > eom)
+ RETERR(EMSGSIZE);
+ NS_GET16(handle->_id, msg);
+ if (msg + NS_INT16SZ > eom)
+ RETERR(EMSGSIZE);
+ NS_GET16(handle->_flags, msg);
+ for (i = 0; i < ns_s_max; i++) {
+ if (msg + NS_INT16SZ > eom)
+ RETERR(EMSGSIZE);
+ NS_GET16(handle->_counts[i], msg);
+ }
+ for (i = 0; i < ns_s_max; i++)
+ if (handle->_counts[i] == 0)
+ handle->_sections[i] = NULL;
+ else {
+ int b = ns_skiprr(msg, eom, (ns_sect)i,
+ handle->_counts[i]);
+
+ if (b < 0)
+ return (-1);
+ handle->_sections[i] = msg;
+ msg += b;
+ }
+ if (msg != eom)
+ RETERR(EMSGSIZE);
+ setsection(handle, ns_s_max);
+ return (0);
+}
+
+int
+ns_parserr(ns_msg *handle, ns_sect section, int rrnum, ns_rr *rr) {
+ int b;
+ int tmp;
+
+ /* Make section right. */
+ tmp = section;
+ if (tmp < 0 || section >= ns_s_max)
+ RETERR(ENODEV);
+ if (section != handle->_sect)
+ setsection(handle, section);
+
+ /* Make rrnum right. */
+ if (rrnum == -1)
+ rrnum = handle->_rrnum;
+ if (rrnum < 0 || rrnum >= handle->_counts[(int)section])
+ RETERR(ENODEV);
+ if (rrnum < handle->_rrnum)
+ setsection(handle, section);
+ if (rrnum > handle->_rrnum) {
+ b = ns_skiprr(handle->_msg_ptr, handle->_eom, section,
+ rrnum - handle->_rrnum);
+
+ if (b < 0)
+ return (-1);
+ handle->_msg_ptr += b;
+ handle->_rrnum = rrnum;
+ }
+
+ /* Do the parse. */
+ b = dn_expand(handle->_msg, handle->_eom,
+ handle->_msg_ptr, rr->name, NS_MAXDNAME);
+ if (b < 0)
+ return (-1);
+ handle->_msg_ptr += b;
+ if (handle->_msg_ptr + NS_INT16SZ + NS_INT16SZ > handle->_eom)
+ RETERR(EMSGSIZE);
+ NS_GET16(rr->type, handle->_msg_ptr);
+ NS_GET16(rr->rr_class, handle->_msg_ptr);
+ if (section == ns_s_qd) {
+ rr->ttl = 0;
+ rr->rdlength = 0;
+ rr->rdata = NULL;
+ } else {
+ if (handle->_msg_ptr + NS_INT32SZ + NS_INT16SZ > handle->_eom)
+ RETERR(EMSGSIZE);
+ NS_GET32(rr->ttl, handle->_msg_ptr);
+ NS_GET16(rr->rdlength, handle->_msg_ptr);
+ if (handle->_msg_ptr + rr->rdlength > handle->_eom)
+ RETERR(EMSGSIZE);
+ rr->rdata = handle->_msg_ptr;
+ handle->_msg_ptr += rr->rdlength;
+ }
+ if (++handle->_rrnum > handle->_counts[(int)section])
+ setsection(handle, (ns_sect)((int)section + 1));
+
+ /* All done. */
+ return (0);
+}
+
+/* Private. */
+
+static void
+setsection(ns_msg *msg, ns_sect sect) {
+ msg->_sect = sect;
+ if (sect == ns_s_max) {
+ msg->_rrnum = -1;
+ msg->_msg_ptr = NULL;
+ } else {
+ msg->_rrnum = 0;
+ msg->_msg_ptr = msg->_sections[(int)sect];
+ }
+}
+
+/*! \file */
diff --git a/lib/libc/nameser/ns_print.c b/lib/libc/nameser/ns_print.c
new file mode 100644
index 0000000..2a46379
--- /dev/null
+++ b/lib/libc/nameser/ns_print.c
@@ -0,0 +1,908 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_print.c,v 1.6.18.4 2005/04/27 05:01:09 sra Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#ifdef _LIBC
+#include <assert.h>
+#define INSIST(cond) assert(cond)
+#else
+#include <isc/assertions.h>
+#include <isc/dst.h>
+#endif
+#include <errno.h>
+#include <resolv.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/* Forward. */
+
+static size_t prune_origin(const char *name, const char *origin);
+static int charstr(const u_char *rdata, const u_char *edata,
+ char **buf, size_t *buflen);
+static int addname(const u_char *msg, size_t msglen,
+ const u_char **p, const char *origin,
+ char **buf, size_t *buflen);
+static void addlen(size_t len, char **buf, size_t *buflen);
+static int addstr(const char *src, size_t len,
+ char **buf, size_t *buflen);
+static int addtab(size_t len, size_t target, int spaced,
+ char **buf, size_t *buflen);
+
+/* Macros. */
+
+#define T(x) \
+ do { \
+ if ((x) < 0) \
+ return (-1); \
+ } while (0)
+
+/* Public. */
+
+/*%
+ * Convert an RR to presentation format.
+ *
+ * return:
+ *\li Number of characters written to buf, or -1 (check errno).
+ */
+int
+ns_sprintrr(const ns_msg *handle, const ns_rr *rr,
+ const char *name_ctx, const char *origin,
+ char *buf, size_t buflen)
+{
+ int n;
+
+ n = ns_sprintrrf(ns_msg_base(*handle), ns_msg_size(*handle),
+ ns_rr_name(*rr), ns_rr_class(*rr), ns_rr_type(*rr),
+ ns_rr_ttl(*rr), ns_rr_rdata(*rr), ns_rr_rdlen(*rr),
+ name_ctx, origin, buf, buflen);
+ return (n);
+}
+
+/*%
+ * Convert the fields of an RR into presentation format.
+ *
+ * return:
+ *\li Number of characters written to buf, or -1 (check errno).
+ */
+int
+ns_sprintrrf(const u_char *msg, size_t msglen,
+ const char *name, ns_class class, ns_type type,
+ u_long ttl, const u_char *rdata, size_t rdlen,
+ const char *name_ctx, const char *origin,
+ char *buf, size_t buflen)
+{
+ const char *obuf = buf;
+ const u_char *edata = rdata + rdlen;
+ int spaced = 0;
+
+ const char *comment;
+ char tmp[100];
+ int len, x;
+
+ /*
+ * Owner.
+ */
+ if (name_ctx != NULL && ns_samename(name_ctx, name) == 1) {
+ T(addstr("\t\t\t", 3, &buf, &buflen));
+ } else {
+ len = prune_origin(name, origin);
+ if (*name == '\0') {
+ goto root;
+ } else if (len == 0) {
+ T(addstr("@\t\t\t", 4, &buf, &buflen));
+ } else {
+ T(addstr(name, len, &buf, &buflen));
+ /* Origin not used or not root, and no trailing dot? */
+ if (((origin == NULL || origin[0] == '\0') ||
+ (origin[0] != '.' && origin[1] != '\0' &&
+ name[len] == '\0')) && name[len - 1] != '.') {
+ root:
+ T(addstr(".", 1, &buf, &buflen));
+ len++;
+ }
+ T(spaced = addtab(len, 24, spaced, &buf, &buflen));
+ }
+ }
+
+ /*
+ * TTL, Class, Type.
+ */
+ T(x = ns_format_ttl(ttl, buf, buflen));
+ addlen(x, &buf, &buflen);
+ len = SPRINTF((tmp, " %s %s", p_class(class), p_type(type)));
+ T(addstr(tmp, len, &buf, &buflen));
+ T(spaced = addtab(x + len, 16, spaced, &buf, &buflen));
+
+ /*
+ * RData.
+ */
+ switch (type) {
+ case ns_t_a:
+ if (rdlen != (size_t)NS_INADDRSZ)
+ goto formerr;
+ (void) inet_ntop(AF_INET, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+
+ case ns_t_cname:
+ case ns_t_mb:
+ case ns_t_mg:
+ case ns_t_mr:
+ case ns_t_ns:
+ case ns_t_ptr:
+ case ns_t_dname:
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+
+ case ns_t_hinfo:
+ case ns_t_isdn:
+ /* First word. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+
+ /* Second word, optional in ISDN records. */
+ if (type == ns_t_isdn && rdata == edata)
+ break;
+
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ break;
+
+ case ns_t_soa: {
+ u_long t;
+
+ /* Server name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Administrator name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" (\n", 3, &buf, &buflen));
+ spaced = 0;
+
+ if ((edata - rdata) != 5*NS_INT32SZ)
+ goto formerr;
+
+ /* Serial number. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ len = SPRINTF((tmp, "%lu", t));
+ T(addstr(tmp, len, &buf, &buflen));
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; serial\n", 9, &buf, &buflen));
+ spaced = 0;
+
+ /* Refresh interval. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; refresh\n", 10, &buf, &buflen));
+ spaced = 0;
+
+ /* Retry interval. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; retry\n", 8, &buf, &buflen));
+ spaced = 0;
+
+ /* Expiry. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; expiry\n", 9, &buf, &buflen));
+ spaced = 0;
+
+ /* Minimum TTL. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ T(addstr("\t\t\t\t\t", 5, &buf, &buflen));
+ T(len = ns_format_ttl(t, buf, buflen));
+ addlen(len, &buf, &buflen);
+ T(addstr(" )", 2, &buf, &buflen));
+ T(spaced = addtab(len, 16, spaced, &buf, &buflen));
+ T(addstr("; minimum\n", 10, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_mx:
+ case ns_t_afsdb:
+ case ns_t_rt: {
+ u_int t;
+
+ if (rdlen < (size_t)NS_INT16SZ)
+ goto formerr;
+
+ /* Priority. */
+ t = ns_get16(rdata);
+ rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", t));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Target. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_px: {
+ u_int t;
+
+ if (rdlen < (size_t)NS_INT16SZ)
+ goto formerr;
+
+ /* Priority. */
+ t = ns_get16(rdata);
+ rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", t));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Name1. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Name2. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_x25:
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ break;
+
+ case ns_t_txt:
+ while (rdata < edata) {
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ if (rdata < edata)
+ T(addstr(" ", 1, &buf, &buflen));
+ }
+ break;
+
+ case ns_t_nsap: {
+ char t[2+255*3];
+
+ (void) inet_nsap_ntoa(rdlen, rdata, t);
+ T(addstr(t, strlen(t), &buf, &buflen));
+ break;
+ }
+
+ case ns_t_aaaa:
+ if (rdlen != (size_t)NS_IN6ADDRSZ)
+ goto formerr;
+ (void) inet_ntop(AF_INET6, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+
+ case ns_t_loc: {
+ char t[255];
+
+ /* XXX protocol format checking? */
+ (void) loc_ntoa(rdata, t);
+ T(addstr(t, strlen(t), &buf, &buflen));
+ break;
+ }
+
+ case ns_t_naptr: {
+ u_int order, preference;
+ char t[50];
+
+ if (rdlen < 2U*NS_INT16SZ)
+ goto formerr;
+
+ /* Order, Precedence. */
+ order = ns_get16(rdata); rdata += NS_INT16SZ;
+ preference = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((t, "%u %u ", order, preference));
+ T(addstr(t, len, &buf, &buflen));
+
+ /* Flags. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Service. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Regexp. */
+ T(len = charstr(rdata, edata, &buf, &buflen));
+ if (len < 0)
+ return (-1);
+ if (len == 0)
+ goto formerr;
+ rdata += len;
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Server. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_srv: {
+ u_int priority, weight, port;
+ char t[50];
+
+ if (rdlen < 3U*NS_INT16SZ)
+ goto formerr;
+
+ /* Priority, Weight, Port. */
+ priority = ns_get16(rdata); rdata += NS_INT16SZ;
+ weight = ns_get16(rdata); rdata += NS_INT16SZ;
+ port = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((t, "%u %u %u ", priority, weight, port));
+ T(addstr(t, len, &buf, &buflen));
+
+ /* Server. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_minfo:
+ case ns_t_rp:
+ /* Name1. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Name2. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+
+ case ns_t_wks: {
+ int n, lcnt;
+
+ if (rdlen < 1U + NS_INT32SZ)
+ goto formerr;
+
+ /* Address. */
+ (void) inet_ntop(AF_INET, rdata, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ rdata += NS_INADDRSZ;
+
+ /* Protocol. */
+ len = SPRINTF((tmp, " %u ( ", *rdata));
+ T(addstr(tmp, len, &buf, &buflen));
+ rdata += NS_INT8SZ;
+
+ /* Bit map. */
+ n = 0;
+ lcnt = 0;
+ while (rdata < edata) {
+ u_int c = *rdata++;
+ do {
+ if (c & 0200) {
+ if (lcnt == 0) {
+ T(addstr("\n\t\t\t\t", 5,
+ &buf, &buflen));
+ lcnt = 10;
+ spaced = 0;
+ }
+ len = SPRINTF((tmp, "%d ", n));
+ T(addstr(tmp, len, &buf, &buflen));
+ lcnt--;
+ }
+ c <<= 1;
+ } while (++n & 07);
+ }
+ T(addstr(")", 1, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_key: {
+ char base64_key[NS_MD5RSA_MAX_BASE64];
+ u_int keyflags, protocol, algorithm, key_id;
+ const char *leader;
+ int n;
+
+ if (rdlen < 0U + NS_INT16SZ + NS_INT8SZ + NS_INT8SZ)
+ goto formerr;
+
+ /* Key flags, Protocol, Algorithm. */
+#ifndef _LIBC
+ key_id = dst_s_dns_key_id(rdata, edata-rdata);
+#else
+ key_id = 0;
+#endif
+ keyflags = ns_get16(rdata); rdata += NS_INT16SZ;
+ protocol = *rdata++;
+ algorithm = *rdata++;
+ len = SPRINTF((tmp, "0x%04x %u %u",
+ keyflags, protocol, algorithm));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Public key data. */
+ len = b64_ntop(rdata, edata - rdata,
+ base64_key, sizeof base64_key);
+ if (len < 0)
+ goto formerr;
+ if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ } else
+ leader = " ";
+ for (n = 0; n < len; n += 48) {
+ T(addstr(leader, strlen(leader), &buf, &buflen));
+ T(addstr(base64_key + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+ n = SPRINTF((tmp, " ; key_tag= %u", key_id));
+ T(addstr(tmp, n, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_sig: {
+ char base64_key[NS_MD5RSA_MAX_BASE64];
+ u_int type, algorithm, labels, footprint;
+ const char *leader;
+ u_long t;
+ int n;
+
+ if (rdlen < 22U)
+ goto formerr;
+
+ /* Type covered, Algorithm, Label count, Original TTL. */
+ type = ns_get16(rdata); rdata += NS_INT16SZ;
+ algorithm = *rdata++;
+ labels = *rdata++;
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s %d %d %lu ",
+ p_type(type), algorithm, labels, t));
+ T(addstr(tmp, len, &buf, &buflen));
+ if (labels > (u_int)dn_count_labels(name))
+ goto formerr;
+
+ /* Signature expiry. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Time signed. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Signature Footprint. */
+ footprint = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u ", footprint));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Signer's name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ /* Signature. */
+ len = b64_ntop(rdata, edata - rdata,
+ base64_key, sizeof base64_key);
+ if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ } else
+ leader = " ";
+ if (len < 0)
+ goto formerr;
+ for (n = 0; n < len; n += 48) {
+ T(addstr(leader, strlen(leader), &buf, &buflen));
+ T(addstr(base64_key + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+ break;
+ }
+
+ case ns_t_nxt: {
+ int n, c;
+
+ /* Next domain name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ /* Type bit map. */
+ n = edata - rdata;
+ for (c = 0; c < n*8; c++)
+ if (NS_NXT_BIT_ISSET(c, rdata)) {
+ len = SPRINTF((tmp, " %s", p_type(c)));
+ T(addstr(tmp, len, &buf, &buflen));
+ }
+ break;
+ }
+
+ case ns_t_cert: {
+ u_int c_type, key_tag, alg;
+ int n;
+ unsigned int siz;
+ char base64_cert[8192], tmp[40];
+ const char *leader;
+
+ c_type = ns_get16(rdata); rdata += NS_INT16SZ;
+ key_tag = ns_get16(rdata); rdata += NS_INT16SZ;
+ alg = (u_int) *rdata++;
+
+ len = SPRINTF((tmp, "%d %d %d ", c_type, key_tag, alg));
+ T(addstr(tmp, len, &buf, &buflen));
+ siz = (edata-rdata)*4/3 + 4; /* "+4" accounts for trailing \0 */
+ if (siz > sizeof(base64_cert) * 3/4) {
+ const char *str = "record too long to print";
+ T(addstr(str, strlen(str), &buf, &buflen));
+ }
+ else {
+ len = b64_ntop(rdata, edata-rdata, base64_cert, siz);
+
+ if (len < 0)
+ goto formerr;
+ else if (len > 15) {
+ T(addstr(" (", 2, &buf, &buflen));
+ leader = "\n\t\t";
+ spaced = 0;
+ }
+ else
+ leader = " ";
+
+ for (n = 0; n < len; n += 48) {
+ T(addstr(leader, strlen(leader),
+ &buf, &buflen));
+ T(addstr(base64_cert + n, MIN(len - n, 48),
+ &buf, &buflen));
+ }
+ if (len > 15)
+ T(addstr(" )", 2, &buf, &buflen));
+ }
+ break;
+ }
+
+ case ns_t_tkey: {
+ /* KJD - need to complete this */
+ u_long t;
+ int mode, err, keysize;
+
+ /* Algorithm name. */
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+
+ /* Inception. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Experation. */
+ t = ns_get32(rdata); rdata += NS_INT32SZ;
+ len = SPRINTF((tmp, "%s ", p_secstodate(t)));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* Mode , Error, Key Size. */
+ /* Priority, Weight, Port. */
+ mode = ns_get16(rdata); rdata += NS_INT16SZ;
+ err = ns_get16(rdata); rdata += NS_INT16SZ;
+ keysize = ns_get16(rdata); rdata += NS_INT16SZ;
+ len = SPRINTF((tmp, "%u %u %u ", mode, err, keysize));
+ T(addstr(tmp, len, &buf, &buflen));
+
+ /* XXX need to dump key, print otherdata length & other data */
+ break;
+ }
+
+ case ns_t_tsig: {
+ /* BEW - need to complete this */
+ int n;
+
+ T(len = addname(msg, msglen, &rdata, origin, &buf, &buflen));
+ T(addstr(" ", 1, &buf, &buflen));
+ rdata += 8; /*%< time */
+ n = ns_get16(rdata); rdata += INT16SZ;
+ rdata += n; /*%< sig */
+ n = ns_get16(rdata); rdata += INT16SZ; /*%< original id */
+ sprintf(buf, "%d", ns_get16(rdata));
+ rdata += INT16SZ;
+ addlen(strlen(buf), &buf, &buflen);
+ break;
+ }
+
+ case ns_t_a6: {
+ struct in6_addr a;
+ int pbyte, pbit;
+
+ /* prefix length */
+ if (rdlen == 0U) goto formerr;
+ len = SPRINTF((tmp, "%d ", *rdata));
+ T(addstr(tmp, len, &buf, &buflen));
+ pbit = *rdata;
+ if (pbit > 128) goto formerr;
+ pbyte = (pbit & ~7) / 8;
+ rdata++;
+
+ /* address suffix: provided only when prefix len != 128 */
+ if (pbit < 128) {
+ if (rdata + pbyte >= edata) goto formerr;
+ memset(&a, 0, sizeof(a));
+ memcpy(&a.s6_addr[pbyte], rdata, sizeof(a) - pbyte);
+ (void) inet_ntop(AF_INET6, &a, buf, buflen);
+ addlen(strlen(buf), &buf, &buflen);
+ rdata += sizeof(a) - pbyte;
+ }
+
+ /* prefix name: provided only when prefix len > 0 */
+ if (pbit == 0)
+ break;
+ if (rdata >= edata) goto formerr;
+ T(addstr(" ", 1, &buf, &buflen));
+ T(addname(msg, msglen, &rdata, origin, &buf, &buflen));
+
+ break;
+ }
+
+ case ns_t_opt: {
+ len = SPRINTF((tmp, "%u bytes", class));
+ T(addstr(tmp, len, &buf, &buflen));
+ break;
+ }
+
+ default:
+ comment = "unknown RR type";
+ goto hexify;
+ }
+ return (buf - obuf);
+ formerr:
+ comment = "RR format error";
+ hexify: {
+ int n, m;
+ char *p;
+
+ len = SPRINTF((tmp, "\\# %u%s\t; %s", (unsigned)(edata - rdata),
+ rdlen != 0U ? " (" : "", comment));
+ T(addstr(tmp, len, &buf, &buflen));
+ while (rdata < edata) {
+ p = tmp;
+ p += SPRINTF((p, "\n\t"));
+ spaced = 0;
+ n = MIN(16, edata - rdata);
+ for (m = 0; m < n; m++)
+ p += SPRINTF((p, "%02x ", rdata[m]));
+ T(addstr(tmp, p - tmp, &buf, &buflen));
+ if (n < 16) {
+ T(addstr(")", 1, &buf, &buflen));
+ T(addtab(p - tmp + 1, 48, spaced, &buf, &buflen));
+ }
+ p = tmp;
+ p += SPRINTF((p, "; "));
+ for (m = 0; m < n; m++)
+ *p++ = (isascii(rdata[m]) && isprint(rdata[m]))
+ ? rdata[m]
+ : '.';
+ T(addstr(tmp, p - tmp, &buf, &buflen));
+ rdata += n;
+ }
+ return (buf - obuf);
+ }
+}
+
+/* Private. */
+
+/*%
+ * size_t
+ * prune_origin(name, origin)
+ * Find out if the name is at or under the current origin.
+ * return:
+ * Number of characters in name before start of origin,
+ * or length of name if origin does not match.
+ * notes:
+ * This function should share code with samedomain().
+ */
+static size_t
+prune_origin(const char *name, const char *origin) {
+ const char *oname = name;
+
+ while (*name != '\0') {
+ if (origin != NULL && ns_samename(name, origin) == 1)
+ return (name - oname - (name > oname));
+ while (*name != '\0') {
+ if (*name == '\\') {
+ name++;
+ /* XXX need to handle \nnn form. */
+ if (*name == '\0')
+ break;
+ } else if (*name == '.') {
+ name++;
+ break;
+ }
+ name++;
+ }
+ }
+ return (name - oname);
+}
+
+/*%
+ * int
+ * charstr(rdata, edata, buf, buflen)
+ * Format a <character-string> into the presentation buffer.
+ * return:
+ * Number of rdata octets consumed
+ * 0 for protocol format error
+ * -1 for output buffer error
+ * side effects:
+ * buffer is advanced on success.
+ */
+static int
+charstr(const u_char *rdata, const u_char *edata, char **buf, size_t *buflen) {
+ const u_char *odata = rdata;
+ size_t save_buflen = *buflen;
+ char *save_buf = *buf;
+
+ if (addstr("\"", 1, buf, buflen) < 0)
+ goto enospc;
+ if (rdata < edata) {
+ int n = *rdata;
+
+ if (rdata + 1 + n <= edata) {
+ rdata++;
+ while (n-- > 0) {
+ if (strchr("\n\"\\", *rdata) != NULL)
+ if (addstr("\\", 1, buf, buflen) < 0)
+ goto enospc;
+ if (addstr((const char *)rdata, 1,
+ buf, buflen) < 0)
+ goto enospc;
+ rdata++;
+ }
+ }
+ }
+ if (addstr("\"", 1, buf, buflen) < 0)
+ goto enospc;
+ return (rdata - odata);
+ enospc:
+ errno = ENOSPC;
+ *buf = save_buf;
+ *buflen = save_buflen;
+ return (-1);
+}
+
+static int
+addname(const u_char *msg, size_t msglen,
+ const u_char **pp, const char *origin,
+ char **buf, size_t *buflen)
+{
+ size_t newlen, save_buflen = *buflen;
+ char *save_buf = *buf;
+ int n;
+
+ n = dn_expand(msg, msg + msglen, *pp, *buf, *buflen);
+ if (n < 0)
+ goto enospc; /*%< Guess. */
+ newlen = prune_origin(*buf, origin);
+ if (**buf == '\0') {
+ goto root;
+ } else if (newlen == 0U) {
+ /* Use "@" instead of name. */
+ if (newlen + 2 > *buflen)
+ goto enospc; /* No room for "@\0". */
+ (*buf)[newlen++] = '@';
+ (*buf)[newlen] = '\0';
+ } else {
+ if (((origin == NULL || origin[0] == '\0') ||
+ (origin[0] != '.' && origin[1] != '\0' &&
+ (*buf)[newlen] == '\0')) && (*buf)[newlen - 1] != '.') {
+ /* No trailing dot. */
+ root:
+ if (newlen + 2 > *buflen)
+ goto enospc; /* No room for ".\0". */
+ (*buf)[newlen++] = '.';
+ (*buf)[newlen] = '\0';
+ }
+ }
+ *pp += n;
+ addlen(newlen, buf, buflen);
+ **buf = '\0';
+ return (newlen);
+ enospc:
+ errno = ENOSPC;
+ *buf = save_buf;
+ *buflen = save_buflen;
+ return (-1);
+}
+
+static void
+addlen(size_t len, char **buf, size_t *buflen) {
+ INSIST(len <= *buflen);
+ *buf += len;
+ *buflen -= len;
+}
+
+static int
+addstr(const char *src, size_t len, char **buf, size_t *buflen) {
+ if (len >= *buflen) {
+ errno = ENOSPC;
+ return (-1);
+ }
+ memcpy(*buf, src, len);
+ addlen(len, buf, buflen);
+ **buf = '\0';
+ return (0);
+}
+
+static int
+addtab(size_t len, size_t target, int spaced, char **buf, size_t *buflen) {
+ size_t save_buflen = *buflen;
+ char *save_buf = *buf;
+ int t;
+
+ if (spaced || len >= target - 1) {
+ T(addstr(" ", 2, buf, buflen));
+ spaced = 1;
+ } else {
+ for (t = (target - len - 1) / 8; t >= 0; t--)
+ if (addstr("\t", 1, buf, buflen) < 0) {
+ *buflen = save_buflen;
+ *buf = save_buf;
+ return (-1);
+ }
+ spaced = 0;
+ }
+ return (spaced);
+}
+
+/*! \file */
diff --git a/lib/libc/nameser/ns_samedomain.c b/lib/libc/nameser/ns_samedomain.c
new file mode 100644
index 0000000..9c43c79
--- /dev/null
+++ b/lib/libc/nameser/ns_samedomain.c
@@ -0,0 +1,211 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1995,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_samedomain.c,v 1.5.18.1 2005/04/27 05:01:09 sra Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <arpa/nameser.h>
+#include <errno.h>
+#include <string.h>
+
+#include "port_after.h"
+
+/*%
+ * Check whether a name belongs to a domain.
+ *
+ * Inputs:
+ *\li a - the domain whose ancestory is being verified
+ *\li b - the potential ancestor we're checking against
+ *
+ * Return:
+ *\li boolean - is a at or below b?
+ *
+ * Notes:
+ *\li Trailing dots are first removed from name and domain.
+ * Always compare complete subdomains, not only whether the
+ * domain name is the trailing string of the given name.
+ *
+ *\li "host.foobar.top" lies in "foobar.top" and in "top" and in ""
+ * but NOT in "bar.top"
+ */
+
+int
+ns_samedomain(const char *a, const char *b) {
+ size_t la, lb;
+ int diff, i, escaped;
+ const char *cp;
+
+ la = strlen(a);
+ lb = strlen(b);
+
+ /* Ignore a trailing label separator (i.e. an unescaped dot) in 'a'. */
+ if (la != 0U && a[la - 1] == '.') {
+ escaped = 0;
+ /* Note this loop doesn't get executed if la==1. */
+ for (i = la - 2; i >= 0; i--)
+ if (a[i] == '\\') {
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ } else
+ break;
+ if (!escaped)
+ la--;
+ }
+
+ /* Ignore a trailing label separator (i.e. an unescaped dot) in 'b'. */
+ if (lb != 0U && b[lb - 1] == '.') {
+ escaped = 0;
+ /* note this loop doesn't get executed if lb==1 */
+ for (i = lb - 2; i >= 0; i--)
+ if (b[i] == '\\') {
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ } else
+ break;
+ if (!escaped)
+ lb--;
+ }
+
+ /* lb == 0 means 'b' is the root domain, so 'a' must be in 'b'. */
+ if (lb == 0U)
+ return (1);
+
+ /* 'b' longer than 'a' means 'a' can't be in 'b'. */
+ if (lb > la)
+ return (0);
+
+ /* 'a' and 'b' being equal at this point indicates sameness. */
+ if (lb == la)
+ return (strncasecmp(a, b, lb) == 0);
+
+ /* Ok, we know la > lb. */
+
+ diff = la - lb;
+
+ /*
+ * If 'a' is only 1 character longer than 'b', then it can't be
+ * a subdomain of 'b' (because of the need for the '.' label
+ * separator).
+ */
+ if (diff < 2)
+ return (0);
+
+ /*
+ * If the character before the last 'lb' characters of 'b'
+ * isn't '.', then it can't be a match (this lets us avoid
+ * having "foobar.com" match "bar.com").
+ */
+ if (a[diff - 1] != '.')
+ return (0);
+
+ /*
+ * We're not sure about that '.', however. It could be escaped
+ * and thus not a really a label separator.
+ */
+ escaped = 0;
+ for (i = diff - 2; i >= 0; i--)
+ if (a[i] == '\\') {
+ if (escaped)
+ escaped = 0;
+ else
+ escaped = 1;
+ } else
+ break;
+ if (escaped)
+ return (0);
+
+ /* Now compare aligned trailing substring. */
+ cp = a + diff;
+ return (strncasecmp(cp, b, lb) == 0);
+}
+
+#ifndef _LIBC
+/*%
+ * is "a" a subdomain of "b"?
+ */
+int
+ns_subdomain(const char *a, const char *b) {
+ return (ns_samename(a, b) != 1 && ns_samedomain(a, b));
+}
+#endif
+
+/*%
+ * make a canonical copy of domain name "src"
+ *
+ * notes:
+ * \code
+ * foo -> foo.
+ * foo. -> foo.
+ * foo.. -> foo.
+ * foo\. -> foo\..
+ * foo\\. -> foo\\.
+ * \endcode
+ */
+
+int
+ns_makecanon(const char *src, char *dst, size_t dstsize) {
+ size_t n = strlen(src);
+
+ if (n + sizeof "." > dstsize) { /*%< Note: sizeof == 2 */
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ strcpy(dst, src);
+ while (n >= 1U && dst[n - 1] == '.') /*%< Ends in "." */
+ if (n >= 2U && dst[n - 2] == '\\' && /*%< Ends in "\." */
+ (n < 3U || dst[n - 3] != '\\')) /*%< But not "\\." */
+ break;
+ else
+ dst[--n] = '\0';
+ dst[n++] = '.';
+ dst[n] = '\0';
+ return (0);
+}
+
+/*%
+ * determine whether domain name "a" is the same as domain name "b"
+ *
+ * return:
+ *\li -1 on error
+ *\li 0 if names differ
+ *\li 1 if names are the same
+ */
+
+int
+ns_samename(const char *a, const char *b) {
+ char ta[NS_MAXDNAME], tb[NS_MAXDNAME];
+
+ if (ns_makecanon(a, ta, sizeof ta) < 0 ||
+ ns_makecanon(b, tb, sizeof tb) < 0)
+ return (-1);
+ if (strcasecmp(ta, tb) == 0)
+ return (1);
+ else
+ return (0);
+}
+
+/*! \file */
diff --git a/lib/libc/nameser/ns_ttl.c b/lib/libc/nameser/ns_ttl.c
new file mode 100644
index 0000000..627ddf1
--- /dev/null
+++ b/lib/libc/nameser/ns_ttl.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef lint
+static const char rcsid[] = "$Id: ns_ttl.c,v 1.2.18.2 2005/07/28 07:38:10 marka Exp $";
+#endif
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) ((size_t)sprintf x)
+#endif
+
+/* Forward. */
+
+static int fmt1(int t, char s, char **buf, size_t *buflen);
+
+/* Macros. */
+
+#define T(x) if ((x) < 0) return (-1); else (void)NULL
+
+/* Public. */
+
+int
+ns_format_ttl(u_long src, char *dst, size_t dstlen) {
+ char *odst = dst;
+ int secs, mins, hours, days, weeks, x;
+ char *p;
+
+ secs = src % 60; src /= 60;
+ mins = src % 60; src /= 60;
+ hours = src % 24; src /= 24;
+ days = src % 7; src /= 7;
+ weeks = src; src = 0;
+
+ x = 0;
+ if (weeks) {
+ T(fmt1(weeks, 'W', &dst, &dstlen));
+ x++;
+ }
+ if (days) {
+ T(fmt1(days, 'D', &dst, &dstlen));
+ x++;
+ }
+ if (hours) {
+ T(fmt1(hours, 'H', &dst, &dstlen));
+ x++;
+ }
+ if (mins) {
+ T(fmt1(mins, 'M', &dst, &dstlen));
+ x++;
+ }
+ if (secs || !(weeks || days || hours || mins)) {
+ T(fmt1(secs, 'S', &dst, &dstlen));
+ x++;
+ }
+
+ if (x > 1) {
+ int ch;
+
+ for (p = odst; (ch = *p) != '\0'; p++)
+ if (isascii(ch) && isupper(ch))
+ *p = tolower(ch);
+ }
+
+ return (dst - odst);
+}
+
+int
+ns_parse_ttl(const char *src, u_long *dst) {
+ u_long ttl, tmp;
+ int ch, digits, dirty;
+
+ ttl = 0;
+ tmp = 0;
+ digits = 0;
+ dirty = 0;
+ while ((ch = *src++) != '\0') {
+ if (!isascii(ch) || !isprint(ch))
+ goto einval;
+ if (isdigit(ch)) {
+ tmp *= 10;
+ tmp += (ch - '0');
+ digits++;
+ continue;
+ }
+ if (digits == 0)
+ goto einval;
+ if (islower(ch))
+ ch = toupper(ch);
+ switch (ch) {
+ case 'W': tmp *= 7;
+ case 'D': tmp *= 24;
+ case 'H': tmp *= 60;
+ case 'M': tmp *= 60;
+ case 'S': break;
+ default: goto einval;
+ }
+ ttl += tmp;
+ tmp = 0;
+ digits = 0;
+ dirty = 1;
+ }
+ if (digits > 0) {
+ if (dirty)
+ goto einval;
+ else
+ ttl += tmp;
+ } else if (!dirty)
+ goto einval;
+ *dst = ttl;
+ return (0);
+
+ einval:
+ errno = EINVAL;
+ return (-1);
+}
+
+/* Private. */
+
+static int
+fmt1(int t, char s, char **buf, size_t *buflen) {
+ char tmp[50];
+ size_t len;
+
+ len = SPRINTF((tmp, "%d%c", t, s));
+ if (len + 1 > *buflen)
+ return (-1);
+ strcpy(*buf, tmp);
+ *buf += len;
+ *buflen -= len;
+ return (0);
+}
+
+/*! \file */
diff --git a/lib/libc/net/Makefile.inc b/lib/libc/net/Makefile.inc
new file mode 100644
index 0000000..4eadf98
--- /dev/null
+++ b/lib/libc/net/Makefile.inc
@@ -0,0 +1,129 @@
+# from @(#)Makefile.inc 8.2 (Berkeley) 9/5/93
+# $FreeBSD$
+
+# machine-independent net sources
+.PATH: ${.CURDIR}/net
+
+SRCS+= base64.c ether_addr.c eui64.c \
+ gai_strerror.c getaddrinfo.c \
+ gethostbydns.c gethostbyht.c gethostbynis.c gethostnamadr.c \
+ getifaddrs.c getifmaddrs.c getnameinfo.c \
+ getnetbydns.c getnetbyht.c getnetbynis.c getnetnamadr.c \
+ getproto.c getprotoent.c getprotoname.c getservent.c \
+ if_indextoname.c if_nameindex.c if_nametoindex.c \
+ ip6opt.c linkaddr.c map_v4v6.c name6.c ntoh.c \
+ nsdispatch.c nslexer.c nsparser.y nss_compat.c \
+ rcmd.c rcmdsh.c recv.c rthdr.c sctp_sys_calls.c send.c \
+ sockatmark.c sourcefilter.c vars.c
+
+.if ${MK_NS_CACHING} != "no"
+SRCS+= nscache.c nscachedcli.c
+.endif
+
+SYM_MAPS+=${.CURDIR}/net/Symbol.map
+
+.if ${MK_INET6_SUPPORT} != "no"
+CFLAGS+=-DINET6
+.endif
+
+CFLAGS+=-I${.OBJDIR}
+
+# name6.c refers res_private.h
+CFLAGS+=-I${.CURDIR}/resolv
+
+YFLAGS+=-p_nsyy
+LFLAGS+=-P_nsyy
+
+CLEANFILES+=nslexer.c
+
+nslexer.c: nslexer.l
+ ${LEX} ${LFLAGS} -o/dev/stdout ${.IMPSRC} | \
+ sed -e '/YY_BUF_SIZE/s/16384/1024/' >${.TARGET}
+
+MAN+= byteorder.3 ethers.3 eui64.3 \
+ getaddrinfo.3 gai_strerror.3 gethostbyname.3 \
+ getifaddrs.3 getifmaddrs.3 getipnodebyname.3 \
+ getnameinfo.3 getnetent.3 getprotoent.3 getservent.3 \
+ if_indextoname.3 \
+ inet.3 inet_net.3 \
+ inet6_opt_init.3 inet6_option_space.3 inet6_rth_space.3 \
+ inet6_rthdr_space.3 linkaddr.3 \
+ nsdispatch.3 rcmd.3 rcmdsh.3 resolver.3 sockatmark.3 \
+ sourcefilter.3 \
+ sctp_bindx.3 sctp_connectx.3 sctp_freepaddrs.3 \
+ sctp_getaddrlen.3 sctp_getassocid.3 sctp_getpaddrs.3 \
+ sctp_opt_info.3 sctp_recvmsg.3 sctp_send.3 sctp_sendmsg.3 \
+
+MLINKS+=byteorder.3 htonl.3 byteorder.3 htons.3 byteorder.3 ntohl.3 \
+ byteorder.3 ntohs.3
+MLINKS+=ethers.3 ether_aton.3 ethers.3 ether_hostton.3 ethers.3 ether_line.3 \
+ ethers.3 ether_ntoa.3 ethers.3 ether_ntohost.3
+MLINKS+=eui64.3 eui64_aton.3 eui64.3 eui64_hostton.3 \
+ eui64.3 eui64_ntoa.3 eui64.3 eui64_ntohost.3
+MLINKS+=getaddrinfo.3 freeaddrinfo.3
+MLINKS+=gethostbyname.3 endhostent.3 gethostbyname.3 gethostbyaddr.3 \
+ gethostbyname.3 gethostbyname2.3 gethostbyname.3 gethostent.3 \
+ gethostbyname.3 herror.3 gethostbyname.3 hstrerror.3 \
+ gethostbyname.3 sethostent.3
+MLINKS+=getifaddrs.3 freeifaddrs.3
+MLINKS+=getifmaddrs.3 freeifmaddrs.3
+MLINKS+=getipnodebyname.3 getipnodebyaddr.3 getipnodebyname.3 freehostent.3
+MLINKS+=getnetent.3 endnetent.3 getnetent.3 getnetbyaddr.3 \
+ getnetent.3 getnetbyname.3 getnetent.3 setnetent.3
+MLINKS+=getprotoent.3 endprotoent.3 getprotoent.3 getprotobyname.3 \
+ getprotoent.3 getprotobynumber.3 getprotoent.3 setprotoent.3
+MLINKS+=getservent.3 endservent.3 getservent.3 getservbyname.3 \
+ getservent.3 getservbyport.3 getservent.3 setservent.3
+MLINKS+=if_indextoname.3 if_nametoindex.3 if_indextoname.3 if_nameindex.3 \
+ if_indextoname.3 if_freenameindex.3
+MLINKS+=inet.3 addr.3 inet.3 inet_addr.3 inet.3 inet_aton.3 \
+ inet.3 inet_lnaof.3 inet.3 inet_makeaddr.3 inet.3 inet_netof.3 \
+ inet.3 inet_network.3 inet.3 inet_ntoa.3 inet.3 inet_ntoa_r.3\
+ inet.3 inet_ntop.3 inet.3 inet_pton.3 \
+ inet.3 network.3 inet.3 ntoa.3
+MLINKS+= sctp_send.3 sctp_sendx.3
+MLINKS+= sctp_sendmsg.3 sctp_sendmsgx.3
+MLINKS+= sctp_freepaddrs.3 sctp_freeladdrs.3
+MLINKS+= sctp_getpaddrs.3 sctp_getladdrs.3
+MLINKS+=inet_net.3 inet_net_ntop.3 inet_net.3 inet_net_pton.3
+MLINKS+=inet6_opt_init.3 inet6_opt_append.3 \
+ inet6_opt_init.3 inet6_opt_find.3 \
+ inet6_opt_init.3 inet6_opt_finish.3 \
+ inet6_opt_init.3 inet6_opt_get_val.3 \
+ inet6_opt_init.3 inet6_opt_next.3 \
+ inet6_opt_init.3 inet6_opt_set_val.3 \
+ inet6_option_space.3 inet6_option_alloc.3 \
+ inet6_option_space.3 inet6_option_append.3 \
+ inet6_option_space.3 inet6_option_find.3 \
+ inet6_option_space.3 inet6_option_init.3 \
+ inet6_option_space.3 inet6_option_next.3 \
+ inet6_rth_space.3 inet6_rth_add.3 \
+ inet6_rth_space.3 inet6_rth_getaddr.3 \
+ inet6_rth_space.3 inet6_rth_init.3 \
+ inet6_rth_space.3 inet6_rth_reverse.3 \
+ inet6_rth_space.3 inet6_rth_segments.3 \
+ inet6_rthdr_space.3 inet6_rthdr_add.3 \
+ inet6_rthdr_space.3 inet6_rthdr_getaddr.3 \
+ inet6_rthdr_space.3 inet6_rthdr_getflags.3 \
+ inet6_rthdr_space.3 inet6_rthdr_init.3 \
+ inet6_rthdr_space.3 inet6_rthdr_lasthop.3 \
+ inet6_rthdr_space.3 inet6_rthdr_reverse.3 \
+ inet6_rthdr_space.3 inet6_rthdr_segments.3
+MLINKS+=linkaddr.3 link_addr.3 linkaddr.3 link_ntoa.3
+MLINKS+=rcmd.3 iruserok.3 rcmd.3 iruserok_sa.3 \
+ rcmd.3 rcmd_af.3 \
+ rcmd.3 rresvport.3 rcmd.3 rresvport_af.3 \
+ rcmd.3 ruserok.3
+MLINKS+=resolver.3 dn_comp.3 resolver.3 dn_expand.3 resolver.3 res_init.3 \
+ resolver.3 res_mkquery.3 resolver.3 res_query.3 \
+ resolver.3 res_search.3 resolver.3 res_send.3 resolver.3 dn_skipname.3 \
+ resolver.3 ns_get16.3 resolver.3 ns_get32.3 \
+ resolver.3 ns_put16.3 resolver.3 ns_put32.3
+MLINKS+=sourcefilter.3 setipv4sourcefilter.3 sourcefilter.3 getipv4sourcefilter.3 \
+ sourcefilter.3 setsourcefilter.3 sourcefilter.3 getsourcefilter.3
+
+.if ${MK_HESIOD} != "no"
+SRCS+= hesiod.c
+MAN+= hesiod.3
+.endif
+
diff --git a/lib/libc/net/Symbol.map b/lib/libc/net/Symbol.map
new file mode 100644
index 0000000..39ab2c7
--- /dev/null
+++ b/lib/libc/net/Symbol.map
@@ -0,0 +1,168 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ __b64_ntop;
+ __b64_pton;
+ ether_line;
+ ether_aton;
+ ether_aton_r;
+ ether_ntoa;
+ ether_ntoa_r;
+ ether_ntohost;
+ ether_hostton;
+ eui64_aton;
+ eui64_ntoa;
+ eui64_ntohost;
+ eui64_hostton;
+ gai_strerror;
+ freeaddrinfo;
+ getaddrinfo;
+ gethostent;
+ gethostent_r;
+ gethostbyname;
+ gethostbyname_r;
+ gethostbyname2;
+ gethostbyname2_r;
+ gethostbyaddr;
+ gethostbyaddr_r;
+ sethostent;
+ endhostent;
+ getifaddrs;
+ freeifaddrs;
+ getifmaddrs;
+ freeifmaddrs;
+ getnameinfo;
+ getnetent;
+ getnetent_r;
+ getnetbyname;
+ getnetbyname_r;
+ getnetbyaddr;
+ getnetbyaddr_r;
+ setnetent;
+ endnetent;
+ getprotobynumber;
+ getprotobynumber_r;
+ setprotoent;
+ endprotoent;
+ getprotoent;
+ getprotoent_r;
+ getprotobyname;
+ getprotobyname_r;
+ getservbyname;
+ getservbyname_r;
+ getservbyport;
+ getservbyport_r;
+ setservent;
+ endservent;
+ getservent;
+ getservent_r;
+ hesiod_init;
+ hesiod_end;
+ hesiod_to_bind;
+ hesiod_resolve;
+ hesiod_free_list;
+ hes_init;
+ hes_to_bind;
+ hes_resolve;
+ hes_error;
+ hes_free;
+ if_indextoname;
+ if_nameindex;
+ if_freenameindex;
+ if_nametoindex;
+ inet6_option_space;
+ inet6_option_init;
+ inet6_option_append;
+ inet6_option_alloc;
+ inet6_option_next;
+ inet6_option_find;
+ inet6_opt_init;
+ inet6_opt_append;
+ inet6_opt_finish;
+ inet6_opt_set_val;
+ inet6_opt_next;
+ inet6_opt_find;
+ inet6_opt_get_val;
+ link_addr;
+ link_ntoa;
+ getipnodebyname;
+ getipnodebyaddr;
+ freehostent;
+ __nsdefaultsrc;
+ _nsdbtaddsrc;
+ _nsdbtdump;
+ _nsdbtput;
+ nsdispatch;
+ rcmd;
+ rcmd_af;
+ rresvport;
+ rresvport_af;
+ ruserok;
+ iruserok;
+ iruserok_sa;
+ rcmdsh;
+ recv;
+ inet6_rthdr_space;
+ inet6_rthdr_init;
+ inet6_rthdr_add;
+ inet6_rthdr_lasthop;
+ inet6_rthdr_segments;
+ inet6_rthdr_getaddr;
+ inet6_rthdr_getflags;
+ inet6_rth_space;
+ inet6_rth_init;
+ inet6_rth_add;
+ inet6_rth_reverse;
+ inet6_rth_segments;
+ inet6_rth_getaddr;
+ send;
+ sockatmark;
+ in6addr_any;
+ in6addr_loopback;
+ in6addr_nodelocal_allnodes;
+ in6addr_linklocal_allnodes;
+ sctp_getaddrlen;
+ sctp_bindx;
+ sctp_connectx;
+ sctp_peeloff;
+ sctp_opt_info;
+ sctp_getpaddrs;
+ sctp_freepaddrs;
+ sctp_getladdrs;
+ sctp_freeladdrs;
+ sctp_sendmsg;
+ sctp_sendmsgx;
+ sctp_send;
+ sctp_sendx;
+ sctp_recvmsg;
+ setipv4sourcefilter;
+ getipv4sourcefilter;
+ getsourcefilter;
+ setsourcefilter;
+};
+
+FBSDprivate_1.0 {
+ _nsdispatch;
+ _nsyyerror; /* generated from nslexer.l */
+ _nsyylex; /* generated from nslexer.l */
+ _nsyyparse; /* generated from nsparser.y */
+ _nsyylineno; /* generated from nsparser.y */
+ __dns_getanswer;
+ __ivaliduser;
+ __ivaliduser_af;
+ __ivaliduser_sa;
+ __check_rhosts_file;
+ __rcmd_errstr;
+ __nss_compat_getgrnam_r;
+ __nss_compat_getgrgid_r;
+ __nss_compat_getgrent_r;
+ __nss_compat_setgrent;
+ __nss_compat_endgrent;
+ __nss_compat_getpwnam_r;
+ __nss_compat_getpwuid_r;
+ __nss_compat_getpwent_r;
+ __nss_compat_setpwent;
+ __nss_compat_endpwent;
+};
diff --git a/lib/libc/net/base64.c b/lib/libc/net/base64.c
new file mode 100644
index 0000000..4335030
--- /dev/null
+++ b/lib/libc/net/base64.c
@@ -0,0 +1,315 @@
+/*
+ * Copyright (c) 1996, 1998 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define Assert(Cond) if (!(Cond)) abort()
+
+static const char Base64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char Pad64 = '=';
+
+/* (From RFC1521 and draft-ietf-dnssec-secext-03.txt)
+ The following encoding technique is taken from RFC 1521 by Borenstein
+ and Freed. It is reproduced here in a slightly edited form for
+ convenience.
+
+ A 65-character subset of US-ASCII is used, enabling 6 bits to be
+ represented per printable character. (The extra 65th character, "=",
+ is used to signify a special processing function.)
+
+ The encoding process represents 24-bit groups of input bits as output
+ strings of 4 encoded characters. Proceeding from left to right, a
+ 24-bit input group is formed by concatenating 3 8-bit input groups.
+ These 24 bits are then treated as 4 concatenated 6-bit groups, each
+ of which is translated into a single digit in the base64 alphabet.
+
+ Each 6-bit group is used as an index into an array of 64 printable
+ characters. The character referenced by the index is placed in the
+ output string.
+
+ Table 1: The Base64 Alphabet
+
+ Value Encoding Value Encoding Value Encoding Value Encoding
+ 0 A 17 R 34 i 51 z
+ 1 B 18 S 35 j 52 0
+ 2 C 19 T 36 k 53 1
+ 3 D 20 U 37 l 54 2
+ 4 E 21 V 38 m 55 3
+ 5 F 22 W 39 n 56 4
+ 6 G 23 X 40 o 57 5
+ 7 H 24 Y 41 p 58 6
+ 8 I 25 Z 42 q 59 7
+ 9 J 26 a 43 r 60 8
+ 10 K 27 b 44 s 61 9
+ 11 L 28 c 45 t 62 +
+ 12 M 29 d 46 u 63 /
+ 13 N 30 e 47 v
+ 14 O 31 f 48 w (pad) =
+ 15 P 32 g 49 x
+ 16 Q 33 h 50 y
+
+ Special processing is performed if fewer than 24 bits are available
+ at the end of the data being encoded. A full encoding quantum is
+ always completed at the end of a quantity. When fewer than 24 input
+ bits are available in an input group, zero bits are added (on the
+ right) to form an integral number of 6-bit groups. Padding at the
+ end of the data is performed using the '=' character.
+
+ Since all base64 input is an integral number of octets, only the
+ -------------------------------------------------
+ following cases can arise:
+
+ (1) the final quantum of encoding input is an integral
+ multiple of 24 bits; here, the final unit of encoded
+ output will be an integral multiple of 4 characters
+ with no "=" padding,
+ (2) the final quantum of encoding input is exactly 8 bits;
+ here, the final unit of encoded output will be two
+ characters followed by two "=" padding characters, or
+ (3) the final quantum of encoding input is exactly 16 bits;
+ here, the final unit of encoded output will be three
+ characters followed by one "=" padding character.
+ */
+
+int
+b64_ntop(u_char const *src, size_t srclength, char *target, size_t targsize) {
+ size_t datalength = 0;
+ u_char input[3];
+ u_char output[4];
+ size_t i;
+
+ while (2 < srclength) {
+ input[0] = *src++;
+ input[1] = *src++;
+ input[2] = *src++;
+ srclength -= 3;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ output[3] = input[2] & 0x3f;
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+ Assert(output[3] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Base64[output[3]];
+ }
+
+ /* Now we worry about padding. */
+ if (0 != srclength) {
+ /* Get what's left. */
+ input[0] = input[1] = input[2] = '\0';
+ for (i = 0; i < srclength; i++)
+ input[i] = *src++;
+
+ output[0] = input[0] >> 2;
+ output[1] = ((input[0] & 0x03) << 4) + (input[1] >> 4);
+ output[2] = ((input[1] & 0x0f) << 2) + (input[2] >> 6);
+ Assert(output[0] < 64);
+ Assert(output[1] < 64);
+ Assert(output[2] < 64);
+
+ if (datalength + 4 > targsize)
+ return (-1);
+ target[datalength++] = Base64[output[0]];
+ target[datalength++] = Base64[output[1]];
+ if (srclength == 1)
+ target[datalength++] = Pad64;
+ else
+ target[datalength++] = Base64[output[2]];
+ target[datalength++] = Pad64;
+ }
+ if (datalength >= targsize)
+ return (-1);
+ target[datalength] = '\0'; /* Returned value doesn't count \0. */
+ return (datalength);
+}
+
+/* skips all whitespace anywhere.
+ converts characters, four at a time, starting at (or after)
+ src from base - 64 numbers into three 8 bit bytes in the target area.
+ it returns the number of data bytes stored at the target, or -1 on error.
+ */
+
+int
+b64_pton(src, target, targsize)
+ char const *src;
+ u_char *target;
+ size_t targsize;
+{
+ int tarindex, state, ch;
+ char *pos;
+
+ state = 0;
+ tarindex = 0;
+
+ while ((ch = *src++) != '\0') {
+ if (isspace((unsigned char)ch)) /* Skip whitespace anywhere. */
+ continue;
+
+ if (ch == Pad64)
+ break;
+
+ pos = strchr(Base64, ch);
+ if (pos == 0) /* A non-base64 character. */
+ return (-1);
+
+ switch (state) {
+ case 0:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] = (pos - Base64) << 2;
+ }
+ state = 1;
+ break;
+ case 1:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 4;
+ target[tarindex+1] = ((pos - Base64) & 0x0f)
+ << 4 ;
+ }
+ tarindex++;
+ state = 2;
+ break;
+ case 2:
+ if (target) {
+ if ((size_t)tarindex + 1 >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64) >> 2;
+ target[tarindex+1] = ((pos - Base64) & 0x03)
+ << 6;
+ }
+ tarindex++;
+ state = 3;
+ break;
+ case 3:
+ if (target) {
+ if ((size_t)tarindex >= targsize)
+ return (-1);
+ target[tarindex] |= (pos - Base64);
+ }
+ tarindex++;
+ state = 0;
+ break;
+ default:
+ abort();
+ }
+ }
+
+ /*
+ * We are done decoding Base-64 chars. Let's see if we ended
+ * on a byte boundary, and/or with erroneous trailing characters.
+ */
+
+ if (ch == Pad64) { /* We got a pad char. */
+ ch = *src++; /* Skip it, get next. */
+ switch (state) {
+ case 0: /* Invalid = in first position */
+ case 1: /* Invalid = in second position */
+ return (-1);
+
+ case 2: /* Valid, means one byte of info */
+ /* Skip any number of spaces. */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace((unsigned char)ch))
+ break;
+ /* Make sure there is another trailing = sign. */
+ if (ch != Pad64)
+ return (-1);
+ ch = *src++; /* Skip the = */
+ /* Fall through to "single trailing =" case. */
+ /* FALLTHROUGH */
+
+ case 3: /* Valid, means two bytes of info */
+ /*
+ * We know this char is an =. Is there anything but
+ * whitespace after it?
+ */
+ for ((void)NULL; ch != '\0'; ch = *src++)
+ if (!isspace((unsigned char)ch))
+ return (-1);
+
+ /*
+ * Now make sure for cases 2 and 3 that the "extra"
+ * bits that slopped past the last full byte were
+ * zeros. If we don't check them, they become a
+ * subliminal channel.
+ */
+ if (target && target[tarindex] != 0)
+ return (-1);
+ }
+ } else {
+ /*
+ * We ended by seeing the end of the string. Make sure we
+ * have no partial bytes lying around.
+ */
+ if (state != 0)
+ return (-1);
+ }
+
+ return (tarindex);
+}
diff --git a/lib/libc/net/byteorder.3 b/lib/libc/net/byteorder.3
new file mode 100644
index 0000000..ebb56d8
--- /dev/null
+++ b/lib/libc/net/byteorder.3
@@ -0,0 +1,86 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)byteorder.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd March 20, 2005
+.Dt BYTEORDER 3
+.Os
+.Sh NAME
+.Nm htonl ,
+.Nm htons ,
+.Nm ntohl ,
+.Nm ntohs
+.Nd convert values between host and network byte order
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In arpa/inet.h
+.Pp
+or
+.Pp
+.In netinet/in.h
+.Ft uint32_t
+.Fn htonl "uint32_t hostlong"
+.Ft uint16_t
+.Fn htons "uint16_t hostshort"
+.Ft uint32_t
+.Fn ntohl "uint32_t netlong"
+.Ft uint16_t
+.Fn ntohs "uint16_t netshort"
+.Sh DESCRIPTION
+These routines convert 16 and 32 bit quantities between network
+byte order and host byte order.
+On machines which have a byte order which is the same as the network
+order, routines are defined as null macros.
+.Pp
+These routines are most often used in conjunction with Internet
+addresses and ports as returned by
+.Xr gethostbyname 3
+and
+.Xr getservent 3 .
+.Sh SEE ALSO
+.Xr gethostbyname 3 ,
+.Xr getservent 3 ,
+.Xr byteorder 9
+.Sh STANDARDS
+The
+.Nm byteorder
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Nm byteorder
+functions appeared in
+.Bx 4.2 .
+.Sh BUGS
+On the
+.Tn VAX
+bytes are handled backwards from most everyone else in
+the world.
+This is not expected to be fixed in the near future.
diff --git a/lib/libc/net/ether_addr.c b/lib/libc/net/ether_addr.c
new file mode 100644
index 0000000..d769f27
--- /dev/null
+++ b/lib/libc/net/ether_addr.c
@@ -0,0 +1,230 @@
+/*
+ * Copyright (c) 1995 Bill Paul <wpaul@ctr.columbia.edu>.
+ * Copyright (c) 2007 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * ethernet address conversion and lookup routines
+ *
+ * Written by Bill Paul <wpaul@ctr.columbia.edu>
+ * Center for Telecommunications Research
+ * Columbia University, New York City
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <net/ethernet.h>
+
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+#include <paths.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#ifndef _PATH_ETHERS
+#define _PATH_ETHERS "/etc/ethers"
+#endif
+
+/*
+ * Parse a string of text containing an ethernet address and hostname and
+ * separate it into its component parts.
+ */
+int
+ether_line(const char *l, struct ether_addr *e, char *hostname)
+{
+ int i, o[6];
+
+ i = sscanf(l, "%x:%x:%x:%x:%x:%x %s", &o[0], &o[1], &o[2], &o[3],
+ &o[4], &o[5], hostname);
+ if (i != 7)
+ return (i);
+ for (i=0; i<6; i++)
+ e->octet[i] = o[i];
+ return (0);
+}
+
+/*
+ * Convert an ASCII representation of an ethernet address to binary form.
+ */
+struct ether_addr *
+ether_aton_r(const char *a, struct ether_addr *e)
+{
+ int i;
+ unsigned int o0, o1, o2, o3, o4, o5;
+
+ i = sscanf(a, "%x:%x:%x:%x:%x:%x", &o0, &o1, &o2, &o3, &o4, &o5);
+ if (i != 6)
+ return (NULL);
+ e->octet[0]=o0;
+ e->octet[1]=o1;
+ e->octet[2]=o2;
+ e->octet[3]=o3;
+ e->octet[4]=o4;
+ e->octet[5]=o5;
+ return (e);
+}
+
+struct ether_addr *
+ether_aton(const char *a)
+{
+ static struct ether_addr e;
+
+ return (ether_aton_r(a, &e));
+}
+
+/*
+ * Convert a binary representation of an ethernet address to an ASCII string.
+ */
+char *
+ether_ntoa_r(const struct ether_addr *n, char *a)
+{
+ int i;
+
+ i = sprintf(a, "%02x:%02x:%02x:%02x:%02x:%02x", n->octet[0],
+ n->octet[1], n->octet[2], n->octet[3], n->octet[4], n->octet[5]);
+ if (i < 17)
+ return (NULL);
+ return (a);
+}
+
+char *
+ether_ntoa(const struct ether_addr *n)
+{
+ static char a[18];
+
+ return (ether_ntoa_r(n, a));
+}
+
+/*
+ * Map an ethernet address to a hostname. Use either /etc/ethers or NIS/YP.
+ */
+int
+ether_ntohost(char *hostname, const struct ether_addr *e)
+{
+ FILE *fp;
+ char buf[BUFSIZ + 2];
+ struct ether_addr local_ether;
+ char local_host[MAXHOSTNAMELEN];
+#ifdef YP
+ char *result;
+ int resultlen;
+ char *ether_a;
+ char *yp_domain;
+#endif
+
+ if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
+ return (1);
+ while (fgets(buf,BUFSIZ,fp)) {
+ if (buf[0] == '#')
+ continue;
+#ifdef YP
+ if (buf[0] == '+') {
+ if (yp_get_default_domain(&yp_domain))
+ continue;
+ ether_a = ether_ntoa(e);
+ if (yp_match(yp_domain, "ethers.byaddr", ether_a,
+ strlen(ether_a), &result, &resultlen)) {
+ continue;
+ }
+ strncpy(buf, result, resultlen);
+ buf[resultlen] = '\0';
+ free(result);
+ }
+#endif
+ if (!ether_line(buf, &local_ether, local_host)) {
+ if (!bcmp((char *)&local_ether.octet[0],
+ (char *)&e->octet[0], 6)) {
+ /* We have a match. */
+ strcpy(hostname, local_host);
+ fclose(fp);
+ return(0);
+ }
+ }
+ }
+ fclose(fp);
+ return (1);
+}
+
+/*
+ * Map a hostname to an ethernet address using /etc/ethers or NIS/YP.
+ */
+int
+ether_hostton(const char *hostname, struct ether_addr *e)
+{
+ FILE *fp;
+ char buf[BUFSIZ + 2];
+ struct ether_addr local_ether;
+ char local_host[MAXHOSTNAMELEN];
+#ifdef YP
+ char *result;
+ int resultlen;
+ char *yp_domain;
+#endif
+
+ if ((fp = fopen(_PATH_ETHERS, "r")) == NULL)
+ return (1);
+ while (fgets(buf,BUFSIZ,fp)) {
+ if (buf[0] == '#')
+ continue;
+#ifdef YP
+ if (buf[0] == '+') {
+ if (yp_get_default_domain(&yp_domain))
+ continue;
+ if (yp_match(yp_domain, "ethers.byname", hostname,
+ strlen(hostname), &result, &resultlen)) {
+ continue;
+ }
+ strncpy(buf, result, resultlen);
+ buf[resultlen] = '\0';
+ free(result);
+ }
+#endif
+ if (!ether_line(buf, &local_ether, local_host)) {
+ if (!strcmp(hostname, local_host)) {
+ /* We have a match. */
+ bcopy((char *)&local_ether.octet[0],
+ (char *)&e->octet[0], 6);
+ fclose(fp);
+ return(0);
+ }
+ }
+ }
+ fclose(fp);
+ return (1);
+}
diff --git a/lib/libc/net/ethers.3 b/lib/libc/net/ethers.3
new file mode 100644
index 0000000..6fe568b
--- /dev/null
+++ b/lib/libc/net/ethers.3
@@ -0,0 +1,233 @@
+.\" Copyright (c) 1995 Bill Paul <wpaul@ctr.columbia.edu>.
+.\" Copyright (c) 2007 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Bill Paul.
+.\" 4. Neither the name of the author nor the names of any co-contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 30, 2007
+.Dt ETHERS 3
+.Os
+.Sh NAME
+.Nm ethers ,
+.Nm ether_line ,
+.Nm ether_aton ,
+.Nm ether_aton_r ,
+.Nm ether_ntoa ,
+.Nm ether_ntoa_r ,
+.Nm ether_ntohost ,
+.Nm ether_hostton
+.Nd Ethernet address conversion and lookup routines
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In net/ethernet.h
+.Ft int
+.Fn ether_line "const char *l" "struct ether_addr *e" "char *hostname"
+.Ft struct ether_addr *
+.Fn ether_aton "const char *a"
+.Ft struct ether_addr *
+.Fn ether_aton_r "const char *a" "struct ether_addr *e"
+.Ft char *
+.Fn ether_ntoa "const struct ether_addr *n"
+.Ft char *
+.Fn ether_ntoa_r "const struct ether_addr *n" "char *buf"
+.Ft int
+.Fn ether_ntohost "char *hostname" "const struct ether_addr *e"
+.Ft int
+.Fn ether_hostton "const char *hostname" "struct ether_addr *e"
+.Sh DESCRIPTION
+These functions operate on ethernet addresses using an
+.Vt ether_addr
+structure, which is defined in the header file
+.In net/ethernet.h :
+.Bd -literal -offset indent
+/*
+ * The number of bytes in an ethernet (MAC) address.
+ */
+#define ETHER_ADDR_LEN 6
+
+/*
+ * Structure of a 48-bit Ethernet address.
+ */
+struct ether_addr {
+ u_char octet[ETHER_ADDR_LEN];
+};
+.Ed
+.Pp
+The function
+.Fn ether_line
+scans
+.Fa l ,
+an
+.Tn ASCII
+string in
+.Xr ethers 5
+format and sets
+.Fa e
+to the ethernet address specified in the string and
+.Fa h
+to the hostname.
+This function is used to parse lines from
+.Pa /etc/ethers
+into their component parts.
+.Pp
+The
+.Fn ether_aton
+and
+.Fn ether_aton_r
+functions convert
+.Tn ASCII
+representation of ethernet addresses into
+.Vt ether_addr
+structures.
+Likewise, the
+.Fn ether_ntoa
+and
+.Fn ether_ntoa_r
+functions
+convert ethernet addresses specified as
+.Vt ether_addr
+structures into
+.Tn ASCII
+strings.
+.Pp
+The
+.Fn ether_ntohost
+and
+.Fn ether_hostton
+functions map ethernet addresses to their corresponding hostnames
+as specified in the
+.Pa /etc/ethers
+database.
+The
+.Fn ether_ntohost
+function
+converts from ethernet address to hostname, and
+.Fn ether_hostton
+converts from hostname to ethernet address.
+.Sh RETURN VALUES
+The
+.Fn ether_line
+function
+returns zero on success and non-zero if it was unable to parse
+any part of the supplied line
+.Fa l .
+It returns the extracted ethernet address in the supplied
+.Vt ether_addr
+structure
+.Fa e
+and the hostname in the supplied string
+.Fa h .
+.Pp
+On success,
+.Fn ether_ntoa
+and
+.Fn ether_ntoa_r
+functions return a pointer to a string containing an
+.Tn ASCII
+representation of an ethernet address.
+If it is unable to convert
+the supplied
+.Vt ether_addr
+structure, it returns a
+.Dv NULL
+pointer.
+.Fn ether_ntoa
+stores the result in a static buffer;
+.Fn ether_ntoa_r
+stores the result in a user-passed buffer.
+.Pp
+Likewise,
+.Fn ether_aton
+and
+.Fn ether_aton_r
+return a pointer to an
+.Vt ether_addr
+structure on success and a
+.Dv NULL
+pointer on failure.
+.Fn ether_aton
+stores the result in a static buffer;
+.Fn ether_aton_r
+stores the result in a user-passed buffer.
+.Pp
+The
+.Fn ether_ntohost
+and
+.Fn ether_hostton
+functions both return zero on success or non-zero if they were
+unable to find a match in the
+.Pa /etc/ethers
+database.
+.Sh NOTES
+The user must ensure that the hostname strings passed to the
+.Fn ether_line ,
+.Fn ether_ntohost
+and
+.Fn ether_hostton
+functions are large enough to contain the returned hostnames.
+.Sh NIS INTERACTION
+If the
+.Pa /etc/ethers
+contains a line with a single + in it, the
+.Fn ether_ntohost
+and
+.Fn ether_hostton
+functions will attempt to consult the NIS
+.Pa ethers.byname
+and
+.Pa ethers.byaddr
+maps in addition to the data in the
+.Pa /etc/ethers
+file.
+.Sh SEE ALSO
+.Xr ethers 5 ,
+.Xr yp 8
+.Sh HISTORY
+This particular implementation of the
+.Nm
+library functions were written for and first appeared in
+.Fx 2.1 .
+Thread-safe function variants first appeared in
+.Fx 7.0 .
+.Sh BUGS
+The
+.Fn ether_aton
+and
+.Fn ether_ntoa
+functions returns values that are stored in static memory areas
+which may be overwritten the next time they are called.
+.Pp
+.Fn ether_ntoa_r
+accepts a character buffer pointer, but not a buffer length.
+The caller must ensure adequate space is available in the buffer in order to
+avoid a buffer overflow.
diff --git a/lib/libc/net/eui64.3 b/lib/libc/net/eui64.3
new file mode 100644
index 0000000..fc563d1
--- /dev/null
+++ b/lib/libc/net/eui64.3
@@ -0,0 +1,223 @@
+.\" Copyright 2004 The Aerospace Corporation. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions, and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions, and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. The name of The Aerospace Corporation may not be used to endorse or
+.\" promote products derived from this software.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "AS IS" AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Copyright (c) 1995
+.\" Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Bill Paul.
+.\" 4. Neither the name of the author nor the names of any co-contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 4, 2004
+.Dt EUI64 3
+.Os
+.Sh NAME
+.Nm eui64 ,
+.\" .Nm eui64_line ,
+.Nm eui64_aton ,
+.Nm eui64_ntoa ,
+.Nm eui64_ntohost ,
+.Nm eui64_hostton
+.Nd IEEE EUI-64 conversion and lookup routines
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/eui64.h
+.\" .Ft int
+.\" .Fn eui64_line "const char *l" "struct eui64 *e" "char *hostname" "size_t len"
+.Ft int
+.Fn eui64_aton "const char *a" "struct eui64 *e"
+.Ft int
+.Fn eui64_ntoa "const struct eui64 *id" "char *a" "size_t len"
+.Ft int
+.Fn eui64_ntohost "char *hostname" "size_t len" "const struct eui64 *id"
+.Ft int
+.Fn eui64_hostton "const char *hostname" "struct eui64 *id"
+.Sh DESCRIPTION
+These functions operate on IEEE EUI-64s using an
+.Vt eui64
+structure, which is defined in the header file
+.In sys/eui64.h :
+.Bd -literal -offset indent
+/*
+ * The number of bytes in an EUI-64.
+ */
+#define EUI64_LEN 8
+
+/*
+ * Structure of an IEEE EUI-64.
+ */
+struct eui64 {
+ u_char octet[EUI64_LEN];
+};
+.Ed
+.\" .Pp
+.\" The function
+.\" .Fn eui64_line
+.\" scans
+.\" .Fa l ,
+.\" an
+.\" .Tn ASCII
+.\" string in
+.\" .Xr eui64 5
+.\" format and sets
+.\" .Fa e
+.\" to the EUI-64 specified in the string and
+.\" .Fa h
+.\" to the hostname.
+.\" This function is used to parse lines from
+.\" .Pa /etc/eui64
+.\" into their component parts.
+.Pp
+The
+.Fn eui64_aton
+function converts an
+.Tn ASCII
+representation of an EUI-64 into an
+.Vt eui64
+structure.
+Likewise,
+.Fn eui64_ntoa
+converts an EUI-64 specified as an
+.Vt eui64
+structure into an
+.Tn ASCII
+string.
+.Pp
+The
+.Fn eui64_ntohost
+and
+.Fn eui64_hostton
+functions map EUI-64s to their corresponding hostnames
+as specified in the
+.Pa /etc/eui64
+database.
+The
+.Fn eui64_ntohost
+function
+converts from EUI-64 to hostname, and
+.Fn eui64_hostton
+converts from hostname to EUI-64.
+.Sh RETURN VALUES
+.\" The
+.\" .Fn eui64_line
+.\" function
+.\" returns zero on success and non-zero if it was unable to parse
+.\" any part of the supplied line
+.\" .Fa l .
+.\" It returns the extracted EUI-64 in the supplied
+.\" .Vt eui64
+.\" structure
+.\" .Fa e
+.\" and the hostname in the supplied string
+.\" .Fa h .
+.\" .Pp
+On success,
+.Fn eui64_ntoa
+returns a pointer to a string containing an
+.Tn ASCII
+representation of an EUI-64.
+If it is unable to convert
+the supplied
+.Vt eui64
+structure, it returns a
+.Dv NULL
+pointer.
+Likewise,
+.Fn eui64_aton
+returns a pointer to an
+.Vt eui64
+structure on success and a
+.Dv NULL
+pointer on failure.
+.Pp
+The
+.Fn eui64_ntohost
+and
+.Fn eui64_hostton
+functions both return zero on success or non-zero if they were
+unable to find a match in the
+.Pa /etc/eui64
+database.
+.Sh NOTES
+The user must ensure that the hostname strings passed to the
+.\" .Fn eui64_line ,
+.Fn eui64_ntohost
+and
+.Fn eui64_hostton
+functions are large enough to contain the returned hostnames.
+.Sh NIS INTERACTION
+If the
+.Pa /etc/eui64
+contains a line with a single
+.Ql +
+in it, the
+.Fn eui64_ntohost
+and
+.Fn eui64_hostton
+functions will attempt to consult the NIS
+.Pa eui64.byname
+and
+.Pa eui64.byid
+maps in addition to the data in the
+.Pa /etc/eui64
+file.
+.Sh SEE ALSO
+.Xr firewire 4 ,
+.Xr eui64 5 ,
+.Xr yp 8
+.Sh HISTORY
+These functions first appears in
+.Fx 5.3 .
+They are derived from the
+.Xr ethers 3
+family of functions.
diff --git a/lib/libc/net/eui64.c b/lib/libc/net/eui64.c
new file mode 100644
index 0000000..5085167
--- /dev/null
+++ b/lib/libc/net/eui64.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright 2004 The Aerospace Corporation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions, and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions, and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of The Aerospace Corporation may not be used to endorse or
+ * promote products derived from this software.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AEROSPACE CORPORATION "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AEROSPACE CORPORATION BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Copyright (c) 1995
+ * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * EUI-64 conversion and lookup routines
+ *
+ *
+ * Converted from ether_addr.c rev
+ * FreeBSD: src/lib/libc/net/eui64.c,v 1.15 2002/04/08 07:51:10 ru Exp
+ * by Brooks Davis
+ *
+ * Written by Bill Paul <wpaul@ctr.columbia.edu>
+ * Center for Telecommunications Research
+ * Columbia University, New York City
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <paths.h>
+#include <sys/types.h>
+#include <sys/eui64.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/param.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+
+#ifndef _PATH_EUI64
+#define _PATH_EUI64 "/etc/eui64"
+#endif
+
+static int eui64_line(const char *l, struct eui64 *e, char *hostname,
+ size_t len);
+
+/*
+ * Parse a string of text containing an EUI-64 and hostname
+ * and separate it into its component parts.
+ */
+static int
+eui64_line(const char *l, struct eui64 *e, char *hostname, size_t len)
+{
+ char *line, *linehead, *cur;
+
+ linehead = strdup(l);
+ if (linehead == NULL)
+ return (-1);
+ line = linehead;
+
+ /* Find and parse the EUI64 */
+ while ((cur = strsep(&line, " \t\r\n")) != NULL) {
+ if (*cur != '\0') {
+ if (eui64_aton(cur, e) == 0)
+ break;
+ else
+ goto bad;
+ }
+ }
+
+ /* Find the hostname */
+ while ((cur = strsep(&line, " \t\r\n")) != NULL) {
+ if (*cur != '\0') {
+ if (strlcpy(hostname, cur, len) <= len)
+ break;
+ else
+ goto bad;
+ }
+ }
+
+ /* Make sure what remains is either whitespace or a comment */
+ while ((cur = strsep(&line, " \t\r\n")) != NULL) {
+ if (*cur == '#')
+ break;
+ if (*cur != '\0')
+ goto bad;
+ }
+
+ return (0);
+
+bad:
+ free(linehead);
+ return (-1);
+}
+
+/*
+ * Convert an ASCII representation of an EUI-64 to binary form.
+ */
+int
+eui64_aton(const char *a, struct eui64 *e)
+{
+ int i;
+ unsigned int o0, o1, o2, o3, o4, o5, o6, o7;
+
+ /* canonical form */
+ i = sscanf(a, "%x-%x-%x-%x-%x-%x-%x-%x",
+ &o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7);
+ if (i == EUI64_LEN)
+ goto good;
+ /* ethernet form */
+ i = sscanf(a, "%x:%x:%x:%x:%x:%x:%x:%x",
+ &o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7);
+ if (i == EUI64_LEN)
+ goto good;
+ /* classic fwcontrol/dconschat form */
+ i = sscanf(a, "0x%2x%2x%2x%2x%2x%2x%2x%2x",
+ &o0, &o1, &o2, &o3, &o4, &o5, &o6, &o7);
+ if (i == EUI64_LEN)
+ goto good;
+ /* MAC format (-) */
+ i = sscanf(a, "%x-%x-%x-%x-%x-%x",
+ &o0, &o1, &o2, &o5, &o6, &o7);
+ if (i == 6) {
+ o3 = 0xff;
+ o4 = 0xfe;
+ goto good;
+ }
+ /* MAC format (:) */
+ i = sscanf(a, "%x:%x:%x:%x:%x:%x",
+ &o0, &o1, &o2, &o5, &o6, &o7);
+ if (i == 6) {
+ o3 = 0xff;
+ o4 = 0xfe;
+ goto good;
+ }
+
+ return (-1);
+
+good:
+ e->octet[0]=o0;
+ e->octet[1]=o1;
+ e->octet[2]=o2;
+ e->octet[3]=o3;
+ e->octet[4]=o4;
+ e->octet[5]=o5;
+ e->octet[6]=o6;
+ e->octet[7]=o7;
+
+ return (0);
+}
+
+/*
+ * Convert a binary representation of an EUI-64 to an ASCII string.
+ */
+int
+eui64_ntoa(const struct eui64 *id, char *a, size_t len)
+{
+ int i;
+
+ i = snprintf(a, len, "%02x-%02x-%02x-%02x-%02x-%02x-%02x-%02x",
+ id->octet[0], id->octet[1], id->octet[2], id->octet[3],
+ id->octet[4], id->octet[5], id->octet[6], id->octet[7]);
+ if (i < 23 || i >= len)
+ return (-1);
+ return (0);
+}
+
+/*
+ * Map an EUI-64 to a hostname. Use either /etc/eui64 or NIS/YP.
+ */
+int
+eui64_ntohost(char *hostname, size_t len, const struct eui64 *id)
+{
+ FILE *fp;
+ char buf[BUFSIZ + 2];
+ struct eui64 local_eui64;
+ char local_host[MAXHOSTNAMELEN];
+#ifdef YP
+ char *result;
+ int resultlen;
+ char eui64_a[24];
+ char *yp_domain;
+#endif
+ if ((fp = fopen(_PATH_EUI64, "r")) == NULL)
+ return (1);
+
+ while (fgets(buf,BUFSIZ,fp)) {
+ if (buf[0] == '#')
+ continue;
+#ifdef YP
+ if (buf[0] == '+') {
+ if (yp_get_default_domain(&yp_domain))
+ continue;
+ eui64_ntoa(id, eui64_a, sizeof(eui64_a));
+ if (yp_match(yp_domain, "eui64.byid", eui64_a,
+ strlen(eui64_a), &result, &resultlen)) {
+ continue;
+ }
+ strncpy(buf, result, resultlen);
+ buf[resultlen] = '\0';
+ free(result);
+ }
+#endif
+ if (eui64_line(buf, &local_eui64, local_host,
+ sizeof(local_host)) == 0) {
+ if (bcmp(&local_eui64.octet[0],
+ &id->octet[0], EUI64_LEN) == 0) {
+ /* We have a match */
+ strcpy(hostname, local_host);
+ fclose(fp);
+ return(0);
+ }
+ }
+ }
+ fclose(fp);
+ return (1);
+}
+
+/*
+ * Map a hostname to an EUI-64 using /etc/eui64 or NIS/YP.
+ */
+int
+eui64_hostton(const char *hostname, struct eui64 *id)
+{
+ FILE *fp;
+ char buf[BUFSIZ + 2];
+ struct eui64 local_eui64;
+ char local_host[MAXHOSTNAMELEN];
+#ifdef YP
+ char *result;
+ int resultlen;
+ char *yp_domain;
+#endif
+ if ((fp = fopen(_PATH_EUI64, "r")) == NULL)
+ return (1);
+
+ while (fgets(buf,BUFSIZ,fp)) {
+ if (buf[0] == '#')
+ continue;
+#ifdef YP
+ if (buf[0] == '+') {
+ if (yp_get_default_domain(&yp_domain))
+ continue;
+ if (yp_match(yp_domain, "eui64.byname", hostname,
+ strlen(hostname), &result, &resultlen)) {
+ continue;
+ }
+ strncpy(buf, result, resultlen);
+ buf[resultlen] = '\0';
+ free(result);
+ }
+#endif
+ if (eui64_line(buf, &local_eui64, local_host,
+ sizeof(local_host)) == 0) {
+ if (strcmp(hostname, local_host) == 0) {
+ /* We have a match */
+ bcopy(&local_eui64, id, sizeof(struct eui64));
+ fclose(fp);
+ return(0);
+ }
+ }
+ }
+ fclose(fp);
+ return (1);
+}
diff --git a/lib/libc/net/gai_strerror.3 b/lib/libc/net/gai_strerror.3
new file mode 100644
index 0000000..25cff0c
--- /dev/null
+++ b/lib/libc/net/gai_strerror.3
@@ -0,0 +1,92 @@
+.\" $KAME: gai_strerror.3,v 1.1 2005/01/05 03:04:47 itojun Exp $
+.\" $OpenBSD: gai_strerror.3,v 1.4 2004/12/20 23:04:53 millert Exp $
+.\"
+.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+.\" PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd May 21, 2006
+.Dt GAI_STRERROR 3
+.Os
+.Sh NAME
+.Nm gai_strerror
+.Nd get error message string from EAI_xxx error code
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netdb.h
+.Ft "const char *"
+.Fn gai_strerror "int ecode"
+.Sh DESCRIPTION
+The
+.Fn gai_strerror
+function returns an error message string corresponding to the error code
+returned by
+.Xr getaddrinfo 3
+or
+.Xr getnameinfo 3 .
+.Pp
+The following error codes and their meaning are defined in
+.In netdb.h :
+.Pp
+.Bl -tag -width ".Dv EAI_BADFLAGS" -offset indent -compact
+.It Dv EAI_AGAIN
+temporary failure in name resolution
+.It Dv EAI_BADFLAGS
+invalid value for
+.Fa ai_flags
+.It Dv EAI_BADHINTS
+invalid value for
+.Fa hints
+.It Dv EAI_FAIL
+non-recoverable failure in name resolution
+.It Dv EAI_FAMILY
+.Fa ai_family
+not supported
+.It Dv EAI_MEMORY
+memory allocation failure
+.It Dv EAI_NONAME
+.Fa hostname
+or
+.Fa servname
+not provided, or not known
+.It Dv EAI_OVERFLOW
+argument buffer overflow
+.It Dv EAI_PROTOCOL
+resolved protocol is unknown
+.It Dv EAI_SERVICE
+.Fa servname
+not supported for
+.Fa ai_socktype
+.It Dv EAI_SOCKTYPE
+.Fa ai_socktype
+not supported
+.It Dv EAI_SYSTEM
+system error returned in
+.Va errno
+.El
+.Sh RETURN VALUES
+The
+.Fn gai_strerror
+function
+returns a pointer to the error message string corresponding to
+.Fa ecode .
+If
+.Fa ecode
+is out of range, an implementation-specific error message string is returned.
+.Sh SEE ALSO
+.Xr getaddrinfo 3 ,
+.Xr getnameinfo 3
diff --git a/lib/libc/net/gai_strerror.c b/lib/libc/net/gai_strerror.c
new file mode 100644
index 0000000..4f60f2d
--- /dev/null
+++ b/lib/libc/net/gai_strerror.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <netdb.h>
+#if defined(NLS)
+#include <nl_types.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <string.h>
+#include "reentrant.h"
+#endif
+#include "un-namespace.h"
+
+/* Entries EAI_ADDRFAMILY (1) and EAI_NODATA (7) are obsoleted, but left */
+/* for backward compatibility with userland code prior to 2553bis-02 */
+static const char *ai_errlist[] = {
+ "Success", /* 0 */
+ "Address family for hostname not supported", /* 1 */
+ "Temporary failure in name resolution", /* EAI_AGAIN */
+ "Invalid value for ai_flags", /* EAI_BADFLAGS */
+ "Non-recoverable failure in name resolution", /* EAI_FAIL */
+ "ai_family not supported", /* EAI_FAMILY */
+ "Memory allocation failure", /* EAI_MEMORY */
+ "No address associated with hostname", /* 7 */
+ "hostname nor servname provided, or not known", /* EAI_NONAME */
+ "servname not supported for ai_socktype", /* EAI_SERVICE */
+ "ai_socktype not supported", /* EAI_SOCKTYPE */
+ "System error returned in errno", /* EAI_SYSTEM */
+ "Invalid value for hints", /* EAI_BADHINTS */
+ "Resolved protocol is unknown", /* EAI_PROTOCOL */
+ "Argument buffer overflow" /* EAI_OVERFLOW */
+};
+
+#if defined(NLS)
+static char gai_buf[NL_TEXTMAX];
+static once_t gai_init_once = ONCE_INITIALIZER;
+static thread_key_t gai_key;
+static int gai_keycreated = 0;
+
+static void
+gai_keycreate(void)
+{
+ gai_keycreated = (thr_keycreate(&gai_key, free) == 0);
+}
+#endif
+
+const char *
+gai_strerror(int ecode)
+{
+#if defined(NLS)
+ nl_catd catd;
+ char *buf;
+
+ if (thr_main() != 0)
+ buf = gai_buf;
+ else {
+ if (thr_once(&gai_init_once, gai_keycreate) != 0 ||
+ !gai_keycreated)
+ goto thr_err;
+ if ((buf = thr_getspecific(gai_key)) == NULL) {
+ if ((buf = malloc(sizeof(gai_buf))) == NULL)
+ goto thr_err;
+ if (thr_setspecific(gai_key, buf) != 0) {
+ free(buf);
+ goto thr_err;
+ }
+ }
+ }
+
+ catd = catopen("libc", NL_CAT_LOCALE);
+ if (ecode > 0 && ecode < EAI_MAX)
+ strlcpy(buf, catgets(catd, 3, ecode, ai_errlist[ecode]),
+ sizeof(gai_buf));
+ else if (ecode == 0)
+ strlcpy(buf, catgets(catd, 3, NL_MSGMAX - 1, "Success"),
+ sizeof(gai_buf));
+ else
+ strlcpy(buf, catgets(catd, 3, NL_MSGMAX, "Unknown error"),
+ sizeof(gai_buf));
+ catclose(catd);
+ return buf;
+
+thr_err:
+#endif
+ if (ecode >= 0 && ecode < EAI_MAX)
+ return ai_errlist[ecode];
+ return "Unknown error";
+}
diff --git a/lib/libc/net/getaddrinfo.3 b/lib/libc/net/getaddrinfo.3
new file mode 100644
index 0000000..b09c068
--- /dev/null
+++ b/lib/libc/net/getaddrinfo.3
@@ -0,0 +1,461 @@
+.\" $KAME: getaddrinfo.3,v 1.36 2005/01/05 03:23:05 itojun Exp $
+.\" $OpenBSD: getaddrinfo.3,v 1.35 2004/12/21 03:40:31 jaredy Exp $
+.\"
+.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+.\" PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 6, 2009
+.Dt GETADDRINFO 3
+.Os
+.Sh NAME
+.Nm getaddrinfo ,
+.Nm freeaddrinfo
+.Nd socket address structure to host and service name
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <netdb.h>
+.Ft int
+.Fo getaddrinfo
+.Fa "const char *hostname" "const char *servname"
+.Fa "const struct addrinfo *hints" "struct addrinfo **res"
+.Fc
+.Ft void
+.Fn freeaddrinfo "struct addrinfo *ai"
+.Sh DESCRIPTION
+The
+.Fn getaddrinfo
+function is used to get a list of
+.Tn IP
+addresses and port numbers for host
+.Fa hostname
+and service
+.Fa servname .
+It is a replacement for and provides more flexibility than the
+.Xr gethostbyname 3
+and
+.Xr getservbyname 3
+functions.
+.Pp
+The
+.Fa hostname
+and
+.Fa servname
+arguments are either pointers to NUL-terminated strings or the null pointer.
+An acceptable value for
+.Fa hostname
+is either a valid host name or a numeric host address string consisting
+of a dotted decimal IPv4 address or an IPv6 address.
+The
+.Fa servname
+is either a decimal port number or a service name listed in
+.Xr services 5 .
+At least one of
+.Fa hostname
+and
+.Fa servname
+must be non-null.
+.Pp
+.Fa hints
+is an optional pointer to a
+.Li struct addrinfo ,
+as defined by
+.Aq Pa netdb.h :
+.Bd -literal
+struct addrinfo {
+ int ai_flags; /* input flags */
+ int ai_family; /* protocol family for socket */
+ int ai_socktype; /* socket type */
+ int ai_protocol; /* protocol for socket */
+ socklen_t ai_addrlen; /* length of socket-address */
+ struct sockaddr *ai_addr; /* socket-address for socket */
+ char *ai_canonname; /* canonical name for service location */
+ struct addrinfo *ai_next; /* pointer to next in list */
+};
+.Ed
+.Pp
+This structure can be used to provide hints concerning the type of socket
+that the caller supports or wishes to use.
+The caller can supply the following structure elements in
+.Fa hints :
+.Bl -tag -width "ai_socktypeXX"
+.It Fa ai_family
+The protocol family that should be used.
+When
+.Fa ai_family
+is set to
+.Dv PF_UNSPEC ,
+it means the caller will accept any protocol family supported by the
+operating system.
+.It Fa ai_socktype
+Denotes the type of socket that is wanted:
+.Dv SOCK_STREAM ,
+.Dv SOCK_DGRAM ,
+or
+.Dv SOCK_RAW .
+When
+.Fa ai_socktype
+is zero the caller will accept any socket type.
+.It Fa ai_protocol
+Indicates which transport protocol is desired,
+.Dv IPPROTO_UDP
+or
+.Dv IPPROTO_TCP .
+If
+.Fa ai_protocol
+is zero the caller will accept any protocol.
+.It Fa ai_flags
+The
+.Fa ai_flags
+field to which the
+.Fa hints
+parameter points shall be set to zero
+or be the bitwise-inclusive OR of one or more of the values
+.Dv AI_ADDRCONFIG ,
+.Dv AI_CANONNAME ,
+.Dv AI_NUMERICHOST ,
+.Dv AI_NUMERICSERV
+and
+.Dv AI_PASSIVE .
+.Bl -tag -width "AI_CANONNAMEXX"
+.It Dv AI_ADDRCONFIG
+If the
+.Dv AI_ADDRCONFIG
+bit is set, IPv4 addresses shall be returned only if
+an IPv4 address is configured on the local system,
+and IPv6 addresses shall be returned only if
+an IPv6 address is configured on the local system.
+.It Dv AI_CANONNAME
+If the
+.Dv AI_CANONNAME
+bit is set, a successful call to
+.Fn getaddrinfo
+will return a NUL-terminated string containing the canonical name
+of the specified hostname in the
+.Fa ai_canonname
+element of the first
+.Li addrinfo
+structure returned.
+.It Dv AI_NUMERICHOST
+If the
+.Dv AI_NUMERICHOST
+bit is set, it indicates that
+.Fa hostname
+should be treated as a numeric string defining an IPv4 or IPv6 address
+and no name resolution should be attempted.
+.It Dv AI_NUMERICSERV
+If the
+.Dv AI_NUMERICSERV
+bit is set,
+then a non-null
+.Fa servname
+string supplied shall be a numeric port string.
+Otherwise, an
+.Dv EAI_NONAME
+error shall be returned.
+This bit shall prevent any type of name resolution service
+(for example, NIS+) from being invoked.
+.It Dv AI_PASSIVE
+If the
+.Dv AI_PASSIVE
+bit is set it indicates that the returned socket address structure
+is intended for use in a call to
+.Xr bind 2 .
+In this case, if the
+.Fa hostname
+argument is the null pointer, then the IP address portion of the
+socket address structure will be set to
+.Dv INADDR_ANY
+for an IPv4 address or
+.Dv IN6ADDR_ANY_INIT
+for an IPv6 address.
+.Pp
+If the
+.Dv AI_PASSIVE
+bit is not set, the returned socket address structure will be ready
+for use in a call to
+.Xr connect 2
+for a connection-oriented protocol or
+.Xr connect 2 ,
+.Xr sendto 2 ,
+or
+.Xr sendmsg 2
+if a connectionless protocol was chosen.
+The
+.Tn IP
+address portion of the socket address structure will be set to the
+loopback address if
+.Fa hostname
+is the null pointer and
+.Dv AI_PASSIVE
+is not set.
+.El
+.El
+.Pp
+All other elements of the
+.Li addrinfo
+structure passed via
+.Fa hints
+must be zero or the null pointer.
+.Pp
+If
+.Fa hints
+is the null pointer,
+.Fn getaddrinfo
+behaves as if the caller provided a
+.Li struct addrinfo
+with
+.Fa ai_family
+set to
+.Dv PF_UNSPEC
+and all other elements set to zero or
+.Dv NULL .
+.Pp
+After a successful call to
+.Fn getaddrinfo ,
+.Fa *res
+is a pointer to a linked list of one or more
+.Li addrinfo
+structures.
+The list can be traversed by following the
+.Fa ai_next
+pointer in each
+.Li addrinfo
+structure until a null pointer is encountered.
+The three members
+.Fa ai_family,
+.Fa ai_socktype,
+and
+.Fa ai_protocol
+in each returned
+.Li addrinfo
+structure are suitable for a call to
+.Xr socket 2 .
+For each
+.Li addrinfo
+structure in the list, the
+.Fa ai_addr
+member points to a filled-in socket address structure of length
+.Fa ai_addrlen .
+.Pp
+This implementation of
+.Fn getaddrinfo
+allows numeric IPv6 address notation with scope identifier,
+as documented in chapter 11 of draft-ietf-ipv6-scoping-arch-02.txt.
+By appending the percent character and scope identifier to addresses,
+one can fill the
+.Li sin6_scope_id
+field for addresses.
+This would make management of scoped addresses easier
+and allows cut-and-paste input of scoped addresses.
+.Pp
+At this moment the code supports only link-local addresses with the format.
+The scope identifier is hardcoded to the name of the hardware interface
+associated
+with the link
+.Po
+such as
+.Li ne0
+.Pc .
+An example is
+.Dq Li fe80::1%ne0 ,
+which means
+.Do
+.Li fe80::1
+on the link associated with the
+.Li ne0
+interface
+.Dc .
+.Pp
+The current implementation assumes a one-to-one relationship between
+the interface and link, which is not necessarily true from the specification.
+.Pp
+All of the information returned by
+.Fn getaddrinfo
+is dynamically allocated: the
+.Li addrinfo
+structures themselves as well as the socket address structures and
+the canonical host name strings included in the
+.Li addrinfo
+structures.
+.Pp
+Memory allocated for the dynamically allocated structures created by
+a successful call to
+.Fn getaddrinfo
+is released by the
+.Fn freeaddrinfo
+function.
+The
+.Fa ai
+pointer should be a
+.Li addrinfo
+structure created by a call to
+.Fn getaddrinfo .
+.Sh RETURN VALUES
+.Fn getaddrinfo
+returns zero on success or one of the error codes listed in
+.Xr gai_strerror 3
+if an error occurs.
+.Sh EXAMPLES
+The following code tries to connect to
+.Dq Li www.kame.net
+service
+.Dq Li http
+via a stream socket.
+It loops through all the addresses available, regardless of address family.
+If the destination resolves to an IPv4 address, it will use an
+.Dv AF_INET
+socket.
+Similarly, if it resolves to IPv6, an
+.Dv AF_INET6
+socket is used.
+Observe that there is no hardcoded reference to a particular address family.
+The code works even if
+.Fn getaddrinfo
+returns addresses that are not IPv4/v6.
+.Bd -literal -offset indent
+struct addrinfo hints, *res, *res0;
+int error;
+int s;
+const char *cause = NULL;
+
+memset(&hints, 0, sizeof(hints));
+hints.ai_family = PF_UNSPEC;
+hints.ai_socktype = SOCK_STREAM;
+error = getaddrinfo("www.kame.net", "http", &hints, &res0);
+if (error) {
+ errx(1, "%s", gai_strerror(error));
+ /*NOTREACHED*/
+}
+s = -1;
+for (res = res0; res; res = res->ai_next) {
+ s = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol);
+ if (s < 0) {
+ cause = "socket";
+ continue;
+ }
+
+ if (connect(s, res->ai_addr, res->ai_addrlen) < 0) {
+ cause = "connect";
+ close(s);
+ s = -1;
+ continue;
+ }
+
+ break; /* okay we got one */
+}
+if (s < 0) {
+ err(1, "%s", cause);
+ /*NOTREACHED*/
+}
+freeaddrinfo(res0);
+.Ed
+.Pp
+The following example tries to open a wildcard listening socket onto service
+.Dq Li http ,
+for all the address families available.
+.Bd -literal -offset indent
+struct addrinfo hints, *res, *res0;
+int error;
+int s[MAXSOCK];
+int nsock;
+const char *cause = NULL;
+
+memset(&hints, 0, sizeof(hints));
+hints.ai_family = PF_UNSPEC;
+hints.ai_socktype = SOCK_STREAM;
+hints.ai_flags = AI_PASSIVE;
+error = getaddrinfo(NULL, "http", &hints, &res0);
+if (error) {
+ errx(1, "%s", gai_strerror(error));
+ /*NOTREACHED*/
+}
+nsock = 0;
+for (res = res0; res && nsock < MAXSOCK; res = res->ai_next) {
+ s[nsock] = socket(res->ai_family, res->ai_socktype,
+ res->ai_protocol);
+ if (s[nsock] < 0) {
+ cause = "socket";
+ continue;
+ }
+
+ if (bind(s[nsock], res->ai_addr, res->ai_addrlen) < 0) {
+ cause = "bind";
+ close(s[nsock]);
+ continue;
+ }
+ (void) listen(s[nsock], 5);
+
+ nsock++;
+}
+if (nsock == 0) {
+ err(1, "%s", cause);
+ /*NOTREACHED*/
+}
+freeaddrinfo(res0);
+.Ed
+.Sh SEE ALSO
+.Xr bind 2 ,
+.Xr connect 2 ,
+.Xr send 2 ,
+.Xr socket 2 ,
+.Xr gai_strerror 3 ,
+.Xr gethostbyname 3 ,
+.Xr getnameinfo 3 ,
+.Xr getservbyname 3 ,
+.Xr resolver 3 ,
+.Xr hosts 5 ,
+.Xr resolv.conf 5 ,
+.Xr services 5 ,
+.Xr hostname 7 ,
+.Xr named 8
+.Rs
+.%A R. Gilligan
+.%A S. Thomson
+.%A J. Bound
+.%A J. McCann
+.%A W. Stevens
+.%T Basic Socket Interface Extensions for IPv6
+.%R RFC 3493
+.%D February 2003
+.Re
+.Rs
+.%A S. Deering
+.%A B. Haberman
+.%A T. Jinmei
+.%A E. Nordmark
+.%A B. Zill
+.%T "IPv6 Scoped Address Architecture"
+.%R internet draft
+.%N draft-ietf-ipv6-scoping-arch-02.txt
+.%O work in progress material
+.Re
+.Rs
+.%A Craig Metz
+.%T Protocol Independence Using the Sockets API
+.%B "Proceedings of the freenix track: 2000 USENIX annual technical conference"
+.%D June 2000
+.Re
+.Sh STANDARDS
+The
+.Fn getaddrinfo
+function is defined by the
+.St -p1003.1-2004
+specification and documented in
+.Dv "RFC 3493" ,
+.Dq Basic Socket Interface Extensions for IPv6 .
diff --git a/lib/libc/net/getaddrinfo.c b/lib/libc/net/getaddrinfo.c
new file mode 100644
index 0000000..8083c39
--- /dev/null
+++ b/lib/libc/net/getaddrinfo.c
@@ -0,0 +1,2847 @@
+/* $KAME: getaddrinfo.c,v 1.15 2000/07/09 04:37:24 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * "#ifdef FAITH" part is local hack for supporting IPv4-v6 translator.
+ *
+ * Issues to be discussed:
+ * - Return values. There are nonstandard return values defined and used
+ * in the source code. This is because RFC2553 is silent about which error
+ * code must be returned for which situation.
+ * - freeaddrinfo(NULL). RFC2553 is silent about it. XNET 5.2 says it is
+ * invalid. current code - SEGV on freeaddrinfo(NULL)
+ *
+ * Note:
+ * - The code filters out AFs that are not supported by the kernel,
+ * when globbing NULL hostname (to loopback, or wildcard). Is it the right
+ * thing to do? What is the relationship with post-RFC2553 AI_ADDRCONFIG
+ * in ai_flags?
+ * - (post-2553) semantics of AI_ADDRCONFIG itself is too vague.
+ * (1) what should we do against numeric hostname (2) what should we do
+ * against NULL hostname (3) what is AI_ADDRCONFIG itself. AF not ready?
+ * non-loopback address configured? global address configured?
+ *
+ * OS specific notes for freebsd4:
+ * - FreeBSD supported $GAI. The code does not.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <sys/queue.h>
+#ifdef INET6
+#include <net/if_var.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <netinet6/in6_var.h> /* XXX */
+#endif
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <ctype.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "res_config.h"
+
+#ifdef DEBUG
+#include <syslog.h>
+#endif
+
+#include <stdarg.h>
+#include <nsswitch.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+
+#if defined(__KAME__) && defined(INET6)
+# define FAITH
+#endif
+
+#define ANY 0
+#define YES 1
+#define NO 0
+
+static const char in_addrany[] = { 0, 0, 0, 0 };
+static const char in_loopback[] = { 127, 0, 0, 1 };
+#ifdef INET6
+static const char in6_addrany[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+};
+static const char in6_loopback[] = {
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1
+};
+#endif
+
+struct policyqueue {
+ TAILQ_ENTRY(policyqueue) pc_entry;
+#ifdef INET6
+ struct in6_addrpolicy pc_policy;
+#endif
+};
+TAILQ_HEAD(policyhead, policyqueue);
+
+static const struct afd {
+ int a_af;
+ int a_addrlen;
+ socklen_t a_socklen;
+ int a_off;
+ const char *a_addrany;
+ const char *a_loopback;
+ int a_scoped;
+} afdl [] = {
+#ifdef INET6
+#define N_INET6 0
+ {PF_INET6, sizeof(struct in6_addr),
+ sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr),
+ in6_addrany, in6_loopback, 1},
+#define N_INET 1
+#else
+#define N_INET 0
+#endif
+ {PF_INET, sizeof(struct in_addr),
+ sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr),
+ in_addrany, in_loopback, 0},
+ {0, 0, 0, 0, NULL, NULL, 0},
+};
+
+struct explore {
+ int e_af;
+ int e_socktype;
+ int e_protocol;
+ const char *e_protostr;
+ int e_wild;
+#define WILD_AF(ex) ((ex)->e_wild & 0x01)
+#define WILD_SOCKTYPE(ex) ((ex)->e_wild & 0x02)
+#define WILD_PROTOCOL(ex) ((ex)->e_wild & 0x04)
+};
+
+static const struct explore explore[] = {
+#if 0
+ { PF_LOCAL, ANY, ANY, NULL, 0x01 },
+#endif
+#ifdef INET6
+ { PF_INET6, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+ { PF_INET6, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+ { PF_INET6, SOCK_STREAM, IPPROTO_SCTP, "sctp", 0x03 },
+ { PF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP, "sctp", 0x07 },
+ { PF_INET6, SOCK_RAW, ANY, NULL, 0x05 },
+#endif
+ { PF_INET, SOCK_DGRAM, IPPROTO_UDP, "udp", 0x07 },
+ { PF_INET, SOCK_STREAM, IPPROTO_TCP, "tcp", 0x07 },
+ { PF_INET, SOCK_STREAM, IPPROTO_SCTP, "sctp", 0x03 },
+ { PF_INET, SOCK_SEQPACKET, IPPROTO_SCTP, "sctp", 0x07 },
+ { PF_INET, SOCK_RAW, ANY, NULL, 0x05 },
+ { -1, 0, 0, NULL, 0 },
+};
+
+#ifdef INET6
+#define PTON_MAX 16
+#else
+#define PTON_MAX 4
+#endif
+
+#define AIO_SRCFLAG_DEPRECATED 0x1
+
+struct ai_order {
+ union {
+ struct sockaddr_storage aiou_ss;
+ struct sockaddr aiou_sa;
+ } aio_src_un;
+#define aio_srcsa aio_src_un.aiou_sa
+ u_int32_t aio_srcflag;
+ int aio_srcscope;
+ int aio_dstscope;
+ struct policyqueue *aio_srcpolicy;
+ struct policyqueue *aio_dstpolicy;
+ struct addrinfo *aio_ai;
+ int aio_matchlen;
+};
+
+static const ns_src default_dns_files[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { NSSRC_DNS, NS_SUCCESS },
+ { 0 }
+};
+
+struct res_target {
+ struct res_target *next;
+ const char *name; /* domain name */
+ int qclass, qtype; /* class and type of query */
+ u_char *answer; /* buffer to put answer */
+ int anslen; /* size of answer buffer */
+ int n; /* result length */
+};
+
+#define MAXPACKET (64*1024)
+
+typedef union {
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+static int str2number(const char *, int *);
+static int explore_copy(const struct addrinfo *, const struct addrinfo *,
+ struct addrinfo **);
+static int explore_null(const struct addrinfo *,
+ const char *, struct addrinfo **);
+static int explore_numeric(const struct addrinfo *, const char *,
+ const char *, struct addrinfo **, const char *);
+static int explore_numeric_scope(const struct addrinfo *, const char *,
+ const char *, struct addrinfo **);
+static int get_canonname(const struct addrinfo *,
+ struct addrinfo *, const char *);
+static struct addrinfo *get_ai(const struct addrinfo *,
+ const struct afd *, const char *);
+static struct addrinfo *copy_ai(const struct addrinfo *);
+static int get_portmatch(const struct addrinfo *, const char *);
+static int get_port(struct addrinfo *, const char *, int);
+static const struct afd *find_afd(int);
+static int addrconfig(struct addrinfo *);
+static void set_source(struct ai_order *, struct policyhead *);
+static int comp_dst(const void *, const void *);
+#ifdef INET6
+static int ip6_str2scopeid(char *, struct sockaddr_in6 *, u_int32_t *);
+#endif
+static int gai_addr2scopetype(struct sockaddr *);
+
+static int explore_fqdn(const struct addrinfo *, const char *,
+ const char *, struct addrinfo **);
+
+static int reorder(struct addrinfo *);
+static int get_addrselectpolicy(struct policyhead *);
+static void free_addrselectpolicy(struct policyhead *);
+static struct policyqueue *match_addrselectpolicy(struct sockaddr *,
+ struct policyhead *);
+static int matchlen(struct sockaddr *, struct sockaddr *);
+
+static struct addrinfo *getanswer(const querybuf *, int, const char *, int,
+ const struct addrinfo *, res_state);
+#if defined(RESOLVSORT)
+static int addr4sort(struct addrinfo *, res_state);
+#endif
+static int _dns_getaddrinfo(void *, void *, va_list);
+static void _sethtent(FILE **);
+static void _endhtent(FILE **);
+static struct addrinfo *_gethtent(FILE **, const char *,
+ const struct addrinfo *);
+static int _files_getaddrinfo(void *, void *, va_list);
+#ifdef YP
+static struct addrinfo *_yphostent(char *, const struct addrinfo *);
+static int _yp_getaddrinfo(void *, void *, va_list);
+#endif
+#ifdef NS_CACHING
+static int addrinfo_id_func(char *, size_t *, va_list, void *);
+static int addrinfo_marshal_func(char *, size_t *, void *, va_list, void *);
+static int addrinfo_unmarshal_func(char *, size_t, void *, va_list, void *);
+#endif
+
+static int res_queryN(const char *, struct res_target *, res_state);
+static int res_searchN(const char *, struct res_target *, res_state);
+static int res_querydomainN(const char *, const char *,
+ struct res_target *, res_state);
+
+/* XXX macros that make external reference is BAD. */
+
+#define GET_AI(ai, afd, addr) \
+do { \
+ /* external reference: pai, error, and label free */ \
+ (ai) = get_ai(pai, (afd), (addr)); \
+ if ((ai) == NULL) { \
+ error = EAI_MEMORY; \
+ goto free; \
+ } \
+} while (/*CONSTCOND*/0)
+
+#define GET_PORT(ai, serv) \
+do { \
+ /* external reference: error and label free */ \
+ error = get_port((ai), (serv), 0); \
+ if (error != 0) \
+ goto free; \
+} while (/*CONSTCOND*/0)
+
+#define GET_CANONNAME(ai, str) \
+do { \
+ /* external reference: pai, error and label free */ \
+ error = get_canonname(pai, (ai), (str)); \
+ if (error != 0) \
+ goto free; \
+} while (/*CONSTCOND*/0)
+
+#define ERR(err) \
+do { \
+ /* external reference: error, and label bad */ \
+ error = (err); \
+ goto bad; \
+ /*NOTREACHED*/ \
+} while (/*CONSTCOND*/0)
+
+#define MATCH_FAMILY(x, y, w) \
+ ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == PF_UNSPEC || (y) == PF_UNSPEC)))
+#define MATCH(x, y, w) \
+ ((x) == (y) || (/*CONSTCOND*/(w) && ((x) == ANY || (y) == ANY)))
+
+void
+freeaddrinfo(struct addrinfo *ai)
+{
+ struct addrinfo *next;
+
+ do {
+ next = ai->ai_next;
+ if (ai->ai_canonname)
+ free(ai->ai_canonname);
+ /* no need to free(ai->ai_addr) */
+ free(ai);
+ ai = next;
+ } while (ai);
+}
+
+static int
+str2number(const char *p, int *portp)
+{
+ char *ep;
+ unsigned long v;
+
+ if (*p == '\0')
+ return -1;
+ ep = NULL;
+ errno = 0;
+ v = strtoul(p, &ep, 10);
+ if (errno == 0 && ep && *ep == '\0' && v <= UINT_MAX) {
+ *portp = v;
+ return 0;
+ } else
+ return -1;
+}
+
+int
+getaddrinfo(const char *hostname, const char *servname,
+ const struct addrinfo *hints, struct addrinfo **res)
+{
+ struct addrinfo sentinel;
+ struct addrinfo *cur;
+ int error = 0;
+ struct addrinfo ai, ai0, *afai;
+ struct addrinfo *pai;
+ const struct afd *afd;
+ const struct explore *ex;
+ struct addrinfo *afailist[sizeof(afdl)/sizeof(afdl[0])];
+ struct addrinfo *afai_unspec;
+ int found;
+ int numeric = 0;
+
+ /* ensure we return NULL on errors */
+ *res = NULL;
+
+ memset(&ai, 0, sizeof(ai));
+
+ memset(afailist, 0, sizeof(afailist));
+ afai_unspec = NULL;
+
+ memset(&sentinel, 0, sizeof(sentinel));
+ cur = &sentinel;
+ pai = &ai;
+ pai->ai_flags = 0;
+ pai->ai_family = PF_UNSPEC;
+ pai->ai_socktype = ANY;
+ pai->ai_protocol = ANY;
+ pai->ai_addrlen = 0;
+ pai->ai_canonname = NULL;
+ pai->ai_addr = NULL;
+ pai->ai_next = NULL;
+
+ if (hostname == NULL && servname == NULL)
+ return EAI_NONAME;
+ if (hints) {
+ /* error check for hints */
+ if (hints->ai_addrlen || hints->ai_canonname ||
+ hints->ai_addr || hints->ai_next)
+ ERR(EAI_BADHINTS); /* xxx */
+ if (hints->ai_flags & ~AI_MASK)
+ ERR(EAI_BADFLAGS);
+ switch (hints->ai_family) {
+ case PF_UNSPEC:
+ case PF_INET:
+#ifdef INET6
+ case PF_INET6:
+#endif
+ break;
+ default:
+ ERR(EAI_FAMILY);
+ }
+ memcpy(pai, hints, sizeof(*pai));
+
+ /*
+ * if both socktype/protocol are specified, check if they
+ * are meaningful combination.
+ */
+ if (pai->ai_socktype != ANY && pai->ai_protocol != ANY) {
+ for (ex = explore; ex->e_af >= 0; ex++) {
+ if (!MATCH_FAMILY(pai->ai_family, ex->e_af,
+ WILD_AF(ex)))
+ continue;
+ if (!MATCH(pai->ai_socktype, ex->e_socktype,
+ WILD_SOCKTYPE(ex)))
+ continue;
+ if (!MATCH(pai->ai_protocol, ex->e_protocol,
+ WILD_PROTOCOL(ex)))
+ continue;
+
+ /* matched */
+ break;
+ }
+
+ if (ex->e_af < 0)
+ ERR(EAI_BADHINTS);
+ }
+ }
+
+ /*
+ * check for special cases. (1) numeric servname is disallowed if
+ * socktype/protocol are left unspecified. (2) servname is disallowed
+ * for raw and other inet{,6} sockets.
+ */
+ if (MATCH_FAMILY(pai->ai_family, PF_INET, 1)
+#ifdef PF_INET6
+ || MATCH_FAMILY(pai->ai_family, PF_INET6, 1)
+#endif
+ ) {
+ ai0 = *pai; /* backup *pai */
+
+ if (pai->ai_family == PF_UNSPEC) {
+#ifdef PF_INET6
+ pai->ai_family = PF_INET6;
+#else
+ pai->ai_family = PF_INET;
+#endif
+ }
+ error = get_portmatch(pai, servname);
+ if (error)
+ ERR(error);
+
+ *pai = ai0;
+ }
+
+ ai0 = *pai;
+
+ /*
+ * NULL hostname, or numeric hostname.
+ * If numeric representation of AF1 can be interpreted as FQDN
+ * representation of AF2, we need to think again about the code below.
+ */
+ found = 0;
+ for (afd = afdl; afd->a_af; afd++) {
+ *pai = ai0;
+
+ if (!MATCH_FAMILY(pai->ai_family, afd->a_af, 1))
+ continue;
+
+ if (pai->ai_family == PF_UNSPEC)
+ pai->ai_family = afd->a_af;
+
+ if (hostname == NULL) {
+ error = explore_null(pai, servname,
+ &afailist[afd - afdl]);
+
+ /*
+ * Errors from explore_null should be unexpected and
+ * be caught to avoid returning an incomplete result.
+ */
+ if (error != 0)
+ goto bad;
+ } else {
+ error = explore_numeric_scope(pai, hostname, servname,
+ &afailist[afd - afdl]);
+
+ /*
+ * explore_numeric_scope returns an error for address
+ * families that do not match that of hostname.
+ * Thus we should not catch the error at this moment.
+ */
+ }
+
+ if (!error && afailist[afd - afdl])
+ found++;
+ }
+ if (found) {
+ numeric = 1;
+ goto globcopy;
+ }
+
+ if (hostname == NULL)
+ ERR(EAI_NONAME); /* used to be EAI_NODATA */
+ if (pai->ai_flags & AI_NUMERICHOST)
+ ERR(EAI_NONAME);
+
+ if ((pai->ai_flags & AI_ADDRCONFIG) != 0 && !addrconfig(&ai0))
+ ERR(EAI_FAIL);
+
+ /*
+ * hostname as alphabetical name.
+ */
+ *pai = ai0;
+ error = explore_fqdn(pai, hostname, servname, &afai_unspec);
+
+globcopy:
+ for (ex = explore; ex->e_af >= 0; ex++) {
+ *pai = ai0;
+
+ if (!MATCH_FAMILY(pai->ai_family, ex->e_af, WILD_AF(ex)))
+ continue;
+ if (!MATCH(pai->ai_socktype, ex->e_socktype,
+ WILD_SOCKTYPE(ex)))
+ continue;
+ if (!MATCH(pai->ai_protocol, ex->e_protocol,
+ WILD_PROTOCOL(ex)))
+ continue;
+
+ if (pai->ai_family == PF_UNSPEC)
+ pai->ai_family = ex->e_af;
+ if (pai->ai_socktype == ANY && ex->e_socktype != ANY)
+ pai->ai_socktype = ex->e_socktype;
+ if (pai->ai_protocol == ANY && ex->e_protocol != ANY)
+ pai->ai_protocol = ex->e_protocol;
+
+ /*
+ * if the servname does not match socktype/protocol, ignore it.
+ */
+ if (get_portmatch(pai, servname) != 0)
+ continue;
+
+ if (afai_unspec)
+ afai = afai_unspec;
+ else {
+ if ((afd = find_afd(pai->ai_family)) == NULL)
+ continue;
+ /* XXX assumes that afd points inside afdl[] */
+ afai = afailist[afd - afdl];
+ }
+ if (!afai)
+ continue;
+
+ error = explore_copy(pai, afai, &cur->ai_next);
+ if (error != 0)
+ goto bad;
+
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+
+ /*
+ * ensure we return either:
+ * - error == 0, non-NULL *res
+ * - error != 0, NULL *res
+ */
+ if (error == 0) {
+ if (sentinel.ai_next) {
+ /*
+ * If the returned entry is for an active connection,
+ * and the given name is not numeric, reorder the
+ * list, so that the application would try the list
+ * in the most efficient order. Since the head entry
+ * of the original list may contain ai_canonname and
+ * that entry may be moved elsewhere in the new list,
+ * we keep the pointer and will restore it in the new
+ * head entry. (Note that RFC3493 requires the head
+ * entry store it when requested by the caller).
+ */
+ if (hints == NULL || !(hints->ai_flags & AI_PASSIVE)) {
+ if (!numeric) {
+ char *canonname;
+
+ canonname =
+ sentinel.ai_next->ai_canonname;
+ sentinel.ai_next->ai_canonname = NULL;
+ (void)reorder(&sentinel);
+ if (sentinel.ai_next->ai_canonname ==
+ NULL) {
+ sentinel.ai_next->ai_canonname
+ = canonname;
+ } else if (canonname != NULL)
+ free(canonname);
+ }
+ }
+ *res = sentinel.ai_next;
+ } else
+ error = EAI_FAIL;
+ }
+
+bad:
+ if (afai_unspec)
+ freeaddrinfo(afai_unspec);
+ for (afd = afdl; afd->a_af; afd++) {
+ if (afailist[afd - afdl])
+ freeaddrinfo(afailist[afd - afdl]);
+ }
+ if (!*res)
+ if (sentinel.ai_next)
+ freeaddrinfo(sentinel.ai_next);
+
+ return (error);
+}
+
+static int
+reorder(struct addrinfo *sentinel)
+{
+ struct addrinfo *ai, **aip;
+ struct ai_order *aio;
+ int i, n;
+ struct policyhead policyhead;
+
+ /* count the number of addrinfo elements for sorting. */
+ for (n = 0, ai = sentinel->ai_next; ai != NULL; ai = ai->ai_next, n++)
+ ;
+
+ /*
+ * If the number is small enough, we can skip the reordering process.
+ */
+ if (n <= 1)
+ return(n);
+
+ /* allocate a temporary array for sort and initialization of it. */
+ if ((aio = malloc(sizeof(*aio) * n)) == NULL)
+ return(n); /* give up reordering */
+ memset(aio, 0, sizeof(*aio) * n);
+
+ /* retrieve address selection policy from the kernel */
+ TAILQ_INIT(&policyhead);
+ if (!get_addrselectpolicy(&policyhead)) {
+ /* no policy is installed into kernel, we don't sort. */
+ free(aio);
+ return (n);
+ }
+
+ for (i = 0, ai = sentinel->ai_next; i < n; ai = ai->ai_next, i++) {
+ aio[i].aio_ai = ai;
+ aio[i].aio_dstscope = gai_addr2scopetype(ai->ai_addr);
+ aio[i].aio_dstpolicy = match_addrselectpolicy(ai->ai_addr,
+ &policyhead);
+ set_source(&aio[i], &policyhead);
+ }
+
+ /* perform sorting. */
+ qsort(aio, n, sizeof(*aio), comp_dst);
+
+ /* reorder the addrinfo chain. */
+ for (i = 0, aip = &sentinel->ai_next; i < n; i++) {
+ *aip = aio[i].aio_ai;
+ aip = &aio[i].aio_ai->ai_next;
+ }
+ *aip = NULL;
+
+ /* cleanup and return */
+ free(aio);
+ free_addrselectpolicy(&policyhead);
+ return(n);
+}
+
+static int
+get_addrselectpolicy(struct policyhead *head)
+{
+#ifdef INET6
+ int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY };
+ size_t l;
+ char *buf;
+ struct in6_addrpolicy *pol, *ep;
+
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0)
+ return (0);
+ if ((buf = malloc(l)) == NULL)
+ return (0);
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
+ free(buf);
+ return (0);
+ }
+
+ ep = (struct in6_addrpolicy *)(buf + l);
+ for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) {
+ struct policyqueue *new;
+
+ if ((new = malloc(sizeof(*new))) == NULL) {
+ free_addrselectpolicy(head); /* make the list empty */
+ break;
+ }
+ new->pc_policy = *pol;
+ TAILQ_INSERT_TAIL(head, new, pc_entry);
+ }
+
+ free(buf);
+ return (1);
+#else
+ return (0);
+#endif
+}
+
+static void
+free_addrselectpolicy(struct policyhead *head)
+{
+ struct policyqueue *ent, *nent;
+
+ for (ent = TAILQ_FIRST(head); ent; ent = nent) {
+ nent = TAILQ_NEXT(ent, pc_entry);
+ TAILQ_REMOVE(head, ent, pc_entry);
+ free(ent);
+ }
+}
+
+static struct policyqueue *
+match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head)
+{
+#ifdef INET6
+ struct policyqueue *ent, *bestent = NULL;
+ struct in6_addrpolicy *pol;
+ int matchlen, bestmatchlen = -1;
+ u_char *mp, *ep, *k, *p, m;
+ struct sockaddr_in6 key;
+
+ switch(addr->sa_family) {
+ case AF_INET6:
+ key = *(struct sockaddr_in6 *)addr;
+ break;
+ case AF_INET:
+ /* convert the address into IPv4-mapped IPv6 address. */
+ memset(&key, 0, sizeof(key));
+ key.sin6_family = AF_INET6;
+ key.sin6_len = sizeof(key);
+ key.sin6_addr.s6_addr[10] = 0xff;
+ key.sin6_addr.s6_addr[11] = 0xff;
+ memcpy(&key.sin6_addr.s6_addr[12],
+ &((struct sockaddr_in *)addr)->sin_addr, 4);
+ break;
+ default:
+ return(NULL);
+ }
+
+ for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) {
+ pol = &ent->pc_policy;
+ matchlen = 0;
+
+ mp = (u_char *)&pol->addrmask.sin6_addr;
+ ep = mp + 16; /* XXX: scope field? */
+ k = (u_char *)&key.sin6_addr;
+ p = (u_char *)&pol->addr.sin6_addr;
+ for (; mp < ep && *mp; mp++, k++, p++) {
+ m = *mp;
+ if ((*k & m) != *p)
+ goto next; /* not match */
+ if (m == 0xff) /* short cut for a typical case */
+ matchlen += 8;
+ else {
+ while (m >= 0x80) {
+ matchlen++;
+ m <<= 1;
+ }
+ }
+ }
+
+ /* matched. check if this is better than the current best. */
+ if (matchlen > bestmatchlen) {
+ bestent = ent;
+ bestmatchlen = matchlen;
+ }
+
+ next:
+ continue;
+ }
+
+ return(bestent);
+#else
+ return(NULL);
+#endif
+
+}
+
+static void
+set_source(struct ai_order *aio, struct policyhead *ph)
+{
+ struct addrinfo ai = *aio->aio_ai;
+ struct sockaddr_storage ss;
+ socklen_t srclen;
+ int s;
+
+ /* set unspec ("no source is available"), just in case */
+ aio->aio_srcsa.sa_family = AF_UNSPEC;
+ aio->aio_srcscope = -1;
+
+ switch(ai.ai_family) {
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
+ break;
+ default: /* ignore unsupported AFs explicitly */
+ return;
+ }
+
+ /* XXX: make a dummy addrinfo to call connect() */
+ ai.ai_socktype = SOCK_DGRAM;
+ ai.ai_protocol = IPPROTO_UDP; /* is UDP too specific? */
+ ai.ai_next = NULL;
+ memset(&ss, 0, sizeof(ss));
+ memcpy(&ss, ai.ai_addr, ai.ai_addrlen);
+ ai.ai_addr = (struct sockaddr *)&ss;
+ get_port(&ai, "1", 0);
+
+ /* open a socket to get the source address for the given dst */
+ if ((s = _socket(ai.ai_family, ai.ai_socktype, ai.ai_protocol)) < 0)
+ return; /* give up */
+ if (_connect(s, ai.ai_addr, ai.ai_addrlen) < 0)
+ goto cleanup;
+ srclen = ai.ai_addrlen;
+ if (_getsockname(s, &aio->aio_srcsa, &srclen) < 0) {
+ aio->aio_srcsa.sa_family = AF_UNSPEC;
+ goto cleanup;
+ }
+ aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa);
+ aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph);
+ aio->aio_matchlen = matchlen(&aio->aio_srcsa, aio->aio_ai->ai_addr);
+#ifdef INET6
+ if (ai.ai_family == AF_INET6) {
+ struct in6_ifreq ifr6;
+ u_int32_t flags6;
+
+ memset(&ifr6, 0, sizeof(ifr6));
+ memcpy(&ifr6.ifr_addr, ai.ai_addr, ai.ai_addrlen);
+ if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) {
+ flags6 = ifr6.ifr_ifru.ifru_flags6;
+ if ((flags6 & IN6_IFF_DEPRECATED))
+ aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED;
+ }
+ }
+#endif
+
+ cleanup:
+ _close(s);
+ return;
+}
+
+static int
+matchlen(struct sockaddr *src, struct sockaddr *dst)
+{
+ int match = 0;
+ u_char *s, *d;
+ u_char *lim, r;
+ int addrlen;
+
+ switch (src->sa_family) {
+#ifdef INET6
+ case AF_INET6:
+ s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr;
+ d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr;
+ addrlen = sizeof(struct in6_addr);
+ lim = s + addrlen;
+ break;
+#endif
+ case AF_INET:
+ s = (u_char *)&((struct sockaddr_in *)src)->sin_addr;
+ d = (u_char *)&((struct sockaddr_in *)dst)->sin_addr;
+ addrlen = sizeof(struct in_addr);
+ lim = s + addrlen;
+ break;
+ default:
+ return(0);
+ }
+
+ while (s < lim)
+ if ((r = (*d++ ^ *s++)) != 0) {
+ while (r < addrlen * 8) {
+ match++;
+ r <<= 1;
+ }
+ break;
+ } else
+ match += 8;
+ return(match);
+}
+
+static int
+comp_dst(const void *arg1, const void *arg2)
+{
+ const struct ai_order *dst1 = arg1, *dst2 = arg2;
+
+ /*
+ * Rule 1: Avoid unusable destinations.
+ * XXX: we currently do not consider if an appropriate route exists.
+ */
+ if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
+ dst2->aio_srcsa.sa_family == AF_UNSPEC) {
+ return(-1);
+ }
+ if (dst1->aio_srcsa.sa_family == AF_UNSPEC &&
+ dst2->aio_srcsa.sa_family != AF_UNSPEC) {
+ return(1);
+ }
+
+ /* Rule 2: Prefer matching scope. */
+ if (dst1->aio_dstscope == dst1->aio_srcscope &&
+ dst2->aio_dstscope != dst2->aio_srcscope) {
+ return(-1);
+ }
+ if (dst1->aio_dstscope != dst1->aio_srcscope &&
+ dst2->aio_dstscope == dst2->aio_srcscope) {
+ return(1);
+ }
+
+ /* Rule 3: Avoid deprecated addresses. */
+ if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
+ dst2->aio_srcsa.sa_family != AF_UNSPEC) {
+ if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
+ (dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
+ return(-1);
+ }
+ if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
+ !(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
+ return(1);
+ }
+ }
+
+ /* Rule 4: Prefer home addresses. */
+ /* XXX: not implemented yet */
+
+ /* Rule 5: Prefer matching label. */
+#ifdef INET6
+ if (dst1->aio_srcpolicy && dst1->aio_dstpolicy &&
+ dst1->aio_srcpolicy->pc_policy.label ==
+ dst1->aio_dstpolicy->pc_policy.label &&
+ (dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL ||
+ dst2->aio_srcpolicy->pc_policy.label !=
+ dst2->aio_dstpolicy->pc_policy.label)) {
+ return(-1);
+ }
+ if (dst2->aio_srcpolicy && dst2->aio_dstpolicy &&
+ dst2->aio_srcpolicy->pc_policy.label ==
+ dst2->aio_dstpolicy->pc_policy.label &&
+ (dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL ||
+ dst1->aio_srcpolicy->pc_policy.label !=
+ dst1->aio_dstpolicy->pc_policy.label)) {
+ return(1);
+ }
+#endif
+
+ /* Rule 6: Prefer higher precedence. */
+#ifdef INET6
+ if (dst1->aio_dstpolicy &&
+ (dst2->aio_dstpolicy == NULL ||
+ dst1->aio_dstpolicy->pc_policy.preced >
+ dst2->aio_dstpolicy->pc_policy.preced)) {
+ return(-1);
+ }
+ if (dst2->aio_dstpolicy &&
+ (dst1->aio_dstpolicy == NULL ||
+ dst2->aio_dstpolicy->pc_policy.preced >
+ dst1->aio_dstpolicy->pc_policy.preced)) {
+ return(1);
+ }
+#endif
+
+ /* Rule 7: Prefer native transport. */
+ /* XXX: not implemented yet */
+
+ /* Rule 8: Prefer smaller scope. */
+ if (dst1->aio_dstscope >= 0 &&
+ dst1->aio_dstscope < dst2->aio_dstscope) {
+ return(-1);
+ }
+ if (dst2->aio_dstscope >= 0 &&
+ dst2->aio_dstscope < dst1->aio_dstscope) {
+ return(1);
+ }
+
+ /*
+ * Rule 9: Use longest matching prefix.
+ * We compare the match length in a same AF only.
+ */
+ if (dst1->aio_ai->ai_addr->sa_family ==
+ dst2->aio_ai->ai_addr->sa_family) {
+ if (dst1->aio_matchlen > dst2->aio_matchlen) {
+ return(-1);
+ }
+ if (dst1->aio_matchlen < dst2->aio_matchlen) {
+ return(1);
+ }
+ }
+
+ /* Rule 10: Otherwise, leave the order unchanged. */
+ return(-1);
+}
+
+/*
+ * Copy from scope.c.
+ * XXX: we should standardize the functions and link them as standard
+ * library.
+ */
+static int
+gai_addr2scopetype(struct sockaddr *sa)
+{
+#ifdef INET6
+ struct sockaddr_in6 *sa6;
+#endif
+ struct sockaddr_in *sa4;
+
+ switch(sa->sa_family) {
+#ifdef INET6
+ case AF_INET6:
+ sa6 = (struct sockaddr_in6 *)sa;
+ if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) {
+ /* just use the scope field of the multicast address */
+ return(sa6->sin6_addr.s6_addr[2] & 0x0f);
+ }
+ /*
+ * Unicast addresses: map scope type to corresponding scope
+ * value defined for multcast addresses.
+ * XXX: hardcoded scope type values are bad...
+ */
+ if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr))
+ return(1); /* node local scope */
+ if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr))
+ return(2); /* link-local scope */
+ if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr))
+ return(5); /* site-local scope */
+ return(14); /* global scope */
+ break;
+#endif
+ case AF_INET:
+ /*
+ * IPv4 pseudo scoping according to RFC 3484.
+ */
+ sa4 = (struct sockaddr_in *)sa;
+ /* IPv4 autoconfiguration addresses have link-local scope. */
+ if (((u_char *)&sa4->sin_addr)[0] == 169 &&
+ ((u_char *)&sa4->sin_addr)[1] == 254)
+ return(2);
+ /* Private addresses have site-local scope. */
+ if (((u_char *)&sa4->sin_addr)[0] == 10 ||
+ (((u_char *)&sa4->sin_addr)[0] == 172 &&
+ (((u_char *)&sa4->sin_addr)[1] & 0xf0) == 16) ||
+ (((u_char *)&sa4->sin_addr)[0] == 192 &&
+ ((u_char *)&sa4->sin_addr)[1] == 168))
+ return(14); /* XXX: It should be 5 unless NAT */
+ /* Loopback addresses have link-local scope. */
+ if (((u_char *)&sa4->sin_addr)[0] == 127)
+ return(2);
+ return(14);
+ break;
+ default:
+ errno = EAFNOSUPPORT; /* is this a good error? */
+ return(-1);
+ }
+}
+
+static int
+explore_copy(const struct addrinfo *pai, const struct addrinfo *src0,
+ struct addrinfo **res)
+{
+ int error;
+ struct addrinfo sentinel, *cur;
+ const struct addrinfo *src;
+
+ error = 0;
+ sentinel.ai_next = NULL;
+ cur = &sentinel;
+
+ for (src = src0; src != NULL; src = src->ai_next) {
+ if (src->ai_family != pai->ai_family)
+ continue;
+
+ cur->ai_next = copy_ai(src);
+ if (!cur->ai_next) {
+ error = EAI_MEMORY;
+ goto fail;
+ }
+
+ cur->ai_next->ai_socktype = pai->ai_socktype;
+ cur->ai_next->ai_protocol = pai->ai_protocol;
+ cur = cur->ai_next;
+ }
+
+ *res = sentinel.ai_next;
+ return 0;
+
+fail:
+ freeaddrinfo(sentinel.ai_next);
+ return error;
+}
+
+/*
+ * hostname == NULL.
+ * passive socket -> anyaddr (0.0.0.0 or ::)
+ * non-passive socket -> localhost (127.0.0.1 or ::1)
+ */
+static int
+explore_null(const struct addrinfo *pai, const char *servname,
+ struct addrinfo **res)
+{
+ int s;
+ const struct afd *afd;
+ struct addrinfo *ai;
+ int error;
+
+ *res = NULL;
+ ai = NULL;
+
+ /*
+ * filter out AFs that are not supported by the kernel
+ * XXX errno?
+ */
+ s = _socket(pai->ai_family, SOCK_DGRAM, 0);
+ if (s < 0) {
+ if (errno != EMFILE)
+ return 0;
+ } else
+ _close(s);
+
+ afd = find_afd(pai->ai_family);
+ if (afd == NULL)
+ return 0;
+
+ if (pai->ai_flags & AI_PASSIVE) {
+ GET_AI(ai, afd, afd->a_addrany);
+ GET_PORT(ai, servname);
+ } else {
+ GET_AI(ai, afd, afd->a_loopback);
+ GET_PORT(ai, servname);
+ }
+
+ *res = ai;
+ return 0;
+
+free:
+ if (ai != NULL)
+ freeaddrinfo(ai);
+ return error;
+}
+
+/*
+ * numeric hostname
+ */
+static int
+explore_numeric(const struct addrinfo *pai, const char *hostname,
+ const char *servname, struct addrinfo **res, const char *canonname)
+{
+ const struct afd *afd;
+ struct addrinfo *ai;
+ int error;
+ char pton[PTON_MAX];
+
+ *res = NULL;
+ ai = NULL;
+
+ afd = find_afd(pai->ai_family);
+ if (afd == NULL)
+ return 0;
+
+ switch (afd->a_af) {
+ case AF_INET:
+ /*
+ * RFC3493 requires getaddrinfo() to accept AF_INET formats
+ * that are accepted by inet_addr() and its family. The
+ * accepted forms includes the "classful" one, which inet_pton
+ * does not accept. So we need to separate the case for
+ * AF_INET.
+ */
+ if (inet_aton(hostname, (struct in_addr *)pton) != 1)
+ return 0;
+ break;
+ default:
+ if (inet_pton(afd->a_af, hostname, pton) != 1)
+ return 0;
+ break;
+ }
+
+ if (pai->ai_family == afd->a_af) {
+ GET_AI(ai, afd, pton);
+ GET_PORT(ai, servname);
+ if ((pai->ai_flags & AI_CANONNAME)) {
+ /*
+ * Set the numeric address itself as the canonical
+ * name, based on a clarification in RFC3493.
+ */
+ GET_CANONNAME(ai, canonname);
+ }
+ } else {
+ /*
+ * XXX: This should not happen since we already matched the AF
+ * by find_afd.
+ */
+ ERR(EAI_FAMILY);
+ }
+
+ *res = ai;
+ return 0;
+
+free:
+bad:
+ if (ai != NULL)
+ freeaddrinfo(ai);
+ return error;
+}
+
+/*
+ * numeric hostname with scope
+ */
+static int
+explore_numeric_scope(const struct addrinfo *pai, const char *hostname,
+ const char *servname, struct addrinfo **res)
+{
+#if !defined(SCOPE_DELIMITER) || !defined(INET6)
+ return explore_numeric(pai, hostname, servname, res, hostname);
+#else
+ const struct afd *afd;
+ struct addrinfo *cur;
+ int error;
+ char *cp, *hostname2 = NULL, *scope, *addr;
+ struct sockaddr_in6 *sin6;
+
+ afd = find_afd(pai->ai_family);
+ if (afd == NULL)
+ return 0;
+
+ if (!afd->a_scoped)
+ return explore_numeric(pai, hostname, servname, res, hostname);
+
+ cp = strchr(hostname, SCOPE_DELIMITER);
+ if (cp == NULL)
+ return explore_numeric(pai, hostname, servname, res, hostname);
+
+ /*
+ * Handle special case of <scoped_address><delimiter><scope id>
+ */
+ hostname2 = strdup(hostname);
+ if (hostname2 == NULL)
+ return EAI_MEMORY;
+ /* terminate at the delimiter */
+ hostname2[cp - hostname] = '\0';
+ addr = hostname2;
+ scope = cp + 1;
+
+ error = explore_numeric(pai, addr, servname, res, hostname);
+ if (error == 0) {
+ u_int32_t scopeid;
+
+ for (cur = *res; cur; cur = cur->ai_next) {
+ if (cur->ai_family != AF_INET6)
+ continue;
+ sin6 = (struct sockaddr_in6 *)(void *)cur->ai_addr;
+ if (ip6_str2scopeid(scope, sin6, &scopeid) == -1) {
+ free(hostname2);
+ freeaddrinfo(*res);
+ *res = NULL;
+ return(EAI_NONAME); /* XXX: is return OK? */
+ }
+ sin6->sin6_scope_id = scopeid;
+ }
+ }
+
+ free(hostname2);
+
+ if (error && *res) {
+ freeaddrinfo(*res);
+ *res = NULL;
+ }
+ return error;
+#endif
+}
+
+static int
+get_canonname(const struct addrinfo *pai, struct addrinfo *ai, const char *str)
+{
+ if ((pai->ai_flags & AI_CANONNAME) != 0) {
+ ai->ai_canonname = strdup(str);
+ if (ai->ai_canonname == NULL)
+ return EAI_MEMORY;
+ }
+ return 0;
+}
+
+static struct addrinfo *
+get_ai(const struct addrinfo *pai, const struct afd *afd, const char *addr)
+{
+ char *p;
+ struct addrinfo *ai;
+#ifdef FAITH
+ struct in6_addr faith_prefix;
+ char *fp_str;
+ int translate = 0;
+#endif
+
+#ifdef FAITH
+ /*
+ * Transfrom an IPv4 addr into a special IPv6 addr format for
+ * IPv6->IPv4 translation gateway. (only TCP is supported now)
+ *
+ * +-----------------------------------+------------+
+ * | faith prefix part (12 bytes) | embedded |
+ * | | IPv4 addr part (4 bytes)
+ * +-----------------------------------+------------+
+ *
+ * faith prefix part is specified as ascii IPv6 addr format
+ * in environmental variable GAI.
+ * For FAITH to work correctly, routing to faith prefix must be
+ * setup toward a machine where a FAITH daemon operates.
+ * Also, the machine must enable some mechanizm
+ * (e.g. faith interface hack) to divert those packet with
+ * faith prefixed destination addr to user-land FAITH daemon.
+ */
+ fp_str = getenv("GAI");
+ if (fp_str && inet_pton(AF_INET6, fp_str, &faith_prefix) == 1 &&
+ afd->a_af == AF_INET && pai->ai_socktype == SOCK_STREAM) {
+ u_int32_t v4a;
+ u_int8_t v4a_top;
+
+ memcpy(&v4a, addr, sizeof v4a);
+ v4a_top = v4a >> IN_CLASSA_NSHIFT;
+ if (!IN_MULTICAST(v4a) && !IN_EXPERIMENTAL(v4a) &&
+ v4a_top != 0 && v4a != IN_LOOPBACKNET) {
+ afd = &afdl[N_INET6];
+ memcpy(&faith_prefix.s6_addr[12], addr,
+ sizeof(struct in_addr));
+ translate = 1;
+ }
+ }
+#endif
+
+ ai = (struct addrinfo *)malloc(sizeof(struct addrinfo)
+ + (afd->a_socklen));
+ if (ai == NULL)
+ return NULL;
+
+ memcpy(ai, pai, sizeof(struct addrinfo));
+ ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
+ memset(ai->ai_addr, 0, (size_t)afd->a_socklen);
+ ai->ai_addr->sa_len = afd->a_socklen;
+ ai->ai_addrlen = afd->a_socklen;
+ ai->ai_addr->sa_family = ai->ai_family = afd->a_af;
+ p = (char *)(void *)(ai->ai_addr);
+#ifdef FAITH
+ if (translate == 1)
+ memcpy(p + afd->a_off, &faith_prefix, (size_t)afd->a_addrlen);
+ else
+#endif
+ memcpy(p + afd->a_off, addr, (size_t)afd->a_addrlen);
+ return ai;
+}
+
+/* XXX need to malloc() the same way we do from other functions! */
+static struct addrinfo *
+copy_ai(const struct addrinfo *pai)
+{
+ struct addrinfo *ai;
+ size_t l;
+
+ l = sizeof(*ai) + pai->ai_addrlen;
+ if ((ai = (struct addrinfo *)malloc(l)) == NULL)
+ return NULL;
+ memset(ai, 0, l);
+ memcpy(ai, pai, sizeof(*ai));
+ ai->ai_addr = (struct sockaddr *)(void *)(ai + 1);
+ memcpy(ai->ai_addr, pai->ai_addr, pai->ai_addrlen);
+
+ if (pai->ai_canonname) {
+ l = strlen(pai->ai_canonname) + 1;
+ if ((ai->ai_canonname = malloc(l)) == NULL) {
+ free(ai);
+ return NULL;
+ }
+ strlcpy(ai->ai_canonname, pai->ai_canonname, l);
+ } else {
+ /* just to make sure */
+ ai->ai_canonname = NULL;
+ }
+
+ ai->ai_next = NULL;
+
+ return ai;
+}
+
+static int
+get_portmatch(const struct addrinfo *ai, const char *servname)
+{
+
+ /* get_port does not touch first argument when matchonly == 1. */
+ /* LINTED const cast */
+ return get_port((struct addrinfo *)ai, servname, 1);
+}
+
+static int
+get_port(struct addrinfo *ai, const char *servname, int matchonly)
+{
+ const char *proto;
+ struct servent *sp;
+ int port, error;
+ int allownumeric;
+
+ if (servname == NULL)
+ return 0;
+ switch (ai->ai_family) {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+ break;
+ default:
+ return 0;
+ }
+
+ switch (ai->ai_socktype) {
+ case SOCK_RAW:
+ return EAI_SERVICE;
+ case SOCK_DGRAM:
+ case SOCK_STREAM:
+ case SOCK_SEQPACKET:
+ allownumeric = 1;
+ break;
+ case ANY:
+ switch (ai->ai_family) {
+ case AF_INET:
+#ifdef AF_INET6
+ case AF_INET6:
+#endif
+ allownumeric = 1;
+ break;
+ default:
+ allownumeric = 0;
+ break;
+ }
+ break;
+ default:
+ return EAI_SOCKTYPE;
+ }
+
+ error = str2number(servname, &port);
+ if (error == 0) {
+ if (!allownumeric)
+ return EAI_SERVICE;
+ if (port < 0 || port > 65535)
+ return EAI_SERVICE;
+ port = htons(port);
+ } else {
+ if (ai->ai_flags & AI_NUMERICSERV)
+ return EAI_NONAME;
+
+ switch (ai->ai_protocol) {
+ case IPPROTO_UDP:
+ proto = "udp";
+ break;
+ case IPPROTO_TCP:
+ proto = "tcp";
+ break;
+ case IPPROTO_SCTP:
+ proto = "sctp";
+ break;
+ default:
+ proto = NULL;
+ break;
+ }
+
+ if ((sp = getservbyname(servname, proto)) == NULL)
+ return EAI_SERVICE;
+ port = sp->s_port;
+ }
+
+ if (!matchonly) {
+ switch (ai->ai_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)(void *)
+ ai->ai_addr)->sin_port = port;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ((struct sockaddr_in6 *)(void *)
+ ai->ai_addr)->sin6_port = port;
+ break;
+#endif
+ }
+ }
+
+ return 0;
+}
+
+static const struct afd *
+find_afd(int af)
+{
+ const struct afd *afd;
+
+ if (af == PF_UNSPEC)
+ return NULL;
+ for (afd = afdl; afd->a_af; afd++) {
+ if (afd->a_af == af)
+ return afd;
+ }
+ return NULL;
+}
+
+/*
+ * post-2553: AI_ADDRCONFIG check. if we use getipnodeby* as backend, backend
+ * will take care of it.
+ * the semantics of AI_ADDRCONFIG is not defined well. we are not sure
+ * if the code is right or not.
+ *
+ * XXX PF_UNSPEC -> PF_INET6 + PF_INET mapping needs to be in sync with
+ * _dns_getaddrinfo.
+ */
+static int
+addrconfig(struct addrinfo *pai)
+{
+ int s, af;
+
+ /*
+ * TODO:
+ * Note that implementation dependent test for address
+ * configuration should be done everytime called
+ * (or apropriate interval),
+ * because addresses will be dynamically assigned or deleted.
+ */
+ af = pai->ai_family;
+ if (af == AF_UNSPEC) {
+ if ((s = _socket(AF_INET6, SOCK_DGRAM, 0)) < 0)
+ af = AF_INET;
+ else {
+ _close(s);
+ if ((s = _socket(AF_INET, SOCK_DGRAM, 0)) < 0)
+ af = AF_INET6;
+ else
+ _close(s);
+ }
+ }
+ if (af != AF_UNSPEC) {
+ if ((s = _socket(af, SOCK_DGRAM, 0)) < 0)
+ return 0;
+ _close(s);
+ }
+ pai->ai_family = af;
+ return 1;
+}
+
+#ifdef INET6
+/* convert a string to a scope identifier. XXX: IPv6 specific */
+static int
+ip6_str2scopeid(char *scope, struct sockaddr_in6 *sin6, u_int32_t *scopeid)
+{
+ u_long lscopeid;
+ struct in6_addr *a6;
+ char *ep;
+
+ a6 = &sin6->sin6_addr;
+
+ /* empty scopeid portion is invalid */
+ if (*scope == '\0')
+ return -1;
+
+ if (IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
+ IN6_IS_ADDR_MC_NODELOCAL(a6)) {
+ /*
+ * We currently assume a one-to-one mapping between links
+ * and interfaces, so we simply use interface indices for
+ * like-local scopes.
+ */
+ *scopeid = if_nametoindex(scope);
+ if (*scopeid == 0)
+ goto trynumeric;
+ return 0;
+ }
+
+ /* still unclear about literal, allow numeric only - placeholder */
+ if (IN6_IS_ADDR_SITELOCAL(a6) || IN6_IS_ADDR_MC_SITELOCAL(a6))
+ goto trynumeric;
+ if (IN6_IS_ADDR_MC_ORGLOCAL(a6))
+ goto trynumeric;
+ else
+ goto trynumeric; /* global */
+
+ /* try to convert to a numeric id as a last resort */
+ trynumeric:
+ errno = 0;
+ lscopeid = strtoul(scope, &ep, 10);
+ *scopeid = (u_int32_t)(lscopeid & 0xffffffffUL);
+ if (errno == 0 && ep && *ep == '\0' && *scopeid == lscopeid)
+ return 0;
+ else
+ return -1;
+}
+#endif
+
+
+#ifdef NS_CACHING
+static int
+addrinfo_id_func(char *buffer, size_t *buffer_size, va_list ap,
+ void *cache_mdata)
+{
+ res_state statp;
+ u_long res_options;
+
+ const int op_id = 0; /* identifies the getaddrinfo for the cache */
+ char *hostname;
+ struct addrinfo *hints;
+
+ char *p;
+ int ai_flags, ai_family, ai_socktype, ai_protocol;
+ size_t desired_size, size;
+
+ statp = __res_state();
+ res_options = statp->options & (RES_RECURSE | RES_DEFNAMES |
+ RES_DNSRCH | RES_NOALIASES | RES_USE_INET6);
+
+ hostname = va_arg(ap, char *);
+ hints = va_arg(ap, struct addrinfo *);
+
+ desired_size = sizeof(res_options) + sizeof(int) + sizeof(int) * 4;
+ if (hostname != NULL) {
+ size = strlen(hostname);
+ desired_size += size + 1;
+ } else
+ size = 0;
+
+ if (desired_size > *buffer_size) {
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ if (hints == NULL)
+ ai_flags = ai_family = ai_socktype = ai_protocol = 0;
+ else {
+ ai_flags = hints->ai_flags;
+ ai_family = hints->ai_family;
+ ai_socktype = hints->ai_socktype;
+ ai_protocol = hints->ai_protocol;
+ }
+
+ p = buffer;
+ memcpy(p, &res_options, sizeof(res_options));
+ p += sizeof(res_options);
+
+ memcpy(p, &op_id, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, &ai_flags, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, &ai_family, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, &ai_socktype, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, &ai_protocol, sizeof(int));
+ p += sizeof(int);
+
+ if (hostname != NULL)
+ memcpy(p, hostname, size);
+
+ *buffer_size = desired_size;
+ return (NS_SUCCESS);
+}
+
+static int
+addrinfo_marshal_func(char *buffer, size_t *buffer_size, void *retval,
+ va_list ap, void *cache_mdata)
+{
+ struct addrinfo *ai, *cai;
+ char *p;
+ size_t desired_size, size, ai_size;
+
+ ai = *((struct addrinfo **)retval);
+
+ desired_size = sizeof(size_t);
+ ai_size = 0;
+ for (cai = ai; cai != NULL; cai = cai->ai_next) {
+ desired_size += sizeof(struct addrinfo) + cai->ai_addrlen;
+ if (cai->ai_canonname != NULL)
+ desired_size += sizeof(size_t) +
+ strlen(cai->ai_canonname);
+ ++ai_size;
+ }
+
+ if (desired_size > *buffer_size) {
+ /* this assignment is here for future use */
+ errno = ERANGE;
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ memset(buffer, 0, desired_size);
+ p = buffer;
+
+ memcpy(p, &ai_size, sizeof(size_t));
+ p += sizeof(size_t);
+ for (cai = ai; cai != NULL; cai = cai->ai_next) {
+ memcpy(p, cai, sizeof(struct addrinfo));
+ p += sizeof(struct addrinfo);
+
+ memcpy(p, cai->ai_addr, cai->ai_addrlen);
+ p += cai->ai_addrlen;
+
+ if (cai->ai_canonname != NULL) {
+ size = strlen(cai->ai_canonname);
+ memcpy(p, &size, sizeof(size_t));
+ p += sizeof(size_t);
+
+ memcpy(p, cai->ai_canonname, size);
+ p += size;
+ }
+ }
+
+ return (NS_SUCCESS);
+}
+
+static int
+addrinfo_unmarshal_func(char *buffer, size_t buffer_size, void *retval,
+ va_list ap, void *cache_mdata)
+{
+ struct addrinfo new_ai, *result, *sentinel, *lasts;
+
+ char *p;
+ size_t ai_size, ai_i, size;
+
+ p = buffer;
+ memcpy(&ai_size, p, sizeof(size_t));
+ p += sizeof(size_t);
+
+ result = NULL;
+ lasts = NULL;
+ for (ai_i = 0; ai_i < ai_size; ++ai_i) {
+ memcpy(&new_ai, p, sizeof(struct addrinfo));
+ p += sizeof(struct addrinfo);
+ size = new_ai.ai_addrlen + sizeof(struct addrinfo) +
+ _ALIGNBYTES;
+
+ sentinel = (struct addrinfo *)malloc(size);
+ memset(sentinel, 0, size);
+
+ memcpy(sentinel, &new_ai, sizeof(struct addrinfo));
+ sentinel->ai_addr = (struct sockaddr *)_ALIGN((char *)sentinel +
+ sizeof(struct addrinfo));
+
+ memcpy(sentinel->ai_addr, p, new_ai.ai_addrlen);
+ p += new_ai.ai_addrlen;
+
+ if (new_ai.ai_canonname != NULL) {
+ memcpy(&size, p, sizeof(size_t));
+ p += sizeof(size_t);
+
+ sentinel->ai_canonname = (char *)malloc(size + 1);
+ memset(sentinel->ai_canonname, 0, size + 1);
+
+ memcpy(sentinel->ai_canonname, p, size);
+ p += size;
+ }
+
+ if (result == NULL) {
+ result = sentinel;
+ lasts = sentinel;
+ } else {
+ lasts->ai_next = sentinel;
+ lasts = sentinel;
+ }
+ }
+
+ *((struct addrinfo **)retval) = result;
+ return (NS_SUCCESS);
+}
+#endif /* NS_CACHING */
+
+/*
+ * FQDN hostname, DNS lookup
+ */
+static int
+explore_fqdn(const struct addrinfo *pai, const char *hostname,
+ const char *servname, struct addrinfo **res)
+{
+ struct addrinfo *result;
+ struct addrinfo *cur;
+ int error = 0;
+
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ hosts, NULL, addrinfo_id_func, addrinfo_marshal_func,
+ addrinfo_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ NS_FILES_CB(_files_getaddrinfo, NULL)
+ { NSSRC_DNS, _dns_getaddrinfo, NULL }, /* force -DHESIOD */
+ NS_NIS_CB(_yp_getaddrinfo, NULL)
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { 0 }
+ };
+
+ result = NULL;
+
+ /*
+ * if the servname does not match socktype/protocol, ignore it.
+ */
+ if (get_portmatch(pai, servname) != 0)
+ return 0;
+
+ switch (_nsdispatch(&result, dtab, NSDB_HOSTS, "getaddrinfo",
+ default_dns_files, hostname, pai)) {
+ case NS_TRYAGAIN:
+ error = EAI_AGAIN;
+ goto free;
+ case NS_UNAVAIL:
+ error = EAI_FAIL;
+ goto free;
+ case NS_NOTFOUND:
+ error = EAI_NONAME;
+ goto free;
+ case NS_SUCCESS:
+ error = 0;
+ for (cur = result; cur; cur = cur->ai_next) {
+ GET_PORT(cur, servname);
+ /* canonname should be filled already */
+ }
+ break;
+ }
+
+ *res = result;
+
+ return 0;
+
+free:
+ if (result)
+ freeaddrinfo(result);
+ return error;
+}
+
+#ifdef DEBUG
+static const char AskedForGot[] =
+ "gethostby*.getanswer: asked for \"%s\", got \"%s\"";
+#endif
+
+static struct addrinfo *
+getanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
+ const struct addrinfo *pai, res_state res)
+{
+ struct addrinfo sentinel, *cur;
+ struct addrinfo ai;
+ const struct afd *afd;
+ char *canonname;
+ const HEADER *hp;
+ const u_char *cp;
+ int n;
+ const u_char *eom;
+ char *bp, *ep;
+ int type, class, ancount, qdcount;
+ int haveanswer, had_error;
+ char tbuf[MAXDNAME];
+ int (*name_ok)(const char *);
+ char hostbuf[8*1024];
+
+ memset(&sentinel, 0, sizeof(sentinel));
+ cur = &sentinel;
+
+ canonname = NULL;
+ eom = answer->buf + anslen;
+ switch (qtype) {
+ case T_A:
+ case T_AAAA:
+ case T_ANY: /*use T_ANY only for T_A/T_AAAA lookup*/
+ name_ok = res_hnok;
+ break;
+ default:
+ return (NULL); /* XXX should be abort(); */
+ }
+ /*
+ * find first satisfactory answer
+ */
+ hp = &answer->hdr;
+ ancount = ntohs(hp->ancount);
+ qdcount = ntohs(hp->qdcount);
+ bp = hostbuf;
+ ep = hostbuf + sizeof hostbuf;
+ cp = answer->buf + HFIXEDSZ;
+ if (qdcount != 1) {
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return (NULL);
+ }
+ n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+ if ((n < 0) || !(*name_ok)(bp)) {
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return (NULL);
+ }
+ cp += n + QFIXEDSZ;
+ if (qtype == T_A || qtype == T_AAAA || qtype == T_ANY) {
+ /* res_send() has already verified that the query name is the
+ * same as the one we sent; this just gets the expanded name
+ * (i.e., with the succeeding search-domain tacked on).
+ */
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return (NULL);
+ }
+ canonname = bp;
+ bp += n;
+ /* The qname can be abbreviated, but h_name is now absolute. */
+ qname = canonname;
+ }
+ haveanswer = 0;
+ had_error = 0;
+ while (ancount-- > 0 && cp < eom && !had_error) {
+ n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+ if ((n < 0) || !(*name_ok)(bp)) {
+ had_error++;
+ continue;
+ }
+ cp += n; /* name */
+ type = _getshort(cp);
+ cp += INT16SZ; /* type */
+ class = _getshort(cp);
+ cp += INT16SZ + INT32SZ; /* class, TTL */
+ n = _getshort(cp);
+ cp += INT16SZ; /* len */
+ if (class != C_IN) {
+ /* XXX - debug? syslog? */
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if ((qtype == T_A || qtype == T_AAAA || qtype == T_ANY) &&
+ type == T_CNAME) {
+ n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+ if ((n < 0) || !(*name_ok)(tbuf)) {
+ had_error++;
+ continue;
+ }
+ cp += n;
+ /* Get canonical name. */
+ n = strlen(tbuf) + 1; /* for the \0 */
+ if (n > ep - bp || n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ strlcpy(bp, tbuf, ep - bp);
+ canonname = bp;
+ bp += n;
+ continue;
+ }
+ if (qtype == T_ANY) {
+ if (!(type == T_A || type == T_AAAA)) {
+ cp += n;
+ continue;
+ }
+ } else if (type != qtype) {
+#ifdef DEBUG
+ if (type != T_KEY && type != T_SIG &&
+ type != ns_t_dname)
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostby*.getanswer: asked for \"%s %s %s\", got type \"%s\"",
+ qname, p_class(C_IN), p_type(qtype),
+ p_type(type));
+#endif
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ switch (type) {
+ case T_A:
+ case T_AAAA:
+ if (strcasecmp(canonname, bp) != 0) {
+#ifdef DEBUG
+ syslog(LOG_NOTICE|LOG_AUTH,
+ AskedForGot, canonname, bp);
+#endif
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if (type == T_A && n != INADDRSZ) {
+ cp += n;
+ continue;
+ }
+ if (type == T_AAAA && n != IN6ADDRSZ) {
+ cp += n;
+ continue;
+ }
+#ifdef FILTER_V4MAPPED
+ if (type == T_AAAA) {
+ struct in6_addr in6;
+ memcpy(&in6, cp, sizeof(in6));
+ if (IN6_IS_ADDR_V4MAPPED(&in6)) {
+ cp += n;
+ continue;
+ }
+ }
+#endif
+ if (!haveanswer) {
+ int nn;
+
+ canonname = bp;
+ nn = strlen(bp) + 1; /* for the \0 */
+ bp += nn;
+ }
+
+ /* don't overwrite pai */
+ ai = *pai;
+ ai.ai_family = (type == T_A) ? AF_INET : AF_INET6;
+ afd = find_afd(ai.ai_family);
+ if (afd == NULL) {
+ cp += n;
+ continue;
+ }
+ cur->ai_next = get_ai(&ai, afd, (const char *)cp);
+ if (cur->ai_next == NULL)
+ had_error++;
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ cp += n;
+ break;
+ default:
+ abort();
+ }
+ if (!had_error)
+ haveanswer++;
+ }
+ if (haveanswer) {
+#if defined(RESOLVSORT)
+ /*
+ * We support only IPv4 address for backward
+ * compatibility against gethostbyname(3).
+ */
+ if (res->nsort && qtype == T_A) {
+ if (addr4sort(&sentinel, res) < 0) {
+ freeaddrinfo(sentinel.ai_next);
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return NULL;
+ }
+ }
+#endif /*RESOLVSORT*/
+ if (!canonname)
+ (void)get_canonname(pai, sentinel.ai_next, qname);
+ else
+ (void)get_canonname(pai, sentinel.ai_next, canonname);
+ RES_SET_H_ERRNO(res, NETDB_SUCCESS);
+ return sentinel.ai_next;
+ }
+
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return NULL;
+}
+
+#ifdef RESOLVSORT
+struct addr_ptr {
+ struct addrinfo *ai;
+ int aval;
+};
+
+static int
+addr4sort(struct addrinfo *sentinel, res_state res)
+{
+ struct addrinfo *ai;
+ struct addr_ptr *addrs, addr;
+ struct sockaddr_in *sin;
+ int naddrs, i, j;
+ int needsort = 0;
+
+ if (!sentinel)
+ return -1;
+ naddrs = 0;
+ for (ai = sentinel->ai_next; ai; ai = ai->ai_next)
+ naddrs++;
+ if (naddrs < 2)
+ return 0; /* We don't need sorting. */
+ if ((addrs = malloc(sizeof(struct addr_ptr) * naddrs)) == NULL)
+ return -1;
+ i = 0;
+ for (ai = sentinel->ai_next; ai; ai = ai->ai_next) {
+ sin = (struct sockaddr_in *)ai->ai_addr;
+ for (j = 0; (unsigned)j < res->nsort; j++) {
+ if (res->sort_list[j].addr.s_addr ==
+ (sin->sin_addr.s_addr & res->sort_list[j].mask))
+ break;
+ }
+ addrs[i].ai = ai;
+ addrs[i].aval = j;
+ if (needsort == 0 && i > 0 && j < addrs[i - 1].aval)
+ needsort = i;
+ i++;
+ }
+ if (!needsort) {
+ free(addrs);
+ return 0;
+ }
+
+ while (needsort < naddrs) {
+ for (j = needsort - 1; j >= 0; j--) {
+ if (addrs[j].aval > addrs[j+1].aval) {
+ addr = addrs[j];
+ addrs[j] = addrs[j + 1];
+ addrs[j + 1] = addr;
+ } else
+ break;
+ }
+ needsort++;
+ }
+
+ ai = sentinel;
+ for (i = 0; i < naddrs; ++i) {
+ ai->ai_next = addrs[i].ai;
+ ai = ai->ai_next;
+ }
+ ai->ai_next = NULL;
+ free(addrs);
+ return 0;
+}
+#endif /*RESOLVSORT*/
+
+/*ARGSUSED*/
+static int
+_dns_getaddrinfo(void *rv, void *cb_data, va_list ap)
+{
+ struct addrinfo *ai;
+ querybuf *buf, *buf2;
+ const char *hostname;
+ const struct addrinfo *pai;
+ struct addrinfo sentinel, *cur;
+ struct res_target q, q2;
+ res_state res;
+
+ hostname = va_arg(ap, char *);
+ pai = va_arg(ap, const struct addrinfo *);
+
+ memset(&q, 0, sizeof(q));
+ memset(&q2, 0, sizeof(q2));
+ memset(&sentinel, 0, sizeof(sentinel));
+ cur = &sentinel;
+
+ buf = malloc(sizeof(*buf));
+ if (!buf) {
+ RES_SET_H_ERRNO(res, NETDB_INTERNAL);
+ return NS_NOTFOUND;
+ }
+ buf2 = malloc(sizeof(*buf2));
+ if (!buf2) {
+ free(buf);
+ RES_SET_H_ERRNO(res, NETDB_INTERNAL);
+ return NS_NOTFOUND;
+ }
+
+ switch (pai->ai_family) {
+ case AF_UNSPEC:
+ q.name = hostname;
+ q.qclass = C_IN;
+ q.qtype = T_A;
+ q.answer = buf->buf;
+ q.anslen = sizeof(buf->buf);
+ q.next = &q2;
+ q2.name = hostname;
+ q2.qclass = C_IN;
+ q2.qtype = T_AAAA;
+ q2.answer = buf2->buf;
+ q2.anslen = sizeof(buf2->buf);
+ break;
+ case AF_INET:
+ q.name = hostname;
+ q.qclass = C_IN;
+ q.qtype = T_A;
+ q.answer = buf->buf;
+ q.anslen = sizeof(buf->buf);
+ break;
+ case AF_INET6:
+ q.name = hostname;
+ q.qclass = C_IN;
+ q.qtype = T_AAAA;
+ q.answer = buf->buf;
+ q.anslen = sizeof(buf->buf);
+ break;
+ default:
+ free(buf);
+ free(buf2);
+ return NS_UNAVAIL;
+ }
+
+ res = __res_state();
+ if ((res->options & RES_INIT) == 0 && res_ninit(res) == -1) {
+ RES_SET_H_ERRNO(res, NETDB_INTERNAL);
+ free(buf);
+ free(buf2);
+ return NS_NOTFOUND;
+ }
+
+ if (res_searchN(hostname, &q, res) < 0) {
+ free(buf);
+ free(buf2);
+ return NS_NOTFOUND;
+ }
+ /* prefer IPv6 */
+ if (q.next) {
+ ai = getanswer(buf2, q2.n, q2.name, q2.qtype, pai, res);
+ if (ai) {
+ cur->ai_next = ai;
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+ }
+ ai = getanswer(buf, q.n, q.name, q.qtype, pai, res);
+ if (ai)
+ cur->ai_next = ai;
+ free(buf);
+ free(buf2);
+ if (sentinel.ai_next == NULL)
+ switch (res->res_h_errno) {
+ case HOST_NOT_FOUND:
+ return NS_NOTFOUND;
+ case TRY_AGAIN:
+ return NS_TRYAGAIN;
+ default:
+ return NS_UNAVAIL;
+ }
+ *((struct addrinfo **)rv) = sentinel.ai_next;
+ return NS_SUCCESS;
+}
+
+static void
+_sethtent(FILE **hostf)
+{
+ if (!*hostf)
+ *hostf = fopen(_PATH_HOSTS, "r");
+ else
+ rewind(*hostf);
+}
+
+static void
+_endhtent(FILE **hostf)
+{
+ if (*hostf) {
+ (void) fclose(*hostf);
+ *hostf = NULL;
+ }
+}
+
+static struct addrinfo *
+_gethtent(FILE **hostf, const char *name, const struct addrinfo *pai)
+{
+ char *p;
+ char *cp, *tname, *cname;
+ struct addrinfo hints, *res0, *res;
+ int error;
+ const char *addr;
+ char hostbuf[8*1024];
+
+ if (!*hostf && !(*hostf = fopen(_PATH_HOSTS, "r")))
+ return (NULL);
+again:
+ if (!(p = fgets(hostbuf, sizeof hostbuf, *hostf)))
+ return (NULL);
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp != NULL)
+ *cp = '\0';
+ if (!(cp = strpbrk(p, " \t")))
+ goto again;
+ *cp++ = '\0';
+ addr = p;
+ cname = NULL;
+ /* if this is not something we're looking for, skip it. */
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ tname = cp;
+ if (cname == NULL)
+ cname = cp;
+ if ((cp = strpbrk(cp, " \t")) != NULL)
+ *cp++ = '\0';
+ if (strcasecmp(name, tname) == 0)
+ goto found;
+ }
+ goto again;
+
+found:
+ /* we should not glob socktype/protocol here */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = pai->ai_family;
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_protocol = 0;
+ hints.ai_flags = AI_NUMERICHOST;
+ error = getaddrinfo(addr, "0", &hints, &res0);
+ if (error)
+ goto again;
+#ifdef FILTER_V4MAPPED
+ /* XXX should check all items in the chain */
+ if (res0->ai_family == AF_INET6 &&
+ IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)res0->ai_addr)->sin6_addr)) {
+ freeaddrinfo(res0);
+ goto again;
+ }
+#endif
+ for (res = res0; res; res = res->ai_next) {
+ /* cover it up */
+ res->ai_flags = pai->ai_flags;
+ res->ai_socktype = pai->ai_socktype;
+ res->ai_protocol = pai->ai_protocol;
+
+ if (pai->ai_flags & AI_CANONNAME) {
+ if (get_canonname(pai, res, cname) != 0) {
+ freeaddrinfo(res0);
+ goto again;
+ }
+ }
+ }
+ return res0;
+}
+
+/*ARGSUSED*/
+static int
+_files_getaddrinfo(void *rv, void *cb_data, va_list ap)
+{
+ const char *name;
+ const struct addrinfo *pai;
+ struct addrinfo sentinel, *cur;
+ struct addrinfo *p;
+ FILE *hostf = NULL;
+
+ name = va_arg(ap, char *);
+ pai = va_arg(ap, struct addrinfo *);
+
+ memset(&sentinel, 0, sizeof(sentinel));
+ cur = &sentinel;
+
+ _sethtent(&hostf);
+ while ((p = _gethtent(&hostf, name, pai)) != NULL) {
+ cur->ai_next = p;
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+ _endhtent(&hostf);
+
+ *((struct addrinfo **)rv) = sentinel.ai_next;
+ if (sentinel.ai_next == NULL)
+ return NS_NOTFOUND;
+ return NS_SUCCESS;
+}
+
+#ifdef YP
+/*ARGSUSED*/
+static struct addrinfo *
+_yphostent(char *line, const struct addrinfo *pai)
+{
+ struct addrinfo sentinel, *cur;
+ struct addrinfo hints, *res, *res0;
+ int error;
+ char *p = line;
+ const char *addr, *canonname;
+ char *nextline;
+ char *cp;
+
+ addr = canonname = NULL;
+
+ memset(&sentinel, 0, sizeof(sentinel));
+ cur = &sentinel;
+
+nextline:
+ /* terminate line */
+ cp = strchr(p, '\n');
+ if (cp) {
+ *cp++ = '\0';
+ nextline = cp;
+ } else
+ nextline = NULL;
+
+ cp = strpbrk(p, " \t");
+ if (cp == NULL) {
+ if (canonname == NULL)
+ return (NULL);
+ else
+ goto done;
+ }
+ *cp++ = '\0';
+
+ addr = p;
+
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (!canonname)
+ canonname = cp;
+ if ((cp = strpbrk(cp, " \t")) != NULL)
+ *cp++ = '\0';
+ }
+
+ hints = *pai;
+ hints.ai_flags = AI_NUMERICHOST;
+ error = getaddrinfo(addr, NULL, &hints, &res0);
+ if (error == 0) {
+ for (res = res0; res; res = res->ai_next) {
+ /* cover it up */
+ res->ai_flags = pai->ai_flags;
+
+ if (pai->ai_flags & AI_CANONNAME)
+ (void)get_canonname(pai, res, canonname);
+ }
+ } else
+ res0 = NULL;
+ if (res0) {
+ cur->ai_next = res0;
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+
+ if (nextline) {
+ p = nextline;
+ goto nextline;
+ }
+
+done:
+ return sentinel.ai_next;
+}
+
+/*ARGSUSED*/
+static int
+_yp_getaddrinfo(void *rv, void *cb_data, va_list ap)
+{
+ struct addrinfo sentinel, *cur;
+ struct addrinfo *ai = NULL;
+ char *ypbuf;
+ int ypbuflen, r;
+ const char *name;
+ const struct addrinfo *pai;
+ char *ypdomain;
+
+ if (_yp_check(&ypdomain) == 0)
+ return NS_UNAVAIL;
+
+ name = va_arg(ap, char *);
+ pai = va_arg(ap, const struct addrinfo *);
+
+ memset(&sentinel, 0, sizeof(sentinel));
+ cur = &sentinel;
+
+ /* hosts.byname is only for IPv4 (Solaris8) */
+ if (pai->ai_family == PF_UNSPEC || pai->ai_family == PF_INET) {
+ r = yp_match(ypdomain, "hosts.byname", name,
+ (int)strlen(name), &ypbuf, &ypbuflen);
+ if (r == 0) {
+ struct addrinfo ai4;
+
+ ai4 = *pai;
+ ai4.ai_family = AF_INET;
+ ai = _yphostent(ypbuf, &ai4);
+ if (ai) {
+ cur->ai_next = ai;
+ while (cur && cur->ai_next)
+ cur = cur->ai_next;
+ }
+ free(ypbuf);
+ }
+ }
+
+ /* ipnodes.byname can hold both IPv4/v6 */
+ r = yp_match(ypdomain, "ipnodes.byname", name,
+ (int)strlen(name), &ypbuf, &ypbuflen);
+ if (r == 0) {
+ ai = _yphostent(ypbuf, pai);
+ if (ai)
+ cur->ai_next = ai;
+ free(ypbuf);
+ }
+
+ if (sentinel.ai_next == NULL) {
+ RES_SET_H_ERRNO(__res_state(), HOST_NOT_FOUND);
+ return NS_NOTFOUND;
+ }
+ *((struct addrinfo **)rv) = sentinel.ai_next;
+ return NS_SUCCESS;
+}
+#endif
+
+/* resolver logic */
+
+/*
+ * Formulate a normal query, send, and await answer.
+ * Returned answer is placed in supplied buffer "answer".
+ * Perform preliminary check of answer, returning success only
+ * if no error is indicated and the answer count is nonzero.
+ * Return the size of the response on success, -1 on error.
+ * Error number is left in h_errno.
+ *
+ * Caller must parse answer and determine whether it answers the question.
+ */
+static int
+res_queryN(const char *name, struct res_target *target, res_state res)
+{
+ u_char *buf;
+ HEADER *hp;
+ int n;
+ u_int oflags;
+ struct res_target *t;
+ int rcode;
+ int ancount;
+
+ rcode = NOERROR;
+ ancount = 0;
+
+ buf = malloc(MAXPACKET);
+ if (!buf) {
+ RES_SET_H_ERRNO(res, NETDB_INTERNAL);
+ return -1;
+ }
+
+ for (t = target; t; t = t->next) {
+ int class, type;
+ u_char *answer;
+ int anslen;
+
+ hp = (HEADER *)(void *)t->answer;
+
+ /* make it easier... */
+ class = t->qclass;
+ type = t->qtype;
+ answer = t->answer;
+ anslen = t->anslen;
+
+ oflags = res->_flags;
+
+again:
+ hp->rcode = NOERROR; /* default */
+
+#ifdef DEBUG
+ if (res->options & RES_DEBUG)
+ printf(";; res_query(%s, %d, %d)\n", name, class, type);
+#endif
+
+ n = res_nmkquery(res, QUERY, name, class, type, NULL, 0, NULL,
+ buf, MAXPACKET);
+ if (n > 0 && (res->_flags & RES_F_EDNS0ERR) == 0 &&
+ (res->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U)
+ n = res_nopt(res, n, buf, MAXPACKET, anslen);
+ if (n <= 0) {
+#ifdef DEBUG
+ if (res->options & RES_DEBUG)
+ printf(";; res_query: mkquery failed\n");
+#endif
+ free(buf);
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return (n);
+ }
+ n = res_nsend(res, buf, n, answer, anslen);
+ if (n < 0) {
+ /*
+ * if the query choked with EDNS0, retry
+ * without EDNS0
+ */
+ if ((res->options & (RES_USE_EDNS0|RES_USE_DNSSEC))
+ != 0U &&
+ ((oflags ^ res->_flags) & RES_F_EDNS0ERR) != 0) {
+ res->_flags |= RES_F_EDNS0ERR;
+ if (res->options & RES_DEBUG)
+ printf(";; res_nquery: retry without EDNS0\n");
+ goto again;
+ }
+ rcode = hp->rcode; /* record most recent error */
+#ifdef DEBUG
+ if (res->options & RES_DEBUG)
+ printf(";; res_query: send error\n");
+#endif
+ continue;
+ }
+
+ if (n > anslen)
+ hp->rcode = FORMERR; /* XXX not very informative */
+ if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
+ rcode = hp->rcode; /* record most recent error */
+#ifdef DEBUG
+ if (res->options & RES_DEBUG)
+ printf(";; rcode = %u, ancount=%u\n", hp->rcode,
+ ntohs(hp->ancount));
+#endif
+ continue;
+ }
+
+ ancount += ntohs(hp->ancount);
+
+ t->n = n;
+ }
+
+ free(buf);
+
+ if (ancount == 0) {
+ switch (rcode) {
+ case NXDOMAIN:
+ RES_SET_H_ERRNO(res, HOST_NOT_FOUND);
+ break;
+ case SERVFAIL:
+ RES_SET_H_ERRNO(res, TRY_AGAIN);
+ break;
+ case NOERROR:
+ RES_SET_H_ERRNO(res, NO_DATA);
+ break;
+ case FORMERR:
+ case NOTIMP:
+ case REFUSED:
+ default:
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ break;
+ }
+ return (-1);
+ }
+ return (ancount);
+}
+
+/*
+ * Formulate a normal query, send, and retrieve answer in supplied buffer.
+ * Return the size of the response on success, -1 on error.
+ * If enabled, implement search rules until answer or unrecoverable failure
+ * is detected. Error code, if any, is left in h_errno.
+ */
+static int
+res_searchN(const char *name, struct res_target *target, res_state res)
+{
+ const char *cp, * const *domain;
+ HEADER *hp = (HEADER *)(void *)target->answer; /*XXX*/
+ u_int dots;
+ int trailing_dot, ret, saved_herrno;
+ int got_nodata = 0, got_servfail = 0, root_on_list = 0;
+ int tried_as_is = 0;
+ int searched = 0;
+ char abuf[MAXDNAME];
+
+ errno = 0;
+ RES_SET_H_ERRNO(res, HOST_NOT_FOUND); /* default, if we never query */
+ dots = 0;
+ for (cp = name; *cp; cp++)
+ dots += (*cp == '.');
+ trailing_dot = 0;
+ if (cp > name && *--cp == '.')
+ trailing_dot++;
+
+ /*
+ * if there aren't any dots, it could be a user-level alias
+ */
+ if (!dots &&
+ (cp = res_hostalias(res, name, abuf, sizeof(abuf))) != NULL)
+ return (res_queryN(cp, target, res));
+
+ /*
+ * If there are enough dots in the name, let's just give it a
+ * try 'as is'. The threshold can be set with the "ndots" option.
+ * Also, query 'as is', if there is a trailing dot in the name.
+ */
+ saved_herrno = -1;
+ if (dots >= res->ndots || trailing_dot) {
+ ret = res_querydomainN(name, NULL, target, res);
+ if (ret > 0 || trailing_dot)
+ return (ret);
+ if (errno == ECONNREFUSED) {
+ RES_SET_H_ERRNO(res, TRY_AGAIN);
+ return (-1);
+ }
+ switch (res->res_h_errno) {
+ case NO_DATA:
+ case HOST_NOT_FOUND:
+ break;
+ case TRY_AGAIN:
+ if (hp->rcode == SERVFAIL)
+ break;
+ /* FALLTHROUGH */
+ default:
+ return (-1);
+ }
+ saved_herrno = res->res_h_errno;
+ tried_as_is++;
+ }
+
+ /*
+ * We do at least one level of search if
+ * - there is no dot and RES_DEFNAME is set, or
+ * - there is at least one dot, there is no trailing dot,
+ * and RES_DNSRCH is set.
+ */
+ if ((!dots && (res->options & RES_DEFNAMES)) ||
+ (dots && !trailing_dot && (res->options & RES_DNSRCH))) {
+ int done = 0;
+
+ for (domain = (const char * const *)res->dnsrch;
+ *domain && !done;
+ domain++) {
+ searched = 1;
+
+ if (domain[0][0] == '\0' ||
+ (domain[0][0] == '.' && domain[0][1] == '\0'))
+ root_on_list++;
+
+ if (root_on_list && tried_as_is)
+ continue;
+
+ ret = res_querydomainN(name, *domain, target, res);
+ if (ret > 0)
+ return (ret);
+
+ /*
+ * If no server present, give up.
+ * If name isn't found in this domain,
+ * keep trying higher domains in the search list
+ * (if that's enabled).
+ * On a NO_DATA error, keep trying, otherwise
+ * a wildcard entry of another type could keep us
+ * from finding this entry higher in the domain.
+ * If we get some other error (negative answer or
+ * server failure), then stop searching up,
+ * but try the input name below in case it's
+ * fully-qualified.
+ */
+ if (errno == ECONNREFUSED) {
+ RES_SET_H_ERRNO(res, TRY_AGAIN);
+ return (-1);
+ }
+
+ switch (res->res_h_errno) {
+ case NO_DATA:
+ got_nodata++;
+ /* FALLTHROUGH */
+ case HOST_NOT_FOUND:
+ /* keep trying */
+ break;
+ case TRY_AGAIN:
+ got_servfail++;
+ if (hp->rcode == SERVFAIL) {
+ /* try next search element, if any */
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ /* anything else implies that we're done */
+ done++;
+ }
+ /*
+ * if we got here for some reason other than DNSRCH,
+ * we only wanted one iteration of the loop, so stop.
+ */
+ if (!(res->options & RES_DNSRCH))
+ done++;
+ }
+ }
+
+ switch (res->res_h_errno) {
+ case NO_DATA:
+ case HOST_NOT_FOUND:
+ break;
+ case TRY_AGAIN:
+ if (hp->rcode == SERVFAIL)
+ break;
+ /* FALLTHROUGH */
+ default:
+ goto giveup;
+ }
+
+ /*
+ * If the query has not already been tried as is then try it
+ * unless RES_NOTLDQUERY is set and there were no dots.
+ */
+ if ((dots || !searched || !(res->options & RES_NOTLDQUERY)) &&
+ !(tried_as_is || root_on_list)) {
+ ret = res_querydomainN(name, NULL, target, res);
+ if (ret > 0)
+ return (ret);
+ }
+
+ /*
+ * if we got here, we didn't satisfy the search.
+ * if we did an initial full query, return that query's h_errno
+ * (note that we wouldn't be here if that query had succeeded).
+ * else if we ever got a nodata, send that back as the reason.
+ * else send back meaningless h_errno, that being the one from
+ * the last DNSRCH we did.
+ */
+giveup:
+ if (saved_herrno != -1)
+ RES_SET_H_ERRNO(res, saved_herrno);
+ else if (got_nodata)
+ RES_SET_H_ERRNO(res, NO_DATA);
+ else if (got_servfail)
+ RES_SET_H_ERRNO(res, TRY_AGAIN);
+ return (-1);
+}
+
+/*
+ * Perform a call on res_query on the concatenation of name and domain,
+ * removing a trailing dot from name if domain is NULL.
+ */
+static int
+res_querydomainN(const char *name, const char *domain,
+ struct res_target *target, res_state res)
+{
+ char nbuf[MAXDNAME];
+ const char *longname = nbuf;
+ size_t n, d;
+
+#ifdef DEBUG
+ if (res->options & RES_DEBUG)
+ printf(";; res_querydomain(%s, %s)\n",
+ name, domain?domain:"<Nil>");
+#endif
+ if (domain == NULL) {
+ /*
+ * Check for trailing '.';
+ * copy without '.' if present.
+ */
+ n = strlen(name);
+ if (n >= MAXDNAME) {
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return (-1);
+ }
+ if (n > 0 && name[--n] == '.') {
+ strncpy(nbuf, name, n);
+ nbuf[n] = '\0';
+ } else
+ longname = name;
+ } else {
+ n = strlen(name);
+ d = strlen(domain);
+ if (n + d + 1 >= MAXDNAME) {
+ RES_SET_H_ERRNO(res, NO_RECOVERY);
+ return (-1);
+ }
+ snprintf(nbuf, sizeof(nbuf), "%s.%s", name, domain);
+ }
+ return (res_queryN(longname, target, res));
+}
diff --git a/lib/libc/net/gethostbydns.c b/lib/libc/net/gethostbydns.c
new file mode 100644
index 0000000..f301c88
--- /dev/null
+++ b/lib/libc/net/gethostbydns.c
@@ -0,0 +1,779 @@
+/*
+ * ++Copyright++ 1985, 1988, 1993
+ * -
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+static char fromrcsid[] = "From: Id: gethnamaddr.c,v 8.23 1998/04/07 04:59:46 vixie Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <errno.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+
+#include "netdb_private.h"
+#include "res_config.h"
+
+#define SPRINTF(x) ((size_t)sprintf x)
+
+static const char AskedForGot[] =
+ "gethostby*.gethostanswer: asked for \"%s\", got \"%s\"";
+
+#ifdef RESOLVSORT
+static void addrsort(char **, int, res_state);
+#endif
+
+#ifdef DEBUG
+static void dprintf(char *, int, res_state) __printflike(1, 0);
+#endif
+
+#define MAXPACKET (64*1024)
+
+typedef union {
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+typedef union {
+ int32_t al;
+ char ac;
+} align;
+
+int _dns_ttl_;
+
+#ifdef DEBUG
+static void
+dprintf(msg, num, res)
+ char *msg;
+ int num;
+ res_state res;
+{
+ if (res->options & RES_DEBUG) {
+ int save = errno;
+
+ printf(msg, num);
+ errno = save;
+ }
+}
+#else
+# define dprintf(msg, num, res) /*nada*/
+#endif
+
+#define BOUNDED_INCR(x) \
+ do { \
+ cp += x; \
+ if (cp > eom) { \
+ RES_SET_H_ERRNO(statp, NO_RECOVERY); \
+ return (-1); \
+ } \
+ } while (0)
+
+#define BOUNDS_CHECK(ptr, count) \
+ do { \
+ if ((ptr) + (count) > eom) { \
+ RES_SET_H_ERRNO(statp, NO_RECOVERY); \
+ return (-1); \
+ } \
+ } while (0)
+
+static int
+gethostanswer(const querybuf *answer, int anslen, const char *qname, int qtype,
+ struct hostent *he, struct hostent_data *hed, res_state statp)
+{
+ const HEADER *hp;
+ const u_char *cp;
+ int n;
+ const u_char *eom, *erdata;
+ char *bp, *ep, **ap, **hap;
+ int type, class, ancount, qdcount;
+ int haveanswer, had_error;
+ int toobig = 0;
+ char tbuf[MAXDNAME];
+ const char *tname;
+ int (*name_ok)(const char *);
+
+ tname = qname;
+ he->h_name = NULL;
+ eom = answer->buf + anslen;
+ switch (qtype) {
+ case T_A:
+ case T_AAAA:
+ name_ok = res_hnok;
+ break;
+ case T_PTR:
+ name_ok = res_dnok;
+ break;
+ default:
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1); /* XXX should be abort(); */
+ }
+ /*
+ * find first satisfactory answer
+ */
+ hp = &answer->hdr;
+ ancount = ntohs(hp->ancount);
+ qdcount = ntohs(hp->qdcount);
+ bp = hed->hostbuf;
+ ep = hed->hostbuf + sizeof hed->hostbuf;
+ cp = answer->buf;
+ BOUNDED_INCR(HFIXEDSZ);
+ if (qdcount != 1) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+ if ((n < 0) || !(*name_ok)(bp)) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ BOUNDED_INCR(n + QFIXEDSZ);
+ if (qtype == T_A || qtype == T_AAAA) {
+ /* res_send() has already verified that the query name is the
+ * same as the one we sent; this just gets the expanded name
+ * (i.e., with the succeeding search-domain tacked on).
+ */
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ he->h_name = bp;
+ bp += n;
+ /* The qname can be abbreviated, but h_name is now absolute. */
+ qname = he->h_name;
+ }
+ ap = hed->host_aliases;
+ *ap = NULL;
+ he->h_aliases = hed->host_aliases;
+ hap = hed->h_addr_ptrs;
+ *hap = NULL;
+ he->h_addr_list = hed->h_addr_ptrs;
+ haveanswer = 0;
+ had_error = 0;
+ _dns_ttl_ = -1;
+ while (ancount-- > 0 && cp < eom && !had_error) {
+ n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+ if ((n < 0) || !(*name_ok)(bp)) {
+ had_error++;
+ continue;
+ }
+ cp += n; /* name */
+ BOUNDS_CHECK(cp, 3 * INT16SZ + INT32SZ);
+ type = _getshort(cp);
+ cp += INT16SZ; /* type */
+ class = _getshort(cp);
+ cp += INT16SZ; /* class */
+ if (qtype == T_A && type == T_A)
+ _dns_ttl_ = _getlong(cp);
+ cp += INT32SZ; /* TTL */
+ n = _getshort(cp);
+ cp += INT16SZ; /* len */
+ BOUNDS_CHECK(cp, n);
+ erdata = cp + n;
+ if (class != C_IN) {
+ /* XXX - debug? syslog? */
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if ((qtype == T_A || qtype == T_AAAA) && type == T_CNAME) {
+ if (ap >= &hed->host_aliases[_MAXALIASES-1])
+ continue;
+ n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+ if ((n < 0) || !(*name_ok)(tbuf)) {
+ had_error++;
+ continue;
+ }
+ cp += n;
+ if (cp != erdata) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ /* Store alias. */
+ *ap++ = bp;
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ bp += n;
+ /* Get canonical name. */
+ n = strlen(tbuf) + 1; /* for the \0 */
+ if (n > ep - bp || n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ strcpy(bp, tbuf);
+ he->h_name = bp;
+ bp += n;
+ continue;
+ }
+ if (qtype == T_PTR && type == T_CNAME) {
+ n = dn_expand(answer->buf, eom, cp, tbuf, sizeof tbuf);
+ if (n < 0 || !res_dnok(tbuf)) {
+ had_error++;
+ continue;
+ }
+ cp += n;
+ if (cp != erdata) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ /* Get canonical name. */
+ n = strlen(tbuf) + 1; /* for the \0 */
+ if (n > ep - bp || n >= MAXHOSTNAMELEN) {
+ had_error++;
+ continue;
+ }
+ strcpy(bp, tbuf);
+ tname = bp;
+ bp += n;
+ continue;
+ }
+ if (type != qtype) {
+ if (type != T_SIG && type != ns_t_dname)
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostby*.gethostanswer: asked for \"%s %s %s\", got type \"%s\"",
+ qname, p_class(C_IN), p_type(qtype),
+ p_type(type));
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ switch (type) {
+ case T_PTR:
+ if (strcasecmp(tname, bp) != 0) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ AskedForGot, qname, bp);
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+ if ((n < 0) || !res_hnok(bp)) {
+ had_error++;
+ break;
+ }
+#if MULTI_PTRS_ARE_ALIASES
+ cp += n;
+ if (cp != erdata) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ if (!haveanswer)
+ he->h_name = bp;
+ else if (ap < &hed->host_aliases[_MAXALIASES-1])
+ *ap++ = bp;
+ else
+ n = -1;
+ if (n != -1) {
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ had_error++;
+ break;
+ }
+ bp += n;
+ }
+ break;
+#else
+ he->h_name = bp;
+ if (statp->options & RES_USE_INET6) {
+ n = strlen(bp) + 1; /* for the \0 */
+ if (n >= MAXHOSTNAMELEN) {
+ had_error++;
+ break;
+ }
+ bp += n;
+ _map_v4v6_hostent(he, &bp, ep);
+ }
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ return (0);
+#endif
+ case T_A:
+ case T_AAAA:
+ if (strcasecmp(he->h_name, bp) != 0) {
+ syslog(LOG_NOTICE|LOG_AUTH,
+ AskedForGot, he->h_name, bp);
+ cp += n;
+ continue; /* XXX - had_error++ ? */
+ }
+ if (n != he->h_length) {
+ cp += n;
+ continue;
+ }
+ if (!haveanswer) {
+ int nn;
+
+ he->h_name = bp;
+ nn = strlen(bp) + 1; /* for the \0 */
+ bp += nn;
+ }
+
+ bp += sizeof(align) - ((u_long)bp % sizeof(align));
+
+ if (bp + n >= ep) {
+ dprintf("size (%d) too big\n", n, statp);
+ had_error++;
+ continue;
+ }
+ if (hap >= &hed->h_addr_ptrs[_MAXADDRS-1]) {
+ if (!toobig++)
+ dprintf("Too many addresses (%d)\n",
+ _MAXADDRS, statp);
+ cp += n;
+ continue;
+ }
+ memcpy(*hap++ = bp, cp, n);
+ bp += n;
+ cp += n;
+ if (cp != erdata) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ break;
+ default:
+ dprintf("Impossible condition (type=%d)\n", type,
+ statp);
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ /* BIND has abort() here, too risky on bad data */
+ }
+ if (!had_error)
+ haveanswer++;
+ }
+ if (haveanswer) {
+ *ap = NULL;
+ *hap = NULL;
+# if defined(RESOLVSORT)
+ /*
+ * Note: we sort even if host can take only one address
+ * in its return structures - should give it the "best"
+ * address in that case, not some random one
+ */
+ if (statp->nsort && haveanswer > 1 && qtype == T_A)
+ addrsort(hed->h_addr_ptrs, haveanswer, statp);
+# endif /*RESOLVSORT*/
+ if (!he->h_name) {
+ n = strlen(qname) + 1; /* for the \0 */
+ if (n > ep - bp || n >= MAXHOSTNAMELEN)
+ goto no_recovery;
+ strcpy(bp, qname);
+ he->h_name = bp;
+ bp += n;
+ }
+ if (statp->options & RES_USE_INET6)
+ _map_v4v6_hostent(he, &bp, ep);
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ return (0);
+ }
+ no_recovery:
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+}
+
+/* XXX: for async DNS resolver in ypserv */
+struct hostent *
+__dns_getanswer(const char *answer, int anslen, const char *qname, int qtype)
+{
+ struct hostent *he;
+ struct hostent_data *hed;
+ int error;
+ res_state statp;
+
+ statp = __res_state();
+ if ((he = __hostent_init()) == NULL ||
+ (hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (NULL);
+ }
+ switch (qtype) {
+ case T_AAAA:
+ he->h_addrtype = AF_INET6;
+ he->h_length = NS_IN6ADDRSZ;
+ break;
+ case T_A:
+ default:
+ he->h_addrtype = AF_INET;
+ he->h_length = NS_INADDRSZ;
+ break;
+ }
+
+ error = gethostanswer((const querybuf *)answer, anslen, qname, qtype,
+ he, hed, statp);
+ return (error == 0) ? he : NULL;
+}
+
+int
+_dns_gethostbyname(void *rval, void *cb_data, va_list ap)
+{
+ const char *name;
+ int af;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
+ struct hostent_data *hed;
+ querybuf *buf;
+ int n, type, error;
+ res_state statp;
+
+ name = va_arg(ap, const char *);
+ af = va_arg(ap, int);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ he.h_addrtype = af;
+ switch (af) {
+ case AF_INET:
+ he.h_length = NS_INADDRSZ;
+ type = T_A;
+ break;
+ case AF_INET6:
+ he.h_length = NS_IN6ADDRSZ;
+ type = T_AAAA;
+ break;
+ default:
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ errno = EAFNOSUPPORT;
+ return (NS_UNAVAIL);
+ }
+
+ if ((buf = malloc(sizeof(*buf))) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ n = res_nsearch(statp, name, C_IN, type, buf->buf, sizeof(buf->buf));
+ if (n < 0) {
+ free(buf);
+ dprintf("res_nsearch failed (%d)\n", n, statp);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ } else if (n > sizeof(buf->buf)) {
+ free(buf);
+ dprintf("static buffer is too small (%d)\n", n, statp);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+ error = gethostanswer(buf, n, name, type, &he, hed, statp);
+ free(buf);
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ switch (statp->res_h_errno) {
+ case HOST_NOT_FOUND:
+ return (NS_NOTFOUND);
+ case TRY_AGAIN:
+ return (NS_TRYAGAIN);
+ default:
+ return (NS_UNAVAIL);
+ }
+ /*NOTREACHED*/
+ }
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
+}
+
+int
+_dns_gethostbyaddr(void *rval, void *cb_data, va_list ap)
+{
+ const void *addr;
+ socklen_t len;
+ int af;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ const u_char *uaddr;
+ struct hostent *hptr, he;
+ struct hostent_data *hed;
+ int n;
+ querybuf *buf;
+ char qbuf[MAXDNAME+1], *qp;
+ res_state statp;
+#ifdef SUNSECURITY
+ struct hostdata rhd;
+ struct hostent *rhe;
+ char **haddr;
+ u_long old_options;
+ char hname2[MAXDNAME+1], numaddr[46];
+ int ret_h_error;
+#endif /*SUNSECURITY*/
+
+ addr = va_arg(ap, const void *);
+ len = va_arg(ap, socklen_t);
+ af = va_arg(ap, int);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+ uaddr = (const u_char *)addr;
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ switch (af) {
+ case AF_INET:
+ (void) sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa",
+ (uaddr[3] & 0xff),
+ (uaddr[2] & 0xff),
+ (uaddr[1] & 0xff),
+ (uaddr[0] & 0xff));
+ break;
+ case AF_INET6:
+ qp = qbuf;
+ for (n = NS_IN6ADDRSZ - 1; n >= 0; n--) {
+ qp += SPRINTF((qp, "%x.%x.",
+ uaddr[n] & 0xf,
+ (uaddr[n] >> 4) & 0xf));
+ }
+ strlcat(qbuf, "ip6.arpa", sizeof(qbuf));
+ break;
+ default:
+ abort();
+ }
+ if ((buf = malloc(sizeof(*buf))) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return NS_NOTFOUND;
+ }
+ n = res_nquery(statp, qbuf, C_IN, T_PTR, (u_char *)buf->buf,
+ sizeof buf->buf);
+ if (n < 0) {
+ free(buf);
+ dprintf("res_nquery failed (%d)\n", n, statp);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+ if (n > sizeof buf->buf) {
+ free(buf);
+ dprintf("static buffer is too small (%d)\n", n, statp);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+ if (gethostanswer(buf, n, qbuf, T_PTR, &he, hed, statp) != 0) {
+ free(buf);
+ *h_errnop = statp->res_h_errno;
+ switch (statp->res_h_errno) {
+ case HOST_NOT_FOUND:
+ return (NS_NOTFOUND);
+ case TRY_AGAIN:
+ return (NS_TRYAGAIN);
+ default:
+ return (NS_UNAVAIL);
+ }
+ /*NOTREACHED*/
+ }
+ free(buf);
+#ifdef SUNSECURITY
+ if (af == AF_INET) {
+ /*
+ * turn off search as the name should be absolute,
+ * 'localhost' should be matched by defnames
+ */
+ strncpy(hname2, he.h_name, MAXDNAME);
+ hname2[MAXDNAME] = '\0';
+ old_options = statp->options;
+ statp->options &= ~RES_DNSRCH;
+ statp->options |= RES_DEFNAMES;
+ memset(&rhd, 0, sizeof rhd);
+ rhe = gethostbyname_r(hname2, &rhd.host, &rhd.data,
+ sizeof(rhd.data), &ret_h_error);
+ if (rhe == NULL) {
+ if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
+ strlcpy(numaddr, "UNKNOWN", sizeof(numaddr));
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostbyaddr: No A record for %s (verifying [%s])",
+ hname2, numaddr);
+ statp->options = old_options;
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ statp->options = old_options;
+ for (haddr = rhe->h_addr_list; *haddr; haddr++)
+ if (!memcmp(*haddr, addr, NS_INADDRSZ))
+ break;
+ if (!*haddr) {
+ if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
+ strlcpy(numaddr, "UNKNOWN", sizeof(numaddr));
+ syslog(LOG_NOTICE|LOG_AUTH,
+ "gethostbyaddr: A record of %s != PTR record [%s]",
+ hname2, numaddr);
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ }
+#endif /*SUNSECURITY*/
+ he.h_addrtype = af;
+ he.h_length = len;
+ memcpy(hed->host_addr, uaddr, len);
+ hed->h_addr_ptrs[0] = (char *)hed->host_addr;
+ hed->h_addr_ptrs[1] = NULL;
+ if (af == AF_INET && (statp->options & RES_USE_INET6)) {
+ _map_v4v6_address((char*)hed->host_addr, (char*)hed->host_addr);
+ he.h_addrtype = AF_INET6;
+ he.h_length = NS_IN6ADDRSZ;
+ }
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
+}
+
+#ifdef RESOLVSORT
+static void
+addrsort(char **ap, int num, res_state res)
+{
+ int i, j;
+ char **p;
+ short aval[_MAXADDRS];
+ int needsort = 0;
+
+ p = ap;
+ for (i = 0; i < num; i++, p++) {
+ for (j = 0 ; (unsigned)j < res->nsort; j++)
+ if (res->sort_list[j].addr.s_addr ==
+ (((struct in_addr *)(*p))->s_addr & res->sort_list[j].mask))
+ break;
+ aval[i] = j;
+ if (needsort == 0 && i > 0 && j < aval[i-1])
+ needsort = i;
+ }
+ if (!needsort)
+ return;
+
+ while (needsort < num) {
+ for (j = needsort - 1; j >= 0; j--) {
+ if (aval[j] > aval[j+1]) {
+ char *hp;
+
+ i = aval[j];
+ aval[j] = aval[j+1];
+ aval[j+1] = i;
+
+ hp = ap[j];
+ ap[j] = ap[j+1];
+ ap[j+1] = hp;
+
+ } else
+ break;
+ }
+ needsort++;
+ }
+}
+#endif
+
+void
+_sethostdnsent(int stayopen)
+{
+ res_state statp;
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1)
+ return;
+ if (stayopen)
+ statp->options |= RES_STAYOPEN | RES_USEVC;
+}
+
+void
+_endhostdnsent()
+{
+ res_state statp;
+
+ statp = __res_state();
+ statp->options &= ~(RES_STAYOPEN | RES_USEVC);
+ res_nclose(statp);
+}
diff --git a/lib/libc/net/gethostbyht.c b/lib/libc/net/gethostbyht.c
new file mode 100644
index 0000000..4253d49
--- /dev/null
+++ b/lib/libc/net/gethostbyht.c
@@ -0,0 +1,339 @@
+/*-
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+#include <arpa/nameser.h> /* XXX */
+#include <resolv.h> /* XXX */
+#include "netdb_private.h"
+
+void
+_sethosthtent(int f, struct hostent_data *hed)
+{
+ if (!hed->hostf)
+ hed->hostf = fopen(_PATH_HOSTS, "r");
+ else
+ rewind(hed->hostf);
+ hed->stayopen = f;
+}
+
+void
+_endhosthtent(struct hostent_data *hed)
+{
+ if (hed->hostf && !hed->stayopen) {
+ (void) fclose(hed->hostf);
+ hed->hostf = NULL;
+ }
+}
+
+static int
+gethostent_p(struct hostent *he, struct hostent_data *hed, int mapped,
+ res_state statp)
+{
+ char *p, *bp, *ep;
+ char *cp, **q;
+ int af, len;
+ char hostbuf[BUFSIZ + 1];
+
+ if (!hed->hostf && !(hed->hostf = fopen(_PATH_HOSTS, "r"))) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+ again:
+ if (!(p = fgets(hostbuf, sizeof hostbuf, hed->hostf))) {
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ return (-1);
+ }
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp != NULL)
+ *cp = '\0';
+ if (!(cp = strpbrk(p, " \t")))
+ goto again;
+ *cp++ = '\0';
+ if (inet_pton(AF_INET6, p, hed->host_addr) > 0) {
+ af = AF_INET6;
+ len = IN6ADDRSZ;
+ } else if (inet_pton(AF_INET, p, hed->host_addr) > 0) {
+ if (mapped) {
+ _map_v4v6_address((char *)hed->host_addr,
+ (char *)hed->host_addr);
+ af = AF_INET6;
+ len = IN6ADDRSZ;
+ } else {
+ af = AF_INET;
+ len = INADDRSZ;
+ }
+ } else {
+ goto again;
+ }
+ hed->h_addr_ptrs[0] = (char *)hed->host_addr;
+ hed->h_addr_ptrs[1] = NULL;
+ he->h_addr_list = hed->h_addr_ptrs;
+ he->h_length = len;
+ he->h_addrtype = af;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ bp = hed->hostbuf;
+ ep = hed->hostbuf + sizeof hed->hostbuf;
+ he->h_name = bp;
+ q = he->h_aliases = hed->host_aliases;
+ if ((p = strpbrk(cp, " \t")) != NULL)
+ *p++ = '\0';
+ len = strlen(cp) + 1;
+ if (ep - bp < len) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ strlcpy(bp, cp, ep - bp);
+ bp += len;
+ cp = p;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q >= &hed->host_aliases[_MAXALIASES - 1])
+ break;
+ if ((p = strpbrk(cp, " \t")) != NULL)
+ *p++ = '\0';
+ len = strlen(cp) + 1;
+ if (ep - bp < len)
+ break;
+ strlcpy(bp, cp, ep - bp);
+ *q++ = bp;
+ bp += len;
+ cp = p;
+ }
+ *q = NULL;
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ return (0);
+}
+
+int
+gethostent_r(struct hostent *hptr, char *buffer, size_t buflen,
+ struct hostent **result, int *h_errnop)
+{
+ struct hostent_data *hed;
+ struct hostent he;
+ res_state statp;
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+ if (gethostent_p(&he, hed, statp->options & RES_USE_INET6, statp) != 0)
+ return (-1);
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return ((errno != 0) ? errno : -1);
+ }
+ *result = hptr;
+ return (0);
+}
+
+struct hostent *
+gethostent(void)
+{
+ struct hostdata *hd;
+ struct hostent *rval;
+ int ret_h_errno;
+
+ if ((hd = __hostdata_init()) == NULL)
+ return (NULL);
+ if (gethostent_r(&hd->host, hd->data, sizeof(hd->data), &rval,
+ &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
+}
+
+int
+_ht_gethostbyname(void *rval, void *cb_data, va_list ap)
+{
+ const char *name;
+ int af;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
+ struct hostent_data *hed;
+ char **cp;
+ res_state statp;
+ int error;
+
+ name = va_arg(ap, const char *);
+ af = va_arg(ap, int);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ _sethosthtent(0, hed);
+ while ((error = gethostent_p(&he, hed, 0, statp)) == 0) {
+ if (he.h_addrtype != af)
+ continue;
+ if (he.h_addrtype == AF_INET &&
+ statp->options & RES_USE_INET6) {
+ _map_v4v6_address(he.h_addr, he.h_addr);
+ he.h_length = IN6ADDRSZ;
+ he.h_addrtype = AF_INET6;
+ }
+ if (strcasecmp(he.h_name, name) == 0)
+ break;
+ for (cp = he.h_aliases; *cp != 0; cp++)
+ if (strcasecmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ _endhosthtent(hed);
+
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
+}
+
+int
+_ht_gethostbyaddr(void *rval, void *cb_data, va_list ap)
+{
+ const void *addr;
+ socklen_t len;
+ int af;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
+ struct hostent_data *hed;
+ res_state statp;
+ int error;
+
+ addr = va_arg(ap, const void *);
+ len = va_arg(ap, socklen_t);
+ af = va_arg(ap, int);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ _sethosthtent(0, hed);
+ while ((error = gethostent_p(&he, hed, 0, statp)) == 0)
+ if (he.h_addrtype == af && !bcmp(he.h_addr, addr, len)) {
+ if (he.h_addrtype == AF_INET &&
+ statp->options & RES_USE_INET6) {
+ _map_v4v6_address(he.h_addr, he.h_addr);
+ he.h_length = IN6ADDRSZ;
+ he.h_addrtype = AF_INET6;
+ }
+ break;
+ }
+ _endhosthtent(hed);
+
+ if (error != 0)
+ return (NS_NOTFOUND);
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
+}
diff --git a/lib/libc/net/gethostbyname.3 b/lib/libc/net/gethostbyname.3
new file mode 100644
index 0000000..9b8c0b9
--- /dev/null
+++ b/lib/libc/net/gethostbyname.3
@@ -0,0 +1,375 @@
+.\" Copyright (c) 1983, 1987, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95
+.\" $FreeBSD$
+.\"
+.Dd May 12, 2006
+.Dt GETHOSTBYNAME 3
+.Os
+.Sh NAME
+.Nm gethostbyname ,
+.Nm gethostbyname2 ,
+.Nm gethostbyaddr ,
+.Nm gethostent ,
+.Nm sethostent ,
+.Nm endhostent ,
+.Nm herror ,
+.Nm hstrerror
+.Nd get network host entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In netdb.h
+.Vt int h_errno ;
+.Ft struct hostent *
+.Fn gethostbyname "const char *name"
+.Ft struct hostent *
+.Fn gethostbyname2 "const char *name" "int af"
+.Ft struct hostent *
+.Fn gethostbyaddr "const void *addr" "socklen_t len" "int type"
+.Ft struct hostent *
+.Fn gethostent void
+.Ft void
+.Fn sethostent "int stayopen"
+.Ft void
+.Fn endhostent void
+.Ft void
+.Fn herror "const char *string"
+.Ft const char *
+.Fn hstrerror "int err"
+.Sh DESCRIPTION
+.Bf -symbolic
+The
+.Xr getaddrinfo 3
+and
+.Xr getnameinfo 3
+functions are preferred over the
+.Fn gethostbyname ,
+.Fn gethostbyname2 ,
+and
+.Fn gethostbyaddr
+functions.
+.Ef
+.Pp
+The
+.Fn gethostbyname ,
+.Fn gethostbyname2
+and
+.Fn gethostbyaddr
+functions
+each return a pointer to an object with the
+following structure describing an internet host
+referenced by name or by address, respectively.
+.Pp
+The
+.Fa name
+argument passed to
+.Fn gethostbyname
+or
+.Fn gethostbyname2
+should point to a
+.Dv NUL Ns -terminated
+hostname.
+The
+.Fa addr
+argument passed to
+.Fn gethostbyaddr
+should point to an address which is
+.Fa len
+bytes long,
+in binary form
+(i.e., not an IP address in human readable
+.Tn ASCII
+form).
+The
+.Fa type
+argument specifies the address family
+(e.g.\&
+.Dv AF_INET , AF_INET6 ,
+etc.) of this address.
+.Pp
+The structure returned contains either the information obtained from the name
+server,
+.Xr named 8 ,
+broken-out fields from a line in
+.Pa /etc/hosts ,
+or database entries supplied by the
+.Xr yp 8
+system.
+The order of the lookups is controlled by the
+.Sq hosts
+entry in
+.Xr nsswitch.conf 5 .
+.Bd -literal
+struct hostent {
+ char *h_name; /* official name of host */
+ char **h_aliases; /* alias list */
+ int h_addrtype; /* host address type */
+ int h_length; /* length of address */
+ char **h_addr_list; /* list of addresses from name server */
+};
+#define h_addr h_addr_list[0] /* address, for backward compatibility */
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width h_addr_list
+.It Va h_name
+Official name of the host.
+.It Va h_aliases
+A
+.Dv NULL Ns -terminated
+array of alternate names for the host.
+.It Va h_addrtype
+The type of address being returned; usually
+.Dv AF_INET .
+.It Va h_length
+The length, in bytes, of the address.
+.It Va h_addr_list
+A
+.Dv NULL Ns -terminated
+array of network addresses for the host.
+Host addresses are returned in network byte order.
+.It Va h_addr
+The first address in
+.Va h_addr_list ;
+this is for backward compatibility.
+.El
+.Pp
+When using the nameserver,
+.Fn gethostbyname
+and
+.Fn gethostbyname2
+will search for the named host in the current domain and its parents
+unless the name ends in a dot.
+If the name contains no dot, and if the environment variable
+.Dq Ev HOSTALIASES
+contains the name of an alias file, the alias file will first be searched
+for an alias matching the input name.
+See
+.Xr hostname 7
+for the domain search procedure and the alias file format.
+.Pp
+The
+.Fn gethostbyname2
+function is an evolution of
+.Fn gethostbyname
+which is intended to allow lookups in address families other than
+.Dv AF_INET ,
+for example
+.Dv AF_INET6 .
+.Pp
+The
+.Fn sethostent
+function
+may be used to request the use of a connected
+.Tn TCP
+socket for queries.
+If the
+.Fa stayopen
+flag is non-zero,
+this sets the option to send all queries to the name server using
+.Tn TCP
+and to retain the connection after each call to
+.Fn gethostbyname ,
+.Fn gethostbyname2
+or
+.Fn gethostbyaddr .
+Otherwise, queries are performed using
+.Tn UDP
+datagrams.
+.Pp
+The
+.Fn endhostent
+function
+closes the
+.Tn TCP
+connection.
+.Pp
+The
+.Fn herror
+function writes a message to the diagnostic output consisting of the
+string argument
+.Fa string ,
+the constant string
+.Qq Li ":\ " ,
+and a message corresponding to the value of
+.Va h_errno .
+.Pp
+The
+.Fn hstrerror
+function returns a string which is the message text corresponding to the
+value of the
+.Fa err
+argument.
+.Sh FILES
+.Bl -tag -width /etc/nsswitch.conf -compact
+.It Pa /etc/hosts
+.It Pa /etc/nsswitch.conf
+.It Pa /etc/resolv.conf
+.El
+.Sh EXAMPLES
+Print out the hostname associated with a specific IP address:
+.Bd -literal -offset indent
+const char *ipstr = "127.0.0.1";
+struct in_addr ip;
+struct hostent *hp;
+
+if (!inet_aton(ipstr, &ip))
+ errx(1, "can't parse IP address %s", ipstr);
+
+if ((hp = gethostbyaddr((const void *)&ip,
+ sizeof ip, AF_INET)) == NULL)
+ errx(1, "no name associated with %s", ipstr);
+
+printf("name associated with %s is %s\en", ipstr, hp->h_name);
+.Ed
+.Sh DIAGNOSTICS
+Error return status from
+.Fn gethostbyname ,
+.Fn gethostbyname2
+and
+.Fn gethostbyaddr
+is indicated by return of a
+.Dv NULL
+pointer.
+The integer
+.Va h_errno
+may then be checked to see whether this is a temporary failure
+or an invalid or unknown host.
+The routine
+.Fn herror
+can be used to print an error message describing the failure.
+If its argument
+.Fa string
+is
+.Pf non- Dv NULL ,
+it is printed, followed by a colon and a space.
+The error message is printed with a trailing newline.
+.Pp
+The variable
+.Va h_errno
+can have the following values:
+.Bl -tag -width HOST_NOT_FOUND
+.It Dv HOST_NOT_FOUND
+No such host is known.
+.It Dv TRY_AGAIN
+This is usually a temporary error
+and means that the local server did not receive
+a response from an authoritative server.
+A retry at some later time may succeed.
+.It Dv NO_RECOVERY
+Some unexpected server failure was encountered.
+This is a non-recoverable error.
+.It Dv NO_DATA
+The requested name is valid but does not have an IP address;
+this is not a temporary error.
+This means that the name is known to the name server but there is no address
+associated with this name.
+Another type of request to the name server using this domain name
+will result in an answer;
+for example, a mail-forwarder may be registered for this domain.
+.El
+.Sh SEE ALSO
+.Xr getaddrinfo 3 ,
+.Xr getnameinfo 3 ,
+.Xr inet_aton 3 ,
+.Xr resolver 3 ,
+.Xr hosts 5 ,
+.Xr hostname 7 ,
+.Xr named 8
+.Sh CAVEAT
+The
+.Fn gethostent
+function
+is defined, and
+.Fn sethostent
+and
+.Fn endhostent
+are redefined,
+when
+.Lb libc
+is built to use only the routines to lookup in
+.Pa /etc/hosts
+and not the name server.
+.Pp
+The
+.Fn gethostent
+function
+reads the next line of
+.Pa /etc/hosts ,
+opening the file if necessary.
+.Pp
+The
+.Fn sethostent
+function
+opens and/or rewinds the file
+.Pa /etc/hosts .
+If the
+.Fa stayopen
+argument is non-zero,
+the file will not be closed after each call to
+.Fn gethostbyname ,
+.Fn gethostbyname2
+or
+.Fn gethostbyaddr .
+.Pp
+The
+.Fn endhostent
+function
+closes the file.
+.Sh HISTORY
+The
+.Fn herror
+function appeared in
+.Bx 4.3 .
+The
+.Fn endhostent ,
+.Fn gethostbyaddr ,
+.Fn gethostbyname ,
+.Fn gethostent ,
+and
+.Fn sethostent
+functions appeared in
+.Bx 4.2 .
+The
+.Fn gethostbyname2
+function first appeared in
+.Tn BIND
+version 4.9.4.
+.Sh BUGS
+These functions use a thread-specific data storage;
+if the data is needed for future use, it should be
+copied before any subsequent calls overwrite it.
+.Pp
+Though these functions are thread-safe,
+still it is recommended to use the
+.Xr getaddrinfo 3
+family of functions, instead.
+.Pp
+Only the Internet
+address format is currently understood.
diff --git a/lib/libc/net/gethostbynis.c b/lib/libc/net/gethostbynis.c
new file mode 100644
index 0000000..c0d5177
--- /dev/null
+++ b/lib/libc/net/gethostbynis.c
@@ -0,0 +1,352 @@
+/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+#include <resolv.h> /* XXX */
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include "netdb_private.h"
+
+#ifdef YP
+static int
+_gethostbynis(const char *name, char *map, int af, struct hostent *he,
+ struct hostent_data *hed)
+{
+ char *p, *bp, *ep;
+ char *cp, **q;
+ char *result;
+ int resultlen, size, addrok = 0;
+ char ypbuf[YPMAXRECORD + 2];
+ res_state statp;
+
+ statp = __res_state();
+ switch(af) {
+ case AF_INET:
+ size = NS_INADDRSZ;
+ break;
+ case AF_INET6:
+ size = NS_IN6ADDRSZ;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ if (hed->yp_domain == (char *)NULL)
+ if (yp_get_default_domain (&hed->yp_domain)) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ if (yp_match(hed->yp_domain, map, name, strlen(name), &result,
+ &resultlen)) {
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ return (-1);
+ }
+
+ /* avoid potential memory leak */
+ bcopy((char *)result, (char *)&ypbuf, resultlen);
+ ypbuf[resultlen] = '\0';
+ free(result);
+ result = (char *)&ypbuf;
+
+ if ((cp = strchr(result, '\n')))
+ *cp = '\0';
+
+ cp = strpbrk(result, " \t");
+ *cp++ = '\0';
+ he->h_addr_list = hed->h_addr_ptrs;
+ he->h_addr = (char *)hed->host_addr;
+ switch (af) {
+ case AF_INET:
+ addrok = inet_aton(result, (struct in_addr *)hed->host_addr);
+ if (addrok != 1)
+ break;
+ if (statp->options & RES_USE_INET6) {
+ _map_v4v6_address((char *)hed->host_addr,
+ (char *)hed->host_addr);
+ af = AF_INET6;
+ size = NS_IN6ADDRSZ;
+ }
+ break;
+ case AF_INET6:
+ addrok = inet_pton(af, result, hed->host_addr);
+ break;
+ }
+ if (addrok != 1) {
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ return (-1);
+ }
+ he->h_addr_list[1] = NULL;
+ he->h_length = size;
+ he->h_addrtype = af;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ bp = hed->hostbuf;
+ ep = hed->hostbuf + sizeof hed->hostbuf;
+ he->h_name = bp;
+ q = he->h_aliases = hed->host_aliases;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ size = strlen(cp) + 1;
+ if (ep - bp < size) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ strlcpy(bp, cp, ep - bp);
+ bp += size;
+ cp = p;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q >= &hed->host_aliases[_MAXALIASES - 1])
+ break;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ size = strlen(cp) + 1;
+ if (ep - bp < size)
+ break;
+ strlcpy(bp, cp, ep - bp);
+ *q++ = bp;
+ bp += size;
+ cp = p;
+ }
+ *q = NULL;
+ return (0);
+}
+
+static int
+_gethostbynisname_r(const char *name, int af, struct hostent *he,
+ struct hostent_data *hed)
+{
+ char *map;
+
+ switch (af) {
+ case AF_INET:
+ map = "hosts.byname";
+ break;
+ default:
+ map = "ipnodes.byname";
+ break;
+ }
+ return (_gethostbynis(name, map, af, he, hed));
+}
+
+static int
+_gethostbynisaddr_r(const void *addr, socklen_t len, int af,
+ struct hostent *he, struct hostent_data *hed)
+{
+ char *map;
+ char numaddr[46];
+
+ switch (af) {
+ case AF_INET:
+ map = "hosts.byaddr";
+ break;
+ default:
+ map = "ipnodes.byaddr";
+ break;
+ }
+ if (inet_ntop(af, addr, numaddr, sizeof(numaddr)) == NULL)
+ return (-1);
+ return (_gethostbynis(numaddr, map, af, he, hed));
+}
+#endif /* YP */
+
+/* XXX _gethostbynisname/_gethostbynisaddr only used by getipnodeby*() */
+struct hostent *
+_gethostbynisname(const char *name, int af)
+{
+#ifdef YP
+ struct hostent *he;
+ struct hostent_data *hed;
+ u_long oresopt;
+ int error;
+ res_state statp;
+
+ statp = __res_state();
+ if ((he = __hostent_init()) == NULL ||
+ (hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (NULL);
+ }
+
+ oresopt = statp->options;
+ statp->options &= ~RES_USE_INET6;
+ error = _gethostbynisname_r(name, af, he, hed);
+ statp->options = oresopt;
+ return (error == 0) ? he : NULL;
+#else
+ return (NULL);
+#endif
+}
+
+struct hostent *
+_gethostbynisaddr(const void *addr, socklen_t len, int af)
+{
+#ifdef YP
+ struct hostent *he;
+ struct hostent_data *hed;
+ u_long oresopt;
+ int error;
+ res_state statp;
+
+ statp = __res_state();
+ if ((he = __hostent_init()) == NULL ||
+ (hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (NULL);
+ }
+
+ oresopt = statp->options;
+ statp->options &= ~RES_USE_INET6;
+ error = _gethostbynisaddr_r(addr, len, af, he, hed);
+ statp->options = oresopt;
+ return (error == 0) ? he : NULL;
+#else
+ return (NULL);
+#endif
+}
+
+int
+_nis_gethostbyname(void *rval, void *cb_data, va_list ap)
+{
+#ifdef YP
+ const char *name;
+ int af;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
+ struct hostent_data *hed;
+ res_state statp;
+
+ name = va_arg(ap, const char *);
+ af = va_arg(ap, int);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ if (_gethostbynisname_r(name, af, &he, hed) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
+#else
+ *((struct hostent **)rval) = NULL;
+ return (NS_UNAVAIL);
+#endif
+}
+
+int
+_nis_gethostbyaddr(void *rval, void *cb_data, va_list ap)
+{
+#ifdef YP
+ const void *addr;
+ socklen_t len;
+ int af;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct hostent *hptr, he;
+ struct hostent_data *hed;
+ res_state statp;
+
+ addr = va_arg(ap, const void *);
+ len = va_arg(ap, socklen_t);
+ af = va_arg(ap, int);
+ hptr = va_arg(ap, struct hostent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ *((struct hostent **)rval) = NULL;
+
+ statp = __res_state();
+ if ((hed = __hostent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ if (_gethostbynisaddr_r(addr, len, af, &he, hed) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_hostent(&he, hptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct hostent **)rval) = hptr;
+ return (NS_SUCCESS);
+#else
+ *((struct hostent **)rval) = NULL;
+ return (NS_UNAVAIL);
+#endif
+}
diff --git a/lib/libc/net/gethostnamadr.c b/lib/libc/net/gethostnamadr.c
new file mode 100644
index 0000000..2dc9d02
--- /dev/null
+++ b/lib/libc/net/gethostnamadr.c
@@ -0,0 +1,734 @@
+/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+#include <arpa/nameser.h> /* XXX hack for _res */
+#include <resolv.h> /* XXX hack for _res */
+#include "un-namespace.h"
+#include "netdb_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+
+extern int _ht_gethostbyname(void *, void *, va_list);
+extern int _dns_gethostbyname(void *, void *, va_list);
+extern int _nis_gethostbyname(void *, void *, va_list);
+extern int _ht_gethostbyaddr(void *, void *, va_list);
+extern int _dns_gethostbyaddr(void *, void *, va_list);
+extern int _nis_gethostbyaddr(void *, void *, va_list);
+
+static int gethostbyname_internal(const char *, int, struct hostent *, char *,
+ size_t, struct hostent **, int *, res_state);
+
+/* Host lookup order if nsswitch.conf is broken or nonexistant */
+static const ns_src default_src[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { NSSRC_DNS, NS_SUCCESS },
+ { 0 }
+};
+#ifdef NS_CACHING
+static int host_id_func(char *, size_t *, va_list, void *);
+static int host_marshal_func(char *, size_t *, void *, va_list, void *);
+static int host_unmarshal_func(char *, size_t, void *, va_list, void *);
+#endif
+
+NETDB_THREAD_ALLOC(hostent)
+NETDB_THREAD_ALLOC(hostent_data)
+NETDB_THREAD_ALLOC(hostdata)
+
+static void
+hostent_free(void *ptr)
+{
+ free(ptr);
+}
+
+static void
+hostent_data_free(void *ptr)
+{
+ struct hostent_data *hed = ptr;
+
+ if (hed == NULL)
+ return;
+ hed->stayopen = 0;
+ _endhosthtent(hed);
+ free(hed);
+}
+
+static void
+hostdata_free(void *ptr)
+{
+ free(ptr);
+}
+
+int
+__copy_hostent(struct hostent *he, struct hostent *hptr, char *buf,
+ size_t buflen)
+{
+ char *cp;
+ char **ptr;
+ int i, n;
+ int nptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ nptr = 2; /* NULL ptrs */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; he->h_addr_list[i]; i++, nptr++) {
+ len += he->h_length;
+ }
+ for (i = 0; he->h_aliases[i]; i++, nptr++) {
+ len += strlen(he->h_aliases[i]) + 1;
+ }
+ len += strlen(he->h_name) + 1;
+ len += nptr * sizeof(char*);
+
+ if (len > buflen) {
+ errno = ERANGE;
+ return (-1);
+ }
+
+ /* copy address size and type */
+ hptr->h_addrtype = he->h_addrtype;
+ n = hptr->h_length = he->h_length;
+
+ ptr = (char **)ALIGN(buf);
+ cp = (char *)ALIGN(buf) + nptr * sizeof(char *);
+
+ /* copy address list */
+ hptr->h_addr_list = ptr;
+ for (i = 0; he->h_addr_list[i]; i++ , ptr++) {
+ memcpy(cp, he->h_addr_list[i], n);
+ hptr->h_addr_list[i] = cp;
+ cp += n;
+ }
+ hptr->h_addr_list[i] = NULL;
+ ptr++;
+
+ /* copy official name */
+ n = strlen(he->h_name) + 1;
+ strcpy(cp, he->h_name);
+ hptr->h_name = cp;
+ cp += n;
+
+ /* copy aliases */
+ hptr->h_aliases = ptr;
+ for (i = 0 ; he->h_aliases[i]; i++) {
+ n = strlen(he->h_aliases[i]) + 1;
+ strcpy(cp, he->h_aliases[i]);
+ hptr->h_aliases[i] = cp;
+ cp += n;
+ }
+ hptr->h_aliases[i] = NULL;
+
+ return (0);
+}
+
+#ifdef NS_CACHING
+static int
+host_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
+{
+ res_state statp;
+ u_long res_options;
+
+ const int op_id = 1;
+ char *str;
+ void *addr;
+ socklen_t len;
+ int type;
+
+ size_t desired_size, size;
+ enum nss_lookup_type lookup_type;
+ char *p;
+ int res = NS_UNAVAIL;
+
+ statp = __res_state();
+ res_options = statp->options & (RES_RECURSE | RES_DEFNAMES |
+ RES_DNSRCH | RES_NOALIASES | RES_USE_INET6);
+
+ lookup_type = (enum nss_lookup_type)cache_mdata;
+ switch (lookup_type) {
+ case nss_lt_name:
+ str = va_arg(ap, char *);
+ type = va_arg(ap, int);
+
+ size = strlen(str);
+ desired_size = sizeof(res_options) + sizeof(int) +
+ sizeof(enum nss_lookup_type) + sizeof(int) + size + 1;
+
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ p = buffer;
+
+ memcpy(p, &res_options, sizeof(res_options));
+ p += sizeof(res_options);
+
+ memcpy(p, &op_id, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, &lookup_type, sizeof(enum nss_lookup_type));
+ p += sizeof(int);
+
+ memcpy(p, &type, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, str, size + 1);
+
+ res = NS_SUCCESS;
+ break;
+ case nss_lt_id:
+ addr = va_arg(ap, void *);
+ len = va_arg(ap, socklen_t);
+ type = va_arg(ap, int);
+
+ desired_size = sizeof(res_options) + sizeof(int) +
+ sizeof(enum nss_lookup_type) + sizeof(int) +
+ sizeof(socklen_t) + len;
+
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ p = buffer;
+ memcpy(p, &res_options, sizeof(res_options));
+ p += sizeof(res_options);
+
+ memcpy(p, &op_id, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, &lookup_type, sizeof(enum nss_lookup_type));
+ p += sizeof(int);
+
+ memcpy(p, &type, sizeof(int));
+ p += sizeof(int);
+
+ memcpy(p, &len, sizeof(socklen_t));
+ p += sizeof(socklen_t);
+
+ memcpy(p, addr, len);
+
+ res = NS_SUCCESS;
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+fin:
+ *buffer_size = desired_size;
+ return (res);
+}
+
+static int
+host_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *str;
+ void *addr;
+ socklen_t len;
+ int type;
+ struct hostent *ht;
+
+ struct hostent new_ht;
+ size_t desired_size, aliases_size, addr_size, size;
+ char *p, **iter;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ str = va_arg(ap, char *);
+ type = va_arg(ap, int);
+ break;
+ case nss_lt_id:
+ addr = va_arg(ap, void *);
+ len = va_arg(ap, socklen_t);
+ type = va_arg(ap, int);
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+ ht = va_arg(ap, struct hostent *);
+
+ desired_size = _ALIGNBYTES + sizeof(struct hostent) + sizeof(char *);
+ if (ht->h_name != NULL)
+ desired_size += strlen(ht->h_name) + 1;
+
+ if (ht->h_aliases != NULL) {
+ aliases_size = 0;
+ for (iter = ht->h_aliases; *iter; ++iter) {
+ desired_size += strlen(*iter) + 1;
+ ++aliases_size;
+ }
+
+ desired_size += _ALIGNBYTES +
+ (aliases_size + 1) * sizeof(char *);
+ }
+
+ if (ht->h_addr_list != NULL) {
+ addr_size = 0;
+ for (iter = ht->h_addr_list; *iter; ++iter)
+ ++addr_size;
+
+ desired_size += addr_size * _ALIGN(ht->h_length);
+ desired_size += _ALIGNBYTES + (addr_size + 1) * sizeof(char *);
+ }
+
+ if (desired_size > *buffer_size) {
+ /* this assignment is here for future use */
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ memcpy(&new_ht, ht, sizeof(struct hostent));
+ memset(buffer, 0, desired_size);
+
+ *buffer_size = desired_size;
+ p = buffer + sizeof(struct hostent) + sizeof(char *);
+ memcpy(buffer + sizeof(struct hostent), &p, sizeof(char *));
+ p = (char *)_ALIGN(p);
+
+ if (new_ht.h_name != NULL) {
+ size = strlen(new_ht.h_name);
+ memcpy(p, new_ht.h_name, size);
+ new_ht.h_name = p;
+ p += size + 1;
+ }
+
+ if (new_ht.h_aliases != NULL) {
+ p = (char *)_ALIGN(p);
+ memcpy(p, new_ht.h_aliases, sizeof(char *) * aliases_size);
+ new_ht.h_aliases = (char **)p;
+ p += sizeof(char *) * (aliases_size + 1);
+
+ for (iter = new_ht.h_aliases; *iter; ++iter) {
+ size = strlen(*iter);
+ memcpy(p, *iter, size);
+ *iter = p;
+ p += size + 1;
+ }
+ }
+
+ if (new_ht.h_addr_list != NULL) {
+ p = (char *)_ALIGN(p);
+ memcpy(p, new_ht.h_addr_list, sizeof(char *) * addr_size);
+ new_ht.h_addr_list = (char **)p;
+ p += sizeof(char *) * (addr_size + 1);
+
+ size = _ALIGN(new_ht.h_length);
+ for (iter = new_ht.h_addr_list; *iter; ++iter) {
+ memcpy(p, *iter, size);
+ *iter = p;
+ p += size + 1;
+ }
+ }
+ memcpy(buffer, &new_ht, sizeof(struct hostent));
+ return (NS_SUCCESS);
+}
+
+static int
+host_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *str;
+ void *addr;
+ socklen_t len;
+ int type;
+ struct hostent *ht;
+
+ char *p;
+ char **iter;
+ char *orig_buf;
+ size_t orig_buf_size;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ str = va_arg(ap, char *);
+ type = va_arg(ap, int);
+ break;
+ case nss_lt_id:
+ addr = va_arg(ap, void *);
+ len = va_arg(ap, socklen_t);
+ type = va_arg(ap, int);
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ ht = va_arg(ap, struct hostent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+
+ if (orig_buf_size <
+ buffer_size - sizeof(struct hostent) - sizeof(char *)) {
+ errno = ERANGE;
+ return (NS_RETURN);
+ }
+
+ memcpy(ht, buffer, sizeof(struct hostent));
+ memcpy(&p, buffer + sizeof(struct hostent), sizeof(char *));
+
+ orig_buf = (char *)_ALIGN(orig_buf);
+ memcpy(orig_buf, buffer + sizeof(struct hostent) + sizeof(char *) +
+ _ALIGN(p) - (size_t)p,
+ buffer_size - sizeof(struct hostent) - sizeof(char *) -
+ _ALIGN(p) + (size_t)p);
+ p = (char *)_ALIGN(p);
+
+ NS_APPLY_OFFSET(ht->h_name, orig_buf, p, char *);
+ if (ht->h_aliases != NULL) {
+ NS_APPLY_OFFSET(ht->h_aliases, orig_buf, p, char **);
+
+ for (iter = ht->h_aliases; *iter; ++iter)
+ NS_APPLY_OFFSET(*iter, orig_buf, p, char *);
+ }
+
+ if (ht->h_addr_list != NULL) {
+ NS_APPLY_OFFSET(ht->h_addr_list, orig_buf, p, char **);
+
+ for (iter = ht->h_addr_list; *iter; ++iter)
+ NS_APPLY_OFFSET(*iter, orig_buf, p, char *);
+ }
+
+ *((struct hostent **)retval) = ht;
+ return (NS_SUCCESS);
+}
+#endif /* NS_CACHING */
+
+static int
+fakeaddr(const char *name, int af, struct hostent *hp, char *buf,
+ size_t buflen, res_state statp)
+{
+ struct hostent_data *hed;
+ struct hostent he;
+
+ if ((hed = __hostent_data_init()) == NULL) {
+ errno = ENOMEM;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ if ((af != AF_INET ||
+ inet_aton(name, (struct in_addr *)hed->host_addr) != 1) &&
+ inet_pton(af, name, hed->host_addr) != 1) {
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ return (-1);
+ }
+ strncpy(hed->hostbuf, name, MAXDNAME);
+ hed->hostbuf[MAXDNAME] = '\0';
+ if (af == AF_INET && (statp->options & RES_USE_INET6) != 0U) {
+ _map_v4v6_address((char *)hed->host_addr,
+ (char *)hed->host_addr);
+ af = AF_INET6;
+ }
+ he.h_addrtype = af;
+ switch(af) {
+ case AF_INET:
+ he.h_length = NS_INADDRSZ;
+ break;
+ case AF_INET6:
+ he.h_length = NS_IN6ADDRSZ;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+ he.h_name = hed->hostbuf;
+ he.h_aliases = hed->host_aliases;
+ hed->host_aliases[0] = NULL;
+ hed->h_addr_ptrs[0] = (char *)hed->host_addr;
+ hed->h_addr_ptrs[1] = NULL;
+ he.h_addr_list = hed->h_addr_ptrs;
+ if (__copy_hostent(&he, hp, buf, buflen) != 0) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+ RES_SET_H_ERRNO(statp, NETDB_SUCCESS);
+ return (0);
+}
+
+int
+gethostbyname_r(const char *name, struct hostent *he, char *buffer,
+ size_t buflen, struct hostent **result, int *h_errnop)
+{
+ res_state statp;
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+ if (statp->options & RES_USE_INET6) {
+ if (fakeaddr(name, AF_INET, he, buffer, buflen, statp) == 0) {
+ *result = he;
+ return (0);
+ }
+ if (gethostbyname_internal(name, AF_INET6, he, buffer, buflen,
+ result, h_errnop, statp) == 0)
+ return (0);
+ }
+ return (gethostbyname_internal(name, AF_INET, he, buffer, buflen,
+ result, h_errnop, statp));
+}
+
+int
+gethostbyname2_r(const char *name, int af, struct hostent *he, char *buffer,
+ size_t buflen, struct hostent **result, int *h_errnop)
+{
+ res_state statp;
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return (-1);
+ }
+ return (gethostbyname_internal(name, af, he, buffer, buflen, result,
+ h_errnop, statp));
+}
+
+int
+gethostbyname_internal(const char *name, int af, struct hostent *hp, char *buf,
+ size_t buflen, struct hostent **result, int *h_errnop, res_state statp)
+{
+ const char *cp;
+ int rval, ret_errno = 0;
+ char abuf[MAXDNAME];
+
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ hosts, (void *)nss_lt_name,
+ host_id_func, host_marshal_func, host_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ NS_FILES_CB(_ht_gethostbyname, NULL)
+ { NSSRC_DNS, _dns_gethostbyname, NULL },
+ NS_NIS_CB(_nis_gethostbyname, NULL) /* force -DHESIOD */
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { 0 }
+ };
+
+ switch (af) {
+ case AF_INET:
+ case AF_INET6:
+ break;
+ default:
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+
+ /*
+ * if there aren't any dots, it could be a user-level alias.
+ * this is also done in res_query() since we are not the only
+ * function that looks up host names.
+ */
+ if (!strchr(name, '.') &&
+ (cp = res_hostalias(statp, name, abuf, sizeof abuf)))
+ name = cp;
+
+ if (fakeaddr(name, af, hp, buf, buflen, statp) == 0) {
+ *result = hp;
+ return (0);
+ }
+
+ rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS,
+ "gethostbyname2_r", default_src, name, af, hp, buf, buflen,
+ &ret_errno, h_errnop);
+
+ if (rval != NS_SUCCESS) {
+ errno = ret_errno;
+ return ((ret_errno != 0) ? ret_errno : -1);
+ }
+ return (0);
+}
+
+int
+gethostbyaddr_r(const void *addr, socklen_t len, int af, struct hostent *hp,
+ char *buf, size_t buflen, struct hostent **result, int *h_errnop)
+{
+ const u_char *uaddr = (const u_char *)addr;
+ const struct in6_addr *addr6;
+ socklen_t size;
+ int rval, ret_errno = 0;
+ res_state statp;
+
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ hosts, (void *)nss_lt_id,
+ host_id_func, host_marshal_func, host_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ NS_FILES_CB(_ht_gethostbyaddr, NULL)
+ { NSSRC_DNS, _dns_gethostbyaddr, NULL },
+ NS_NIS_CB(_nis_gethostbyaddr, NULL) /* force -DHESIOD */
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { 0 }
+ };
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+
+ if (af == AF_INET6 && len == NS_IN6ADDRSZ) {
+ addr6 = (const struct in6_addr *)addr;
+ if (IN6_IS_ADDR_LINKLOCAL(addr6)) {
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+ if (IN6_IS_ADDR_V4MAPPED(addr6) ||
+ IN6_IS_ADDR_V4COMPAT(addr6)) {
+ /* Unmap. */
+ uaddr += NS_IN6ADDRSZ - NS_INADDRSZ;
+ af = AF_INET;
+ len = NS_INADDRSZ;
+ }
+ }
+ switch (af) {
+ case AF_INET:
+ size = NS_INADDRSZ;
+ break;
+ case AF_INET6:
+ size = NS_IN6ADDRSZ;
+ break;
+ default:
+ errno = EAFNOSUPPORT;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+ if (size != len) {
+ errno = EINVAL;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+
+ rval = _nsdispatch((void *)result, dtab, NSDB_HOSTS,
+ "gethostbyaddr_r", default_src, uaddr, len, af, hp, buf, buflen,
+ &ret_errno, h_errnop);
+
+ if (rval != NS_SUCCESS) {
+ errno = ret_errno;
+ return ((ret_errno != 0) ? ret_errno : -1);
+ }
+ return (0);
+}
+
+struct hostent *
+gethostbyname(const char *name)
+{
+ struct hostdata *hd;
+ struct hostent *rval;
+ int ret_h_errno;
+
+ if ((hd = __hostdata_init()) == NULL)
+ return (NULL);
+ if (gethostbyname_r(name, &hd->host, hd->data, sizeof(hd->data), &rval,
+ &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
+}
+
+struct hostent *
+gethostbyname2(const char *name, int af)
+{
+ struct hostdata *hd;
+ struct hostent *rval;
+ int ret_h_errno;
+
+ if ((hd = __hostdata_init()) == NULL)
+ return (NULL);
+ if (gethostbyname2_r(name, af, &hd->host, hd->data, sizeof(hd->data),
+ &rval, &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
+}
+
+struct hostent *
+gethostbyaddr(const void *addr, socklen_t len, int af)
+{
+ struct hostdata *hd;
+ struct hostent *rval;
+ int ret_h_errno;
+
+ if ((hd = __hostdata_init()) == NULL)
+ return (NULL);
+ if (gethostbyaddr_r(addr, len, af, &hd->host, hd->data,
+ sizeof(hd->data), &rval, &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
+}
+
+void
+sethostent(int stayopen)
+{
+ struct hostent_data *hed;
+
+ if ((hed = __hostent_data_init()) == NULL)
+ return;
+ _sethosthtent(stayopen, hed);
+ _sethostdnsent(stayopen);
+}
+
+void
+endhostent(void)
+{
+ struct hostent_data *hed;
+
+ if ((hed = __hostent_data_init()) == NULL)
+ return;
+ _endhosthtent(hed);
+ _endhostdnsent();
+}
diff --git a/lib/libc/net/getifaddrs.3 b/lib/libc/net/getifaddrs.3
new file mode 100644
index 0000000..a12cd00
--- /dev/null
+++ b/lib/libc/net/getifaddrs.3
@@ -0,0 +1,167 @@
+.\" $KAME: getifaddrs.3,v 1.4 2000/05/17 14:13:14 itojun Exp $
+.\" BSDI getifaddrs.3,v 2.5 2000/02/23 14:51:59 dab Exp
+.\"
+.\" Copyright (c) 1995, 1999
+.\" Berkeley Software Design, Inc. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 12, 1995
+.Dt GETIFADDRS 3
+.Os
+.Sh NAME
+.Nm getifaddrs
+.Nd get interface addresses
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In ifaddrs.h
+.Ft int
+.Fn getifaddrs "struct ifaddrs **ifap"
+.Ft void
+.Fn freeifaddrs "struct ifaddrs *ifp"
+.Sh DESCRIPTION
+The
+.Fn getifaddrs
+function stores a reference to a linked list of the network interfaces
+on the local machine in the memory referenced by
+.Fa ifap .
+The list consists of
+.Nm ifaddrs
+structures, as defined in the include file
+.In ifaddrs.h .
+The
+.Nm ifaddrs
+structure contains at least the following entries:
+.Bd -literal
+ struct ifaddrs *ifa_next; /* Pointer to next struct */
+ char *ifa_name; /* Interface name */
+ u_int ifa_flags; /* Interface flags */
+ struct sockaddr *ifa_addr; /* Interface address */
+ struct sockaddr *ifa_netmask; /* Interface netmask */
+ struct sockaddr *ifa_broadaddr; /* Interface broadcast address */
+ struct sockaddr *ifa_dstaddr; /* P2P interface destination */
+ void *ifa_data; /* Address specific data */
+.Ed
+.Pp
+The
+.Li ifa_next
+field contains a pointer to the next structure on the list.
+This field is
+.Dv NULL
+in last structure on the list.
+.Pp
+The
+.Li ifa_name
+field contains the interface name.
+.Pp
+The
+.Li ifa_flags
+field contains the interface flags, as set by
+.Xr ifconfig 8
+utility.
+.Pp
+The
+.Li ifa_addr
+field references either the address of the interface or the link level
+address of the interface, if one exists, otherwise it is NULL.
+(The
+.Li sa_family
+field of the
+.Li ifa_addr
+field should be consulted to determine the format of the
+.Li ifa_addr
+address.)
+.Pp
+The
+.Li ifa_netmask
+field references the netmask associated with
+.Li ifa_addr ,
+if one is set, otherwise it is NULL.
+.Pp
+The
+.Li ifa_broadaddr
+field,
+which should only be referenced for non-P2P interfaces,
+references the broadcast address associated with
+.Li ifa_addr ,
+if one exists, otherwise it is NULL.
+.Pp
+The
+.Li ifa_dstaddr
+field references the destination address on a P2P interface,
+if one exists, otherwise it is NULL.
+.Pp
+The
+.Li ifa_data
+field references address family specific data.
+For
+.Dv AF_LINK
+addresses it contains a pointer to the
+.Fa struct if_data
+(as defined in include file
+.In net/if.h )
+which contains various interface attributes and statistics.
+For all other address families, it contains a pointer to the
+.Fa struct ifa_data
+(as defined in include file
+.In net/if.h )
+which contains per-address interface statistics.
+.Pp
+The data returned by
+.Fn getifaddrs
+is dynamically allocated and should be freed using
+.Fn freeifaddrs
+when no longer needed.
+.Sh RETURN VALUES
+.Rv -std getifaddrs
+.Sh ERRORS
+The
+.Fn getifaddrs
+may fail and set
+.Va errno
+for any of the errors specified for the library routines
+.Xr ioctl 2 ,
+.Xr socket 2 ,
+.Xr malloc 3
+or
+.Xr sysctl 3 .
+.Sh SEE ALSO
+.Xr ioctl 2 ,
+.Xr socket 2 ,
+.Xr sysctl 3 ,
+.Xr networking 4 ,
+.Xr ifconfig 8
+.Sh HISTORY
+The
+.Nm
+implementation first appeared in BSDi
+.Bsx .
+.Sh BUGS
+If both
+.In net/if.h
+and
+.In ifaddrs.h
+are being included,
+.In net/if.h
+.Em must
+be included before
+.In ifaddrs.h .
diff --git a/lib/libc/net/getifaddrs.c b/lib/libc/net/getifaddrs.c
new file mode 100644
index 0000000..f8633d5
--- /dev/null
+++ b/lib/libc/net/getifaddrs.c
@@ -0,0 +1,343 @@
+/* $KAME: getifaddrs.c,v 1.9 2001/08/20 02:31:20 itojun Exp $ */
+
+/*
+ * Copyright (c) 1995, 1999
+ * Berkeley Software Design, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * BSDI getifaddrs.c,v 2.12 2000/02/23 14:51:59 dab Exp
+ */
+/*
+ * NOTE: SIOCGIFCONF case is not LP64 friendly. it also does not perform
+ * try-and-error for region size.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#ifdef NET_RT_IFLIST
+#include <sys/param.h>
+#include <net/route.h>
+#include <sys/sysctl.h>
+#include <net/if_dl.h>
+#endif
+
+#include <errno.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#if !defined(AF_LINK)
+#define SA_LEN(sa) sizeof(struct sockaddr)
+#endif
+
+#if !defined(SA_LEN)
+#define SA_LEN(sa) (sa)->sa_len
+#endif
+
+#define SALIGN (sizeof(long) - 1)
+#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : (SALIGN + 1))
+
+#ifndef ALIGNBYTES
+/*
+ * On systems with a routing socket, ALIGNBYTES should match the value
+ * that the kernel uses when building the messages.
+ */
+#define ALIGNBYTES XXX
+#endif
+#ifndef ALIGN
+#define ALIGN(p) (((u_long)(p) + ALIGNBYTES) &~ ALIGNBYTES)
+#endif
+
+#define MAX_SYSCTL_TRY 5
+
+int
+getifaddrs(struct ifaddrs **pif)
+{
+ int icnt = 1;
+ int dcnt = 0;
+ int ncnt = 0;
+ int ntry = 0;
+ int mib[6];
+ size_t needed;
+ char *buf;
+ char *next;
+ struct ifaddrs *cif = 0;
+ char *p, *p0;
+ struct rt_msghdr *rtm;
+ struct if_msghdrl *ifm;
+ struct ifa_msghdrl *ifam;
+ struct sockaddr_dl *dl;
+ struct sockaddr *sa;
+ struct ifaddrs *ifa, *ift;
+ struct if_data *if_data;
+ u_short idx = 0;
+ int i;
+ size_t len, alen;
+ char *data;
+ char *names;
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0; /* protocol */
+ mib[3] = 0; /* wildcard address family */
+ mib[4] = NET_RT_IFLISTL;/* extra fields for extensible msghdr structs */
+ mib[5] = 0; /* no flags */
+ do {
+ /*
+ * We'll try to get addresses several times in case that
+ * the number of addresses is unexpectedly increased during
+ * the two sysctl calls. This should rarely happen, but we'll
+ * try to do our best for applications that assume success of
+ * this library (which should usually be the case).
+ * Portability note: since FreeBSD does not add margin of
+ * memory at the first sysctl, the possibility of failure on
+ * the second sysctl call is a bit higher.
+ */
+
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+ return (-1);
+ if ((buf = malloc(needed)) == NULL)
+ return (-1);
+ if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
+ if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
+ free(buf);
+ return (-1);
+ }
+ free(buf);
+ buf = NULL;
+ }
+ } while (buf == NULL);
+
+ for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)(void *)next;
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+ switch (rtm->rtm_type) {
+ case RTM_IFINFO:
+ ifm = (struct if_msghdrl *)(void *)rtm;
+ if (ifm->ifm_addrs & RTA_IFP) {
+ idx = ifm->ifm_index;
+ ++icnt;
+ if_data = IF_MSGHDRL_IFM_DATA(ifm);
+ dcnt += if_data->ifi_datalen;
+ dl = (struct sockaddr_dl *)IF_MSGHDRL_RTA(ifm);
+ dcnt += SA_RLEN((struct sockaddr *)(void*)dl) +
+ ALIGNBYTES;
+ ncnt += dl->sdl_nlen + 1;
+ } else
+ idx = 0;
+ break;
+
+ case RTM_NEWADDR:
+ ifam = (struct ifa_msghdrl *)(void *)rtm;
+ if (idx && ifam->ifam_index != idx)
+ abort(); /* this cannot happen */
+
+#define RTA_MASKS (RTA_NETMASK | RTA_IFA | RTA_BRD)
+ if (idx == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
+ break;
+ p = (char *)IFA_MSGHDRL_RTA(ifam);
+ ++icnt;
+ if_data = IFA_MSGHDRL_IFAM_DATA(ifam);
+ dcnt += if_data->ifi_datalen + ALIGNBYTES;
+
+ /* Scan to look for length of address */
+ alen = 0;
+ for (p0 = p, i = 0; i < RTAX_MAX; i++) {
+ if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
+ == 0)
+ continue;
+ sa = (struct sockaddr *)(void *)p;
+ len = SA_RLEN(sa);
+ if (i == RTAX_IFA) {
+ alen = len;
+ break;
+ }
+ p += len;
+ }
+ for (p = p0, i = 0; i < RTAX_MAX; i++) {
+ if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
+ == 0)
+ continue;
+ sa = (struct sockaddr *)(void *)p;
+ len = SA_RLEN(sa);
+ if (i == RTAX_NETMASK && SA_LEN(sa) == 0)
+ dcnt += alen;
+ else
+ dcnt += len;
+ p += len;
+ }
+ break;
+ }
+ }
+
+ if (icnt + dcnt + ncnt == 1) {
+ *pif = NULL;
+ free(buf);
+ return (0);
+ }
+ data = malloc(sizeof(struct ifaddrs) * icnt + dcnt + ncnt);
+ if (data == NULL) {
+ free(buf);
+ return(-1);
+ }
+
+ ifa = (struct ifaddrs *)(void *)data;
+ data += sizeof(struct ifaddrs) * icnt;
+ names = data + dcnt;
+
+ memset(ifa, 0, sizeof(struct ifaddrs) * icnt);
+ ift = ifa;
+
+ idx = 0;
+ for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)(void *)next;
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+ switch (rtm->rtm_type) {
+ case RTM_IFINFO:
+ ifm = (struct if_msghdrl *)(void *)rtm;
+ if ((ifm->ifm_addrs & RTA_IFP) == 0) {
+ idx = 0;
+ break;
+ }
+
+ idx = ifm->ifm_index;
+ dl = (struct sockaddr_dl *)IF_MSGHDRL_RTA(ifm);
+
+ cif = ift;
+ ift->ifa_name = names;
+ ift->ifa_flags = (int)ifm->ifm_flags;
+ memcpy(names, dl->sdl_data, (size_t)dl->sdl_nlen);
+ names[dl->sdl_nlen] = 0;
+ names += dl->sdl_nlen + 1;
+
+ ift->ifa_addr = (struct sockaddr *)(void *)data;
+ memcpy(data, dl, (size_t)SA_LEN((struct sockaddr *)
+ (void *)dl));
+ data += SA_RLEN((struct sockaddr *)(void *)dl);
+
+ if_data = IF_MSGHDRL_IFM_DATA(ifm);
+ /* ifm_data needs to be aligned */
+ ift->ifa_data = data = (void *)ALIGN(data);
+ memcpy(data, if_data, if_data->ifi_datalen);
+ data += if_data->ifi_datalen;
+
+ ift = (ift->ifa_next = ift + 1);
+ break;
+
+ case RTM_NEWADDR:
+ ifam = (struct ifa_msghdrl *)(void *)rtm;
+ if (idx && ifam->ifam_index != idx)
+ abort(); /* this cannot happen */
+
+ if (idx == 0 || (ifam->ifam_addrs & RTA_MASKS) == 0)
+ break;
+ ift->ifa_name = cif->ifa_name;
+ ift->ifa_flags = cif->ifa_flags;
+ ift->ifa_data = NULL;
+
+ p = (char *)IFA_MSGHDRL_RTA(ifam);
+ /* Scan to look for length of address */
+ alen = 0;
+ for (p0 = p, i = 0; i < RTAX_MAX; i++) {
+ if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
+ == 0)
+ continue;
+ sa = (struct sockaddr *)(void *)p;
+ len = SA_RLEN(sa);
+ if (i == RTAX_IFA) {
+ alen = len;
+ break;
+ }
+ p += len;
+ }
+ for (p = p0, i = 0; i < RTAX_MAX; i++) {
+ if ((RTA_MASKS & ifam->ifam_addrs & (1 << i))
+ == 0)
+ continue;
+ sa = (struct sockaddr *)(void *)p;
+ len = SA_RLEN(sa);
+ switch (i) {
+ case RTAX_IFA:
+ ift->ifa_addr =
+ (struct sockaddr *)(void *)data;
+ memcpy(data, p, len);
+ data += len;
+ break;
+
+ case RTAX_NETMASK:
+ ift->ifa_netmask =
+ (struct sockaddr *)(void *)data;
+ if (SA_LEN(sa) == 0) {
+ memset(data, 0, alen);
+ data += alen;
+ break;
+ }
+ memcpy(data, p, len);
+ data += len;
+ break;
+
+ case RTAX_BRD:
+ ift->ifa_broadaddr =
+ (struct sockaddr *)(void *)data;
+ memcpy(data, p, len);
+ data += len;
+ break;
+ }
+ p += len;
+ }
+
+ if_data = IFA_MSGHDRL_IFAM_DATA(ifam);
+ /* ifam_data needs to be aligned */
+ ift->ifa_data = data = (void *)ALIGN(data);
+ memcpy(data, if_data, if_data->ifi_datalen);
+ data += if_data->ifi_datalen;
+
+ ift = (ift->ifa_next = ift + 1);
+ break;
+ }
+ }
+
+ free(buf);
+
+ if (--ift >= ifa) {
+ ift->ifa_next = NULL;
+ *pif = ifa;
+ } else {
+ *pif = NULL;
+ free(ifa);
+ }
+ return (0);
+}
+
+void
+freeifaddrs(struct ifaddrs *ifp)
+{
+
+ free(ifp);
+}
diff --git a/lib/libc/net/getifmaddrs.3 b/lib/libc/net/getifmaddrs.3
new file mode 100644
index 0000000..2d2a936
--- /dev/null
+++ b/lib/libc/net/getifmaddrs.3
@@ -0,0 +1,116 @@
+.\" Copyright (c) 2003 Bruce M. Simpson. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY Bruce M. Simpson ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL Bruce M. Simpson BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 14, 2003
+.Dt GETIFMADDRS 3
+.Os
+.Sh NAME
+.Nm getifmaddrs
+.Nd get multicast group memberships
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In ifaddrs.h
+.Ft int
+.Fn getifmaddrs "struct ifmaddrs **ifmap"
+.Ft void
+.Fn freeifmaddrs "struct ifmaddrs *ifmp"
+.Sh DESCRIPTION
+The
+.Fn getifmaddrs
+function stores a reference to a linked list of the multicast memberships
+on the local machine in the memory referenced by
+.Fa ifmap .
+The list consists of
+.Vt ifmaddrs
+structures, as defined in the include file
+.In ifaddrs.h .
+The
+.Vt ifmaddrs
+structure contains at least the following entries:
+.Bd -literal
+ struct ifmaddrs *ifma_next; /* Pointer to next struct */
+ struct sockaddr *ifma_name; /* Interface name (AF_LINK) */
+ struct sockaddr *ifma_addr; /* Multicast address */
+ struct sockaddr *ifma_lladdr; /* Link-layer translation, if any */
+.Ed
+.Pp
+The
+.Va ifma_next
+field contains a pointer to the next structure on the list.
+This field is
+.Dv NULL
+in last structure on the list.
+.Pp
+The
+.Va ifma_name
+field references an
+.Dv AF_LINK
+address structure, containing the name of the
+interface where the membership exists.
+.Pp
+The
+.Va ifma_addr
+references the address that this membership is for.
+.Pp
+The
+.Va ifma_lladdr
+field references a link-layer translation for the protocol-level address in
+.Va ifma_addr ,
+if one is set, otherwise it is
+.Dv NULL .
+.Pp
+The data returned by
+.Fn getifmaddrs
+is dynamically allocated and should be freed using
+.Fn freeifmaddrs
+when no longer needed.
+.Sh RETURN VALUES
+.Rv -std getifmaddrs
+.Sh ERRORS
+The
+.Fn getifmaddrs
+may fail and set
+.Va errno
+for any of the errors specified for the library routines
+.Xr malloc 3
+or
+.Xr sysctl 3 .
+.Sh SEE ALSO
+.Xr sysctl 3 ,
+.Xr networking 4 ,
+.Xr ifconfig 8
+.Sh HISTORY
+The
+.Fn getifmaddrs
+function first appeared in
+.Fx 5.2 .
+.Sh BUGS
+If both
+.In net/if.h
+and
+.In ifaddrs.h
+are being included,
+.In net/if.h
+.Em must
+be included before
+.In ifaddrs.h .
diff --git a/lib/libc/net/getifmaddrs.c b/lib/libc/net/getifmaddrs.c
new file mode 100644
index 0000000..adbc4a5
--- /dev/null
+++ b/lib/libc/net/getifmaddrs.c
@@ -0,0 +1,203 @@
+/*
+ * Copyright (c) 2003 Bruce M. Simpson.
+ * All rights reserved
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bruce M. Simpson.
+ * 4. Neither the name of Bruce M. Simpson nor the names of other
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY BRUCE M. SIMPSON AND AFFILIATES
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BRUCE M. SIMPSON OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <errno.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#define SALIGN (sizeof(long) - 1)
+#define SA_RLEN(sa) ((sa)->sa_len ? (((sa)->sa_len + SALIGN) & ~SALIGN) : \
+ (SALIGN + 1))
+#define MAX_SYSCTL_TRY 5
+#define RTA_MASKS (RTA_GATEWAY | RTA_IFP | RTA_IFA)
+
+int
+getifmaddrs(struct ifmaddrs **pif)
+{
+ int icnt = 1;
+ int dcnt = 0;
+ int ntry = 0;
+ size_t len;
+ size_t needed;
+ int mib[6];
+ int i;
+ char *buf;
+ char *data;
+ char *next;
+ char *p;
+ struct ifma_msghdr *ifmam;
+ struct ifmaddrs *ifa, *ift;
+ struct rt_msghdr *rtm;
+ struct sockaddr *sa;
+
+ mib[0] = CTL_NET;
+ mib[1] = PF_ROUTE;
+ mib[2] = 0; /* protocol */
+ mib[3] = 0; /* wildcard address family */
+ mib[4] = NET_RT_IFMALIST;
+ mib[5] = 0; /* no flags */
+ do {
+ if (sysctl(mib, 6, NULL, &needed, NULL, 0) < 0)
+ return (-1);
+ if ((buf = malloc(needed)) == NULL)
+ return (-1);
+ if (sysctl(mib, 6, buf, &needed, NULL, 0) < 0) {
+ if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
+ free(buf);
+ return (-1);
+ }
+ free(buf);
+ buf = NULL;
+ }
+ } while (buf == NULL);
+
+ for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)(void *)next;
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+ switch (rtm->rtm_type) {
+ case RTM_NEWMADDR:
+ ifmam = (struct ifma_msghdr *)(void *)rtm;
+ if ((ifmam->ifmam_addrs & RTA_IFA) == 0)
+ break;
+ icnt++;
+ p = (char *)(ifmam + 1);
+ for (i = 0; i < RTAX_MAX; i++) {
+ if ((RTA_MASKS & ifmam->ifmam_addrs &
+ (1 << i)) == 0)
+ continue;
+ sa = (struct sockaddr *)(void *)p;
+ len = SA_RLEN(sa);
+ dcnt += len;
+ p += len;
+ }
+ break;
+ }
+ }
+
+ data = malloc(sizeof(struct ifmaddrs) * icnt + dcnt);
+ if (data == NULL) {
+ free(buf);
+ return (-1);
+ }
+
+ ifa = (struct ifmaddrs *)(void *)data;
+ data += sizeof(struct ifmaddrs) * icnt;
+
+ memset(ifa, 0, sizeof(struct ifmaddrs) * icnt);
+ ift = ifa;
+
+ for (next = buf; next < buf + needed; next += rtm->rtm_msglen) {
+ rtm = (struct rt_msghdr *)(void *)next;
+ if (rtm->rtm_version != RTM_VERSION)
+ continue;
+
+ switch (rtm->rtm_type) {
+ case RTM_NEWMADDR:
+ ifmam = (struct ifma_msghdr *)(void *)rtm;
+ if ((ifmam->ifmam_addrs & RTA_IFA) == 0)
+ break;
+
+ p = (char *)(ifmam + 1);
+ for (i = 0; i < RTAX_MAX; i++) {
+ if ((RTA_MASKS & ifmam->ifmam_addrs &
+ (1 << i)) == 0)
+ continue;
+ sa = (struct sockaddr *)(void *)p;
+ len = SA_RLEN(sa);
+ switch (i) {
+ case RTAX_GATEWAY:
+ ift->ifma_lladdr =
+ (struct sockaddr *)(void *)data;
+ memcpy(data, p, len);
+ data += len;
+ break;
+
+ case RTAX_IFP:
+ ift->ifma_name =
+ (struct sockaddr *)(void *)data;
+ memcpy(data, p, len);
+ data += len;
+ break;
+
+ case RTAX_IFA:
+ ift->ifma_addr =
+ (struct sockaddr *)(void *)data;
+ memcpy(data, p, len);
+ data += len;
+ break;
+
+ default:
+ data += len;
+ break;
+ }
+ p += len;
+ }
+ ift->ifma_next = ift + 1;
+ ift = ift->ifma_next;
+ break;
+ }
+ }
+
+ free(buf);
+
+ if (ift > ifa) {
+ ift--;
+ ift->ifma_next = NULL;
+ *pif = ifa;
+ } else {
+ *pif = NULL;
+ free(ifa);
+ }
+ return (0);
+}
+
+void
+freeifmaddrs(struct ifmaddrs *ifmp)
+{
+
+ free(ifmp);
+}
diff --git a/lib/libc/net/getipnodebyname.3 b/lib/libc/net/getipnodebyname.3
new file mode 100644
index 0000000..0697c64
--- /dev/null
+++ b/lib/libc/net/getipnodebyname.3
@@ -0,0 +1,474 @@
+.\" $KAME: getipnodebyname.3,v 1.6 2000/08/09 21:16:17 itojun Exp $
+.\"
+.\" Copyright (c) 1983, 1987, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)gethostbyname.3 8.4 (Berkeley) 5/25/95
+.\" $FreeBSD$
+.\"
+.Dd August 6, 2004
+.Dt GETIPNODEBYNAME 3
+.Os
+.\"
+.Sh NAME
+.Nm getipnodebyname ,
+.Nm getipnodebyaddr ,
+.Nm freehostent
+.Nd nodename-to-address and address-to-nodename translation
+.\"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netdb.h
+.Ft "struct hostent *"
+.Fn getipnodebyname "const char *name" "int af" "int flags" "int *error_num"
+.Ft "struct hostent *"
+.Fn getipnodebyaddr "const void *src" "size_t len" "int af" "int *error_num"
+.Ft void
+.Fn freehostent "struct hostent *ptr"
+.\"
+.Sh DESCRIPTION
+The
+.Fn getipnodebyname
+and
+.Fn getipnodebyaddr
+functions are very similar to
+.Xr gethostbyname 3 ,
+.Xr gethostbyname2 3
+and
+.Xr gethostbyaddr 3 .
+The functions cover all the functionalities provided by the older ones,
+and provide better interface to programmers.
+The functions require additional arguments,
+.Fa af ,
+and
+.Fa flags ,
+for specifying address family and operation mode.
+The additional arguments allow programmer to get address for a nodename,
+for specific address family
+(such as
+.Dv AF_INET
+or
+.Dv AF_INET6 ) .
+The functions also require an additional pointer argument,
+.Fa error_num
+to return the appropriate error code,
+to support thread safe error code returns.
+.Pp
+The type and usage of the return value,
+.Li "struct hostent"
+is described in
+.Xr gethostbyname 3 .
+.Pp
+For
+.Fn getipnodebyname ,
+the
+.Fa name
+argument can be either a node name or a numeric address
+string
+(i.e., a dotted-decimal IPv4 address or an IPv6 hex address).
+The
+.Fa af
+argument specifies the address family, either
+.Dv AF_INET
+or
+.Dv AF_INET6 .
+The
+.Fa flags
+argument specifies the types of addresses that are searched for,
+and the types of addresses that are returned.
+We note that a special flags value of
+.Dv AI_DEFAULT
+(defined below)
+should handle most applications.
+That is, porting simple applications to use IPv6 replaces the call
+.Bd -literal -offset indent
+hptr = gethostbyname(name);
+.Ed
+.Pp
+with
+.Bd -literal -offset indent
+hptr = getipnodebyname(name, AF_INET6, AI_DEFAULT, &error_num);
+.Ed
+.Pp
+Applications desiring finer control over the types of addresses
+searched for and returned, can specify other combinations of the
+.Fa flags
+argument.
+.Pp
+A
+.Fa flags
+of
+.Li 0
+implies a strict interpretation of the
+.Fa af
+argument:
+.Bl -bullet
+.It
+If
+.Fa flags
+is 0 and
+.Fa af
+is
+.Dv AF_INET ,
+then the caller wants only IPv4 addresses.
+A query is made for
+.Li A
+records.
+If successful, the IPv4 addresses are returned and the
+.Li h_length
+member of the
+.Li hostent
+structure will be 4, else the function returns a
+.Dv NULL
+pointer.
+.It
+If
+.Fa flags
+is 0 and if
+.Fa af
+is
+.Li AF_INET6 ,
+then the caller wants only IPv6 addresses.
+A query is made for
+.Li AAAA
+records.
+If successful, the IPv6 addresses are returned and the
+.Li h_length
+member of the
+.Li hostent
+structure will be 16, else the function returns a
+.Dv NULL
+pointer.
+.El
+.Pp
+Other constants can be logically-ORed into the
+.Fa flags
+argument, to modify the behavior of the function.
+.Bl -bullet
+.It
+If the
+.Dv AI_V4MAPPED
+flag is specified along with an
+.Fa af
+of
+.Dv AF_INET6 ,
+then the caller will accept IPv4-mapped IPv6 addresses.
+That is, if no
+.Li AAAA
+records are found then a query is made for
+.Li A
+records and any found are returned as IPv4-mapped IPv6 addresses
+.Li ( h_length
+will be 16).
+The
+.Dv AI_V4MAPPED
+flag is ignored unless
+.Fa af
+equals
+.Dv AF_INET6 .
+.It
+The
+.Dv AI_V4MAPPED_CFG
+flag is exact same as the
+.Dv AI_V4MAPPED
+flag only if the kernel supports IPv4-mapped IPv6 address.
+.It
+If the
+.Dv AI_ALL
+flag is used in conjunction with the
+.Dv AI_V4MAPPED
+flag, and only used with the IPv6 address family.
+When
+.Dv AI_ALL
+is logically or'd with
+.Dv AI_V4MAPPED
+flag then the caller wants all addresses: IPv6 and IPv4-mapped IPv6.
+A query is first made for
+.Li AAAA
+records and if successful, the
+IPv6 addresses are returned.
+Another query is then made for
+.Li A
+records and any found are returned as IPv4-mapped IPv6 addresses.
+.Li h_length
+will be 16.
+Only if both queries fail does the function
+return a
+.Dv NULL
+pointer.
+This flag is ignored unless af equals
+AF_INET6.
+If both
+.Dv AI_ALL
+and
+.Dv AI_V4MAPPED
+are specified,
+.Dv AI_ALL
+takes precedence.
+.It
+The
+.Dv AI_ADDRCONFIG
+flag specifies that a query for
+.Li AAAA
+records
+should occur only if the node has at least one IPv6 source
+address configured and a query for
+.Li A
+records should occur only if the node has at least one IPv4 source address
+configured.
+.Pp
+For example, if the node has no IPv6 source addresses configured,
+and
+.Fa af
+equals AF_INET6, and the node name being looked up has both
+.Li AAAA
+and
+.Li A
+records, then:
+(a) if only
+.Dv AI_ADDRCONFIG
+is
+specified, the function returns a
+.Dv NULL
+pointer;
+(b) if
+.Dv AI_ADDRCONFIG
+|
+.Dv AI_V4MAPPED
+is specified, the
+.Li A
+records are returned as IPv4-mapped IPv6 addresses;
+.El
+.Pp
+The special flags value of
+.Dv AI_DEFAULT
+is defined as
+.Bd -literal -offset indent
+#define AI_DEFAULT (AI_V4MAPPED_CFG | AI_ADDRCONFIG)
+.Ed
+.Pp
+We noted that the
+.Fn getipnodebyname
+function must allow the
+.Fa name
+argument to be either a node name or a literal address string
+(i.e., a dotted-decimal IPv4 address or an IPv6 hex address).
+This saves applications from having to call
+.Xr inet_pton 3
+to handle literal address strings.
+When the
+.Fa name
+argument is a literal address string,
+the
+.Fa flags
+argument is always ignored.
+.Pp
+There are four scenarios based on the type of literal address string
+and the value of the
+.Fa af
+argument.
+The two simple cases are when
+.Fa name
+is a dotted-decimal IPv4 address and
+.Fa af
+equals
+.Dv AF_INET ,
+or when
+.Fa name
+is an IPv6 hex address and
+.Fa af
+equals
+.Dv AF_INET6 .
+The members of the
+returned hostent structure are:
+.Li h_name
+points to a copy of the
+.Fa name
+argument,
+.Li h_aliases
+is a
+.Dv NULL
+pointer,
+.Li h_addrtype
+is a copy of the
+.Fa af
+argument,
+.Li h_length
+is either 4
+(for
+.Dv AF_INET )
+or 16
+(for
+.Dv AF_INET6 ) ,
+.Li h_addr_list[0]
+is a pointer to the 4-byte or 16-byte binary address,
+and
+.Li h_addr_list[1]
+is a
+.Dv NULL
+pointer.
+.Pp
+When
+.Fa name
+is a dotted-decimal IPv4 address and
+.Fa af
+equals
+.Dv AF_INET6 ,
+and
+.Dv AI_V4MAPPED
+is specified,
+an IPv4-mapped IPv6 address is returned:
+.Li h_name
+points to an IPv6 hex address containing the IPv4-mapped IPv6 address,
+.Li h_aliases
+is a
+.Dv NULL
+pointer,
+.Li h_addrtype
+is
+.Dv AF_INET6 ,
+.Li h_length
+is 16,
+.Li h_addr_list[0]
+is a pointer to the 16-byte binary address, and
+.Li h_addr_list[1]
+is a
+.Dv NULL
+pointer.
+.Pp
+It is an error when
+.Fa name
+is an IPv6 hex address and
+.Fa af
+equals
+.Dv AF_INET .
+The function's return value is a
+.Dv NULL
+pointer and the value pointed to by
+.Fa error_num
+equals
+.Dv HOST_NOT_FOUND .
+.Pp
+The
+.Fn getipnodebyaddr
+function
+takes almost the same argument as
+.Xr gethostbyaddr 3 ,
+but adds a pointer to return an error number.
+Additionally it takes care of IPv4-mapped IPv6 addresses,
+and IPv4-compatible IPv6 addresses.
+.Pp
+The
+.Fn getipnodebyname
+and
+.Fn getipnodebyaddr
+functions
+dynamically allocate the structure to be returned to the caller.
+The
+.Fn freehostent
+function
+reclaims memory region allocated and returned by
+.Fn getipnodebyname
+or
+.Fn getipnodebyaddr .
+.\"
+.Sh FILES
+.Bl -tag -width /etc/nsswitch.conf -compact
+.It Pa /etc/hosts
+.It Pa /etc/nsswitch.conf
+.It Pa /etc/resolv.conf
+.El
+.\"
+.Sh DIAGNOSTICS
+The
+.Fn getipnodebyname
+and
+.Fn getipnodebyaddr
+functions
+returns
+.Dv NULL
+on errors.
+The integer values pointed to by
+.Fa error_num
+may then be checked to see whether this is a temporary failure
+or an invalid or unknown host.
+The meanings of each error code are described in
+.Xr gethostbyname 3 .
+.\"
+.Sh SEE ALSO
+.Xr getaddrinfo 3 ,
+.Xr gethostbyaddr 3 ,
+.Xr gethostbyname 3 ,
+.Xr getnameinfo 3 ,
+.Xr hosts 5 ,
+.Xr nsswitch.conf 5 ,
+.Xr services 5 ,
+.Xr hostname 7 ,
+.Xr named 8
+.Pp
+.Rs
+.%A R. Gilligan
+.%A S. Thomson
+.%A J. Bound
+.%A W. Stevens
+.%T Basic Socket Interface Extensions for IPv6
+.%R RFC2553
+.%D March 1999
+.Re
+.\"
+.Sh STANDARDS
+The
+.Fn getipnodebyname
+and
+.Fn getipnodebyaddr
+functions
+are documented in
+.Dq Basic Socket Interface Extensions for IPv6
+(RFC2553).
+.\"
+.Sh HISTORY
+The implementation first appeared in KAME advanced networking kit.
+.\"
+.Sh BUGS
+The
+.Fn getipnodebyname
+and
+.Fn getipnodebyaddr
+functions
+do not handle scoped IPv6 address properly.
+If you use these functions,
+your program will not be able to handle scoped IPv6 addresses.
+For IPv6 address manipulation,
+.Fn getaddrinfo 3
+and
+.Fn getnameinfo 3
+are recommended.
+.Pp
+The text was shamelessly copied from RFC2553.
diff --git a/lib/libc/net/getnameinfo.3 b/lib/libc/net/getnameinfo.3
new file mode 100644
index 0000000..327c135
--- /dev/null
+++ b/lib/libc/net/getnameinfo.3
@@ -0,0 +1,285 @@
+.\" $KAME: getnameinfo.3,v 1.37 2005/01/05 03:23:05 itojun Exp $
+.\" $OpenBSD: getnameinfo.3,v 1.36 2004/12/21 09:48:20 jmc Exp $
+.\"
+.\" Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC")
+.\" Copyright (C) 2000, 2001 Internet Software Consortium.
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
+.\" REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
+.\" INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+.\" LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
+.\" OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+.\" PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 28, 2007
+.Dt GETNAMEINFO 3
+.Os
+.Sh NAME
+.Nm getnameinfo
+.Nd socket address structure to hostname and service name
+.Sh SYNOPSIS
+.Fd #include <sys/types.h>
+.Fd #include <sys/socket.h>
+.Fd #include <netdb.h>
+.Ft int
+.Fo getnameinfo
+.Fa "const struct sockaddr *sa" "socklen_t salen" "char *host"
+.Fa "size_t hostlen" "char *serv" "size_t servlen" "int flags"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn getnameinfo
+function is used to convert a
+.Li sockaddr
+structure to a pair of host name and service strings.
+It is a replacement for and provides more flexibility than the
+.Xr gethostbyaddr 3
+and
+.Xr getservbyport 3
+functions and is the converse of the
+.Xr getaddrinfo 3
+function.
+.Pp
+If a link-layer address is passed to
+.Fn getnameinfo ,
+its ASCII representation will be stored in
+.Fa host .
+The string pointed to by
+.Fa serv
+will be set to the empty string if non-NULL;
+.Fa flags
+will always be ignored.
+This is intended as a replacement for the legacy
+.Xr link_ntoa 3
+function.
+.Pp
+The
+.Li sockaddr
+structure
+.Fa sa
+should point to either a
+.Li sockaddr_in ,
+.Li sockaddr_in6
+or
+.Li sockaddr_dl
+structure (for IPv4, IPv6 or link-layer respectively) that is
+.Fa salen
+bytes long.
+.Pp
+The host and service names associated with
+.Fa sa
+are stored in
+.Fa host
+and
+.Fa serv
+which have length parameters
+.Fa hostlen
+and
+.Fa servlen .
+The maximum value for
+.Fa hostlen
+is
+.Dv NI_MAXHOST
+and
+the maximum value for
+.Fa servlen
+is
+.Dv NI_MAXSERV ,
+as defined by
+.Aq Pa netdb.h .
+If a length parameter is zero, no string will be stored.
+Otherwise, enough space must be provided to store the
+host name or service string plus a byte for the NUL terminator.
+.Pp
+The
+.Fa flags
+argument is formed by
+.Tn OR Ns 'ing
+the following values:
+.Bl -tag -width "NI_NUMERICHOSTXX"
+.It Dv NI_NOFQDN
+A fully qualified domain name is not required for local hosts.
+The local part of the fully qualified domain name is returned instead.
+.It Dv NI_NUMERICHOST
+Return the address in numeric form, as if calling
+.Xr inet_ntop 3 ,
+instead of a host name.
+.It Dv NI_NAMEREQD
+A name is required.
+If the host name cannot be found in DNS and this flag is set,
+a non-zero error code is returned.
+If the host name is not found and the flag is not set, the
+address is returned in numeric form.
+.It NI_NUMERICSERV
+The service name is returned as a digit string representing the port number.
+.It NI_DGRAM
+Specifies that the service being looked up is a datagram
+service, and causes
+.Xr getservbyport 3
+to be called with a second argument of
+.Dq udp
+instead of its default of
+.Dq tcp .
+This is required for the few ports (512\-514) that have different services
+for
+.Tn UDP
+and
+.Tn TCP .
+.El
+.Pp
+This implementation allows numeric IPv6 address notation with scope identifier,
+as documented in chapter 11 of RFC 4007.
+IPv6 link-local address will appear as a string like
+.Dq Li fe80::1%ne0 .
+Refer to
+.Xr getaddrinfo 3
+for more information.
+.Sh RETURN VALUES
+.Fn getnameinfo
+returns zero on success or one of the error codes listed in
+.Xr gai_strerror 3
+if an error occurs.
+.Sh EXAMPLES
+The following code tries to get a numeric host name, and service name,
+for a given socket address.
+Observe that there is no hardcoded reference to a particular address family.
+.Bd -literal -offset indent
+struct sockaddr *sa; /* input */
+char hbuf[NI_MAXHOST], sbuf[NI_MAXSERV];
+
+if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), sbuf,
+ sizeof(sbuf), NI_NUMERICHOST | NI_NUMERICSERV)) {
+ errx(1, "could not get numeric hostname");
+ /*NOTREACHED*/
+}
+printf("host=%s, serv=%s\en", hbuf, sbuf);
+.Ed
+.Pp
+The following version checks if the socket address has a reverse address mapping:
+.Bd -literal -offset indent
+struct sockaddr *sa; /* input */
+char hbuf[NI_MAXHOST];
+
+if (getnameinfo(sa, sa->sa_len, hbuf, sizeof(hbuf), NULL, 0,
+ NI_NAMEREQD)) {
+ errx(1, "could not resolve hostname");
+ /*NOTREACHED*/
+}
+printf("host=%s\en", hbuf);
+.Ed
+.Sh SEE ALSO
+.Xr gai_strerror 3 ,
+.Xr getaddrinfo 3 ,
+.Xr gethostbyaddr 3 ,
+.Xr getservbyport 3 ,
+.Xr inet_ntop 3 ,
+.Xr link_ntoa 3 ,
+.Xr resolver 3 ,
+.Xr hosts 5 ,
+.Xr resolv.conf 5 ,
+.Xr services 5 ,
+.Xr hostname 7 ,
+.Xr named 8
+.Rs
+.%A R. Gilligan
+.%A S. Thomson
+.%A J. Bound
+.%A W. Stevens
+.%T Basic Socket Interface Extensions for IPv6
+.%R RFC 2553
+.%D March 1999
+.Re
+.Rs
+.%A S. Deering
+.%A B. Haberman
+.%A T. Jinmei
+.%A E. Nordmark
+.%A B. Zill
+.%T "IPv6 Scoped Address Architecture"
+.%R internet draft
+.%N draft-ietf-ipv6-scoping-arch-02.txt
+.%O work in progress material
+.Re
+.Rs
+.%A Craig Metz
+.%T Protocol Independence Using the Sockets API
+.%B "Proceedings of the freenix track: 2000 USENIX annual technical conference"
+.%D June 2000
+.Re
+.Sh STANDARDS
+The
+.Fn getnameinfo
+function is defined by the
+.St -p1003.1g-2000
+draft specification and documented in
+.Tn "RFC 2553" ,
+.Dq Basic Socket Interface Extensions for IPv6 .
+.Sh CAVEATS
+.Fn getnameinfo
+can return both numeric and FQDN forms of the address specified in
+.Fa sa .
+There is no return value that indicates whether the string returned in
+.Fa host
+is a result of binary to numeric-text translation (like
+.Xr inet_ntop 3 ) ,
+or is the result of a DNS reverse lookup.
+Because of this, malicious parties could set up a PTR record as follows:
+.Bd -literal -offset indent
+1.0.0.127.in-addr.arpa. IN PTR 10.1.1.1
+.Ed
+.Pp
+and trick the caller of
+.Fn getnameinfo
+into believing that
+.Fa sa
+is
+.Li 10.1.1.1
+when it is actually
+.Li 127.0.0.1 .
+.Pp
+To prevent such attacks, the use of
+.Dv NI_NAMEREQD
+is recommended when the result of
+.Fn getnameinfo
+is used
+for access control purposes:
+.Bd -literal -offset indent
+struct sockaddr *sa;
+socklen_t salen;
+char addr[NI_MAXHOST];
+struct addrinfo hints, *res;
+int error;
+
+error = getnameinfo(sa, salen, addr, sizeof(addr),
+ NULL, 0, NI_NAMEREQD);
+if (error == 0) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ hints.ai_flags = AI_NUMERICHOST;
+ if (getaddrinfo(addr, "0", &hints, &res) == 0) {
+ /* malicious PTR record */
+ freeaddrinfo(res);
+ printf("bogus PTR record\en");
+ return -1;
+ }
+ /* addr is FQDN as a result of PTR lookup */
+} else {
+ /* addr is numeric string */
+ error = getnameinfo(sa, salen, addr, sizeof(addr),
+ NULL, 0, NI_NUMERICHOST);
+}
+.Ed
+.\".Pp
+.\".Ox
+.\"intentionally uses a different
+.\".Dv NI_MAXHOST
+.\"value from what
+.\".Tn "RFC 2553"
+.\"suggests, to avoid buffer length handling mistakes.
diff --git a/lib/libc/net/getnameinfo.c b/lib/libc/net/getnameinfo.c
new file mode 100644
index 0000000..ffd34a1
--- /dev/null
+++ b/lib/libc/net/getnameinfo.c
@@ -0,0 +1,464 @@
+/* $KAME: getnameinfo.c,v 1.61 2002/06/27 09:25:47 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * Copyright (c) 2000 Ben Harris.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Issues to be discussed:
+ * - Thread safe-ness must be checked
+ * - RFC2553 says that we should raise error on short buffer. X/Open says
+ * we need to truncate the result. We obey RFC2553 (and X/Open should be
+ * modified). ipngwg rough consensus seems to follow RFC2553.
+ * - What is "local" in NI_FQDN?
+ * - NI_NAMEREQD and NI_NUMERICHOST conflict with each other.
+ * - (KAME extension) always attach textual scopeid (fe80::1%lo0), if
+ * sin6_scope_id is filled - standardization status?
+ * XXX breaks backward compat for code that expects no scopeid.
+ * beware on merge.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <net/if_types.h>
+#include <net/firewire.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <stddef.h>
+#include <errno.h>
+
+static int getnameinfo_inet(const struct sockaddr *, socklen_t, char *,
+ size_t, char *, size_t, int);
+#ifdef INET6
+static int ip6_parsenumeric(const struct sockaddr *, const char *, char *,
+ size_t, int);
+static int ip6_sa2str(const struct sockaddr_in6 *, char *, size_t, int);
+#endif
+static int getnameinfo_link(const struct sockaddr *, socklen_t, char *,
+ size_t, char *, size_t, int);
+static int hexname(const u_int8_t *, size_t, char *, size_t);
+
+int
+getnameinfo(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen, char *serv, size_t servlen,
+ int flags)
+{
+
+ switch (sa->sa_family) {
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
+ return getnameinfo_inet(sa, salen, host, hostlen, serv,
+ servlen, flags);
+ case AF_LINK:
+ return getnameinfo_link(sa, salen, host, hostlen, serv,
+ servlen, flags);
+ default:
+ return EAI_FAMILY;
+ }
+}
+
+static const struct afd {
+ int a_af;
+ size_t a_addrlen;
+ socklen_t a_socklen;
+ int a_off;
+} afdl [] = {
+#ifdef INET6
+ {PF_INET6, sizeof(struct in6_addr), sizeof(struct sockaddr_in6),
+ offsetof(struct sockaddr_in6, sin6_addr)},
+#endif
+ {PF_INET, sizeof(struct in_addr), sizeof(struct sockaddr_in),
+ offsetof(struct sockaddr_in, sin_addr)},
+ {0, 0, 0},
+};
+
+struct sockinet {
+ u_char si_len;
+ u_char si_family;
+ u_short si_port;
+};
+
+static int
+getnameinfo_inet(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen, char *serv, size_t servlen,
+ int flags)
+{
+ const struct afd *afd;
+ struct servent *sp;
+ struct hostent *hp;
+ u_short port;
+ int family, i;
+ const char *addr;
+ u_int32_t v4a;
+ int h_error;
+ char numserv[512];
+ char numaddr[512];
+
+ if (sa == NULL)
+ return EAI_FAIL;
+
+ family = sa->sa_family;
+ for (i = 0; afdl[i].a_af; i++)
+ if (afdl[i].a_af == family) {
+ afd = &afdl[i];
+ goto found;
+ }
+ return EAI_FAMILY;
+
+ found:
+ if (salen != afd->a_socklen)
+ return EAI_FAIL;
+
+ /* network byte order */
+ port = ((const struct sockinet *)sa)->si_port;
+ addr = (const char *)sa + afd->a_off;
+
+ if (serv == NULL || servlen == 0) {
+ /*
+ * do nothing in this case.
+ * in case you are wondering if "&&" is more correct than
+ * "||" here: rfc2553bis-03 says that serv == NULL OR
+ * servlen == 0 means that the caller does not want the result.
+ */
+ } else {
+ if (flags & NI_NUMERICSERV)
+ sp = NULL;
+ else {
+ sp = getservbyport(port,
+ (flags & NI_DGRAM) ? "udp" : "tcp");
+ }
+ if (sp) {
+ if (strlen(sp->s_name) + 1 > servlen)
+ return EAI_MEMORY;
+ strlcpy(serv, sp->s_name, servlen);
+ } else {
+ snprintf(numserv, sizeof(numserv), "%u", ntohs(port));
+ if (strlen(numserv) + 1 > servlen)
+ return EAI_MEMORY;
+ strlcpy(serv, numserv, servlen);
+ }
+ }
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ v4a = (u_int32_t)
+ ntohl(((const struct sockaddr_in *)sa)->sin_addr.s_addr);
+ if (IN_MULTICAST(v4a) || IN_EXPERIMENTAL(v4a))
+ flags |= NI_NUMERICHOST;
+ v4a >>= IN_CLASSA_NSHIFT;
+ if (v4a == 0)
+ flags |= NI_NUMERICHOST;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ {
+ const struct sockaddr_in6 *sin6;
+ sin6 = (const struct sockaddr_in6 *)sa;
+ switch (sin6->sin6_addr.s6_addr[0]) {
+ case 0x00:
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr))
+ ;
+ else if (IN6_IS_ADDR_LOOPBACK(&sin6->sin6_addr))
+ ;
+ else
+ flags |= NI_NUMERICHOST;
+ break;
+ default:
+ if (IN6_IS_ADDR_LINKLOCAL(&sin6->sin6_addr)) {
+ flags |= NI_NUMERICHOST;
+ }
+ else if (IN6_IS_ADDR_MULTICAST(&sin6->sin6_addr))
+ flags |= NI_NUMERICHOST;
+ break;
+ }
+ }
+ break;
+#endif
+ }
+ if (host == NULL || hostlen == 0) {
+ /*
+ * do nothing in this case.
+ * in case you are wondering if "&&" is more correct than
+ * "||" here: rfc2553bis-03 says that host == NULL or
+ * hostlen == 0 means that the caller does not want the result.
+ */
+ } else if (flags & NI_NUMERICHOST) {
+ size_t numaddrlen;
+
+ /* NUMERICHOST and NAMEREQD conflicts with each other */
+ if (flags & NI_NAMEREQD)
+ return EAI_NONAME;
+
+ switch(afd->a_af) {
+#ifdef INET6
+ case AF_INET6:
+ {
+ int error;
+
+ if ((error = ip6_parsenumeric(sa, addr, host,
+ hostlen, flags)) != 0)
+ return(error);
+ break;
+ }
+#endif
+ default:
+ if (inet_ntop(afd->a_af, addr, numaddr, sizeof(numaddr))
+ == NULL)
+ return EAI_SYSTEM;
+ numaddrlen = strlen(numaddr);
+ if (numaddrlen + 1 > hostlen) /* don't forget terminator */
+ return EAI_MEMORY;
+ strlcpy(host, numaddr, hostlen);
+ break;
+ }
+ } else {
+ hp = getipnodebyaddr(addr, afd->a_addrlen, afd->a_af, &h_error);
+
+ if (hp) {
+#if 0
+ /*
+ * commented out, since "for local host" is not
+ * implemented here - see RFC2553 p30
+ */
+ if (flags & NI_NOFQDN) {
+ char *p;
+ p = strchr(hp->h_name, '.');
+ if (p)
+ *p = '\0';
+ }
+#endif
+ if (strlen(hp->h_name) + 1 > hostlen) {
+ freehostent(hp);
+ return EAI_MEMORY;
+ }
+ strlcpy(host, hp->h_name, hostlen);
+ freehostent(hp);
+ } else {
+ if (flags & NI_NAMEREQD)
+ return EAI_NONAME;
+ switch(afd->a_af) {
+#ifdef INET6
+ case AF_INET6:
+ {
+ int error;
+
+ if ((error = ip6_parsenumeric(sa, addr, host,
+ hostlen,
+ flags)) != 0)
+ return(error);
+ break;
+ }
+#endif
+ default:
+ if (inet_ntop(afd->a_af, addr, host,
+ hostlen) == NULL)
+ return EAI_SYSTEM;
+ break;
+ }
+ }
+ }
+ return(0);
+}
+
+#ifdef INET6
+static int
+ip6_parsenumeric(const struct sockaddr *sa, const char *addr,
+ char *host, size_t hostlen, int flags)
+{
+ size_t numaddrlen;
+ char numaddr[512];
+
+ if (inet_ntop(AF_INET6, addr, numaddr, sizeof(numaddr)) == NULL)
+ return EAI_SYSTEM;
+
+ numaddrlen = strlen(numaddr);
+ if (numaddrlen + 1 > hostlen) /* don't forget terminator */
+ return EAI_OVERFLOW;
+ strlcpy(host, numaddr, hostlen);
+
+ if (((const struct sockaddr_in6 *)sa)->sin6_scope_id) {
+ char zonebuf[MAXHOSTNAMELEN];
+ int zonelen;
+
+ zonelen = ip6_sa2str(
+ (const struct sockaddr_in6 *)(const void *)sa,
+ zonebuf, sizeof(zonebuf), flags);
+ if (zonelen < 0)
+ return EAI_OVERFLOW;
+ if (zonelen + 1 + numaddrlen + 1 > hostlen)
+ return EAI_OVERFLOW;
+
+ /* construct <numeric-addr><delim><zoneid> */
+ memcpy(host + numaddrlen + 1, zonebuf,
+ (size_t)zonelen);
+ host[numaddrlen] = SCOPE_DELIMITER;
+ host[numaddrlen + 1 + zonelen] = '\0';
+ }
+
+ return 0;
+}
+
+/* ARGSUSED */
+static int
+ip6_sa2str(const struct sockaddr_in6 *sa6, char *buf, size_t bufsiz, int flags)
+{
+ unsigned int ifindex;
+ const struct in6_addr *a6;
+ int n;
+
+ ifindex = (unsigned int)sa6->sin6_scope_id;
+ a6 = &sa6->sin6_addr;
+
+#ifdef NI_NUMERICSCOPE
+ if ((flags & NI_NUMERICSCOPE) != 0) {
+ n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
+ if (n < 0 || n >= bufsiz)
+ return -1;
+ else
+ return n;
+ }
+#endif
+
+ /* if_indextoname() does not take buffer size. not a good api... */
+ if ((IN6_IS_ADDR_LINKLOCAL(a6) || IN6_IS_ADDR_MC_LINKLOCAL(a6) ||
+ IN6_IS_ADDR_MC_NODELOCAL(a6)) && bufsiz >= IF_NAMESIZE) {
+ char *p = if_indextoname(ifindex, buf);
+ if (p) {
+ return(strlen(p));
+ }
+ }
+
+ /* last resort */
+ n = snprintf(buf, bufsiz, "%u", sa6->sin6_scope_id);
+ if (n < 0 || (size_t)n >= bufsiz)
+ return -1;
+ else
+ return n;
+}
+#endif /* INET6 */
+
+/*
+ * getnameinfo_link():
+ * Format a link-layer address into a printable format, paying attention to
+ * the interface type.
+ */
+/* ARGSUSED */
+static int
+getnameinfo_link(const struct sockaddr *sa, socklen_t salen,
+ char *host, size_t hostlen, char *serv, size_t servlen, int flags)
+{
+ const struct sockaddr_dl *sdl =
+ (const struct sockaddr_dl *)(const void *)sa;
+ const struct fw_hwaddr *iha;
+ int n;
+
+ if (serv != NULL && servlen > 0)
+ *serv = '\0';
+
+ if (sdl->sdl_nlen == 0 && sdl->sdl_alen == 0 && sdl->sdl_slen == 0) {
+ n = snprintf(host, hostlen, "link#%d", sdl->sdl_index);
+ if (n > hostlen) {
+ *host = '\0';
+ return EAI_MEMORY;
+ }
+ return 0;
+ }
+
+ switch (sdl->sdl_type) {
+ case IFT_IEEE1394:
+ if (sdl->sdl_alen < sizeof(iha->sender_unique_ID_hi) +
+ sizeof(iha->sender_unique_ID_lo))
+ return EAI_FAMILY;
+ iha = (const struct fw_hwaddr *)(const void *)LLADDR(sdl);
+ return hexname((const u_int8_t *)&iha->sender_unique_ID_hi,
+ sizeof(iha->sender_unique_ID_hi) +
+ sizeof(iha->sender_unique_ID_lo),
+ host, hostlen);
+ /*
+ * The following have zero-length addresses.
+ * IFT_ATM (net/if_atmsubr.c)
+ * IFT_FAITH (net/if_faith.c)
+ * IFT_GIF (net/if_gif.c)
+ * IFT_LOOP (net/if_loop.c)
+ * IFT_PPP (net/if_ppp.c, net/if_spppsubr.c)
+ * IFT_SLIP (net/if_sl.c, net/if_strip.c)
+ * IFT_STF (net/if_stf.c)
+ * IFT_L2VLAN (net/if_vlan.c)
+ * IFT_BRIDGE (net/if_bridge.h>
+ */
+ /*
+ * The following use IPv4 addresses as link-layer addresses:
+ * IFT_OTHER (net/if_gre.c)
+ * IFT_OTHER (netinet/ip_ipip.c)
+ */
+ /* default below is believed correct for all these. */
+ case IFT_ARCNET:
+ case IFT_ETHER:
+ case IFT_FDDI:
+ case IFT_HIPPI:
+ case IFT_ISO88025:
+ default:
+ return hexname((u_int8_t *)LLADDR(sdl), (size_t)sdl->sdl_alen,
+ host, hostlen);
+ }
+}
+
+static int
+hexname(cp, len, host, hostlen)
+ const u_int8_t *cp;
+ char *host;
+ size_t len, hostlen;
+{
+ int i, n;
+ char *outp = host;
+
+ *outp = '\0';
+ for (i = 0; i < len; i++) {
+ n = snprintf(outp, hostlen, "%s%02x",
+ i ? ":" : "", cp[i]);
+ if (n < 0 || n >= hostlen) {
+ *host = '\0';
+ return EAI_MEMORY;
+ }
+ outp += n;
+ hostlen -= n;
+ }
+ return 0;
+}
diff --git a/lib/libc/net/getnetbydns.c b/lib/libc/net/getnetbydns.c
new file mode 100644
index 0000000..79e40a5
--- /dev/null
+++ b/lib/libc/net/getnetbydns.c
@@ -0,0 +1,465 @@
+/*-
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+/* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
+ * Dep. Matematica Universidade de Coimbra, Portugal, Europe
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <string.h>
+#include <unistd.h>
+#include <syslog.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+
+#include "netdb_private.h"
+#include "res_config.h"
+
+#define BYADDR 0
+#define BYNAME 1
+
+#define MAXPACKET (64*1024)
+
+typedef union {
+ HEADER hdr;
+ u_char buf[MAXPACKET];
+} querybuf;
+
+typedef union {
+ long al;
+ char ac;
+} align;
+
+/*
+ * Reverse the order of first four dotted entries of in.
+ * Out must contain space for at least strlen(in) characters.
+ * The result does not include any leading 0s of in.
+ */
+static void
+ipreverse(char *in, char *out)
+{
+ char *pos[4];
+ int len[4];
+ char *p, *start;
+ int i = 0;
+ int leading = 1;
+
+ /* Fill-in element positions and lengths: pos[], len[]. */
+ start = p = in;
+ for (;;) {
+ if (*p == '.' || *p == '\0') {
+ /* Leading 0? */
+ if (leading && p - start == 1 && *start == '0')
+ len[i] = 0;
+ else {
+ len[i] = p - start;
+ leading = 0;
+ }
+ pos[i] = start;
+ start = p + 1;
+ i++;
+ }
+ if (i == 4)
+ break;
+ if (*p == 0) {
+ for (; i < 4; i++) {
+ pos[i] = p;
+ len[i] = 0;
+ }
+ break;
+ }
+ p++;
+ }
+
+ /* Copy the entries in reverse order */
+ p = out;
+ leading = 1;
+ for (i = 3; i >= 0; i--) {
+ memcpy(p, pos[i], len[i]);
+ if (len[i])
+ leading = 0;
+ p += len[i];
+ /* Need a . separator? */
+ if (!leading && i > 0 && len[i - 1])
+ *p++ = '.';
+ }
+ *p = '\0';
+}
+
+static int
+getnetanswer(querybuf *answer, int anslen, int net_i, struct netent *ne,
+ struct netent_data *ned, res_state statp)
+{
+
+ HEADER *hp;
+ u_char *cp;
+ int n;
+ u_char *eom;
+ int type, class, ancount, qdcount, haveanswer;
+ char aux[MAXHOSTNAMELEN];
+ char ans[MAXHOSTNAMELEN];
+ char *in, *bp, *ep, **ap;
+
+ /*
+ * find first satisfactory answer
+ *
+ * answer --> +------------+ ( MESSAGE )
+ * | Header |
+ * +------------+
+ * | Question | the question for the name server
+ * +------------+
+ * | Answer | RRs answering the question
+ * +------------+
+ * | Authority | RRs pointing toward an authority
+ * | Additional | RRs holding additional information
+ * +------------+
+ */
+ eom = answer->buf + anslen;
+ hp = &answer->hdr;
+ ancount = ntohs(hp->ancount); /* #/records in the answer section */
+ qdcount = ntohs(hp->qdcount); /* #/entries in the question section */
+ bp = ned->netbuf;
+ ep = ned->netbuf + sizeof(ned->netbuf);
+ cp = answer->buf + HFIXEDSZ;
+ if (!qdcount) {
+ if (hp->aa)
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ else
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (-1);
+ }
+ while (qdcount-- > 0)
+ cp += __dn_skipname(cp, eom) + QFIXEDSZ;
+ ap = ned->net_aliases;
+ *ap = NULL;
+ ne->n_aliases = ned->net_aliases;
+ haveanswer = 0;
+ while (--ancount >= 0 && cp < eom) {
+ n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+ if ((n < 0) || !res_dnok(bp))
+ break;
+ cp += n;
+ ans[0] = '\0';
+ (void)strncpy(&ans[0], bp, sizeof(ans) - 1);
+ ans[sizeof(ans) - 1] = '\0';
+ GETSHORT(type, cp);
+ GETSHORT(class, cp);
+ cp += INT32SZ; /* TTL */
+ GETSHORT(n, cp);
+ if (class == C_IN && type == T_PTR) {
+ n = dn_expand(answer->buf, eom, cp, bp, ep - bp);
+ if ((n < 0) || !res_hnok(bp)) {
+ cp += n;
+ return (-1);
+ }
+ cp += n;
+ *ap++ = bp;
+ n = strlen(bp) + 1;
+ bp += n;
+ ne->n_addrtype = (class == C_IN) ? AF_INET : AF_UNSPEC;
+ haveanswer++;
+ }
+ }
+ if (haveanswer) {
+ *ap = NULL;
+ switch (net_i) {
+ case BYADDR:
+ ne->n_name = *ne->n_aliases;
+ ne->n_net = 0L;
+ break;
+ case BYNAME:
+ in = *ne->n_aliases;
+ n = strlen(ans) + 1;
+ if (ep - bp < n) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ errno = ENOBUFS;
+ return (-1);
+ }
+ strlcpy(bp, ans, ep - bp);
+ ne->n_name = bp;
+ if (strlen(in) + 1 > sizeof(aux)) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ errno = ENOBUFS;
+ return (-1);
+ }
+ ipreverse(in, aux);
+ ne->n_net = inet_network(aux);
+ break;
+ }
+ ne->n_aliases++;
+ return (0);
+ }
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (-1);
+}
+
+int
+_dns_getnetbyaddr(void *rval, void *cb_data, va_list ap)
+{
+ uint32_t net;
+ int net_type;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
+ struct netent_data *ned;
+ unsigned int netbr[4];
+ int nn, anslen, error;
+ querybuf *buf;
+ char qbuf[MAXDNAME];
+ uint32_t net2;
+ res_state statp;
+
+ net = va_arg(ap, uint32_t);
+ net_type = va_arg(ap, int);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ *((struct netent **)rval) = NULL;
+
+ if (net_type != AF_INET) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ for (nn = 4, net2 = net; net2; net2 >>= 8)
+ netbr[--nn] = net2 & 0xff;
+ switch (nn) {
+ case 3: /* Class A */
+ sprintf(qbuf, "0.0.0.%u.in-addr.arpa", netbr[3]);
+ break;
+ case 2: /* Class B */
+ sprintf(qbuf, "0.0.%u.%u.in-addr.arpa", netbr[3], netbr[2]);
+ break;
+ case 1: /* Class C */
+ sprintf(qbuf, "0.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2],
+ netbr[1]);
+ break;
+ case 0: /* Class D - E */
+ sprintf(qbuf, "%u.%u.%u.%u.in-addr.arpa", netbr[3], netbr[2],
+ netbr[1], netbr[0]);
+ break;
+ }
+ if ((buf = malloc(sizeof(*buf))) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ anslen = res_nquery(statp, qbuf, C_IN, T_PTR, (u_char *)buf,
+ sizeof(*buf));
+ if (anslen < 0) {
+ free(buf);
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf("res_nsearch failed\n");
+#endif
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ } else if (anslen > sizeof(*buf)) {
+ free(buf);
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf("res_nsearch static buffer too small\n");
+#endif
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+ error = getnetanswer(buf, anslen, BYADDR, &ne, ned, statp);
+ free(buf);
+ if (error == 0) {
+ /* Strip trailing zeros */
+ while ((net & 0xff) == 0 && net != 0)
+ net >>= 8;
+ ne.n_net = net;
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
+ }
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+}
+
+int
+_dns_getnetbyname(void *rval, void *cb_data, va_list ap)
+{
+ const char *net;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
+ struct netent_data *ned;
+ int anslen, error;
+ querybuf *buf;
+ char qbuf[MAXDNAME];
+ res_state statp;
+
+ net = va_arg(ap, const char *);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+ if ((buf = malloc(sizeof(*buf))) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+
+ *((struct netent **)rval) = NULL;
+
+ strncpy(qbuf, net, sizeof(qbuf) - 1);
+ qbuf[sizeof(qbuf) - 1] = '\0';
+ anslen = res_nsearch(statp, qbuf, C_IN, T_PTR, (u_char *)buf,
+ sizeof(*buf));
+ if (anslen < 0) {
+ free(buf);
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf("res_nsearch failed\n");
+#endif
+ return (NS_UNAVAIL);
+ } else if (anslen > sizeof(*buf)) {
+ free(buf);
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf("res_search static buffer too small\n");
+#endif
+ return (NS_UNAVAIL);
+ }
+ error = getnetanswer(buf, anslen, BYNAME, &ne, ned, statp);
+ free(buf);
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
+}
+
+void
+_setnetdnsent(int stayopen)
+{
+ res_state statp;
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0 && res_ninit(statp) == -1)
+ return;
+ if (stayopen)
+ statp->options |= RES_STAYOPEN | RES_USEVC;
+}
+
+void
+_endnetdnsent()
+{
+ res_state statp;
+
+ statp = __res_state();
+ statp->options &= ~(RES_STAYOPEN | RES_USEVC);
+ res_nclose(statp);
+}
diff --git a/lib/libc/net/getnetbyht.c b/lib/libc/net/getnetbyht.c
new file mode 100644
index 0000000..d2df570
--- /dev/null
+++ b/lib/libc/net/getnetbyht.c
@@ -0,0 +1,288 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/* Portions Copyright (c) 1993 Carlos Leandro and Rui Salgueiro
+ * Dep. Matematica Universidade de Coimbra, Portugal, Europe
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * from getnetent.c 1.1 (Coimbra) 93/06/02
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetent.c 8.1 (Berkeley) 6/4/93";
+static char orig_rcsid[] = "From: Id: getnetent.c,v 8.4 1997/06/01 20:34:37 vixie Exp";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+#include "netdb_private.h"
+
+void
+_setnethtent(int f, struct netent_data *ned)
+{
+
+ if (ned->netf == NULL)
+ ned->netf = fopen(_PATH_NETWORKS, "r");
+ else
+ rewind(ned->netf);
+ ned->stayopen |= f;
+}
+
+void
+_endnethtent(struct netent_data *ned)
+{
+
+ if (ned->netf) {
+ fclose(ned->netf);
+ ned->netf = NULL;
+ }
+ ned->stayopen = 0;
+}
+
+static int
+getnetent_p(struct netent *ne, struct netent_data *ned)
+{
+ char *p, *bp, *ep;
+ char *cp, **q;
+ int len;
+ char line[BUFSIZ + 1];
+
+ if (ned->netf == NULL &&
+ (ned->netf = fopen(_PATH_NETWORKS, "r")) == NULL)
+ return (-1);
+again:
+ p = fgets(line, sizeof line, ned->netf);
+ if (p == NULL)
+ return (-1);
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp != NULL)
+ *cp = '\0';
+ bp = ned->netbuf;
+ ep = ned->netbuf + sizeof ned->netbuf;
+ ne->n_name = bp;
+ cp = strpbrk(p, " \t");
+ if (cp == NULL)
+ goto again;
+ *cp++ = '\0';
+ len = strlen(p) + 1;
+ if (ep - bp < len) {
+ RES_SET_H_ERRNO(__res_state(), NO_RECOVERY);
+ return (-1);
+ }
+ strlcpy(bp, p, ep - bp);
+ bp += len;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ ne->n_net = inet_network(cp);
+ ne->n_addrtype = AF_INET;
+ q = ne->n_aliases = ned->net_aliases;
+ if (p != NULL) {
+ cp = p;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q >= &ned->net_aliases[_MAXALIASES - 1])
+ break;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ len = strlen(cp) + 1;
+ if (ep - bp < len)
+ break;
+ strlcpy(bp, cp, ep - bp);
+ *q++ = bp;
+ bp += len;
+ cp = p;
+ }
+ }
+ *q = NULL;
+ return (0);
+}
+
+int
+getnetent_r(struct netent *nptr, char *buffer, size_t buflen,
+ struct netent **result, int *h_errnop)
+{
+ struct netent_data *ned;
+ struct netent ne;
+ res_state statp;
+
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (-1);
+ }
+ if (getnetent_p(&ne, ned) != 0)
+ return (-1);
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return ((errno != 0) ? errno : -1);
+ }
+ *result = nptr;
+ return (0);
+}
+
+struct netent *
+getnetent(void)
+{
+ struct netdata *nd;
+ struct netent *rval;
+ int ret_h_errno;
+
+ if ((nd = __netdata_init()) == NULL)
+ return (NULL);
+ if (getnetent_r(&nd->net, nd->data, sizeof(nd->data), &rval,
+ &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
+}
+
+int
+_ht_getnetbyname(void *rval, void *cb_data, va_list ap)
+{
+ const char *name;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
+ struct netent_data *ned;
+ char **cp;
+ res_state statp;
+ int error;
+
+ name = va_arg(ap, const char *);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ _setnethtent(ned->stayopen, ned);
+ while ((error = getnetent_p(&ne, ned)) == 0) {
+ if (strcasecmp(ne.n_name, name) == 0)
+ break;
+ for (cp = ne.n_aliases; *cp != 0; cp++)
+ if (strcasecmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ if (!ned->stayopen)
+ _endnethtent(ned);
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
+}
+
+int
+_ht_getnetbyaddr(void *rval, void *cb_data, va_list ap)
+{
+ uint32_t net;
+ int type;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
+ struct netent_data *ned;
+ res_state statp;
+ int error;
+
+ net = va_arg(ap, uint32_t);
+ type = va_arg(ap, int);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ _setnethtent(ned->stayopen, ned);
+ while ((error = getnetent_p(&ne, ned)) == 0)
+ if (ne.n_addrtype == type && ne.n_net == net)
+ break;
+ if (!ned->stayopen)
+ _endnethtent(ned);
+ if (error != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
+}
diff --git a/lib/libc/net/getnetbynis.c b/lib/libc/net/getnetbynis.c
new file mode 100644
index 0000000..1dbed83
--- /dev/null
+++ b/lib/libc/net/getnetbynis.c
@@ -0,0 +1,259 @@
+/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+#include <arpa/nameser.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include "netdb_private.h"
+
+#ifdef YP
+static int
+_getnetbynis(const char *name, char *map, int af, struct netent *ne,
+ struct netent_data *ned)
+{
+ char *p, *bp, *ep;
+ char *cp, **q;
+ char *result;
+ int resultlen, len;
+ char ypbuf[YPMAXRECORD + 2];
+
+ switch(af) {
+ case AF_INET:
+ break;
+ default:
+ case AF_INET6:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+
+ if (ned->yp_domain == (char *)NULL)
+ if (yp_get_default_domain (&ned->yp_domain))
+ return (-1);
+
+ if (yp_match(ned->yp_domain, map, name, strlen(name), &result,
+ &resultlen))
+ return (-1);
+
+ bcopy((char *)result, (char *)&ypbuf, resultlen);
+ ypbuf[resultlen] = '\0';
+ free(result);
+ result = (char *)&ypbuf;
+
+ if ((cp = strchr(result, '\n')))
+ *cp = '\0';
+
+ cp = strpbrk(result, " \t");
+ *cp++ = '\0';
+ bp = ned->netbuf;
+ ep = ned->netbuf + sizeof ned->netbuf;
+ len = strlen(result) + 1;
+ if (ep - bp < len) {
+ RES_SET_H_ERRNO(__res_state(), NO_RECOVERY);
+ return (-1);
+ }
+ strlcpy(bp, result, ep - bp);
+ ne->n_name = bp;
+ bp += len;
+
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+
+ ne->n_net = inet_network(cp);
+ ne->n_addrtype = AF_INET;
+
+ q = ne->n_aliases = ned->net_aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q > &ned->net_aliases[_MAXALIASES - 1])
+ break;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ len = strlen(cp) + 1;
+ if (ep - bp < len)
+ break;
+ strlcpy(bp, cp, ep - bp);
+ *q++ = bp;
+ bp += len;
+ cp = p;
+ }
+ *q = NULL;
+ return (0);
+}
+#endif /* YP */
+
+int
+_nis_getnetbyname(void *rval, void *cb_data, va_list ap)
+{
+#ifdef YP
+ const char *name;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
+ struct netent_data *ned;
+ res_state statp;
+
+ name = va_arg(ap, const char *);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ if (_getnetbynis(name, "networks.byname", AF_INET, &ne, ned) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
+#else
+ return (NS_UNAVAIL);
+#endif
+
+}
+
+int
+_nis_getnetbyaddr(void *rval, void *cb_data, va_list ap)
+{
+#ifdef YP
+ uint32_t addr;
+ int af;
+ char *buffer;
+ size_t buflen;
+ int *errnop, *h_errnop;
+ struct netent *nptr, ne;
+ struct netent_data *ned;
+ char *str, *cp;
+ uint32_t net2;
+ int nn;
+ unsigned int netbr[4];
+ char buf[MAXDNAME];
+ res_state statp;
+
+ addr = va_arg(ap, uint32_t);
+ af = va_arg(ap, int);
+ nptr = va_arg(ap, struct netent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ h_errnop = va_arg(ap, int *);
+
+ statp = __res_state();
+ if ((ned = __netent_data_init()) == NULL) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_UNAVAIL);
+ }
+
+ if (af != AF_INET) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ errno = EAFNOSUPPORT;
+ return (NS_UNAVAIL);
+ }
+
+ for (nn = 4, net2 = addr; net2; net2 >>= 8) {
+ netbr[--nn] = net2 & 0xff;
+ }
+
+ switch (nn) {
+ case 3: /* Class A */
+ sprintf(buf, "%u", netbr[3]);
+ break;
+ case 2: /* Class B */
+ sprintf(buf, "%u.%u", netbr[2], netbr[3]);
+ break;
+ case 1: /* Class C */
+ sprintf(buf, "%u.%u.%u", netbr[1], netbr[2], netbr[3]);
+ break;
+ case 0: /* Class D - E */
+ sprintf(buf, "%u.%u.%u.%u", netbr[0], netbr[1],
+ netbr[2], netbr[3]);
+ break;
+ }
+
+ str = (char *)&buf;
+ cp = str + (strlen(str) - 2);
+
+ while(!strcmp(cp, ".0")) {
+ *cp = '\0';
+ cp = str + (strlen(str) - 2);
+ }
+
+ if (_getnetbynis(str, "networks.byaddr", af, &ne, ned) != 0) {
+ *h_errnop = statp->res_h_errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_netent(&ne, nptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ *h_errnop = statp->res_h_errno;
+ return (NS_RETURN);
+ }
+ *((struct netent **)rval) = nptr;
+ return (NS_SUCCESS);
+#else
+ return (NS_UNAVAIL);
+#endif /* YP */
+}
diff --git a/lib/libc/net/getnetent.3 b/lib/libc/net/getnetent.3
new file mode 100644
index 0000000..2e9cd33
--- /dev/null
+++ b/lib/libc/net/getnetent.3
@@ -0,0 +1,171 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getnetent.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt GETNETENT 3
+.Os
+.Sh NAME
+.Nm getnetent ,
+.Nm getnetbyaddr ,
+.Nm getnetbyname ,
+.Nm setnetent ,
+.Nm endnetent
+.Nd get network entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In netdb.h
+.Ft struct netent *
+.Fn getnetent void
+.Ft struct netent *
+.Fn getnetbyname "const char *name"
+.Ft struct netent *
+.Fn getnetbyaddr "uint32_t net" "int type"
+.Ft void
+.Fn setnetent "int stayopen"
+.Ft void
+.Fn endnetent void
+.Sh DESCRIPTION
+The
+.Fn getnetent ,
+.Fn getnetbyname ,
+and
+.Fn getnetbyaddr
+functions
+each return a pointer to an object with the
+following structure describing an internet network.
+This structure contains either the information obtained
+from the nameserver,
+.Xr named 8 ,
+broken-out fields of a line in the network data base
+.Pa /etc/networks ,
+or entries supplied by the
+.Xr yp 8
+system.
+The order of the lookups is controlled by the
+`networks' entry in
+.Xr nsswitch.conf 5 .
+.Bd -literal -offset indent
+struct netent {
+ char *n_name; /* official name of net */
+ char **n_aliases; /* alias list */
+ int n_addrtype; /* net number type */
+ uint32_t n_net; /* net number */
+};
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width n_addrtype
+.It Fa n_name
+The official name of the network.
+.It Fa n_aliases
+A zero terminated list of alternate names for the network.
+.It Fa n_addrtype
+The type of the network number returned; currently only AF_INET.
+.It Fa n_net
+The network number.
+Network numbers are returned in machine byte
+order.
+.El
+.Pp
+The
+.Fn getnetent
+function
+reads the next line of the file, opening the file if necessary.
+.Pp
+The
+.Fn setnetent
+function
+opens and rewinds the file.
+If the
+.Fa stayopen
+flag is non-zero,
+the net data base will not be closed after each call to
+.Fn getnetbyname
+or
+.Fn getnetbyaddr .
+.Pp
+The
+.Fn endnetent
+function
+closes the file.
+.Pp
+The
+.Fn getnetbyname
+function
+and
+.Fn getnetbyaddr
+sequentially search from the beginning
+of the file until a matching
+net name or
+net address and type is found,
+or until
+.Dv EOF
+is encountered.
+The
+.Fa type
+argument
+must be
+.Dv AF_INET .
+Network numbers are supplied in host order.
+.Sh FILES
+.Bl -tag -width /etc/nsswitch.conf -compact
+.It Pa /etc/networks
+.It Pa /etc/nsswitch.conf
+.It Pa /etc/resolv.conf
+.El
+.Sh DIAGNOSTICS
+Null pointer
+(0) returned on
+.Dv EOF
+or error.
+.Sh SEE ALSO
+.Xr networks 5
+.Pp
+.%T RFC 1101
+.Sh HISTORY
+The
+.Fn getnetent ,
+.Fn getnetbyaddr ,
+.Fn getnetbyname ,
+.Fn setnetent ,
+and
+.Fn endnetent
+functions appeared in
+.Bx 4.2 .
+.Sh BUGS
+The data space used by
+these functions is thread-specific; if future use requires the data, it should be
+copied before any subsequent calls to these functions overwrite it.
+Only Internet network
+numbers are currently understood.
+Expecting network numbers to fit
+in no more than 32 bits is probably
+naive.
diff --git a/lib/libc/net/getnetnamadr.c b/lib/libc/net/getnetnamadr.c
new file mode 100644
index 0000000..9aa4d51
--- /dev/null
+++ b/lib/libc/net/getnetnamadr.c
@@ -0,0 +1,458 @@
+/*-
+ * Copyright (c) 1994, Garrett Wollman
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+#include "un-namespace.h"
+#include "netdb_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+
+extern int _ht_getnetbyname(void *, void *, va_list);
+extern int _dns_getnetbyname(void *, void *, va_list);
+extern int _nis_getnetbyname(void *, void *, va_list);
+extern int _ht_getnetbyaddr(void *, void *, va_list);
+extern int _dns_getnetbyaddr(void *, void *, va_list);
+extern int _nis_getnetbyaddr(void *, void *, va_list);
+
+/* Network lookup order if nsswitch.conf is broken or nonexistant */
+static const ns_src default_src[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { NSSRC_DNS, NS_SUCCESS },
+ { 0 }
+};
+
+NETDB_THREAD_ALLOC(netent_data)
+NETDB_THREAD_ALLOC(netdata)
+
+#ifdef NS_CACHING
+static int
+net_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
+{
+ char *name;
+ uint32_t net;
+ int type;
+
+ size_t desired_size, size;
+ enum nss_lookup_type lookup_type;
+ int res = NS_UNAVAIL;
+
+ lookup_type = (enum nss_lookup_type)cache_mdata;
+ switch (lookup_type) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+
+ size = strlen(name);
+ desired_size = sizeof(enum nss_lookup_type) + size + 1;
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
+
+ res = NS_SUCCESS;
+ break;
+ case nss_lt_id:
+ net = va_arg(ap, uint32_t);
+ type = va_arg(ap, int);
+
+ desired_size = sizeof(enum nss_lookup_type) +
+ sizeof(uint32_t) + sizeof(int);
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), &net,
+ sizeof(uint32_t));
+ memcpy(buffer + sizeof(enum nss_lookup_type) + sizeof(uint32_t),
+ &type, sizeof(int));
+
+ res = NS_SUCCESS;
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+fin:
+ *buffer_size = desired_size;
+ return (res);
+}
+
+
+static int
+net_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ uint32_t net;
+ int type;
+ struct netent *ne;
+ char *orig_buf;
+ size_t orig_buf_size;
+
+ struct netent new_ne;
+ size_t desired_size, size, aliases_size;
+ char *p;
+ char **alias;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ net = va_arg(ap, uint32_t);
+ type = va_arg(ap, int);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ ne = va_arg(ap, struct netent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+
+ desired_size = _ALIGNBYTES + sizeof(struct netent) + sizeof(char *);
+ if (ne->n_name != NULL)
+ desired_size += strlen(ne->n_name) + 1;
+
+ if (ne->n_aliases != NULL) {
+ aliases_size = 0;
+ for (alias = ne->n_aliases; *alias; ++alias) {
+ desired_size += strlen(*alias) + 1;
+ ++aliases_size;
+ }
+
+ desired_size += _ALIGNBYTES +
+ (aliases_size + 1) * sizeof(char *);
+ }
+
+ if (*buffer_size < desired_size) {
+ /* this assignment is here for future use */
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ memcpy(&new_ne, ne, sizeof(struct netent));
+
+ *buffer_size = desired_size;
+ memset(buffer, 0, desired_size);
+ p = buffer + sizeof(struct netent) + sizeof(char *);
+ memcpy(buffer + sizeof(struct netent), &p, sizeof(char *));
+ p = (char *)_ALIGN(p);
+
+ if (new_ne.n_name != NULL) {
+ size = strlen(new_ne.n_name);
+ memcpy(p, new_ne.n_name, size);
+ new_ne.n_name = p;
+ p += size + 1;
+ }
+
+ if (new_ne.n_aliases != NULL) {
+ p = (char *)_ALIGN(p);
+ memcpy(p, new_ne.n_aliases, sizeof(char *) * aliases_size);
+ new_ne.n_aliases = (char **)p;
+ p += sizeof(char *) * (aliases_size + 1);
+
+ for (alias = new_ne.n_aliases; *alias; ++alias) {
+ size = strlen(*alias);
+ memcpy(p, *alias, size);
+ *alias = p;
+ p += size + 1;
+ }
+ }
+
+ memcpy(buffer, &new_ne, sizeof(struct netent));
+ return (NS_SUCCESS);
+}
+
+static int
+net_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ uint32_t net;
+ int type;
+ struct netent *ne;
+ char *orig_buf;
+ size_t orig_buf_size;
+ int *ret_errno;
+
+ char *p;
+ char **alias;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ net = va_arg(ap, uint32_t);
+ type = va_arg(ap, int);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ ne = va_arg(ap, struct netent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+ ret_errno = va_arg(ap, int *);
+
+ if (orig_buf_size <
+ buffer_size - sizeof(struct netent) - sizeof(char *)) {
+ *ret_errno = ERANGE;
+ return (NS_RETURN);
+ }
+
+ memcpy(ne, buffer, sizeof(struct netent));
+ memcpy(&p, buffer + sizeof(struct netent), sizeof(char *));
+
+ orig_buf = (char *)_ALIGN(orig_buf);
+ memcpy(orig_buf, buffer + sizeof(struct netent) + sizeof(char *) +
+ _ALIGN(p) - (size_t)p,
+ buffer_size - sizeof(struct netent) - sizeof(char *) -
+ _ALIGN(p) + (size_t)p);
+ p = (char *)_ALIGN(p);
+
+ NS_APPLY_OFFSET(ne->n_name, orig_buf, p, char *);
+ if (ne->n_aliases != NULL) {
+ NS_APPLY_OFFSET(ne->n_aliases, orig_buf, p, char **);
+
+ for (alias = ne->n_aliases; *alias; ++alias)
+ NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
+ }
+
+ if (retval != NULL)
+ *((struct netent **)retval) = ne;
+
+ return (NS_SUCCESS);
+}
+#endif /* NS_CACHING */
+
+static void
+netent_data_free(void *ptr)
+{
+ struct netent_data *ned = ptr;
+
+ if (ned == NULL)
+ return;
+ ned->stayopen = 0;
+ _endnethtent(ned);
+ free(ned);
+}
+
+static void
+netdata_free(void *ptr)
+{
+ free(ptr);
+}
+
+int
+__copy_netent(struct netent *ne, struct netent *nptr, char *buf, size_t buflen)
+{
+ char *cp;
+ int i, n;
+ int numptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ numptr = 1; /* NULL ptr */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; ne->n_aliases[i]; i++, numptr++) {
+ len += strlen(ne->n_aliases[i]) + 1;
+ }
+ len += strlen(ne->n_name) + 1;
+ len += numptr * sizeof(char*);
+
+ if (len > (int)buflen) {
+ errno = ERANGE;
+ return (-1);
+ }
+
+ /* copy net value and type */
+ nptr->n_addrtype = ne->n_addrtype;
+ nptr->n_net = ne->n_net;
+
+ cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
+
+ /* copy official name */
+ n = strlen(ne->n_name) + 1;
+ strcpy(cp, ne->n_name);
+ nptr->n_name = cp;
+ cp += n;
+
+ /* copy aliases */
+ nptr->n_aliases = (char **)ALIGN(buf);
+ for (i = 0 ; ne->n_aliases[i]; i++) {
+ n = strlen(ne->n_aliases[i]) + 1;
+ strcpy(cp, ne->n_aliases[i]);
+ nptr->n_aliases[i] = cp;
+ cp += n;
+ }
+ nptr->n_aliases[i] = NULL;
+
+ return (0);
+}
+
+int
+getnetbyname_r(const char *name, struct netent *ne, char *buffer,
+ size_t buflen, struct netent **result, int *h_errorp)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ networks, (void *)nss_lt_name,
+ net_id_func, net_marshal_func, net_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ NS_FILES_CB(_ht_getnetbyname, NULL)
+ { NSSRC_DNS, _dns_getnetbyname, NULL },
+ NS_NIS_CB(_nis_getnetbyname, NULL) /* force -DHESIOD */
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { 0 }
+ };
+ int rval, ret_errno = 0;
+
+ rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS,
+ "getnetbyname_r", default_src, name, ne, buffer, buflen,
+ &ret_errno, h_errorp);
+
+ if (rval != NS_SUCCESS) {
+ errno = ret_errno;
+ return ((ret_errno != 0) ? ret_errno : -1);
+ }
+ return (0);
+}
+
+int
+getnetbyaddr_r(uint32_t addr, int af, struct netent *ne, char *buffer,
+ size_t buflen, struct netent **result, int *h_errorp)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ networks, (void *)nss_lt_id,
+ net_id_func, net_marshal_func, net_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ NS_FILES_CB(_ht_getnetbyaddr, NULL)
+ { NSSRC_DNS, _dns_getnetbyaddr, NULL },
+ NS_NIS_CB(_nis_getnetbyaddr, NULL) /* force -DHESIOD */
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { 0 }
+ };
+ int rval, ret_errno = 0;
+
+ rval = _nsdispatch((void *)result, dtab, NSDB_NETWORKS,
+ "getnetbyaddr_r", default_src, addr, af, ne, buffer, buflen,
+ &ret_errno, h_errorp);
+
+ if (rval != NS_SUCCESS) {
+ errno = ret_errno;
+ return ((ret_errno != 0) ? ret_errno : -1);
+ }
+ return (0);
+}
+
+struct netent *
+getnetbyname(const char *name)
+{
+ struct netdata *nd;
+ struct netent *rval;
+ int ret_h_errno;
+
+ if ((nd = __netdata_init()) == NULL)
+ return (NULL);
+ if (getnetbyname_r(name, &nd->net, nd->data, sizeof(nd->data), &rval,
+ &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
+}
+
+struct netent *
+getnetbyaddr(uint32_t addr, int af)
+{
+ struct netdata *nd;
+ struct netent *rval;
+ int ret_h_errno;
+
+ if ((nd = __netdata_init()) == NULL)
+ return (NULL);
+ if (getnetbyaddr_r(addr, af, &nd->net, nd->data, sizeof(nd->data),
+ &rval, &ret_h_errno) != 0)
+ return (NULL);
+ return (rval);
+}
+
+void
+setnetent(int stayopen)
+{
+ struct netent_data *ned;
+
+ if ((ned = __netent_data_init()) == NULL)
+ return;
+ _setnethtent(stayopen, ned);
+ _setnetdnsent(stayopen);
+}
+
+void
+endnetent(void)
+{
+ struct netent_data *ned;
+
+ if ((ned = __netent_data_init()) == NULL)
+ return;
+ _endnethtent(ned);
+ _endnetdnsent();
+}
diff --git a/lib/libc/net/getproto.c b/lib/libc/net/getproto.c
new file mode 100644
index 0000000..b923edf
--- /dev/null
+++ b/lib/libc/net/getproto.c
@@ -0,0 +1,143 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getproto.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <netdb.h>
+#include <nsswitch.h>
+#include "netdb_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+#include "nss_tls.h"
+
+static const ns_src defaultsrc[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { NULL, 0 }
+};
+
+#ifdef NS_CACHING
+extern int __proto_id_func(char *, size_t *, va_list, void *);
+extern int __proto_marshal_func(char *, size_t *, void *, va_list, void *);
+extern int __proto_unmarshal_func(char *, size_t, void *, va_list, void *);
+#endif
+
+static int
+files_getprotobynumber(void *retval, void *mdata, va_list ap)
+{
+ struct protoent pe;
+ struct protoent_data *ped;
+ int error;
+
+ int number;
+ struct protoent *pptr;
+ char *buffer;
+ size_t buflen;
+ int *errnop;
+
+ number = va_arg(ap, int);
+ pptr = va_arg(ap, struct protoent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+
+ if ((ped = __protoent_data_init()) == NULL) {
+ *errnop = errno;
+ return (NS_NOTFOUND);
+ }
+
+ __setprotoent_p(ped->stayopen, ped);
+ while ((error = __getprotoent_p(&pe, ped)) == 0)
+ if (pe.p_proto == number)
+ break;
+ if (!ped->stayopen)
+ __endprotoent_p(ped);
+ if (error != 0) {
+ *errnop = errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_protoent(&pe, pptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ return (NS_RETURN);
+ }
+
+ *((struct protoent **)retval) = pptr;
+ return (NS_SUCCESS);
+}
+
+int
+getprotobynumber_r(int proto, struct protoent *pptr, char *buffer,
+ size_t buflen, struct protoent **result)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ protocols, (void *)nss_lt_id,
+ __proto_id_func, __proto_marshal_func, __proto_unmarshal_func);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_getprotobynumber, NULL },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_PROTOCOLS, "getprotobynumber_r",
+ defaultsrc, proto, pptr, buffer, buflen, &ret_errno);
+
+ if (rv != NS_SUCCESS) {
+ errno = ret_errno;
+ return (ret_errno);
+ }
+ return (0);
+}
+
+struct protoent *
+getprotobynumber(int proto)
+{
+ struct protodata *pd;
+ struct protoent *rval;
+
+ if ((pd = __protodata_init()) == NULL)
+ return (NULL);
+ if (getprotobynumber_r(proto, &pd->proto, pd->data, sizeof(pd->data),
+ &rval) != 0)
+ return (NULL);
+ return (rval);
+}
diff --git a/lib/libc/net/getprotoent.3 b/lib/libc/net/getprotoent.3
new file mode 100644
index 0000000..9f9e00d
--- /dev/null
+++ b/lib/libc/net/getprotoent.3
@@ -0,0 +1,145 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getprotoent.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt GETPROTOENT 3
+.Os
+.Sh NAME
+.Nm getprotoent ,
+.Nm getprotobynumber ,
+.Nm getprotobyname ,
+.Nm setprotoent ,
+.Nm endprotoent
+.Nd get protocol entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In netdb.h
+.Ft struct protoent *
+.Fn getprotoent void
+.Ft struct protoent *
+.Fn getprotobyname "const char *name"
+.Ft struct protoent *
+.Fn getprotobynumber "int proto"
+.Ft void
+.Fn setprotoent "int stayopen"
+.Ft void
+.Fn endprotoent void
+.Sh DESCRIPTION
+The
+.Fn getprotoent ,
+.Fn getprotobyname ,
+and
+.Fn getprotobynumber
+functions
+each return a pointer to an object with the
+following structure
+containing the broken-out
+fields of a line in the network protocol data base,
+.Pa /etc/protocols .
+.Bd -literal -offset indent
+struct protoent {
+ char *p_name; /* official name of protocol */
+ char **p_aliases; /* alias list */
+ int p_proto; /* protocol number */
+};
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width p_aliases
+.It Fa p_name
+The official name of the protocol.
+.It Fa p_aliases
+A zero terminated list of alternate names for the protocol.
+.It Fa p_proto
+The protocol number.
+.El
+.Pp
+The
+.Fn getprotoent
+function
+reads the next line of the file, opening the file if necessary.
+.Pp
+The
+.Fn setprotoent
+function
+opens and rewinds the file.
+If the
+.Fa stayopen
+flag is non-zero,
+the net data base will not be closed after each call to
+.Fn getprotobyname
+or
+.Fn getprotobynumber .
+.Pp
+The
+.Fn endprotoent
+function
+closes the file.
+.Pp
+The
+.Fn getprotobyname
+function
+and
+.Fn getprotobynumber
+sequentially search from the beginning
+of the file until a matching
+protocol name or
+protocol number is found,
+or until
+.Dv EOF
+is encountered.
+.Sh RETURN VALUES
+Null pointer
+(0) returned on
+.Dv EOF
+or error.
+.Sh FILES
+.Bl -tag -width /etc/protocols -compact
+.It Pa /etc/protocols
+.El
+.Sh SEE ALSO
+.Xr protocols 5
+.Sh HISTORY
+The
+.Fn getprotoent ,
+.Fn getprotobynumber ,
+.Fn getprotobyname ,
+.Fn setprotoent ,
+and
+.Fn endprotoent
+functions appeared in
+.Bx 4.2 .
+.Sh BUGS
+These functions use a thread-specific data space;
+if the data is needed for future use, it should be
+copied before any subsequent calls overwrite it.
+Only the Internet
+protocols are currently understood.
diff --git a/lib/libc/net/getprotoent.c b/lib/libc/net/getprotoent.c
new file mode 100644
index 0000000..0cfca45
--- /dev/null
+++ b/lib/libc/net/getprotoent.c
@@ -0,0 +1,554 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getprotoent.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <nsswitch.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "namespace.h"
+#include "reentrant.h"
+#include "un-namespace.h"
+#include "netdb_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+#include "nss_tls.h"
+
+static const ns_src defaultsrc[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { NULL, 0 }
+};
+
+NETDB_THREAD_ALLOC(protoent_data)
+NETDB_THREAD_ALLOC(protodata)
+
+static void
+protoent_data_clear(struct protoent_data *ped)
+{
+ if (ped->fp) {
+ fclose(ped->fp);
+ ped->fp = NULL;
+ }
+}
+
+static void
+protoent_data_free(void *ptr)
+{
+ struct protoent_data *ped = ptr;
+
+ protoent_data_clear(ped);
+ free(ped);
+}
+
+static void
+protodata_free(void *ptr)
+{
+ free(ptr);
+}
+
+#ifdef NS_CACHING
+int
+__proto_id_func(char *buffer, size_t *buffer_size, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ int proto;
+
+ size_t desired_size, size;
+ enum nss_lookup_type lookup_type;
+ int res = NS_UNAVAIL;
+
+ lookup_type = (enum nss_lookup_type)cache_mdata;
+ switch (lookup_type) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+
+ size = strlen(name);
+ desired_size = sizeof(enum nss_lookup_type) + size + 1;
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
+
+ res = NS_SUCCESS;
+ break;
+ case nss_lt_id:
+ proto = va_arg(ap, int);
+
+ desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), &proto,
+ sizeof(int));
+
+ res = NS_SUCCESS;
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+fin:
+ *buffer_size = desired_size;
+ return (res);
+}
+
+
+int
+__proto_marshal_func(char *buffer, size_t *buffer_size, void *retval,
+ va_list ap, void *cache_mdata)
+{
+ char *name;
+ int num;
+ struct protoent *proto;
+ char *orig_buf;
+ size_t orig_buf_size;
+
+ struct protoent new_proto;
+ size_t desired_size, size, aliases_size;
+ char *p;
+ char **alias;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ num = va_arg(ap, int);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ proto = va_arg(ap, struct protoent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+
+ desired_size = _ALIGNBYTES + sizeof(struct protoent) + sizeof(char *);
+ if (proto->p_name != NULL)
+ desired_size += strlen(proto->p_name) + 1;
+
+ if (proto->p_aliases != NULL) {
+ aliases_size = 0;
+ for (alias = proto->p_aliases; *alias; ++alias) {
+ desired_size += strlen(*alias) + 1;
+ ++aliases_size;
+ }
+
+ desired_size += _ALIGNBYTES + (aliases_size + 1) *
+ sizeof(char *);
+ }
+
+ if (*buffer_size < desired_size) {
+ /* this assignment is here for future use */
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ memcpy(&new_proto, proto, sizeof(struct protoent));
+
+ *buffer_size = desired_size;
+ memset(buffer, 0, desired_size);
+ p = buffer + sizeof(struct protoent) + sizeof(char *);
+ memcpy(buffer + sizeof(struct protoent), &p, sizeof(char *));
+ p = (char *)_ALIGN(p);
+
+ if (new_proto.p_name != NULL) {
+ size = strlen(new_proto.p_name);
+ memcpy(p, new_proto.p_name, size);
+ new_proto.p_name = p;
+ p += size + 1;
+ }
+
+ if (new_proto.p_aliases != NULL) {
+ p = (char *)_ALIGN(p);
+ memcpy(p, new_proto.p_aliases, sizeof(char *) * aliases_size);
+ new_proto.p_aliases = (char **)p;
+ p += sizeof(char *) * (aliases_size + 1);
+
+ for (alias = new_proto.p_aliases; *alias; ++alias) {
+ size = strlen(*alias);
+ memcpy(p, *alias, size);
+ *alias = p;
+ p += size + 1;
+ }
+ }
+
+ memcpy(buffer, &new_proto, sizeof(struct protoent));
+ return (NS_SUCCESS);
+}
+
+int
+__proto_unmarshal_func(char *buffer, size_t buffer_size, void *retval,
+ va_list ap, void *cache_mdata)
+{
+ char *name;
+ int num;
+ struct protoent *proto;
+ char *orig_buf;
+ size_t orig_buf_size;
+ int *ret_errno;
+
+ char *p;
+ char **alias;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ num = va_arg(ap, int);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ proto = va_arg(ap, struct protoent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+ ret_errno = va_arg(ap, int *);
+
+ if (orig_buf_size <
+ buffer_size - sizeof(struct protoent) - sizeof(char *)) {
+ *ret_errno = ERANGE;
+ return (NS_RETURN);
+ }
+
+ memcpy(proto, buffer, sizeof(struct protoent));
+ memcpy(&p, buffer + sizeof(struct protoent), sizeof(char *));
+
+ orig_buf = (char *)_ALIGN(orig_buf);
+ memcpy(orig_buf, buffer + sizeof(struct protoent) + sizeof(char *) +
+ _ALIGN(p) - (size_t)p,
+ buffer_size - sizeof(struct protoent) - sizeof(char *) -
+ _ALIGN(p) + (size_t)p);
+ p = (char *)_ALIGN(p);
+
+ NS_APPLY_OFFSET(proto->p_name, orig_buf, p, char *);
+ if (proto->p_aliases != NULL) {
+ NS_APPLY_OFFSET(proto->p_aliases, orig_buf, p, char **);
+
+ for (alias = proto->p_aliases; *alias; ++alias)
+ NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
+ }
+
+ if (retval != NULL)
+ *((struct protoent **)retval) = proto;
+
+ return (NS_SUCCESS);
+}
+
+NSS_MP_CACHE_HANDLING(protocols);
+#endif /* NS_CACHING */
+
+int
+__copy_protoent(struct protoent *pe, struct protoent *pptr, char *buf,
+ size_t buflen)
+{
+ char *cp;
+ int i, n;
+ int numptr, len;
+
+ /* Find out the amount of space required to store the answer. */
+ numptr = 1; /* NULL ptr */
+ len = (char *)ALIGN(buf) - buf;
+ for (i = 0; pe->p_aliases[i]; i++, numptr++) {
+ len += strlen(pe->p_aliases[i]) + 1;
+ }
+ len += strlen(pe->p_name) + 1;
+ len += numptr * sizeof(char*);
+
+ if (len > (int)buflen) {
+ errno = ERANGE;
+ return (-1);
+ }
+
+ /* copy protocol value*/
+ pptr->p_proto = pe->p_proto;
+
+ cp = (char *)ALIGN(buf) + numptr * sizeof(char *);
+
+ /* copy official name */
+ n = strlen(pe->p_name) + 1;
+ strcpy(cp, pe->p_name);
+ pptr->p_name = cp;
+ cp += n;
+
+ /* copy aliases */
+ pptr->p_aliases = (char **)ALIGN(buf);
+ for (i = 0 ; pe->p_aliases[i]; i++) {
+ n = strlen(pe->p_aliases[i]) + 1;
+ strcpy(cp, pe->p_aliases[i]);
+ pptr->p_aliases[i] = cp;
+ cp += n;
+ }
+ pptr->p_aliases[i] = NULL;
+
+ return (0);
+}
+
+void
+__setprotoent_p(int f, struct protoent_data *ped)
+{
+ if (ped->fp == NULL)
+ ped->fp = fopen(_PATH_PROTOCOLS, "r");
+ else
+ rewind(ped->fp);
+ ped->stayopen |= f;
+}
+
+void
+__endprotoent_p(struct protoent_data *ped)
+{
+ if (ped->fp) {
+ fclose(ped->fp);
+ ped->fp = NULL;
+ }
+ ped->stayopen = 0;
+}
+
+int
+__getprotoent_p(struct protoent *pe, struct protoent_data *ped)
+{
+ char *p;
+ char *cp, **q, *endp;
+ long l;
+
+ if (ped->fp == NULL && (ped->fp = fopen(_PATH_PROTOCOLS, "r")) == NULL)
+ return (-1);
+again:
+ if ((p = fgets(ped->line, sizeof ped->line, ped->fp)) == NULL)
+ return (-1);
+ if (*p == '#')
+ goto again;
+ cp = strpbrk(p, "#\n");
+ if (cp != NULL)
+ *cp = '\0';
+ pe->p_name = p;
+ cp = strpbrk(p, " \t");
+ if (cp == NULL)
+ goto again;
+ *cp++ = '\0';
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ p = strpbrk(cp, " \t");
+ if (p != NULL)
+ *p++ = '\0';
+ l = strtol(cp, &endp, 10);
+ if (endp == cp || *endp != '\0' || l < 0 || l > USHRT_MAX)
+ goto again;
+ pe->p_proto = l;
+ q = pe->p_aliases = ped->aliases;
+ if (p != NULL) {
+ cp = p;
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &ped->aliases[_MAXALIASES - 1])
+ *q++ = cp;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ }
+ *q = NULL;
+ return (0);
+}
+
+static int
+files_getprotoent_r(void *retval, void *mdata, va_list ap)
+{
+ struct protoent pe;
+ struct protoent_data *ped;
+
+ struct protoent *pptr;
+ char *buffer;
+ size_t buflen;
+ int *errnop;
+
+ pptr = va_arg(ap, struct protoent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+
+ if ((ped = __protoent_data_init()) == NULL) {
+ *errnop = errno;
+ return (NS_NOTFOUND);
+ }
+
+ if (__getprotoent_p(&pe, ped) != 0) {
+ *errnop = errno;
+ return (NS_NOTFOUND);
+ }
+
+ if (__copy_protoent(&pe, pptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ return (NS_RETURN);
+ }
+
+ *((struct protoent **)retval) = pptr;
+ return (NS_SUCCESS);
+}
+
+static int
+files_setprotoent(void *retval, void *mdata, va_list ap)
+{
+ struct protoent_data *ped;
+ int f;
+
+ f = va_arg(ap, int);
+ if ((ped = __protoent_data_init()) == NULL)
+ return (NS_UNAVAIL);
+
+ __setprotoent_p(f, ped);
+ return (NS_UNAVAIL);
+}
+
+static int
+files_endprotoent(void *retval, void *mdata, va_list ap)
+{
+ struct protoent_data *ped;
+
+ if ((ped = __protoent_data_init()) == NULL)
+ return (NS_UNAVAIL);
+
+ __endprotoent_p(ped);
+ return (NS_UNAVAIL);
+}
+
+int
+getprotoent_r(struct protoent *pptr, char *buffer, size_t buflen,
+ struct protoent **result)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ protocols, (void *)nss_lt_all,
+ __proto_marshal_func, __proto_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_getprotoent_r, (void *)nss_lt_all },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_PROTOCOLS, "getprotoent_r",
+ defaultsrc, pptr, buffer, buflen, &ret_errno);
+
+ if (rv != NS_SUCCESS) {
+ errno = ret_errno;
+ return (ret_errno);
+ }
+ return (0);
+}
+
+void
+setprotoent(int stayopen)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ protocols, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_setprotoent, NULL },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+
+ (void)nsdispatch(NULL, dtab, NSDB_PROTOCOLS, "setprotoent", defaultsrc,
+ stayopen);
+}
+
+void
+endprotoent(void)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ protocols, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_endprotoent, NULL },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+
+ (void)nsdispatch(NULL, dtab, NSDB_PROTOCOLS, "endprotoent", defaultsrc);
+}
+
+struct protoent *
+getprotoent(void)
+{
+ struct protodata *pd;
+ struct protoent *rval;
+
+ if ((pd = __protodata_init()) == NULL)
+ return (NULL);
+ if (getprotoent_r(&pd->proto, pd->data, sizeof(pd->data), &rval) != 0)
+ return (NULL);
+ return (rval);
+}
diff --git a/lib/libc/net/getprotoname.c b/lib/libc/net/getprotoname.c
new file mode 100644
index 0000000..22c5759
--- /dev/null
+++ b/lib/libc/net/getprotoname.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getprotoname.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <netdb.h>
+#include <nsswitch.h>
+#include <string.h>
+#include "netdb_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+#include "nss_tls.h"
+
+static const ns_src defaultsrc[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { NULL, 0 }
+};
+
+#ifdef NS_CACHING
+extern int __proto_id_func(char *, size_t *, va_list, void *);
+extern int __proto_marshal_func(char *, size_t *, void *, va_list, void *);
+extern int __proto_unmarshal_func(char *, size_t, void *, va_list, void *);
+#endif
+
+static int
+files_getprotobyname(void *retval, void *mdata, va_list ap)
+{
+ struct protoent pe;
+ struct protoent_data *ped;
+ char **cp;
+ int error;
+
+ char *name;
+ struct protoent *pptr;
+ char *buffer;
+ size_t buflen;
+ int *errnop;
+
+ name = va_arg(ap, char *);
+ pptr = va_arg(ap, struct protoent *);
+ buffer = va_arg(ap, char *);
+ buflen = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+
+
+ if ((ped = __protoent_data_init()) == NULL) {
+ *errnop = errno;
+ return (NS_NOTFOUND);
+ }
+
+ __setprotoent_p(ped->stayopen, ped);
+ while ((error = __getprotoent_p(&pe, ped)) == 0) {
+ if (strcmp(pe.p_name, name) == 0)
+ break;
+ for (cp = pe.p_aliases; *cp != 0; cp++)
+ if (strcmp(*cp, name) == 0)
+ goto found;
+ }
+found:
+ if (!ped->stayopen)
+ __endprotoent_p(ped);
+ if (error != 0) {
+ *errnop = errno;
+ return (NS_NOTFOUND);
+ }
+ if (__copy_protoent(&pe, pptr, buffer, buflen) != 0) {
+ *errnop = errno;
+ return (NS_RETURN);
+ }
+
+ *((struct protoent **)retval) = pptr;
+ return (NS_SUCCESS);
+}
+
+
+int
+getprotobyname_r(const char *name, struct protoent *pptr, char *buffer,
+ size_t buflen, struct protoent **result)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ protocols, (void *)nss_lt_name,
+ __proto_id_func, __proto_marshal_func, __proto_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_getprotobyname, NULL },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_PROTOCOLS, "getprotobyname_r",
+ defaultsrc, name, pptr, buffer, buflen, &ret_errno);
+
+ if (rv != NS_SUCCESS) {
+ errno = ret_errno;
+ return (ret_errno);
+ }
+ return (0);
+}
+
+struct protoent *
+getprotobyname(const char *name)
+{
+ struct protodata *pd;
+ struct protoent *rval;
+
+ if ((pd = __protodata_init()) == NULL)
+ return (NULL);
+ if (getprotobyname_r(name, &pd->proto, pd->data, sizeof(pd->data),
+ &rval) != 0)
+ return (NULL);
+ return (rval);
+}
diff --git a/lib/libc/net/getservent.3 b/lib/libc/net/getservent.3
new file mode 100644
index 0000000..65d40bb
--- /dev/null
+++ b/lib/libc/net/getservent.3
@@ -0,0 +1,155 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)getservent.3 8.3 (Berkeley) 1/12/94
+.\" $FreeBSD$
+.\"
+.Dd July 9, 1995
+.Dt GETSERVENT 3
+.Os
+.Sh NAME
+.Nm getservent ,
+.Nm getservbyport ,
+.Nm getservbyname ,
+.Nm setservent ,
+.Nm endservent
+.Nd get service entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In netdb.h
+.Ft struct servent *
+.Fn getservent
+.Ft struct servent *
+.Fn getservbyname "const char *name" "const char *proto"
+.Ft struct servent *
+.Fn getservbyport "int port" "const char *proto"
+.Ft void
+.Fn setservent "int stayopen"
+.Ft void
+.Fn endservent void
+.Sh DESCRIPTION
+The
+.Fn getservent ,
+.Fn getservbyname ,
+and
+.Fn getservbyport
+functions
+each return a pointer to an object with the
+following structure
+containing the broken-out
+fields of a line in the network services data base,
+.Pa /etc/services .
+.Bd -literal -offset indent
+struct servent {
+ char *s_name; /* official name of service */
+ char **s_aliases; /* alias list */
+ int s_port; /* port service resides at */
+ char *s_proto; /* protocol to use */
+};
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width s_aliases
+.It Fa s_name
+The official name of the service.
+.It Fa s_aliases
+A zero terminated list of alternate names for the service.
+.It Fa s_port
+The port number at which the service resides.
+Port numbers are returned in network byte order.
+.It Fa s_proto
+The name of the protocol to use when contacting the
+service.
+.El
+.Pp
+The
+.Fn getservent
+function
+reads the next line of the file, opening the file if necessary.
+.Pp
+The
+.Fn setservent
+function
+opens and rewinds the file.
+If the
+.Fa stayopen
+flag is non-zero,
+the net data base will not be closed after each call to
+.Fn getservbyname
+or
+.Fn getservbyport .
+.Pp
+The
+.Fn endservent
+function
+closes the file.
+.Pp
+The
+.Fn getservbyname
+and
+.Fn getservbyport
+functions
+sequentially search from the beginning
+of the file until a matching
+protocol name or
+port number (which must be specified in
+network byte order) is found,
+or until
+.Dv EOF
+is encountered.
+If a protocol name is also supplied (non-
+.Dv NULL ) ,
+searches must also match the protocol.
+.Sh FILES
+.Bl -tag -width /etc/services -compact
+.It Pa /etc/services
+.El
+.Sh DIAGNOSTICS
+Null pointer
+(0) returned on
+.Dv EOF
+or error.
+.Sh SEE ALSO
+.Xr getprotoent 3 ,
+.Xr services 5
+.Sh HISTORY
+The
+.Fn getservent ,
+.Fn getservbyport ,
+.Fn getservbyname ,
+.Fn setservent ,
+and
+.Fn endservent
+functions appeared in
+.Bx 4.2 .
+.Sh BUGS
+These functions use a thread-specific data storage;
+if the data is needed for future use, it should be
+copied before any subsequent calls overwrite it.
+Expecting port numbers to fit in a 32 bit
+quantity is probably naive.
diff --git a/lib/libc/net/getservent.c b/lib/libc/net/getservent.c
new file mode 100644
index 0000000..3228bdc
--- /dev/null
+++ b/lib/libc/net/getservent.c
@@ -0,0 +1,1373 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getservent.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <db.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <netdb.h>
+#include <nsswitch.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#ifdef YP
+#include <rpc/rpc.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include "namespace.h"
+#include "reentrant.h"
+#include "un-namespace.h"
+#include "netdb_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+#include "nss_tls.h"
+
+enum constants
+{
+ SETSERVENT = 1,
+ ENDSERVENT = 2,
+ SERVENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */
+ SERVENT_STORAGE_MAX = 1 << 20, /* 1 MByte */
+};
+
+struct servent_mdata
+{
+ enum nss_lookup_type how;
+ int compat_mode;
+};
+
+static const ns_src defaultsrc[] = {
+ { NSSRC_COMPAT, NS_SUCCESS },
+ { NULL, 0 }
+};
+
+static int servent_unpack(char *, struct servent *, char **, size_t, int *);
+
+/* files backend declarations */
+struct files_state
+{
+ FILE *fp;
+ int stayopen;
+
+ int compat_mode_active;
+};
+static void files_endstate(void *);
+NSS_TLS_HANDLING(files);
+
+static int files_servent(void *, void *, va_list);
+static int files_setservent(void *, void *, va_list);
+
+/* db backend declarations */
+struct db_state
+{
+ DB *db;
+ int stayopen;
+ int keynum;
+};
+static void db_endstate(void *);
+NSS_TLS_HANDLING(db);
+
+static int db_servent(void *, void *, va_list);
+static int db_setservent(void *, void *, va_list);
+
+#ifdef YP
+/* nis backend declarations */
+static int nis_servent(void *, void *, va_list);
+static int nis_setservent(void *, void *, va_list);
+
+struct nis_state
+{
+ int yp_stepping;
+ char yp_domain[MAXHOSTNAMELEN];
+ char *yp_key;
+ int yp_keylen;
+};
+static void nis_endstate(void *);
+NSS_TLS_HANDLING(nis);
+
+static int nis_servent(void *, void *, va_list);
+static int nis_setservent(void *, void *, va_list);
+#endif
+
+/* compat backend declarations */
+static int compat_setservent(void *, void *, va_list);
+
+/* get** wrappers for get**_r functions declarations */
+struct servent_state {
+ struct servent serv;
+ char *buffer;
+ size_t bufsize;
+};
+static void servent_endstate(void *);
+NSS_TLS_HANDLING(servent);
+
+struct key {
+ const char *proto;
+ union {
+ const char *name;
+ int port;
+ };
+};
+
+static int wrap_getservbyname_r(struct key, struct servent *, char *, size_t,
+ struct servent **);
+static int wrap_getservbyport_r(struct key, struct servent *, char *, size_t,
+ struct servent **);
+static int wrap_getservent_r(struct key, struct servent *, char *, size_t,
+ struct servent **);
+static struct servent *getserv(int (*fn)(struct key, struct servent *, char *,
+ size_t, struct servent **), struct key);
+
+#ifdef NS_CACHING
+static int serv_id_func(char *, size_t *, va_list, void *);
+static int serv_marshal_func(char *, size_t *, void *, va_list, void *);
+static int serv_unmarshal_func(char *, size_t, void *, va_list, void *);
+#endif
+
+static int
+servent_unpack(char *p, struct servent *serv, char **aliases,
+ size_t aliases_size, int *errnop)
+{
+ char *cp, **q, *endp;
+ long l;
+
+ if (*p == '#')
+ return -1;
+
+ memset(serv, 0, sizeof(struct servent));
+
+ cp = strpbrk(p, "#\n");
+ if (cp != NULL)
+ *cp = '\0';
+ serv->s_name = p;
+
+ p = strpbrk(p, " \t");
+ if (p == NULL)
+ return -1;
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+ p++;
+ cp = strpbrk(p, ",/");
+ if (cp == NULL)
+ return -1;
+
+ *cp++ = '\0';
+ l = strtol(p, &endp, 10);
+ if (endp == p || *endp != '\0' || l < 0 || l > USHRT_MAX)
+ return -1;
+ serv->s_port = htons((in_port_t)l);
+ serv->s_proto = cp;
+
+ q = serv->s_aliases = aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &aliases[aliases_size - 1]) {
+ *q++ = cp;
+ } else {
+ *q = NULL;
+ *errnop = ERANGE;
+ return -1;
+ }
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+
+ return 0;
+}
+
+static int
+parse_result(struct servent *serv, char *buffer, size_t bufsize,
+ char *resultbuf, size_t resultbuflen, int *errnop)
+{
+ char **aliases;
+ int aliases_size;
+
+ if (bufsize <= resultbuflen + _ALIGNBYTES + sizeof(char *)) {
+ *errnop = ERANGE;
+ return (NS_RETURN);
+ }
+ aliases = (char **)_ALIGN(&buffer[resultbuflen + 1]);
+ aliases_size = (buffer + bufsize - (char *)aliases) / sizeof(char *);
+ if (aliases_size < 1) {
+ *errnop = ERANGE;
+ return (NS_RETURN);
+ }
+
+ memcpy(buffer, resultbuf, resultbuflen);
+ buffer[resultbuflen] = '\0';
+
+ if (servent_unpack(buffer, serv, aliases, aliases_size, errnop) != 0)
+ return ((*errnop == 0) ? NS_NOTFOUND : NS_RETURN);
+ return (NS_SUCCESS);
+}
+
+/* files backend implementation */
+static void
+files_endstate(void *p)
+{
+ FILE * f;
+
+ if (p == NULL)
+ return;
+
+ f = ((struct files_state *)p)->fp;
+ if (f != NULL)
+ fclose(f);
+
+ free(p);
+}
+
+/*
+ * compat structures. compat and files sources functionalities are almost
+ * equal, so they all are managed by files_servent function
+ */
+static int
+files_servent(void *retval, void *mdata, va_list ap)
+{
+ static const ns_src compat_src[] = {
+#ifdef YP
+ { NSSRC_NIS, NS_SUCCESS },
+#endif
+ { NULL, 0 }
+ };
+ ns_dtab compat_dtab[] = {
+ { NSSRC_DB, db_servent,
+ (void *)((struct servent_mdata *)mdata)->how },
+#ifdef YP
+ { NSSRC_NIS, nis_servent,
+ (void *)((struct servent_mdata *)mdata)->how },
+#endif
+ { NULL, NULL, NULL }
+ };
+
+ struct files_state *st;
+ int rv;
+ int stayopen;
+
+ struct servent_mdata *serv_mdata;
+ char *name;
+ char *proto;
+ int port;
+
+ struct servent *serv;
+ char *buffer;
+ size_t bufsize;
+ int *errnop;
+
+ size_t linesize;
+ char *line;
+ char **cp;
+
+ name = NULL;
+ proto = NULL;
+ serv_mdata = (struct servent_mdata *)mdata;
+ switch (serv_mdata->how) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ port = va_arg(ap, int);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ return NS_NOTFOUND;
+ };
+
+ serv = va_arg(ap, struct servent *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap,int *);
+
+ *errnop = files_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+
+ if (st->fp == NULL)
+ st->compat_mode_active = 0;
+
+ if (st->fp == NULL && (st->fp = fopen(_PATH_SERVICES, "r")) == NULL) {
+ *errnop = errno;
+ return (NS_UNAVAIL);
+ }
+
+ if (serv_mdata->how == nss_lt_all)
+ stayopen = 1;
+ else {
+ rewind(st->fp);
+ stayopen = st->stayopen;
+ }
+
+ rv = NS_NOTFOUND;
+ do {
+ if (!st->compat_mode_active) {
+ if ((line = fgetln(st->fp, &linesize)) == NULL) {
+ *errnop = errno;
+ rv = NS_RETURN;
+ break;
+ }
+
+ if (*line=='+' && serv_mdata->compat_mode != 0)
+ st->compat_mode_active = 1;
+ }
+
+ if (st->compat_mode_active != 0) {
+ switch (serv_mdata->how) {
+ case nss_lt_name:
+ rv = nsdispatch(retval, compat_dtab,
+ NSDB_SERVICES_COMPAT, "getservbyname_r",
+ compat_src, name, proto, serv, buffer,
+ bufsize, errnop);
+ break;
+ case nss_lt_id:
+ rv = nsdispatch(retval, compat_dtab,
+ NSDB_SERVICES_COMPAT, "getservbyport_r",
+ compat_src, port, proto, serv, buffer,
+ bufsize, errnop);
+ break;
+ case nss_lt_all:
+ rv = nsdispatch(retval, compat_dtab,
+ NSDB_SERVICES_COMPAT, "getservent_r",
+ compat_src, serv, buffer, bufsize, errnop);
+ break;
+ }
+
+ if (!(rv & NS_TERMINATE) ||
+ serv_mdata->how != nss_lt_all)
+ st->compat_mode_active = 0;
+
+ continue;
+ }
+
+ rv = parse_result(serv, buffer, bufsize, line, linesize,
+ errnop);
+ if (rv == NS_NOTFOUND)
+ continue;
+ if (rv == NS_RETURN)
+ break;
+
+ rv = NS_NOTFOUND;
+ switch (serv_mdata->how) {
+ case nss_lt_name:
+ if (strcmp(name, serv->s_name) == 0)
+ goto gotname;
+ for (cp = serv->s_aliases; *cp; cp++)
+ if (strcmp(name, *cp) == 0)
+ goto gotname;
+
+ continue;
+ gotname:
+ if (proto == 0 || strcmp(serv->s_proto, proto) == 0)
+ rv = NS_SUCCESS;
+ break;
+ case nss_lt_id:
+ if (port != serv->s_port)
+ continue;
+
+ if (proto == 0 || strcmp(serv->s_proto, proto) == 0)
+ rv = NS_SUCCESS;
+ break;
+ case nss_lt_all:
+ rv = NS_SUCCESS;
+ break;
+ }
+
+ } while (!(rv & NS_TERMINATE));
+
+ if (!stayopen && st->fp != NULL) {
+ fclose(st->fp);
+ st->fp = NULL;
+ }
+
+ if ((rv == NS_SUCCESS) && (retval != NULL))
+ *(struct servent **)retval=serv;
+
+ return (rv);
+}
+
+static int
+files_setservent(void *retval, void *mdata, va_list ap)
+{
+ struct files_state *st;
+ int rv;
+ int f;
+
+ rv = files_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+
+ switch ((enum constants)mdata) {
+ case SETSERVENT:
+ f = va_arg(ap,int);
+ if (st->fp == NULL)
+ st->fp = fopen(_PATH_SERVICES, "r");
+ else
+ rewind(st->fp);
+ st->stayopen |= f;
+ break;
+ case ENDSERVENT:
+ if (st->fp != NULL) {
+ fclose(st->fp);
+ st->fp = NULL;
+ }
+ st->stayopen = 0;
+ break;
+ default:
+ break;
+ };
+
+ st->compat_mode_active = 0;
+ return (NS_UNAVAIL);
+}
+
+/* db backend implementation */
+static void
+db_endstate(void *p)
+{
+ DB *db;
+
+ if (p == NULL)
+ return;
+
+ db = ((struct db_state *)p)->db;
+ if (db != NULL)
+ db->close(db);
+
+ free(p);
+}
+
+static int
+db_servent(void *retval, void *mdata, va_list ap)
+{
+ char buf[BUFSIZ];
+ DBT key, data, *result;
+ DB *db;
+
+ struct db_state *st;
+ int rv;
+ int stayopen;
+
+ enum nss_lookup_type how;
+ char *name;
+ char *proto;
+ int port;
+
+ struct servent *serv;
+ char *buffer;
+ size_t bufsize;
+ int *errnop;
+
+ name = NULL;
+ proto = NULL;
+ how = (enum nss_lookup_type)mdata;
+ switch (how) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ port = va_arg(ap, int);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ return NS_NOTFOUND;
+ };
+
+ serv = va_arg(ap, struct servent *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap,int *);
+
+ *errnop = db_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+
+ if (how == nss_lt_all && st->keynum < 0)
+ return (NS_NOTFOUND);
+
+ if (st->db == NULL) {
+ st->db = dbopen(_PATH_SERVICES_DB, O_RDONLY, 0, DB_HASH, NULL);
+ if (st->db == NULL) {
+ *errnop = errno;
+ return (NS_UNAVAIL);
+ }
+ }
+
+ stayopen = (how == nss_lt_all) ? 1 : st->stayopen;
+ db = st->db;
+
+ do {
+ switch (how) {
+ case nss_lt_name:
+ key.data = buf;
+ if (proto == NULL)
+ key.size = snprintf(buf, sizeof(buf),
+ "\376%s", name);
+ else
+ key.size = snprintf(buf, sizeof(buf),
+ "\376%s/%s", name, proto);
+ key.size++;
+ if (db->get(db, &key, &data, 0) != 0 ||
+ db->get(db, &data, &key, 0) != 0) {
+ rv = NS_NOTFOUND;
+ goto db_fin;
+ }
+ result = &key;
+ break;
+ case nss_lt_id:
+ key.data = buf;
+ port = htons(port);
+ if (proto == NULL)
+ key.size = snprintf(buf, sizeof(buf),
+ "\377%d", port);
+ else
+ key.size = snprintf(buf, sizeof(buf),
+ "\377%d/%s", port, proto);
+ key.size++;
+ if (db->get(db, &key, &data, 0) != 0 ||
+ db->get(db, &data, &key, 0) != 0) {
+ rv = NS_NOTFOUND;
+ goto db_fin;
+ }
+ result = &key;
+ break;
+ case nss_lt_all:
+ key.data = buf;
+ key.size = snprintf(buf, sizeof(buf), "%d",
+ st->keynum++);
+ key.size++;
+ if (db->get(db, &key, &data, 0) != 0) {
+ st->keynum = -1;
+ rv = NS_NOTFOUND;
+ goto db_fin;
+ }
+ result = &data;
+ break;
+ }
+
+ rv = parse_result(serv, buffer, bufsize, result->data,
+ result->size - 1, errnop);
+
+ } while (!(rv & NS_TERMINATE) && how == nss_lt_all);
+
+db_fin:
+ if (!stayopen && st->db != NULL) {
+ db->close(db);
+ st->db = NULL;
+ }
+
+ if (rv == NS_SUCCESS && retval != NULL)
+ *(struct servent **)retval = serv;
+
+ return (rv);
+}
+
+static int
+db_setservent(void *retval, void *mdata, va_list ap)
+{
+ DB *db;
+ struct db_state *st;
+ int rv;
+ int f;
+
+ rv = db_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+
+ switch ((enum constants)mdata) {
+ case SETSERVENT:
+ f = va_arg(ap, int);
+ st->stayopen |= f;
+ st->keynum = 0;
+ break;
+ case ENDSERVENT:
+ db = st->db;
+ if (db != NULL) {
+ db->close(db);
+ st->db = NULL;
+ }
+ st->stayopen = 0;
+ break;
+ default:
+ break;
+ };
+
+ return (NS_UNAVAIL);
+}
+
+/* nis backend implementation */
+#ifdef YP
+static void
+nis_endstate(void *p)
+{
+ if (p == NULL)
+ return;
+
+ free(((struct nis_state *)p)->yp_key);
+ free(p);
+}
+
+static int
+nis_servent(void *retval, void *mdata, va_list ap)
+{
+ char *resultbuf, *lastkey;
+ int resultbuflen;
+ char buf[YPMAXRECORD + 2];
+
+ struct nis_state *st;
+ int rv;
+
+ enum nss_lookup_type how;
+ char *name;
+ char *proto;
+ int port;
+
+ struct servent *serv;
+ char *buffer;
+ size_t bufsize;
+ int *errnop;
+
+ name = NULL;
+ proto = NULL;
+ how = (enum nss_lookup_type)mdata;
+ switch (how) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ port = va_arg(ap, int);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ return NS_NOTFOUND;
+ };
+
+ serv = va_arg(ap, struct servent *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+
+ *errnop = nis_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+
+ if (st->yp_domain[0] == '\0') {
+ if (getdomainname(st->yp_domain, sizeof st->yp_domain)) {
+ *errnop = errno;
+ return (NS_UNAVAIL);
+ }
+ }
+
+ do {
+ switch (how) {
+ case nss_lt_name:
+ snprintf(buf, sizeof(buf), "%s/%s", name, proto);
+ if (yp_match(st->yp_domain, "services.byname", buf,
+ strlen(buf), &resultbuf, &resultbuflen)) {
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ break;
+ case nss_lt_id:
+ snprintf(buf, sizeof(buf), "%d/%s", ntohs(port),
+ proto);
+
+ /*
+ * We have to be a little flexible
+ * here. Ideally you're supposed to have both
+ * a services.byname and a services.byport
+ * map, but some systems have only
+ * services.byname. FreeBSD cheats a little by
+ * putting the services.byport information in
+ * the same map as services.byname so that
+ * either case will work. We allow for both
+ * possibilities here: if there is no
+ * services.byport map, we try services.byname
+ * instead.
+ */
+ rv = yp_match(st->yp_domain, "services.byport", buf,
+ strlen(buf), &resultbuf, &resultbuflen);
+ if (rv) {
+ if (rv == YPERR_MAP) {
+ if (yp_match(st->yp_domain,
+ "services.byname", buf,
+ strlen(buf), &resultbuf,
+ &resultbuflen)) {
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ } else {
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ }
+
+ break;
+ case nss_lt_all:
+ if (!st->yp_stepping) {
+ free(st->yp_key);
+ rv = yp_first(st->yp_domain, "services.byname",
+ &st->yp_key, &st->yp_keylen, &resultbuf,
+ &resultbuflen);
+ if (rv) {
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ st->yp_stepping = 1;
+ } else {
+ lastkey = st->yp_key;
+ rv = yp_next(st->yp_domain, "services.byname",
+ st->yp_key, st->yp_keylen, &st->yp_key,
+ &st->yp_keylen, &resultbuf, &resultbuflen);
+ free(lastkey);
+ if (rv) {
+ st->yp_stepping = 0;
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ }
+ break;
+ };
+
+ rv = parse_result(serv, buffer, bufsize, resultbuf,
+ resultbuflen, errnop);
+ free(resultbuf);
+
+ } while (!(rv & NS_TERMINATE) && how == nss_lt_all);
+
+fin:
+ if (rv == NS_SUCCESS && retval != NULL)
+ *(struct servent **)retval = serv;
+
+ return (rv);
+}
+
+static int
+nis_setservent(void *result, void *mdata, va_list ap)
+{
+ struct nis_state *st;
+ int rv;
+
+ rv = nis_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+
+ switch ((enum constants)mdata) {
+ case SETSERVENT:
+ case ENDSERVENT:
+ free(st->yp_key);
+ st->yp_key = NULL;
+ st->yp_stepping = 0;
+ break;
+ default:
+ break;
+ };
+
+ return (NS_UNAVAIL);
+}
+#endif
+
+/* compat backend implementation */
+static int
+compat_setservent(void *retval, void *mdata, va_list ap)
+{
+ static const ns_src compat_src[] = {
+#ifdef YP
+ { NSSRC_NIS, NS_SUCCESS },
+#endif
+ { NULL, 0 }
+ };
+ ns_dtab compat_dtab[] = {
+ { NSSRC_DB, db_setservent, mdata },
+#ifdef YP
+ { NSSRC_NIS, nis_setservent, mdata },
+#endif
+ { NULL, NULL, NULL }
+ };
+ int f;
+
+ (void)files_setservent(retval, mdata, ap);
+
+ switch ((enum constants)mdata) {
+ case SETSERVENT:
+ f = va_arg(ap,int);
+ (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT,
+ "setservent", compat_src, f);
+ break;
+ case ENDSERVENT:
+ (void)nsdispatch(retval, compat_dtab, NSDB_SERVICES_COMPAT,
+ "endservent", compat_src);
+ break;
+ default:
+ break;
+ }
+
+ return (NS_UNAVAIL);
+}
+
+#ifdef NS_CACHING
+static int
+serv_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
+{
+ char *name;
+ char *proto;
+ int port;
+
+ size_t desired_size, size, size2;
+ enum nss_lookup_type lookup_type;
+ int res = NS_UNAVAIL;
+
+ lookup_type = (enum nss_lookup_type)cache_mdata;
+ switch (lookup_type) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ proto = va_arg(ap, char *);
+
+ size = strlen(name);
+ desired_size = sizeof(enum nss_lookup_type) + size + 1;
+ if (proto != NULL) {
+ size2 = strlen(proto);
+ desired_size += size2 + 1;
+ } else
+ size2 = 0;
+
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
+
+ if (proto != NULL)
+ memcpy(buffer + sizeof(enum nss_lookup_type) + size + 1,
+ proto, size2 + 1);
+
+ res = NS_SUCCESS;
+ break;
+ case nss_lt_id:
+ port = va_arg(ap, int);
+ proto = va_arg(ap, char *);
+
+ desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
+ if (proto != NULL) {
+ size = strlen(proto);
+ desired_size += size + 1;
+ } else
+ size = 0;
+
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), &port,
+ sizeof(int));
+
+ if (proto != NULL)
+ memcpy(buffer + sizeof(enum nss_lookup_type) +
+ sizeof(int), proto, size + 1);
+
+ res = NS_SUCCESS;
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+fin:
+ *buffer_size = desired_size;
+ return (res);
+}
+
+int
+serv_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ char *proto;
+ int port;
+ struct servent *serv;
+ char *orig_buf;
+ size_t orig_buf_size;
+
+ struct servent new_serv;
+ size_t desired_size;
+ char **alias;
+ char *p;
+ size_t size;
+ size_t aliases_size;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ port = va_arg(ap, int);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ serv = va_arg(ap, struct servent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+
+ desired_size = _ALIGNBYTES + sizeof(struct servent) + sizeof(char *);
+ if (serv->s_name != NULL)
+ desired_size += strlen(serv->s_name) + 1;
+ if (serv->s_proto != NULL)
+ desired_size += strlen(serv->s_proto) + 1;
+
+ aliases_size = 0;
+ if (serv->s_aliases != NULL) {
+ for (alias = serv->s_aliases; *alias; ++alias) {
+ desired_size += strlen(*alias) + 1;
+ ++aliases_size;
+ }
+
+ desired_size += _ALIGNBYTES +
+ sizeof(char *) * (aliases_size + 1);
+ }
+
+ if (*buffer_size < desired_size) {
+ /* this assignment is here for future use */
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ memcpy(&new_serv, serv, sizeof(struct servent));
+ memset(buffer, 0, desired_size);
+
+ *buffer_size = desired_size;
+ p = buffer + sizeof(struct servent) + sizeof(char *);
+ memcpy(buffer + sizeof(struct servent), &p, sizeof(char *));
+ p = (char *)_ALIGN(p);
+
+ if (new_serv.s_name != NULL) {
+ size = strlen(new_serv.s_name);
+ memcpy(p, new_serv.s_name, size);
+ new_serv.s_name = p;
+ p += size + 1;
+ }
+
+ if (new_serv.s_proto != NULL) {
+ size = strlen(new_serv.s_proto);
+ memcpy(p, new_serv.s_proto, size);
+ new_serv.s_proto = p;
+ p += size + 1;
+ }
+
+ if (new_serv.s_aliases != NULL) {
+ p = (char *)_ALIGN(p);
+ memcpy(p, new_serv.s_aliases, sizeof(char *) * aliases_size);
+ new_serv.s_aliases = (char **)p;
+ p += sizeof(char *) * (aliases_size + 1);
+
+ for (alias = new_serv.s_aliases; *alias; ++alias) {
+ size = strlen(*alias);
+ memcpy(p, *alias, size);
+ *alias = p;
+ p += size + 1;
+ }
+ }
+
+ memcpy(buffer, &new_serv, sizeof(struct servent));
+ return (NS_SUCCESS);
+}
+
+int
+serv_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ char *proto;
+ int port;
+ struct servent *serv;
+ char *orig_buf;
+ char *p;
+ char **alias;
+ size_t orig_buf_size;
+ int *ret_errno;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ port = va_arg(ap, int);
+ proto = va_arg(ap, char *);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ serv = va_arg(ap, struct servent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+ ret_errno = va_arg(ap, int *);
+
+ if (orig_buf_size <
+ buffer_size - sizeof(struct servent) - sizeof(char *)) {
+ *ret_errno = ERANGE;
+ return (NS_RETURN);
+ }
+
+ memcpy(serv, buffer, sizeof(struct servent));
+ memcpy(&p, buffer + sizeof(struct servent), sizeof(char *));
+
+ orig_buf = (char *)_ALIGN(orig_buf);
+ memcpy(orig_buf, buffer + sizeof(struct servent) + sizeof(char *) +
+ (_ALIGN(p) - (size_t)p),
+ buffer_size - sizeof(struct servent) - sizeof(char *) -
+ (_ALIGN(p) - (size_t)p));
+ p = (char *)_ALIGN(p);
+
+ NS_APPLY_OFFSET(serv->s_name, orig_buf, p, char *);
+ NS_APPLY_OFFSET(serv->s_proto, orig_buf, p, char *);
+ if (serv->s_aliases != NULL) {
+ NS_APPLY_OFFSET(serv->s_aliases, orig_buf, p, char **);
+
+ for (alias = serv->s_aliases; *alias; ++alias)
+ NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
+ }
+
+ if (retval != NULL)
+ *((struct servent **)retval) = serv;
+ return (NS_SUCCESS);
+}
+
+NSS_MP_CACHE_HANDLING(services);
+#endif /* NS_CACHING */
+
+/* get**_r functions implementation */
+int
+getservbyname_r(const char *name, const char *proto, struct servent *serv,
+ char *buffer, size_t bufsize, struct servent **result)
+{
+ static const struct servent_mdata mdata = { nss_lt_name, 0 };
+ static const struct servent_mdata compat_mdata = { nss_lt_name, 1 };
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ services, (void *)nss_lt_name,
+ serv_id_func, serv_marshal_func, serv_unmarshal_func);
+#endif /* NS_CACHING */
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_servent, (void *)&mdata },
+ { NSSRC_DB, db_servent, (void *)nss_lt_name },
+#ifdef YP
+ { NSSRC_NIS, nis_servent, (void *)nss_lt_name },
+#endif
+ { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyname_r",
+ defaultsrc, name, proto, serv, buffer, bufsize, &ret_errno);
+
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+int
+getservbyport_r(int port, const char *proto, struct servent *serv,
+ char *buffer, size_t bufsize, struct servent **result)
+{
+ static const struct servent_mdata mdata = { nss_lt_id, 0 };
+ static const struct servent_mdata compat_mdata = { nss_lt_id, 1 };
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ services, (void *)nss_lt_id,
+ serv_id_func, serv_marshal_func, serv_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_servent, (void *)&mdata },
+ { NSSRC_DB, db_servent, (void *)nss_lt_id },
+#ifdef YP
+ { NSSRC_NIS, nis_servent, (void *)nss_lt_id },
+#endif
+ { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservbyport_r",
+ defaultsrc, port, proto, serv, buffer, bufsize, &ret_errno);
+
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+int
+getservent_r(struct servent *serv, char *buffer, size_t bufsize,
+ struct servent **result)
+{
+ static const struct servent_mdata mdata = { nss_lt_all, 0 };
+ static const struct servent_mdata compat_mdata = { nss_lt_all, 1 };
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ services, (void *)nss_lt_all,
+ serv_marshal_func, serv_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_servent, (void *)&mdata },
+ { NSSRC_DB, db_servent, (void *)nss_lt_all },
+#ifdef YP
+ { NSSRC_NIS, nis_servent, (void *)nss_lt_all },
+#endif
+ { NSSRC_COMPAT, files_servent, (void *)&compat_mdata },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_SERVICES, "getservent_r",
+ defaultsrc, serv, buffer, bufsize, &ret_errno);
+
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+void
+setservent(int stayopen)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ services, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_setservent, (void *)SETSERVENT },
+ { NSSRC_DB, db_setservent, (void *)SETSERVENT },
+#ifdef YP
+ { NSSRC_NIS, nis_setservent, (void *)SETSERVENT },
+#endif
+ { NSSRC_COMPAT, compat_setservent, (void *)SETSERVENT },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+
+ (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "setservent", defaultsrc,
+ stayopen);
+}
+
+void
+endservent()
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ services, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_setservent, (void *)ENDSERVENT },
+ { NSSRC_DB, db_setservent, (void *)ENDSERVENT },
+#ifdef YP
+ { NSSRC_NIS, nis_setservent, (void *)ENDSERVENT },
+#endif
+ { NSSRC_COMPAT, compat_setservent, (void *)ENDSERVENT },
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+
+ (void)nsdispatch(NULL, dtab, NSDB_SERVICES, "endservent", defaultsrc);
+}
+
+/* get** wrappers for get**_r functions implementation */
+static void
+servent_endstate(void *p)
+{
+ if (p == NULL)
+ return;
+
+ free(((struct servent_state *)p)->buffer);
+ free(p);
+}
+
+static int
+wrap_getservbyname_r(struct key key, struct servent *serv, char *buffer,
+ size_t bufsize, struct servent **res)
+{
+ return (getservbyname_r(key.name, key.proto, serv, buffer, bufsize,
+ res));
+}
+
+static int
+wrap_getservbyport_r(struct key key, struct servent *serv, char *buffer,
+ size_t bufsize, struct servent **res)
+{
+ return (getservbyport_r(key.port, key.proto, serv, buffer, bufsize,
+ res));
+}
+
+static int
+wrap_getservent_r(struct key key, struct servent *serv, char *buffer,
+ size_t bufsize, struct servent **res)
+{
+ return (getservent_r(serv, buffer, bufsize, res));
+}
+
+static struct servent *
+getserv(int (*fn)(struct key, struct servent *, char *, size_t,
+ struct servent **), struct key key)
+{
+ int rv;
+ struct servent *res;
+ struct servent_state * st;
+
+ rv = servent_getstate(&st);
+ if (rv != 0) {
+ errno = rv;
+ return NULL;
+ }
+
+ if (st->buffer == NULL) {
+ st->buffer = malloc(SERVENT_STORAGE_INITIAL);
+ if (st->buffer == NULL)
+ return (NULL);
+ st->bufsize = SERVENT_STORAGE_INITIAL;
+ }
+ do {
+ rv = fn(key, &st->serv, st->buffer, st->bufsize, &res);
+ if (res == NULL && rv == ERANGE) {
+ free(st->buffer);
+ if ((st->bufsize << 1) > SERVENT_STORAGE_MAX) {
+ st->buffer = NULL;
+ errno = ERANGE;
+ return (NULL);
+ }
+ st->bufsize <<= 1;
+ st->buffer = malloc(st->bufsize);
+ if (st->buffer == NULL)
+ return (NULL);
+ }
+ } while (res == NULL && rv == ERANGE);
+ if (rv != 0)
+ errno = rv;
+
+ return (res);
+}
+
+struct servent *
+getservbyname(const char *name, const char *proto)
+{
+ struct key key;
+
+ key.name = name;
+ key.proto = proto;
+
+ return (getserv(wrap_getservbyname_r, key));
+}
+
+struct servent *
+getservbyport(int port, const char *proto)
+{
+ struct key key;
+
+ key.port = port;
+ key.proto = proto;
+
+ return (getserv(wrap_getservbyport_r, key));
+}
+
+struct servent *
+getservent()
+{
+ struct key key;
+
+ key.proto = NULL;
+ key.port = 0;
+
+ return (getserv(wrap_getservent_r, key));
+}
diff --git a/lib/libc/net/hesiod.3 b/lib/libc/net/hesiod.3
new file mode 100644
index 0000000..bae4e44
--- /dev/null
+++ b/lib/libc/net/hesiod.3
@@ -0,0 +1,176 @@
+.\" $NetBSD: hesiod.3,v 1.1 1999/01/25 03:43:04 lukem Exp $
+.\"
+.\" from: #Id: hesiod.3,v 1.9.2.1 1997/01/03 21:02:23 ghudson Exp #
+.\"
+.\" Copyright 1988, 1996 by the Massachusetts Institute of Technology.
+.\"
+.\" Permission to use, copy, modify, and distribute this
+.\" software and its documentation for any purpose and without
+.\" fee is hereby granted, provided that the above copyright
+.\" notice appear in all copies and that both that copyright
+.\" notice and this permission notice appear in supporting
+.\" documentation, and that the name of M.I.T. not be used in
+.\" advertising or publicity pertaining to distribution of the
+.\" software without specific, written prior permission.
+.\" M.I.T. makes no representations about the suitability of
+.\" this software for any purpose. It is provided "as is"
+.\" without express or implied warranty.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 30, 1996
+.Dt HESIOD 3
+.Os
+.Sh NAME
+.Nm hesiod ,
+.Nm hesiod_init ,
+.Nm hesiod_resolve ,
+.Nm hesiod_free_list ,
+.Nm hesiod_to_bind ,
+.Nm hesiod_end
+.Nd Hesiod name server interface library
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In hesiod.h
+.Ft int
+.Fn hesiod_init "void **context"
+.Ft char **
+.Fn hesiod_resolve "void *context" "const char *name" "const char *type"
+.Ft void
+.Fn hesiod_free_list "void *context" "char **list"
+.Ft char *
+.Fn hesiod_to_bind "void *context" "const char *name" "const char *type"
+.Ft void
+.Fn hesiod_end "void *context"
+.Sh DESCRIPTION
+This family of functions allows you to perform lookups of Hesiod
+information, which is stored as text records in the Domain Name
+Service.
+To perform lookups, you must first initialize a
+.Fa context ,
+an opaque object which stores information used internally by the
+library between calls.
+The
+.Fn hesiod_init
+function
+initializes a context, storing a pointer to the context in the
+location pointed to by the
+.Fa context
+argument.
+The
+.Fn hesiod_end
+function
+frees the resources used by a context.
+.Pp
+The
+.Fn hesiod_resolve
+function
+is the primary interface to the library.
+If successful, it returns a
+list of one or more strings giving the records matching
+.Fa name
+and
+.Fa type .
+The last element of the list is followed by a
+.Dv NULL
+pointer.
+It is the
+caller's responsibility to call
+.Fn hesiod_free_list
+to free the resources used by the returned list.
+.Pp
+The
+.Fn hesiod_to_bind
+function
+converts
+.Fa name
+and
+.Fa type
+into the DNS name used by
+.Fn hesiod_resolve .
+It is the caller's responsibility to free the returned string using
+.Fn free .
+.Sh RETURN VALUES
+.Rv -std hesiod_init
+On failure,
+.Fn hesiod_resolve
+and
+.Fn hesiod_to_bind
+return
+.Dv NULL
+and set the global variable
+.Va errno
+to indicate the error.
+.Sh ENVIRONMENT
+.Bl -tag -width HESIOD_CONFIG
+.It Ev HES_DOMAIN
+If the environment variable
+.Ev HES_DOMAIN
+is set, it will override the domain in the Hesiod configuration file.
+.It Ev HESIOD_CONFIG
+If the environment variable
+.Ev HESIOD_CONFIG
+is set, it specifies the location of the Hesiod configuration file.
+.El
+.Sh ERRORS
+Hesiod calls may fail because of:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+Insufficient memory was available to carry out the requested
+operation.
+.It Bq Er ENOEXEC
+The
+.Fn hesiod_init
+function
+failed because the Hesiod configuration file was invalid.
+.It Bq Er ECONNREFUSED
+The
+.Fn hesiod_resolve
+function
+failed because no name server could be contacted to answer the query.
+.It Bq Er EMSGSIZE
+The
+.Fn hesiod_resolve
+or
+.Fn hesiod_to_bind
+function
+failed because the query or response was too big to fit into the
+packet buffers.
+.It Bq Er ENOENT
+The
+.Fn hesiod_resolve
+function
+failed because the name server had no text records matching
+.Fa name
+and
+.Fa type ,
+or
+.Fn hesiod_to_bind
+failed because the
+.Fa name
+argument had a domain extension which could not be resolved with type
+.Dq rhs\-extension
+in the local Hesiod domain.
+.El
+.Sh SEE ALSO
+.Xr hesiod.conf 5 ,
+.Xr named 8
+.Rs
+.%T "Hesiod - Project Athena Technical Plan -- Name Service"
+.Re
+.Sh AUTHORS
+.An Steve Dyer ,
+IBM/Project Athena
+.An Greg Hudson ,
+MIT Team Athena
+.Pp
+Copyright 1987, 1988, 1995, 1996 by the Massachusetts Institute of Technology.
+.Sh BUGS
+The strings corresponding to the
+.Va errno
+values set by the Hesiod functions are not particularly indicative of
+what went wrong, especially for
+.Er ENOEXEC
+and
+.Er ENOENT .
diff --git a/lib/libc/net/hesiod.c b/lib/libc/net/hesiod.c
new file mode 100644
index 0000000..2413727
--- /dev/null
+++ b/lib/libc/net/hesiod.c
@@ -0,0 +1,584 @@
+/* $NetBSD: hesiod.c,v 1.9 1999/02/11 06:16:38 simonb Exp $ */
+
+/* Copyright (c) 1996 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
+ * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
+ * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/* Copyright 1996 by the Massachusetts Institute of Technology.
+ *
+ * Permission to use, copy, modify, and distribute this
+ * software and its documentation for any purpose and without
+ * fee is hereby granted, provided that the above copyright
+ * notice appear in all copies and that both that copyright
+ * notice and this permission notice appear in supporting
+ * documentation, and that the name of M.I.T. not be used in
+ * advertising or publicity pertaining to distribution of the
+ * software without specific, written prior permission.
+ * M.I.T. makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is"
+ * without express or implied warranty.
+ */
+
+/* This file is part of the hesiod library. It implements the core
+ * portion of the hesiod resolver.
+ *
+ * This file is loosely based on an interim version of hesiod.c from
+ * the BIND IRS library, which was in turn based on an earlier version
+ * of this file. Extensive changes have been made on each step of the
+ * path.
+ *
+ * This implementation is not truly thread-safe at the moment because
+ * it uses res_send() and accesses _res.
+ */
+
+#include <sys/cdefs.h>
+
+#if 0
+static char *orig_rcsid = "$NetBSD: hesiod.c,v 1.9 1999/02/11 06:16:38 simonb Exp $";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <hesiod.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+struct hesiod_p {
+ char *lhs; /* normally ".ns" */
+ char *rhs; /* AKA the default hesiod domain */
+ int classes[2]; /* The class search order. */
+};
+
+#define MAX_HESRESP 1024
+
+static int read_config_file(struct hesiod_p *, const char *);
+static char **get_txt_records(int, const char *);
+static int init_context(void);
+static void translate_errors(void);
+
+
+/*
+ * hesiod_init --
+ * initialize a hesiod_p.
+ */
+int
+hesiod_init(context)
+ void **context;
+{
+ struct hesiod_p *ctx;
+ const char *p, *configname;
+
+ ctx = malloc(sizeof(struct hesiod_p));
+ if (ctx) {
+ *context = ctx;
+ if (!issetugid())
+ configname = getenv("HESIOD_CONFIG");
+ else
+ configname = NULL;
+ if (!configname)
+ configname = _PATH_HESIOD_CONF;
+ if (read_config_file(ctx, configname) >= 0) {
+ /*
+ * The default rhs can be overridden by an
+ * environment variable.
+ */
+ if (!issetugid())
+ p = getenv("HES_DOMAIN");
+ else
+ p = NULL;
+ if (p) {
+ if (ctx->rhs)
+ free(ctx->rhs);
+ ctx->rhs = malloc(strlen(p) + 2);
+ if (ctx->rhs) {
+ *ctx->rhs = '.';
+ strcpy(ctx->rhs + 1,
+ (*p == '.') ? p + 1 : p);
+ return 0;
+ } else
+ errno = ENOMEM;
+ } else
+ return 0;
+ }
+ } else
+ errno = ENOMEM;
+
+ if (ctx->lhs)
+ free(ctx->lhs);
+ if (ctx->rhs)
+ free(ctx->rhs);
+ if (ctx)
+ free(ctx);
+ return -1;
+}
+
+/*
+ * hesiod_end --
+ * Deallocates the hesiod_p.
+ */
+void
+hesiod_end(context)
+ void *context;
+{
+ struct hesiod_p *ctx = (struct hesiod_p *) context;
+
+ free(ctx->rhs);
+ if (ctx->lhs)
+ free(ctx->lhs);
+ free(ctx);
+}
+
+/*
+ * hesiod_to_bind --
+ * takes a hesiod (name, type) and returns a DNS
+ * name which is to be resolved.
+ */
+char *
+hesiod_to_bind(void *context, const char *name, const char *type)
+{
+ struct hesiod_p *ctx = (struct hesiod_p *) context;
+ char bindname[MAXDNAME], *p, *ret, **rhs_list = NULL;
+ const char *rhs;
+ int len;
+
+ if (strlcpy(bindname, name, sizeof(bindname)) >= sizeof(bindname)) {
+ errno = EMSGSIZE;
+ return NULL;
+ }
+
+ /*
+ * Find the right right hand side to use, possibly
+ * truncating bindname.
+ */
+ p = strchr(bindname, '@');
+ if (p) {
+ *p++ = 0;
+ if (strchr(p, '.'))
+ rhs = name + (p - bindname);
+ else {
+ rhs_list = hesiod_resolve(context, p, "rhs-extension");
+ if (rhs_list)
+ rhs = *rhs_list;
+ else {
+ errno = ENOENT;
+ return NULL;
+ }
+ }
+ } else
+ rhs = ctx->rhs;
+
+ /* See if we have enough room. */
+ len = strlen(bindname) + 1 + strlen(type);
+ if (ctx->lhs)
+ len += strlen(ctx->lhs) + ((ctx->lhs[0] != '.') ? 1 : 0);
+ len += strlen(rhs) + ((rhs[0] != '.') ? 1 : 0);
+ if (len > sizeof(bindname) - 1) {
+ if (rhs_list)
+ hesiod_free_list(context, rhs_list);
+ errno = EMSGSIZE;
+ return NULL;
+ }
+ /* Put together the rest of the domain. */
+ strcat(bindname, ".");
+ strcat(bindname, type);
+ /* Only append lhs if it isn't empty. */
+ if (ctx->lhs && ctx->lhs[0] != '\0' ) {
+ if (ctx->lhs[0] != '.')
+ strcat(bindname, ".");
+ strcat(bindname, ctx->lhs);
+ }
+ if (rhs[0] != '.')
+ strcat(bindname, ".");
+ strcat(bindname, rhs);
+
+ /* rhs_list is no longer needed, since we're done with rhs. */
+ if (rhs_list)
+ hesiod_free_list(context, rhs_list);
+
+ /* Make a copy of the result and return it to the caller. */
+ ret = strdup(bindname);
+ if (!ret)
+ errno = ENOMEM;
+ return ret;
+}
+
+/*
+ * hesiod_resolve --
+ * Given a hesiod name and type, return an array of strings returned
+ * by the resolver.
+ */
+char **
+hesiod_resolve(context, name, type)
+ void *context;
+ const char *name;
+ const char *type;
+{
+ struct hesiod_p *ctx = (struct hesiod_p *) context;
+ char *bindname, **retvec;
+
+ bindname = hesiod_to_bind(context, name, type);
+ if (!bindname)
+ return NULL;
+
+ retvec = get_txt_records(ctx->classes[0], bindname);
+ if (retvec == NULL && errno == ENOENT && ctx->classes[1])
+ retvec = get_txt_records(ctx->classes[1], bindname);
+
+ free(bindname);
+ return retvec;
+}
+
+/*ARGSUSED*/
+void
+hesiod_free_list(context, list)
+ void *context;
+ char **list;
+{
+ char **p;
+
+ if (list == NULL)
+ return;
+ for (p = list; *p; p++)
+ free(*p);
+ free(list);
+}
+
+
+/* read_config_file --
+ * Parse the /etc/hesiod.conf file. Returns 0 on success,
+ * -1 on failure. On failure, it might leave values in ctx->lhs
+ * or ctx->rhs which need to be freed by the caller.
+ */
+static int
+read_config_file(ctx, filename)
+ struct hesiod_p *ctx;
+ const char *filename;
+{
+ char *key, *data, *p, **which;
+ char buf[MAXDNAME + 7];
+ int n;
+ FILE *fp;
+
+ /* Set default query classes. */
+ ctx->classes[0] = C_IN;
+ ctx->classes[1] = C_HS;
+
+ /* Try to open the configuration file. */
+ fp = fopen(filename, "r");
+ if (!fp) {
+ /* Use compiled in default domain names. */
+ ctx->lhs = strdup(DEF_LHS);
+ ctx->rhs = strdup(DEF_RHS);
+ if (ctx->lhs && ctx->rhs)
+ return 0;
+ else {
+ errno = ENOMEM;
+ return -1;
+ }
+ }
+ ctx->lhs = NULL;
+ ctx->rhs = NULL;
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ p = buf;
+ if (*p == '#' || *p == '\n' || *p == '\r')
+ continue;
+ while (*p == ' ' || *p == '\t')
+ p++;
+ key = p;
+ while (*p != ' ' && *p != '\t' && *p != '=')
+ p++;
+ *p++ = 0;
+
+ while (isspace(*p) || *p == '=')
+ p++;
+ data = p;
+ while (!isspace(*p))
+ p++;
+ *p = 0;
+
+ if (strcasecmp(key, "lhs") == 0 ||
+ strcasecmp(key, "rhs") == 0) {
+ which = (strcasecmp(key, "lhs") == 0)
+ ? &ctx->lhs : &ctx->rhs;
+ *which = strdup(data);
+ if (!*which) {
+ fclose(fp);
+ errno = ENOMEM;
+ return -1;
+ }
+ } else {
+ if (strcasecmp(key, "classes") == 0) {
+ n = 0;
+ while (*data && n < 2) {
+ p = data;
+ while (*p && *p != ',')
+ p++;
+ if (*p)
+ *p++ = 0;
+ if (strcasecmp(data, "IN") == 0)
+ ctx->classes[n++] = C_IN;
+ else
+ if (strcasecmp(data, "HS") == 0)
+ ctx->classes[n++] =
+ C_HS;
+ data = p;
+ }
+ while (n < 2)
+ ctx->classes[n++] = 0;
+ }
+ }
+ }
+ fclose(fp);
+
+ if (!ctx->rhs || ctx->classes[0] == 0 ||
+ ctx->classes[0] == ctx->classes[1]) {
+ errno = ENOEXEC;
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ * get_txt_records --
+ * Given a DNS class and a DNS name, do a lookup for TXT records, and
+ * return a list of them.
+ */
+static char **
+get_txt_records(qclass, name)
+ int qclass;
+ const char *name;
+{
+ HEADER *hp;
+ unsigned char qbuf[PACKETSZ], abuf[MAX_HESRESP], *p, *eom, *eor;
+ char *dst, **list;
+ int ancount, qdcount, i, j, n, skip, type, class, len;
+
+ /* Make sure the resolver is initialized. */
+ if ((_res.options & RES_INIT) == 0 && res_init() == -1)
+ return NULL;
+
+ /* Construct the query. */
+ n = res_mkquery(QUERY, name, qclass, T_TXT, NULL, 0,
+ NULL, qbuf, PACKETSZ);
+ if (n < 0)
+ return NULL;
+
+ /* Send the query. */
+ n = res_send(qbuf, n, abuf, MAX_HESRESP);
+ if (n < 0 || n > MAX_HESRESP) {
+ errno = ECONNREFUSED; /* XXX */
+ return NULL;
+ }
+ /* Parse the header of the result. */
+ hp = (HEADER *) (void *) abuf;
+ ancount = ntohs(hp->ancount);
+ qdcount = ntohs(hp->qdcount);
+ p = abuf + sizeof(HEADER);
+ eom = abuf + n;
+
+ /*
+ * Skip questions, trying to get to the answer section
+ * which follows.
+ */
+ for (i = 0; i < qdcount; i++) {
+ skip = dn_skipname(p, eom);
+ if (skip < 0 || p + skip + QFIXEDSZ > eom) {
+ errno = EMSGSIZE;
+ return NULL;
+ }
+ p += skip + QFIXEDSZ;
+ }
+
+ /* Allocate space for the text record answers. */
+ list = malloc((ancount + 1) * sizeof(char *));
+ if (!list) {
+ errno = ENOMEM;
+ return NULL;
+ }
+ /* Parse the answers. */
+ j = 0;
+ for (i = 0; i < ancount; i++) {
+ /* Parse the header of this answer. */
+ skip = dn_skipname(p, eom);
+ if (skip < 0 || p + skip + 10 > eom)
+ break;
+ type = p[skip + 0] << 8 | p[skip + 1];
+ class = p[skip + 2] << 8 | p[skip + 3];
+ len = p[skip + 8] << 8 | p[skip + 9];
+ p += skip + 10;
+ if (p + len > eom) {
+ errno = EMSGSIZE;
+ break;
+ }
+ /* Skip entries of the wrong class and type. */
+ if (class != qclass || type != T_TXT) {
+ p += len;
+ continue;
+ }
+ /* Allocate space for this answer. */
+ list[j] = malloc((size_t)len);
+ if (!list[j]) {
+ errno = ENOMEM;
+ break;
+ }
+ dst = list[j++];
+
+ /* Copy answer data into the allocated area. */
+ eor = p + len;
+ while (p < eor) {
+ n = (unsigned char) *p++;
+ if (p + n > eor) {
+ errno = EMSGSIZE;
+ break;
+ }
+ memcpy(dst, p, (size_t)n);
+ p += n;
+ dst += n;
+ }
+ if (p < eor) {
+ errno = EMSGSIZE;
+ break;
+ }
+ *dst = 0;
+ }
+
+ /*
+ * If we didn't terminate the loop normally, something
+ * went wrong.
+ */
+ if (i < ancount) {
+ for (i = 0; i < j; i++)
+ free(list[i]);
+ free(list);
+ return NULL;
+ }
+ if (j == 0) {
+ errno = ENOENT;
+ free(list);
+ return NULL;
+ }
+ list[j] = NULL;
+ return list;
+}
+
+ /*
+ * COMPATIBILITY FUNCTIONS
+ */
+
+static int inited = 0;
+static void *context;
+static int errval = HES_ER_UNINIT;
+
+int
+hes_init()
+{
+ init_context();
+ return errval;
+}
+
+char *
+hes_to_bind(name, type)
+ const char *name;
+ const char *type;
+{
+ static char *bindname;
+ if (init_context() < 0)
+ return NULL;
+ if (bindname)
+ free(bindname);
+ bindname = hesiod_to_bind(context, name, type);
+ if (!bindname)
+ translate_errors();
+ return bindname;
+}
+
+char **
+hes_resolve(name, type)
+ const char *name;
+ const char *type;
+{
+ static char **list;
+
+ if (init_context() < 0)
+ return NULL;
+
+ /*
+ * In the old Hesiod interface, the caller was responsible for
+ * freeing the returned strings but not the vector of strings itself.
+ */
+ if (list)
+ free(list);
+
+ list = hesiod_resolve(context, name, type);
+ if (!list)
+ translate_errors();
+ return list;
+}
+
+int
+hes_error()
+{
+ return errval;
+}
+
+void
+hes_free(hp)
+ char **hp;
+{
+ hesiod_free_list(context, hp);
+}
+
+static int
+init_context()
+{
+ if (!inited) {
+ inited = 1;
+ if (hesiod_init(&context) < 0) {
+ errval = HES_ER_CONFIG;
+ return -1;
+ }
+ errval = HES_ER_OK;
+ }
+ return 0;
+}
+
+static void
+translate_errors()
+{
+ switch (errno) {
+ case ENOENT:
+ errval = HES_ER_NOTFOUND;
+ break;
+ case ECONNREFUSED:
+ case EMSGSIZE:
+ errval = HES_ER_NET;
+ break;
+ case ENOMEM:
+ default:
+ /* Not a good match, but the best we can do. */
+ errval = HES_ER_CONFIG;
+ break;
+ }
+}
diff --git a/lib/libc/net/if_indextoname.3 b/lib/libc/net/if_indextoname.3
new file mode 100644
index 0000000..715c33c
--- /dev/null
+++ b/lib/libc/net/if_indextoname.3
@@ -0,0 +1,152 @@
+.\" $KAME: if_indextoname.3,v 1.10 2000/11/24 08:13:51 itojun Exp $
+.\" BSDI Id: if_indextoname.3,v 2.2 2000/04/17 22:38:05 dab Exp
+.\"
+.\" Copyright (c) 1997, 2000
+.\" Berkeley Software Design, Inc. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 23, 2005
+.Dt IF_NAMETOINDEX 3
+.Os
+.Sh NAME
+.Nm if_nametoindex ,
+.Nm if_indextoname ,
+.Nm if_nameindex ,
+.Nm if_freenameindex
+.Nd provide mappings between interface names and indexes
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In net/if.h
+.Ft "unsigned int"
+.Fn if_nametoindex "const char *ifname"
+.Ft "char *"
+.Fn if_indextoname "unsigned int ifindex" "char *ifname"
+.Ft "struct if_nameindex *"
+.Fn if_nameindex "void"
+.Ft void
+.Fn if_freenameindex "struct if_nameindex *ptr"
+.Sh DESCRIPTION
+The
+.Fn if_nametoindex
+function maps the interface name specified in
+.Fa ifname
+to its corresponding index.
+If the specified interface does not exist, it returns 0.
+.Pp
+The
+.Fn if_indextoname
+function maps the interface index specified in
+.Fa ifindex
+to it corresponding name, which is copied into the
+buffer pointed to by
+.Fa ifname ,
+which must be of at least
+.Dv IFNAMSIZ
+bytes.
+This pointer is also the return value of the function.
+If there is no interface corresponding to the specified
+index,
+.Dv NULL
+is returned.
+.Pp
+The
+.Fn if_nameindex
+function returns an array of
+.Vt if_nameindex
+structures, one structure per interface, as
+defined in the include file
+.In net/if.h .
+The
+.Vt if_nameindex
+structure contains at least the following entries:
+.Bd -literal
+ unsigned int if_index; /* 1, 2, ... */
+ char *if_name; /* null terminated name: "le0", ... */
+.Ed
+.Pp
+The end of the array of structures is indicated by a structure with an
+.Va if_index
+of 0 and an
+.Va if_name
+of
+.Dv NULL .
+A
+.Dv NULL
+pointer is returned upon an error.
+.Pp
+The
+.Fn if_freenameindex
+function frees the dynamic memory that was
+allocated by
+.Fn if_nameindex .
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn if_nametoindex
+returns the index number of the interface.
+If the interface is not found, a value of 0 is returned and
+.Va errno
+is set to
+.Er ENXIO .
+A value of 0 is also returned if an error
+occurs while retrieving the list of interfaces via
+.Xr getifaddrs 3 .
+.Pp
+Upon successful completion,
+.Fn if_indextoname
+returns
+.Fa ifname .
+If the interface is not found, a
+.Dv NULL
+pointer is returned and
+.Va errno
+is set to
+.Er ENXIO .
+A
+.Dv NULL
+pointer is also returned if an error
+occurs while retrieving the list of interfaces via
+.Xr getifaddrs 3 .
+.Pp
+The
+.Fn if_nameindex
+returns a
+.Dv NULL
+pointer if an error
+occurs while retrieving the list of interfaces via
+.Xr getifaddrs 3 ,
+or if sufficient memory cannot be allocated.
+.Sh SEE ALSO
+.Xr getifaddrs 3 ,
+.Xr networking 4
+.Sh STANDARDS
+The
+.Fn if_nametoindex ,
+.Fn if_indextoname ,
+.Fn if_nameindex ,
+and
+.Fn if_freenameindex
+functions conform to
+.%T "RFC 2553" .
+.Sh HISTORY
+The implementation first appeared in BSDi
+.Bsx .
diff --git a/lib/libc/net/if_indextoname.c b/lib/libc/net/if_indextoname.c
new file mode 100644
index 0000000..4dadce3
--- /dev/null
+++ b/lib/libc/net/if_indextoname.c
@@ -0,0 +1,88 @@
+/* $KAME: if_indextoname.c,v 1.7 2000/11/08 03:09:30 itojun Exp $ */
+
+/*-
+ * Copyright (c) 1997, 2000
+ * Berkeley Software Design, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * BSDI Id: if_indextoname.c,v 2.3 2000/04/17 22:38:05 dab Exp
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if_dl.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+/*
+ * From RFC 2533:
+ *
+ * The second function maps an interface index into its corresponding
+ * name.
+ *
+ * #include <net/if.h>
+ *
+ * char *if_indextoname(unsigned int ifindex, char *ifname);
+ *
+ * The ifname argument must point to a buffer of at least IF_NAMESIZE
+ * bytes into which the interface name corresponding to the specified
+ * index is returned. (IF_NAMESIZE is also defined in <net/if.h> and
+ * its value includes a terminating null byte at the end of the
+ * interface name.) This pointer is also the return value of the
+ * function. If there is no interface corresponding to the specified
+ * index, NULL is returned, and errno is set to ENXIO, if there was a
+ * system error (such as running out of memory), if_indextoname returns
+ * NULL and errno would be set to the proper value (e.g., ENOMEM).
+ */
+
+char *
+if_indextoname(unsigned int ifindex, char *ifname)
+{
+ struct ifaddrs *ifaddrs, *ifa;
+ int error = 0;
+
+ if (getifaddrs(&ifaddrs) < 0)
+ return(NULL); /* getifaddrs properly set errno */
+
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr &&
+ ifa->ifa_addr->sa_family == AF_LINK &&
+ ifindex == ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index)
+ break;
+ }
+
+ if (ifa == NULL) {
+ error = ENXIO;
+ ifname = NULL;
+ }
+ else
+ strncpy(ifname, ifa->ifa_name, IFNAMSIZ);
+
+ freeifaddrs(ifaddrs);
+
+ errno = error;
+ return(ifname);
+}
diff --git a/lib/libc/net/if_nameindex.c b/lib/libc/net/if_nameindex.c
new file mode 100644
index 0000000..7a12d34
--- /dev/null
+++ b/lib/libc/net/if_nameindex.c
@@ -0,0 +1,147 @@
+/* $KAME: if_nameindex.c,v 1.8 2000/11/24 08:20:01 itojun Exp $ */
+
+/*-
+ * Copyright (c) 1997, 2000
+ * Berkeley Software Design, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * BSDI Id: if_nameindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if_dl.h>
+#include <net/if.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * From RFC 2553:
+ *
+ * 4.3 Return All Interface Names and Indexes
+ *
+ * The if_nameindex structure holds the information about a single
+ * interface and is defined as a result of including the <net/if.h>
+ * header.
+ *
+ * struct if_nameindex {
+ * unsigned int if_index;
+ * char *if_name;
+ * };
+ *
+ * The final function returns an array of if_nameindex structures, one
+ * structure per interface.
+ *
+ * struct if_nameindex *if_nameindex(void);
+ *
+ * The end of the array of structures is indicated by a structure with
+ * an if_index of 0 and an if_name of NULL. The function returns a NULL
+ * pointer upon an error, and would set errno to the appropriate value.
+ *
+ * The memory used for this array of structures along with the interface
+ * names pointed to by the if_name members is obtained dynamically.
+ * This memory is freed by the next function.
+ *
+ * 4.4. Free Memory
+ *
+ * The following function frees the dynamic memory that was allocated by
+ * if_nameindex().
+ *
+ * #include <net/if.h>
+ *
+ * void if_freenameindex(struct if_nameindex *ptr);
+ *
+ * The argument to this function must be a pointer that was returned by
+ * if_nameindex().
+ */
+
+struct if_nameindex *
+if_nameindex(void)
+{
+ struct ifaddrs *ifaddrs, *ifa;
+ unsigned int ni;
+ int nbytes;
+ struct if_nameindex *ifni, *ifni2;
+ char *cp;
+
+ if (getifaddrs(&ifaddrs) < 0)
+ return(NULL);
+
+ /*
+ * First, find out how many interfaces there are, and how
+ * much space we need for the string names.
+ */
+ ni = 0;
+ nbytes = 0;
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr &&
+ ifa->ifa_addr->sa_family == AF_LINK) {
+ nbytes += strlen(ifa->ifa_name) + 1;
+ ni++;
+ }
+ }
+
+ /*
+ * Next, allocate a chunk of memory, use the first part
+ * for the array of structures, and the last part for
+ * the strings.
+ */
+ cp = malloc((ni + 1) * sizeof(struct if_nameindex) + nbytes);
+ ifni = (struct if_nameindex *)cp;
+ if (ifni == NULL)
+ goto out;
+ cp += (ni + 1) * sizeof(struct if_nameindex);
+
+ /*
+ * Now just loop through the list of interfaces again,
+ * filling in the if_nameindex array and making copies
+ * of all the strings.
+ */
+ ifni2 = ifni;
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr &&
+ ifa->ifa_addr->sa_family == AF_LINK) {
+ ifni2->if_index =
+ ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
+ ifni2->if_name = cp;
+ strcpy(cp, ifa->ifa_name);
+ ifni2++;
+ cp += strlen(cp) + 1;
+ }
+ }
+ /*
+ * Finally, don't forget to terminate the array.
+ */
+ ifni2->if_index = 0;
+ ifni2->if_name = NULL;
+out:
+ freeifaddrs(ifaddrs);
+ return(ifni);
+}
+
+void
+if_freenameindex(struct if_nameindex *ptr)
+{
+ free(ptr);
+}
diff --git a/lib/libc/net/if_nametoindex.c b/lib/libc/net/if_nametoindex.c
new file mode 100644
index 0000000..9d47089
--- /dev/null
+++ b/lib/libc/net/if_nametoindex.c
@@ -0,0 +1,102 @@
+/* $KAME: if_nametoindex.c,v 1.6 2000/11/24 08:18:54 itojun Exp $ */
+
+/*-
+ * Copyright (c) 1997, 2000
+ * Berkeley Software Design, Inc. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * BSDI Id: if_nametoindex.c,v 2.3 2000/04/17 22:38:05 dab Exp
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <net/if.h>
+#include <net/if_dl.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+/*
+ * From RFC 2553:
+ *
+ * 4.1 Name-to-Index
+ *
+ *
+ * The first function maps an interface name into its corresponding
+ * index.
+ *
+ * #include <net/if.h>
+ *
+ * unsigned int if_nametoindex(const char *ifname);
+ *
+ * If the specified interface name does not exist, the return value is
+ * 0, and errno is set to ENXIO. If there was a system error (such as
+ * running out of memory), the return value is 0 and errno is set to the
+ * proper value (e.g., ENOMEM).
+ */
+
+unsigned int
+if_nametoindex(const char *ifname)
+{
+ int s;
+ struct ifreq ifr;
+ struct ifaddrs *ifaddrs, *ifa;
+ unsigned int ni;
+
+ s = _socket(AF_INET, SOCK_DGRAM, 0);
+ if (s != -1) {
+#ifdef PURIFY
+ memset(&ifr, 0, sizeof(ifr));
+#endif
+ strlcpy(ifr.ifr_name, ifname, sizeof(ifr.ifr_name));
+ if (_ioctl(s, SIOCGIFINDEX, &ifr) != -1) {
+ _close(s);
+ return (ifr.ifr_index);
+ }
+ _close(s);
+ }
+
+ if (getifaddrs(&ifaddrs) < 0)
+ return(0);
+
+ ni = 0;
+
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr &&
+ ifa->ifa_addr->sa_family == AF_LINK &&
+ strcmp(ifa->ifa_name, ifname) == 0) {
+ ni = ((struct sockaddr_dl*)ifa->ifa_addr)->sdl_index;
+ break;
+ }
+ }
+
+ freeifaddrs(ifaddrs);
+ if (!ni)
+ errno = ENXIO;
+ return(ni);
+}
diff --git a/lib/libc/net/inet.3 b/lib/libc/net/inet.3
new file mode 100644
index 0000000..af48143
--- /dev/null
+++ b/lib/libc/net/inet.3
@@ -0,0 +1,305 @@
+.\" Copyright (c) 1983, 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)inet.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 14, 2007
+.Dt INET 3
+.Os
+.Sh NAME
+.Nm inet_aton ,
+.Nm inet_addr ,
+.Nm inet_network ,
+.Nm inet_ntoa ,
+.Nm inet_ntoa_r ,
+.Nm inet_ntop ,
+.Nm inet_pton ,
+.Nm inet_makeaddr ,
+.Nm inet_lnaof ,
+.Nm inet_netof
+.Nd Internet address manipulation routines
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/in.h
+.In arpa/inet.h
+.Ft int
+.Fn inet_aton "const char *cp" "struct in_addr *pin"
+.Ft in_addr_t
+.Fn inet_addr "const char *cp"
+.Ft in_addr_t
+.Fn inet_network "const char *cp"
+.Ft char *
+.Fn inet_ntoa "struct in_addr in"
+.Ft char *
+.Fo inet_ntoa_r
+.Fa "struct in_addr in"
+.Fa "char *buf"
+.Fa "socklen_t size"
+.Fc
+.Ft const char *
+.Fo inet_ntop
+.Fa "int af"
+.Fa "const void * restrict src"
+.Fa "char * restrict dst"
+.Fa "socklen_t size"
+.Fc
+.Ft int
+.Fn inet_pton "int af" "const char * restrict src" "void * restrict dst"
+.Ft struct in_addr
+.Fn inet_makeaddr "in_addr_t net" "in_addr_t lna"
+.Ft in_addr_t
+.Fn inet_lnaof "struct in_addr in"
+.Ft in_addr_t
+.Fn inet_netof "struct in_addr in"
+.Sh DESCRIPTION
+The routines
+.Fn inet_aton ,
+.Fn inet_addr
+and
+.Fn inet_network
+interpret character strings representing
+numbers expressed in the Internet standard
+.Ql .\&
+notation.
+.Pp
+The
+.Fn inet_pton
+function converts a presentation format address (that is, printable form
+as held in a character string) to network format (usually a
+.Ft struct in_addr
+or some other internal binary representation, in network byte order).
+It returns 1 if the address was valid for the specified address family, or
+0 if the address was not parseable in the specified address family, or -1
+if some system error occurred (in which case
+.Va errno
+will have been set).
+This function is presently valid for
+.Dv AF_INET
+and
+.Dv AF_INET6 .
+.Pp
+The
+.Fn inet_aton
+routine interprets the specified character string as an Internet address,
+placing the address into the structure provided.
+It returns 1 if the string was successfully interpreted,
+or 0 if the string is invalid.
+The
+.Fn inet_addr
+and
+.Fn inet_network
+functions return numbers suitable for use
+as Internet addresses and Internet network
+numbers, respectively.
+.Pp
+The function
+.Fn inet_ntop
+converts an address
+.Fa *src
+from network format
+(usually a
+.Ft struct in_addr
+or some other binary form, in network byte order) to presentation format
+(suitable for external display purposes).
+The
+.Fa size
+argument specifies the size, in bytes, of the buffer
+.Fa *dst .
+.Dv INET_ADDRSTRLEN
+and
+.Dv INET6_ADDRSTRLEN
+define the maximum size required to convert an address of the respective
+type.
+It returns NULL if a system error occurs (in which case,
+.Va errno
+will have been set), or it returns a pointer to the destination string.
+This function is presently valid for
+.Dv AF_INET
+and
+.Dv AF_INET6 .
+.Pp
+The routine
+.Fn inet_ntoa
+takes an Internet address and returns an
+.Tn ASCII
+string representing the address in
+.Ql .\&
+notation.
+The routine
+.Fn inet_ntoa_r
+is the reentrant version of
+.Fn inet_ntoa .
+The routine
+.Fn inet_makeaddr
+takes an Internet network number and a local
+network address and constructs an Internet address
+from it.
+The routines
+.Fn inet_netof
+and
+.Fn inet_lnaof
+break apart Internet host addresses, returning
+the network number and local network address part,
+respectively.
+.Pp
+All Internet addresses are returned in network
+order (bytes ordered from left to right).
+All network numbers and local address parts are
+returned as machine byte order integer values.
+.Sh INTERNET ADDRESSES
+Values specified using the
+.Ql .\&
+notation take one
+of the following forms:
+.Bd -literal -offset indent
+a.b.c.d
+a.b.c
+a.b
+a
+.Ed
+.Pp
+When four parts are specified, each is interpreted
+as a byte of data and assigned, from left to right,
+to the four bytes of an Internet address.
+Note
+that when an Internet address is viewed as a 32-bit
+integer quantity on the
+.Tn VAX
+the bytes referred to
+above appear as
+.Dq Li d.c.b.a .
+That is,
+.Tn VAX
+bytes are
+ordered from right to left.
+.Pp
+When a three part address is specified, the last
+part is interpreted as a 16-bit quantity and placed
+in the right-most two bytes of the network address.
+This makes the three part address format convenient
+for specifying Class B network addresses as
+.Dq Li 128.net.host .
+.Pp
+When a two part address is supplied, the last part
+is interpreted as a 24-bit quantity and placed in
+the right most three bytes of the network address.
+This makes the two part address format convenient
+for specifying Class A network addresses as
+.Dq Li net.host .
+.Pp
+When only one part is given, the value is stored
+directly in the network address without any byte
+rearrangement.
+.Pp
+All numbers supplied as
+.Dq parts
+in a
+.Ql .\&
+notation
+may be decimal, octal, or hexadecimal, as specified
+in the C language (i.e., a leading 0x or 0X implies
+hexadecimal; otherwise, a leading 0 implies octal;
+otherwise, the number is interpreted as decimal).
+.Sh DIAGNOSTICS
+The constant
+.Dv INADDR_NONE
+is returned by
+.Fn inet_addr
+and
+.Fn inet_network
+for malformed requests.
+.Sh ERRORS
+The
+.Fn inet_ntop
+call fails if:
+.Bl -tag -width Er
+.It Bq Er ENOSPC
+.Fa size
+was not large enough to store the presentation form of the address.
+.It Bq Er EAFNOSUPPORT
+.Fa *src
+was not an
+.Dv AF_INET
+or
+.Dv AF_INET6
+family address.
+.El
+.Sh SEE ALSO
+.Xr byteorder 3 ,
+.Xr getaddrinfo 3 ,
+.Xr gethostbyname 3 ,
+.Xr getnameinfo 3 ,
+.Xr getnetent 3 ,
+.Xr inet_net 3 ,
+.Xr hosts 5 ,
+.Xr networks 5
+.Rs
+.%R RFC
+.%N 2373
+.%D July 1998
+.%T "IP Version 6 Addressing Architecture"
+.Re
+.Sh STANDARDS
+The
+.Fn inet_ntop
+and
+.Fn inet_pton
+functions conform to
+.St -xns5.2 .
+Note that
+.Fn inet_pton
+does not accept 1-, 2-, or 3-part dotted addresses; all four parts
+must be specified and are interpreted only as decimal values.
+This is a narrower input set than that accepted by
+.Fn inet_aton .
+.Sh HISTORY
+These
+functions appeared in
+.Bx 4.2 .
+.Sh BUGS
+The value
+.Dv INADDR_NONE
+(0xffffffff) is a valid broadcast address, but
+.Fn inet_addr
+cannot return that value without indicating failure.
+The newer
+.Fn inet_aton
+function does not share this problem.
+The problem of host byte ordering versus network byte ordering is
+confusing.
+The string returned by
+.Fn inet_ntoa
+resides in a static memory area.
+.Pp
+The
+.Fn inet_addr
+function should return a
+.Fa struct in_addr .
diff --git a/lib/libc/net/inet6_opt_init.3 b/lib/libc/net/inet6_opt_init.3
new file mode 100644
index 0000000..6713468
--- /dev/null
+++ b/lib/libc/net/inet6_opt_init.3
@@ -0,0 +1,337 @@
+.\" $KAME: inet6_opt_init.3,v 1.7 2004/12/27 05:08:23 itojun Exp $
+.\"
+.\" Copyright (C) 2004 WIDE Project.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the project nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 23, 2004
+.Dt INET6_OPT_INIT 3
+.Os
+.\"
+.Sh NAME
+.Nm inet6_opt_init ,
+.Nm inet6_opt_append ,
+.Nm inet6_opt_finish ,
+.Nm inet6_opt_set_val ,
+.Nm inet6_opt_next ,
+.Nm inet6_opt_find ,
+.Nm inet6_opt_get_val
+.Nd IPv6 Hop-by-Hop and Destination Options manipulation
+.\"
+.Sh SYNOPSIS
+.In netinet/in.h
+.Ft "int"
+.Fn inet6_opt_init "void *extbuf" "socklen_t extlen"
+.Ft "int"
+.Fn inet6_opt_append "void *extbuf" "socklen_t extlen" "int offset" "u_int8_t type" "socklen_t len" "u_int8_t align" "void **databufp"
+.Ft "int"
+.Fn inet6_opt_finish "void *extbuf" "socklen_t extlen" "int offset"
+.Ft "int"
+.Fn inet6_opt_set_val "void *databuf" "int offset" "void *val" "socklen_t vallen"
+.Ft "int"
+.Fn inet6_opt_next "void *extbuf" "socklen_t extlen" "int offset" "u_int8_t *typep" "socklen_t *lenp" "void **databufp"
+.Ft "int"
+.Fn inet6_opt_find "void *extbuf" "socklen_t extlen" "int offset" "u_int8_t type" "socklen_t *lenp" "void **databufp"
+.Ft "int"
+.Fn inet6_opt_get_val "void *databuf" "int offset" "void *val" "socklen_t vallen"
+.\"
+.Sh DESCRIPTION
+Building and parsing the Hop-by-Hop and Destination options is
+complicated.
+The advanced sockets API defines a set of functions to
+help applications create and manipulate Hop-by-Hop and Destination
+options.
+This man page describes the functions specified in
+IETF Draft RFC3542.
+These functions use the
+formatting rules specified in Appendix B in RFC2460, i.e., that the
+largest field is placed last in the option.
+The function prototypes
+for these functions are all contained in the
+.In netinet/in.h
+header file.
+.\"
+.Ss inet6_opt_init
+The
+.Fn inet6_opt_init
+function
+returns the number of bytes needed for an empty
+extension header, one without any options.
+If the
+.Fa extbuf
+argument points to a valid section of memory
+then the
+.Fn inet6_opt_init
+function also initializes the extension header's length field.
+When attempting to initialize an extension buffer passed in the
+.Fa extbuf
+argument,
+.Fa extlen
+must be a positive multiple of 8 or else the function fails and
+returns \-1 to the caller.
+.\"
+.Ss inet6_opt_append
+The
+.Fn inet6_opt_append
+function can perform two different jobs.
+When a valid
+.Fa extbuf
+argument is supplied it appends an option to the extension buffer and
+returns the updated total length as well as a pointer to the newly
+created option in
+.Fa databufp .
+If the value
+of
+.Fa extbuf
+is
+.Dv NULL
+then the
+.Fn inet6_opt_append
+function only reports what the total length would
+be if the option were actually appended.
+The
+.Fa len
+and
+.Fa align
+arguments specify the length of the option and the required data
+alignment which must be used when appending the option.
+The
+.Fa offset
+argument should be the length returned by the
+.Fn inet6_opt_init
+function or a previous call to
+.Fn inet6_opt_append .
+.Pp
+The
+.Fa type
+argument is the 8-bit option type.
+.Pp
+After
+.Fn inet6_opt_append
+has been called, the application can use the buffer pointed to by
+.Fa databufp
+directly, or use
+.Fn inet6_opt_set_val
+to specify the data to be contained in the option.
+.Pp
+Option types of
+.Li 0
+and
+.Li 1
+are reserved for the
+.Li Pad1
+and
+.Li PadN
+options.
+All other values from 2 through 255 may be used by applications.
+.Pp
+The length of the option data is contained in an 8-bit value and so
+may contain any value from 0 through 255.
+.Pp
+The
+.Fa align
+parameter must have a value of 1, 2, 4, or 8 and cannot exceed the
+value of
+.Fa len .
+The alignment values represent no alignment, 16 bit, 32 bit and 64 bit
+alignments, respectively.
+.\"
+.Ss inet6_opt_finish
+The
+.Fn inet6_opt_finish
+function
+calculates the final padding necessary to make the extension header a
+multiple of 8 bytes, as required by the IPv6 extension header
+specification, and returns the extension header's updated total
+length.
+The
+.Fa offset
+argument should be the length returned by
+.Fn inet6_opt_init
+or
+.Fn inet6_opt_append .
+When
+.Fa extbuf
+is not
+.Dv NULL
+the function also sets up the appropriate padding bytes by inserting a
+Pad1 or PadN option of the proper length.
+.Pp
+If the extension header is too small to contain the proper padding
+then an error of \-1 is returned to the caller.
+.\"
+.Ss inet6_opt_set_val
+The
+.Fn inet6_opt_set_val
+function inserts data items of various sizes into the data portion of
+the option.
+The
+.Fa databuf
+argument is a pointer to memory that was returned by the
+.Fn inet6_opt_append
+call and the
+.Fa offset
+argument specifies where the option should be placed in the
+data buffer.
+The
+.Fa val
+argument points to an area of memory containing the data to be
+inserted into the extension header, and the
+.Fa vallen
+argument indicates how much data to copy.
+.Pp
+The caller should ensure that each field is aligned on its natural
+boundaries as described in Appendix B of RFC2460.
+.Pp
+The function returns the offset for the next field which is calculated as
+.Fa offset
++
+.Fa vallen
+and is used when composing options with multiple fields.
+.\"
+.Ss inet6_opt_next
+The
+.Fn inet6_opt_next
+function parses received extension headers.
+The
+.Fa extbuf
+and
+.Fa extlen
+arguments specify the location and length of the extension header
+being parsed.
+The
+.Fa offset
+argument should either be zero, for the first option, or the length value
+returned by a previous call to
+.Fn inet6_opt_next
+or
+.Fn inet6_opt_find .
+The return value specifies the position where to continue scanning the
+extension buffer.
+The option is returned in the arguments
+.Fa typep , lenp ,
+and
+.Fa databufp ,
+which
+point to the 8-bit option type, the 8-bit option length and the option
+data, respectively.
+This function does not return any PAD1 or PADN options.
+When an error occurs or there are no more options, the return
+value is \-1.
+.\"
+.Ss inet6_opt_find
+The
+.Fn inet6_opt_find
+function searches the extension buffer for a particular option type,
+passed in through the
+.Fa type
+argument.
+If the option is found then the
+.Fa lenp
+and
+.Fa databufp
+arguments are updated to point to the option's length and data,
+respectively.
+The
+.Fa extbuf
+and
+.Fa extlen
+arguments
+must point to a valid extension buffer and give its length.
+The
+.Fa offset
+argument can be used to search from a location anywhere in the
+extension header.
+.Ss inet6_opt_get_val
+The
+.Fn inet6_opt_get_val
+function extracts data items of various sizes in the data portion of
+the option.
+The
+.Fa databuf
+is a pointer returned by the
+.Fn inet6_opt_next
+or
+.Fn inet6_opt_find
+functions.
+The
+.Fa val
+argument points where the data will be extracted.
+The
+.Fa offset
+argument specifies from where in the data portion of the option the
+value should be extracted; the first byte of option data is specified
+by an offset of zero.
+.Pp
+It is expected that each field is aligned on its natural boundaries as
+described in Appendix B of RFC2460.
+.Pp
+The function returns the offset for the next field
+by calculating
+.Fa offset
++
+.Fa vallen
+which can be used when extracting option content with multiple fields.
+Robust receivers must verify alignment before calling this function.
+.\"
+.Sh RETURN VALUES
+All the functions return
+\-1
+on an error.
+.\"
+.Sh EXAMPLES
+RFC3542 gives comprehensive examples in Section 23.
+.Pp
+KAME also provides examples in the
+.Pa advapitest
+directory of its kit.
+.\"
+.Sh SEE ALSO
+.Rs
+.%A W. Stevens
+.%A M. Thomas
+.%A E. Nordmark
+.%A T. Jinmei
+.%T "Advanced Sockets API for IPv6"
+.%N RFC3542
+.%D October 2002
+.Re
+.Rs
+.%A S. Deering
+.%A R. Hinden
+.%T "Internet Protocol, Version 6 (IPv6) Specification"
+.%N RFC2460
+.%D December 1998
+.Re
+.Sh STANDARDS
+The functions are documented in
+.Dq Advanced Sockets API for IPv6
+.Pq RFC3542 .
+.\"
+.Sh HISTORY
+The implementation first appeared in KAME advanced networking kit.
diff --git a/lib/libc/net/inet6_option_space.3 b/lib/libc/net/inet6_option_space.3
new file mode 100644
index 0000000..e17855a
--- /dev/null
+++ b/lib/libc/net/inet6_option_space.3
@@ -0,0 +1,54 @@
+.\" $KAME: inet6_option_space.3,v 1.11 2005/01/05 03:00:44 itojun Exp $
+.\"
+.\" Copyright (C) 2004 WIDE Project.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the project nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 24, 2005
+.Dt INET6_OPTION_SPACE 3
+.Os
+.\"
+.Sh NAME
+.Nm inet6_option_space ,
+.Nm inet6_option_init ,
+.Nm inet6_option_append ,
+.Nm inet6_option_alloc ,
+.Nm inet6_option_next ,
+.Nm inet6_option_find
+.Nd IPv6 Hop-by-Hop and Destination Option Manipulation
+.\"
+.Sh DESCRIPTION
+The functions that were documented in this manual page are now
+deprecated in favor of those described in
+.Xr inet6_opt_init 3 .
+Please refer to that manual page for information on how to manipulate
+IPv6 Hop-by-Hop and Destination options.
+.Sh SEE ALSO
+.Xr inet6_opt_init 3
+.\"
+.\"
diff --git a/lib/libc/net/inet6_rth_space.3 b/lib/libc/net/inet6_rth_space.3
new file mode 100644
index 0000000..a3db794
--- /dev/null
+++ b/lib/libc/net/inet6_rth_space.3
@@ -0,0 +1,225 @@
+.\" $KAME: inet6_rth_space.3,v 1.7 2005/01/05 03:00:44 itojun Exp $
+.\"
+.\" Copyright (C) 2004 WIDE Project.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the project nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 24, 2004
+.Dt INET6_RTH_SPACE 3
+.Os
+.\"
+.Sh NAME
+.Nm inet6_rth_space ,
+.Nm inet6_rth_init ,
+.Nm inet6_rth_add ,
+.Nm inet6_rth_reverse ,
+.Nm inet6_rth_segments ,
+.Nm inet6_rth_getaddr
+.Nd IPv6 Routing Header Options manipulation
+.\"
+.Sh SYNOPSIS
+.In netinet/in.h
+.Ft socklen_t
+.Fn inet6_rth_space "int" "int"
+.Ft "void *"
+.Fn inet6_rth_init "void *" "socklen_t" "int" "int"
+.Ft int
+.Fn inet6_rth_add "void *" "const struct in6_addr *"
+.Ft int
+.Fn inet6_rth_reverse "const void *" "void *"
+.Ft int
+.Fn inet6_rth_segments "const void *"
+.Ft "struct in6_addr *"
+.Fn inet6_rth_getaddr "const void *" "int"
+.\"
+.Sh DESCRIPTION
+The IPv6 Advanced API, RFC 3542, defines the functions that an
+application calls to build and examine IPv6 Routing headers.
+Routing headers are used to perform source routing in IPv6 networks.
+The RFC uses the word
+.Dq segments
+to describe addresses and that is the term used here as well.
+All of the functions are defined in the
+.In netinet/in.h
+header file.
+The functions described in this manual page all operate
+on routing header structures which are defined in
+.In netinet/ip6.h
+but which should not need to be modified outside the use of this API.
+The size and shape of the route header structures may change, so using
+the APIs is a more portable, long term, solution.
+.Pp
+The functions in the API are split into two groups, those that build a
+routing header and those that parse a received routing header.
+We will describe the builder functions followed by the parser functions.
+.Ss inet6_rth_space
+The
+.Fn inet6_rth_space
+function returns the number of bytes required to hold a Routing Header
+of the type, specified in the
+.Fa type
+argument and containing the number of addresses specified in the
+.Fa segments
+argument.
+When the type is
+.Dv IPV6_RTHDR_TYPE_0
+the number of segments must be from 0 through 127.
+Routing headers of type
+.Dv IPV6_RTHDR_TYPE_2
+contain only one segment, and are only used with Mobile IPv6.
+The return value from this function is the number of bytes required to
+store the routing header.
+If the value 0 is returned then either the
+route header type was not recognized or another error occurred.
+.Ss inet6_rth_init
+The
+.Fn inet6_rth_init
+function initializes the pre-allocated buffer pointed to by
+.Fa bp
+to contain a routing header of the specified type.
+The
+.Fa bp_len
+argument is used to verify that the buffer is large enough.
+The caller must allocate the buffer pointed to by bp.
+The necessary buffer size should be determined by calling
+.Fn inet6_rth_space
+described in the previous sections.
+.Pp
+The
+.Fn inet6_rth_init
+function returns a pointer to
+.Fa bp
+on success and
+.Dv NULL
+when there is an error.
+.Ss inet6_rth_add
+The
+.Fn inet6_rth_add
+function adds the IPv6 address pointed to by
+.Fa addr
+to the end of the routing header being constructed.
+.Pp
+A successful addition results in the function returning 0, otherwise
+\-1 is returned.
+.Ss inet6_rth_reverse
+The
+.Fn inet6_rth_reverse
+function takes a routing header, pointed to by the
+argument
+.Fa in ,
+and writes a new routing header into the argument pointed to by
+.Fa out .
+The routing header at that sends datagrams along the reverse of that
+route.
+Both arguments are allowed to point to the same buffer meaning
+that the reversal can occur in place.
+.Pp
+The return value of the function is 0 on success, or \-1 when
+there is an error.
+.\"
+.Pp
+The next set of functions operate on a routing header that the
+application wants to parse.
+In the usual case such a routing header
+is received from the network, although these functions can also be
+used with routing headers that the application itself created.
+.Ss inet6_rth_segments
+The
+.Fn inet6_rth_segments
+function returns the number of segments contained in the
+routing header pointed to by
+.Fa bp .
+The return value is the number of segments contained in the routing
+header, or \-1 if an error occurred.
+It is not an error for 0 to be
+returned as a routing header may contain 0 segments.
+.\"
+.Ss inet6_rth_getaddr
+The
+.Fn inet6_rth_getaddr
+function is used to retrieve a single address from a routing header.
+The
+.Fa index
+is the location in the routing header from which the application wants
+to retrieve an address.
+The
+.Fa index
+parameter must have a value between 0 and one less than the number of
+segments present in the routing header.
+The
+.Fn inet6_rth_segments
+function, described in the last section, should be used to determine
+the total number of segments in the routing header.
+The
+.Fn inet6_rth_getaddr
+function returns a pointer to an IPv6 address on success or
+.Dv NULL
+when an error has occurred.
+.\"
+.Sh EXAMPLES
+RFC 3542 gives extensive examples in Section 21, Appendix B.
+.Pp
+KAME also provides examples in the advapitest directory of its kit.
+.\"
+.Sh DIAGNOSTICS
+The
+.Fn inet6_rth_space
+and
+.Fn inet6_rth_getaddr
+functions return 0 on errors.
+.Pp
+The
+.Fn inet6_rthdr_init
+function returns
+.Dv NULL
+on error.
+The
+.Fn inet6_rth_add
+and
+.Fn inet6_rth_reverse
+functions return 0 on success, or \-1 upon an error.
+.\"
+.Sh SEE ALSO
+.Rs
+.%A W. Stevens
+.%A M. Thomas
+.%A E. Nordmark
+.%A T. Jinmei
+.%T "Advanced Sockets API for IPv6"
+.%N RFC 3542
+.%D May 2003
+.Re
+.Rs
+.%A S. Deering
+.%A R. Hinden
+.%T "Internet Protocol, Version 6 (IPv6) Specification"
+.%N RFC2460
+.%D December 1998
+.Re
+.Sh HISTORY
+The implementation first appeared in KAME advanced networking kit.
diff --git a/lib/libc/net/inet6_rthdr_space.3 b/lib/libc/net/inet6_rthdr_space.3
new file mode 100644
index 0000000..bfb2f23
--- /dev/null
+++ b/lib/libc/net/inet6_rthdr_space.3
@@ -0,0 +1,57 @@
+.\" $KAME: inet6_rthdr_space.3,v 1.11 2005/01/05 03:00:44 itojun Exp $
+.\"
+.\" Copyright (C) 2004 WIDE Project.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the project nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 24, 2005
+.Dt INET6_RTHDR_SPACE 3
+.Os
+.\"
+.Sh NAME
+.Nm inet6_rthdr_space ,
+.Nm inet6_rthdr_init ,
+.Nm inet6_rthdr_add ,
+.Nm inet6_rthdr_lasthop ,
+.Nm inet6_rthdr_reverse ,
+.Nm inet6_rthdr_segments ,
+.Nm inet6_rthdr_getaddr ,
+.Nm inet6_rthdr_getflags
+.Nd IPv6 Routing Header Options Manipulation
+.\"
+.Sh DESCRIPTION
+The RFC 2292 IPv6 Advanced API has been deprecated in favor of the
+newer, RFC 3542 APIs documented in
+.Xr inet6_rth_space 3 .
+On platforms that support it, currently only
+.Fx ,
+please use the newer API to manipulate routing header
+options.
+.\"
+.Sh SEE ALSO
+.Xr inet6_rth_space 3
diff --git a/lib/libc/net/inet_net.3 b/lib/libc/net/inet_net.3
new file mode 100644
index 0000000..9a12cc7
--- /dev/null
+++ b/lib/libc/net/inet_net.3
@@ -0,0 +1,162 @@
+.\" $NetBSD: inet_net.3,v 1.4 1999/03/22 19:44:52 garbled Exp $
+.\"
+.\" Copyright (c) 1997 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Luke Mewburn.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of The NetBSD Foundation nor the names of its
+.\" contributors may be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 26, 2006
+.Dt INET_NET 3
+.Os
+.Sh NAME
+.Nm inet_net_ntop ,
+.Nm inet_net_pton
+.Nd Internet network number manipulation routines
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/in.h
+.In arpa/inet.h
+.Ft char *
+.Fn inet_net_ntop "int af" "const void *src" "int bits" "char *dst" "size_t size"
+.Ft int
+.Fn inet_net_pton "int af" "const char *src" "void *dst" "size_t size"
+.Sh DESCRIPTION
+The
+.Fn inet_net_ntop
+function converts an Internet network number from network format (usually a
+.Vt "struct in_addr"
+or some other binary form, in network byte order) to CIDR presentation format
+(suitable for external display purposes).
+The
+.Fa bits
+argument
+is the number of bits in
+.Fa src
+that are the network number.
+It returns
+.Dv NULL
+if a system error occurs (in which case,
+.Va errno
+will have been set), or it returns a pointer to the destination string.
+.Pp
+The
+.Fn inet_net_pton
+function converts a presentation format Internet network number (that is,
+printable form as held in a character string) to network format (usually a
+.Vt "struct in_addr"
+or some other internal binary representation, in network byte order).
+It returns the number of bits (either computed based on the class, or
+specified with /CIDR), or \-1 if a failure occurred
+(in which case
+.Va errno
+will have been set.
+It will be set to
+.Er ENOENT
+if the Internet network number was not valid).
+.Pp
+The currently supported values for
+.Fa af
+are
+.Dv AF_INET
+and
+.Dv AF_INET6 .
+The
+.Fa size
+argument
+is the size of the result buffer
+.Fa dst .
+.Sh NETWORK NUMBERS (IP VERSION 4)
+Internet network numbers may be specified in one of the following forms:
+.Bd -literal -offset indent
+a.b.c.d/bits
+a.b.c.d
+a.b.c
+a.b
+a
+.Ed
+.Pp
+When four parts are specified, each is interpreted
+as a byte of data and assigned, from left to right,
+to the four bytes of an Internet network number.
+Note
+that when an Internet network number is viewed as a 32-bit
+integer quantity on a system that uses little-endian
+byte order (such as the
+.Tn Intel 386 , 486 ,
+and
+.Tn Pentium
+processors) the bytes referred to above appear as
+.Dq Li d.c.b.a .
+That is, little-endian bytes are ordered from right to left.
+.Pp
+When a three part number is specified, the last
+part is interpreted as a 16-bit quantity and placed
+in the rightmost two bytes of the Internet network number.
+This makes the three part number format convenient
+for specifying Class B network numbers as
+.Dq Li 128.net.host .
+.Pp
+When a two part number is supplied, the last part
+is interpreted as a 24-bit quantity and placed in
+the rightmost three bytes of the Internet network number.
+This makes the two part number format convenient
+for specifying Class A network numbers as
+.Dq Li net.host .
+.Pp
+When only one part is given, the value is stored
+directly in the Internet network number without any byte
+rearrangement.
+.Pp
+All numbers supplied as
+.Dq parts
+in a
+.Ql \&.
+notation
+may be decimal, octal, or hexadecimal, as specified
+in the C language (i.e., a leading 0x or 0X implies
+hexadecimal; otherwise, a leading 0 implies octal;
+otherwise, the number is interpreted as decimal).
+.\"
+.\" .Sh NETWORK NUMBERS (IP VERSION 6)
+.\" XXX - document this!
+.\"
+.Sh SEE ALSO
+.Xr byteorder 3 ,
+.Xr inet 3 ,
+.Xr networks 5
+.Sh HISTORY
+The
+.Fn inet_net_ntop
+and
+.Fn inet_net_pton
+functions appeared in BIND 4.9.4.
diff --git a/lib/libc/net/ip6opt.c b/lib/libc/net/ip6opt.c
new file mode 100644
index 0000000..d999fd4
--- /dev/null
+++ b/lib/libc/net/ip6opt.c
@@ -0,0 +1,593 @@
+/* $KAME: ip6opt.c,v 1.13 2003/06/06 10:08:20 suz Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+
+#include <string.h>
+#include <stdio.h>
+
+static int ip6optlen(u_int8_t *opt, u_int8_t *lim);
+static void inet6_insert_padopt(u_char *p, int len);
+
+/*
+ * This function returns the number of bytes required to hold an option
+ * when it is stored as ancillary data, including the cmsghdr structure
+ * at the beginning, and any padding at the end (to make its size a
+ * multiple of 8 bytes). The argument is the size of the structure
+ * defining the option, which must include any pad bytes at the
+ * beginning (the value y in the alignment term "xn + y"), the type
+ * byte, the length byte, and the option data.
+ */
+int
+inet6_option_space(int nbytes)
+{
+ nbytes += 2; /* we need space for nxt-hdr and length fields */
+ return(CMSG_SPACE((nbytes + 7) & ~7));
+}
+
+/*
+ * This function is called once per ancillary data object that will
+ * contain either Hop-by-Hop or Destination options. It returns 0 on
+ * success or -1 on an error.
+ */
+int
+inet6_option_init(void *bp, struct cmsghdr **cmsgp, int type)
+{
+ struct cmsghdr *ch = (struct cmsghdr *)bp;
+
+ /* argument validation */
+ if (type != IPV6_HOPOPTS && type != IPV6_DSTOPTS)
+ return(-1);
+
+ ch->cmsg_level = IPPROTO_IPV6;
+ ch->cmsg_type = type;
+ ch->cmsg_len = CMSG_LEN(0);
+
+ *cmsgp = ch;
+ return(0);
+}
+
+/*
+ * This function appends a Hop-by-Hop option or a Destination option
+ * into an ancillary data object that has been initialized by
+ * inet6_option_init(). This function returns 0 if it succeeds or -1 on
+ * an error.
+ * multx is the value x in the alignment term "xn + y" described
+ * earlier. It must have a value of 1, 2, 4, or 8.
+ * plusy is the value y in the alignment term "xn + y" described
+ * earlier. It must have a value between 0 and 7, inclusive.
+ */
+int
+inet6_option_append(struct cmsghdr *cmsg, const u_int8_t *typep, int multx,
+ int plusy)
+{
+ int padlen, optlen, off;
+ u_char *bp = (u_char *)cmsg + cmsg->cmsg_len;
+ struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg);
+
+ /* argument validation */
+ if (multx != 1 && multx != 2 && multx != 4 && multx != 8)
+ return(-1);
+ if (plusy < 0 || plusy > 7)
+ return(-1);
+
+ /*
+ * If this is the first option, allocate space for the
+ * first 2 bytes(for next header and length fields) of
+ * the option header.
+ */
+ if (bp == (u_char *)eh) {
+ bp += 2;
+ cmsg->cmsg_len += 2;
+ }
+
+ /* calculate pad length before the option. */
+ off = bp - (u_char *)eh;
+ padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) -
+ (off % multx);
+ padlen += plusy;
+ padlen %= multx; /* keep the pad as short as possible */
+ /* insert padding */
+ inet6_insert_padopt(bp, padlen);
+ cmsg->cmsg_len += padlen;
+ bp += padlen;
+
+ /* copy the option */
+ if (typep[0] == IP6OPT_PAD1)
+ optlen = 1;
+ else
+ optlen = typep[1] + 2;
+ memcpy(bp, typep, optlen);
+ bp += optlen;
+ cmsg->cmsg_len += optlen;
+
+ /* calculate pad length after the option and insert the padding */
+ off = bp - (u_char *)eh;
+ padlen = ((off + 7) & ~7) - off;
+ inet6_insert_padopt(bp, padlen);
+ bp += padlen;
+ cmsg->cmsg_len += padlen;
+
+ /* update the length field of the ip6 option header */
+ eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1;
+
+ return(0);
+}
+
+/*
+ * This function appends a Hop-by-Hop option or a Destination option
+ * into an ancillary data object that has been initialized by
+ * inet6_option_init(). This function returns a pointer to the 8-bit
+ * option type field that starts the option on success, or NULL on an
+ * error.
+ * The difference between this function and inet6_option_append() is
+ * that the latter copies the contents of a previously built option into
+ * the ancillary data object while the current function returns a
+ * pointer to the space in the data object where the option's TLV must
+ * then be built by the caller.
+ *
+ */
+u_int8_t *
+inet6_option_alloc(struct cmsghdr *cmsg, int datalen, int multx, int plusy)
+{
+ int padlen, off;
+ u_int8_t *bp = (u_char *)cmsg + cmsg->cmsg_len;
+ u_int8_t *retval;
+ struct ip6_ext *eh = (struct ip6_ext *)CMSG_DATA(cmsg);
+
+ /* argument validation */
+ if (multx != 1 && multx != 2 && multx != 4 && multx != 8)
+ return(NULL);
+ if (plusy < 0 || plusy > 7)
+ return(NULL);
+
+ /*
+ * If this is the first option, allocate space for the
+ * first 2 bytes(for next header and length fields) of
+ * the option header.
+ */
+ if (bp == (u_char *)eh) {
+ bp += 2;
+ cmsg->cmsg_len += 2;
+ }
+
+ /* calculate pad length before the option. */
+ off = bp - (u_char *)eh;
+ padlen = (((off % multx) + (multx - 1)) & ~(multx - 1)) -
+ (off % multx);
+ padlen += plusy;
+ padlen %= multx; /* keep the pad as short as possible */
+ /* insert padding */
+ inet6_insert_padopt(bp, padlen);
+ cmsg->cmsg_len += padlen;
+ bp += padlen;
+
+ /* keep space to store specified length of data */
+ retval = bp;
+ bp += datalen;
+ cmsg->cmsg_len += datalen;
+
+ /* calculate pad length after the option and insert the padding */
+ off = bp - (u_char *)eh;
+ padlen = ((off + 7) & ~7) - off;
+ inet6_insert_padopt(bp, padlen);
+ bp += padlen;
+ cmsg->cmsg_len += padlen;
+
+ /* update the length field of the ip6 option header */
+ eh->ip6e_len = ((bp - (u_char *)eh) >> 3) - 1;
+
+ return(retval);
+}
+
+/*
+ * This function processes the next Hop-by-Hop option or Destination
+ * option in an ancillary data object. If another option remains to be
+ * processed, the return value of the function is 0 and *tptrp points to
+ * the 8-bit option type field (which is followed by the 8-bit option
+ * data length, followed by the option data). If no more options remain
+ * to be processed, the return value is -1 and *tptrp is NULL. If an
+ * error occurs, the return value is -1 and *tptrp is not NULL.
+ * (RFC 2292, 6.3.5)
+ */
+int
+inet6_option_next(const struct cmsghdr *cmsg, u_int8_t **tptrp)
+{
+ struct ip6_ext *ip6e;
+ int hdrlen, optlen;
+ u_int8_t *lim;
+
+ if (cmsg->cmsg_level != IPPROTO_IPV6 ||
+ (cmsg->cmsg_type != IPV6_HOPOPTS &&
+ cmsg->cmsg_type != IPV6_DSTOPTS))
+ return(-1);
+
+ /* message length validation */
+ if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext)))
+ return(-1);
+ ip6e = (struct ip6_ext *)CMSG_DATA(cmsg);
+ hdrlen = (ip6e->ip6e_len + 1) << 3;
+ if (cmsg->cmsg_len < CMSG_SPACE(hdrlen))
+ return(-1);
+
+ /*
+ * If the caller does not specify the starting point,
+ * simply return the 1st option.
+ * Otherwise, search the option list for the next option.
+ */
+ lim = (u_int8_t *)ip6e + hdrlen;
+ if (*tptrp == NULL)
+ *tptrp = (u_int8_t *)(ip6e + 1);
+ else {
+ if ((optlen = ip6optlen(*tptrp, lim)) == 0)
+ return(-1);
+
+ *tptrp = *tptrp + optlen;
+ }
+ if (*tptrp >= lim) { /* there is no option */
+ *tptrp = NULL;
+ return(-1);
+ }
+ /*
+ * Finally, checks if the next option is safely stored in the
+ * cmsg data.
+ */
+ if (ip6optlen(*tptrp, lim) == 0)
+ return(-1);
+ else
+ return(0);
+}
+
+/*
+ * This function is similar to the inet6_option_next() function,
+ * except this function lets the caller specify the option type to be
+ * searched for, instead of always returning the next option in the
+ * ancillary data object.
+ * Note: RFC 2292 says the type of tptrp is u_int8_t *, but we think
+ * it's a typo. The variable should be type of u_int8_t **.
+ */
+int
+inet6_option_find(const struct cmsghdr *cmsg, u_int8_t **tptrp, int type)
+{
+ struct ip6_ext *ip6e;
+ int hdrlen, optlen;
+ u_int8_t *optp, *lim;
+
+ if (cmsg->cmsg_level != IPPROTO_IPV6 ||
+ (cmsg->cmsg_type != IPV6_HOPOPTS &&
+ cmsg->cmsg_type != IPV6_DSTOPTS))
+ return(-1);
+
+ /* message length validation */
+ if (cmsg->cmsg_len < CMSG_SPACE(sizeof(struct ip6_ext)))
+ return(-1);
+ ip6e = (struct ip6_ext *)CMSG_DATA(cmsg);
+ hdrlen = (ip6e->ip6e_len + 1) << 3;
+ if (cmsg->cmsg_len < CMSG_SPACE(hdrlen))
+ return(-1);
+
+ /*
+ * If the caller does not specify the starting point,
+ * search from the beginning of the option list.
+ * Otherwise, search from *the next option* of the specified point.
+ */
+ lim = (u_int8_t *)ip6e + hdrlen;
+ if (*tptrp == NULL)
+ *tptrp = (u_int8_t *)(ip6e + 1);
+ else {
+ if ((optlen = ip6optlen(*tptrp, lim)) == 0)
+ return(-1);
+
+ *tptrp = *tptrp + optlen;
+ }
+ for (optp = *tptrp; optp < lim; optp += optlen) {
+ if (*optp == type) {
+ *tptrp = optp;
+ return(0);
+ }
+ if ((optlen = ip6optlen(optp, lim)) == 0)
+ return(-1);
+ }
+
+ /* search failed */
+ *tptrp = NULL;
+ return(-1);
+}
+
+/*
+ * Calculate the length of a given IPv6 option. Also checks
+ * if the option is safely stored in user's buffer according to the
+ * calculated length and the limitation of the buffer.
+ */
+static int
+ip6optlen(u_int8_t *opt, u_int8_t *lim)
+{
+ int optlen;
+
+ if (*opt == IP6OPT_PAD1)
+ optlen = 1;
+ else {
+ /* is there enough space to store type and len? */
+ if (opt + 2 > lim)
+ return(0);
+ optlen = *(opt + 1) + 2;
+ }
+ if (opt + optlen <= lim)
+ return(optlen);
+
+ return(0);
+}
+
+static void
+inet6_insert_padopt(u_char *p, int len)
+{
+ switch(len) {
+ case 0:
+ return;
+ case 1:
+ p[0] = IP6OPT_PAD1;
+ return;
+ default:
+ p[0] = IP6OPT_PADN;
+ p[1] = len - 2;
+ memset(&p[2], 0, len - 2);
+ return;
+ }
+}
+
+/*
+ * The following functions are defined in RFC3542, which is a successor
+ * of RFC2292.
+ */
+
+int
+inet6_opt_init(void *extbuf, socklen_t extlen)
+{
+ struct ip6_ext *ext = (struct ip6_ext *)extbuf;
+
+ if (extlen < 0 || (extlen % 8))
+ return(-1);
+
+ if (ext) {
+ if (extlen == 0)
+ return(-1);
+ ext->ip6e_len = (extlen >> 3) - 1;
+ }
+
+ return(2); /* sizeof the next and the length fields */
+}
+
+int
+inet6_opt_append(void *extbuf, socklen_t extlen, int offset, u_int8_t type,
+ socklen_t len, u_int8_t align, void **databufp)
+{
+ int currentlen = offset, padlen = 0;
+
+ /*
+ * The option type must have a value from 2 to 255, inclusive.
+ * (0 and 1 are reserved for the Pad1 and PadN options, respectively.)
+ */
+ if (type < 2)
+ return(-1);
+
+ /*
+ * The option data length must have a value between 0 and 255,
+ * inclusive, and is the length of the option data that follows.
+ */
+ if (len < 0 || len > 255)
+ return(-1);
+
+ /*
+ * The align parameter must have a value of 1, 2, 4, or 8.
+ * The align value can not exceed the value of len.
+ */
+ if (align != 1 && align != 2 && align != 4 && align != 8)
+ return(-1);
+ if (align > len)
+ return(-1);
+
+ /* Calculate the padding length. */
+ currentlen += 2 + len; /* 2 means "type + len" */
+ if (currentlen % align)
+ padlen = align - (currentlen % align);
+
+ /* The option must fit in the extension header buffer. */
+ currentlen += padlen;
+ if (extlen && /* XXX: right? */
+ currentlen > extlen)
+ return(-1);
+
+ if (extbuf) {
+ u_int8_t *optp = (u_int8_t *)extbuf + offset;
+
+ if (padlen == 1) {
+ /* insert a Pad1 option */
+ *optp = IP6OPT_PAD1;
+ optp++;
+ }
+ else if (padlen > 0) {
+ /* insert a PadN option for alignment */
+ *optp++ = IP6OPT_PADN;
+ *optp++ = padlen - 2;
+ memset(optp, 0, padlen - 2);
+ optp += (padlen - 2);
+ }
+
+ *optp++ = type;
+ *optp++ = len;
+
+ *databufp = optp;
+ }
+
+ return(currentlen);
+}
+
+int
+inet6_opt_finish(void *extbuf, socklen_t extlen, int offset)
+{
+ int updatelen = offset > 0 ? (1 + ((offset - 1) | 7)) : 0;;
+
+ if (extbuf) {
+ u_int8_t *padp;
+ int padlen = updatelen - offset;
+
+ if (updatelen > extlen)
+ return(-1);
+
+ padp = (u_int8_t *)extbuf + offset;
+ if (padlen == 1)
+ *padp = IP6OPT_PAD1;
+ else if (padlen > 0) {
+ *padp++ = IP6OPT_PADN;
+ *padp++ = (padlen - 2);
+ memset(padp, 0, padlen - 2);
+ }
+ }
+
+ return(updatelen);
+}
+
+int
+inet6_opt_set_val(void *databuf, int offset, void *val, socklen_t vallen)
+{
+
+ memcpy((u_int8_t *)databuf + offset, val, vallen);
+ return(offset + vallen);
+}
+
+int
+inet6_opt_next(void *extbuf, socklen_t extlen, int offset, u_int8_t *typep,
+ socklen_t *lenp, void **databufp)
+{
+ u_int8_t *optp, *lim;
+ int optlen;
+
+ /* Validate extlen. XXX: is the variable really necessary?? */
+ if (extlen == 0 || (extlen % 8))
+ return(-1);
+ lim = (u_int8_t *)extbuf + extlen;
+
+ /*
+ * If this is the first time this function called for this options
+ * header, simply return the 1st option.
+ * Otherwise, search the option list for the next option.
+ */
+ if (offset == 0) {
+ optp = (u_int8_t *)((struct ip6_hbh *)extbuf + 1);
+ }
+ else
+ optp = (u_int8_t *)extbuf + offset;
+
+ /* Find the next option skipping any padding options. */
+ while(optp < lim) {
+ switch(*optp) {
+ case IP6OPT_PAD1:
+ optp++;
+ break;
+ case IP6OPT_PADN:
+ if ((optlen = ip6optlen(optp, lim)) == 0)
+ goto optend;
+ optp += optlen;
+ break;
+ default: /* found */
+ if ((optlen = ip6optlen(optp, lim)) == 0)
+ goto optend;
+ *typep = *optp;
+ *lenp = optlen - 2;
+ *databufp = optp + 2;
+ return(optp + optlen - (u_int8_t *)extbuf);
+ }
+ }
+
+ optend:
+ *databufp = NULL; /* for safety */
+ return(-1);
+}
+
+int
+inet6_opt_find(void *extbuf, socklen_t extlen, int offset, u_int8_t type,
+ socklen_t *lenp, void **databufp)
+{
+ u_int8_t *optp, *lim;
+ int optlen;
+
+ /* Validate extlen. XXX: is the variable really necessary?? */
+ if (extlen == 0 || (extlen % 8))
+ return(-1);
+ lim = (u_int8_t *)extbuf + extlen;
+
+ /*
+ * If this is the first time this function called for this options
+ * header, simply return the 1st option.
+ * Otherwise, search the option list for the next option.
+ */
+ if (offset == 0) {
+ optp = (u_int8_t *)((struct ip6_hbh *)extbuf + 1);
+ }
+ else
+ optp = (u_int8_t *)extbuf + offset;
+
+ /* Find the specified option */
+ while(optp < lim) {
+ if ((optlen = ip6optlen(optp, lim)) == 0)
+ goto optend;
+
+ if (*optp == type) { /* found */
+ *lenp = optlen - 2;
+ *databufp = optp + 2;
+ return(optp + optlen - (u_int8_t *)extbuf);
+ }
+
+ optp += optlen;
+ }
+
+ optend:
+ *databufp = NULL; /* for safety */
+ return(-1);
+}
+
+int
+inet6_opt_get_val(void *databuf, int offset, void *val, socklen_t vallen)
+{
+
+ /* we can't assume alignment here */
+ memcpy(val, (u_int8_t *)databuf + offset, vallen);
+
+ return(offset + vallen);
+}
diff --git a/lib/libc/net/linkaddr.3 b/lib/libc/net/linkaddr.3
new file mode 100644
index 0000000..4387675
--- /dev/null
+++ b/lib/libc/net/linkaddr.3
@@ -0,0 +1,134 @@
+.\" Copyright (c) 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Donn Seeley at BSDI.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)linkaddr.3 8.1 (Berkeley) 7/28/93
+.\" $FreeBSD$
+.\"
+.Dd February 28, 2007
+.Dt LINK_ADDR 3
+.Os
+.Sh NAME
+.Nm link_addr ,
+.Nm link_ntoa
+.Nd elementary address specification routines for link level access
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In net/if_dl.h
+.Ft void
+.Fn link_addr "const char *addr" "struct sockaddr_dl *sdl"
+.Ft char *
+.Fn link_ntoa "const struct sockaddr_dl *sdl"
+.Sh DESCRIPTION
+The routine
+.Fn link_addr
+interprets character strings representing
+link-level addresses, returning binary information suitable
+for use in system calls.
+The routine
+.Fn link_ntoa
+takes
+a link-level
+address and returns an
+.Tn ASCII
+string representing some of the information present,
+including the link level address itself, and the interface name
+or number, if present.
+This facility is experimental and is
+still subject to change.
+.Pp
+For
+.Fn link_addr ,
+the string
+.Fa addr
+may contain
+an optional network interface identifier of the form
+.Dq "name unit-number" ,
+suitable for the first argument to
+.Xr ifconfig 8 ,
+followed in all cases by a colon and
+an interface address in the form of
+groups of hexadecimal digits
+separated by periods.
+Each group represents a byte of address;
+address bytes are filled left to right from
+low order bytes through high order bytes.
+.Pp
+.\" A regular expression may make this format clearer:
+.\" .Bd -literal -offset indent
+.\" ([a-z]+[0-9]+:)?[0-9a-f]+(\e.[0-9a-f]+)*
+.\" .Ed
+.\" .Pp
+Thus
+.Li le0:8.0.9.13.d.30
+represents an ethernet address
+to be transmitted on the first Lance ethernet interface.
+.Sh RETURN VALUES
+The
+.Fn link_ntoa
+function
+always returns a null terminated string.
+The
+.Fn link_addr
+function
+has no return value.
+(See
+.Sx BUGS . )
+.Sh SEE ALSO
+.Xr getnameinfo 3
+.Sh HISTORY
+The
+.Fn link_addr
+and
+.Fn link_ntoa
+functions appeared in
+.Bx 4.3 Reno .
+.Sh BUGS
+The returned values for link_ntoa
+reside in a static memory area.
+.Pp
+The function
+.Fn link_addr
+should diagnose improperly formed input, and there should be an unambiguous
+way to recognize this.
+.Pp
+If the
+.Va sdl_len
+field of the link socket address
+.Fa sdl
+is 0,
+.Fn link_ntoa
+will not insert a colon before the interface address bytes.
+If this translated address is given to
+.Fn link_addr
+without inserting an initial colon,
+the latter will not interpret it correctly.
diff --git a/lib/libc/net/linkaddr.c b/lib/libc/net/linkaddr.c
new file mode 100644
index 0000000..86bb7a2
--- /dev/null
+++ b/lib/libc/net/linkaddr.c
@@ -0,0 +1,156 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)linkaddr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <net/if_dl.h>
+#include <string.h>
+
+/* States*/
+#define NAMING 0
+#define GOTONE 1
+#define GOTTWO 2
+#define RESET 3
+/* Inputs */
+#define DIGIT (4*0)
+#define END (4*1)
+#define DELIM (4*2)
+#define LETTER (4*3)
+
+void
+link_addr(addr, sdl)
+ const char *addr;
+ struct sockaddr_dl *sdl;
+{
+ char *cp = sdl->sdl_data;
+ char *cplim = sdl->sdl_len + (char *)sdl;
+ int byte = 0, state = NAMING, new;
+
+ bzero((char *)&sdl->sdl_family, sdl->sdl_len - 1);
+ sdl->sdl_family = AF_LINK;
+ do {
+ state &= ~LETTER;
+ if ((*addr >= '0') && (*addr <= '9')) {
+ new = *addr - '0';
+ } else if ((*addr >= 'a') && (*addr <= 'f')) {
+ new = *addr - 'a' + 10;
+ } else if ((*addr >= 'A') && (*addr <= 'F')) {
+ new = *addr - 'A' + 10;
+ } else if (*addr == 0) {
+ state |= END;
+ } else if (state == NAMING &&
+ (((*addr >= 'A') && (*addr <= 'Z')) ||
+ ((*addr >= 'a') && (*addr <= 'z'))))
+ state |= LETTER;
+ else
+ state |= DELIM;
+ addr++;
+ switch (state /* | INPUT */) {
+ case NAMING | DIGIT:
+ case NAMING | LETTER:
+ *cp++ = addr[-1];
+ continue;
+ case NAMING | DELIM:
+ state = RESET;
+ sdl->sdl_nlen = cp - sdl->sdl_data;
+ continue;
+ case GOTTWO | DIGIT:
+ *cp++ = byte;
+ /* FALLTHROUGH */
+ case RESET | DIGIT:
+ state = GOTONE;
+ byte = new;
+ continue;
+ case GOTONE | DIGIT:
+ state = GOTTWO;
+ byte = new + (byte << 4);
+ continue;
+ default: /* | DELIM */
+ state = RESET;
+ *cp++ = byte;
+ byte = 0;
+ continue;
+ case GOTONE | END:
+ case GOTTWO | END:
+ *cp++ = byte;
+ /* FALLTHROUGH */
+ case RESET | END:
+ break;
+ }
+ break;
+ } while (cp < cplim);
+ sdl->sdl_alen = cp - LLADDR(sdl);
+ new = cp - (char *)sdl;
+ if (new > sizeof(*sdl))
+ sdl->sdl_len = new;
+ return;
+}
+
+static char hexlist[] = "0123456789abcdef";
+
+char *
+link_ntoa(sdl)
+ const struct sockaddr_dl *sdl;
+{
+ static char obuf[64];
+ char *out = obuf;
+ int i;
+ u_char *in = (u_char *)LLADDR(sdl);
+ u_char *inlim = in + sdl->sdl_alen;
+ int firsttime = 1;
+
+ if (sdl->sdl_nlen) {
+ bcopy(sdl->sdl_data, obuf, sdl->sdl_nlen);
+ out += sdl->sdl_nlen;
+ if (sdl->sdl_alen)
+ *out++ = ':';
+ }
+ while (in < inlim) {
+ if (firsttime)
+ firsttime = 0;
+ else
+ *out++ = '.';
+ i = *in++;
+ if (i > 0xf) {
+ out[1] = hexlist[i & 0xf];
+ i >>= 4;
+ out[0] = hexlist[i];
+ out += 2;
+ } else
+ *out++ = hexlist[i];
+ }
+ *out = 0;
+ return (obuf);
+}
diff --git a/lib/libc/net/map_v4v6.c b/lib/libc/net/map_v4v6.c
new file mode 100644
index 0000000..dbc7e70
--- /dev/null
+++ b/lib/libc/net/map_v4v6.c
@@ -0,0 +1,119 @@
+/*
+ * ++Copyright++ 1985, 1988, 1993
+ * -
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gethostnamadr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <stdio.h>
+#include <string.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <ctype.h>
+#include <syslog.h>
+
+typedef union {
+ int32_t al;
+ char ac;
+} align;
+
+void
+_map_v4v6_address(const char *src, char *dst)
+{
+ u_char *p = (u_char *)dst;
+ char tmp[NS_INADDRSZ];
+ int i;
+
+ /* Stash a temporary copy so our caller can update in place. */
+ memcpy(tmp, src, NS_INADDRSZ);
+ /* Mark this ipv6 addr as a mapped ipv4. */
+ for (i = 0; i < 10; i++)
+ *p++ = 0x00;
+ *p++ = 0xff;
+ *p++ = 0xff;
+ /* Retrieve the saved copy and we're done. */
+ memcpy((void*)p, tmp, NS_INADDRSZ);
+}
+
+void
+_map_v4v6_hostent(struct hostent *hp, char **bpp, char *ep) {
+ char **ap;
+
+ if (hp->h_addrtype != AF_INET || hp->h_length != INADDRSZ)
+ return;
+ hp->h_addrtype = AF_INET6;
+ hp->h_length = IN6ADDRSZ;
+ for (ap = hp->h_addr_list; *ap; ap++) {
+ int i = (u_long)*bpp % sizeof(align);
+
+ if (i != 0)
+ i = sizeof(align) - i;
+
+ if ((ep - *bpp) < (i + IN6ADDRSZ)) {
+ /* Out of memory. Truncate address list here. */
+ *ap = NULL;
+ return;
+ }
+ *bpp += i;
+ _map_v4v6_address(*ap, *bpp);
+ *ap = *bpp;
+ *bpp += IN6ADDRSZ;
+ }
+}
diff --git a/lib/libc/net/name6.c b/lib/libc/net/name6.c
new file mode 100644
index 0000000..0031f46
--- /dev/null
+++ b/lib/libc/net/name6.c
@@ -0,0 +1,1111 @@
+/* $KAME: name6.c,v 1.25 2000/06/26 16:44:40 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, 1998, and 1999 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * ++Copyright++ 1985, 1988, 1993
+ * -
+ * Copyright (c) 1985, 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * -
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ * -
+ * --Copyright--
+ */
+
+/*
+ * Atsushi Onoe <onoe@sm.sony.co.jp>
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/queue.h>
+#include <netinet/in.h>
+#ifdef INET6
+#include <net/if.h>
+#include <net/if_var.h>
+#include <sys/sysctl.h>
+#include <sys/ioctl.h>
+#include <netinet6/in6_var.h> /* XXX */
+#endif
+
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <stdarg.h>
+#include <nsswitch.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "netdb_private.h"
+#include "res_private.h"
+
+#ifndef MAXALIASES
+#define MAXALIASES 10
+#endif
+#ifndef MAXADDRS
+#define MAXADDRS 20
+#endif
+#ifndef MAXDNAME
+#define MAXDNAME 1025
+#endif
+
+#ifdef INET6
+#define ADDRLEN(af) ((af) == AF_INET6 ? sizeof(struct in6_addr) : \
+ sizeof(struct in_addr))
+#else
+#define ADDRLEN(af) sizeof(struct in_addr)
+#endif
+
+#define MAPADDR(ab, ina) \
+do { \
+ memcpy(&(ab)->map_inaddr, ina, sizeof(struct in_addr)); \
+ memset((ab)->map_zero, 0, sizeof((ab)->map_zero)); \
+ memset((ab)->map_one, 0xff, sizeof((ab)->map_one)); \
+} while (0)
+#define MAPADDRENABLED(flags) \
+ (((flags) & AI_V4MAPPED) || \
+ (((flags) & AI_V4MAPPED_CFG)))
+
+union inx_addr {
+ struct in_addr in_addr;
+#ifdef INET6
+ struct in6_addr in6_addr;
+#endif
+ struct {
+ u_char mau_zero[10];
+ u_char mau_one[2];
+ struct in_addr mau_inaddr;
+ } map_addr_un;
+#define map_zero map_addr_un.mau_zero
+#define map_one map_addr_un.mau_one
+#define map_inaddr map_addr_un.mau_inaddr
+};
+
+struct policyqueue {
+ TAILQ_ENTRY(policyqueue) pc_entry;
+#ifdef INET6
+ struct in6_addrpolicy pc_policy;
+#endif
+};
+TAILQ_HEAD(policyhead, policyqueue);
+
+#define AIO_SRCFLAG_DEPRECATED 0x1
+
+struct hp_order {
+ union {
+ struct sockaddr_storage aiou_ss;
+ struct sockaddr aiou_sa;
+ } aio_src_un;
+#define aio_srcsa aio_src_un.aiou_sa
+ u_int32_t aio_srcflag;
+ int aio_srcscope;
+ int aio_dstscope;
+ struct policyqueue *aio_srcpolicy;
+ struct policyqueue *aio_dstpolicy;
+ union {
+ struct sockaddr_storage aiou_ss;
+ struct sockaddr aiou_sa;
+ } aio_un;
+#define aio_sa aio_un.aiou_sa
+ int aio_matchlen;
+ char *aio_h_addr;
+};
+
+static struct hostent *_hpcopy(struct hostent *, int *);
+static struct hostent *_hpaddr(int, const char *, void *, int *);
+#ifdef INET6
+static struct hostent *_hpmerge(struct hostent *, struct hostent *, int *);
+static struct hostent *_hpmapv6(struct hostent *, int *);
+#endif
+static struct hostent *_hpsort(struct hostent *, res_state);
+
+static struct hostent *_hpreorder(struct hostent *);
+static int get_addrselectpolicy(struct policyhead *);
+static void free_addrselectpolicy(struct policyhead *);
+static struct policyqueue *match_addrselectpolicy(struct sockaddr *,
+ struct policyhead *);
+static void set_source(struct hp_order *, struct policyhead *);
+static int matchlen(struct sockaddr *, struct sockaddr *);
+static int comp_dst(const void *, const void *);
+static int gai_addr2scopetype(struct sockaddr *);
+
+/*
+ * Functions defined in RFC2553
+ * getipnodebyname, getipnodebyaddr, freehostent
+ */
+
+struct hostent *
+getipnodebyname(const char *name, int af, int flags, int *errp)
+{
+ struct hostent *hp;
+ union inx_addr addrbuf;
+ res_state statp;
+ u_long options;
+
+ switch (af) {
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
+ break;
+ default:
+ *errp = NO_RECOVERY;
+ return NULL;
+ }
+
+ if (flags & AI_ADDRCONFIG) {
+ int s;
+
+ if ((s = _socket(af, SOCK_DGRAM, 0)) < 0)
+ return NULL;
+ /*
+ * TODO:
+ * Note that implementation dependent test for address
+ * configuration should be done everytime called
+ * (or apropriate interval),
+ * because addresses will be dynamically assigned or deleted.
+ */
+ _close(s);
+ }
+
+#ifdef INET6
+ /* special case for literal address */
+ if (inet_pton(AF_INET6, name, &addrbuf) == 1) {
+ if (af != AF_INET6) {
+ *errp = HOST_NOT_FOUND;
+ return NULL;
+ }
+ return _hpaddr(af, name, &addrbuf, errp);
+ }
+#endif
+ if (inet_aton(name, (struct in_addr *)&addrbuf) == 1) {
+ if (af != AF_INET) {
+ if (MAPADDRENABLED(flags)) {
+ MAPADDR(&addrbuf, &addrbuf.in_addr);
+ } else {
+ *errp = HOST_NOT_FOUND;
+ return NULL;
+ }
+ }
+ return _hpaddr(af, name, &addrbuf, errp);
+ }
+
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0) {
+ if (res_ninit(statp) < 0) {
+ *errp = NETDB_INTERNAL;
+ return NULL;
+ }
+ }
+
+ options = statp->options;
+ statp->options &= ~RES_USE_INET6;
+
+ hp = gethostbyname2(name, af);
+ hp = _hpcopy(hp, errp);
+
+#ifdef INET6
+ if (af == AF_INET6 && ((flags & AI_ALL) || hp == NULL) &&
+ MAPADDRENABLED(flags)) {
+ struct hostent *hp2 = gethostbyname2(name, AF_INET);
+ if (hp == NULL)
+ if (hp2 == NULL)
+ *errp = statp->res_h_errno;
+ else
+ hp = _hpmapv6(hp2, errp);
+ else {
+ if (hp2 && strcmp(hp->h_name, hp2->h_name) == 0) {
+ struct hostent *hpb = hp;
+ hp = _hpmerge(hpb, hp2, errp);
+ freehostent(hpb);
+ }
+ }
+ }
+#endif
+
+ if (hp == NULL)
+ *errp = statp->res_h_errno;
+
+ statp->options = options;
+ return _hpreorder(_hpsort(hp, statp));
+}
+
+struct hostent *
+getipnodebyaddr(const void *src, size_t len, int af, int *errp)
+{
+ struct hostent *hp;
+ res_state statp;
+ u_long options;
+
+#ifdef INET6
+ struct in6_addr addrbuf;
+#else
+ struct in_addr addrbuf;
+#endif
+
+ switch (af) {
+ case AF_INET:
+ if (len != sizeof(struct in_addr)) {
+ *errp = NO_RECOVERY;
+ return NULL;
+ }
+ if ((long)src & ~(sizeof(struct in_addr) - 1)) {
+ memcpy(&addrbuf, src, len);
+ src = &addrbuf;
+ }
+ if (((struct in_addr *)src)->s_addr == 0)
+ return NULL;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (len != sizeof(struct in6_addr)) {
+ *errp = NO_RECOVERY;
+ return NULL;
+ }
+ if ((long)src & ~(sizeof(struct in6_addr) / 2 - 1)) { /*XXX*/
+ memcpy(&addrbuf, src, len);
+ src = &addrbuf;
+ }
+ if (IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *)src))
+ return NULL;
+ if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)src)
+ || IN6_IS_ADDR_V4COMPAT((struct in6_addr *)src)) {
+ src = (char *)src +
+ (sizeof(struct in6_addr) - sizeof(struct in_addr));
+ af = AF_INET;
+ len = sizeof(struct in_addr);
+ }
+ break;
+#endif
+ default:
+ *errp = NO_RECOVERY;
+ return NULL;
+ }
+
+ statp = __res_state();
+ if ((statp->options & RES_INIT) == 0) {
+ if (res_ninit(statp) < 0) {
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ return NULL;
+ }
+ }
+
+ options = statp->options;
+ statp->options &= ~RES_USE_INET6;
+
+ hp = gethostbyaddr(src, len, af);
+ if (hp == NULL)
+ *errp = statp->res_h_errno;
+
+ statp->options = options;
+ return (_hpcopy(hp, errp));
+}
+
+void
+freehostent(struct hostent *ptr)
+{
+ free(ptr);
+}
+
+/*
+ * Private utility functions
+ */
+
+/*
+ * _hpcopy: allocate and copy hostent structure
+ */
+static struct hostent *
+_hpcopy(struct hostent *hp, int *errp)
+{
+ struct hostent *nhp;
+ char *cp, **pp;
+ int size, addrsize;
+ int nalias = 0, naddr = 0;
+ int al_off;
+ int i;
+
+ if (hp == NULL)
+ return hp;
+
+ /* count size to be allocated */
+ size = sizeof(struct hostent);
+ if (hp->h_name != NULL)
+ size += strlen(hp->h_name) + 1;
+ if ((pp = hp->h_aliases) != NULL) {
+ for (i = 0; *pp != NULL; i++, pp++) {
+ if (**pp != '\0') {
+ size += strlen(*pp) + 1;
+ nalias++;
+ }
+ }
+ }
+ /* adjust alignment */
+ size = ALIGN(size);
+ al_off = size;
+ size += sizeof(char *) * (nalias + 1);
+ addrsize = ALIGN(hp->h_length);
+ if ((pp = hp->h_addr_list) != NULL) {
+ while (*pp++ != NULL)
+ naddr++;
+ }
+ size += addrsize * naddr;
+ size += sizeof(char *) * (naddr + 1);
+
+ /* copy */
+ if ((nhp = (struct hostent *)malloc(size)) == NULL) {
+ *errp = TRY_AGAIN;
+ return NULL;
+ }
+ cp = (char *)&nhp[1];
+ if (hp->h_name != NULL) {
+ nhp->h_name = cp;
+ strcpy(cp, hp->h_name);
+ cp += strlen(cp) + 1;
+ } else
+ nhp->h_name = NULL;
+ nhp->h_aliases = (char **)((char *)nhp + al_off);
+ if ((pp = hp->h_aliases) != NULL) {
+ for (i = 0; *pp != NULL; pp++) {
+ if (**pp != '\0') {
+ nhp->h_aliases[i++] = cp;
+ strcpy(cp, *pp);
+ cp += strlen(cp) + 1;
+ }
+ }
+ }
+ nhp->h_aliases[nalias] = NULL;
+ cp = (char *)&nhp->h_aliases[nalias + 1];
+ nhp->h_addrtype = hp->h_addrtype;
+ nhp->h_length = hp->h_length;
+ nhp->h_addr_list = (char **)cp;
+ if ((pp = hp->h_addr_list) != NULL) {
+ cp = (char *)&nhp->h_addr_list[naddr + 1];
+ for (i = 0; *pp != NULL; pp++) {
+ nhp->h_addr_list[i++] = cp;
+ memcpy(cp, *pp, hp->h_length);
+ cp += addrsize;
+ }
+ }
+ nhp->h_addr_list[naddr] = NULL;
+ return nhp;
+}
+
+/*
+ * _hpaddr: construct hostent structure with one address
+ */
+static struct hostent *
+_hpaddr(int af, const char *name, void *addr, int *errp)
+{
+ struct hostent *hp, hpbuf;
+ char *addrs[2];
+
+ hp = &hpbuf;
+ hp->h_name = (char *)name;
+ hp->h_aliases = NULL;
+ hp->h_addrtype = af;
+ hp->h_length = ADDRLEN(af);
+ hp->h_addr_list = addrs;
+ addrs[0] = (char *)addr;
+ addrs[1] = NULL;
+ return (_hpcopy(hp, errp));
+}
+
+#ifdef INET6
+/*
+ * _hpmerge: merge 2 hostent structure, arguments will be freed
+ */
+static struct hostent *
+_hpmerge(struct hostent *hp1, struct hostent *hp2, int *errp)
+{
+ int i, j;
+ int naddr, nalias;
+ char **pp;
+ struct hostent *hp, hpbuf;
+ char *aliases[MAXALIASES + 1], *addrs[MAXADDRS + 1];
+ union inx_addr addrbuf[MAXADDRS];
+
+ if (hp1 == NULL)
+ return _hpcopy(hp2, errp);
+ if (hp2 == NULL)
+ return _hpcopy(hp1, errp);
+
+#define HP(i) (i == 1 ? hp1 : hp2)
+ hp = &hpbuf;
+ hp->h_name = (hp1->h_name != NULL ? hp1->h_name : hp2->h_name);
+ hp->h_aliases = aliases;
+ nalias = 0;
+ for (i = 1; i <= 2; i++) {
+ if ((pp = HP(i)->h_aliases) == NULL)
+ continue;
+ for (; nalias < MAXALIASES && *pp != NULL; pp++) {
+ /* check duplicates */
+ for (j = 0; j < nalias; j++)
+ if (strcasecmp(*pp, aliases[j]) == 0)
+ break;
+ if (j == nalias)
+ aliases[nalias++] = *pp;
+ }
+ }
+ aliases[nalias] = NULL;
+ if (hp1->h_length != hp2->h_length) {
+ hp->h_addrtype = AF_INET6;
+ hp->h_length = sizeof(struct in6_addr);
+ } else {
+ hp->h_addrtype = hp1->h_addrtype;
+ hp->h_length = hp1->h_length;
+ }
+
+ hp->h_addr_list = addrs;
+ naddr = 0;
+ for (i = 1; i <= 2; i++) {
+ if ((pp = HP(i)->h_addr_list) == NULL)
+ continue;
+ if (HP(i)->h_length == hp->h_length) {
+ while (naddr < MAXADDRS && *pp != NULL)
+ addrs[naddr++] = *pp++;
+ } else {
+ /* copy IPv4 addr as mapped IPv6 addr */
+ while (naddr < MAXADDRS && *pp != NULL) {
+ MAPADDR(&addrbuf[naddr], *pp++);
+ addrs[naddr] = (char *)&addrbuf[naddr];
+ naddr++;
+ }
+ }
+ }
+ addrs[naddr] = NULL;
+ return (_hpcopy(hp, errp));
+}
+#endif
+
+/*
+ * _hpmapv6: convert IPv4 hostent into IPv4-mapped IPv6 addresses
+ */
+#ifdef INET6
+static struct hostent *
+_hpmapv6(struct hostent *hp, int *errp)
+{
+ struct hostent hp6;
+
+ if (hp == NULL)
+ return NULL;
+ if (hp->h_addrtype == AF_INET6)
+ return _hpcopy(hp, errp);
+
+ memset(&hp6, 0, sizeof(struct hostent));
+ hp6.h_addrtype = AF_INET6;
+ hp6.h_length = sizeof(struct in6_addr);
+ return _hpmerge(&hp6, hp, errp);
+}
+#endif
+
+/*
+ * _hpsort: sort address by sortlist
+ */
+static struct hostent *
+_hpsort(struct hostent *hp, res_state statp)
+{
+ int i, j, n;
+ u_char *ap, *sp, *mp, **pp;
+ char t;
+ char order[MAXADDRS];
+ int nsort = statp->nsort;
+
+ if (hp == NULL || hp->h_addr_list[1] == NULL || nsort == 0)
+ return hp;
+ for (i = 0; (ap = (u_char *)hp->h_addr_list[i]); i++) {
+ for (j = 0; j < nsort; j++) {
+#ifdef INET6
+ if (statp->_u._ext.ext->sort_list[j].af !=
+ hp->h_addrtype)
+ continue;
+ sp = (u_char *)&statp->_u._ext.ext->sort_list[j].addr;
+ mp = (u_char *)&statp->_u._ext.ext->sort_list[j].mask;
+#else
+ sp = (u_char *)&statp->sort_list[j].addr;
+ mp = (u_char *)&statp->sort_list[j].mask;
+#endif
+ for (n = 0; n < hp->h_length; n++) {
+ if ((ap[n] & mp[n]) != sp[n])
+ break;
+ }
+ if (n == hp->h_length)
+ break;
+ }
+ order[i] = j;
+ }
+ n = i;
+ pp = (u_char **)hp->h_addr_list;
+ for (i = 0; i < n - 1; i++) {
+ for (j = i + 1; j < n; j++) {
+ if (order[i] > order[j]) {
+ ap = pp[i];
+ pp[i] = pp[j];
+ pp[j] = ap;
+ t = order[i];
+ order[i] = order[j];
+ order[j] = t;
+ }
+ }
+ }
+ return hp;
+}
+
+/*
+ * _hpreorder: sort address by default address selection
+ */
+static struct hostent *
+_hpreorder(struct hostent *hp)
+{
+ struct hp_order *aio;
+ int i, n;
+ char *ap;
+ struct sockaddr *sa;
+ struct policyhead policyhead;
+
+ if (hp == NULL)
+ return hp;
+
+ switch (hp->h_addrtype) {
+ case AF_INET:
+#ifdef INET6
+ case AF_INET6:
+#endif
+ break;
+ default:
+ free_addrselectpolicy(&policyhead);
+ return hp;
+ }
+
+ /* count the number of addrinfo elements for sorting. */
+ for (n = 0; hp->h_addr_list[n] != NULL; n++)
+ ;
+
+ /*
+ * If the number is small enough, we can skip the reordering process.
+ */
+ if (n <= 1)
+ return hp;
+
+ /* allocate a temporary array for sort and initialization of it. */
+ if ((aio = malloc(sizeof(*aio) * n)) == NULL)
+ return hp; /* give up reordering */
+ memset(aio, 0, sizeof(*aio) * n);
+
+ /* retrieve address selection policy from the kernel */
+ TAILQ_INIT(&policyhead);
+ if (!get_addrselectpolicy(&policyhead)) {
+ /* no policy is installed into kernel, we don't sort. */
+ free(aio);
+ return hp;
+ }
+
+ for (i = 0; i < n; i++) {
+ ap = hp->h_addr_list[i];
+ aio[i].aio_h_addr = ap;
+ sa = &aio[i].aio_sa;
+ switch (hp->h_addrtype) {
+ case AF_INET:
+ sa->sa_family = AF_INET;
+ sa->sa_len = sizeof(struct sockaddr_in);
+ memcpy(&((struct sockaddr_in *)sa)->sin_addr, ap,
+ sizeof(struct in_addr));
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (IN6_IS_ADDR_V4MAPPED((struct in6_addr *)ap)) {
+ sa->sa_family = AF_INET;
+ sa->sa_len = sizeof(struct sockaddr_in);
+ memcpy(&((struct sockaddr_in *)sa)->sin_addr,
+ &ap[12], sizeof(struct in_addr));
+ } else {
+ sa->sa_family = AF_INET6;
+ sa->sa_len = sizeof(struct sockaddr_in6);
+ memcpy(&((struct sockaddr_in6 *)sa)->sin6_addr,
+ ap, sizeof(struct in6_addr));
+ }
+ break;
+#endif
+ }
+ aio[i].aio_dstscope = gai_addr2scopetype(sa);
+ aio[i].aio_dstpolicy = match_addrselectpolicy(sa, &policyhead);
+ set_source(&aio[i], &policyhead);
+ }
+
+ /* perform sorting. */
+ qsort(aio, n, sizeof(*aio), comp_dst);
+
+ /* reorder the h_addr_list. */
+ for (i = 0; i < n; i++)
+ hp->h_addr_list[i] = aio[i].aio_h_addr;
+
+ /* cleanup and return */
+ free(aio);
+ free_addrselectpolicy(&policyhead);
+ return hp;
+}
+
+static int
+get_addrselectpolicy(struct policyhead *head)
+{
+#ifdef INET6
+ int mib[] = { CTL_NET, PF_INET6, IPPROTO_IPV6, IPV6CTL_ADDRCTLPOLICY };
+ size_t l;
+ char *buf;
+ struct in6_addrpolicy *pol, *ep;
+
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), NULL, &l, NULL, 0) < 0)
+ return (0);
+ if ((buf = malloc(l)) == NULL)
+ return (0);
+ if (sysctl(mib, sizeof(mib) / sizeof(mib[0]), buf, &l, NULL, 0) < 0) {
+ free(buf);
+ return (0);
+ }
+
+ ep = (struct in6_addrpolicy *)(buf + l);
+ for (pol = (struct in6_addrpolicy *)buf; pol + 1 <= ep; pol++) {
+ struct policyqueue *new;
+
+ if ((new = malloc(sizeof(*new))) == NULL) {
+ free_addrselectpolicy(head); /* make the list empty */
+ break;
+ }
+ new->pc_policy = *pol;
+ TAILQ_INSERT_TAIL(head, new, pc_entry);
+ }
+
+ free(buf);
+ return (1);
+#else
+ return (0);
+#endif
+}
+
+static void
+free_addrselectpolicy(struct policyhead *head)
+{
+ struct policyqueue *ent, *nent;
+
+ for (ent = TAILQ_FIRST(head); ent; ent = nent) {
+ nent = TAILQ_NEXT(ent, pc_entry);
+ TAILQ_REMOVE(head, ent, pc_entry);
+ free(ent);
+ }
+}
+
+static struct policyqueue *
+match_addrselectpolicy(struct sockaddr *addr, struct policyhead *head)
+{
+#ifdef INET6
+ struct policyqueue *ent, *bestent = NULL;
+ struct in6_addrpolicy *pol;
+ int matchlen, bestmatchlen = -1;
+ u_char *mp, *ep, *k, *p, m;
+ struct sockaddr_in6 key;
+
+ switch(addr->sa_family) {
+ case AF_INET6:
+ key = *(struct sockaddr_in6 *)addr;
+ break;
+ case AF_INET:
+ /* convert the address into IPv4-mapped IPv6 address. */
+ memset(&key, 0, sizeof(key));
+ key.sin6_family = AF_INET6;
+ key.sin6_len = sizeof(key);
+ key.sin6_addr.s6_addr[10] = 0xff;
+ key.sin6_addr.s6_addr[11] = 0xff;
+ memcpy(&key.sin6_addr.s6_addr[12],
+ &((struct sockaddr_in *)addr)->sin_addr, 4);
+ break;
+ default:
+ return(NULL);
+ }
+
+ for (ent = TAILQ_FIRST(head); ent; ent = TAILQ_NEXT(ent, pc_entry)) {
+ pol = &ent->pc_policy;
+ matchlen = 0;
+
+ mp = (u_char *)&pol->addrmask.sin6_addr;
+ ep = mp + 16; /* XXX: scope field? */
+ k = (u_char *)&key.sin6_addr;
+ p = (u_char *)&pol->addr.sin6_addr;
+ for (; mp < ep && *mp; mp++, k++, p++) {
+ m = *mp;
+ if ((*k & m) != *p)
+ goto next; /* not match */
+ if (m == 0xff) /* short cut for a typical case */
+ matchlen += 8;
+ else {
+ while (m >= 0x80) {
+ matchlen++;
+ m <<= 1;
+ }
+ }
+ }
+
+ /* matched. check if this is better than the current best. */
+ if (matchlen > bestmatchlen) {
+ bestent = ent;
+ bestmatchlen = matchlen;
+ }
+
+ next:
+ continue;
+ }
+
+ return(bestent);
+#else
+ return(NULL);
+#endif
+
+}
+
+static void
+set_source(struct hp_order *aio, struct policyhead *ph)
+{
+ struct sockaddr_storage ss = aio->aio_un.aiou_ss;
+ socklen_t srclen;
+ int s;
+
+ /* set unspec ("no source is available"), just in case */
+ aio->aio_srcsa.sa_family = AF_UNSPEC;
+ aio->aio_srcscope = -1;
+
+ switch(ss.ss_family) {
+ case AF_INET:
+ ((struct sockaddr_in *)&ss)->sin_port = htons(1);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ((struct sockaddr_in6 *)&ss)->sin6_port = htons(1);
+ break;
+#endif
+ default: /* ignore unsupported AFs explicitly */
+ return;
+ }
+
+ /* open a socket to get the source address for the given dst */
+ if ((s = _socket(ss.ss_family, SOCK_DGRAM, IPPROTO_UDP)) < 0)
+ return; /* give up */
+ if (_connect(s, (struct sockaddr *)&ss, ss.ss_len) < 0)
+ goto cleanup;
+ srclen = ss.ss_len;
+ if (_getsockname(s, &aio->aio_srcsa, &srclen) < 0) {
+ aio->aio_srcsa.sa_family = AF_UNSPEC;
+ goto cleanup;
+ }
+ aio->aio_srcscope = gai_addr2scopetype(&aio->aio_srcsa);
+ aio->aio_srcpolicy = match_addrselectpolicy(&aio->aio_srcsa, ph);
+ aio->aio_matchlen = matchlen(&aio->aio_srcsa, (struct sockaddr *)&ss);
+#ifdef INET6
+ if (ss.ss_family == AF_INET6) {
+ struct in6_ifreq ifr6;
+ u_int32_t flags6;
+
+ memset(&ifr6, 0, sizeof(ifr6));
+ memcpy(&ifr6.ifr_addr, &ss, ss.ss_len);
+ if (_ioctl(s, SIOCGIFAFLAG_IN6, &ifr6) == 0) {
+ flags6 = ifr6.ifr_ifru.ifru_flags6;
+ if ((flags6 & IN6_IFF_DEPRECATED))
+ aio->aio_srcflag |= AIO_SRCFLAG_DEPRECATED;
+ }
+ }
+#endif
+
+ cleanup:
+ _close(s);
+ return;
+}
+
+static int
+matchlen(struct sockaddr *src, struct sockaddr *dst)
+{
+ int match = 0;
+ u_char *s, *d;
+ u_char *lim, r;
+ int addrlen;
+
+ switch (src->sa_family) {
+#ifdef INET6
+ case AF_INET6:
+ s = (u_char *)&((struct sockaddr_in6 *)src)->sin6_addr;
+ d = (u_char *)&((struct sockaddr_in6 *)dst)->sin6_addr;
+ addrlen = sizeof(struct in6_addr);
+ lim = s + addrlen;
+ break;
+#endif
+ case AF_INET:
+ s = (u_char *)&((struct sockaddr_in *)src)->sin_addr;
+ d = (u_char *)&((struct sockaddr_in *)dst)->sin_addr;
+ addrlen = sizeof(struct in_addr);
+ lim = s + addrlen;
+ break;
+ default:
+ return(0);
+ }
+
+ while (s < lim)
+ if ((r = (*d++ ^ *s++)) != 0) {
+ while (r < addrlen * 8) {
+ match++;
+ r <<= 1;
+ }
+ break;
+ } else
+ match += 8;
+ return(match);
+}
+
+static int
+comp_dst(const void *arg1, const void *arg2)
+{
+ const struct hp_order *dst1 = arg1, *dst2 = arg2;
+
+ /*
+ * Rule 1: Avoid unusable destinations.
+ * XXX: we currently do not consider if an appropriate route exists.
+ */
+ if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
+ dst2->aio_srcsa.sa_family == AF_UNSPEC) {
+ return(-1);
+ }
+ if (dst1->aio_srcsa.sa_family == AF_UNSPEC &&
+ dst2->aio_srcsa.sa_family != AF_UNSPEC) {
+ return(1);
+ }
+
+ /* Rule 2: Prefer matching scope. */
+ if (dst1->aio_dstscope == dst1->aio_srcscope &&
+ dst2->aio_dstscope != dst2->aio_srcscope) {
+ return(-1);
+ }
+ if (dst1->aio_dstscope != dst1->aio_srcscope &&
+ dst2->aio_dstscope == dst2->aio_srcscope) {
+ return(1);
+ }
+
+ /* Rule 3: Avoid deprecated addresses. */
+ if (dst1->aio_srcsa.sa_family != AF_UNSPEC &&
+ dst2->aio_srcsa.sa_family != AF_UNSPEC) {
+ if (!(dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
+ (dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
+ return(-1);
+ }
+ if ((dst1->aio_srcflag & AIO_SRCFLAG_DEPRECATED) &&
+ !(dst2->aio_srcflag & AIO_SRCFLAG_DEPRECATED)) {
+ return(1);
+ }
+ }
+
+ /* Rule 4: Prefer home addresses. */
+ /* XXX: not implemented yet */
+
+ /* Rule 5: Prefer matching label. */
+#ifdef INET6
+ if (dst1->aio_srcpolicy && dst1->aio_dstpolicy &&
+ dst1->aio_srcpolicy->pc_policy.label ==
+ dst1->aio_dstpolicy->pc_policy.label &&
+ (dst2->aio_srcpolicy == NULL || dst2->aio_dstpolicy == NULL ||
+ dst2->aio_srcpolicy->pc_policy.label !=
+ dst2->aio_dstpolicy->pc_policy.label)) {
+ return(-1);
+ }
+ if (dst2->aio_srcpolicy && dst2->aio_dstpolicy &&
+ dst2->aio_srcpolicy->pc_policy.label ==
+ dst2->aio_dstpolicy->pc_policy.label &&
+ (dst1->aio_srcpolicy == NULL || dst1->aio_dstpolicy == NULL ||
+ dst1->aio_srcpolicy->pc_policy.label !=
+ dst1->aio_dstpolicy->pc_policy.label)) {
+ return(1);
+ }
+#endif
+
+ /* Rule 6: Prefer higher precedence. */
+#ifdef INET6
+ if (dst1->aio_dstpolicy &&
+ (dst2->aio_dstpolicy == NULL ||
+ dst1->aio_dstpolicy->pc_policy.preced >
+ dst2->aio_dstpolicy->pc_policy.preced)) {
+ return(-1);
+ }
+ if (dst2->aio_dstpolicy &&
+ (dst1->aio_dstpolicy == NULL ||
+ dst2->aio_dstpolicy->pc_policy.preced >
+ dst1->aio_dstpolicy->pc_policy.preced)) {
+ return(1);
+ }
+#endif
+
+ /* Rule 7: Prefer native transport. */
+ /* XXX: not implemented yet */
+
+ /* Rule 8: Prefer smaller scope. */
+ if (dst1->aio_dstscope >= 0 &&
+ dst1->aio_dstscope < dst2->aio_dstscope) {
+ return(-1);
+ }
+ if (dst2->aio_dstscope >= 0 &&
+ dst2->aio_dstscope < dst1->aio_dstscope) {
+ return(1);
+ }
+
+ /*
+ * Rule 9: Use longest matching prefix.
+ * We compare the match length in a same AF only.
+ */
+ if (dst1->aio_sa.sa_family == dst2->aio_sa.sa_family) {
+ if (dst1->aio_matchlen > dst2->aio_matchlen) {
+ return(-1);
+ }
+ if (dst1->aio_matchlen < dst2->aio_matchlen) {
+ return(1);
+ }
+ }
+
+ /* Rule 10: Otherwise, leave the order unchanged. */
+ return(-1);
+}
+
+/*
+ * Copy from scope.c.
+ * XXX: we should standardize the functions and link them as standard
+ * library.
+ */
+static int
+gai_addr2scopetype(struct sockaddr *sa)
+{
+#ifdef INET6
+ struct sockaddr_in6 *sa6;
+#endif
+ struct sockaddr_in *sa4;
+
+ switch(sa->sa_family) {
+#ifdef INET6
+ case AF_INET6:
+ sa6 = (struct sockaddr_in6 *)sa;
+ if (IN6_IS_ADDR_MULTICAST(&sa6->sin6_addr)) {
+ /* just use the scope field of the multicast address */
+ return(sa6->sin6_addr.s6_addr[2] & 0x0f);
+ }
+ /*
+ * Unicast addresses: map scope type to corresponding scope
+ * value defined for multcast addresses.
+ * XXX: hardcoded scope type values are bad...
+ */
+ if (IN6_IS_ADDR_LOOPBACK(&sa6->sin6_addr))
+ return(1); /* node local scope */
+ if (IN6_IS_ADDR_LINKLOCAL(&sa6->sin6_addr))
+ return(2); /* link-local scope */
+ if (IN6_IS_ADDR_SITELOCAL(&sa6->sin6_addr))
+ return(5); /* site-local scope */
+ return(14); /* global scope */
+ break;
+#endif
+ case AF_INET:
+ /*
+ * IPv4 pseudo scoping according to RFC 3484.
+ */
+ sa4 = (struct sockaddr_in *)sa;
+ /* IPv4 autoconfiguration addresses have link-local scope. */
+ if (((u_char *)&sa4->sin_addr)[0] == 169 &&
+ ((u_char *)&sa4->sin_addr)[1] == 254)
+ return(2);
+ /* Private addresses have site-local scope. */
+ if (((u_char *)&sa4->sin_addr)[0] == 10 ||
+ (((u_char *)&sa4->sin_addr)[0] == 172 &&
+ (((u_char *)&sa4->sin_addr)[1] & 0xf0) == 16) ||
+ (((u_char *)&sa4->sin_addr)[0] == 192 &&
+ ((u_char *)&sa4->sin_addr)[1] == 168))
+ return(14); /* XXX: It should be 5 unless NAT */
+ /* Loopback addresses have link-local scope. */
+ if (((u_char *)&sa4->sin_addr)[0] == 127)
+ return(2);
+ return(14);
+ break;
+ default:
+ errno = EAFNOSUPPORT; /* is this a good error? */
+ return(-1);
+ }
+}
diff --git a/lib/libc/net/netdb_private.h b/lib/libc/net/netdb_private.h
new file mode 100644
index 0000000..b48dd7b
--- /dev/null
+++ b/lib/libc/net/netdb_private.h
@@ -0,0 +1,145 @@
+/*-
+ * Copyright (C) 2005 The FreeBSD Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _NETDB_PRIVATE_H_
+#define _NETDB_PRIVATE_H_
+
+#include <stdio.h> /* XXX: for FILE */
+
+#define NETDB_THREAD_ALLOC(name) \
+static struct name name; \
+static thread_key_t name##_key; \
+static once_t name##_init_once = ONCE_INITIALIZER; \
+static int name##_thr_keycreated = 0; \
+\
+static void name##_free(void *); \
+\
+static void \
+name##_keycreate(void) \
+{ \
+ name##_thr_keycreated = \
+ (thr_keycreate(&name##_key, name##_free) == 0); \
+} \
+\
+struct name * \
+__##name##_init(void) \
+{ \
+ struct name *he; \
+ \
+ if (thr_main() != 0) \
+ return (&name); \
+ if (thr_once(&name##_init_once, name##_keycreate) != 0 || \
+ !name##_thr_keycreated) \
+ return (NULL); \
+ if ((he = thr_getspecific(name##_key)) != NULL) \
+ return (he); \
+ if ((he = calloc(1, sizeof(*he))) == NULL) \
+ return (NULL); \
+ if (thr_setspecific(name##_key, he) == 0) \
+ return (he); \
+ free(he); \
+ return (NULL); \
+}
+
+#define _MAXALIASES 35
+#define _MAXLINELEN 1024
+#define _MAXADDRS 35
+#define _HOSTBUFSIZE (8 * 1024)
+#define _NETBUFSIZE 1025
+
+struct hostent_data {
+ uint32_t host_addr[4]; /* IPv4 or IPv6 */
+ char *h_addr_ptrs[_MAXADDRS + 1];
+ char *host_aliases[_MAXALIASES];
+ char hostbuf[_HOSTBUFSIZE];
+ FILE *hostf;
+ int stayopen;
+#ifdef YP
+ char *yp_domain;
+#endif
+};
+
+struct netent_data {
+ char *net_aliases[_MAXALIASES];
+ char netbuf[_NETBUFSIZE];
+ FILE *netf;
+ int stayopen;
+#ifdef YP
+ char *yp_domain;
+#endif
+};
+
+struct protoent_data {
+ FILE *fp;
+ char *aliases[_MAXALIASES];
+ int stayopen;
+ char line[_MAXLINELEN + 1];
+};
+
+struct hostdata {
+ struct hostent host;
+ char data[sizeof(struct hostent_data)];
+};
+
+struct netdata {
+ struct netent net;
+ char data[sizeof(struct netent_data)];
+};
+
+struct protodata {
+ struct protoent proto;
+ char data[sizeof(struct protoent_data)];
+};
+
+struct hostdata *__hostdata_init(void);
+struct hostent *__hostent_init(void);
+struct hostent_data *__hostent_data_init(void);
+struct netdata *__netdata_init(void);
+struct netent_data *__netent_data_init(void);
+struct protodata *__protodata_init(void);
+struct protoent_data *__protoent_data_init(void);
+int __copy_hostent(struct hostent *, struct hostent *, char *, size_t);
+int __copy_netent(struct netent *, struct netent *, char *, size_t);
+int __copy_protoent(struct protoent *, struct protoent *, char *, size_t);
+
+void __endprotoent_p(struct protoent_data *);
+int __getprotoent_p(struct protoent *, struct protoent_data *);
+void __setprotoent_p(int, struct protoent_data *);
+void _endhostdnsent(void);
+void _endhosthtent(struct hostent_data *);
+void _endnetdnsent(void);
+void _endnethtent(struct netent_data *);
+struct hostent *_gethostbynisaddr(const void *, socklen_t, int);
+struct hostent *_gethostbynisname(const char *, int);
+void _map_v4v6_address(const char *, char *);
+void _map_v4v6_hostent(struct hostent *, char **, char *);
+void _sethostdnsent(int);
+void _sethosthtent(int, struct hostent_data *);
+void _setnetdnsent(int);
+void _setnethtent(int, struct netent_data *);
+
+#endif /* _NETDB_PRIVATE_H_ */
diff --git a/lib/libc/net/nscache.c b/lib/libc/net/nscache.c
new file mode 100644
index 0000000..68cec21
--- /dev/null
+++ b/lib/libc/net/nscache.c
@@ -0,0 +1,438 @@
+/*-
+ * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <nsswitch.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "nscachedcli.h"
+#include "nscache.h"
+
+#define NSS_CACHE_KEY_INITIAL_SIZE (256)
+#define NSS_CACHE_KEY_SIZE_LIMIT (NSS_CACHE_KEY_INITIAL_SIZE << 4)
+
+#define NSS_CACHE_BUFFER_INITIAL_SIZE (1024)
+#define NSS_CACHE_BUFFER_SIZE_LIMIT (NSS_CACHE_BUFFER_INITIAL_SIZE << 8)
+
+#define CACHED_SOCKET_PATH "/var/run/nscd"
+
+int
+__nss_cache_handler(void *retval, void *mdata, va_list ap)
+{
+ return (NS_UNAVAIL);
+}
+
+int
+__nss_common_cache_read(void *retval, void *mdata, va_list ap)
+{
+ struct cached_connection_params params;
+ cached_connection connection;
+
+ char *buffer;
+ size_t buffer_size, size;
+
+ nss_cache_info const *cache_info;
+ nss_cache_data *cache_data;
+ va_list ap_new;
+ int res;
+
+ cache_data = (nss_cache_data *)mdata;
+ cache_info = cache_data->info;
+
+ memset(&params, 0, sizeof(struct cached_connection_params));
+ params.socket_path = CACHED_SOCKET_PATH;
+
+ cache_data->key = (char *)malloc(NSS_CACHE_KEY_INITIAL_SIZE);
+ memset(cache_data->key, 0, NSS_CACHE_KEY_INITIAL_SIZE);
+ cache_data->key_size = NSS_CACHE_KEY_INITIAL_SIZE;
+ va_copy(ap_new, ap);
+
+ do {
+ size = cache_data->key_size;
+ res = cache_info->id_func(cache_data->key, &size, ap_new,
+ cache_info->mdata);
+ va_end(ap_new);
+ if (res == NS_RETURN) {
+ if (cache_data->key_size > NSS_CACHE_KEY_SIZE_LIMIT)
+ break;
+
+ cache_data->key_size <<= 1;
+ cache_data->key = realloc(cache_data->key,
+ cache_data->key_size);
+ memset(cache_data->key, 0, cache_data->key_size);
+ va_copy(ap_new, ap);
+ }
+ } while (res == NS_RETURN);
+
+ if (res != NS_SUCCESS) {
+ free(cache_data->key);
+ cache_data->key = NULL;
+ cache_data->key_size = 0;
+ return (res);
+ } else
+ cache_data->key_size = size;
+
+ buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
+ buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
+ memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
+
+ do {
+ connection = __open_cached_connection(&params);
+ if (connection == NULL) {
+ res = -1;
+ break;
+ }
+ res = __cached_read(connection, cache_info->entry_name,
+ cache_data->key, cache_data->key_size, buffer,
+ &buffer_size);
+ __close_cached_connection(connection);
+ if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
+ buffer = (char *)realloc(buffer, buffer_size);
+ memset(buffer, 0, buffer_size);
+ }
+ } while (res == -2);
+
+ if (res == 0) {
+ if (buffer_size == 0) {
+ free(buffer);
+ free(cache_data->key);
+ cache_data->key = NULL;
+ cache_data->key_size = 0;
+ return (NS_RETURN);
+ }
+
+ va_copy(ap_new, ap);
+ res = cache_info->unmarshal_func(buffer, buffer_size, retval,
+ ap_new, cache_info->mdata);
+ va_end(ap_new);
+
+ if (res != NS_SUCCESS) {
+ free(buffer);
+ free(cache_data->key);
+ cache_data->key = NULL;
+ cache_data->key_size = 0;
+ return (res);
+ } else
+ res = 0;
+ }
+
+ if (res == 0) {
+ free(cache_data->key);
+ cache_data->key = NULL;
+ cache_data->key_size = 0;
+ }
+
+ free(buffer);
+ return (res == 0 ? NS_SUCCESS : NS_NOTFOUND);
+}
+
+int
+__nss_common_cache_write(void *retval, void *mdata, va_list ap)
+{
+ struct cached_connection_params params;
+ cached_connection connection;
+
+ char *buffer;
+ size_t buffer_size;
+
+ nss_cache_info const *cache_info;
+ nss_cache_data *cache_data;
+ va_list ap_new;
+ int res;
+
+ cache_data = (nss_cache_data *)mdata;
+ cache_info = cache_data->info;
+
+ if (cache_data->key == NULL)
+ return (NS_UNAVAIL);
+
+ memset(&params, 0, sizeof(struct cached_connection_params));
+ params.socket_path = CACHED_SOCKET_PATH;
+
+ connection = __open_cached_connection(&params);
+ if (connection == NULL) {
+ free(cache_data->key);
+ return (NS_UNAVAIL);
+ }
+
+ buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
+ buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
+ memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
+
+ do {
+ size_t size;
+
+ size = buffer_size;
+ va_copy(ap_new, ap);
+ res = cache_info->marshal_func(buffer, &size, retval, ap_new,
+ cache_info->mdata);
+ va_end(ap_new);
+
+ if (res == NS_RETURN) {
+ if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
+ break;
+
+ buffer_size <<= 1;
+ buffer = (char *)realloc(buffer, buffer_size);
+ memset(buffer, 0, buffer_size);
+ }
+ } while (res == NS_RETURN);
+
+ if (res != NS_SUCCESS) {
+ __close_cached_connection(connection);
+ free(cache_data->key);
+ free(buffer);
+ return (res);
+ }
+
+ res = __cached_write(connection, cache_info->entry_name,
+ cache_data->key, cache_data->key_size, buffer, buffer_size);
+ __close_cached_connection(connection);
+
+ free(cache_data->key);
+ free(buffer);
+
+ return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
+}
+
+int
+__nss_common_cache_write_negative(void *mdata)
+{
+ struct cached_connection_params params;
+ cached_connection connection;
+ int res;
+
+ nss_cache_info const *cache_info;
+ nss_cache_data *cache_data;
+
+ cache_data = (nss_cache_data *)mdata;
+ cache_info = cache_data->info;
+
+ if (cache_data->key == NULL)
+ return (NS_UNAVAIL);
+
+ memset(&params, 0, sizeof(struct cached_connection_params));
+ params.socket_path = CACHED_SOCKET_PATH;
+
+ connection = __open_cached_connection(&params);
+ if (connection == NULL) {
+ free(cache_data->key);
+ return (NS_UNAVAIL);
+ }
+
+ res = __cached_write(connection, cache_info->entry_name,
+ cache_data->key, cache_data->key_size, NULL, 0);
+ __close_cached_connection(connection);
+
+ free(cache_data->key);
+ return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
+}
+
+int
+__nss_mp_cache_read(void *retval, void *mdata, va_list ap)
+{
+ struct cached_connection_params params;
+ cached_mp_read_session rs;
+
+ char *buffer;
+ size_t buffer_size;
+
+ nss_cache_info const *cache_info;
+ nss_cache_data *cache_data;
+ va_list ap_new;
+ int res;
+
+ cache_data = (nss_cache_data *)mdata;
+ cache_info = cache_data->info;
+
+ if (cache_info->get_mp_ws_func() != INVALID_CACHED_MP_WRITE_SESSION)
+ return (NS_UNAVAIL);
+
+ rs = cache_info->get_mp_rs_func();
+ if (rs == INVALID_CACHED_MP_READ_SESSION) {
+ memset(&params, 0, sizeof(struct cached_connection_params));
+ params.socket_path = CACHED_SOCKET_PATH;
+
+ rs = __open_cached_mp_read_session(&params,
+ cache_info->entry_name);
+ if (rs == INVALID_CACHED_MP_READ_SESSION)
+ return (NS_UNAVAIL);
+
+ cache_info->set_mp_rs_func(rs);
+ }
+
+ buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
+ buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
+ memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
+
+ do {
+ res = __cached_mp_read(rs, buffer, &buffer_size);
+ if (res == -2 && buffer_size < NSS_CACHE_BUFFER_SIZE_LIMIT) {
+ buffer = (char *)realloc(buffer, buffer_size);
+ memset(buffer, 0, buffer_size);
+ }
+ } while (res == -2);
+
+ if (res == 0) {
+ va_copy(ap_new, ap);
+ res = cache_info->unmarshal_func(buffer, buffer_size, retval,
+ ap_new, cache_info->mdata);
+ va_end(ap_new);
+
+ if (res != NS_SUCCESS) {
+ free(buffer);
+ return (res);
+ } else
+ res = 0;
+ } else {
+ free(buffer);
+ __close_cached_mp_read_session(rs);
+ rs = INVALID_CACHED_MP_READ_SESSION;
+ cache_info->set_mp_rs_func(rs);
+ return (res == -1 ? NS_RETURN : NS_UNAVAIL);
+ }
+
+ free(buffer);
+ return (res == 0 ? NS_SUCCESS : NS_NOTFOUND);
+}
+
+int
+__nss_mp_cache_write(void *retval, void *mdata, va_list ap)
+{
+ struct cached_connection_params params;
+ cached_mp_write_session ws;
+
+ char *buffer;
+ size_t buffer_size;
+
+ nss_cache_info const *cache_info;
+ nss_cache_data *cache_data;
+ va_list ap_new;
+ int res;
+
+ cache_data = (nss_cache_data *)mdata;
+ cache_info = cache_data->info;
+
+ ws = cache_info->get_mp_ws_func();
+ if (ws == INVALID_CACHED_MP_WRITE_SESSION) {
+ memset(&params, 0, sizeof(struct cached_connection_params));
+ params.socket_path = CACHED_SOCKET_PATH;
+
+ ws = __open_cached_mp_write_session(&params,
+ cache_info->entry_name);
+ if (ws == INVALID_CACHED_MP_WRITE_SESSION)
+ return (NS_UNAVAIL);
+
+ cache_info->set_mp_ws_func(ws);
+ }
+
+ buffer_size = NSS_CACHE_BUFFER_INITIAL_SIZE;
+ buffer = (char *)malloc(NSS_CACHE_BUFFER_INITIAL_SIZE);
+ memset(buffer, 0, NSS_CACHE_BUFFER_INITIAL_SIZE);
+
+ do {
+ size_t size;
+
+ size = buffer_size;
+ va_copy(ap_new, ap);
+ res = cache_info->marshal_func(buffer, &size, retval, ap_new,
+ cache_info->mdata);
+ va_end(ap_new);
+
+ if (res == NS_RETURN) {
+ if (buffer_size > NSS_CACHE_BUFFER_SIZE_LIMIT)
+ break;
+
+ buffer_size <<= 1;
+ buffer = (char *)realloc(buffer, buffer_size);
+ memset(buffer, 0, buffer_size);
+ }
+ } while (res == NS_RETURN);
+
+ if (res != NS_SUCCESS) {
+ free(buffer);
+ return (res);
+ }
+
+ res = __cached_mp_write(ws, buffer, buffer_size);
+
+ free(buffer);
+ return (res == 0 ? NS_SUCCESS : NS_UNAVAIL);
+}
+
+int
+__nss_mp_cache_write_submit(void *retval, void *mdata, va_list ap)
+{
+ cached_mp_write_session ws;
+
+ nss_cache_info const *cache_info;
+ nss_cache_data *cache_data;
+
+ cache_data = (nss_cache_data *)mdata;
+ cache_info = cache_data->info;
+
+ ws = cache_info->get_mp_ws_func();
+ if (ws != INVALID_CACHED_MP_WRITE_SESSION) {
+ __close_cached_mp_write_session(ws);
+ ws = INVALID_CACHED_MP_WRITE_SESSION;
+ cache_info->set_mp_ws_func(ws);
+ }
+ return (NS_UNAVAIL);
+}
+
+int
+__nss_mp_cache_end(void *retval, void *mdata, va_list ap)
+{
+ cached_mp_write_session ws;
+ cached_mp_read_session rs;
+
+ nss_cache_info const *cache_info;
+ nss_cache_data *cache_data;
+
+ cache_data = (nss_cache_data *)mdata;
+ cache_info = cache_data->info;
+
+ ws = cache_info->get_mp_ws_func();
+ if (ws != INVALID_CACHED_MP_WRITE_SESSION) {
+ __abandon_cached_mp_write_session(ws);
+ ws = INVALID_CACHED_MP_WRITE_SESSION;
+ cache_info->set_mp_ws_func(ws);
+ }
+
+ rs = cache_info->get_mp_rs_func();
+ if (rs != INVALID_CACHED_MP_READ_SESSION) {
+ __close_cached_mp_read_session(rs);
+ rs = INVALID_CACHED_MP_READ_SESSION;
+ cache_info->set_mp_rs_func(rs);
+ }
+
+ return (NS_UNAVAIL);
+}
diff --git a/lib/libc/net/nscachedcli.c b/lib/libc/net/nscachedcli.c
new file mode 100644
index 0000000..1323805
--- /dev/null
+++ b/lib/libc/net/nscachedcli.c
@@ -0,0 +1,576 @@
+/*-
+ * Copyright (c) 2005 Michael Bushkov <bushman@rsu.ru>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/event.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+#include <assert.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "nscachedcli.h"
+
+#define NS_DEFAULT_CACHED_IO_TIMEOUT 4
+
+static int safe_write(struct cached_connection_ *, const void *, size_t);
+static int safe_read(struct cached_connection_ *, void *, size_t);
+static int send_credentials(struct cached_connection_ *, int);
+
+/*
+ * safe_write writes data to the specified connection and tries to do it in
+ * the very safe manner. We ensure, that we can write to the socket with
+ * kevent. If the data_size can't be sent in one piece, then it would be
+ * splitted.
+ */
+static int
+safe_write(struct cached_connection_ *connection, const void *data,
+ size_t data_size)
+{
+ struct kevent eventlist;
+ int nevents;
+ size_t result;
+ ssize_t s_result;
+ struct timespec timeout;
+
+ if (data_size == 0)
+ return (0);
+
+ timeout.tv_sec = NS_DEFAULT_CACHED_IO_TIMEOUT;
+ timeout.tv_nsec = 0;
+ result = 0;
+ do {
+ nevents = _kevent(connection->write_queue, NULL, 0, &eventlist,
+ 1, &timeout);
+ if ((nevents == 1) && (eventlist.filter == EVFILT_WRITE)) {
+ s_result = _write(connection->sockfd, data + result,
+ eventlist.data < data_size - result ?
+ eventlist.data : data_size - result);
+ if (s_result == -1)
+ return (-1);
+ else
+ result += s_result;
+
+ if (eventlist.flags & EV_EOF)
+ return (result < data_size ? -1 : 0);
+ } else
+ return (-1);
+ } while (result < data_size);
+
+ return (0);
+}
+
+/*
+ * safe_read reads data from connection and tries to do it in the very safe
+ * and stable way. It uses kevent to ensure, that the data are availabe for
+ * reading. If the amount of data to be read is too large, then they would
+ * be splitted.
+ */
+static int
+safe_read(struct cached_connection_ *connection, void *data, size_t data_size)
+{
+ struct kevent eventlist;
+ size_t result;
+ ssize_t s_result;
+ struct timespec timeout;
+ int nevents;
+
+ if (data_size == 0)
+ return (0);
+
+ timeout.tv_sec = NS_DEFAULT_CACHED_IO_TIMEOUT;
+ timeout.tv_nsec = 0;
+ result = 0;
+ do {
+ nevents = _kevent(connection->read_queue, NULL, 0, &eventlist,
+ 1, &timeout);
+ if (nevents == 1 && eventlist.filter == EVFILT_READ) {
+ s_result = _read(connection->sockfd, data + result,
+ eventlist.data <= data_size - result ?
+ eventlist.data : data_size - result);
+ if (s_result == -1)
+ return (-1);
+ else
+ result += s_result;
+
+ if (eventlist.flags & EV_EOF)
+ return (result < data_size ? -1 : 0);
+ } else
+ return (-1);
+ } while (result < data_size);
+
+ return (0);
+}
+
+/*
+ * Sends the credentials information to the connection along with the
+ * communication element type.
+ */
+static int
+send_credentials(struct cached_connection_ *connection, int type)
+{
+ struct kevent eventlist;
+ int nevents;
+ ssize_t result;
+ int res;
+
+ struct msghdr cred_hdr;
+ struct iovec iov;
+
+ struct {
+ struct cmsghdr hdr;
+ char cred[CMSG_SPACE(sizeof(struct cmsgcred))];
+ } cmsg;
+
+ memset(&cmsg, 0, sizeof(cmsg));
+ cmsg.hdr.cmsg_len = CMSG_LEN(sizeof(struct cmsgcred));
+ cmsg.hdr.cmsg_level = SOL_SOCKET;
+ cmsg.hdr.cmsg_type = SCM_CREDS;
+
+ memset(&cred_hdr, 0, sizeof(struct msghdr));
+ cred_hdr.msg_iov = &iov;
+ cred_hdr.msg_iovlen = 1;
+ cred_hdr.msg_control = (caddr_t)&cmsg;
+ cred_hdr.msg_controllen = CMSG_SPACE(sizeof(struct cmsgcred));
+
+ iov.iov_base = &type;
+ iov.iov_len = sizeof(int);
+
+ EV_SET(&eventlist, connection->sockfd, EVFILT_WRITE, EV_ADD,
+ NOTE_LOWAT, sizeof(int), NULL);
+ res = _kevent(connection->write_queue, &eventlist, 1, NULL, 0, NULL);
+
+ nevents = _kevent(connection->write_queue, NULL, 0, &eventlist, 1,
+ NULL);
+ if (nevents == 1 && eventlist.filter == EVFILT_WRITE) {
+ result = (_sendmsg(connection->sockfd, &cred_hdr, 0) == -1) ?
+ -1 : 0;
+ EV_SET(&eventlist, connection->sockfd, EVFILT_WRITE, EV_ADD,
+ 0, 0, NULL);
+ _kevent(connection->write_queue, &eventlist, 1, NULL, 0, NULL);
+ return (result);
+ } else
+ return (-1);
+}
+
+/*
+ * Opens the connection with the specified params. Initializes all kqueues.
+ */
+struct cached_connection_ *
+__open_cached_connection(struct cached_connection_params const *params)
+{
+ struct cached_connection_ *retval;
+ struct kevent eventlist;
+ struct sockaddr_un client_address;
+ int client_address_len, client_socket;
+ int res;
+
+ assert(params != NULL);
+
+ client_socket = _socket(PF_LOCAL, SOCK_STREAM, 0);
+ client_address.sun_family = PF_LOCAL;
+ strncpy(client_address.sun_path, params->socket_path,
+ sizeof(client_address.sun_path));
+ client_address_len = sizeof(client_address.sun_family) +
+ strlen(client_address.sun_path) + 1;
+
+ res = _connect(client_socket, (struct sockaddr *)&client_address,
+ client_address_len);
+ if (res == -1) {
+ _close(client_socket);
+ return (NULL);
+ }
+ _fcntl(client_socket, F_SETFL, O_NONBLOCK);
+
+ retval = malloc(sizeof(struct cached_connection_));
+ assert(retval != NULL);
+ memset(retval, 0, sizeof(struct cached_connection_));
+
+ retval->sockfd = client_socket;
+
+ retval->write_queue = kqueue();
+ assert(retval->write_queue != -1);
+
+ EV_SET(&eventlist, retval->sockfd, EVFILT_WRITE, EV_ADD, 0, 0, NULL);
+ res = _kevent(retval->write_queue, &eventlist, 1, NULL, 0, NULL);
+
+ retval->read_queue = kqueue();
+ assert(retval->read_queue != -1);
+
+ EV_SET(&eventlist, retval->sockfd, EVFILT_READ, EV_ADD, 0, 0, NULL);
+ res = _kevent(retval->read_queue, &eventlist, 1, NULL, 0, NULL);
+
+ return (retval);
+}
+
+void
+__close_cached_connection(struct cached_connection_ *connection)
+{
+ assert(connection != NULL);
+
+ _close(connection->sockfd);
+ _close(connection->read_queue);
+ _close(connection->write_queue);
+ free(connection);
+}
+
+/*
+ * This function is very close to the cache_write function of the caching
+ * library, which is used in the caching daemon. It caches the data with the
+ * specified key in the cache entry with entry_name.
+ */
+int
+__cached_write(struct cached_connection_ *connection, const char *entry_name,
+ const char *key, size_t key_size, const char *data, size_t data_size)
+{
+ size_t name_size;
+ int error_code;
+ int result;
+
+ error_code = -1;
+ result = 0;
+ result = send_credentials(connection, CET_WRITE_REQUEST);
+ if (result != 0)
+ goto fin;
+
+ name_size = strlen(entry_name);
+ result = safe_write(connection, &name_size, sizeof(size_t));
+ if (result != 0)
+ goto fin;
+
+ result = safe_write(connection, &key_size, sizeof(size_t));
+ if (result != 0)
+ goto fin;
+
+ result = safe_write(connection, &data_size, sizeof(size_t));
+ if (result != 0)
+ goto fin;
+
+ result = safe_write(connection, entry_name, name_size);
+ if (result != 0)
+ goto fin;
+
+ result = safe_write(connection, key, key_size);
+ if (result != 0)
+ goto fin;
+
+ result = safe_write(connection, data, data_size);
+ if (result != 0)
+ goto fin;
+
+ result = safe_read(connection, &error_code, sizeof(int));
+ if (result != 0)
+ error_code = -1;
+
+fin:
+ return (error_code);
+}
+
+/*
+ * This function is very close to the cache_read function of the caching
+ * library, which is used in the caching daemon. It reads cached data with the
+ * specified key from the cache entry with entry_name.
+ */
+int
+__cached_read(struct cached_connection_ *connection, const char *entry_name,
+ const char *key, size_t key_size, char *data, size_t *data_size)
+{
+ size_t name_size, result_size;
+ int error_code, rec_error_code;
+ int result;
+
+ assert(connection != NULL);
+ result = 0;
+ error_code = -1;
+
+ result = send_credentials(connection, CET_READ_REQUEST);
+ if (result != 0)
+ goto fin;
+
+ name_size = strlen(entry_name);
+ result = safe_write(connection, &name_size, sizeof(size_t));
+ if (result != 0)
+ goto fin;
+
+ result = safe_write(connection, &key_size, sizeof(size_t));
+ if (result != 0)
+ goto fin;
+
+ result = safe_write(connection, entry_name, name_size);
+ if (result != 0)
+ goto fin;
+
+ result = safe_write(connection, key, key_size);
+ if (result != 0)
+ goto fin;
+
+ result = safe_read(connection, &rec_error_code, sizeof(int));
+ if (result != 0)
+ goto fin;
+
+ if (rec_error_code != 0) {
+ error_code = rec_error_code;
+ goto fin;
+ }
+
+ result = safe_read(connection, &result_size, sizeof(size_t));
+ if (result != 0)
+ goto fin;
+
+ if (result_size > *data_size) {
+ *data_size = result_size;
+ error_code = -2;
+ goto fin;
+ }
+
+ result = safe_read(connection, data, result_size);
+ if (result != 0)
+ goto fin;
+
+ *data_size = result_size;
+ error_code = 0;
+
+fin:
+ return (error_code);
+}
+
+/*
+ * Initializes the mp_write_session. For such a session the new connection
+ * would be opened. The data should be written to the session with
+ * __cached_mp_write function. The __close_cached_mp_write_session function
+ * should be used to submit session and __abandon_cached_mp_write_session - to
+ * abandon it. When the session is submitted, the whole se
+ */
+struct cached_connection_ *
+__open_cached_mp_write_session(struct cached_connection_params const *params,
+ const char *entry_name)
+{
+ struct cached_connection_ *connection, *retval;
+ size_t name_size;
+ int error_code;
+ int result;
+
+ retval = NULL;
+ connection = __open_cached_connection(params);
+ if (connection == NULL)
+ return (NULL);
+ connection->mp_flag = 1;
+
+ result = send_credentials(connection, CET_MP_WRITE_SESSION_REQUEST);
+ if (result != 0)
+ goto fin;
+
+ name_size = strlen(entry_name);
+ result = safe_write(connection, &name_size, sizeof(size_t));
+ if (result != 0)
+ goto fin;
+
+ result = safe_write(connection, entry_name, name_size);
+ if (result != 0)
+ goto fin;
+
+ result = safe_read(connection, &error_code, sizeof(int));
+ if (result != 0)
+ goto fin;
+
+ if (error_code != 0)
+ result = error_code;
+
+fin:
+ if (result != 0)
+ __close_cached_connection(connection);
+ else
+ retval = connection;
+ return (retval);
+}
+
+/*
+ * Adds new portion of data to the opened write session
+ */
+int
+__cached_mp_write(struct cached_connection_ *ws, const char *data,
+ size_t data_size)
+{
+ int request, result;
+ int error_code;
+
+ error_code = -1;
+
+ request = CET_MP_WRITE_SESSION_WRITE_REQUEST;
+ result = safe_write(ws, &request, sizeof(int));
+ if (result != 0)
+ goto fin;
+
+ result = safe_write(ws, &data_size, sizeof(size_t));
+ if (result != 0)
+ goto fin;
+
+ result = safe_write(ws, data, data_size);
+ if (result != 0)
+ goto fin;
+
+ result = safe_read(ws, &error_code, sizeof(int));
+ if (result != 0)
+ error_code = -1;
+
+fin:
+ return (error_code);
+}
+
+/*
+ * Abandons all operations with the write session. All data, that were written
+ * to the session before, are discarded.
+ */
+int
+__abandon_cached_mp_write_session(struct cached_connection_ *ws)
+{
+ int notification;
+ int result;
+
+ notification = CET_MP_WRITE_SESSION_ABANDON_NOTIFICATION;
+ result = safe_write(ws, &notification, sizeof(int));
+ __close_cached_connection(ws);
+ return (result);
+}
+
+/*
+ * Gracefully closes the write session. The data, that were previously written
+ * to the session, are committed.
+ */
+int
+__close_cached_mp_write_session(struct cached_connection_ *ws)
+{
+ int notification;
+ int result;
+
+ notification = CET_MP_WRITE_SESSION_CLOSE_NOTIFICATION;
+ result = safe_write(ws, &notification, sizeof(int));
+ __close_cached_connection(ws);
+ return (0);
+}
+
+struct cached_connection_ *
+__open_cached_mp_read_session(struct cached_connection_params const *params,
+ const char *entry_name)
+{
+ struct cached_connection_ *connection, *retval;
+ size_t name_size;
+ int error_code;
+ int result;
+
+ retval = NULL;
+ connection = __open_cached_connection(params);
+ if (connection == NULL)
+ return (NULL);
+ connection->mp_flag = 1;
+
+ result = send_credentials(connection, CET_MP_READ_SESSION_REQUEST);
+ if (result != 0)
+ goto fin;
+
+ name_size = strlen(entry_name);
+ result = safe_write(connection, &name_size, sizeof(size_t));
+ if (result != 0)
+ goto fin;
+
+ result = safe_write(connection, entry_name, name_size);
+ if (result != 0)
+ goto fin;
+
+ result = safe_read(connection, &error_code, sizeof(int));
+ if (result != 0)
+ goto fin;
+
+ if (error_code != 0)
+ result = error_code;
+
+fin:
+ if (result != 0)
+ __close_cached_connection(connection);
+ else
+ retval = connection;
+ return (retval);
+}
+
+int
+__cached_mp_read(struct cached_connection_ *rs, char *data, size_t *data_size)
+{
+ size_t result_size;
+ int error_code, rec_error_code;
+ int request, result;
+
+ error_code = -1;
+ request = CET_MP_READ_SESSION_READ_REQUEST;
+ result = safe_write(rs, &request, sizeof(int));
+ if (result != 0)
+ goto fin;
+
+ result = safe_read(rs, &rec_error_code, sizeof(int));
+ if (result != 0)
+ goto fin;
+
+ if (rec_error_code != 0) {
+ error_code = rec_error_code;
+ goto fin;
+ }
+
+ result = safe_read(rs, &result_size, sizeof(size_t));
+ if (result != 0)
+ goto fin;
+
+ if (result_size > *data_size) {
+ *data_size = result_size;
+ error_code = -2;
+ goto fin;
+ }
+
+ result = safe_read(rs, data, result_size);
+ if (result != 0)
+ goto fin;
+
+ *data_size = result_size;
+ error_code = 0;
+
+fin:
+ return (error_code);
+}
+
+int
+__close_cached_mp_read_session(struct cached_connection_ *rs)
+{
+
+ __close_cached_connection(rs);
+ return (0);
+}
diff --git a/lib/libc/net/nsdispatch.3 b/lib/libc/net/nsdispatch.3
new file mode 100644
index 0000000..a1da892
--- /dev/null
+++ b/lib/libc/net/nsdispatch.3
@@ -0,0 +1,258 @@
+.\" $NetBSD: nsdispatch.3,v 1.8 1999/03/22 19:44:53 garbled Exp $
+.\"
+.\" Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Luke Mewburn.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of The NetBSD Foundation nor the names of its
+.\" contributors may be used to endorse or promote products derived
+.\" from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 4, 2010
+.Dt NSDISPATCH 3
+.Os
+.Sh NAME
+.Nm nsdispatch
+.Nd name-service switch dispatcher routine
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In stdarg.h
+.In nsswitch.h
+.Ft int
+.Fo nsdispatch
+.Fa "void *retval"
+.Fa "const ns_dtab dtab[]"
+.Fa "const char *database"
+.Fa "const char *method_name"
+.Fa "const ns_src defaults[]"
+.Fa "..."
+.Fc
+.Sh DESCRIPTION
+The
+.Fn nsdispatch
+function invokes the methods specified in
+.Va dtab
+in the order given by
+.Xr nsswitch.conf 5
+for the database
+.Va database
+until a successful entry is found.
+.Pp
+.Va retval
+is passed to each method to modify as necessary, to pass back results to
+the caller of
+.Fn nsdispatch .
+.Pp
+Each method has the function signature described by the typedef:
+.Pp
+.Ft typedef int
+.Fn \*(lp*nss_method\*(rp "void *retval" "void *mdata" "va_list *ap" ;
+.Pp
+.Va dtab
+is an array of
+.Va ns_dtab
+structures, which have the following format:
+.Bd -literal -offset indent
+typedef struct _ns_dtab {
+ const char *src;
+ nss_method method;
+ void *mdata;
+} ns_dtab;
+.Ed
+.Pp
+The
+.Fa dtab
+array should consist of one entry for each source type that is
+implemented, with
+.Va src
+as the name of the source,
+.Va method
+as a function which handles that source, and
+.Va mdata
+as a handle on arbitrary data to be passed to the method.
+The last entry in
+.Va dtab
+should contain
+.Dv NULL
+values for
+.Va src ,
+.Va method ,
+and
+.Va mdata .
+.Pp
+Additionally, methods may be implemented in NSS modules, in
+which case they are selected using the
+.Fa database
+and
+.Fa method_name
+arguments along with the configured source.
+(The methods supplied via
+.Fa dtab
+take priority over those implemented in NSS modules in the event
+of a conflict.)
+.Pp
+.Va defaults
+contains a list of default sources to try if
+.Xr nsswitch.conf 5
+is missing or corrupted, or if there is no relevant entry for
+.Va database .
+It is an array of
+.Va ns_src
+structures, which have the following format:
+.Bd -literal -offset indent
+typedef struct _ns_src {
+ const char *src;
+ uint32_t flags;
+} ns_src;
+.Ed
+.Pp
+The
+.Fa defaults
+array should consist of one entry for each source to be configured by
+default indicated by
+.Va src ,
+and
+.Va flags
+set to the criterion desired
+(usually
+.Dv NS_SUCCESS ;
+refer to
+.Sx Method return values
+for more information).
+The last entry in
+.Va defaults
+should have
+.Va src
+set to
+.Dv NULL
+and
+.Va flags
+set to 0.
+.Pp
+For convenience, a global variable defined as:
+.Pp
+.Dl extern const ns_src __nsdefaultsrc[];
+.Pp
+exists which contains a single default entry for the source
+.Sq files
+that may be used by callers which do not require complicated default
+rules.
+.Pp
+.Sq Va ...
+are optional extra arguments, which are passed to the appropriate method
+as a variable argument list of the type
+.Vt va_list .
+.Ss Valid source types
+While there is support for arbitrary sources, the following
+#defines for commonly implemented sources are available:
+.Bl -column NSSRC_COMPAT compat -offset indent
+.It Sy "#define value"
+.It Dv NSSRC_FILES Ta """files""
+.It Dv NSSRC_DB Ta """db""
+.It Dv NSSRC_DNS Ta """dns""
+.It Dv NSSRC_NIS Ta """nis""
+.It Dv NSSRC_COMPAT Ta """compat""
+.El
+.Pp
+Refer to
+.Xr nsswitch.conf 5
+for a complete description of what each source type is.
+.Ss Method return values
+The
+.Vt nss_method
+functions must return one of the following values depending upon status
+of the lookup:
+.Bl -column "Return value" "Status code"
+.It Sy "Return value Status code"
+.It Dv NS_SUCCESS Ta success
+.It Dv NS_NOTFOUND Ta notfound
+.It Dv NS_UNAVAIL Ta unavail
+.It Dv NS_TRYAGAIN Ta tryagain
+.It Dv NS_RETURN Ta -none-
+.El
+.Pp
+Refer to
+.Xr nsswitch.conf 5
+for a complete description of each status code.
+.Pp
+The
+.Fn nsdispatch
+function returns the value of the method that caused the dispatcher to
+terminate, or
+.Dv NS_NOTFOUND
+otherwise.
+.Sh NOTES
+.Fx Ns 's
+.Lb libc
+provides stubs for compatibility with NSS modules
+written for the
+.Tn GNU
+C Library
+.Nm nsswitch
+interface.
+However, these stubs only support the use of the
+.Dq Li passwd
+and
+.Dq Li group
+databases.
+.Sh SEE ALSO
+.Xr hesiod 3 ,
+.Xr stdarg 3 ,
+.Xr nsswitch.conf 5 ,
+.Xr yp 8
+.Sh HISTORY
+The
+.Fn nsdispatch
+function first appeared in
+.Fx 5.0 .
+It was imported from the
+.Nx
+Project,
+where it appeared first in
+.Nx 1.4 .
+Support for NSS modules first appeared in
+.Fx 5.1 .
+.Sh AUTHORS
+Luke Mewburn
+.Aq lukem@netbsd.org
+wrote this freely-distributable name-service switch implementation,
+using ideas from the
+.Tn ULTRIX
+svc.conf(5)
+and
+.Tn Solaris
+nsswitch.conf(4)
+manual pages.
+The
+.Fx
+Project
+added the support for threads and NSS modules, and normalized the uses
+of
+.Fn nsdispatch
+within the standard C library.
diff --git a/lib/libc/net/nsdispatch.c b/lib/libc/net/nsdispatch.c
new file mode 100644
index 0000000..f9d787a
--- /dev/null
+++ b/lib/libc/net/nsdispatch.c
@@ -0,0 +1,766 @@
+/* $NetBSD: nsdispatch.c,v 1.9 1999/01/25 00:16:17 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * Portions of this software were developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <fcntl.h>
+#define _NS_PRIVATE
+#include <nsswitch.h>
+#include <pthread.h>
+#include <pthread_np.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "nss_tls.h"
+#include "libc_private.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+
+enum _nss_constants {
+ /* Number of elements allocated when we grow a vector */
+ ELEMSPERCHUNK = 8
+};
+
+/*
+ * Global NSS data structures are mostly read-only, but we update
+ * them when we read or re-read the nsswitch.conf.
+ */
+static pthread_rwlock_t nss_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/*
+ * Runtime determination of whether we are dynamically linked or not.
+ */
+extern int _DYNAMIC __attribute__ ((weak));
+#define is_dynamic() (&_DYNAMIC != NULL)
+
+/*
+ * default sourcelist: `files'
+ */
+const ns_src __nsdefaultsrc[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+ { 0 },
+};
+
+/* Database, source mappings. */
+static unsigned int _nsmapsize;
+static ns_dbt *_nsmap = NULL;
+
+/* NSS modules. */
+static unsigned int _nsmodsize;
+static ns_mod *_nsmod;
+
+/* Placeholder for builtin modules' dlopen `handle'. */
+static int __nss_builtin_handle;
+static void *nss_builtin_handle = &__nss_builtin_handle;
+
+#ifdef NS_CACHING
+/*
+ * Cache lookup cycle prevention function - if !NULL then no cache lookups
+ * will be made
+ */
+static void *nss_cache_cycle_prevention_func = NULL;
+#endif
+
+/*
+ * When this is set to 1, nsdispatch won't use nsswitch.conf
+ * but will consult the 'defaults' source list only.
+ * NOTE: nested fallbacks (when nsdispatch calls fallback functions,
+ * which in turn calls nsdispatch, which should call fallback
+ * function) are not supported
+ */
+struct fb_state {
+ int fb_dispatch;
+};
+static void fb_endstate(void *);
+NSS_TLS_HANDLING(fb);
+
+/*
+ * Attempt to spew relatively uniform messages to syslog.
+ */
+#define nss_log(level, fmt, ...) \
+ syslog((level), "NSSWITCH(%s): " fmt, __func__, __VA_ARGS__)
+#define nss_log_simple(level, s) \
+ syslog((level), "NSSWITCH(%s): " s, __func__)
+
+/*
+ * Dynamically growable arrays are used for lists of databases, sources,
+ * and modules. The following `vector' interface is used to isolate the
+ * common operations.
+ */
+typedef int (*vector_comparison)(const void *, const void *);
+typedef void (*vector_free_elem)(void *);
+static void vector_sort(void *, unsigned int, size_t,
+ vector_comparison);
+static void vector_free(void *, unsigned int *, size_t,
+ vector_free_elem);
+static void *vector_ref(unsigned int, void *, unsigned int, size_t);
+static void *vector_search(const void *, void *, unsigned int, size_t,
+ vector_comparison);
+static void *vector_append(const void *, void *, unsigned int *, size_t);
+
+
+/*
+ * Internal interfaces.
+ */
+static int string_compare(const void *, const void *);
+static int mtab_compare(const void *, const void *);
+static int nss_configure(void);
+static void ns_dbt_free(ns_dbt *);
+static void ns_mod_free(ns_mod *);
+static void ns_src_free(ns_src **, int);
+static void nss_load_builtin_modules(void);
+static void nss_load_module(const char *, nss_module_register_fn);
+static void nss_atexit(void);
+/* nsparser */
+extern FILE *_nsyyin;
+
+
+/*
+ * The vector operations
+ */
+static void
+vector_sort(void *vec, unsigned int count, size_t esize,
+ vector_comparison comparison)
+{
+ qsort(vec, count, esize, comparison);
+}
+
+
+static void *
+vector_search(const void *key, void *vec, unsigned int count, size_t esize,
+ vector_comparison comparison)
+{
+ return (bsearch(key, vec, count, esize, comparison));
+}
+
+
+static void *
+vector_append(const void *elem, void *vec, unsigned int *count, size_t esize)
+{
+ void *p;
+
+ if ((*count % ELEMSPERCHUNK) == 0) {
+ p = realloc(vec, (*count + ELEMSPERCHUNK) * esize);
+ if (p == NULL) {
+ nss_log_simple(LOG_ERR, "memory allocation failure");
+ return (vec);
+ }
+ vec = p;
+ }
+ memmove((void *)(((uintptr_t)vec) + (*count * esize)), elem, esize);
+ (*count)++;
+ return (vec);
+}
+
+
+static void *
+vector_ref(unsigned int i, void *vec, unsigned int count, size_t esize)
+{
+ if (i < count)
+ return (void *)((uintptr_t)vec + (i * esize));
+ else
+ return (NULL);
+}
+
+
+#define VECTOR_FREE(v, c, s, f) \
+ do { vector_free(v, c, s, f); v = NULL; } while (0)
+static void
+vector_free(void *vec, unsigned int *count, size_t esize,
+ vector_free_elem free_elem)
+{
+ unsigned int i;
+ void *elem;
+
+ for (i = 0; i < *count; i++) {
+ elem = vector_ref(i, vec, *count, esize);
+ if (elem != NULL)
+ free_elem(elem);
+ }
+ free(vec);
+ *count = 0;
+}
+
+/*
+ * Comparison functions for vector_search.
+ */
+static int
+string_compare(const void *a, const void *b)
+{
+ return (strcasecmp(*(const char * const *)a, *(const char * const *)b));
+}
+
+
+static int
+mtab_compare(const void *a, const void *b)
+{
+ int cmp;
+
+ cmp = strcmp(((const ns_mtab *)a)->name, ((const ns_mtab *)b)->name);
+ if (cmp != 0)
+ return (cmp);
+ else
+ return (strcmp(((const ns_mtab *)a)->database,
+ ((const ns_mtab *)b)->database));
+}
+
+/*
+ * NSS nsmap management.
+ */
+void
+_nsdbtaddsrc(ns_dbt *dbt, const ns_src *src)
+{
+ const ns_mod *modp;
+
+ dbt->srclist = vector_append(src, dbt->srclist, &dbt->srclistsize,
+ sizeof(*src));
+ modp = vector_search(&src->name, _nsmod, _nsmodsize, sizeof(*_nsmod),
+ string_compare);
+ if (modp == NULL)
+ nss_load_module(src->name, NULL);
+}
+
+
+#ifdef _NSS_DEBUG
+void
+_nsdbtdump(const ns_dbt *dbt)
+{
+ int i;
+
+ printf("%s (%d source%s):", dbt->name, dbt->srclistsize,
+ dbt->srclistsize == 1 ? "" : "s");
+ for (i = 0; i < (int)dbt->srclistsize; i++) {
+ printf(" %s", dbt->srclist[i].name);
+ if (!(dbt->srclist[i].flags &
+ (NS_UNAVAIL|NS_NOTFOUND|NS_TRYAGAIN)) &&
+ (dbt->srclist[i].flags & NS_SUCCESS))
+ continue;
+ printf(" [");
+ if (!(dbt->srclist[i].flags & NS_SUCCESS))
+ printf(" SUCCESS=continue");
+ if (dbt->srclist[i].flags & NS_UNAVAIL)
+ printf(" UNAVAIL=return");
+ if (dbt->srclist[i].flags & NS_NOTFOUND)
+ printf(" NOTFOUND=return");
+ if (dbt->srclist[i].flags & NS_TRYAGAIN)
+ printf(" TRYAGAIN=return");
+ printf(" ]");
+ }
+ printf("\n");
+}
+#endif
+
+
+/*
+ * The first time nsdispatch is called (during a process's lifetime,
+ * or after nsswitch.conf has been updated), nss_configure will
+ * prepare global data needed by NSS.
+ */
+static int
+nss_configure(void)
+{
+ static pthread_mutex_t conf_lock = PTHREAD_MUTEX_INITIALIZER;
+ static time_t confmod;
+ struct stat statbuf;
+ int result, isthreaded;
+ const char *path;
+#ifdef NS_CACHING
+ void *handle;
+#endif
+
+ result = 0;
+ isthreaded = __isthreaded;
+#if defined(_NSS_DEBUG) && defined(_NSS_SHOOT_FOOT)
+ /* NOTE WELL: THIS IS A SECURITY HOLE. This must only be built
+ * for debugging purposes and MUST NEVER be used in production.
+ */
+ path = getenv("NSSWITCH_CONF");
+ if (path == NULL)
+#endif
+ path = _PATH_NS_CONF;
+ if (stat(path, &statbuf) != 0)
+ return (0);
+ if (statbuf.st_mtime <= confmod)
+ return (0);
+ if (isthreaded) {
+ result = _pthread_mutex_trylock(&conf_lock);
+ if (result != 0)
+ return (0);
+ (void)_pthread_rwlock_unlock(&nss_lock);
+ result = _pthread_rwlock_wrlock(&nss_lock);
+ if (result != 0)
+ goto fin2;
+ }
+ _nsyyin = fopen(path, "r");
+ if (_nsyyin == NULL)
+ goto fin;
+ VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap),
+ (vector_free_elem)ns_dbt_free);
+ VECTOR_FREE(_nsmod, &_nsmodsize, sizeof(*_nsmod),
+ (vector_free_elem)ns_mod_free);
+ nss_load_builtin_modules();
+ _nsyyparse();
+ (void)fclose(_nsyyin);
+ vector_sort(_nsmap, _nsmapsize, sizeof(*_nsmap), string_compare);
+ if (confmod == 0)
+ (void)atexit(nss_atexit);
+ confmod = statbuf.st_mtime;
+
+#ifdef NS_CACHING
+ handle = libc_dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL);
+ if (handle != NULL) {
+ nss_cache_cycle_prevention_func = dlsym(handle,
+ "_nss_cache_cycle_prevention_function");
+ dlclose(handle);
+ }
+#endif
+fin:
+ if (isthreaded) {
+ (void)_pthread_rwlock_unlock(&nss_lock);
+ if (result == 0)
+ result = _pthread_rwlock_rdlock(&nss_lock);
+ }
+fin2:
+ if (isthreaded)
+ (void)_pthread_mutex_unlock(&conf_lock);
+ return (result);
+}
+
+
+void
+_nsdbtput(const ns_dbt *dbt)
+{
+ unsigned int i;
+ ns_dbt *p;
+
+ for (i = 0; i < _nsmapsize; i++) {
+ p = vector_ref(i, _nsmap, _nsmapsize, sizeof(*_nsmap));
+ if (string_compare(&dbt->name, &p->name) == 0) {
+ /* overwrite existing entry */
+ if (p->srclist != NULL)
+ ns_src_free(&p->srclist, p->srclistsize);
+ memmove(p, dbt, sizeof(*dbt));
+ return;
+ }
+ }
+ _nsmap = vector_append(dbt, _nsmap, &_nsmapsize, sizeof(*_nsmap));
+}
+
+
+static void
+ns_dbt_free(ns_dbt *dbt)
+{
+ ns_src_free(&dbt->srclist, dbt->srclistsize);
+ if (dbt->name)
+ free((void *)dbt->name);
+}
+
+
+static void
+ns_src_free(ns_src **src, int srclistsize)
+{
+ int i;
+
+ for (i = 0; i < srclistsize; i++)
+ if ((*src)[i].name != NULL)
+ /* This one was allocated by nslexer. You'll just
+ * have to trust me.
+ */
+ free((void *)((*src)[i].name));
+ free(*src);
+ *src = NULL;
+}
+
+
+
+/*
+ * NSS module management.
+ */
+/* The built-in NSS modules are all loaded at once. */
+#define NSS_BACKEND(name, reg) \
+ns_mtab *reg(unsigned int *, nss_module_unregister_fn *);
+#include "nss_backends.h"
+#undef NSS_BACKEND
+
+static void
+nss_load_builtin_modules(void)
+{
+#define NSS_BACKEND(name, reg) nss_load_module(#name, reg);
+#include "nss_backends.h"
+#undef NSS_BACKEND
+}
+
+
+/* Load a built-in or dynamically linked module. If the `reg_fn'
+ * argument is non-NULL, assume a built-in module and use reg_fn to
+ * register it. Otherwise, search for a dynamic NSS module.
+ */
+static void
+nss_load_module(const char *source, nss_module_register_fn reg_fn)
+{
+ char buf[PATH_MAX];
+ ns_mod mod;
+ nss_module_register_fn fn;
+
+ memset(&mod, 0, sizeof(mod));
+ mod.name = strdup(source);
+ if (mod.name == NULL) {
+ nss_log_simple(LOG_ERR, "memory allocation failure");
+ return;
+ }
+ if (reg_fn != NULL) {
+ /* The placeholder is required, as a NULL handle
+ * represents an invalid module.
+ */
+ mod.handle = nss_builtin_handle;
+ fn = reg_fn;
+ } else if (!is_dynamic())
+ goto fin;
+ else {
+ if (snprintf(buf, sizeof(buf), "nss_%s.so.%d", mod.name,
+ NSS_MODULE_INTERFACE_VERSION) >= (int)sizeof(buf))
+ goto fin;
+ mod.handle = libc_dlopen(buf, RTLD_LOCAL|RTLD_LAZY);
+ if (mod.handle == NULL) {
+#ifdef _NSS_DEBUG
+ /* This gets pretty annoying since the built-in
+ * sources aren't modules yet.
+ */
+ nss_log(LOG_DEBUG, "%s, %s", mod.name, dlerror());
+#endif
+ goto fin;
+ }
+ fn = (nss_module_register_fn)dlfunc(mod.handle,
+ "nss_module_register");
+ if (fn == NULL) {
+ (void)dlclose(mod.handle);
+ mod.handle = NULL;
+ nss_log(LOG_ERR, "%s, %s", mod.name, dlerror());
+ goto fin;
+ }
+ }
+ mod.mtab = fn(mod.name, &mod.mtabsize, &mod.unregister);
+ if (mod.mtab == NULL || mod.mtabsize == 0) {
+ if (mod.handle != nss_builtin_handle)
+ (void)dlclose(mod.handle);
+ mod.handle = NULL;
+ nss_log(LOG_ERR, "%s, registration failed", mod.name);
+ goto fin;
+ }
+ if (mod.mtabsize > 1)
+ qsort(mod.mtab, mod.mtabsize, sizeof(mod.mtab[0]),
+ mtab_compare);
+fin:
+ _nsmod = vector_append(&mod, _nsmod, &_nsmodsize, sizeof(*_nsmod));
+ vector_sort(_nsmod, _nsmodsize, sizeof(*_nsmod), string_compare);
+}
+
+
+
+static void
+ns_mod_free(ns_mod *mod)
+{
+
+ free(mod->name);
+ if (mod->handle == NULL)
+ return;
+ if (mod->unregister != NULL)
+ mod->unregister(mod->mtab, mod->mtabsize);
+ if (mod->handle != nss_builtin_handle)
+ (void)dlclose(mod->handle);
+}
+
+
+
+/*
+ * Cleanup
+ */
+static void
+nss_atexit(void)
+{
+ int isthreaded;
+
+ isthreaded = __isthreaded;
+ if (isthreaded)
+ (void)_pthread_rwlock_wrlock(&nss_lock);
+ VECTOR_FREE(_nsmap, &_nsmapsize, sizeof(*_nsmap),
+ (vector_free_elem)ns_dbt_free);
+ VECTOR_FREE(_nsmod, &_nsmodsize, sizeof(*_nsmod),
+ (vector_free_elem)ns_mod_free);
+ if (isthreaded)
+ (void)_pthread_rwlock_unlock(&nss_lock);
+}
+
+
+
+/*
+ * Finally, the actual implementation.
+ */
+static nss_method
+nss_method_lookup(const char *source, const char *database,
+ const char *method, const ns_dtab disp_tab[], void **mdata)
+{
+ ns_mod *mod;
+ ns_mtab *match, key;
+ int i;
+
+ if (disp_tab != NULL)
+ for (i = 0; disp_tab[i].src != NULL; i++)
+ if (strcasecmp(source, disp_tab[i].src) == 0) {
+ *mdata = disp_tab[i].mdata;
+ return (disp_tab[i].method);
+ }
+ mod = vector_search(&source, _nsmod, _nsmodsize, sizeof(*_nsmod),
+ string_compare);
+ if (mod != NULL && mod->handle != NULL) {
+ key.database = database;
+ key.name = method;
+ match = bsearch(&key, mod->mtab, mod->mtabsize,
+ sizeof(mod->mtab[0]), mtab_compare);
+ if (match != NULL) {
+ *mdata = match->mdata;
+ return (match->method);
+ }
+ }
+
+ *mdata = NULL;
+ return (NULL);
+}
+
+static void
+fb_endstate(void *p)
+{
+ free(p);
+}
+
+__weak_reference(_nsdispatch, nsdispatch);
+
+int
+_nsdispatch(void *retval, const ns_dtab disp_tab[], const char *database,
+ const char *method_name, const ns_src defaults[], ...)
+{
+ va_list ap;
+ const ns_dbt *dbt;
+ const ns_src *srclist;
+ nss_method method, fb_method;
+ void *mdata;
+ int isthreaded, serrno, i, result, srclistsize;
+ struct fb_state *st;
+
+#ifdef NS_CACHING
+ nss_cache_data cache_data;
+ nss_cache_data *cache_data_p;
+ int cache_flag;
+#endif
+
+ dbt = NULL;
+ fb_method = NULL;
+
+ isthreaded = __isthreaded;
+ serrno = errno;
+ if (isthreaded) {
+ result = _pthread_rwlock_rdlock(&nss_lock);
+ if (result != 0) {
+ result = NS_UNAVAIL;
+ goto fin;
+ }
+ }
+
+ result = fb_getstate(&st);
+ if (result != 0) {
+ result = NS_UNAVAIL;
+ goto fin;
+ }
+
+ result = nss_configure();
+ if (result != 0) {
+ result = NS_UNAVAIL;
+ goto fin;
+ }
+ if (st->fb_dispatch == 0) {
+ dbt = vector_search(&database, _nsmap, _nsmapsize, sizeof(*_nsmap),
+ string_compare);
+ fb_method = nss_method_lookup(NSSRC_FALLBACK, database,
+ method_name, disp_tab, &mdata);
+ }
+
+ if (dbt != NULL) {
+ srclist = dbt->srclist;
+ srclistsize = dbt->srclistsize;
+ } else {
+ srclist = defaults;
+ srclistsize = 0;
+ while (srclist[srclistsize].name != NULL)
+ srclistsize++;
+ }
+
+#ifdef NS_CACHING
+ cache_data_p = NULL;
+ cache_flag = 0;
+#endif
+ for (i = 0; i < srclistsize; i++) {
+ result = NS_NOTFOUND;
+ method = nss_method_lookup(srclist[i].name, database,
+ method_name, disp_tab, &mdata);
+
+ if (method != NULL) {
+#ifdef NS_CACHING
+ if (strcmp(srclist[i].name, NSSRC_CACHE) == 0 &&
+ nss_cache_cycle_prevention_func == NULL) {
+#ifdef NS_STRICT_LIBC_EID_CHECKING
+ if (issetugid() != 0)
+ continue;
+#endif
+ cache_flag = 1;
+
+ memset(&cache_data, 0, sizeof(nss_cache_data));
+ cache_data.info = (nss_cache_info const *)mdata;
+ cache_data_p = &cache_data;
+
+ va_start(ap, defaults);
+ if (cache_data.info->id_func != NULL)
+ result = __nss_common_cache_read(retval,
+ cache_data_p, ap);
+ else if (cache_data.info->marshal_func != NULL)
+ result = __nss_mp_cache_read(retval,
+ cache_data_p, ap);
+ else
+ result = __nss_mp_cache_end(retval,
+ cache_data_p, ap);
+ va_end(ap);
+ } else {
+ cache_flag = 0;
+ errno = 0;
+ va_start(ap, defaults);
+ result = method(retval, mdata, ap);
+ va_end(ap);
+ }
+#else /* NS_CACHING */
+ errno = 0;
+ va_start(ap, defaults);
+ result = method(retval, mdata, ap);
+ va_end(ap);
+#endif /* NS_CACHING */
+
+ if (result & (srclist[i].flags))
+ break;
+ } else {
+ if (fb_method != NULL) {
+ st->fb_dispatch = 1;
+ va_start(ap, defaults);
+ result = fb_method(retval,
+ (void *)srclist[i].name, ap);
+ va_end(ap);
+ st->fb_dispatch = 0;
+ } else
+ nss_log(LOG_DEBUG, "%s, %s, %s, not found, "
+ "and no fallback provided",
+ srclist[i].name, database, method_name);
+ }
+ }
+
+#ifdef NS_CACHING
+ if (cache_data_p != NULL &&
+ (result & (NS_NOTFOUND | NS_SUCCESS)) && cache_flag == 0) {
+ va_start(ap, defaults);
+ if (result == NS_SUCCESS) {
+ if (cache_data.info->id_func != NULL)
+ __nss_common_cache_write(retval, cache_data_p,
+ ap);
+ else if (cache_data.info->marshal_func != NULL)
+ __nss_mp_cache_write(retval, cache_data_p, ap);
+ } else if (result == NS_NOTFOUND) {
+ if (cache_data.info->id_func == NULL) {
+ if (cache_data.info->marshal_func != NULL)
+ __nss_mp_cache_write_submit(retval,
+ cache_data_p, ap);
+ } else
+ __nss_common_cache_write_negative(cache_data_p);
+ }
+ va_end(ap);
+ }
+#endif /* NS_CACHING */
+
+ if (isthreaded)
+ (void)_pthread_rwlock_unlock(&nss_lock);
+fin:
+ errno = serrno;
+ return (result);
+}
diff --git a/lib/libc/net/nslexer.l b/lib/libc/net/nslexer.l
new file mode 100644
index 0000000..0f705cf
--- /dev/null
+++ b/lib/libc/net/nslexer.l
@@ -0,0 +1,120 @@
+%{
+/* $NetBSD: nslexer.l,v 1.3 1999/01/25 00:16:17 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid =
+ "$FreeBSD$";
+#endif /* LIBC_SCCS and not lint */
+
+#include "namespace.h"
+#include <ctype.h>
+#define _NS_PRIVATE
+#include <nsswitch.h>
+#include <string.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+#include "nsparser.h"
+
+#define YY_NO_INPUT
+#define YY_NO_UNPUT
+
+%}
+
+%option yylineno
+
+BLANK [ \t]
+CR \n
+STRING [a-zA-Z][a-zA-Z0-9_]*
+
+%%
+
+{BLANK}+ ; /* skip whitespace */
+
+#.* ; /* skip comments */
+
+\\{CR} ; /* allow continuation */
+
+{CR} return NL;
+
+[sS][uU][cC][cC][eE][sS][sS] return SUCCESS;
+[uU][nN][aA][vV][aA][iI][lL] return UNAVAIL;
+[nN][oO][tT][fF][oO][uU][nN][dD] return NOTFOUND;
+[tT][rR][yY][aA][gG][aA][iI][nN] return TRYAGAIN;
+
+[rR][eE][tT][uU][rR][nN] return RETURN;
+[cC][oO][nN][tT][iI][nN][uU][eE] return CONTINUE;
+
+{STRING} {
+ char *p;
+ int i;
+
+ if ((p = strdup(yytext)) == NULL) {
+ syslog(LOG_ERR,
+ "NSSWITCH(nslexer): memory allocation failure");
+ return ERRORTOKEN;
+ }
+ for (i = 0; i < strlen(p); i++) {
+ if (isupper((unsigned char)p[i]))
+ p[i] = tolower((unsigned char)p[i]);
+ }
+ _nsyylval.str = p;
+ return STRING;
+ }
+
+. return yytext[0];
+
+%%
+
+#undef _nsyywrap
+int
+_nsyywrap()
+{
+ return 1;
+} /* _nsyywrap */
+
+void
+_nsyyerror(msg)
+ const char *msg;
+{
+
+ syslog(LOG_ERR, "NSSWITCH(nslexer): %s line %d: %s at '%s'",
+ _PATH_NS_CONF, yylineno, msg, yytext);
+} /* _nsyyerror */
diff --git a/lib/libc/net/nsparser.y b/lib/libc/net/nsparser.y
new file mode 100644
index 0000000..730458a
--- /dev/null
+++ b/lib/libc/net/nsparser.y
@@ -0,0 +1,184 @@
+%{
+/* $NetBSD: nsparser.y,v 1.3 1999/01/25 00:16:18 lukem Exp $ */
+
+/*-
+ * Copyright (c) 1997, 1998, 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Luke Mewburn.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#define _NS_PRIVATE
+#include <nsswitch.h>
+#include <stdio.h>
+#include <string.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+static void _nsaddsrctomap(const char *);
+
+static ns_dbt curdbt;
+static ns_src cursrc;
+%}
+
+%union {
+ char *str;
+ int mapval;
+}
+
+%token NL
+%token SUCCESS UNAVAIL NOTFOUND TRYAGAIN
+%token RETURN CONTINUE
+%token ERRORTOKEN
+%token <str> STRING
+
+%type <mapval> Status Action
+
+%%
+
+File
+ : /* empty */
+ | Lines
+ ;
+
+Lines
+ : Entry
+ | Lines Entry
+ ;
+
+Entry
+ : NL
+ | Database ':' NL
+ {
+ free((char*)curdbt.name);
+ }
+ | Database ':' Srclist NL
+ {
+ _nsdbtput(&curdbt);
+ }
+ | error NL
+ {
+ yyerrok;
+ }
+ ;
+
+Database
+ : STRING
+ {
+ curdbt.name = yylval.str;
+ curdbt.srclist = NULL;
+ curdbt.srclistsize = 0;
+ }
+ ;
+
+Srclist
+ : Item
+ | Srclist Item
+ ;
+
+Item
+ : STRING
+ {
+ cursrc.flags = NS_TERMINATE;
+ _nsaddsrctomap($1);
+ }
+ | STRING '[' { cursrc.flags = NS_SUCCESS; } Criteria ']'
+ {
+ _nsaddsrctomap($1);
+ }
+ ;
+
+Criteria
+ : Criterion
+ | Criteria Criterion
+ ;
+
+Criterion
+ : Status '=' Action
+ {
+ if ($3) /* if action == RETURN set RETURN bit */
+ cursrc.flags |= $1;
+ else /* else unset it */
+ cursrc.flags &= ~$1;
+ }
+ ;
+
+Status
+ : SUCCESS { $$ = NS_SUCCESS; }
+ | UNAVAIL { $$ = NS_UNAVAIL; }
+ | NOTFOUND { $$ = NS_NOTFOUND; }
+ | TRYAGAIN { $$ = NS_TRYAGAIN; }
+ ;
+
+Action
+ : RETURN { $$ = NS_ACTION_RETURN; }
+ | CONTINUE { $$ = NS_ACTION_CONTINUE; }
+ ;
+
+%%
+
+static void
+_nsaddsrctomap(elem)
+ const char *elem;
+{
+ int i, lineno;
+ extern int _nsyylineno;
+ extern char * _nsyytext;
+
+ lineno = _nsyylineno - (*_nsyytext == '\n' ? 1 : 0);
+ if (curdbt.srclistsize > 0) {
+ if (((strcasecmp(elem, NSSRC_COMPAT) == 0) &&
+ (strcasecmp(curdbt.srclist[0].name, NSSRC_CACHE) != 0)) ||
+ (strcasecmp(curdbt.srclist[0].name, NSSRC_COMPAT) == 0)) {
+ syslog(LOG_ERR,
+ "NSSWITCH(nsparser): %s line %d: 'compat' used with sources, other than 'cache'",
+ _PATH_NS_CONF, lineno);
+ free((void*)elem);
+ return;
+ }
+ }
+ for (i = 0; i < curdbt.srclistsize; i++) {
+ if (strcasecmp(curdbt.srclist[i].name, elem) == 0) {
+ syslog(LOG_ERR,
+ "NSSWITCH(nsparser): %s line %d: duplicate source '%s'",
+ _PATH_NS_CONF, lineno, elem);
+ free((void*)elem);
+ return;
+ }
+ }
+ cursrc.name = elem;
+ _nsdbtaddsrc(&curdbt, &cursrc);
+}
diff --git a/lib/libc/net/nss_backends.h b/lib/libc/net/nss_backends.h
new file mode 100644
index 0000000..9bea37b
--- /dev/null
+++ b/lib/libc/net/nss_backends.h
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/*
+ * Eventually, the implementations of existing built-in NSS functions
+ * may be moved into NSS modules and live here.
+ */
+#if 0
+NSS_BACKEND( files, _files_nss_module_register )
+NSS_BACKEND( dns, _dns_nss_module_register )
+NSS_BACKEND( nis, _nis_nss_module_register )
+NSS_BACKEND( compat, _compat_nss_module_register )
+#endif
diff --git a/lib/libc/net/nss_compat.c b/lib/libc/net/nss_compat.c
new file mode 100644
index 0000000..09a2d4f
--- /dev/null
+++ b/lib/libc/net/nss_compat.c
@@ -0,0 +1,278 @@
+/*-
+ * Copyright (c) 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project by
+ * Jacques A. Vidrine, Safeport Network Services, and Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035
+ * ("CBOSS"), as part of the DARPA CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Compatibility shims for the GNU C Library-style nsswitch interface.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <errno.h>
+#include <nss.h>
+#include <pthread.h>
+#include <pthread_np.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+
+struct group;
+struct passwd;
+
+static int terminator;
+
+#define DECLARE_TERMINATOR(x) \
+static pthread_key_t _term_key_##x; \
+static void \
+_term_create_##x(void) \
+{ \
+ (void)_pthread_key_create(&_term_key_##x, NULL); \
+} \
+static void *_term_main_##x; \
+static pthread_once_t _term_once_##x = PTHREAD_ONCE_INIT
+
+#define SET_TERMINATOR(x, y) \
+do { \
+ if (!__isthreaded || _pthread_main_np()) \
+ _term_main_##x = (y); \
+ else { \
+ (void)_pthread_once(&_term_once_##x, _term_create_##x); \
+ (void)_pthread_setspecific(_term_key_##x, y); \
+ } \
+} while (0)
+
+#define CHECK_TERMINATOR(x) \
+(!__isthreaded || _pthread_main_np() ? \
+ (_term_main_##x) : \
+ ((void)_pthread_once(&_term_once_##x, _term_create_##x), \
+ _pthread_getspecific(_term_key_##x)))
+
+
+
+DECLARE_TERMINATOR(group);
+
+
+int
+__nss_compat_getgrnam_r(void *retval, void *mdata, va_list ap)
+{
+ int (*fn)(const char *, struct group *, char *, size_t, int *);
+ const char *name;
+ struct group *grp;
+ char *buffer;
+ int *errnop;
+ size_t bufsize;
+ enum nss_status status;
+
+ fn = mdata;
+ name = va_arg(ap, const char *);
+ grp = va_arg(ap, struct group *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ status = fn(name, grp, buffer, bufsize, errnop);
+ status = __nss_compat_result(status, *errnop);
+ if (status == NS_SUCCESS)
+ *(struct group **)retval = grp;
+ return (status);
+}
+
+
+int
+__nss_compat_getgrgid_r(void *retval, void *mdata, va_list ap)
+{
+ int (*fn)(gid_t, struct group *, char *, size_t, int *);
+ gid_t gid;
+ struct group *grp;
+ char *buffer;
+ int *errnop;
+ size_t bufsize;
+ enum nss_status status;
+
+ fn = mdata;
+ gid = va_arg(ap, gid_t);
+ grp = va_arg(ap, struct group *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ status = fn(gid, grp, buffer, bufsize, errnop);
+ status = __nss_compat_result(status, *errnop);
+ if (status == NS_SUCCESS)
+ *(struct group **)retval = grp;
+ return (status);
+}
+
+
+int
+__nss_compat_getgrent_r(void *retval, void *mdata, va_list ap)
+{
+ int (*fn)(struct group *, char *, size_t, int *);
+ struct group *grp;
+ char *buffer;
+ int *errnop;
+ size_t bufsize;
+ enum nss_status status;
+
+ if (CHECK_TERMINATOR(group))
+ return (NS_NOTFOUND);
+ fn = mdata;
+ grp = va_arg(ap, struct group *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ status = fn(grp, buffer, bufsize, errnop);
+ status = __nss_compat_result(status, *errnop);
+ if (status == NS_SUCCESS)
+ *(struct group **)retval = grp;
+ else if (status != NS_RETURN)
+ SET_TERMINATOR(group, &terminator);
+ return (status);
+}
+
+
+int
+__nss_compat_setgrent(void *retval, void *mdata, va_list ap)
+{
+
+ SET_TERMINATOR(group, NULL);
+ ((int (*)(void))mdata)();
+ return (NS_UNAVAIL);
+}
+
+
+int
+__nss_compat_endgrent(void *retval, void *mdata, va_list ap)
+{
+
+ SET_TERMINATOR(group, NULL);
+ ((int (*)(void))mdata)();
+ return (NS_UNAVAIL);
+}
+
+
+
+DECLARE_TERMINATOR(passwd);
+
+
+int
+__nss_compat_getpwnam_r(void *retval, void *mdata, va_list ap)
+{
+ int (*fn)(const char *, struct passwd *, char *, size_t, int *);
+ const char *name;
+ struct passwd *pwd;
+ char *buffer;
+ int *errnop;
+ size_t bufsize;
+ enum nss_status status;
+
+ fn = mdata;
+ name = va_arg(ap, const char *);
+ pwd = va_arg(ap, struct passwd *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ status = fn(name, pwd, buffer, bufsize, errnop);
+ status = __nss_compat_result(status, *errnop);
+ if (status == NS_SUCCESS)
+ *(struct passwd **)retval = pwd;
+ return (status);
+}
+
+
+int
+__nss_compat_getpwuid_r(void *retval, void *mdata, va_list ap)
+{
+ int (*fn)(uid_t, struct passwd *, char *, size_t, int *);
+ uid_t uid;
+ struct passwd *pwd;
+ char *buffer;
+ int *errnop;
+ size_t bufsize;
+ enum nss_status status;
+
+ fn = mdata;
+ uid = va_arg(ap, uid_t);
+ pwd = va_arg(ap, struct passwd *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ status = fn(uid, pwd, buffer, bufsize, errnop);
+ status = __nss_compat_result(status, *errnop);
+ if (status == NS_SUCCESS)
+ *(struct passwd **)retval = pwd;
+ return (status);
+}
+
+
+int
+__nss_compat_getpwent_r(void *retval, void *mdata, va_list ap)
+{
+ int (*fn)(struct passwd *, char *, size_t, int *);
+ struct passwd *pwd;
+ char *buffer;
+ int *errnop;
+ size_t bufsize;
+ enum nss_status status;
+
+ if (CHECK_TERMINATOR(passwd))
+ return (NS_NOTFOUND);
+ fn = mdata;
+ pwd = va_arg(ap, struct passwd *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+ status = fn(pwd, buffer, bufsize, errnop);
+ status = __nss_compat_result(status, *errnop);
+ if (status == NS_SUCCESS)
+ *(struct passwd **)retval = pwd;
+ else if (status != NS_RETURN)
+ SET_TERMINATOR(passwd, &terminator);
+ return (status);
+}
+
+
+int
+__nss_compat_setpwent(void *retval, void *mdata, va_list ap)
+{
+
+ SET_TERMINATOR(passwd, NULL);
+ ((int (*)(void))mdata)();
+ return (NS_UNAVAIL);
+}
+
+
+int
+__nss_compat_endpwent(void *retval, void *mdata, va_list ap)
+{
+
+ SET_TERMINATOR(passwd, NULL);
+ ((int (*)(void))mdata)();
+ return (NS_UNAVAIL);
+}
diff --git a/lib/libc/net/ntoh.c b/lib/libc/net/ntoh.c
new file mode 100644
index 0000000..738d8c7
--- /dev/null
+++ b/lib/libc/net/ntoh.c
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2006 Olivier Houchard
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/endian.h>
+
+uint32_t
+htonl(uint32_t hl)
+{
+
+ return (__htonl(hl));
+}
+
+uint16_t
+htons(uint16_t hs)
+{
+
+ return (__htons(hs));
+}
+
+uint32_t
+ntohl(uint32_t nl)
+{
+
+ return (__ntohl(nl));
+}
+
+uint16_t
+ntohs(uint16_t ns)
+{
+
+ return (__ntohs(ns));
+}
diff --git a/lib/libc/net/rcmd.3 b/lib/libc/net/rcmd.3
new file mode 100644
index 0000000..1cd4327
--- /dev/null
+++ b/lib/libc/net/rcmd.3
@@ -0,0 +1,306 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)rcmd.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd March 3, 2000
+.Dt RCMD 3
+.Os
+.Sh NAME
+.Nm rcmd ,
+.Nm rresvport ,
+.Nm iruserok ,
+.Nm ruserok ,
+.Nm rcmd_af ,
+.Nm rresvport_af ,
+.Nm iruserok_sa
+.Nd routines for returning a stream to a remote command
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn rcmd "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p"
+.Ft int
+.Fn rresvport "int *port"
+.Ft int
+.Fn iruserok "u_long raddr" "int superuser" "const char *ruser" "const char *luser"
+.Ft int
+.Fn ruserok "const char *rhost" "int superuser" "const char *ruser" "const char *luser"
+.Ft int
+.Fn rcmd_af "char **ahost" "int inport" "const char *locuser" "const char *remuser" "const char *cmd" "int *fd2p" "int af"
+.Ft int
+.Fn rresvport_af "int *port" "int af"
+.Ft int
+.Fn iruserok_sa "const void *addr" "int addrlen" "int superuser" "const char *ruser" "const char *luser"
+.Sh DESCRIPTION
+The
+.Fn rcmd
+function
+is used by the super-user to execute a command on
+a remote machine using an authentication scheme based
+on reserved port numbers.
+The
+.Fn rresvport
+function
+returns a descriptor to a socket
+with an address in the privileged port space.
+The
+.Fn ruserok
+function
+is used by servers
+to authenticate clients requesting service with
+.Fn rcmd .
+All three functions are present in the same file and are used
+by the
+.Xr rshd 8
+server (among others).
+.Pp
+The
+.Fn rcmd
+function
+looks up the host
+.Fa *ahost
+using
+.Xr gethostbyname 3 ,
+returning -1 if the host does not exist.
+Otherwise
+.Fa *ahost
+is set to the standard name of the host
+and a connection is established to a server
+residing at the well-known Internet port
+.Fa inport .
+.Pp
+If the connection succeeds,
+a socket in the Internet domain of type
+.Dv SOCK_STREAM
+is returned to the caller, and given to the remote
+command as
+.Dv stdin
+and
+.Dv stdout .
+If
+.Fa fd2p
+is non-zero, then an auxiliary channel to a control
+process will be set up, and a descriptor for it will be placed
+in
+.Fa *fd2p .
+The control process will return diagnostic
+output from the command (unit 2) on this channel, and will also
+accept bytes on this channel as being
+.Ux
+signal numbers, to be
+forwarded to the process group of the command.
+If
+.Fa fd2p
+is 0, then the
+.Dv stderr
+(unit 2 of the remote
+command) will be made the same as the
+.Dv stdout
+and no
+provision is made for sending arbitrary signals to the remote process,
+although you may be able to get its attention by using out-of-band data.
+.Pp
+The protocol is described in detail in
+.Xr rshd 8 .
+.Pp
+The
+.Fn rresvport
+function is used to obtain a socket to which an address with a Privileged
+Internet port is bound.
+This socket is suitable for use by
+.Fn rcmd
+and several other functions.
+Privileged Internet ports are those in the range 0 to 1023.
+Only the super-user is allowed to bind an address of this sort
+to a socket.
+.Pp
+The
+.Fn iruserok
+and
+.Fn ruserok
+functions take a remote host's IP address or name, as returned by the
+.Xr gethostbyname 3
+routines, two user names and a flag indicating whether the local user's
+name is that of the super-user.
+Then, if the user is
+.Em NOT
+the super-user, it checks the
+.Pa /etc/hosts.equiv
+file.
+If that lookup is not done, or is unsuccessful, the
+.Pa .rhosts
+in the local user's home directory is checked to see if the request for
+service is allowed.
+.Pp
+If this file does not exist, is not a regular file, is owned by anyone
+other than the user or the super-user, or is writable by anyone other
+than the owner, the check automatically fails.
+Zero is returned if the machine name is listed in the
+.Dq Pa hosts.equiv
+file, or the host and remote user name are found in the
+.Dq Pa .rhosts
+file; otherwise
+.Fn iruserok
+and
+.Fn ruserok
+return -1.
+If the local domain (as obtained from
+.Xr gethostname 3 )
+is the same as the remote domain, only the machine name need be specified.
+.Pp
+The
+.Fn iruserok
+function is strongly preferred for security reasons.
+It requires trusting the local DNS at most, while the
+.Fn ruserok
+function requires trusting the entire DNS, which can be spoofed.
+.Pp
+The functions with an
+.Dq Li _af
+or
+.Dq Li _sa
+suffix, i.e.,
+.Fn rcmd_af ,
+.Fn rresvport_af
+and
+.Fn iruserok_sa ,
+work the same as the corresponding functions without a
+suffix, except that they are capable of handling both IPv6 and IPv4 ports.
+.Pp
+The
+.Dq Li _af
+suffix means that the function has an additional
+.Fa af
+argument which is used to specify the address family,
+(see below).
+The
+.Fa af
+argument extension is implemented for functions
+that have no binary address argument.
+Instead, the
+.Fa af
+argument specifies which address family is desired.
+.Pp
+The
+.Dq Li _sa
+suffix means that the function has general socket address and
+length arguments.
+As the socket address is a protocol independent data structure,
+IPv4 and IPv6 socket address can be passed as desired.
+The
+.Fa sa
+argument extension is implemented for functions
+that pass a protocol dependent binary address argument.
+The argument needs to be replaced with a more general address structure
+to support multiple address families in a general way.
+.Pp
+The functions with neither an
+.Dq Li _af
+suffix nor an
+.Dq Li _sa
+suffix work for IPv4 only, except for
+.Fn ruserok
+which can handle both IPv6 and IPv4.
+To switch the address family, the
+.Fa af
+argument must be filled with
+.Dv AF_INET ,
+or
+.Dv AF_INET6 .
+For
+.Fn rcmd_af ,
+.Dv PF_UNSPEC
+is also allowed.
+.Sh ENVIRONMENT
+.Bl -tag -width RSH
+.It Ev RSH
+When using the
+.Fn rcmd
+function, this variable is used as the program to run instead of
+.Xr rsh 1 .
+.El
+.Sh DIAGNOSTICS
+The
+.Fn rcmd
+function
+returns a valid socket descriptor on success.
+It returns -1 on error and prints a diagnostic message
+on the standard error.
+.Pp
+The
+.Fn rresvport
+function
+returns a valid, bound socket descriptor on success.
+It returns -1 on error with the global value
+.Va errno
+set according to the reason for failure.
+The error code
+.Er EAGAIN
+is overloaded to mean ``All network ports in use.''
+.Sh SEE ALSO
+.Xr rlogin 1 ,
+.Xr rsh 1 ,
+.Xr intro 2 ,
+.Xr rlogind 8 ,
+.Xr rshd 8
+.Pp
+.Rs
+.%A W. Stevens
+.%A M. Thomas
+.%T "Advanced Socket API for IPv6"
+.%O RFC2292
+.Re
+.Rs
+.%A W. Stevens
+.%A M. Thomas
+.%A E. Nordmark
+.%T "Advanced Socket API for IPv6"
+.%O RFC3542
+.Re
+.Sh HISTORY
+Most of these
+functions appeared in
+.Bx 4.2 .
+The
+.Fn rresvport_af
+function
+appeared in RFC2292, and was implemented by the WIDE project
+for the Hydrangea IPv6 protocol stack kit.
+The
+.Fn rcmd_af
+function
+appeared in draft-ietf-ipngwg-rfc2292bis-01.txt,
+and was implemented in the WIDE/KAME IPv6 protocol stack kit.
+The
+.Fn iruserok_sa
+function
+appeared in discussion on the IETF ipngwg mailing list,
+and was implemented in
+.Fx 4.0 .
diff --git a/lib/libc/net/rcmd.c b/lib/libc/net/rcmd.c
new file mode 100644
index 0000000..990289a
--- /dev/null
+++ b/lib/libc/net/rcmd.c
@@ -0,0 +1,761 @@
+/*
+ * Copyright (c) 1983, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rcmd.c 8.3 (Berkeley) 3/26/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/stat.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <signal.h>
+#include <fcntl.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pwd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#ifdef YP
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <arpa/nameser.h>
+#include "un-namespace.h"
+
+extern int innetgr( const char *, const char *, const char *, const char * );
+
+#define max(a, b) ((a > b) ? a : b)
+
+int __ivaliduser(FILE *, u_int32_t, const char *, const char *);
+int __ivaliduser_af(FILE *,const void *, const char *, const char *, int, int);
+int __ivaliduser_sa(FILE *, const struct sockaddr *, socklen_t, const char *,
+ const char *);
+static int __icheckhost(const struct sockaddr *, socklen_t, const char *);
+
+char paddr[NI_MAXHOST];
+
+int
+rcmd(ahost, rport, locuser, remuser, cmd, fd2p)
+ char **ahost;
+ u_short rport;
+ const char *locuser, *remuser, *cmd;
+ int *fd2p;
+{
+ return rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, AF_INET);
+}
+
+int
+rcmd_af(ahost, rport, locuser, remuser, cmd, fd2p, af)
+ char **ahost;
+ u_short rport;
+ const char *locuser, *remuser, *cmd;
+ int *fd2p;
+ int af;
+{
+ struct addrinfo hints, *res, *ai;
+ struct sockaddr_storage from;
+ fd_set reads;
+ sigset_t oldmask, newmask;
+ pid_t pid;
+ int s, aport, lport, timo, error;
+ char c, *p;
+ int refused, nres;
+ char num[8];
+ static char canonnamebuf[MAXDNAME]; /* is it proper here? */
+
+ /* call rcmdsh() with specified remote shell if appropriate. */
+ if (!issetugid() && (p = getenv("RSH"))) {
+ struct servent *sp = getservbyname("shell", "tcp");
+
+ if (sp && sp->s_port == rport)
+ return (rcmdsh(ahost, rport, locuser, remuser,
+ cmd, p));
+ }
+
+ /* use rsh(1) if non-root and remote port is shell. */
+ if (geteuid()) {
+ struct servent *sp = getservbyname("shell", "tcp");
+
+ if (sp && sp->s_port == rport)
+ return (rcmdsh(ahost, rport, locuser, remuser,
+ cmd, NULL));
+ }
+
+ pid = getpid();
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = af;
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_protocol = 0;
+ (void)snprintf(num, sizeof(num), "%d", ntohs(rport));
+ error = getaddrinfo(*ahost, num, &hints, &res);
+ if (error) {
+ fprintf(stderr, "rcmd: getaddrinfo: %s\n",
+ gai_strerror(error));
+ if (error == EAI_SYSTEM)
+ fprintf(stderr, "rcmd: getaddrinfo: %s\n",
+ strerror(errno));
+ return (-1);
+ }
+
+ if (res->ai_canonname
+ && strlen(res->ai_canonname) + 1 < sizeof(canonnamebuf)) {
+ strncpy(canonnamebuf, res->ai_canonname, sizeof(canonnamebuf));
+ *ahost = canonnamebuf;
+ }
+ nres = 0;
+ for (ai = res; ai; ai = ai->ai_next)
+ nres++;
+ ai = res;
+ refused = 0;
+ sigemptyset(&newmask);
+ sigaddset(&newmask, SIGURG);
+ _sigprocmask(SIG_BLOCK, (const sigset_t *)&newmask, &oldmask);
+ for (timo = 1, lport = IPPORT_RESERVED - 1;;) {
+ s = rresvport_af(&lport, ai->ai_family);
+ if (s < 0) {
+ if (errno != EAGAIN && ai->ai_next) {
+ ai = ai->ai_next;
+ continue;
+ }
+ if (errno == EAGAIN)
+ (void)fprintf(stderr,
+ "rcmd: socket: All ports in use\n");
+ else
+ (void)fprintf(stderr, "rcmd: socket: %s\n",
+ strerror(errno));
+ freeaddrinfo(res);
+ _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask,
+ NULL);
+ return (-1);
+ }
+ _fcntl(s, F_SETOWN, pid);
+ if (_connect(s, ai->ai_addr, ai->ai_addrlen) >= 0)
+ break;
+ (void)_close(s);
+ if (errno == EADDRINUSE) {
+ lport--;
+ continue;
+ }
+ if (errno == ECONNREFUSED)
+ refused = 1;
+ if (ai->ai_next == NULL && (!refused || timo > 16)) {
+ (void)fprintf(stderr, "%s: %s\n",
+ *ahost, strerror(errno));
+ freeaddrinfo(res);
+ _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask,
+ NULL);
+ return (-1);
+ }
+ if (nres > 1) {
+ int oerrno = errno;
+
+ getnameinfo(ai->ai_addr, ai->ai_addrlen, paddr,
+ sizeof(paddr), NULL, 0, NI_NUMERICHOST);
+ (void)fprintf(stderr, "connect to address %s: ",
+ paddr);
+ errno = oerrno;
+ perror(0);
+ }
+ if ((ai = ai->ai_next) == NULL) {
+ /* refused && timo <= 16 */
+ struct timespec time_to_sleep, time_remaining;
+
+ time_to_sleep.tv_sec = timo;
+ time_to_sleep.tv_nsec = 0;
+ (void)_nanosleep(&time_to_sleep, &time_remaining);
+ timo *= 2;
+ ai = res;
+ refused = 0;
+ }
+ if (nres > 1) {
+ getnameinfo(ai->ai_addr, ai->ai_addrlen, paddr,
+ sizeof(paddr), NULL, 0, NI_NUMERICHOST);
+ fprintf(stderr, "Trying %s...\n", paddr);
+ }
+ }
+ lport--;
+ if (fd2p == 0) {
+ _write(s, "", 1);
+ lport = 0;
+ } else {
+ int s2 = rresvport_af(&lport, ai->ai_family), s3;
+ socklen_t len = ai->ai_addrlen;
+ int nfds;
+
+ if (s2 < 0)
+ goto bad;
+ _listen(s2, 1);
+ (void)snprintf(num, sizeof(num), "%d", lport);
+ if (_write(s, num, strlen(num)+1) != strlen(num)+1) {
+ (void)fprintf(stderr,
+ "rcmd: write (setting up stderr): %s\n",
+ strerror(errno));
+ (void)_close(s2);
+ goto bad;
+ }
+ nfds = max(s, s2)+1;
+ if(nfds > FD_SETSIZE) {
+ fprintf(stderr, "rcmd: too many files\n");
+ (void)_close(s2);
+ goto bad;
+ }
+again:
+ FD_ZERO(&reads);
+ FD_SET(s, &reads);
+ FD_SET(s2, &reads);
+ errno = 0;
+ if (_select(nfds, &reads, 0, 0, 0) < 1 || !FD_ISSET(s2, &reads)){
+ if (errno != 0)
+ (void)fprintf(stderr,
+ "rcmd: select (setting up stderr): %s\n",
+ strerror(errno));
+ else
+ (void)fprintf(stderr,
+ "select: protocol failure in circuit setup\n");
+ (void)_close(s2);
+ goto bad;
+ }
+ s3 = _accept(s2, (struct sockaddr *)&from, &len);
+ switch (from.ss_family) {
+ case AF_INET:
+ aport = ntohs(((struct sockaddr_in *)&from)->sin_port);
+ break;
+#ifdef INET6
+ case AF_INET6:
+ aport = ntohs(((struct sockaddr_in6 *)&from)->sin6_port);
+ break;
+#endif
+ default:
+ aport = 0; /* error */
+ break;
+ }
+ /*
+ * XXX careful for ftp bounce attacks. If discovered, shut them
+ * down and check for the real auxiliary channel to connect.
+ */
+ if (aport == 20) {
+ _close(s3);
+ goto again;
+ }
+ (void)_close(s2);
+ if (s3 < 0) {
+ (void)fprintf(stderr,
+ "rcmd: accept: %s\n", strerror(errno));
+ lport = 0;
+ goto bad;
+ }
+ *fd2p = s3;
+ if (aport >= IPPORT_RESERVED || aport < IPPORT_RESERVED / 2) {
+ (void)fprintf(stderr,
+ "socket: protocol failure in circuit setup.\n");
+ goto bad2;
+ }
+ }
+ (void)_write(s, locuser, strlen(locuser)+1);
+ (void)_write(s, remuser, strlen(remuser)+1);
+ (void)_write(s, cmd, strlen(cmd)+1);
+ if (_read(s, &c, 1) != 1) {
+ (void)fprintf(stderr,
+ "rcmd: %s: %s\n", *ahost, strerror(errno));
+ goto bad2;
+ }
+ if (c != 0) {
+ while (_read(s, &c, 1) == 1) {
+ (void)_write(STDERR_FILENO, &c, 1);
+ if (c == '\n')
+ break;
+ }
+ goto bad2;
+ }
+ _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL);
+ freeaddrinfo(res);
+ return (s);
+bad2:
+ if (lport)
+ (void)_close(*fd2p);
+bad:
+ (void)_close(s);
+ _sigprocmask(SIG_SETMASK, (const sigset_t *)&oldmask, NULL);
+ freeaddrinfo(res);
+ return (-1);
+}
+
+int
+rresvport(port)
+ int *port;
+{
+ return rresvport_af(port, AF_INET);
+}
+
+int
+rresvport_af(alport, family)
+ int *alport, family;
+{
+ int s;
+ struct sockaddr_storage ss;
+ u_short *sport;
+
+ memset(&ss, 0, sizeof(ss));
+ ss.ss_family = family;
+ switch (family) {
+ case AF_INET:
+ ((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in);
+ sport = &((struct sockaddr_in *)&ss)->sin_port;
+ ((struct sockaddr_in *)&ss)->sin_addr.s_addr = INADDR_ANY;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ ((struct sockaddr *)&ss)->sa_len = sizeof(struct sockaddr_in6);
+ sport = &((struct sockaddr_in6 *)&ss)->sin6_port;
+ ((struct sockaddr_in6 *)&ss)->sin6_addr = in6addr_any;
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+
+ s = _socket(ss.ss_family, SOCK_STREAM, 0);
+ if (s < 0)
+ return (-1);
+#if 0 /* compat_exact_traditional_rresvport_semantics */
+ sin.sin_port = htons((u_short)*alport);
+ if (_bind(s, (struct sockaddr *)&sin, sizeof(sin)) >= 0)
+ return (s);
+ if (errno != EADDRINUSE) {
+ (void)_close(s);
+ return (-1);
+ }
+#endif
+ *sport = 0;
+ if (bindresvport_sa(s, (struct sockaddr *)&ss) == -1) {
+ (void)_close(s);
+ return (-1);
+ }
+ *alport = (int)ntohs(*sport);
+ return (s);
+}
+
+int __check_rhosts_file = 1;
+char *__rcmd_errstr;
+
+int
+ruserok(rhost, superuser, ruser, luser)
+ const char *rhost, *ruser, *luser;
+ int superuser;
+{
+ struct addrinfo hints, *res, *r;
+ int error;
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ error = getaddrinfo(rhost, "0", &hints, &res);
+ if (error)
+ return (-1);
+
+ for (r = res; r; r = r->ai_next) {
+ if (iruserok_sa(r->ai_addr, r->ai_addrlen, superuser, ruser,
+ luser) == 0) {
+ freeaddrinfo(res);
+ return (0);
+ }
+ }
+ freeaddrinfo(res);
+ return (-1);
+}
+
+/*
+ * New .rhosts strategy: We are passed an ip address. We spin through
+ * hosts.equiv and .rhosts looking for a match. When the .rhosts only
+ * has ip addresses, we don't have to trust a nameserver. When it
+ * contains hostnames, we spin through the list of addresses the nameserver
+ * gives us and look for a match.
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int
+iruserok(raddr, superuser, ruser, luser)
+ unsigned long raddr;
+ int superuser;
+ const char *ruser, *luser;
+{
+ struct sockaddr_in sin;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
+ return iruserok_sa((struct sockaddr *)&sin, sin.sin_len, superuser,
+ ruser, luser);
+}
+
+/*
+ * AF independent extension of iruserok.
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int
+iruserok_sa(ra, rlen, superuser, ruser, luser)
+ const void *ra;
+ int rlen;
+ int superuser;
+ const char *ruser, *luser;
+{
+ char *cp;
+ struct stat sbuf;
+ struct passwd *pwd;
+ FILE *hostf;
+ uid_t uid;
+ int first;
+ char pbuf[MAXPATHLEN];
+ const struct sockaddr *raddr;
+ struct sockaddr_storage ss;
+
+ /* avoid alignment issue */
+ if (rlen > sizeof(ss))
+ return(-1);
+ memcpy(&ss, ra, rlen);
+ raddr = (struct sockaddr *)&ss;
+
+ first = 1;
+ hostf = superuser ? NULL : fopen(_PATH_HEQUIV, "r");
+again:
+ if (hostf) {
+ if (__ivaliduser_sa(hostf, raddr, rlen, luser, ruser) == 0) {
+ (void)fclose(hostf);
+ return (0);
+ }
+ (void)fclose(hostf);
+ }
+ if (first == 1 && (__check_rhosts_file || superuser)) {
+ first = 0;
+ if ((pwd = getpwnam(luser)) == NULL)
+ return (-1);
+ (void)strcpy(pbuf, pwd->pw_dir);
+ (void)strcat(pbuf, "/.rhosts");
+
+ /*
+ * Change effective uid while opening .rhosts. If root and
+ * reading an NFS mounted file system, can't read files that
+ * are protected read/write owner only.
+ */
+ uid = geteuid();
+ (void)seteuid(pwd->pw_uid);
+ hostf = fopen(pbuf, "r");
+ (void)seteuid(uid);
+
+ if (hostf == NULL)
+ return (-1);
+ /*
+ * If not a regular file, or is owned by someone other than
+ * user or root or if writeable by anyone but the owner, quit.
+ */
+ cp = NULL;
+ if (lstat(pbuf, &sbuf) < 0)
+ cp = ".rhosts lstat failed";
+ else if (!S_ISREG(sbuf.st_mode))
+ cp = ".rhosts not regular file";
+ else if (_fstat(fileno(hostf), &sbuf) < 0)
+ cp = ".rhosts fstat failed";
+ else if (sbuf.st_uid && sbuf.st_uid != pwd->pw_uid)
+ cp = "bad .rhosts owner";
+ else if (sbuf.st_mode & (S_IWGRP|S_IWOTH))
+ cp = ".rhosts writeable by other than owner";
+ /* If there were any problems, quit. */
+ if (cp) {
+ __rcmd_errstr = cp;
+ (void)fclose(hostf);
+ return (-1);
+ }
+ goto again;
+ }
+ return (-1);
+}
+
+/*
+ * XXX
+ * Don't make static, used by lpd(8).
+ *
+ * Returns 0 if ok, -1 if not ok.
+ */
+int
+__ivaliduser(hostf, raddr, luser, ruser)
+ FILE *hostf;
+ u_int32_t raddr;
+ const char *luser, *ruser;
+{
+ struct sockaddr_in sin;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ memcpy(&sin.sin_addr, &raddr, sizeof(sin.sin_addr));
+ return __ivaliduser_sa(hostf, (struct sockaddr *)&sin, sin.sin_len,
+ luser, ruser);
+}
+
+/*
+ * Returns 0 if ok, -1 if not ok.
+ *
+ * XXX obsolete API.
+ */
+int
+__ivaliduser_af(hostf, raddr, luser, ruser, af, len)
+ FILE *hostf;
+ const void *raddr;
+ const char *luser, *ruser;
+ int af, len;
+{
+ struct sockaddr *sa = NULL;
+ struct sockaddr_in *sin = NULL;
+#ifdef INET6
+ struct sockaddr_in6 *sin6 = NULL;
+#endif
+ struct sockaddr_storage ss;
+
+ memset(&ss, 0, sizeof(ss));
+ switch (af) {
+ case AF_INET:
+ if (len != sizeof(sin->sin_addr))
+ return -1;
+ sin = (struct sockaddr_in *)&ss;
+ sin->sin_family = AF_INET;
+ sin->sin_len = sizeof(struct sockaddr_in);
+ memcpy(&sin->sin_addr, raddr, sizeof(sin->sin_addr));
+ break;
+#ifdef INET6
+ case AF_INET6:
+ if (len != sizeof(sin6->sin6_addr))
+ return -1;
+ /* you will lose scope info */
+ sin6 = (struct sockaddr_in6 *)&ss;
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_len = sizeof(struct sockaddr_in6);
+ memcpy(&sin6->sin6_addr, raddr, sizeof(sin6->sin6_addr));
+ break;
+#endif
+ default:
+ return -1;
+ }
+
+ sa = (struct sockaddr *)&ss;
+ return __ivaliduser_sa(hostf, sa, sa->sa_len, luser, ruser);
+}
+
+int
+__ivaliduser_sa(hostf, raddr, salen, luser, ruser)
+ FILE *hostf;
+ const struct sockaddr *raddr;
+ socklen_t salen;
+ const char *luser, *ruser;
+{
+ char *user, *p;
+ int ch;
+ char buf[MAXHOSTNAMELEN + 128]; /* host + login */
+ char hname[MAXHOSTNAMELEN];
+ /* Presumed guilty until proven innocent. */
+ int userok = 0, hostok = 0;
+#ifdef YP
+ char *ypdomain;
+
+ if (yp_get_default_domain(&ypdomain))
+ ypdomain = NULL;
+#else
+#define ypdomain NULL
+#endif
+ /* We need to get the damn hostname back for netgroup matching. */
+ if (getnameinfo(raddr, salen, hname, sizeof(hname), NULL, 0,
+ NI_NAMEREQD) != 0)
+ hname[0] = '\0';
+
+ while (fgets(buf, sizeof(buf), hostf)) {
+ p = buf;
+ /* Skip lines that are too long. */
+ if (strchr(p, '\n') == NULL) {
+ while ((ch = getc(hostf)) != '\n' && ch != EOF);
+ continue;
+ }
+ if (*p == '\n' || *p == '#') {
+ /* comment... */
+ continue;
+ }
+ while (*p != '\n' && *p != ' ' && *p != '\t' && *p != '\0') {
+ *p = isupper((unsigned char)*p) ? tolower((unsigned char)*p) : *p;
+ p++;
+ }
+ if (*p == ' ' || *p == '\t') {
+ *p++ = '\0';
+ while (*p == ' ' || *p == '\t')
+ p++;
+ user = p;
+ while (*p != '\n' && *p != ' ' &&
+ *p != '\t' && *p != '\0')
+ p++;
+ } else
+ user = p;
+ *p = '\0';
+ /*
+ * Do +/- and +@/-@ checking. This looks really nasty,
+ * but it matches SunOS's behavior so far as I can tell.
+ */
+ switch(buf[0]) {
+ case '+':
+ if (!buf[1]) { /* '+' matches all hosts */
+ hostok = 1;
+ break;
+ }
+ if (buf[1] == '@') /* match a host by netgroup */
+ hostok = hname[0] != '\0' &&
+ innetgr(&buf[2], hname, NULL, ypdomain);
+ else /* match a host by addr */
+ hostok = __icheckhost(raddr, salen,
+ (char *)&buf[1]);
+ break;
+ case '-': /* reject '-' hosts and all their users */
+ if (buf[1] == '@') {
+ if (hname[0] == '\0' ||
+ innetgr(&buf[2], hname, NULL, ypdomain))
+ return(-1);
+ } else {
+ if (__icheckhost(raddr, salen,
+ (char *)&buf[1]))
+ return(-1);
+ }
+ break;
+ default: /* if no '+' or '-', do a simple match */
+ hostok = __icheckhost(raddr, salen, buf);
+ break;
+ }
+ switch(*user) {
+ case '+':
+ if (!*(user+1)) { /* '+' matches all users */
+ userok = 1;
+ break;
+ }
+ if (*(user+1) == '@') /* match a user by netgroup */
+ userok = innetgr(user+2, NULL, ruser, ypdomain);
+ else /* match a user by direct specification */
+ userok = !(strcmp(ruser, user+1));
+ break;
+ case '-': /* if we matched a hostname, */
+ if (hostok) { /* check for user field rejections */
+ if (!*(user+1))
+ return(-1);
+ if (*(user+1) == '@') {
+ if (innetgr(user+2, NULL,
+ ruser, ypdomain))
+ return(-1);
+ } else {
+ if (!strcmp(ruser, user+1))
+ return(-1);
+ }
+ }
+ break;
+ default: /* no rejections: try to match the user */
+ if (hostok)
+ userok = !(strcmp(ruser,*user ? user : luser));
+ break;
+ }
+ if (hostok && userok)
+ return(0);
+ }
+ return (-1);
+}
+
+/*
+ * Returns "true" if match, 0 if no match.
+ */
+static int
+__icheckhost(raddr, salen, lhost)
+ const struct sockaddr *raddr;
+ socklen_t salen;
+ const char *lhost;
+{
+ struct sockaddr_in sin;
+ struct sockaddr_in6 *sin6;
+ struct addrinfo hints, *res, *r;
+ int error;
+ char h1[NI_MAXHOST], h2[NI_MAXHOST];
+
+ if (raddr->sa_family == AF_INET6) {
+ sin6 = (struct sockaddr_in6 *)raddr;
+ if (IN6_IS_ADDR_V4MAPPED(&sin6->sin6_addr)) {
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ sin.sin_len = sizeof(struct sockaddr_in);
+ memcpy(&sin.sin_addr, &sin6->sin6_addr.s6_addr[12],
+ sizeof(sin.sin_addr));
+ raddr = (struct sockaddr *)&sin;
+ salen = sin.sin_len;
+ }
+ }
+
+ h1[0] = '\0';
+ if (getnameinfo(raddr, salen, h1, sizeof(h1), NULL, 0,
+ NI_NUMERICHOST) != 0)
+ return (0);
+
+ /* Resolve laddr into sockaddr */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = raddr->sa_family;
+ hints.ai_socktype = SOCK_DGRAM; /*XXX dummy*/
+ res = NULL;
+ error = getaddrinfo(lhost, "0", &hints, &res);
+ if (error)
+ return (0);
+
+ for (r = res; r ; r = r->ai_next) {
+ h2[0] = '\0';
+ if (getnameinfo(r->ai_addr, r->ai_addrlen, h2, sizeof(h2),
+ NULL, 0, NI_NUMERICHOST) != 0)
+ continue;
+ if (strcmp(h1, h2) == 0) {
+ freeaddrinfo(res);
+ return (1);
+ }
+ }
+
+ /* No match. */
+ freeaddrinfo(res);
+ return (0);
+}
diff --git a/lib/libc/net/rcmdsh.3 b/lib/libc/net/rcmdsh.3
new file mode 100644
index 0000000..54c3a0a
--- /dev/null
+++ b/lib/libc/net/rcmdsh.3
@@ -0,0 +1,116 @@
+.\" $OpenBSD: rcmdsh.3,v 1.6 1999/07/05 04:41:00 aaron Exp $
+.\"
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd September 1, 1996
+.Dt RCMDSH 3
+.Os
+.Sh NAME
+.Nm rcmdsh
+.Nd return a stream to a remote command without superuser
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fo rcmdsh
+.Fa "char **ahost"
+.Fa "int inport"
+.Fa "const char *locuser"
+.Fa "const char *remuser"
+.Fa "const char *cmd"
+.Fa "const char *rshprog"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn rcmdsh
+function
+is used by normal users to execute a command on
+a remote machine using an authentication scheme based
+on reserved port numbers using
+.Xr rshd 8
+or the value of
+.Fa rshprog
+(if
+.No non- Ns Dv NULL ) .
+.Pp
+The
+.Fn rcmdsh
+function
+looks up the host
+.Fa *ahost
+using
+.Xr gethostbyname 3 ,
+returning \-1 if the host does not exist.
+Otherwise
+.Fa *ahost
+is set to the standard name of the host
+and a connection is established to a server
+residing at the well-known Internet port
+.Dq Li shell/tcp
+(or whatever port is used by
+.Fa rshprog ) .
+The
+.Fa inport
+argument
+is ignored; it is only included to provide an interface similar to
+.Xr rcmd 3 .
+.Pp
+If the connection succeeds,
+a socket in the
+.Ux
+domain of type
+.Dv SOCK_STREAM
+is returned to the caller, and given to the remote
+command as
+.Dv stdin , stdout ,
+and
+.Dv stderr .
+.Sh RETURN VALUES
+The
+.Fn rcmdsh
+function
+returns a valid socket descriptor on success.
+Otherwise, \-1 is returned
+and a diagnostic message is printed on the standard error.
+.Sh SEE ALSO
+.Xr rsh 1 ,
+.Xr socketpair 2 ,
+.Xr rcmd 3 ,
+.Xr rshd 8
+.Sh HISTORY
+The
+.Fn rcmdsh
+function first appeared in
+.Ox 2.0 ,
+and made its way into
+.Fx 4.6 .
+.Sh BUGS
+If
+.Xr rsh 1
+encounters an error, a file descriptor is still returned instead of \-1.
diff --git a/lib/libc/net/rcmdsh.c b/lib/libc/net/rcmdsh.c
new file mode 100644
index 0000000..bc4e87a
--- /dev/null
+++ b/lib/libc/net/rcmdsh.c
@@ -0,0 +1,170 @@
+/* $OpenBSD: rcmdsh.c,v 1.5 1998/04/25 16:23:58 millert Exp $ */
+
+/*
+ * Copyright (c) 2001, MagniComp
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the MagniComp nor the names of its contributors may
+ * be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * This is an rcmd() replacement originally by
+ * Chris Siebenmann <cks@utcc.utoronto.ca>.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/wait.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <paths.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#ifndef _PATH_RSH
+#define _PATH_RSH "/usr/bin/rsh"
+#endif
+
+/*
+ * This is a replacement rcmd() function that uses the rsh(1)
+ * program in place of a direct rcmd(3) function call so as to
+ * avoid having to be root. Note that rport is ignored.
+ */
+int
+rcmdsh(ahost, rport, locuser, remuser, cmd, rshprog)
+ char **ahost;
+ int rport;
+ const char *locuser, *remuser, *cmd, *rshprog;
+{
+ struct addrinfo hints, *res;
+ int cpid, sp[2], error;
+ char *p;
+ struct passwd *pw;
+ char num[8];
+ static char hbuf[NI_MAXHOST];
+
+ /* What rsh/shell to use. */
+ if (rshprog == NULL)
+ rshprog = _PATH_RSH;
+
+ /* locuser must exist on this host. */
+ if ((pw = getpwnam(locuser)) == NULL) {
+ (void)fprintf(stderr, "rcmdsh: unknown user: %s\n", locuser);
+ return (-1);
+ }
+
+ /* Validate remote hostname. */
+ if (strcmp(*ahost, "localhost") != 0) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_flags = AI_CANONNAME;
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_STREAM;
+ (void)snprintf(num, sizeof(num), "%u",
+ (unsigned int)ntohs(rport));
+ error = getaddrinfo(*ahost, num, &hints, &res);
+ if (error) {
+ fprintf(stderr, "rcmdsh: getaddrinfo: %s\n",
+ gai_strerror(error));
+ return (-1);
+ }
+ if (res->ai_canonname) {
+ strncpy(hbuf, res->ai_canonname, sizeof(hbuf) - 1);
+ hbuf[sizeof(hbuf) - 1] = '\0';
+ *ahost = hbuf;
+ }
+ freeaddrinfo(res);
+ }
+
+ /* Get a socketpair we'll use for stdin and stdout. */
+ if (socketpair(AF_UNIX, SOCK_STREAM, PF_UNSPEC, sp) == -1) {
+ perror("rcmdsh: socketpair");
+ return (-1);
+ }
+
+ cpid = fork();
+ if (cpid == -1) {
+ perror("rcmdsh: fork failed");
+ return (-1);
+ } else if (cpid == 0) {
+ /*
+ * Child. We use sp[1] to be stdin/stdout, and close sp[0].
+ */
+ (void)close(sp[0]);
+ if (dup2(sp[1], 0) == -1 || dup2(0, 1) == -1) {
+ perror("rcmdsh: dup2 failed");
+ _exit(255);
+ }
+ /* Fork again to lose parent. */
+ cpid = fork();
+ if (cpid == -1) {
+ perror("rcmdsh: fork to lose parent failed");
+ _exit(255);
+ }
+ if (cpid > 0)
+ _exit(0);
+
+ /* In grandchild here. Become local user for rshprog. */
+ if (setuid(pw->pw_uid) == -1) {
+ (void)fprintf(stderr, "rcmdsh: setuid(%u): %s\n",
+ pw->pw_uid, strerror(errno));
+ _exit(255);
+ }
+
+ /*
+ * If remote host is "localhost" and local and remote users
+ * are the same, avoid running remote shell for efficiency.
+ */
+ if (strcmp(*ahost, "localhost") == 0 &&
+ strcmp(locuser, remuser) == 0) {
+ if (pw->pw_shell[0] == '\0')
+ rshprog = _PATH_BSHELL;
+ else
+ rshprog = pw->pw_shell;
+ p = strrchr(rshprog, '/');
+ execlp(rshprog, p ? p + 1 : rshprog, "-c", cmd,
+ (char *)NULL);
+ } else {
+ p = strrchr(rshprog, '/');
+ execlp(rshprog, p ? p + 1 : rshprog, *ahost, "-l",
+ remuser, cmd, (char *)NULL);
+ }
+ (void)fprintf(stderr, "rcmdsh: execlp %s failed: %s\n",
+ rshprog, strerror(errno));
+ _exit(255);
+ } else {
+ /* Parent. close sp[1], return sp[0]. */
+ (void)close(sp[1]);
+ /* Reap child. */
+ (void)wait(NULL);
+ return (sp[0]);
+ }
+ /* NOTREACHED */
+}
diff --git a/lib/libc/net/recv.c b/lib/libc/net/recv.c
new file mode 100644
index 0000000..c8230d6
--- /dev/null
+++ b/lib/libc/net/recv.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)recv.c 8.2 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <stddef.h>
+#include "un-namespace.h"
+
+ssize_t
+recv(s, buf, len, flags)
+ int s, flags;
+ size_t len;
+ void *buf;
+{
+ return (_recvfrom(s, buf, len, flags, NULL, 0));
+}
diff --git a/lib/libc/net/res_config.h b/lib/libc/net/res_config.h
new file mode 100644
index 0000000..05909bc
--- /dev/null
+++ b/lib/libc/net/res_config.h
@@ -0,0 +1,6 @@
+/* $FreeBSD$ */
+
+#define DEBUG 1 /* enable debugging code (needed for dig) */
+#define RESOLVSORT /* allow sorting of addresses in gethostbyname */
+#undef SUNSECURITY /* verify gethostbyaddr() calls - WE DONT NEED IT */
+#define MULTI_PTRS_ARE_ALIASES 1 /* fold multiple PTR records into aliases */
diff --git a/lib/libc/net/resolver.3 b/lib/libc/net/resolver.3
new file mode 100644
index 0000000..c1a37b3
--- /dev/null
+++ b/lib/libc/net/resolver.3
@@ -0,0 +1,461 @@
+.\" Copyright (c) 1985, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)resolver.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd May 29, 2009
+.Dt RESOLVER 3
+.Os
+.Sh NAME
+.Nm res_query ,
+.Nm res_search ,
+.Nm res_mkquery ,
+.Nm res_send ,
+.Nm res_init ,
+.Nm dn_comp ,
+.Nm dn_expand ,
+.Nm dn_skipname ,
+.Nm ns_get16 ,
+.Nm ns_get32 ,
+.Nm ns_put16 ,
+.Nm ns_put32
+.Nd resolver routines
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In netinet/in.h
+.In arpa/nameser.h
+.In resolv.h
+.Ft int
+.Fo res_query
+.Fa "const char *dname"
+.Fa "int class"
+.Fa "int type"
+.Fa "u_char *answer"
+.Fa "int anslen"
+.Fc
+.Ft int
+.Fo res_search
+.Fa "const char *dname"
+.Fa "int class"
+.Fa "int type"
+.Fa "u_char *answer"
+.Fa "int anslen"
+.Fc
+.Ft int
+.Fo res_mkquery
+.Fa "int op"
+.Fa "const char *dname"
+.Fa "int class"
+.Fa "int type"
+.Fa "const u_char *data"
+.Fa "int datalen"
+.Fa "const u_char *newrr_in"
+.Fa "u_char *buf"
+.Fa "int buflen"
+.Fc
+.Ft int
+.Fo res_send
+.Fa "const u_char *msg"
+.Fa "int msglen"
+.Fa "u_char *answer"
+.Fa "int anslen"
+.Fc
+.Ft int
+.Fn res_init void
+.Ft int
+.Fo dn_comp
+.Fa "const char *exp_dn"
+.Fa "u_char *comp_dn"
+.Fa "int length"
+.Fa "u_char **dnptrs"
+.Fa "u_char **lastdnptr"
+.Fc
+.Ft int
+.Fo dn_expand
+.Fa "const u_char *msg"
+.Fa "const u_char *eomorig"
+.Fa "const u_char *comp_dn"
+.Fa "char *exp_dn"
+.Fa "int length"
+.Fc
+.Ft int
+.Fn dn_skipname "const u_char *comp_dn" "const u_char *eom"
+.Ft u_int
+.Fn ns_get16 "const u_char *src"
+.Ft u_long
+.Fn ns_get32 "const u_char *src"
+.Ft void
+.Fn ns_put16 "u_int src" "u_char *dst"
+.Ft void
+.Fn ns_put32 "u_long src" "u_char *dst"
+.Sh DESCRIPTION
+These routines are used for making, sending and interpreting
+query and reply messages with Internet domain name servers.
+.Pp
+Global configuration and state information that is used by the
+resolver routines is kept in the structure
+.Va _res .
+Most of the values have reasonable defaults and can be ignored.
+Options
+stored in
+.Va _res.options
+are defined in
+.In resolv.h
+and are as follows.
+Options are stored as a simple bit mask containing the bitwise ``or''
+of the options enabled.
+.Bl -tag -width RES_USE_INET6
+.It Dv RES_INIT
+True if the initial name server address and default domain name are
+initialized (i.e.,
+.Fn res_init
+has been called).
+.It Dv RES_DEBUG
+Print debugging messages.
+.It Dv RES_AAONLY
+Accept authoritative answers only.
+With this option,
+.Fn res_send
+should continue until it finds an authoritative answer or finds an error.
+Currently this is not implemented.
+.It Dv RES_USEVC
+Use
+.Tn TCP
+connections for queries instead of
+.Tn UDP
+datagrams.
+.It Dv RES_STAYOPEN
+Used with
+.Dv RES_USEVC
+to keep the
+.Tn TCP
+connection open between
+queries.
+This is useful only in programs that regularly do many queries.
+.Tn UDP
+should be the normal mode used.
+.It Dv RES_IGNTC
+Unused currently (ignore truncation errors, i.e., do not retry with
+.Tn TCP ) .
+.It Dv RES_RECURSE
+Set the recursion-desired bit in queries.
+This is the default.
+.Pf ( Fn res_send
+does not do iterative queries and expects the name server
+to handle recursion.)
+.It Dv RES_DEFNAMES
+If set,
+.Fn res_search
+will append the default domain name to single-component names
+(those that do not contain a dot).
+This option is enabled by default.
+.It Dv RES_DNSRCH
+If this option is set,
+.Fn res_search
+will search for host names in the current domain and in parent domains; see
+.Xr hostname 7 .
+This is used by the standard host lookup routine
+.Xr gethostbyname 3 .
+This option is enabled by default.
+.It Dv RES_NOALIASES
+This option turns off the user level aliasing feature controlled by the
+.Dq Ev HOSTALIASES
+environment variable.
+Network daemons should set this option.
+.It Dv RES_USE_INET6
+Enables support for IPv6-only applications.
+This causes IPv4 addresses to be returned as an IPv4 mapped address.
+For example,
+.Li 10.1.1.1
+will be returned as
+.Li ::ffff:10.1.1.1 .
+The option is meaningful with certain kernel configuration only.
+.It Dv RES_USE_EDNS0
+Enables support for OPT pseudo-RR for EDNS0 extension.
+With the option, resolver code will attach OPT pseudo-RR into DNS queries,
+to inform of our receive buffer size.
+The option will allow DNS servers to take advantage of non-default receive
+buffer size, and to send larger replies.
+DNS query packets with EDNS0 extension is not compatible with
+non-EDNS0 DNS servers.
+.El
+.Pp
+The
+.Fn res_init
+routine
+reads the configuration file (if any; see
+.Xr resolver 5 )
+to get the default domain name,
+search list and
+the Internet address of the local name server(s).
+If no server is configured, the host running
+the resolver is tried.
+The current domain name is defined by the hostname
+if not specified in the configuration file;
+it can be overridden by the environment variable
+.Ev LOCALDOMAIN .
+This environment variable may contain several blank-separated
+tokens if you wish to override the
+.Em "search list"
+on a per-process basis.
+This is similar to the
+.Ic search
+command in the configuration file.
+Another environment variable
+.Dq Ev RES_OPTIONS
+can be set to
+override certain internal resolver options which are otherwise
+set by changing fields in the
+.Va _res
+structure or are inherited from the configuration file's
+.Ic options
+command.
+The syntax of the
+.Dq Ev RES_OPTIONS
+environment variable is explained in
+.Xr resolver 5 .
+Initialization normally occurs on the first call
+to one of the following routines.
+.Pp
+The
+.Fn res_query
+function provides an interface to the server query mechanism.
+It constructs a query, sends it to the local server,
+awaits a response, and makes preliminary checks on the reply.
+The query requests information of the specified
+.Fa type
+and
+.Fa class
+for the specified fully-qualified domain name
+.Fa dname .
+The reply message is left in the
+.Fa answer
+buffer with length
+.Fa anslen
+supplied by the caller.
+.Pp
+The
+.Fn res_search
+routine makes a query and awaits a response like
+.Fn res_query ,
+but in addition, it implements the default and search rules
+controlled by the
+.Dv RES_DEFNAMES
+and
+.Dv RES_DNSRCH
+options.
+It returns the first successful reply.
+.Pp
+The remaining routines are lower-level routines used by
+.Fn res_query .
+The
+.Fn res_mkquery
+function
+constructs a standard query message and places it in
+.Fa buf .
+It returns the size of the query, or \-1 if the query is
+larger than
+.Fa buflen .
+The query type
+.Fa op
+is usually
+.Dv QUERY ,
+but can be any of the query types defined in
+.In arpa/nameser.h .
+The domain name for the query is given by
+.Fa dname .
+The
+.Fa newrr_in
+argument
+is currently unused but is intended for making update messages.
+.Pp
+The
+.Fn res_send
+routine
+sends a pre-formatted query and returns an answer.
+It will call
+.Fn res_init
+if
+.Dv RES_INIT
+is not set, send the query to the local name server, and
+handle timeouts and retries.
+The length of the reply message is returned, or
+\-1 if there were errors.
+.Pp
+The
+.Fn dn_comp
+function
+compresses the domain name
+.Fa exp_dn
+and stores it in
+.Fa comp_dn .
+The size of the compressed name is returned or \-1 if there were errors.
+The size of the array pointed to by
+.Fa comp_dn
+is given by
+.Fa length .
+The compression uses
+an array of pointers
+.Fa dnptrs
+to previously-compressed names in the current message.
+The first pointer points to
+the beginning of the message and the list ends with
+.Dv NULL .
+The limit to the array is specified by
+.Fa lastdnptr .
+A side effect of
+.Fn dn_comp
+is to update the list of pointers for
+labels inserted into the message
+as the name is compressed.
+If
+.Fa dnptr
+is
+.Dv NULL ,
+names are not compressed.
+If
+.Fa lastdnptr
+is
+.Dv NULL ,
+the list of labels is not updated.
+.Pp
+The
+.Fn dn_expand
+entry
+expands the compressed domain name
+.Fa comp_dn
+to a full domain name
+The compressed name is contained in a query or reply message;
+.Fa msg
+is a pointer to the beginning of the message.
+The uncompressed name is placed in the buffer indicated by
+.Fa exp_dn
+which is of size
+.Fa length .
+The size of compressed name is returned or \-1 if there was an error.
+.Pp
+The
+.Fn dn_skipname
+function skips over a compressed domain name, which starts at a location
+pointed to by
+.Fa comp_dn .
+The compressed name is contained in a query or reply message;
+.Fa eom
+is a pointer to the end of the message.
+The size of compressed name is returned or \-1 if there was
+an error.
+.Pp
+The
+.Fn ns_get16
+function gets a 16-bit quantity from a buffer pointed to by
+.Fa src .
+.Pp
+The
+.Fn ns_get32
+function gets a 32-bit quantity from a buffer pointed to by
+.Fa src .
+.Pp
+The
+.Fn ns_put16
+function puts a 16-bit quantity
+.Fa src
+to a buffer pointed to by
+.Fa dst .
+.Pp
+The
+.Fn ns_put32
+function puts a 32-bit quantity
+.Fa src
+to a buffer pointed to by
+.Fa dst .
+.Sh IMPLEMENTATION NOTES
+This implementation of the resolver is thread-safe, but it will not
+function properly if the programmer attempts to declare his or her own
+.Va _res
+structure in an attempt to replace the per-thread version referred to
+by that macro.
+.Pp
+The following compile-time option can be specified to change the default
+behavior of resolver routines when necessary.
+.Bl -tag -width RES_ENFORCE_RFC1034
+.It Dv RES_ENFORCE_RFC1034
+If this symbol is defined during compile-time,
+.Fn res_search
+will enforce RFC 1034 check, namely, disallow using of underscore character
+within host names.
+This is used by the standard host lookup routines like
+.Xr gethostbyname 3 .
+For compatibility reasons this option is not enabled by default.
+.El
+.Sh RETURN VALUES
+The
+.Fn res_init
+function will return 0 on success, or \-1 in a threaded program if
+per-thread storage could not be allocated.
+.Pp
+The
+.Fn res_mkquery ,
+.Fn res_search ,
+and
+.Fn res_query
+functions return the size of the response on success, or \-1 if an
+error occurs.
+The integer
+.Vt h_errno
+may be checked to determine the reason for error.
+See
+.Xr gethostbyname 3
+for more information.
+.Sh FILES
+.Bl -tag -width /etc/resolv.conf
+.It Pa /etc/resolv.conf
+The configuration file,
+see
+.Xr resolver 5 .
+.El
+.Sh SEE ALSO
+.Xr gethostbyname 3 ,
+.Xr resolver 5 ,
+.Xr hostname 7 ,
+.Xr named 8
+.Pp
+.%T RFC1032 ,
+.%T RFC1033 ,
+.%T RFC1034 ,
+.%T RFC1035 ,
+.%T RFC974
+.Rs
+.%T "Name Server Operations Guide for BIND"
+.Re
+.Sh HISTORY
+The
+.Nm
+function appeared in
+.Bx 4.3 .
diff --git a/lib/libc/net/rthdr.c b/lib/libc/net/rthdr.c
new file mode 100644
index 0000000..f92fdec
--- /dev/null
+++ b/lib/libc/net/rthdr.c
@@ -0,0 +1,450 @@
+/* $KAME: rthdr.c,v 1.19 2003/06/06 10:48:51 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <netinet/ip6.h>
+
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * RFC2292 API
+ */
+
+size_t
+inet6_rthdr_space(type, seg)
+ int type, seg;
+{
+ switch (type) {
+ case IPV6_RTHDR_TYPE_0:
+ if (seg < 1 || seg > 23)
+ return (0);
+#ifdef COMPAT_RFC2292
+ return (CMSG_SPACE(sizeof(struct in6_addr) * (seg - 1) +
+ sizeof(struct ip6_rthdr0)));
+#else
+ return (CMSG_SPACE(sizeof(struct in6_addr) * seg +
+ sizeof(struct ip6_rthdr0)));
+#endif
+ default:
+ return (0);
+ }
+}
+
+struct cmsghdr *
+inet6_rthdr_init(bp, type)
+ void *bp;
+ int type;
+{
+ struct cmsghdr *ch = (struct cmsghdr *)bp;
+ struct ip6_rthdr *rthdr;
+
+ rthdr = (struct ip6_rthdr *)CMSG_DATA(ch);
+
+ ch->cmsg_level = IPPROTO_IPV6;
+ ch->cmsg_type = IPV6_RTHDR;
+
+ switch (type) {
+ case IPV6_RTHDR_TYPE_0:
+#ifdef COMPAT_RFC2292
+ ch->cmsg_len = CMSG_LEN(sizeof(struct ip6_rthdr0) -
+ sizeof(struct in6_addr));
+#else
+ ch->cmsg_len = CMSG_LEN(sizeof(struct ip6_rthdr0));
+#endif
+
+ bzero(rthdr, sizeof(struct ip6_rthdr0));
+ rthdr->ip6r_type = IPV6_RTHDR_TYPE_0;
+ return (ch);
+ default:
+ return (NULL);
+ }
+}
+
+/* ARGSUSED */
+int
+inet6_rthdr_add(cmsg, addr, flags)
+ struct cmsghdr *cmsg;
+ const struct in6_addr *addr;
+ u_int flags;
+{
+ struct ip6_rthdr *rthdr;
+
+ rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
+
+ switch (rthdr->ip6r_type) {
+ case IPV6_RTHDR_TYPE_0:
+ {
+ struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
+ if (flags != IPV6_RTHDR_LOOSE && flags != IPV6_RTHDR_STRICT)
+ return (-1);
+ if (rt0->ip6r0_segleft == 23)
+ return (-1);
+
+#ifdef COMPAT_RFC1883 /* XXX */
+ if (flags == IPV6_RTHDR_STRICT) {
+ int c, b;
+ c = rt0->ip6r0_segleft / 8;
+ b = rt0->ip6r0_segleft % 8;
+ rt0->ip6r0_slmap[c] |= (1 << (7 - b));
+ }
+#else
+ if (flags != IPV6_RTHDR_LOOSE)
+ return (-1);
+#endif
+ rt0->ip6r0_segleft++;
+ bcopy(addr, (caddr_t)rt0 + ((rt0->ip6r0_len + 1) << 3),
+ sizeof(struct in6_addr));
+ rt0->ip6r0_len += sizeof(struct in6_addr) >> 3;
+ cmsg->cmsg_len = CMSG_LEN((rt0->ip6r0_len + 1) << 3);
+ break;
+ }
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+/* ARGSUSED */
+int
+inet6_rthdr_lasthop(cmsg, flags)
+ struct cmsghdr *cmsg;
+ unsigned int flags;
+{
+ struct ip6_rthdr *rthdr;
+
+ rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
+
+ switch (rthdr->ip6r_type) {
+ case IPV6_RTHDR_TYPE_0:
+ {
+ struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
+#ifdef COMPAT_RFC1883 /* XXX */
+ if (flags != IPV6_RTHDR_LOOSE && flags != IPV6_RTHDR_STRICT)
+ return (-1);
+#endif /* COMPAT_RFC1883 */
+ if (rt0->ip6r0_segleft > 23)
+ return (-1);
+#ifdef COMPAT_RFC1883 /* XXX */
+ if (flags == IPV6_RTHDR_STRICT) {
+ int c, b;
+ c = rt0->ip6r0_segleft / 8;
+ b = rt0->ip6r0_segleft % 8;
+ rt0->ip6r0_slmap[c] |= (1 << (7 - b));
+ }
+#else
+ if (flags != IPV6_RTHDR_LOOSE)
+ return (-1);
+#endif /* COMPAT_RFC1883 */
+ break;
+ }
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+#if 0
+int
+inet6_rthdr_reverse(in, out)
+ const struct cmsghdr *in;
+ struct cmsghdr *out;
+{
+
+ return (-1);
+}
+#endif
+
+int
+inet6_rthdr_segments(cmsg)
+ const struct cmsghdr *cmsg;
+{
+ struct ip6_rthdr *rthdr;
+
+ rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
+
+ switch (rthdr->ip6r_type) {
+ case IPV6_RTHDR_TYPE_0:
+ {
+ struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
+
+ if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
+ return (-1);
+
+ return (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
+ }
+
+ default:
+ return (-1);
+ }
+}
+
+struct in6_addr *
+inet6_rthdr_getaddr(cmsg, idx)
+ struct cmsghdr *cmsg;
+ int idx;
+{
+ struct ip6_rthdr *rthdr;
+
+ rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
+
+ switch (rthdr->ip6r_type) {
+ case IPV6_RTHDR_TYPE_0:
+ {
+ struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
+ int naddr;
+
+ if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
+ return NULL;
+ naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
+ if (idx <= 0 || naddr < idx)
+ return NULL;
+#ifdef COMPAT_RFC2292
+ return (((struct in6_addr *)(rt0 + 1)) + idx - 1);
+#else
+ return (((struct in6_addr *)(rt0 + 1)) + idx);
+#endif
+ }
+
+ default:
+ return NULL;
+ }
+}
+
+int
+inet6_rthdr_getflags(cmsg, idx)
+ const struct cmsghdr *cmsg;
+ int idx;
+{
+ struct ip6_rthdr *rthdr;
+
+ rthdr = (struct ip6_rthdr *)CMSG_DATA(cmsg);
+
+ switch (rthdr->ip6r_type) {
+ case IPV6_RTHDR_TYPE_0:
+ {
+ struct ip6_rthdr0 *rt0 = (struct ip6_rthdr0 *)rthdr;
+ int naddr;
+
+ if (rt0->ip6r0_len % 2 || 46 < rt0->ip6r0_len)
+ return (-1);
+ naddr = (rt0->ip6r0_len * 8) / sizeof(struct in6_addr);
+ if (idx < 0 || naddr < idx)
+ return (-1);
+#ifdef COMPAT_RFC1883 /* XXX */
+ if (rt0->ip6r0_slmap[idx / 8] & (0x80 >> (idx % 8)))
+ return IPV6_RTHDR_STRICT;
+ else
+ return IPV6_RTHDR_LOOSE;
+#else
+ return IPV6_RTHDR_LOOSE;
+#endif /* COMPAT_RFC1883 */
+ }
+
+ default:
+ return (-1);
+ }
+}
+
+/*
+ * RFC3542 API
+ */
+
+socklen_t
+inet6_rth_space(int type, int segments)
+{
+ switch (type) {
+ case IPV6_RTHDR_TYPE_0:
+ if ((segments >= 0) && (segments <= 127))
+ return (((segments * 2) + 1) << 3);
+ /* FALLTHROUGH */
+ default:
+ return (0); /* type not suppported */
+ }
+}
+
+void *
+inet6_rth_init(void *bp, socklen_t bp_len, int type, int segments)
+{
+ struct ip6_rthdr *rth = (struct ip6_rthdr *)bp;
+ struct ip6_rthdr0 *rth0;
+
+ switch (type) {
+ case IPV6_RTHDR_TYPE_0:
+ /* length validation */
+ if (bp_len < inet6_rth_space(IPV6_RTHDR_TYPE_0, segments))
+ return (NULL);
+ /* segment validation */
+ if ((segments < 0) || (segments > 127))
+ return (NULL);
+
+ memset(bp, 0, bp_len);
+ rth0 = (struct ip6_rthdr0 *)rth;
+ rth0->ip6r0_len = segments * 2;
+ rth0->ip6r0_type = IPV6_RTHDR_TYPE_0;
+ rth0->ip6r0_segleft = 0;
+ rth0->ip6r0_reserved = 0;
+ break;
+ default:
+ return (NULL); /* type not supported */
+ }
+
+ return (bp);
+}
+
+int
+inet6_rth_add(void *bp, const struct in6_addr *addr)
+{
+ struct ip6_rthdr *rth = (struct ip6_rthdr *)bp;
+ struct ip6_rthdr0 *rth0;
+ struct in6_addr *nextaddr;
+
+ switch (rth->ip6r_type) {
+ case IPV6_RTHDR_TYPE_0:
+ rth0 = (struct ip6_rthdr0 *)rth;
+ /* Don't exceed the number of stated segments */
+ if (rth0->ip6r0_segleft == (rth0->ip6r0_len / 2))
+ return (-1);
+ nextaddr = (struct in6_addr *)(rth0 + 1) + rth0->ip6r0_segleft;
+ *nextaddr = *addr;
+ rth0->ip6r0_segleft++;
+ break;
+ default:
+ return (-1); /* type not supported */
+ }
+
+ return (0);
+}
+
+int
+inet6_rth_reverse(const void *in, void *out)
+{
+ struct ip6_rthdr *rth_in = (struct ip6_rthdr *)in;
+ struct ip6_rthdr0 *rth0_in, *rth0_out;
+ int i, segments;
+
+ switch (rth_in->ip6r_type) {
+ case IPV6_RTHDR_TYPE_0:
+ rth0_in = (struct ip6_rthdr0 *)in;
+ rth0_out = (struct ip6_rthdr0 *)out;
+
+ /* parameter validation XXX too paranoid? */
+ if (rth0_in->ip6r0_len % 2)
+ return (-1);
+ segments = rth0_in->ip6r0_len / 2;
+
+ /* we can't use memcpy here, since in and out may overlap */
+ memmove((void *)rth0_out, (void *)rth0_in,
+ ((rth0_in->ip6r0_len) + 1) << 3);
+ rth0_out->ip6r0_segleft = segments;
+
+ /* reverse the addresses */
+ for (i = 0; i < segments / 2; i++) {
+ struct in6_addr addr_tmp, *addr1, *addr2;
+
+ addr1 = (struct in6_addr *)(rth0_out + 1) + i;
+ addr2 = (struct in6_addr *)(rth0_out + 1) +
+ (segments - i - 1);
+ addr_tmp = *addr1;
+ *addr1 = *addr2;
+ *addr2 = addr_tmp;
+ }
+
+ break;
+ default:
+ return (-1); /* type not supported */
+ }
+
+ return (0);
+}
+
+int
+inet6_rth_segments(const void *bp)
+{
+ struct ip6_rthdr *rh = (struct ip6_rthdr *)bp;
+ struct ip6_rthdr0 *rh0;
+ int addrs;
+
+ switch (rh->ip6r_type) {
+ case IPV6_RTHDR_TYPE_0:
+ rh0 = (struct ip6_rthdr0 *)bp;
+
+ /*
+ * Validation for a type-0 routing header.
+ * Is this too strict?
+ */
+ if ((rh0->ip6r0_len % 2) != 0 ||
+ (addrs = (rh0->ip6r0_len >> 1)) < rh0->ip6r0_segleft)
+ return (-1);
+
+ return (addrs);
+ default:
+ return (-1); /* unknown type */
+ }
+}
+
+struct in6_addr *
+inet6_rth_getaddr(const void *bp, int idx)
+{
+ struct ip6_rthdr *rh = (struct ip6_rthdr *)bp;
+ struct ip6_rthdr0 *rh0;
+ int addrs;
+
+ switch (rh->ip6r_type) {
+ case IPV6_RTHDR_TYPE_0:
+ rh0 = (struct ip6_rthdr0 *)bp;
+
+ /*
+ * Validation for a type-0 routing header.
+ * Is this too strict?
+ */
+ if ((rh0->ip6r0_len % 2) != 0 ||
+ (addrs = (rh0->ip6r0_len >> 1)) < rh0->ip6r0_segleft)
+ return (NULL);
+
+ if (idx < 0 || addrs <= idx)
+ return (NULL);
+
+ return (((struct in6_addr *)(rh0 + 1)) + idx);
+ default:
+ return (NULL); /* unknown type */
+ break;
+ }
+}
diff --git a/lib/libc/net/sctp_bindx.3 b/lib/libc/net/sctp_bindx.3
new file mode 100644
index 0000000..403cf7d
--- /dev/null
+++ b/lib/libc/net/sctp_bindx.3
@@ -0,0 +1,114 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)send.2 8.2 (Berkeley) 2/21/94
+.\" $FreeBSD$
+.\"
+.Dd December 15, 2006
+.Dt SCTP_BINDX 3
+.Os
+.Sh NAME
+.Nm sctp_bindx
+.Nd bind or unbind an SCTP socket to a list of addresses.
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft int
+.Fn sctp_bindx "int s" "struct sockaddr *addrs" "int num" "int type"
+.Sh DESCRIPTION
+The
+.Fn sctp_bindx
+call binds or unbinds a address or a list of addresses to an
+SCTP endpoint.
+This allows a user to bind a subset of
+addresses.
+The
+.Fn sctp_bindx
+call operates similarly to
+.Fn bind
+but allows a list of addresses and also allows a bind or an
+unbind.
+The argument
+.Fa s
+must be a valid SCTP socket descriptor.
+The argument
+.Fa addrs
+is a list of addresses (where the list may be only 1 in
+length) that the user wishes to bind or unbind to the
+socket.
+The argument
+.Fa type
+must be one of the following values.
+.Pp
+.Dv SCTP_BINDX_ADD_ADDR
+This value indicates that the listed address(es) need to
+be added to the endpoint.
+.Pp
+.Dv SCTP_BINDX_DEL_ADDR
+This value indicates that the listed address(es) need to
+be removed from the endpoint.
+.Pp
+Note that when a user adds or deletes an address to an
+association if the dynamic address flag
+.Va net.inet.sctp.auto_asconf
+is enabled any associations in the endpoint will attempt to
+have the address(es) added dynamically to the existing
+association.
+.Sh RETURN VALUES
+The call returns 0 on success and -1 upon failure.
+.Sh ERRORS
+The
+.Fn sctp_bindx
+function can return the following errors:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+This value is returned if the
+.Fa type
+field is not one of the allowed values (see above).
+.It Bq Er ENOMEM
+This value is returned if the number of addresses
+being added causes a memory allocation failure in
+the call.
+.It Bq Er EBADF
+The argument
+.Fa s
+is not a valid descriptor.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.El
+.Sh SEE ALSO
+.Xr bind 2 ,
+.Xr sctp 4
diff --git a/lib/libc/net/sctp_connectx.3 b/lib/libc/net/sctp_connectx.3
new file mode 100644
index 0000000..1851d4a
--- /dev/null
+++ b/lib/libc/net/sctp_connectx.3
@@ -0,0 +1,106 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 19, 2007
+.Dt SCTP_CONNECTX 3
+.Os
+.Sh NAME
+.Nm sctp_connectx
+.Nd connect an SCTP socket with multiple destination addresses.
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft int
+.Fn sctp_connectx "int sd" "struct sockaddr *addrs" "int addrcnt" "sctp_assoc_t *id"
+.Sh DESCRIPTION
+The
+.Fn sctp_connectx
+call attempts to initiate an association to a peer SCTP
+endpoint.
+The call operates similarly to
+.Fn connect
+but it also provides the ability to specify multiple destination
+addresses for the peer.
+This allows a fault tolerant method
+of initiating an association.
+When one of the peers addresses
+is unreachable, the subsequent listed addresses will also be used
+to set up the association with the peer.
+.Pp
+The user also needs to consider that any address listed in an
+.Fn sctp_connectx
+call is also considered "confirmed".
+A confirmed address is one in
+which the SCTP transport will trust is a part of the association
+and it will not send a confirmation heartbeat to it with
+a random nonce.
+.Pp
+If the peer SCTP stack does not list one or more of
+the provided addresses in its response message then
+the extra addresses sent in the
+.Fn sctp_connectx
+call will be silently discarded from the association.
+On
+successful completion the provided
+.Fa id
+will be
+filled in with the association identification of the newly
+forming association.
+.Sh RETURN VALUES
+The call returns 0 on success and -1 upon failure.
+.Sh ERRORS
+The
+.Fn sctp_connectx
+function can return the following errors:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+An address listed has an invalid family or no
+addresses were provided.
+.It Bq Er E2BIG
+The size of the address list exceeds the amount of
+data provided.
+.It Bq Er EBADF
+The argument
+.Fa s
+is not a valid descriptor.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.El
+.Sh SEE ALSO
+.Xr connect 2 ,
+.Xr sctp 4
diff --git a/lib/libc/net/sctp_freepaddrs.3 b/lib/libc/net/sctp_freepaddrs.3
new file mode 100644
index 0000000..77a8488
--- /dev/null
+++ b/lib/libc/net/sctp_freepaddrs.3
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)send.2 8.2 (Berkeley) 2/21/94
+.\" $FreeBSD$
+.\"
+.Dd December 15, 2006
+.Dt SCTP_FREEPADDRS 3
+.Os
+.Sh NAME
+.Nm sctp_freepaddrs ,
+.Nm sctp_freeladdrs
+.Nd release the memory returned from a previous call
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft void
+.Fn sctp_freepaddrs "struct sockaddr *"
+.Ft void
+.Fn sctp_freeladdrs "struct sockaddr *"
+.Sh DESCRIPTION
+The
+.Fn sctp_freepaddrs
+and
+.Fn sctp_freeladdrs
+functions are used to release the memory allocated by previous
+calls to
+.Fn sctp_getpaddrs
+or
+.Fn sctp_getladdrs
+respectively.
+.Sh RETURN VALUES
+none.
+.Sh SEE ALSO
+.Xr sctp_getladdrs 3 ,
+.Xr sctp_getpaddrs 3 ,
+.Xr sctp 4
diff --git a/lib/libc/net/sctp_getaddrlen.3 b/lib/libc/net/sctp_getaddrlen.3
new file mode 100644
index 0000000..7259635
--- /dev/null
+++ b/lib/libc/net/sctp_getaddrlen.3
@@ -0,0 +1,87 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)send.2 8.2 (Berkeley) 2/21/94
+.\" $FreeBSD$
+.\"
+.Dd December 15, 2006
+.Dt SCTP_GETADDRLEN 3
+.Os
+.Sh NAME
+.Nm sctp_getaddrlen
+.Nd return the address length of an address family
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft int
+.Fn sctp_getaddrlen "sa_family_t family"
+.Sh DESCRIPTION
+The
+.Fn sctp_getaddrlen
+function returns the size of a specific address family.
+This function
+is provided for application binary compatibility since it
+provides the application with the size the operating system
+thinks the specific address family is.
+Note that the function
+will actually create an SCTP socket and then gather the
+information via a
+.Fn getsockopt
+system calls.
+If for some reason a SCTP socket cannot
+be created or the
+.Fn getsockopt
+call fails, an error will be returned
+with
+.Va errno
+set as specified in the
+.Fn socket
+or
+.Fn getsockopt
+system call.
+.Sh RETURN VALUES
+The call returns the number of bytes that the operating
+system expects for the specific address family or -1.
+.Sh ERRORS
+The
+.Fn sctp_getaddrlen
+function can return the following errors:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The address family specified does NOT exist.
+.El
+.Sh SEE ALSO
+.Xr getsockopt 2 ,
+.Xr socket 2 ,
+.Xr sctp 4
diff --git a/lib/libc/net/sctp_getassocid.3 b/lib/libc/net/sctp_getassocid.3
new file mode 100644
index 0000000..f347a13
--- /dev/null
+++ b/lib/libc/net/sctp_getassocid.3
@@ -0,0 +1,74 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 15, 2006
+.Dt SCTP_GETASSOCID 3
+.Os
+.Sh NAME
+.Nm sctp_getassocid
+.Nd return an association id for a specified socket address.
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft sctp_assoc_t
+.Fn sctp_getassocid "int s" "struct sockaddr *addr"
+.Sh DESCRIPTION
+The
+.Fn sctp_getassocid
+call attempts to look up the specified socket address
+.Fa addr
+and find the respective association identification.
+.Sh RETURN VALUES
+The call returns the association id upon success and
+0 is returned upon failure.
+.Sh ERRORS
+The
+.Fn sctp_getassocid
+function can return the following errors:
+.Bl -tag -width Er
+.It Bq Er ENOENT
+The address does not have an association setup to it.
+.It Bq Er EBADF
+The argument
+.Fa s
+is not a valid descriptor.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.El
+.Sh SEE ALSO
+.Xr sctp 4
diff --git a/lib/libc/net/sctp_getpaddrs.3 b/lib/libc/net/sctp_getpaddrs.3
new file mode 100644
index 0000000..8bdf2cc
--- /dev/null
+++ b/lib/libc/net/sctp_getpaddrs.3
@@ -0,0 +1,100 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)send.2 8.2 (Berkeley) 2/21/94
+.\" $FreeBSD$
+.\"
+.Dd December 15, 2006
+.Dt SCTP_GETPADDRS 3
+.Os
+.Sh NAME
+.Nm sctp_getpaddrs ,
+.Nm sctp_getladdrs
+.Nd return a list of addresses to the caller
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft int
+.Fn sctp_getpaddrs "int s" "sctp_assoc_t asocid" "struct sockaddr **addrs"
+.Ft int
+.Fn sctp_getladdrs "int s" "sctp_assoc_t asocid" "struct sockaddr **addrs"
+.Sh DESCRIPTION
+The
+.Fn sctp_getpaddrs
+function is used to get the list of the peers addresses.
+The
+.Fn sctp_getladdrs
+function is used to get the list of the local addresses.
+The association of interest is identified by the
+.Fa asocid
+argument.
+The addresses are returned in a newly allocated
+array of socket addresses returned in the argument
+.Fa addrs
+upon success.
+.Pp
+After the caller is finished, the function
+.Fn sctp_freepaddrs
+or
+.Fn sctp_freeladdrs
+should be used to release the memory allocated by these
+calls.
+.Sh RETURN VALUES
+The call returns -1 upon failure and a count of
+the number of addresses returned in
+.Fa addrs
+upon success.
+.Sh ERRORS
+The functions can return the following errors:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+An address listed has an invalid family or no
+addresses were provided.
+.It Bq Er ENOMEM
+The call cannot allocate memory to hold the
+socket addresses.
+.It Bq Er EBADF
+The argument
+.Fa s
+is not a valid descriptor.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.El
+.Sh SEE ALSO
+.Xr getsockopt 2 ,
+.Xr sctp_freeladdrs 3 ,
+.Xr sctp_freepaddrs 3 ,
+.Xr sctp 4
diff --git a/lib/libc/net/sctp_opt_info.3 b/lib/libc/net/sctp_opt_info.3
new file mode 100644
index 0000000..02b0f85
--- /dev/null
+++ b/lib/libc/net/sctp_opt_info.3
@@ -0,0 +1,144 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)send.2 8.2 (Berkeley) 2/21/94
+.\" $FreeBSD$
+.\"
+.Dd June 18, 2011
+.Dt SCTP_OPT_INFO 3
+.Os
+.Sh NAME
+.Nm sctp_opt_info
+.Nd get SCTP socket information
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft int
+.Fn sctp_opt_info "int sd" "sctp_assoc_t id" "int opt" "void *arg" "socklen_t *size"
+.Sh DESCRIPTION
+The
+.Fn sctp_opt_info
+call provides a multi-os compatible method for getting
+specific
+.Fn getsockopt
+data where an association identification needs to be passed
+into the operating system.
+For
+.Fx
+a direct
+.Fn getsockopt
+may be used, since
+.Fx
+has the ability to pass information
+into the operating system on a
+.Fn getsockopt
+call.
+Other operating systems may not have this ability.
+For those
+who wish to write portable code amongst multiple operating systems
+this call should be used for the following SCTP
+socket options.
+.Pp
+.Dv SCTP_RTOINFO
+.Pp
+.Dv SCTP_ASSOCINFO
+.Pp
+.Dv SCTP_PRIMARY_ADDR
+.Pp
+.Dv SCTP_PEER_ADDR_PARAMS
+.Pp
+.Dv SCTP_DEFAULT_SEND_PARAM
+.Pp
+.Dv SCTP_MAX_SEG
+.Pp
+.Dv SCTP_AUTH_ACTIVE_KEY
+.Pp
+.Dv SCTP_DELAYED_SACK
+.Pp
+.Dv SCTP_MAX_BURST
+.Pp
+.Dv SCTP_CONTEXT
+.Pp
+.Dv SCTP_EVENT
+.Pp
+.Dv SCTP_DEFAULT_SNDINFO
+.Pp
+.Dv SCTP_DEFAULT_PRINFO
+.Pp
+.Dv SCTP_STATUS
+.Pp
+.Dv SCTP_GET_PEER_ADDR_INFO
+.Pp
+.Dv SCTP_PEER_AUTH_CHUNKS
+.Pp
+.Dv SCTP_LOCAL_AUTH_CHUNKS
+.Sh RETURN VALUES
+The call returns 0 on success and -1 upon error.
+.Sh ERRORS
+The
+.Fn sctp_opt_info
+function can return the following errors:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The argument
+.Fa arg
+value was invalid.
+.It Bq Er EOPNOTSUPP
+The argument
+.Fa opt
+was not one of the above listed SCTP socket
+options.
+.It Bq Er EBADF
+The argument
+.Fa s
+is not a valid descriptor.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.El
+.Sh SEE ALSO
+.Xr getsockopt 2 ,
+.Xr sctp 4
+.Sh BUGS
+Because the structure used for
+.Fa arg
+of the
+.Dv SCTP_MAX_BURST
+socket option has changed in FreeBSD 9.0 and higher,
+using
+.Dv SCTP_MAX_BURST
+as
+.Fa opt
+is only supported in FreeBSD 9.0 and higher.
diff --git a/lib/libc/net/sctp_recvmsg.3 b/lib/libc/net/sctp_recvmsg.3
new file mode 100644
index 0000000..37323c8
--- /dev/null
+++ b/lib/libc/net/sctp_recvmsg.3
@@ -0,0 +1,298 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 13, 2007
+.Dt SCTP_RECVMSG 3
+.Os
+.Sh NAME
+.Nm sctp_recvmsg
+.Nd receive a message from an SCTP socket
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft ssize_t
+.Fo sctp_recvmsg
+.Fa "int s" "void *msg" "size_t len" "struct sockaddr * restrict from"
+.Fa "socklen_t * restrict fromlen" "struct sctp_sndrcvinfo *sinfo" "int *flags"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn sctp_recvmsg
+system call
+is used to receive a message from another SCTP endpoint.
+The
+.Fn sctp_recvmsg
+call is used by one-to-one (SOCK_STREAM) type sockets after a
+successful
+.Fn connect
+call or after the application has performed a
+.Fn listen
+followed by a successful
+.Fn accept .
+For a one-to-many (SOCK_SEQPACKET) type socket, an endpoint may call
+.Fn sctp_recvmsg
+after having implicitly started an association via one
+of the send calls including
+.Fn sctp_sendmsg
+.Fn sendto
+and
+.Fn sendmsg .
+Or, an application may also receive a message after having
+called
+.Fn listen
+with a positive backlog to enable the reception of new associations.
+.Pp
+The address of the sender is held in the
+.Fa from
+argument with
+.Fa fromlen
+specifying its size.
+At the completion of a successful
+.Fn sctp_recvmsg
+call
+.Fa from
+will hold the address of the peer and
+.Fa fromlen
+will hold the length of that address.
+Note that
+the address is bounded by the initial value of
+.Fa fromlen
+which is used as an in/out variable.
+.Pp
+The length of the message
+.Fa msg
+to be received is bounded by
+.Fa len .
+If the message is too long to fit in the users
+receive buffer, then the
+.Fa flags
+argument will
+.Em not
+have the
+.Dv MSG_EOF
+flag applied.
+If the message is a complete message then
+the
+.Fa flags
+argument will have
+.Dv MSG_EOF
+set.
+Locally detected errors are
+indicated by a return value of -1 with
+.Va errno
+set accordingly.
+The
+.Fa flags
+argument may also hold the value
+.Dv MSG_NOTIFICATION .
+When this
+occurs it indicates that the message received is
+.Em not
+from
+the peer endpoint, but instead is a notification from the
+SCTP stack (see
+.Xr sctp 4
+for more details).
+Note that no notifications are ever
+given unless the user subscribes to such notifications using
+the
+.Dv SCTP_EVENTS
+socket option.
+.Pp
+If no messages are available at the socket then
+.Fn sctp_recvmsg
+normally blocks on the reception of a message or NOTIFICATION, unless the
+socket has been placed in non-blocking I/O mode.
+The
+.Xr select 2
+system call may be used to determine when it is possible to
+receive a message.
+.Pp
+The
+.Fa sinfo
+argument is defined as follows.
+.Bd -literal
+struct sctp_sndrcvinfo {
+ uint16_t sinfo_stream; /* Stream arriving on */
+ uint16_t sinfo_ssn; /* Stream Sequence Number */
+ uint16_t sinfo_flags; /* Flags on the incoming message */
+ uint32_t sinfo_ppid; /* The ppid field */
+ uint32_t sinfo_context; /* context field */
+ uint32_t sinfo_timetolive; /* not used by sctp_recvmsg */
+ uint32_t sinfo_tsn; /* The transport sequence number */
+ uint32_t sinfo_cumtsn; /* The cumulative acknowledgment point */
+ sctp_assoc_t sinfo_assoc_id; /* The association id of the peer */
+};
+.Ed
+.Pp
+The
+.Fa sinfo->sinfo_ppid
+field is an opaque 32 bit value that is passed transparently
+through the stack from the peer endpoint.
+Note that the stack passes this value without regard to byte
+order.
+.Pp
+The
+.Fa sinfo->sinfo_flags
+field may include the following:
+.Bd -literal
+#define SCTP_UNORDERED 0x0400 /* Message is un-ordered */
+.Ed
+.Pp
+The
+.Dv SCTP_UNORDERED
+flag is used to specify that the message arrived with no
+specific order and was delivered to the peer application
+as soon as possible.
+When this flag is absent the message
+was delivered in order within the stream it was received.
+.Pp
+The
+.Fa sinfo->sinfo_stream
+field is the SCTP stream that the message was received on.
+Streams in SCTP are reliable (or partially reliable) flows of ordered
+messages.
+.Pp
+The
+.Fa sinfo->sinfo_context
+field is used only if the local application set an association level
+context with the
+.Dv SCTP_CONTEXT
+socket option.
+Optionally a user process can use this value to index some application
+specific data structure for all data coming from a specific
+association.
+.Pp
+The
+.Fa sinfo->sinfo_ssn
+field will hold the stream sequence number assigned
+by the peer endpoint if the message is
+.Em not
+unordered.
+For unordered messages this field holds an undefined value.
+.Pp
+The
+.Fa sinfo->sinfo_tsn
+field holds a transport sequence number (TSN) that was assigned
+to this message by the peer endpoint.
+For messages that fit in or less
+than the path MTU this will be the only TSN assigned.
+Note that for messages that span multiple TSNs this
+value will be one of the TSNs that was used on the
+message.
+.Pp
+The
+.Fa sinfo->sinfo_cumtsn
+field holds the current cumulative acknowledgment point of
+the transport association.
+Note that this may be larger
+or smaller than the TSN assigned to the message itself.
+.Pp
+The
+.Fa sinfo->sinfo_assoc_id
+is the unique association identification that was assigned
+to the association.
+For one-to-many (SOCK_SEQPACKET) type
+sockets this value can be used to send data to the peer without
+the use of an address field.
+It is also quite useful in
+setting various socket options on the specific association
+(see
+.Xr sctp 4 ) .
+.Pp
+The
+.Fa sinfo->info_timetolive
+field is not used by
+.Fn sctp_recvmsg .
+.Sh RETURN VALUES
+The call returns the number of bytes received, or -1
+if an error occurred.
+.Sh ERRORS
+The
+.Fn sctp_recvmsg
+system call
+fails if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+An invalid descriptor was specified.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.It Bq Er EFAULT
+An invalid user space address was specified for an argument.
+.It Bq Er EMSGSIZE
+The socket requires that message be sent atomically,
+and the size of the message to be sent made this impossible.
+.It Bq Er EAGAIN
+The socket is marked non-blocking and the requested operation
+would block.
+.It Bq Er ENOBUFS
+The system was unable to allocate an internal buffer.
+The operation may succeed when buffers become available.
+.It Bq Er ENOBUFS
+The output queue for a network interface was full.
+This generally indicates that the interface has stopped sending,
+but may be caused by transient congestion.
+.It Bq Er EHOSTUNREACH
+The remote host was unreachable.
+.It Bq Er ENOTCONN
+On a one-to-one style socket no association exists.
+.It Bq Er ECONNRESET
+An abort was received by the stack while the user was
+attempting to send data to the peer.
+.It Bq Er ENOENT
+On a one to many style socket no address is specified
+so that the association cannot be located or the
+SCTP_ABORT flag was specified on a non-existing association.
+.It Bq Er EPIPE
+The socket is unable to send anymore data
+.Dv ( SBS_CANTSENDMORE
+has been set on the socket).
+This typically means that the socket
+is not connected and is a one-to-one style socket.
+.El
+.Sh SEE ALSO
+.Xr recv 2 ,
+.Xr select 2 ,
+.Xr socket 2 ,
+.Xr write 2 ,
+.Xr getsockopt 2 ,
+.Xr setsockopt 2 ,
+.Xr sctp_send 3 ,
+.Xr sctp_sendmsg 3 ,
+.Xr sendmsg 3 ,
+.Xr sctp 4
diff --git a/lib/libc/net/sctp_send.3 b/lib/libc/net/sctp_send.3
new file mode 100644
index 0000000..d195b7a
--- /dev/null
+++ b/lib/libc/net/sctp_send.3
@@ -0,0 +1,354 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 15, 2006
+.Dt SCTP_SEND 3
+.Os
+.Sh NAME
+.Nm sctp_send ,
+.Nm sctp_sendx
+.Nd send a message from an SCTP socket
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft ssize_t
+.Fo sctp_send
+.Fa "int sd" "const void *msg" "size_t len"
+.Fa "const struct sctp_sndrcvinfo *sinfo" "int flags"
+.Fc
+.Ft ssize_t
+.Fo sctp_sendx
+.Fa "int sd" "const void *msg" "size_t len" "struct sockaddr *addrs"
+.Fa "int addrcnt" "const struct sctp_sndrcvinfo *sinfo" "int flags"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn sctp_send
+system call
+is used to transmit a message to another SCTP endpoint.
+.Fn sctp_send
+may be used to send data to an existing association for both
+one-to-many (SOCK_SEQPACKET) and one-to-one (SOCK_STREAM) socket types.
+The length of the message
+.Fa msg
+is given by
+.Fa len .
+If the message is too long to pass atomically through the
+underlying protocol,
+.Va errno
+is set to
+.Er EMSGSIZE ,
+-1 is returned, and
+the message is not transmitted.
+.Pp
+No indication of failure to deliver is implicit in a
+.Fn sctp_send .
+Locally detected errors are indicated by a return value of -1.
+.Pp
+If no space is available at the socket to hold
+the message to be transmitted, then
+.Fn sctp_send
+normally blocks, unless the socket has been placed in
+non-blocking I/O mode.
+The
+.Xr select 2
+system call may be used to determine when it is possible to
+send more data on one-to-one type (SOCK_STREAM) sockets.
+.Pp
+The
+.Fa sinfo
+structure is used to control various SCTP features
+and has the following format:
+.Bd -literal
+struct sctp_sndrcvinfo {
+ uint16_t sinfo_stream; /* Stream sending to */
+ uint16_t sinfo_ssn; /* valid for recv only */
+ uint16_t sinfo_flags; /* flags to control sending */
+ uint32_t sinfo_ppid; /* ppid field */
+ uint32_t sinfo_context; /* context field */
+ uint32_t sinfo_timetolive; /* timetolive for PR-SCTP */
+ uint32_t sinfo_tsn; /* valid for recv only */
+ uint32_t sinfo_cumtsn; /* valid for recv only */
+ sctp_assoc_t sinfo_assoc_id; /* The association id */
+};
+.Ed
+.Pp
+The
+.Fa sinfo->sinfo_ppid
+argument is an opaque 32 bit value that is passed transparently
+through the stack to the peer endpoint. It will be available on
+reception of a message (see
+.Xr sctp_recvmsg 3 ) .
+Note that the stack passes this value without regard to byte
+order.
+.Pp
+The
+.Fa sinfo->sinfo_flags
+argument may include one or more of the following:
+.Bd -literal
+#define SCTP_EOF 0x0100 /* Start a shutdown procedures */
+#define SCTP_ABORT 0x0200 /* Send an ABORT to peer */
+#define SCTP_UNORDERED 0x0400 /* Message is un-ordered */
+#define SCTP_ADDR_OVER 0x0800 /* Override the primary-address */
+#define SCTP_SENDALL 0x1000 /* Send this on all associations */
+ /* for the endpoint */
+/* The lower byte is an enumeration of PR-SCTP policies */
+#define SCTP_PR_SCTP_TTL 0x0001 /* Time based PR-SCTP */
+#define SCTP_PR_SCTP_BUF 0x0002 /* Buffer based PR-SCTP */
+#define SCTP_PR_SCTP_RTX 0x0003 /* Number of retransmissions based PR-SCTP */
+.Ed
+.Pp
+The flag
+.Dv SCTP_EOF
+is used to instruct the SCTP stack to queue this message
+and then start a graceful shutdown of the association.
+All
+remaining data in queue will be sent after which the association
+will be shut down.
+.Pp
+.Dv SCTP_ABORT
+is used to immediately terminate an association.
+An abort
+is sent to the peer and the local TCB is destroyed.
+.Pp
+.Dv SCTP_UNORDERED
+is used to specify that the message being sent has no
+specific order and should be delivered to the peer application
+as soon as possible.
+When this flag is absent messages
+are delivered in order within the stream they are sent, but without
+respect to order to peer streams.
+.Pp
+The flag
+.Dv SCTP_ADDR_OVER
+is used to specify that a specific address should be used.
+Normally
+SCTP will use only one of a multi-homed peers addresses as the primary
+address to send to.
+By default, no matter what the
+.Fa to
+argument is, this primary address is used to send data.
+By specifying
+this flag, the user is asking the stack to ignore the primary address
+and instead use the specified address not only as a lookup mechanism
+to find the association but also as the actual address to send to.
+.Pp
+For a one-to-many type (SOCK_SEQPACKET) socket the flag
+.Dv SCTP_SENDALL
+can be used as a convenient way to make one send call and have
+all associations that are under the socket get a copy of the message.
+Note that this mechanism is quite efficient and makes only one actual
+copy of the data which is shared by all the associations for sending.
+.Pp
+The remaining flags are used for the partial reliability extension (RFC3758)
+and will only be effective if the peer endpoint supports this extension.
+This option specifies what local policy the local endpoint should use
+in skipping data.
+If none of these options are set, then data is
+never skipped over.
+.Pp
+.Dv SCTP_PR_SCTP_TTL
+is used to indicate that a time based lifetime is being applied
+to the data.
+The
+.Fa sinfo->sinfo_timetolive
+argument is then a number of milliseconds for which the data is
+attempted to be transmitted.
+If that many milliseconds elapse
+and the peer has not acknowledged the data, the data will be
+skipped and no longer transmitted.
+Note that this policy does
+not even assure that the data will ever be sent.
+In times of a congestion
+with large amounts of data being queued, the
+.Fa sinfo->sinfo_timetolive
+may expire before the first transmission is ever made.
+.Pp
+The
+.Dv SCTP_PR_SCTP_BUF
+based policy transforms the
+.Fa sinfo->sinfo_timetolive
+field into a total number of bytes allowed on the outbound
+send queue.
+If that number or more bytes are in queue, then
+other buffer-based sends are looked to be removed and
+skipped.
+Note that this policy may also result in the data
+never being sent if no buffer based sends are in queue and
+the maximum specified by
+.Fa timetolive
+bytes is in queue.
+.Pp
+The
+.Dv SCTP_PR_SCTP_RTX
+policy transforms the
+.Fa sinfo->sinfo_timetolive
+into a number of retransmissions to allow.
+This policy
+always assures that at a minimum one send attempt is
+made of the data.
+After which no more than
+.Fa sinfo->sinfo_timetolive
+retransmissions will be made before the data is skipped.
+.Pp
+.Fa sinfo->sinfo_stream
+is the SCTP stream that you wish to send the
+message on.
+Streams in SCTP are reliable (or partially reliable) flows of ordered
+messages.
+.Pp
+The
+.Fa sinfo->sinfo_assoc_id
+field is used to
+select the association to send to on a one-to-many socket.
+For a one-to-one socket, this field is ignored.
+.Pp
+The
+.Fa sinfo->sinfo_context
+field is used only in the event the message cannot be sent.
+This is an opaque
+value that the stack retains and will give to the user when a failed send
+is given if that notification is enabled (see
+.Xr sctp 4 ) .
+Normally a user process can use this value to index some application
+specific data structure when a send cannot be fulfilled.
+.Pp
+The
+.Fa flags
+argument holds the same meaning and values as those found in
+.Xr sendmsg 2
+but is generally ignored by SCTP.
+.Pp
+The fields
+.Fa sinfo->sinfo_ssn ,
+.Fa sinfo->sinfo_tsn ,
+and
+.Fa sinfo->sinfo_cumtsn
+are used only when receiving messages and are thus ignored by
+.Fn sctp_send .
+The function
+.Fn sctp_sendx
+has the same properties as
+.Fn sctp_send
+with the additional arguments of an array of sockaddr structures
+passed in.
+With the
+.Fa addrs
+argument being given as an array of addresses to be sent to and
+the
+.Fa addrcnt
+argument indicating how many socket addresses are in the passed
+in array.
+Note that all of the addresses will only be used
+when an implicit association is being set up.
+This allows the
+user the equivalent behavior as doing a
+.Fn sctp_connectx
+followed by a
+.Fn sctp_send
+to the association.
+Note that if the
+.Fa sinfo->sinfo_assoc_id
+field is 0, then the first address will be used to look up
+the association in place of the association id.
+If both
+an address and an association id are specified, the association
+id has priority.
+.Sh RETURN VALUES
+The call returns the number of characters sent, or -1
+if an error occurred.
+.Sh ERRORS
+The
+.Fn sctp_send
+system call
+fails if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+An invalid descriptor was specified.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.It Bq Er EFAULT
+An invalid user space address was specified for an argument.
+.It Bq Er EMSGSIZE
+The socket requires that message be sent atomically,
+and the size of the message to be sent made this impossible.
+.It Bq Er EAGAIN
+The socket is marked non-blocking and the requested operation
+would block.
+.It Bq Er ENOBUFS
+The system was unable to allocate an internal buffer.
+The operation may succeed when buffers become available.
+.It Bq Er ENOBUFS
+The output queue for a network interface was full.
+This generally indicates that the interface has stopped sending,
+but may be caused by transient congestion.
+.It Bq Er EHOSTUNREACH
+The remote host was unreachable.
+.It Bq Er ENOTCONN
+On a one-to-one style socket no association exists.
+.It Bq Er ECONNRESET
+An abort was received by the stack while the user was
+attempting to send data to the peer.
+.It Bq Er ENOENT
+On a one-to-many style socket no address is specified
+so that the association cannot be located or the
+SCTP_ABORT flag was specified on a non-existing association.
+.It Bq Er EPIPE
+The socket is unable to send anymore data
+.Dv ( SBS_CANTSENDMORE
+has been set on the socket).
+This typically means that the socket
+is not connected and is a one-to-one style socket.
+.El
+.Sh SEE ALSO
+.Xr getsockopt 2 ,
+.Xr recv 2 ,
+.Xr select 2 ,
+.Xr sendmsg 2 ,
+.Xr socket 2 ,
+.Xr write 2
+.Xr sctp_connectx 3 ,
+.Xr sctp_recvmsg 3 ,
+.Xr sctp_sendmsg 3 ,
+.Xr sctp 4
+.Sh BUGS
+Because
+.Fn sctp_send
+may have multiple associations under one endpoint, a
+select on write will only work for a one-to-one style
+socket.
diff --git a/lib/libc/net/sctp_sendmsg.3 b/lib/libc/net/sctp_sendmsg.3
new file mode 100644
index 0000000..4158932
--- /dev/null
+++ b/lib/libc/net/sctp_sendmsg.3
@@ -0,0 +1,333 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" From: @(#)send.2 8.2 (Berkeley) 2/21/94
+.\" $FreeBSD$
+.\"
+.Dd December 15, 2006
+.Dt SCTP_SENDMSG 3
+.Os
+.Sh NAME
+.Nm sctp_sendmsg ,
+.Nm sctp_sendmsgx
+.Nd send a message from an SCTP socket
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/socket.h
+.In netinet/sctp.h
+.Ft ssize_t
+.Fo sctp_sendmsg
+.Fa "int s" "const void *msg" "size_t len" "const struct sockaddr *to"
+.Fa "socklen_t tolen" "uint32_t ppid" "uint32_t flags" "uint16_t stream_no"
+.Fa "uint32_t timetolive" "uint32_t context"
+.Fc
+.Ft ssize_t
+.Fo sctp_sendmsgx
+.Fa "int s" "const void *msg" "size_t len" "const struct sockaddr *to"
+.Fa "int addrcnt" "uint32_t ppid" "uint32_t flags" "uint16_t stream_no"
+.Fa "uint32_t timetolive" "uint32_t context"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn sctp_sendmsg
+system call
+is used to transmit a message to another SCTP endpoint.
+The
+.Fn sctp_sendmsg
+may be used at any time.
+If the socket is a one-to-many type (SOCK_SEQPACKET)
+socket then an attempt to send to an address that no association exists to will
+implicitly create a new association.
+Data sent in such an instance will result in
+the data being sent on the third leg of the SCTP four-way handshake.
+Note that if
+the socket is a one-to-one type (SOCK_STREAM) socket then an association must
+be in existence (by use of the
+.Xr connect 2
+system call).
+Calling
+.Fn sctp_sendmsg
+or
+.Fn sctp_sendmsgx
+on a non-connected one-to-one socket will result in
+.Va errno
+being set to
+.Er ENOTCONN ,
+-1 being returned, and the message not being transmitted.
+.Pp
+The address of the target is given by
+.Fa to
+with
+.Fa tolen
+specifying its size.
+The length of the message
+.Fa msg
+is given by
+.Fa len .
+If the message is too long to pass atomically through the
+underlying protocol,
+.Va errno
+is set to
+.Er EMSGSIZE ,
+-1 is returned, and
+the message is not transmitted.
+.Pp
+No indication of failure to deliver is implicit in a
+.Xr sctp_sendmsg 3
+call.
+Locally detected errors are indicated by a return value of -1.
+.Pp
+If no space is available at the socket to hold
+the message to be transmitted, then
+.Xr sctp_sendmsg 3
+normally blocks, unless the socket has been placed in
+non-blocking I/O mode.
+The
+.Xr select 2
+system call may be used to determine when it is possible to
+send more data on one-to-one type (SOCK_STREAM) sockets.
+.Pp
+The
+.Fa ppid
+argument is an opaque 32 bit value that is passed transparently
+through the stack to the peer endpoint.
+It will be available on
+reception of a message (see
+.Xr sctp_recvmsg 3 ) .
+Note that the stack passes this value without regard to byte
+order.
+.Pp
+The
+.Fa flags
+argument may include one or more of the following:
+.Bd -literal
+#define SCTP_EOF 0x0100 /* Start a shutdown procedures */
+#define SCTP_ABORT 0x0200 /* Send an ABORT to peer */
+#define SCTP_UNORDERED 0x0400 /* Message is un-ordered */
+#define SCTP_ADDR_OVER 0x0800 /* Override the primary-address */
+#define SCTP_SENDALL 0x1000 /* Send this on all associations */
+ /* for the endpoint */
+/* The lower byte is an enumeration of PR-SCTP policies */
+#define SCTP_PR_SCTP_TTL 0x0001 /* Time based PR-SCTP */
+#define SCTP_PR_SCTP_BUF 0x0002 /* Buffer based PR-SCTP */
+#define SCTP_PR_SCTP_RTX 0x0003 /* Number of retransmissions based PR-SCTP */
+.Ed
+.Pp
+The flag
+.Dv SCTP_EOF
+is used to instruct the SCTP stack to queue this message
+and then start a graceful shutdown of the association.
+All
+remaining data in queue will be sent after which the association
+will be shut down.
+.Pp
+.Dv SCTP_ABORT
+is used to immediately terminate an association.
+An abort
+is sent to the peer and the local TCB is destroyed.
+.Pp
+.Dv SCTP_UNORDERED
+is used to specify that the message being sent has no
+specific order and should be delivered to the peer application
+as soon as possible.
+When this flag is absent messages
+are delivered in order within the stream they are sent, but without
+respect to order to peer streams.
+.Pp
+The flag
+.Dv SCTP_ADDR_OVER
+is used to specify that an specific address should be used.
+Normally
+SCTP will use only one of a multi-homed peers addresses as the primary
+address to send to.
+By default, no matter what the
+.Fa to
+argument is, this primary address is used to send data.
+By specifying
+this flag, the user is asking the stack to ignore the primary address
+and instead use the specified address not only as a lookup mechanism
+to find the association but also as the actual address to send to.
+.Pp
+For a one-to-many type (SOCK_SEQPACKET) socket the flag
+.Dv SCTP_SENDALL
+can be used as a convenient way to make one send call and have
+all associations that are under the socket get a copy of the message.
+Note that this mechanism is quite efficient and makes only one actual
+copy of the data which is shared by all the associations for sending.
+.Pp
+The remaining flags are used for the partial reliability extension (RFC3758)
+and will only be effective if the peer endpoint supports this extension.
+This option specifies what local policy the local endpoint should use
+in skipping data.
+If none of these options are set, then data is
+never skipped over.
+.Pp
+.Dv SCTP_PR_SCTP_TTL
+is used to indicate that a time based lifetime is being applied
+to the data.
+The
+.Fa timetolive
+argument is then a number of milliseconds for which the data is
+attempted to be transmitted.
+If that many milliseconds elapse
+and the peer has not acknowledged the data, the data will be
+skipped and no longer transmitted.
+Note that this policy does
+not even assure that the data will ever be sent.
+In times of a congestion
+with large amounts of data being queued, the
+.Fa timetolive
+may expire before the first transmission is ever made.
+.Pp
+The
+.Dv SCTP_PR_SCTP_BUF
+based policy transforms the
+.Fa timetolive
+field into a total number of bytes allowed on the outbound
+send queue.
+If that number or more bytes are in queue, then
+other buffer based sends are looked to be removed and
+skipped.
+Note that this policy may also result in the data
+never being sent if no buffer based sends are in queue and
+the maximum specified by
+.Fa timetolive
+bytes is in queue.
+.Pp
+The
+.Dv SCTP_PR_SCTP_RTX
+policy transforms the
+.Fa timetolive
+into a number of retransmissions to allow.
+This policy
+always assures that at a minimum one send attempt is
+made of the data.
+After which no more than
+.Fa timetolive
+retransmissions will be made before the data is skipped.
+.Pp
+.Fa stream_no
+is the SCTP stream that you wish to send the
+message on.
+Streams in SCTP are reliable (or partially reliable) flows of ordered
+messages.
+The
+.Fa context
+field is used only in the event the message cannot be sent.
+This is an opaque
+value that the stack retains and will give to the user when a failed send
+is given if that notification is enabled (see
+.Xr sctp 4 ) .
+Normally a user process can use this value to index some application
+specific data structure when a send cannot be fulfilled.
+.Fn sctp_sendmsgx
+is identical to
+.Fn sctp_sendmsg
+with the exception that it takes an array of sockaddr structures in the
+argument
+.Fa to
+and adds the additional argument
+.Fa addrcnt
+which specifies how many addresses are in the array.
+This allows a
+caller to implicitly set up an association passing multiple addresses
+as if
+.Fn sctp_connectx
+had been called to set up the association.
+.Sh RETURN VALUES
+The call returns the number of characters sent, or -1
+if an error occurred.
+.Sh ERRORS
+The
+.Fn sctp_sendmsg
+system call
+fails if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+An invalid descriptor was specified.
+.It Bq Er ENOTSOCK
+The argument
+.Fa s
+is not a socket.
+.It Bq Er EFAULT
+An invalid user space address was specified for an argument.
+.It Bq Er EMSGSIZE
+The socket requires that message be sent atomically,
+and the size of the message to be sent made this impossible.
+.It Bq Er EAGAIN
+The socket is marked non-blocking and the requested operation
+would block.
+.It Bq Er ENOBUFS
+The system was unable to allocate an internal buffer.
+The operation may succeed when buffers become available.
+.It Bq Er ENOBUFS
+The output queue for a network interface was full.
+This generally indicates that the interface has stopped sending,
+but may be caused by transient congestion.
+.It Bq Er EHOSTUNREACH
+The remote host was unreachable.
+.It Bq Er ENOTCONN
+On a one-to-one style socket no association exists.
+.It Bq Er ECONNRESET
+An abort was received by the stack while the user was
+attempting to send data to the peer.
+.It Bq Er ENOENT
+On a one-to-many style socket no address is specified
+so that the association cannot be located or the
+.Dv SCTP_ABORT
+flag was specified on a non-existing association.
+.It Bq Er EPIPE
+The socket is unable to send anymore data
+.Dv ( SBS_CANTSENDMORE
+has been set on the socket).
+This typically means that the socket
+is not connected and is a one-to-one style socket.
+.El
+.Sh SEE ALSO
+.Xr connect 2 ,
+.Xr getsockopt 2 ,
+.Xr recv 2 ,
+.Xr select 2 ,
+.Xr socket 2 ,
+.Xr write 2 ,
+.Xr sctp_connectx 3 ,
+.Xr sendmsg 3 ,
+.Xr sctp 4
+.Sh BUGS
+Because in the one-to-many style socket
+.Fn sctp_sendmsg
+or
+.Fn sctp_sendmsgx
+may have multiple associations under one endpoint, a
+select on write will only work for a one-to-one style
+socket.
diff --git a/lib/libc/net/sctp_sys_calls.c b/lib/libc/net/sctp_sys_calls.c
new file mode 100644
index 0000000..e9c9d64
--- /dev/null
+++ b/lib/libc/net/sctp_sys_calls.c
@@ -0,0 +1,1247 @@
+/*-
+ * Copyright (c) 2001-2007, by Cisco Systems, Inc. All rights reserved.
+ * Copyright (c) 2008-2011, by Randall Stewart. All rights reserved.
+ * Copyright (c) 2008-2011, by Michael Tuexen. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * a) Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer.
+ *
+ * b) Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the distribution.
+ *
+ * c) Neither the name of Cisco Systems, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/errno.h>
+#include <sys/syscall.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netinet/sctp_uio.h>
+#include <netinet/sctp.h>
+
+#include <net/if_dl.h>
+
+#ifndef IN6_IS_ADDR_V4MAPPED
+#define IN6_IS_ADDR_V4MAPPED(a) \
+ ((*(const uint32_t *)(const void *)(&(a)->s6_addr[0]) == 0) && \
+ (*(const uint32_t *)(const void *)(&(a)->s6_addr[4]) == 0) && \
+ (*(const uint32_t *)(const void *)(&(a)->s6_addr[8]) == ntohl(0x0000ffff)))
+#endif
+
+
+#define SCTP_CONTROL_VEC_SIZE_SND 8192
+#define SCTP_CONTROL_VEC_SIZE_RCV 16384
+#define SCTP_STACK_BUF_SIZE 2048
+
+#ifdef SCTP_DEBUG_PRINT_ADDRESS
+
+#define SCTP_STRING_BUF_SZ 256
+
+static void
+SCTPPrintAnAddress(struct sockaddr *a)
+{
+ char stringToPrint[SCTP_STRING_BUF_SZ];
+ u_short prt;
+ char *srcaddr, *txt;
+
+ if (a == NULL) {
+ printf("NULL\n");
+ return;
+ }
+ if (a->sa_family == AF_INET) {
+ srcaddr = (char *)&((struct sockaddr_in *)a)->sin_addr;
+ txt = "IPv4 Address: ";
+ prt = ntohs(((struct sockaddr_in *)a)->sin_port);
+ } else if (a->sa_family == AF_INET6) {
+ srcaddr = (char *)&((struct sockaddr_in6 *)a)->sin6_addr;
+ prt = ntohs(((struct sockaddr_in6 *)a)->sin6_port);
+ txt = "IPv6 Address: ";
+ } else if (a->sa_family == AF_LINK) {
+ int i;
+ char tbuf[SCTP_STRING_BUF_SZ];
+ u_char adbuf[SCTP_STRING_BUF_SZ];
+ struct sockaddr_dl *dl;
+
+ dl = (struct sockaddr_dl *)a;
+ strncpy(tbuf, dl->sdl_data, dl->sdl_nlen);
+ tbuf[dl->sdl_nlen] = 0;
+ printf("Intf:%s (len:%d)Interface index:%d type:%x(%d) ll-len:%d ",
+ tbuf,
+ dl->sdl_nlen,
+ dl->sdl_index,
+ dl->sdl_type,
+ dl->sdl_type,
+ dl->sdl_alen
+ );
+ memcpy(adbuf, LLADDR(dl), dl->sdl_alen);
+ for (i = 0; i < dl->sdl_alen; i++) {
+ printf("%2.2x", adbuf[i]);
+ if (i < (dl->sdl_alen - 1))
+ printf(":");
+ }
+ printf("\n");
+ return;
+ } else {
+ return;
+ }
+ if (inet_ntop(a->sa_family, srcaddr, stringToPrint, sizeof(stringToPrint))) {
+ if (a->sa_family == AF_INET6) {
+ printf("%s%s:%d scope:%d\n",
+ txt, stringToPrint, prt,
+ ((struct sockaddr_in6 *)a)->sin6_scope_id);
+ } else {
+ printf("%s%s:%d\n", txt, stringToPrint, prt);
+ }
+
+ } else {
+ printf("%s unprintable?\n", txt);
+ }
+}
+
+#endif /* SCTP_DEBUG_PRINT_ADDRESS */
+
+static void
+in6_sin6_2_sin(struct sockaddr_in *sin, struct sockaddr_in6 *sin6)
+{
+ bzero(sin, sizeof(*sin));
+ sin->sin_len = sizeof(struct sockaddr_in);
+ sin->sin_family = AF_INET;
+ sin->sin_port = sin6->sin6_port;
+ sin->sin_addr.s_addr = sin6->sin6_addr.__u6_addr.__u6_addr32[3];
+}
+
+int
+sctp_getaddrlen(sa_family_t family)
+{
+ int ret, sd;
+ socklen_t siz;
+ struct sctp_assoc_value av;
+
+ av.assoc_value = family;
+ siz = sizeof(av);
+#if defined(AF_INET)
+ sd = socket(AF_INET, SOCK_SEQPACKET, IPPROTO_SCTP);
+#elif defined(AF_INET6)
+ sd = socket(AF_INET6, SOCK_SEQPACKET, IPPROTO_SCTP);
+#else
+ sd = -1;
+#endif
+ if (sd == -1) {
+ return (-1);
+ }
+ ret = getsockopt(sd, IPPROTO_SCTP, SCTP_GET_ADDR_LEN, &av, &siz);
+ close(sd);
+ if (ret == 0) {
+ return ((int)av.assoc_value);
+ } else {
+ return (-1);
+ }
+}
+
+int
+sctp_connectx(int sd, const struct sockaddr *addrs, int addrcnt,
+ sctp_assoc_t * id)
+{
+ char buf[SCTP_STACK_BUF_SIZE];
+ int i, ret, cnt, *aa;
+ char *cpto;
+ const struct sockaddr *at;
+ sctp_assoc_t *p_id;
+ size_t len = sizeof(int);
+
+ /* validate the address count and list */
+ if ((addrs == NULL) || (addrcnt <= 0)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ at = addrs;
+ cnt = 0;
+ cpto = ((caddr_t)buf + sizeof(int));
+ /* validate all the addresses and get the size */
+ for (i = 0; i < addrcnt; i++) {
+ if (at->sa_family == AF_INET) {
+ if (at->sa_len != sizeof(struct sockaddr_in)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ memcpy(cpto, at, at->sa_len);
+ cpto = ((caddr_t)cpto + at->sa_len);
+ len += at->sa_len;
+ } else if (at->sa_family == AF_INET6) {
+ if (at->sa_len != sizeof(struct sockaddr_in6)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (IN6_IS_ADDR_V4MAPPED(&((struct sockaddr_in6 *)at)->sin6_addr)) {
+ len += sizeof(struct sockaddr_in);
+ in6_sin6_2_sin((struct sockaddr_in *)cpto, (struct sockaddr_in6 *)at);
+ cpto = ((caddr_t)cpto + sizeof(struct sockaddr_in));
+ len += sizeof(struct sockaddr_in);
+ } else {
+ memcpy(cpto, at, at->sa_len);
+ cpto = ((caddr_t)cpto + at->sa_len);
+ len += at->sa_len;
+ }
+ } else {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (len > (sizeof(buf) - sizeof(int))) {
+ /* Never enough memory */
+ errno = E2BIG;
+ return (-1);
+ }
+ at = (struct sockaddr *)((caddr_t)at + at->sa_len);
+ cnt++;
+ }
+ /* do we have any? */
+ if (cnt == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+ aa = (int *)buf;
+ *aa = cnt;
+ ret = setsockopt(sd, IPPROTO_SCTP, SCTP_CONNECT_X, (void *)buf,
+ (socklen_t) len);
+ if ((ret == 0) && id) {
+ p_id = (sctp_assoc_t *) buf;
+ *id = *p_id;
+ }
+ return (ret);
+}
+
+int
+sctp_bindx(int sd, struct sockaddr *addrs, int addrcnt, int flags)
+{
+ struct sctp_getaddresses *gaddrs;
+ struct sockaddr *sa;
+ struct sockaddr_in *sin;
+ struct sockaddr_in6 *sin6;
+ int i;
+ size_t argsz;
+ uint16_t sport = 0;
+
+ /* validate the flags */
+ if ((flags != SCTP_BINDX_ADD_ADDR) &&
+ (flags != SCTP_BINDX_REM_ADDR)) {
+ errno = EFAULT;
+ return (-1);
+ }
+ /* validate the address count and list */
+ if ((addrcnt <= 0) || (addrs == NULL)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ argsz = (sizeof(struct sockaddr_storage) +
+ sizeof(struct sctp_getaddresses));
+ gaddrs = (struct sctp_getaddresses *)calloc(1, argsz);
+ if (gaddrs == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ /* First pre-screen the addresses */
+ sa = addrs;
+ for (i = 0; i < addrcnt; i++) {
+ if (sa->sa_family == AF_INET) {
+ if (sa->sa_len != sizeof(struct sockaddr_in))
+ goto out_error;
+ sin = (struct sockaddr_in *)sa;
+ if (sin->sin_port) {
+ /* non-zero port, check or save */
+ if (sport) {
+ /* Check against our port */
+ if (sport != sin->sin_port) {
+ goto out_error;
+ }
+ } else {
+ /* save off the port */
+ sport = sin->sin_port;
+ }
+ }
+ } else if (sa->sa_family == AF_INET6) {
+ if (sa->sa_len != sizeof(struct sockaddr_in6))
+ goto out_error;
+ sin6 = (struct sockaddr_in6 *)sa;
+ if (sin6->sin6_port) {
+ /* non-zero port, check or save */
+ if (sport) {
+ /* Check against our port */
+ if (sport != sin6->sin6_port) {
+ goto out_error;
+ }
+ } else {
+ /* save off the port */
+ sport = sin6->sin6_port;
+ }
+ }
+ } else {
+ /* invalid address family specified */
+ goto out_error;
+ }
+
+ sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len);
+ }
+ sa = addrs;
+ /*
+ * Now if there was a port mentioned, assure that the first address
+ * has that port to make sure it fails or succeeds correctly.
+ */
+ if (sport) {
+ sin = (struct sockaddr_in *)sa;
+ sin->sin_port = sport;
+ }
+ for (i = 0; i < addrcnt; i++) {
+ if (sa->sa_family == AF_INET) {
+ if (sa->sa_len != sizeof(struct sockaddr_in))
+ goto out_error;
+ } else if (sa->sa_family == AF_INET6) {
+ if (sa->sa_len != sizeof(struct sockaddr_in6))
+ goto out_error;
+ } else {
+ /* invalid address family specified */
+ out_error:
+ free(gaddrs);
+ errno = EINVAL;
+ return (-1);
+ }
+ memset(gaddrs, 0, argsz);
+ gaddrs->sget_assoc_id = 0;
+ memcpy(gaddrs->addr, sa, sa->sa_len);
+ if (setsockopt(sd, IPPROTO_SCTP, flags, gaddrs,
+ (socklen_t) argsz) != 0) {
+ free(gaddrs);
+ return (-1);
+ }
+ sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len);
+ }
+ free(gaddrs);
+ return (0);
+}
+
+
+int
+sctp_opt_info(int sd, sctp_assoc_t id, int opt, void *arg, socklen_t * size)
+{
+ if (arg == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ switch (opt) {
+ case SCTP_RTOINFO:
+ ((struct sctp_rtoinfo *)arg)->srto_assoc_id = id;
+ break;
+ case SCTP_ASSOCINFO:
+ ((struct sctp_assocparams *)arg)->sasoc_assoc_id = id;
+ break;
+ case SCTP_DEFAULT_SEND_PARAM:
+ ((struct sctp_assocparams *)arg)->sasoc_assoc_id = id;
+ break;
+ case SCTP_PRIMARY_ADDR:
+ ((struct sctp_setprim *)arg)->ssp_assoc_id = id;
+ break;
+ case SCTP_PEER_ADDR_PARAMS:
+ ((struct sctp_paddrparams *)arg)->spp_assoc_id = id;
+ break;
+ case SCTP_MAXSEG:
+ ((struct sctp_assoc_value *)arg)->assoc_id = id;
+ break;
+ case SCTP_AUTH_KEY:
+ ((struct sctp_authkey *)arg)->sca_assoc_id = id;
+ break;
+ case SCTP_AUTH_ACTIVE_KEY:
+ ((struct sctp_authkeyid *)arg)->scact_assoc_id = id;
+ break;
+ case SCTP_DELAYED_SACK:
+ ((struct sctp_sack_info *)arg)->sack_assoc_id = id;
+ break;
+ case SCTP_CONTEXT:
+ ((struct sctp_assoc_value *)arg)->assoc_id = id;
+ break;
+ case SCTP_STATUS:
+ ((struct sctp_status *)arg)->sstat_assoc_id = id;
+ break;
+ case SCTP_GET_PEER_ADDR_INFO:
+ ((struct sctp_paddrinfo *)arg)->spinfo_assoc_id = id;
+ break;
+ case SCTP_PEER_AUTH_CHUNKS:
+ ((struct sctp_authchunks *)arg)->gauth_assoc_id = id;
+ break;
+ case SCTP_LOCAL_AUTH_CHUNKS:
+ ((struct sctp_authchunks *)arg)->gauth_assoc_id = id;
+ break;
+ case SCTP_TIMEOUTS:
+ ((struct sctp_timeouts *)arg)->stimo_assoc_id = id;
+ break;
+ case SCTP_EVENT:
+ ((struct sctp_event *)arg)->se_assoc_id = id;
+ break;
+ case SCTP_DEFAULT_SNDINFO:
+ ((struct sctp_sndinfo *)arg)->snd_assoc_id = id;
+ break;
+ case SCTP_DEFAULT_PRINFO:
+ ((struct sctp_default_prinfo *)arg)->pr_assoc_id = id;
+ break;
+ case SCTP_PEER_ADDR_THLDS:
+ ((struct sctp_paddrthlds *)arg)->spt_assoc_id = id;
+ break;
+ case SCTP_REMOTE_UDP_ENCAPS_PORT:
+ ((struct sctp_udpencaps *)arg)->sue_assoc_id = id;
+ break;
+ case SCTP_MAX_BURST:
+ ((struct sctp_assoc_value *)arg)->assoc_id = id;
+ break;
+ default:
+ break;
+ }
+ return (getsockopt(sd, IPPROTO_SCTP, opt, arg, size));
+}
+
+int
+sctp_getpaddrs(int sd, sctp_assoc_t id, struct sockaddr **raddrs)
+{
+ struct sctp_getaddresses *addrs;
+ struct sockaddr *sa;
+ sctp_assoc_t asoc;
+ caddr_t lim;
+ socklen_t opt_len;
+ int cnt;
+
+ if (raddrs == NULL) {
+ errno = EFAULT;
+ return (-1);
+ }
+ asoc = id;
+ opt_len = (socklen_t) sizeof(sctp_assoc_t);
+ if (getsockopt(sd, IPPROTO_SCTP, SCTP_GET_REMOTE_ADDR_SIZE,
+ &asoc, &opt_len) != 0) {
+ return (-1);
+ }
+ /* size required is returned in 'asoc' */
+ opt_len = (socklen_t) ((size_t)asoc + sizeof(struct sctp_getaddresses));
+ addrs = calloc(1, (size_t)opt_len);
+ if (addrs == NULL) {
+ return (-1);
+ }
+ addrs->sget_assoc_id = id;
+ /* Now lets get the array of addresses */
+ if (getsockopt(sd, IPPROTO_SCTP, SCTP_GET_PEER_ADDRESSES,
+ addrs, &opt_len) != 0) {
+ free(addrs);
+ return (-1);
+ }
+ *raddrs = (struct sockaddr *)&addrs->addr[0];
+ cnt = 0;
+ sa = (struct sockaddr *)&addrs->addr[0];
+ lim = (caddr_t)addrs + opt_len;
+ while (((caddr_t)sa < lim) && (sa->sa_len > 0)) {
+ sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len);
+ cnt++;
+ }
+ return (cnt);
+}
+
+void
+sctp_freepaddrs(struct sockaddr *addrs)
+{
+ /* Take away the hidden association id */
+ void *fr_addr;
+
+ fr_addr = (void *)((caddr_t)addrs - sizeof(sctp_assoc_t));
+ /* Now free it */
+ free(fr_addr);
+}
+
+int
+sctp_getladdrs(int sd, sctp_assoc_t id, struct sockaddr **raddrs)
+{
+ struct sctp_getaddresses *addrs;
+ caddr_t lim;
+ struct sockaddr *sa;
+ size_t size_of_addresses;
+ socklen_t opt_len;
+ int cnt;
+
+ if (raddrs == NULL) {
+ errno = EFAULT;
+ return (-1);
+ }
+ size_of_addresses = 0;
+ opt_len = (socklen_t) sizeof(int);
+ if (getsockopt(sd, IPPROTO_SCTP, SCTP_GET_LOCAL_ADDR_SIZE,
+ &size_of_addresses, &opt_len) != 0) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ if (size_of_addresses == 0) {
+ errno = ENOTCONN;
+ return (-1);
+ }
+ opt_len = (socklen_t) (size_of_addresses +
+ sizeof(struct sockaddr_storage) +
+ sizeof(struct sctp_getaddresses));
+ addrs = calloc(1, (size_t)opt_len);
+ if (addrs == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ addrs->sget_assoc_id = id;
+ /* Now lets get the array of addresses */
+ if (getsockopt(sd, IPPROTO_SCTP, SCTP_GET_LOCAL_ADDRESSES, addrs,
+ &opt_len) != 0) {
+ free(addrs);
+ errno = ENOMEM;
+ return (-1);
+ }
+ *raddrs = (struct sockaddr *)&addrs->addr[0];
+ cnt = 0;
+ sa = (struct sockaddr *)&addrs->addr[0];
+ lim = (caddr_t)addrs + opt_len;
+ while (((caddr_t)sa < lim) && (sa->sa_len > 0)) {
+ sa = (struct sockaddr *)((caddr_t)sa + sa->sa_len);
+ cnt++;
+ }
+ return (cnt);
+}
+
+void
+sctp_freeladdrs(struct sockaddr *addrs)
+{
+ /* Take away the hidden association id */
+ void *fr_addr;
+
+ fr_addr = (void *)((caddr_t)addrs - sizeof(sctp_assoc_t));
+ /* Now free it */
+ free(fr_addr);
+}
+
+
+ssize_t
+sctp_sendmsg(int s,
+ const void *data,
+ size_t len,
+ const struct sockaddr *to,
+ socklen_t tolen,
+ uint32_t ppid,
+ uint32_t flags,
+ uint16_t stream_no,
+ uint32_t timetolive,
+ uint32_t context)
+{
+#ifdef SYS_sctp_generic_sendmsg
+ struct sctp_sndrcvinfo sinfo;
+
+ memset(&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
+ sinfo.sinfo_ppid = ppid;
+ sinfo.sinfo_flags = flags;
+ sinfo.sinfo_stream = stream_no;
+ sinfo.sinfo_timetolive = timetolive;
+ sinfo.sinfo_context = context;
+ sinfo.sinfo_assoc_id = 0;
+ return (syscall(SYS_sctp_generic_sendmsg, s,
+ data, len, to, tolen, &sinfo, 0));
+#else
+ ssize_t sz;
+ struct msghdr msg;
+ struct sctp_sndrcvinfo *s_info;
+ struct iovec iov;
+ char controlVector[SCTP_CONTROL_VEC_SIZE_RCV];
+ struct cmsghdr *cmsg;
+ struct sockaddr *who = NULL;
+ union {
+ struct sockaddr_in in;
+ struct sockaddr_in6 in6;
+ } addr;
+
+ if ((tolen > 0) &&
+ ((to == NULL) || (tolen < sizeof(struct sockaddr)))) {
+ errno = EINVAL;
+ return -1;
+ }
+ if (to && (tolen > 0)) {
+ if (to->sa_family == AF_INET) {
+ if (tolen != sizeof(struct sockaddr_in)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if ((to->sa_len > 0) &&
+ (to->sa_len != sizeof(struct sockaddr_in))) {
+ errno = EINVAL;
+ return -1;
+ }
+ memcpy(&addr, to, sizeof(struct sockaddr_in));
+ addr.in.sin_len = sizeof(struct sockaddr_in);
+ } else if (to->sa_family == AF_INET6) {
+ if (tolen != sizeof(struct sockaddr_in6)) {
+ errno = EINVAL;
+ return -1;
+ }
+ if ((to->sa_len > 0) &&
+ (to->sa_len != sizeof(struct sockaddr_in6))) {
+ errno = EINVAL;
+ return -1;
+ }
+ memcpy(&addr, to, sizeof(struct sockaddr_in6));
+ addr.in6.sin6_len = sizeof(struct sockaddr_in6);
+ } else {
+ errno = EAFNOSUPPORT;
+ return -1;
+ }
+ who = (struct sockaddr *)&addr;
+ }
+ iov.iov_base = (char *)data;
+ iov.iov_len = len;
+
+ if (who) {
+ msg.msg_name = (caddr_t)who;
+ msg.msg_namelen = who->sa_len;
+ } else {
+ msg.msg_name = (caddr_t)NULL;
+ msg.msg_namelen = 0;
+ }
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = (caddr_t)controlVector;
+
+ cmsg = (struct cmsghdr *)controlVector;
+
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_SNDRCV;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
+ s_info = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+
+ s_info->sinfo_stream = stream_no;
+ s_info->sinfo_ssn = 0;
+ s_info->sinfo_flags = flags;
+ s_info->sinfo_ppid = ppid;
+ s_info->sinfo_context = context;
+ s_info->sinfo_assoc_id = 0;
+ s_info->sinfo_timetolive = timetolive;
+ errno = 0;
+ msg.msg_controllen = cmsg->cmsg_len;
+ sz = sendmsg(s, &msg, 0);
+ return (sz);
+#endif
+}
+
+
+sctp_assoc_t
+sctp_getassocid(int sd, struct sockaddr *sa)
+{
+ struct sctp_paddrinfo sp;
+ socklen_t siz;
+
+ /* First get the assoc id */
+ siz = sizeof(sp);
+ memset(&sp, 0, sizeof(sp));
+ memcpy((caddr_t)&sp.spinfo_address, sa, sa->sa_len);
+ errno = 0;
+ if (getsockopt(sd, IPPROTO_SCTP,
+ SCTP_GET_PEER_ADDR_INFO, &sp, &siz) != 0) {
+ return ((sctp_assoc_t) 0);
+ }
+ /* We depend on the fact that 0 can never be returned */
+ return (sp.spinfo_assoc_id);
+}
+
+ssize_t
+sctp_send(int sd, const void *data, size_t len,
+ const struct sctp_sndrcvinfo *sinfo,
+ int flags)
+{
+
+#ifdef SYS_sctp_generic_sendmsg
+ struct sockaddr *to = NULL;
+
+ return (syscall(SYS_sctp_generic_sendmsg, sd,
+ data, len, to, 0, sinfo, flags));
+#else
+ ssize_t sz;
+ struct msghdr msg;
+ struct iovec iov;
+ struct sctp_sndrcvinfo *s_info;
+ char controlVector[SCTP_CONTROL_VEC_SIZE_SND];
+ struct cmsghdr *cmsg;
+
+ if (sinfo == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ iov.iov_base = (char *)data;
+ iov.iov_len = len;
+
+ msg.msg_name = 0;
+ msg.msg_namelen = 0;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = (caddr_t)controlVector;
+
+ cmsg = (struct cmsghdr *)controlVector;
+
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_SNDRCV;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndrcvinfo));
+ s_info = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+ /* copy in the data */
+ *s_info = *sinfo;
+ errno = 0;
+ msg.msg_controllen = cmsg->cmsg_len;
+ sz = sendmsg(sd, &msg, flags);
+ return (sz);
+#endif
+}
+
+
+
+ssize_t
+sctp_sendx(int sd, const void *msg, size_t msg_len,
+ struct sockaddr *addrs, int addrcnt,
+ struct sctp_sndrcvinfo *sinfo,
+ int flags)
+{
+ struct sctp_sndrcvinfo __sinfo;
+ ssize_t ret;
+ int i, cnt, *aa, saved_errno;
+ char *buf;
+ int no_end_cx = 0;
+ size_t len, add_len;
+ struct sockaddr *at;
+
+ if (addrs == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+#ifdef SYS_sctp_generic_sendmsg
+ if (addrcnt == 1) {
+ socklen_t l;
+
+ /*
+ * Quick way, we don't need to do a connectx so lets use the
+ * syscall directly.
+ */
+ l = addrs->sa_len;
+ return (syscall(SYS_sctp_generic_sendmsg, sd,
+ msg, msg_len, addrs, l, sinfo, flags));
+ }
+#endif
+
+ len = sizeof(int);
+ at = addrs;
+ cnt = 0;
+ /* validate all the addresses and get the size */
+ for (i = 0; i < addrcnt; i++) {
+ if (at->sa_family == AF_INET) {
+ add_len = sizeof(struct sockaddr_in);
+ } else if (at->sa_family == AF_INET6) {
+ add_len = sizeof(struct sockaddr_in6);
+ } else {
+ errno = EINVAL;
+ return (-1);
+ }
+ len += add_len;
+ at = (struct sockaddr *)((caddr_t)at + add_len);
+ cnt++;
+ }
+ /* do we have any? */
+ if (cnt == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+ buf = malloc(len);
+ if (buf == NULL) {
+ return (-1);
+ }
+ aa = (int *)buf;
+ *aa = cnt;
+ aa++;
+ memcpy((caddr_t)aa, addrs, (size_t)(len - sizeof(int)));
+ ret = setsockopt(sd, IPPROTO_SCTP, SCTP_CONNECT_X_DELAYED, (void *)buf,
+ (socklen_t) len);
+
+ free(buf);
+ if (ret != 0) {
+ if (errno == EALREADY) {
+ no_end_cx = 1;
+ goto continue_send;
+ }
+ return (ret);
+ }
+continue_send:
+ if (sinfo == NULL) {
+ sinfo = &__sinfo;
+ memset(&__sinfo, 0, sizeof(__sinfo));
+ }
+ sinfo->sinfo_assoc_id = sctp_getassocid(sd, addrs);
+ if (sinfo->sinfo_assoc_id == 0) {
+ printf("Huh, can't get associd? TSNH!\n");
+ (void)setsockopt(sd, IPPROTO_SCTP, SCTP_CONNECT_X_COMPLETE, (void *)addrs,
+ (socklen_t) addrs->sa_len);
+ errno = ENOENT;
+ return (-1);
+ }
+ ret = sctp_send(sd, msg, msg_len, sinfo, flags);
+ saved_errno = errno;
+ if (no_end_cx == 0)
+ (void)setsockopt(sd, IPPROTO_SCTP, SCTP_CONNECT_X_COMPLETE, (void *)addrs,
+ (socklen_t) addrs->sa_len);
+
+ errno = saved_errno;
+ return (ret);
+}
+
+ssize_t
+sctp_sendmsgx(int sd,
+ const void *msg,
+ size_t len,
+ struct sockaddr *addrs,
+ int addrcnt,
+ uint32_t ppid,
+ uint32_t flags,
+ uint16_t stream_no,
+ uint32_t timetolive,
+ uint32_t context)
+{
+ struct sctp_sndrcvinfo sinfo;
+
+ memset((void *)&sinfo, 0, sizeof(struct sctp_sndrcvinfo));
+ sinfo.sinfo_ppid = ppid;
+ sinfo.sinfo_flags = flags;
+ sinfo.sinfo_ssn = stream_no;
+ sinfo.sinfo_timetolive = timetolive;
+ sinfo.sinfo_context = context;
+ return sctp_sendx(sd, msg, len, addrs, addrcnt, &sinfo, 0);
+}
+
+ssize_t
+sctp_recvmsg(int s,
+ void *dbuf,
+ size_t len,
+ struct sockaddr *from,
+ socklen_t * fromlen,
+ struct sctp_sndrcvinfo *sinfo,
+ int *msg_flags)
+{
+#ifdef SYS_sctp_generic_recvmsg
+ struct iovec iov;
+
+ iov.iov_base = dbuf;
+ iov.iov_len = len;
+ return (syscall(SYS_sctp_generic_recvmsg, s,
+ &iov, 1, from, fromlen, sinfo, msg_flags));
+#else
+ struct sctp_sndrcvinfo *s_info;
+ ssize_t sz;
+ struct msghdr msg;
+ struct iovec iov;
+ char controlVector[SCTP_CONTROL_VEC_SIZE_RCV];
+ struct cmsghdr *cmsg;
+
+ if (msg_flags == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ msg.msg_flags = 0;
+ iov.iov_base = dbuf;
+ iov.iov_len = len;
+ msg.msg_name = (caddr_t)from;
+ if (fromlen == NULL)
+ msg.msg_namelen = 0;
+ else
+ msg.msg_namelen = *fromlen;
+ msg.msg_iov = &iov;
+ msg.msg_iovlen = 1;
+ msg.msg_control = (caddr_t)controlVector;
+ msg.msg_controllen = sizeof(controlVector);
+ errno = 0;
+ sz = recvmsg(s, &msg, *msg_flags);
+ *msg_flags = msg.msg_flags;
+ if (sz <= 0) {
+ return (sz);
+ }
+ s_info = NULL;
+ if (sinfo) {
+ sinfo->sinfo_assoc_id = 0;
+ }
+ if ((msg.msg_controllen) && sinfo) {
+ /*
+ * parse through and see if we find the sctp_sndrcvinfo (if
+ * the user wants it).
+ */
+ cmsg = (struct cmsghdr *)controlVector;
+ while (cmsg) {
+ if ((cmsg->cmsg_len == 0) || (cmsg->cmsg_len > msg.msg_controllen)) {
+ break;
+ }
+ if (cmsg->cmsg_level == IPPROTO_SCTP) {
+ if (cmsg->cmsg_type == SCTP_SNDRCV) {
+ /* Got it */
+ s_info = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+ /* Copy it to the user */
+ if (sinfo)
+ *sinfo = *s_info;
+ break;
+ } else if (cmsg->cmsg_type == SCTP_EXTRCV) {
+ /*
+ * Got it, presumably the user has
+ * asked for this extra info, so the
+ * structure holds more room :-D
+ */
+ s_info = (struct sctp_sndrcvinfo *)CMSG_DATA(cmsg);
+ /* Copy it to the user */
+ if (sinfo) {
+ memcpy(sinfo, s_info, sizeof(struct sctp_extrcvinfo));
+ }
+ break;
+
+ }
+ }
+ cmsg = CMSG_NXTHDR(&msg, cmsg);
+ }
+ }
+ return (sz);
+#endif
+}
+
+ssize_t
+sctp_recvv(int sd,
+ const struct iovec *iov,
+ int iovlen,
+ struct sockaddr *from,
+ socklen_t * fromlen,
+ void *info,
+ socklen_t * infolen,
+ unsigned int *infotype,
+ int *flags)
+{
+ char ctlbuf[SCTP_CONTROL_VEC_SIZE_RCV];
+ struct msghdr msg;
+ struct cmsghdr *cmsg;
+ ssize_t n;
+ struct sctp_rcvinfo *rcvinfo;
+ struct sctp_nxtinfo *nxtinfo;
+
+ if (((info != NULL) && (infolen == NULL)) |
+ ((info == NULL) && (infolen != NULL) && (*infolen != 0)) ||
+ ((info != NULL) && (infotype == NULL))) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (infotype) {
+ *infotype = SCTP_RECVV_NOINFO;
+ }
+ msg.msg_name = from;
+ if (fromlen == NULL) {
+ msg.msg_namelen = 0;
+ } else {
+ msg.msg_namelen = *fromlen;
+ }
+ msg.msg_iov = (struct iovec *)iov;
+ msg.msg_iovlen = iovlen;
+ msg.msg_control = ctlbuf;
+ msg.msg_controllen = sizeof(ctlbuf);
+ errno = 0;
+ n = recvmsg(sd, &msg, *flags);
+ *flags = msg.msg_flags;
+ if ((n > 0) &&
+ (msg.msg_controllen > 0) &&
+ (infotype != NULL) &&
+ (infolen != NULL) &&
+ (*infolen > 0)) {
+ rcvinfo = NULL;
+ nxtinfo = NULL;
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg; cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ if (cmsg->cmsg_level != IPPROTO_SCTP) {
+ continue;
+ }
+ if (cmsg->cmsg_type == SCTP_RCVINFO) {
+ rcvinfo = (struct sctp_rcvinfo *)CMSG_DATA(cmsg);
+ }
+ if (cmsg->cmsg_type == SCTP_NXTINFO) {
+ nxtinfo = (struct sctp_nxtinfo *)CMSG_DATA(cmsg);
+ }
+ if (rcvinfo && nxtinfo) {
+ break;
+ }
+ }
+ if (rcvinfo) {
+ if (nxtinfo) {
+ if (*infolen >= sizeof(struct sctp_recvv_rn)) {
+ struct sctp_recvv_rn *rn_info;
+
+ rn_info = (struct sctp_recvv_rn *)info;
+ rn_info->recvv_rcvinfo = *rcvinfo;
+ rn_info->recvv_nxtinfo = *nxtinfo;
+ *infolen = (socklen_t) sizeof(struct sctp_recvv_rn);
+ *infotype = SCTP_RECVV_RN;
+ }
+ } else {
+ if (*infolen >= sizeof(struct sctp_rcvinfo)) {
+ memcpy(info, rcvinfo, sizeof(struct sctp_rcvinfo));
+ *infolen = (socklen_t) sizeof(struct sctp_rcvinfo);
+ *infotype = SCTP_RECVV_RCVINFO;
+ }
+ }
+ } else if (nxtinfo) {
+ if (*infolen >= sizeof(struct sctp_rcvinfo)) {
+ memcpy(info, nxtinfo, sizeof(struct sctp_nxtinfo));
+ *infolen = (socklen_t) sizeof(struct sctp_nxtinfo);
+ *infotype = SCTP_RECVV_NXTINFO;
+ }
+ }
+ }
+ return (n);
+}
+
+ssize_t
+sctp_sendv(int sd,
+ const struct iovec *iov, int iovcnt,
+ struct sockaddr *addrs, int addrcnt,
+ void *info, socklen_t infolen, unsigned int infotype,
+ int flags)
+{
+ ssize_t ret;
+ int i;
+ socklen_t addr_len;
+ struct msghdr msg;
+ in_port_t port;
+ struct sctp_sendv_spa *spa_info;
+ struct cmsghdr *cmsg;
+ char *cmsgbuf;
+ struct sockaddr *addr;
+ struct sockaddr_in *addr_in;
+ struct sockaddr_in6 *addr_in6;
+
+ if ((addrcnt < 0) ||
+ (iovcnt < 0) ||
+ ((addrs == NULL) && (addrcnt > 0)) ||
+ ((addrs != NULL) && (addrcnt == 0)) ||
+ ((iov == NULL) && (iovcnt > 0)) ||
+ ((iov != NULL) && (iovcnt == 0))) {
+ errno = EINVAL;
+ return (-1);
+ }
+ cmsgbuf = malloc(CMSG_SPACE(sizeof(struct sctp_sndinfo)) +
+ CMSG_SPACE(sizeof(struct sctp_prinfo)) +
+ CMSG_SPACE(sizeof(struct sctp_authinfo)) +
+ (size_t)addrcnt * CMSG_SPACE(sizeof(struct in6_addr)));
+ if (cmsgbuf == NULL) {
+ errno = ENOBUFS;
+ return (-1);
+ }
+ msg.msg_control = cmsgbuf;
+ msg.msg_controllen = 0;
+ cmsg = (struct cmsghdr *)cmsgbuf;
+ switch (infotype) {
+ case SCTP_SENDV_NOINFO:
+ if ((infolen != 0) || (info != NULL)) {
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ break;
+ case SCTP_SENDV_SNDINFO:
+ if ((info == NULL) || (infolen < sizeof(struct sctp_sndinfo))) {
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_SNDINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
+ memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_sndinfo));
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
+ cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_sndinfo)));
+ break;
+ case SCTP_SENDV_PRINFO:
+ if ((info == NULL) || (infolen < sizeof(struct sctp_prinfo))) {
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_PRINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
+ memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_prinfo));
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
+ cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_prinfo)));
+ break;
+ case SCTP_SENDV_AUTHINFO:
+ if ((info == NULL) || (infolen < sizeof(struct sctp_authinfo))) {
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_AUTHINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_authinfo));
+ memcpy(CMSG_DATA(cmsg), info, sizeof(struct sctp_authinfo));
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_authinfo));
+ cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_authinfo)));
+ break;
+ case SCTP_SENDV_SPA:
+ if ((info == NULL) || (infolen < sizeof(struct sctp_sendv_spa))) {
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ spa_info = (struct sctp_sendv_spa *)info;
+ if (spa_info->sendv_flags & SCTP_SEND_SNDINFO_VALID) {
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_SNDINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_sndinfo));
+ memcpy(CMSG_DATA(cmsg), &spa_info->sendv_sndinfo, sizeof(struct sctp_sndinfo));
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_sndinfo));
+ cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_sndinfo)));
+ }
+ if (spa_info->sendv_flags & SCTP_SEND_PRINFO_VALID) {
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_PRINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_prinfo));
+ memcpy(CMSG_DATA(cmsg), &spa_info->sendv_prinfo, sizeof(struct sctp_prinfo));
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_prinfo));
+ cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_prinfo)));
+ }
+ if (spa_info->sendv_flags & SCTP_SEND_AUTHINFO_VALID) {
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_AUTHINFO;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct sctp_authinfo));
+ memcpy(CMSG_DATA(cmsg), &spa_info->sendv_authinfo, sizeof(struct sctp_authinfo));
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct sctp_authinfo));
+ cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct sctp_authinfo)));
+ }
+ break;
+ default:
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ addr = addrs;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+
+ for (i = 0; i < addrcnt; i++) {
+ switch (addr->sa_family) {
+ case AF_INET:
+ addr_len = (socklen_t) sizeof(struct sockaddr_in);
+ addr_in = (struct sockaddr_in *)addr;
+ if (addr_in->sin_len != addr_len) {
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ if (i == 0) {
+ port = addr_in->sin_port;
+ } else {
+ if (port == addr_in->sin_port) {
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_DSTADDRV4;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_addr));
+ memcpy(CMSG_DATA(cmsg), &addr_in->sin_addr, sizeof(struct in_addr));
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct in_addr));
+ cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in_addr)));
+ } else {
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ }
+ break;
+ case AF_INET6:
+ addr_len = (socklen_t) sizeof(struct sockaddr_in6);
+ addr_in6 = (struct sockaddr_in6 *)addr;
+ if (addr_in6->sin6_len != addr_len) {
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ if (i == 0) {
+ port = addr_in6->sin6_port;
+ } else {
+ if (port == addr_in6->sin6_port) {
+ cmsg->cmsg_level = IPPROTO_SCTP;
+ cmsg->cmsg_type = SCTP_DSTADDRV6;
+ cmsg->cmsg_len = CMSG_LEN(sizeof(struct in6_addr));
+ memcpy(CMSG_DATA(cmsg), &addr_in6->sin6_addr, sizeof(struct in6_addr));
+ msg.msg_controllen += CMSG_SPACE(sizeof(struct in6_addr));
+ cmsg = (struct cmsghdr *)((caddr_t)cmsg + CMSG_SPACE(sizeof(struct in6_addr)));
+ } else {
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ }
+ break;
+ default:
+ free(cmsgbuf);
+ errno = EINVAL;
+ return (-1);
+ }
+ if (i == 0) {
+ msg.msg_name = addr;
+ msg.msg_namelen = addr_len;
+ }
+ addr = (struct sockaddr *)((caddr_t)addr + addr_len);
+ }
+ if (msg.msg_controllen == 0) {
+ msg.msg_control = NULL;
+ }
+ msg.msg_iov = (struct iovec *)iov;
+ msg.msg_iovlen = iovcnt;
+ msg.msg_flags = 0;
+ ret = sendmsg(sd, &msg, flags);
+ free(cmsgbuf);
+ return (ret);
+}
+
+
+#if !defined(SYS_sctp_peeloff) && !defined(HAVE_SCTP_PEELOFF_SOCKOPT)
+
+int
+sctp_peeloff(int sd, sctp_assoc_t assoc_id)
+{
+ /* NOT supported, return invalid sd */
+ errno = ENOTSUP;
+ return (-1);
+}
+
+#endif
+#if defined(SYS_sctp_peeloff) && !defined(HAVE_SCTP_PEELOFF_SOCKOPT)
+int
+sctp_peeloff(int sd, sctp_assoc_t assoc_id)
+{
+ return (syscall(SYS_sctp_peeloff, sd, assoc_id));
+}
+
+#endif
+
+
+#undef SCTP_CONTROL_VEC_SIZE_SND
+#undef SCTP_CONTROL_VEC_SIZE_RCV
+#undef SCTP_STACK_BUF_SIZE
diff --git a/lib/libc/net/send.c b/lib/libc/net/send.c
new file mode 100644
index 0000000..101b0ce
--- /dev/null
+++ b/lib/libc/net/send.c
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)send.c 8.2 (Berkeley) 2/21/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <stddef.h>
+#include "un-namespace.h"
+
+ssize_t
+send(s, msg, len, flags)
+ int s, flags;
+ size_t len;
+ const void *msg;
+{
+ return (_sendto(s, msg, len, flags, NULL, 0));
+}
diff --git a/lib/libc/net/sockatmark.3 b/lib/libc/net/sockatmark.3
new file mode 100644
index 0000000..61a1a9f
--- /dev/null
+++ b/lib/libc/net/sockatmark.3
@@ -0,0 +1,123 @@
+.\" Copyright (c) 2002 William C. Fenner. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 13, 2002
+.Dt SOCKATMARK 3
+.Os
+.Sh NAME
+.Nm sockatmark
+.Nd determine whether the read pointer is at the OOB mark
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/socket.h
+.Ft int
+.Fn sockatmark "int s"
+.Sh DESCRIPTION
+To find out if the read pointer is currently pointing at
+the mark in the data stream, the
+.Fn sockatmark
+function is provided.
+If
+.Fn sockatmark
+returns 1, the next read will return data
+after the mark.
+Otherwise (assuming out of band data has arrived),
+the next read will provide data sent by the client prior
+to transmission of the out of band signal.
+The routine used
+in the remote login process to flush output on receipt of an
+interrupt or quit signal is shown below.
+It reads the normal data up to the mark (to discard it),
+then reads the out-of-band byte.
+.Bd -literal -offset indent
+#include <sys/socket.h>
+\&...
+oob()
+{
+ int out = FWRITE, mark;
+ char waste[BUFSIZ];
+
+ /* flush local terminal output */
+ ioctl(1, TIOCFLUSH, (char *)&out);
+ for (;;) {
+ if ((mark = sockatmark(rem)) < 0) {
+ perror("sockatmark");
+ break;
+ }
+ if (mark)
+ break;
+ (void) read(rem, waste, sizeof (waste));
+ }
+ if (recv(rem, &mark, 1, MSG_OOB) < 0) {
+ perror("recv");
+ ...
+ }
+ ...
+}
+.Ed
+.Sh RETURN VALUES
+Upon successful completion, the
+.Fn sockatmark
+function returns the value 1 if the read pointer is pointing at
+the OOB mark, 0 if it is not.
+Otherwise the value \-1 is returned
+and the global variable
+.Va errno
+is set to
+indicate the error.
+.Sh ERRORS
+The
+.Fn sockatmark
+call fails if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa s
+argument
+is not a valid descriptor.
+.It Bq Er ENOTTY
+The
+.Fa s
+argument
+is a descriptor for a file, not a socket.
+.El
+.Sh SEE ALSO
+.Xr recv 2 ,
+.Xr send 2
+.Sh HISTORY
+The
+.Fn sockatmark
+function was introduced by
+.St -p1003.1-2001 ,
+to standardize the historical
+.Dv SIOCATMARK
+.Xr ioctl 2 .
+The
+.Er ENOTTY
+error instead of the usual
+.Er ENOTSOCK
+is to match the historical behavior of
+.Dv SIOCATMARK .
diff --git a/lib/libc/net/sockatmark.c b/lib/libc/net/sockatmark.c
new file mode 100644
index 0000000..e416de8
--- /dev/null
+++ b/lib/libc/net/sockatmark.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2002 William C. Fenner. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <sys/ioctl.h>
+
+int sockatmark(int s)
+{
+ int atmark;
+
+ if (ioctl(s, SIOCATMARK, &atmark) == -1)
+ return -1;
+ return atmark;
+}
diff --git a/lib/libc/net/sourcefilter.3 b/lib/libc/net/sourcefilter.3
new file mode 100644
index 0000000..c7293e0
--- /dev/null
+++ b/lib/libc/net/sourcefilter.3
@@ -0,0 +1,240 @@
+.\" Copyright (c) 2007-2009 Bruce Simpson.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 13, 2009
+.Dt SOURCEFILTER 3
+.Os
+.Sh NAME
+.Nm sourcefilter
+.Nd advanced multicast group membership API
+.Sh SYNOPSIS
+.In sys/socket.h
+.In netinet/in.h
+.Ft int
+.Fo getipv4sourcefilter
+.Fa "int s"
+.Fa "struct in_addr interface"
+.Fa "struct in_addr group"
+.Fa "uint32_t *fmode"
+.Fa "uint32_t *numsrc"
+.Fa "struct in_addr *slist"
+.Fc
+.Ft int
+.Fo getsourcefilter
+.Fa "int s"
+.Fa "uint32_t interface"
+.Fa "struct sockaddr *group"
+.Fa "socklen_t grouplen"
+.Fa "uint32_t *fmode"
+.Fa "uint32_t *numsrc"
+.Fa "struct sockaddr_storage *slist"
+.Fc
+.Ft int
+.Fo setipv4sourcefilter
+.Fa "int s"
+.Fa "struct in_addr interface"
+.Fa "struct in_addr group"
+.Fa "uint32_t fmode"
+.Fa "uint32_t numsrc"
+.Fa "struct in_addr *slist"
+.Fc
+.Ft int
+.Fo setsourcefilter
+.Fa "int s"
+.Fa "uint32_t interface"
+.Fa "struct sockaddr *group"
+.Fa "socklen_t grouplen"
+.Fa "uint32_t fmode"
+.Fa "uint32_t numsrc"
+.Fa "struct sockaddr_storage *slist"
+.Fc
+.Sh DESCRIPTION
+The
+.Nm
+functions implement the advanced, full-state multicast API
+defined in RFC 3678.
+An application may use these functions to atomically set and
+retrieve the multicast source address filters associated with a socket
+.Fa s
+and a multicast
+.Fa group .
+.Pp
+The functions
+.Fn getipv4sourcefilter
+and
+.Fn getsourcefilter
+allow an application to discover the filter mode, and
+source filter entries,
+for an existing group membership.
+.Pp
+The kernel will always return the number of source filter
+entries on the socket for that group in
+.Fa *numsrc .
+If the
+.Fa *numsrc
+argument is non-zero, the kernel will attempt to return up to
+.Fa *numsrc
+filter entries in the array pointed to by
+.Fa slist .
+The
+.Fa *numsrc
+argument may be set to 0, in which case the
+.Fa slist
+argument will be ignored.
+.Pp
+For the
+.Fn setipv4sourcefilter
+and
+.Fn setsourcefilter
+functions,
+the
+.Fa fmode
+argument may be used to place the socket into inclusive or exclusive
+group membership modes, by using the
+.Dv MCAST_INCLUDE
+or
+.Dv MCAST_EXCLUDE
+constants respectively.
+The
+.Fa numsrc
+argument specifies the number of source entries in the
+.Fa slist
+array.
+If the
+.Fa numsrc
+argument has a value of 0,
+all source filters will be removed from the socket.
+Removing all source filters from a membership which is in the
+.Dv MCAST_INCLUDE
+filter mode will cause the group to be left on that socket.
+.Pp
+The protocol-independent function
+.Fn setsourcefilter
+allows an application to join a multicast group on an interface
+which may not have an assigned protocol address,
+by passing its index for the
+.Fa interface
+argument.
+.Pp
+Any changes made by these functions
+will be communicated to IGMPv3 and/or MLDv2 routers
+on the local network as appropriate.
+If no IGMPv3 or MLDv2 routers are present, changes in the source filter
+lists made by these functions will not cause
+state changes to be transmitted, with the exception of any
+change which causes a group to be joined or left.
+The kernel will continue to maintain the source filter state
+regardless of the IGMP or MLD version in use on the link.
+.Sh IMPLEMENTATION NOTES
+The IPv4 specific versions of these functions are implemented in terms
+of the protocol-independent functions.
+Application writers are encouraged to use the protocol-independent functions
+for efficiency, and forwards compatibility with IPv6 networks.
+.Pp
+For the protocol-independent functions
+.Fn getsourcefilter
+and
+.Fn setsourcefilter ,
+the argument
+.Fa grouplen
+argument specifies the size of the structure pointed to by
+.Fa group .
+This is required in order to differentiate between different
+address families.
+.Pp
+Currently
+.Fx
+does not support source address selection for the IPv4
+protocol family, therefore the use of multicast APIs with
+an unnumbered IPv4 interface is
+.Em not recommended.
+In all cases, the first assigned IPv4 address on the interface
+will be used as the source address of IGMP control traffic.
+If this address is removed or changed, the results are undefined.
+.Sh RETURN VALUES
+.Rv -std getsourcefilter getipv4sourcefilter setsourcefilter setipv4sourcefilter
+.Sh ERRORS
+The
+.Nm
+functions may fail because of:
+.Bl -tag -width Er
+.It Bq Er EADDRNOTAVAIL
+The network interface which the
+.Dv interface
+argument refers to was not configured in the system,
+or the system is not a member of the
+.Dv group .
+.It Bq Er EAFNOSUPPORT
+The
+.Dv group
+and/or one or more of the
+.Dv slist
+arguments were of an address family unsupported by the system,
+or the address family of the
+.Dv group
+and
+.Dv slist
+arguments were not identical.
+.It Bq Er EINVAL
+The
+.Dv group
+argument does not contain a multicast address.
+The
+.Dv fmode
+argument is invalid; it must be set to either
+.Dv MCAST_INCLUDE
+or
+.Dv MCAST_EXCLUDE .
+The
+.Dv numsrc
+or
+.Dv slist
+arguments do not specify a source list.
+.It Bq Er ENOMEM
+Insufficient memory was available to carry out the requested
+operation.
+.El
+.Sh SEE ALSO
+.Xr ip 4 ,
+.Xr ip6 4 ,
+.Xr multicast 4,
+.Xr ifmcstat 8
+.Rs
+.%A D. Thaler
+.%A B. Fenner
+.%A B. Quinn
+.%T "Socket Interface Extensions for Multicast Source Filters"
+.%N RFC 3678
+.%D Jan 2004
+.Re
+.Sh HISTORY
+The
+.Nm
+functions first appeared in
+.Fx 7.0 .
+.Sh AUTHORS
+Bruce M. Simpson
+.Aq bms@FreeBSD.org
diff --git a/lib/libc/net/sourcefilter.c b/lib/libc/net/sourcefilter.c
new file mode 100644
index 0000000..cc0f1b9
--- /dev/null
+++ b/lib/libc/net/sourcefilter.c
@@ -0,0 +1,402 @@
+/*-
+ * Copyright (c) 2007-2009 Bruce Simpson.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/ioctl.h>
+#include <sys/socket.h>
+
+#include <net/if_dl.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <ifaddrs.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "un-namespace.h"
+
+/*
+ * Advanced (Full-state) multicast group membership APIs [RFC3678]
+ * Currently this module assumes IPv4 support (INET) in the base system.
+ */
+#ifndef INET
+#define INET
+#endif
+
+union sockunion {
+ struct sockaddr_storage ss;
+ struct sockaddr sa;
+ struct sockaddr_dl sdl;
+#ifdef INET
+ struct sockaddr_in sin;
+#endif
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+#endif
+};
+typedef union sockunion sockunion_t;
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif
+
+/*
+ * Internal: Map an IPv4 unicast address to an interface index.
+ * This is quite inefficient so it is recommended applications use
+ * the newer, more portable, protocol independent API.
+ */
+static uint32_t
+__inaddr_to_index(in_addr_t ifaddr)
+{
+ struct ifaddrs *ifa;
+ struct ifaddrs *ifaddrs;
+ char *ifname;
+ int ifindex;
+ sockunion_t *psu;
+
+ if (getifaddrs(&ifaddrs) < 0)
+ return (0);
+
+ ifindex = 0;
+ ifname = NULL;
+
+ /*
+ * Pass #1: Find the ifaddr entry corresponding to the
+ * supplied IPv4 address. We should really use the ifindex
+ * consistently for matches, however it is not available to
+ * us on this pass.
+ */
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ psu = (sockunion_t *)ifa->ifa_addr;
+ if (psu && psu->ss.ss_family == AF_INET &&
+ psu->sin.sin_addr.s_addr == ifaddr) {
+ ifname = ifa->ifa_name;
+ break;
+ }
+ }
+ if (ifname == NULL)
+ goto out;
+
+ /*
+ * Pass #2: Find the index of the interface matching the name
+ * we obtained from looking up the IPv4 ifaddr in pass #1.
+ * There must be a better way of doing this.
+ */
+ for (ifa = ifaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ psu = (sockunion_t *)ifa->ifa_addr;
+ if (psu && psu->ss.ss_family == AF_LINK &&
+ strcmp(ifa->ifa_name, ifname) == 0) {
+ ifindex = psu->sdl.sdl_index;
+ break;
+ }
+ }
+ assert(ifindex != 0);
+
+out:
+ freeifaddrs(ifaddrs);
+ return (ifindex);
+}
+
+/*
+ * Set IPv4 source filter list in use on socket.
+ *
+ * Stubbed to setsourcefilter(). Performs conversion of structures which
+ * may be inefficient; applications are encouraged to use the
+ * protocol-independent API.
+ */
+int
+setipv4sourcefilter(int s, struct in_addr interface, struct in_addr group,
+ uint32_t fmode, uint32_t numsrc, struct in_addr *slist)
+{
+#ifdef INET
+ sockunion_t tmpgroup;
+ struct in_addr *pina;
+ sockunion_t *psu, *tmpslist;
+ int err;
+ size_t i;
+ uint32_t ifindex;
+
+ assert(s != -1);
+
+ tmpslist = NULL;
+
+ if (!IN_MULTICAST(ntohl(group.s_addr)) ||
+ (fmode != MCAST_INCLUDE && fmode != MCAST_EXCLUDE)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ifindex = __inaddr_to_index(interface.s_addr);
+ if (ifindex == 0) {
+ errno = EADDRNOTAVAIL;
+ return (-1);
+ }
+
+ memset(&tmpgroup, 0, sizeof(sockunion_t));
+ tmpgroup.sin.sin_family = AF_INET;
+ tmpgroup.sin.sin_len = sizeof(struct sockaddr_in);
+ tmpgroup.sin.sin_addr = group;
+
+ if (numsrc != 0 || slist != NULL) {
+ tmpslist = calloc(numsrc, sizeof(sockunion_t));
+ if (tmpslist == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ pina = slist;
+ psu = tmpslist;
+ for (i = 0; i < numsrc; i++, pina++, psu++) {
+ psu->sin.sin_family = AF_INET;
+ psu->sin.sin_len = sizeof(struct sockaddr_in);
+ psu->sin.sin_addr = *pina;
+ }
+ }
+
+ err = setsourcefilter(s, ifindex, (struct sockaddr *)&tmpgroup,
+ sizeof(struct sockaddr_in), fmode, numsrc,
+ (struct sockaddr_storage *)tmpslist);
+
+ if (tmpslist != NULL)
+ free(tmpslist);
+
+ return (err);
+#else /* !INET */
+ return (EAFNOSUPPORT);
+#endif /* INET */
+}
+
+/*
+ * Get IPv4 source filter list in use on socket.
+ *
+ * Stubbed to getsourcefilter(). Performs conversion of structures which
+ * may be inefficient; applications are encouraged to use the
+ * protocol-independent API.
+ * An slist of NULL may be used for guessing the required buffer size.
+ */
+int
+getipv4sourcefilter(int s, struct in_addr interface, struct in_addr group,
+ uint32_t *fmode, uint32_t *numsrc, struct in_addr *slist)
+{
+ sockunion_t *psu, *tmpslist;
+ sockunion_t tmpgroup;
+ struct in_addr *pina;
+ int err;
+ size_t i;
+ uint32_t ifindex, onumsrc;
+
+ assert(s != -1);
+ assert(fmode != NULL);
+ assert(numsrc != NULL);
+
+ onumsrc = *numsrc;
+ *numsrc = 0;
+ tmpslist = NULL;
+
+ if (!IN_MULTICAST(ntohl(group.s_addr)) ||
+ (onumsrc != 0 && slist == NULL)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ ifindex = __inaddr_to_index(interface.s_addr);
+ if (ifindex == 0) {
+ errno = EADDRNOTAVAIL;
+ return (-1);
+ }
+
+ memset(&tmpgroup, 0, sizeof(sockunion_t));
+ tmpgroup.sin.sin_family = AF_INET;
+ tmpgroup.sin.sin_len = sizeof(struct sockaddr_in);
+ tmpgroup.sin.sin_addr = group;
+
+ if (onumsrc != 0 || slist != NULL) {
+ tmpslist = calloc(onumsrc, sizeof(sockunion_t));
+ if (tmpslist == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ }
+
+ err = getsourcefilter(s, ifindex, (struct sockaddr *)&tmpgroup,
+ sizeof(struct sockaddr_in), fmode, numsrc,
+ (struct sockaddr_storage *)tmpslist);
+
+ if (tmpslist != NULL && *numsrc != 0) {
+ pina = slist;
+ psu = tmpslist;
+ for (i = 0; i < MIN(onumsrc, *numsrc); i++, psu++) {
+ if (psu->ss.ss_family != AF_INET)
+ continue;
+ *pina++ = psu->sin.sin_addr;
+ }
+ free(tmpslist);
+ }
+
+ return (err);
+}
+
+/*
+ * Set protocol-independent source filter list in use on socket.
+ */
+int
+setsourcefilter(int s, uint32_t interface, struct sockaddr *group,
+ socklen_t grouplen, uint32_t fmode, uint32_t numsrc,
+ struct sockaddr_storage *slist)
+{
+ struct __msfilterreq msfr;
+ sockunion_t *psu;
+ int level, optname;
+
+ if (fmode != MCAST_INCLUDE && fmode != MCAST_EXCLUDE) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ psu = (sockunion_t *)group;
+ switch (psu->ss.ss_family) {
+#ifdef INET
+ case AF_INET:
+ if ((grouplen != sizeof(struct sockaddr_in) ||
+ !IN_MULTICAST(ntohl(psu->sin.sin_addr.s_addr)))) {
+ errno = EINVAL;
+ return (-1);
+ }
+ level = IPPROTO_IP;
+ optname = IP_MSFILTER;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (grouplen != sizeof(struct sockaddr_in6) ||
+ !IN6_IS_ADDR_MULTICAST(&psu->sin6.sin6_addr)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ level = IPPROTO_IPV6;
+ optname = IPV6_MSFILTER;
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ }
+
+ memset(&msfr, 0, sizeof(msfr));
+ msfr.msfr_ifindex = interface;
+ msfr.msfr_fmode = fmode;
+ msfr.msfr_nsrcs = numsrc;
+ memcpy(&msfr.msfr_group, &psu->ss, psu->ss.ss_len);
+ msfr.msfr_srcs = slist; /* pointer */
+
+ return (_setsockopt(s, level, optname, &msfr, sizeof(msfr)));
+}
+
+/*
+ * Get protocol-independent source filter list in use on socket.
+ * An slist of NULL may be used for guessing the required buffer size.
+ */
+int
+getsourcefilter(int s, uint32_t interface, struct sockaddr *group,
+ socklen_t grouplen, uint32_t *fmode, uint32_t *numsrc,
+ struct sockaddr_storage *slist)
+{
+ struct __msfilterreq msfr;
+ sockunion_t *psu;
+ int err, level, nsrcs, optlen, optname;
+
+ if (interface == 0 || group == NULL || numsrc == NULL ||
+ fmode == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ nsrcs = *numsrc;
+ *numsrc = 0;
+ *fmode = 0;
+
+ psu = (sockunion_t *)group;
+ switch (psu->ss.ss_family) {
+#ifdef INET
+ case AF_INET:
+ if ((grouplen != sizeof(struct sockaddr_in) ||
+ !IN_MULTICAST(ntohl(psu->sin.sin_addr.s_addr)))) {
+ errno = EINVAL;
+ return (-1);
+ }
+ level = IPPROTO_IP;
+ optname = IP_MSFILTER;
+ break;
+#endif
+#ifdef INET6
+ case AF_INET6:
+ if (grouplen != sizeof(struct sockaddr_in6) ||
+ !IN6_IS_ADDR_MULTICAST(&psu->sin6.sin6_addr)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ level = IPPROTO_IPV6;
+ optname = IPV6_MSFILTER;
+ break;
+#endif
+ default:
+ errno = EAFNOSUPPORT;
+ return (-1);
+ break;
+ }
+
+ optlen = sizeof(struct __msfilterreq);
+ memset(&msfr, 0, optlen);
+ msfr.msfr_ifindex = interface;
+ msfr.msfr_fmode = 0;
+ msfr.msfr_nsrcs = nsrcs;
+ memcpy(&msfr.msfr_group, &psu->ss, psu->ss.ss_len);
+
+ /*
+ * msfr_srcs is a pointer to a vector of sockaddr_storage. It
+ * may be NULL. The kernel will always return the total number
+ * of filter entries for the group in msfr.msfr_nsrcs.
+ */
+ msfr.msfr_srcs = slist;
+ err = _getsockopt(s, level, optname, &msfr, &optlen);
+ if (err == 0) {
+ *numsrc = msfr.msfr_nsrcs;
+ *fmode = msfr.msfr_fmode;
+ }
+
+ return (err);
+}
diff --git a/lib/libc/net/vars.c b/lib/libc/net/vars.c
new file mode 100644
index 0000000..42ee205
--- /dev/null
+++ b/lib/libc/net/vars.c
@@ -0,0 +1,45 @@
+/* $KAME: vars.c,v 1.2 2001/08/20 02:32:41 itojun Exp $ */
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <netinet/in.h>
+
+/*
+ * Definitions of some costant IPv6 addresses.
+ */
+const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
+const struct in6_addr in6addr_loopback = IN6ADDR_LOOPBACK_INIT;
+const struct in6_addr in6addr_nodelocal_allnodes = IN6ADDR_NODELOCAL_ALLNODES_INIT;
+const struct in6_addr in6addr_linklocal_allnodes = IN6ADDR_LINKLOCAL_ALLNODES_INIT;
+
diff --git a/lib/libc/nls/C.msg b/lib/libc/nls/C.msg
new file mode 100644
index 0000000..2210df6
--- /dev/null
+++ b/lib/libc/nls/C.msg
@@ -0,0 +1,295 @@
+$ $FreeBSD$
+$
+$ Message catalog for C locale (template)
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operation not permitted
+$ ENOENT
+2 No such file or directory
+$ ESRCH
+3 No such process
+$ EINTR
+4 Interrupted system call
+$ EIO
+5 Input/output error
+$ ENXIO
+6 Device not configured
+$ E2BIG
+7 Argument list too long
+$ ENOEXEC
+8 Exec format error
+$ EBADF
+9 Bad file descriptor
+$ ECHILD
+10 No child processes
+$ EDEADLK
+11 Resource deadlock avoided
+$ ENOMEM
+12 Cannot allocate memory
+$ EACCES
+13 Permission denied
+$ EFAULT
+14 Bad address
+$ ENOTBLK
+15 Block device required
+$ EBUSY
+16 Device busy
+$ EEXIST
+17 File exists
+$ EXDEV
+18 Cross-device link
+$ ENODEV
+19 Operation not supported by device
+$ ENOTDIR
+20 Not a directory
+$ EISDIR
+21 Is a directory
+$ EINVAL
+22 Invalid argument
+$ ENFILE
+23 Too many open files in system
+$ EMFILE
+24 Too many open files
+$ ENOTTY
+25 Inappropriate ioctl for device
+$ ETXTBSY
+26 Text file busy
+$ EFBIG
+27 File too large
+$ ENOSPC
+28 No space left on device
+$ ESPIPE
+29 Illegal seek
+$ EROFS
+30 Read-only file system
+$ EMLINK
+31 Too many links
+$ EPIPE
+32 Broken pipe
+$ EDOM
+33 Numerical argument out of domain
+$ ERANGE
+34 Result too large
+$ EAGAIN, EWOULDBLOCK
+35 Resource temporarily unavailable
+$ EINPROGRESS
+36 Operation now in progress
+$ EALREADY
+37 Operation already in progress
+$ ENOTSOCK
+38 Socket operation on non-socket
+$ EDESTADDRREQ
+39 Destination address required
+$ EMSGSIZE
+40 Message too long
+$ EPROTOTYPE
+41 Protocol wrong type for socket
+$ ENOPROTOOPT
+42 Protocol not available
+$ EPROTONOSUPPORT
+43 Protocol not supported
+$ ESOCKTNOSUPPORT
+44 Socket type not supported
+$ EOPNOTSUPP
+45 Operation not supported
+$ EPFNOSUPPORT
+46 Protocol family not supported
+$ EAFNOSUPPORT
+47 Address family not supported by protocol family
+$ EADDRINUSE
+48 Address already in use
+$ EADDRNOTAVAIL
+49 Can't assign requested address
+$ ENETDOWN
+50 Network is down
+$ ENETUNREACH
+51 Network is unreachable
+$ ENETRESET
+52 Network dropped connection on reset
+$ ECONNABORTED
+53 Software caused connection abort
+$ ECONNRESET
+54 Connection reset by peer
+$ ENOBUFS
+55 No buffer space available
+$ EISCONN
+56 Socket is already connected
+$ ENOTCONN
+57 Socket is not connected
+$ ESHUTDOWN
+58 Can't send after socket shutdown
+$ ETOOMANYREFS
+59 Too many references: can't splice
+$ ETIMEDOUT
+60 Operation timed out
+$ ECONNREFUSED
+61 Connection refused
+$ ELOOP
+62 Too many levels of symbolic links
+$ ENAMETOOLONG
+63 File name too long
+$ EHOSTDOWN
+64 Host is down
+$ EHOSTUNREACH
+65 No route to host
+$ ENOTEMPTY
+66 Directory not empty
+$ EPROCLIM
+67 Too many processes
+$ EUSERS
+68 Too many users
+$ EDQUOT
+69 Disc quota exceeded
+$ ESTALE
+70 Stale NFS file handle
+$ EREMOTE
+71 Too many levels of remote in path
+$ EBADRPC
+72 RPC struct is bad
+$ ERPCMISMATCH
+73 RPC version wrong
+$ EPROGUNAVAIL
+74 RPC prog. not avail
+$ EPROGMISMATCH
+75 Program version wrong
+$ EPROCUNAVAIL
+76 Bad procedure for program
+$ ENOLCK
+77 No locks available
+$ ENOSYS
+78 Function not implemented
+$ EFTYPE
+79 Inappropriate file type or format
+$ EAUTH
+80 Authentication error
+$ ENEEDAUTH
+81 Need authenticator
+$ EIDRM
+82 Identifier removed
+$ ENOMSG
+83 No message of desired type
+$ EOVERFLOW
+84 Value too large to be stored in data type
+$ ECANCELED
+85 Operation canceled
+$ EILSEQ
+86 Illegal byte sequence
+$ ENOATTR
+87 Attribute not found
+$ EDOOFUS
+88 Programming error
+$ EBADMSG
+89 Bad message
+$ EMULTIHOP
+90 Multihop attempted
+$ ENOLINK
+91 Link has been severed
+$ EPROTO
+92 Protocol error
+$ ENOTCAPABLE
+93 Capabilities insufficient
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Hangup
+$ SIGINT
+2 Interrupt
+$ SIGQUIT
+3 Quit
+$ SIGILL
+4 Illegal instruction
+$ SIGTRAP
+5 Trace/BPT trap
+$ SIGABRT
+6 Abort trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Floating point exception
+$ SIGKILL
+9 Killed
+$ SIGBUS
+10 Bus error
+$ SIGSEGV
+11 Segmentation fault
+$ SIGSYS
+12 Bad system call
+$ SIGPIPE
+13 Broken pipe
+$ SIGALRM
+14 Alarm clock
+$ SIGTERM
+15 Terminated
+$ SIGURG
+16 Urgent I/O condition
+$ SIGSTOP
+17 Suspended (signal)
+$ SIGTSTP
+18 Suspended
+$ SIGCONT
+19 Continued
+$ SIGCHLD
+20 Child exited
+$ SIGTTIN
+21 Stopped (tty input)
+$ SIGTTOU
+22 Stopped (tty output)
+$ SIGIO
+23 I/O possible
+$ SIGXCPU
+24 Cputime limit exceeded
+$ SIGXFSZ
+25 Filesize limit exceeded
+$ SIGVTALRM
+26 Virtual timer expired
+$ SIGPROF
+27 Profiling timer expired
+$ SIGWINCH
+28 Window size changes
+$ SIGINFO
+29 Information request
+$ SIGUSR1
+30 User defined signal 1
+$ SIGUSR2
+31 User defined signal 2
+$
+$ gai_strerror() support catalog
+$
+$set 3
+$ 1 (obsolete)
+1 Address family for hostname not supported
+$ EAI_AGAIN
+2 Temporary failure in name resolution
+$ EAI_BADFLAGS
+3 Invalid value for ai_flags
+$ EAI_FAIL
+4 Non-recoverable failure in name resolution
+$ EAI_FAMILY
+5 ai_family not supported
+$ EAI_MEMORY
+6 Memory allocation failure
+$ 7 (obsolete)
+7 No address associated with hostname
+$ EAI_NONAME
+8 hostname nor servname provided, or not known
+$ EAI_SERVICE
+9 servname not supported for ai_socktype
+$ EAI_SOCKTYPE
+10 ai_socktype not supported
+$ EAI_SYSTEM
+11 System error returned in errno
+$ EAI_BADHINTS
+12 Invalid value for hints
+$ EAI_PROTOCOL
+13 Resolved protocol is unknown
+$ EAI_OVERFLOW
+14 Argument buffer overflow
+$ 0
+32766 Success
+$ NL_MSGMAX
+32767 Unknown error
diff --git a/lib/libc/nls/Makefile.inc b/lib/libc/nls/Makefile.inc
new file mode 100644
index 0000000..f5c6885
--- /dev/null
+++ b/lib/libc/nls/Makefile.inc
@@ -0,0 +1,38 @@
+# from $NetBSD: Makefile.inc,v 1.7 1995/02/27 13:06:20 cgd Exp $
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/nls
+
+SRCS+= msgcat.c
+
+SYM_MAPS+=${.CURDIR}/nls/Symbol.map
+
+MAN+= catclose.3 catgets.3 catopen.3
+
+# NOTE: C.msg should not be processed here, it's used as a template
+# for translators.
+
+NLSNAME= libc
+NLS+= be_BY.UTF-8
+NLS+= ca_ES.ISO8859-1
+NLS+= de_DE.ISO8859-1
+NLS+= el_GR.ISO8859-7
+NLS+= es_ES.ISO8859-1
+NLS+= fi_FI.ISO8859-1
+NLS+= fr_FR.ISO8859-1
+NLS+= gl_ES.ISO8859-1
+NLS+= hu_HU.ISO8859-2
+NLS+= it_IT.ISO8859-15
+NLS+= ja_JP.UTF-8
+NLS+= ja_JP.eucJP
+NLS+= ko_KR.UTF-8
+NLS+= ko_KR.eucKR
+NLS+= mn_MN.UTF-8
+NLS+= nl_NL.ISO8859-1
+NLS+= no_NO.ISO8859-1
+NLS+= pl_PL.ISO8859-2
+NLS+= pt_BR.ISO8859-1
+NLS+= ru_RU.KOI8-R
+NLS+= sk_SK.ISO8859-2
+NLS+= sv_SE.ISO8859-1
+NLS+= uk_UA.UTF-8
diff --git a/lib/libc/nls/Symbol.map b/lib/libc/nls/Symbol.map
new file mode 100644
index 0000000..818466e
--- /dev/null
+++ b/lib/libc/nls/Symbol.map
@@ -0,0 +1,9 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ catopen;
+ catgets;
+ catclose;
+};
diff --git a/lib/libc/nls/be_BY.UTF-8.msg b/lib/libc/nls/be_BY.UTF-8.msg
new file mode 100644
index 0000000..56bd038
--- /dev/null
+++ b/lib/libc/nls/be_BY.UTF-8.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for be_BY.UTF-8 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð½Ðµ дазволена
+$ ENOENT
+2 ÐÑма такога файлу ці каталогу
+$ ESRCH
+3 ÐÑма такога працÑÑу
+$ EINTR
+4 Перарваны ÑÑ–ÑÑ‚Ñмны выклік
+$ EIO
+5 Памылка ўводу/вываду
+$ ENXIO
+6 ПрыÑтаÑаванне не Ñканфігуравана
+$ E2BIG
+7 Ðадта доўгі ÑÐ¿Ñ–Ñ Ð°Ñ€Ð³ÑƒÐ¼ÐµÐ½Ñ‚Ð°Ñž
+$ ENOEXEC
+8 Памылка фармату файлу, Ñкі выконваецца
+$ EBADF
+9 ÐекарÑктны дÑÑкрыптар файлу
+$ ECHILD
+10 ÐÑма дачÑрніх працÑÑаў
+$ EDEADLK
+11 Прадухілена ÑžÐ·Ð°ÐµÐ¼Ð½Ð°Ñ Ð±Ð»Ð°ÐºÑ–Ñ€Ð¾ÑžÐºÐ° Ð¿Ð°Ð´Ñ‡Ð°Ñ Ð´Ð¾Ñтупу да Ñ€ÑÑурÑу
+$ ENOMEM
+12 Ðе даÑтае памÑці
+$ EACCES
+13 Ðе даÑтае прывілеÑÑž
+$ EFAULT
+14 ÐекарÑктны адраÑ
+$ ENOTBLK
+15 Ðеабходна блочнае прыÑтаÑаванне
+$ EBUSY
+16 ПрыÑтаÑаванне занÑтае
+$ EEXIST
+17 Файл Ñ–Ñнуе
+$ EXDEV
+18 СпаÑылка на іншае прыÑтаÑаванне
+$ ENODEV
+19 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð½Ðµ падтрымліваецца прыÑтаÑаваннем
+$ ENOTDIR
+20 Пазначаны файл не з'ÑўлÑецца каталогам
+$ EISDIR
+21 Пазначаны файл з'ÑўлÑецца каталогам
+$ EINVAL
+22 Ðедапушчальны аргумент
+$ ENFILE
+23 Ðадта шмат адчыненых файлаў у ÑÑ–ÑÑ‚Ñме
+$ EMFILE
+24 Ðадта шмат адчыненых файлаў
+$ ENOTTY
+25 Выклік ioctl не падтрымліваецца прыÑтаÑаваннем
+$ ETXTBSY
+26 ТекÑтавы файл занÑты
+$ EFBIG
+27 Ðадта вÑлікі файл
+$ ENOSPC
+28 Ðа прыÑтаÑаванні не заÑталоÑÑ Ð¼ÐµÑца
+$ ESPIPE
+29 Ðедапушчальнае пазіцыÑнаванне
+$ EROFS
+30 Ð¤Ð°Ð¹Ð»Ð°Ð²Ð°Ñ ÑÑ–ÑÑ‚Ñма толькі Ð´Ð»Ñ Ñ‡Ñ‹Ñ‚Ð°Ð½Ð½Ñ
+$ EMLINK
+31 Ðадта шмат ÑпаÑылак
+$ EPIPE
+32 Канал пашкоджаны
+$ EDOM
+33 Ðедапушчальнае значÑнне лічбавага аргументу
+$ ERANGE
+34 Ðадта вÑлікі Ñ€Ñзультат
+$ EAGAIN, EWOULDBLOCK
+35 РÑÑÑƒÑ€Ñ Ñ‡Ð°Ñова недаÑтупны
+$ EINPROGRESS
+36 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ñž працÑÑе выкананнÑ
+$ EALREADY
+37 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ ÑžÐ¶Ð¾ выконваецца
+$ ENOTSOCK
+38 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð· Ñокетам прыменена не да Ñокету
+$ EDESTADDRREQ
+39 Патрабуецца Ð°Ð´Ñ€Ð°Ñ Ð¿Ñ€Ñ‹Ð·Ð½Ð°Ñ‡ÑннÑ
+$ EMSGSIZE
+40 Ðадта доўгае паведамленне
+$ EPROTOTYPE
+41 ÐÑправільны тып пратаколу Ð´Ð»Ñ Ñокету
+$ ENOPROTOOPT
+42 Пратакол недаÑтупны
+$ EPROTONOSUPPORT
+43 Пратакол не падтрымліваецца
+$ ESOCKTNOSUPPORT
+44 Тып Ñокету не падтрымліваецца
+$ EOPNOTSUPP
+45 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð½Ðµ падтрымліваецца
+$ EPFNOSUPPORT
+46 СÑмейÑтва пратаколаў не падтрымліваецца
+$ EAFNOSUPPORT
+47 СÑмейÑтва адраÑоў не падтрымліваецца ÑÑмейÑтвам пратаколаў
+$ EADDRINUSE
+48 ÐÐ´Ñ€Ð°Ñ ÑžÐ¶Ð¾ выкарыÑтоўваецца
+$ EADDRNOTAVAIL
+49 Ðе магчыма прызначыць дадзены адраÑ
+$ ENETDOWN
+50 Сетка не працуе
+$ ENETUNREACH
+51 Сетка недаÑÑжна
+$ ENETRESET
+52 ЗлучÑнне прыпынена Ñеткай
+$ ECONNABORTED
+53 Праграма выклікала аварыйнае завÑршÑнне злучÑннÑ
+$ ECONNRESET
+54 ЗлучÑнне завÑршана Ñупрацьлеглым бокам
+$ ENOBUFS
+55 Ðе заÑталоÑÑ Ð¼ÐµÑца пад буфер
+$ EISCONN
+56 Сокет ужо падлучаны
+$ ENOTCONN
+57 Сокет не падлучаны
+$ ESHUTDOWN
+58 Ðе магчыма даÑылаць паÑÐ»Ñ Ð·Ð°ÐºÑ€Ñ‹Ñ†Ñ†Ñ Ñокету
+$ ETOOMANYREFS
+59 Ðадта шмат ÑпаÑылак: не магчыма злучыць
+$ ETIMEDOUT
+60 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð¿ÐµÑ€Ð°Ð²Ñ‹Ñіла чаÑавы ліміт
+$ ECONNREFUSED
+61 У злучÑнні адмоўлена
+$ ELOOP
+62 Ðадта шмат узроўнÑÑž Ñімвальных ÑпаÑылак
+$ ENAMETOOLONG
+63 Ðадта доўгае Ñ–Ð¼Ñ Ñ„Ð°Ð¹Ð»Ñƒ
+$ EHOSTDOWN
+64 ХоÑÑ‚ не працуе
+$ EHOSTUNREACH
+65 ÐÑма маршруту да хоÑту
+$ ENOTEMPTY
+66 Каталог не пуÑты
+$ EPROCLIM
+67 Ðадта шмат працÑÑаў
+$ EUSERS
+68 Ðадта шмат карыÑтальнікаў
+$ EDQUOT
+69 Перавышана дыÑÐºÐ°Ð²Ð°Ñ ÐºÐ²Ð¾Ñ‚Ð°
+$ ESTALE
+70 СаÑтарÑлы дÑÑкрыптар файлу NFS
+$ EREMOTE
+71 Ðадта шмат дыÑтанцыйных пераходаў на шлÑху
+$ EBADRPC
+72 ÐекарÑÐºÑ‚Ð½Ð°Ñ Ñтруктура RPC
+$ ERPCMISMATCH
+73 ÐÑÐ¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ RPC
+$ EPROGUNAVAIL
+74 Праграма RPC недаÑÑжнаÑ
+$ EPROGMISMATCH
+75 ÐÑÐ¿Ñ€Ð°Ð²Ñ–Ð»ÑŒÐ½Ð°Ñ Ð²ÐµÑ€ÑÑ–Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ñ‹
+$ EPROCUNAVAIL
+76 ÐекарÑÐºÑ‚Ð½Ð°Ñ Ð¿Ñ€Ð°Ñ†Ñдура Ð´Ð»Ñ Ð¿Ñ€Ð°Ð³Ñ€Ð°Ð¼Ñ‹
+$ ENOLCK
+77 Блакіроўкі недаÑтупны
+$ ENOSYS
+78 Ð¤ÑƒÐ½ÐºÑ†Ñ‹Ñ Ð½Ðµ Ñ€Ñалізавана
+$ EFTYPE
+79 ÐепадыходзÑчы тып ці фармат файлу
+$ EAUTH
+80 Памылка аўтÑнтыфікацыі
+$ ENEEDAUTH
+81 Ðеабходна аўтÑнтыфікацыÑ
+$ EIDRM
+82 ІдÑнтыфікатар выдалены
+$ ENOMSG
+83 ÐÑма Ð¿Ð°Ð²ÐµÐ´Ð°Ð¼Ð»ÐµÐ½Ð½Ñ Ð¿Ð°Ñ‚Ñ€Ñбнага тыпу
+$ EOVERFLOW
+84 Ðадта вÑлікае значÑнне Ð´Ð»Ñ Ð·Ð°Ñ…Ð¾ÑžÐ²Ð°Ð½Ð½Ñ Ñž пазначаным тыпе дадзеных
+$ ECANCELED
+85 ÐÐ¿ÐµÑ€Ð°Ñ†Ñ‹Ñ Ð°Ð´Ð¼ÐµÐ½ÐµÐ½Ð°
+$ EILSEQ
+86 ÐÐµÐ´Ð°Ð·Ð²Ð¾Ð»ÐµÐ½Ð°Ñ Ð¿Ð°ÑлÑдоўнаÑць байтаў
+$ ENOATTR
+87 Ðтрыбут не знойдзены
+$ EDOOFUS
+88 Памылка праграмаваннÑ
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Разрыў ÑувÑзі
+$ SIGINT
+2 Перарванне па Ñігналу
+$ SIGQUIT
+3 Выхад
+$ SIGILL
+4 ÐÐµÐ´Ð°Ð¿ÑƒÑˆÑ‡Ð°Ð»ÑŒÐ½Ð°Ñ Ñ–Ð½ÑтрукцыÑ
+$ SIGTRAP
+5 ПаÑтка траÑіроўкі/кропкі ÑпыненнÑ
+$ SIGABRT
+6 ПаÑтка аварыйнага завÑршÑннÑ
+$ SIGEMT
+7 ПаÑтка EMT
+$ SIGFPE
+8 Памылка Ð¿Ð°Ð´Ñ‡Ð°Ñ Ð¿Ñ€Ð°Ñ†Ñ‹ з Ñ€Ñчыўным лікам
+$ SIGKILL
+9 ПрымуÑова Ñпынены
+$ SIGBUS
+10 Памылка шыны
+$ SIGSEGV
+11 Памылка Ñегментацыі
+$ SIGSYS
+12 Ðедапушчальны ÑÑ–ÑÑ‚Ñмны выклік
+$ SIGPIPE
+13 Канал пашкоджаны
+$ SIGALRM
+14 Спрацаваў таймер
+$ SIGTERM
+15 Завершаны
+$ SIGURG
+16 Ðеабходны Ñ‚Ñрміновы ўвод-вывад
+$ SIGSTOP
+17 Прыпыненне (Ñігнал)
+$ SIGTSTP
+18 Прыпыненне
+$ SIGCONT
+19 ПрацÑг працы
+$ SIGCHLD
+20 Завершана праца дачÑрнÑга працÑÑу
+$ SIGTTIN
+21 Спынены (увод з Ñ‚Ñрміналу)
+$ SIGTTOU
+22 Спынены (увод на Ñ‚Ñрмінал)
+$ SIGIO
+23 Увод-вывад магчымы
+$ SIGXCPU
+24 Перавышана абмежаванне працÑÑарнага чаÑу
+$ SIGXFSZ
+25 Перавышаны макÑімальны памер файлу
+$ SIGVTALRM
+26 Вычарпаны віртуальны таймер
+$ SIGPROF
+27 Вычарпаны таймер прафілÑваннÑ
+$ SIGWINCH
+28 Змена памеру вакна
+$ SIGINFO
+29 Запыт інфармацыі
+$ SIGUSR1
+30 Сігнал карыÑтальніка 1
+$ SIGUSR2
+31 Сігнал карыÑтальніка 2
diff --git a/lib/libc/nls/ca_ES.ISO8859-1.msg b/lib/libc/nls/ca_ES.ISO8859-1.msg
new file mode 100644
index 0000000..e786c29
--- /dev/null
+++ b/lib/libc/nls/ca_ES.ISO8859-1.msg
@@ -0,0 +1,267 @@
+$ $FreeBSD$
+$
+$ Message catalog for ca_ES.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operació no permesa
+$ ENOENT
+2 Arxiu o directori inexistent
+$ ESRCH
+3 Procés inexistent
+$ EINTR
+4 Crida del sistema interrompuda
+$ EIO
+5 Error d'entrada/sortida
+$ ENXIO
+6 Dispositiu no configurat
+$ E2BIG
+7 Llista de paràmetres massa llarga
+$ ENOEXEC
+8 Error en el format de l'executable
+$ EBADF
+9 Descriptor d'arxiu incorrecte
+$ ECHILD
+10 No hi ha processos fills
+$ EDEADLK
+11 S'ha evitat el bloqueig del recurs
+$ ENOMEM
+12 No es pot assignar la memòria demanada
+$ EACCES
+13 Permís denegat
+$ EFAULT
+14 Adreça incorrecta
+$ ENOTBLK
+15 Es necessita un dispositiu de blocs
+$ EBUSY
+16 Dispositiu ocupat
+$ EEXIST
+17 L'arxiu ja existeix
+$ EXDEV
+18 Enllaç entre dispositius
+$ ENODEV
+19 Operació no suportada pel dispositiu
+$ ENOTDIR
+20 No és un directori
+$ EISDIR
+21 És un directori
+$ EINVAL
+22 Paràmetre incorrecte
+$ ENFILE
+23 Hi ha massa arxius oberts al sistema
+$ EMFILE
+24 Hi ha massa arxius oberts
+$ ENOTTY
+25 L'ioctl no és adecuat per al dispositiu
+$ ETXTBSY
+26 Arxiu de text ocupat
+$ EFBIG
+27 Arxiu massa gran
+$ ENOSPC
+28 No queda espai lliure en el dispositiu
+$ ESPIPE
+29 Cerca il·legal
+$ EROFS
+30 Sistema d'arxius de només lectura
+$ EMLINK
+31 Massa enllaços
+$ EPIPE
+32 Canal (pipe) trencat
+$ EDOM
+33 El resultat surt fora de rang
+$ ERANGE
+34 Resultat massa gran
+$ EAGAIN, EWOULDBLOCK
+35 El recurs no està disponible temporalment
+$ EINPROGRESS
+36 L'operació es troba en progrés actualment
+$ EALREADY
+37 L'operació ja es troba en progrés
+$ ENOTSOCK
+38 Operació de tipus socket en quelcom que no ho és
+$ EDESTADDRREQ
+39 Es requereix l'adreça de destí
+$ EMSGSIZE
+40 Missatge massa llarg
+$ EPROTOTYPE
+41 Tipus de protocol incorrecte per al socket
+$ ENOPROTOOPT
+42 Protocol no disponible
+$ EPROTONOSUPPORT
+43 Protocol no suportat
+$ ESOCKTNOSUPPORT
+44 Tipus de socket no suportat
+$ EOPNOTSUPP
+45 Operació no suportada
+$ EPFNOSUPPORT
+46 Família de protocols no suportada
+$ EAFNOSUPPORT
+47 Família d'adreces no suportada per la família de protocols
+$ EADDRINUSE
+48 L'adreça ja es troba en ús
+$ EADDRNOTAVAIL
+49 No es pot assignar l'adreça demanada
+$ ENETDOWN
+50 La xarxa no es troba disponible
+$ ENETUNREACH
+51 No es pot accedir a la xarxa
+$ ENETRESET
+52 La connexió a la xarxa s'ha perdut durant la reinicialització
+$ ECONNABORTED
+53 El programari ha causat l'avort de la connexió
+$ ECONNRESET
+54 L'interlocutor ha reinicialitzat la comunicació
+$ ENOBUFS
+55 No hi ha prou espai per a la memoria intermèdia (buffer)
+$ EISCONN
+56 El socket ja es troba connectat
+$ ENOTCONN
+57 El socket no es troba connectat
+$ ESHUTDOWN
+58 No es pot enviar desprès de la desconnexió del socket
+$ ETOOMANYREFS
+59 Hi ha massa referències: no es poden unir
+$ ETIMEDOUT
+60 El temps de connexió s'ha esgotat
+$ ECONNREFUSED
+61 Connexió rebutjada
+$ ELOOP
+62 Hi ha massa nivells d'enllaços simbòlics
+$ ENAMETOOLONG
+63 Nom d'arxiu massa llarg
+$ EHOSTDOWN
+64 La màquina no es troba disponible
+$ EHOSTUNREACH
+65 No hi ha cap camí fins a la màquina
+$ ENOTEMPTY
+66 El directori no està buit
+$ EPROCLIM
+67 Hi ha massa processos
+$ EUSERS
+68 Hi ha massa usuaris
+$ EDQUOT
+69 Quota de disc sobrepassada
+$ ESTALE
+70 Descriptor d'arxiu NFS incorrecte
+$ EREMOTE
+71 Massa nivells en el camí de destí
+$ EBADRPC
+72 L'estructura RPC es incorrecta
+$ ERPCMISMATCH
+73 La versió del RPC es incorrecta
+$ EPROGUNAVAIL
+74 El programa RPC no es troba disponible
+$ EPROGMISMATCH
+75 Versió incorrecta del programa
+$ EPROCUNAVAIL
+76 Procediment erroni per al programa
+$ ENOLCK
+77 No hi ha bloquejos disponibles
+$ ENOSYS
+78 Funció no implementada
+$ EFTYPE
+79 Tipus d'arxiu o de format inadequat
+$ EAUTH
+80 Error d'autenticació
+$ ENEEDAUTH
+81 Es necessita un autenticador
+$ EIDRM
+82 Identificador eliminat
+$ ENOMSG
+83 No hi ha missatges del tipus desitjat
+$ EOVERFLOW
+84 Valor massa gran per a ésser emmagatzemat en el tipus de dades
+$ EILSEQ
+85 Seqüència de bytes il·legal
+$ ENOTSUP
+86 No suportat
+$ ECANCELED
+87 Operació cancel·lada
+$ EBADMSG
+88 Missatje incorrecte o corrupte
+$ ENODATA
+89 No hi ha missatges disponibles
+$ ENOSR
+90 No hi ha recursos de tipus STREAM
+$ ENOSTR
+91 No és un STREAM
+$ ETIME
+92 Temps d'espera esgotat en el ioctl STREAM
+$ ENOATTR
+93 Atribut inexistent
+$ EMULTIHOP
+94 S'ha intentat un multisalt
+$ ENOLINK
+95 L'enllaç s'ha servit
+$ EPROTO
+96 Error de protocol
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Fí de línia (hangup)
+$ SIGINT
+2 Interrupció
+$ SIGQUIT
+3 Finalització
+$ SIGILL
+4 Instrucció il·legal
+$ SIGTRAP
+5 Depuració (Trace/BPT)
+$ SIGABRT
+6 Crida d'avort
+$ SIGEMT
+7 Captura d'EMT
+$ SIGFPE
+8 Excepció de coma flotant
+$ SIGKILL
+9 Matat
+$ SIGBUS
+10 Error del bus
+$ SIGSEGV
+11 Error de segmentació
+$ SIGSYS
+12 Crida al sistema incorrecta
+$ SIGPIPE
+13 Canal (pipe) trencat
+$ SIGALRM
+14 Alarma de rellotge
+$ SIGTERM
+15 Finalitzat
+$ SIGURG
+16 Condició urgent d'E/S
+$ SIGSTOP
+17 Parat (per senyal)
+$ SIGTSTP
+18 Parat
+$ SIGCONT
+19 Continuant
+$ SIGCHLD
+20 El fill ha acabat
+$ SIGTTIN
+21 Parat (entrada de tty)
+$ SIGTTOU
+22 Parat (sortida de tty)
+$ SIGIO
+23 I/O permesa
+$ SIGXCPU
+24 S'ha sobrepassat el límit de temps de la CPU
+$ SIGXFSZ
+25 S'ha sobrepassat el límit de la longitud de l'arxiu
+$ SIGVTALRM
+26 El temporitzador virtual ha expirat
+$ SIGPROF
+27 El temporitzador del perfilador ha expirat
+$ SIGWINCH
+28 Canvis en la mida de la finestra
+$ SIGINFO
+29 Demanda d'informació
+$ SIGUSR1
+30 Senyal 1 definida per l'usuari
+$ SIGUSR2
+31 Senyal 2 definida per l'usuari
+$ SIGPWR
+32 Fallada/reinicialització de l'alimentació
diff --git a/lib/libc/nls/catclose.3 b/lib/libc/nls/catclose.3
new file mode 100644
index 0000000..ed0f639
--- /dev/null
+++ b/lib/libc/nls/catclose.3
@@ -0,0 +1,64 @@
+.\" Copyright (c) 1994 Winning Strategies, Inc.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Winning Strategies, Inc.
+.\" 4. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.Dd February 12, 2005
+.Dt CATCLOSE 3
+.Os
+.Sh NAME
+.Nm catclose
+.Nd close message catalog
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In nl_types.h
+.Ft int
+.Fn catclose "nl_catd catd"
+.Sh DESCRIPTION
+The
+.Fn catclose
+function closes the message catalog specified by the argument
+.Fa catd .
+.Sh RETURN VALUES
+.Rv -std catclose
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBADF
+An invalid message catalog descriptor was passed by the
+.Fa catd
+argument.
+.El
+.Sh SEE ALSO
+.Xr gencat 1 ,
+.Xr catgets 3 ,
+.Xr catopen 3
+.Sh STANDARDS
+The
+.Fn catclose
+function conforms to
+.St -p1003.1-2001 .
diff --git a/lib/libc/nls/catgets.3 b/lib/libc/nls/catgets.3
new file mode 100644
index 0000000..38e92ba
--- /dev/null
+++ b/lib/libc/nls/catgets.3
@@ -0,0 +1,82 @@
+.\" Copyright (c) 1994 Winning Strategies, Inc.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Winning Strategies, Inc.
+.\" 4. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.Dd February 12, 2005
+.Dt CATGETS 3
+.Os
+.Sh NAME
+.Nm catgets
+.Nd retrieve string from message catalog
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In nl_types.h
+.Ft char *
+.Fn catgets "nl_catd catd" "int set_id" "int msg_id" "const char *s"
+.Sh DESCRIPTION
+The
+.Fn catgets
+function attempts to retrieve message
+.Fa msg_id
+of set
+.Fa set_id
+from the message catalog referenced by the descriptor
+.Fa catd .
+The argument
+.Fa s
+points to a default message which is returned if the function
+is unable to retrieve the specified message.
+.Sh RETURN VALUES
+If the specified message was retrieved successfully,
+.Fn catgets
+returns a pointer to an internal buffer containing the message string;
+otherwise it returns
+.Fa s .
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa catd
+argument is not a valid message catalog descriptor.
+.It Bq Er EBADMSG
+The message identified by
+.Fa set_id
+and
+.Fa msg_id
+is not in the message catalog.
+.El
+.Sh SEE ALSO
+.Xr gencat 1 ,
+.Xr catclose 3 ,
+.Xr catopen 3
+.Sh STANDARDS
+The
+.Fn catgets
+function conforms to
+.St -p1003.1-2001 .
diff --git a/lib/libc/nls/catopen.3 b/lib/libc/nls/catopen.3
new file mode 100644
index 0000000..7a16ee5
--- /dev/null
+++ b/lib/libc/nls/catopen.3
@@ -0,0 +1,157 @@
+.\" Copyright (c) 1994 Winning Strategies, Inc.
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Winning Strategies, Inc.
+.\" 4. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.Dd February 12, 2005
+.Dt CATOPEN 3
+.Os
+.Sh NAME
+.Nm catopen
+.Nd open message catalog
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In nl_types.h
+.Ft nl_catd
+.Fn catopen "const char *name" "int oflag"
+.Sh DESCRIPTION
+The
+.Fn catopen
+function opens the message catalog specified by
+.Fa name
+and returns a message catalog descriptor.
+If
+.Fa name
+contains a
+.Sq /
+then
+.Fa name
+specifies the full pathname for the message catalog, otherwise the value
+of the environment variable
+.Ev NLSPATH
+is used with
+the following substitutions:
+.Bl -tag -width XXX
+.It \&%N
+The value of the
+.Fa name
+argument.
+.It \&%L
+The value of the
+.Ev LANG
+environment variable or the
+.Dv LC_MESSAGES
+category (see below).
+.It \&%l
+The language element from the
+.Ev LANG
+environment variable or from the
+.Dv LC_MESSAGES
+category.
+.It \&%t
+The territory element from the
+.Ev LANG
+environment variable or from the
+.Dv LC_MESSAGES
+category.
+.It \&%c
+The codeset element from the
+.Ev LANG
+environment variable or from the
+.Dv LC_MESSAGES
+category.
+.It \&%%
+A single % character.
+.El
+.Pp
+An empty string is substituted for undefined values.
+.Pp
+Path names templates defined in
+.Ev NLSPATH
+are separated by colons
+.No ( Sq \&: ) .
+A leading or two adjacent colons
+is equivalent to specifying %N.
+.Pp
+If the
+.Fa oflag
+argument is set to the
+.Dv NL_CAT_LOCALE
+constant,
+.Dv LC_MESSAGES
+locale category used to open the message catalog; using
+.Dv NL_CAT_LOCALE
+conforms to the
+.St -xpg4
+standard.
+You can specify 0 for compatibility with
+.St -xpg3 ;
+when
+.Fa oflag
+is set to 0, the
+.Ev LANG
+environment variable
+determines the message catalog locale.
+.Pp
+A message catalog descriptor
+remains valid in a process until that process closes it, or
+until a successful call to one of the
+.Xr exec 3
+function.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn catopen
+returns a message catalog descriptor.
+Otherwise, (nl_catd) -1 is returned and
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa name
+does not point to a valid message catalog, or catalog is corrupt.
+.It Bq Er ENAMETOOLONG
+An entire path to the message catalog exceeded 1024 characters.
+.It Bq Er ENOENT
+The named message catalog does not exists, or the
+.Fa name
+argument points to an empty string.
+.It Bq Er ENOMEM
+Insufficient memory is available.
+.El
+.Sh SEE ALSO
+.Xr gencat 1 ,
+.Xr catclose 3 ,
+.Xr catgets 3 ,
+.Xr setlocale 3
+.Sh STANDARDS
+The
+.Fn catopen
+function conforms to
+.St -p1003.1-2001 .
diff --git a/lib/libc/nls/de_DE.ISO8859-1.msg b/lib/libc/nls/de_DE.ISO8859-1.msg
new file mode 100644
index 0000000..1bb4a3b
--- /dev/null
+++ b/lib/libc/nls/de_DE.ISO8859-1.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for de_DE.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operation nicht erlaubt
+$ ENOENT
+2 Datei oder Verzeichnis nicht gefunden
+$ ESRCH
+3 Prozess nicht gefunden
+$ EINTR
+4 Interrupt innerhalb eines Systemaufrufs
+$ EIO
+5 Ein-/Ausgabefehler
+$ ENXIO
+6 Gerät ist nicht konfiguriert
+$ E2BIG
+7 Argumentliste ist zu lang
+$ ENOEXEC
+8 Die Datei hat kein bekanntes ausführbares Format
+$ EBADF
+9 Ungültiger Dateideskriptor
+$ ECHILD
+10 Keine Kindprozesse
+$ EDEADLK
+11 Ein Deadlock wurde vermieden
+$ ENOMEM
+12 Kann nicht genug Speicher belegen
+$ EACCES
+13 Zugriff verweigert
+$ EFAULT
+14 Ungültige Adresse
+$ ENOTBLK
+15 Es wird ein Blockgerät benötigt
+$ EBUSY
+16 Das Gerät ist belegt
+$ EEXIST
+17 Datei existiert bereits
+$ EXDEV
+18 Link zwischen verschiedenen Geräten
+$ ENODEV
+19 Die Operation wird von diesem Gerät nicht unterstützt
+$ ENOTDIR
+20 Kein Verzeichnis
+$ EISDIR
+21 Ist ein Verzeichnis
+$ EINVAL
+22 Ungültiges Argument
+$ ENFILE
+23 Zu viele offene Dateien im System
+$ EMFILE
+24 Zu viele offene Dateien
+$ ENOTTY
+25 Ungültiger IOCTL für dieses Gerät
+$ ETXTBSY
+26 Datei wird benutzt
+$ EFBIG
+27 Datei zu groß
+$ ENOSPC
+28 Kein Platz mehr auf dem Gerät
+$ ESPIPE
+29 Ungültige Positionierung
+$ EROFS
+30 Dateisystem ist schreibgeschützt
+$ EMLINK
+31 Zu viele Links
+$ EPIPE
+32 Unterbrochene Pipe
+$ EDOM
+33 Numerisches Argument außerhalb des Wertebereichs
+$ ERANGE
+34 Ergebnis außerhalb des Wertebereichs
+$ EAGAIN, EWOULDBLOCK
+35 Ressource vorübergehend nicht verfügbar
+$ EINPROGRESS
+36 Operation wird gerade ausgeführt
+$ EALREADY
+37 Operation wird bereits ausgeführt
+$ ENOTSOCK
+38 Deskriptor ist kein Socket
+$ EDESTADDRREQ
+39 Zieladresse benötigt
+$ EMSGSIZE
+40 Nachricht zu lang
+$ EPROTOTYPE
+41 Ungültiger Protokolltyp für diesen Socket
+$ ENOPROTOOPT
+42 Protokoll nicht verfügbar
+$ EPROTONOSUPPORT
+43 Protokoll nicht unterstützt
+$ ESOCKTNOSUPPORT
+44 Sockettyp nicht unterstützt
+$ EOPNOTSUPP
+45 Operation nicht unterstützt
+$ EPFNOSUPPORT
+46 Protokollfamilie nicht unterstützt
+$ EAFNOSUPPORT
+47 Adressfamilie wird von der Protokollfamilie nicht unterstützt
+$ EADDRINUSE
+48 Adresse wird bereits benutzt
+$ EADDRNOTAVAIL
+49 Kann angeforderte Adresse nicht belegen
+$ ENETDOWN
+50 Netzwerk nicht verfügbar
+$ ENETUNREACH
+51 Netzwerk nicht erreichbar
+$ ENETRESET
+52 Netzwerk hat Verbindung mit Reset abgebrochen
+$ ECONNABORTED
+53 Software verursachte einen Verbindungsabbruch
+$ ECONNRESET
+54 Verbindung wurde von der Gegenstelle geschlossen
+$ ENOBUFS
+55 Keine Buffer verfügbar
+$ EISCONN
+56 Socket ist schon verbunden
+$ ENOTCONN
+57 Socket ist nicht verbunden
+$ ESHUTDOWN
+58 Kann nach einem Socket-Shutdown nicht mehr senden
+$ ETOOMANYREFS
+59 Zu viele Referenzen, kann nicht verbinden
+$ ETIMEDOUT
+60 Verbindungsabbruch durch Zeitüberschreitung
+$ ECONNREFUSED
+61 Verbindung wurde abgelehnt
+$ ELOOP
+62 Zu viele symbolische Links (zirkulär?)
+$ ENAMETOOLONG
+63 Dateiname zu lang
+$ EHOSTDOWN
+64 Host nicht verfügbar
+$ EHOSTUNREACH
+65 Keine Route zum Host
+$ ENOTEMPTY
+66 Verzeichnis ist nicht leer
+$ EPROCLIM
+67 Zu viele Prozesse
+$ EUSERS
+68 Zu viele Benutzer
+$ EDQUOT
+69 Platzlimit überschritten
+$ ESTALE
+70 Verwaister NFS-Dateideskriptor
+$ EREMOTE
+71 Zu viele Fernverweise in diesem Zugriff
+$ EBADRPC
+72 RPC-Struktur ist ungültig
+$ ERPCMISMATCH
+73 RPC-Version ist falsch
+$ EPROGUNAVAIL
+74 RPC-Programm nicht verfügbar
+$ EPROGMISMATCH
+75 Falsche Programmversion
+$ EPROCUNAVAIL
+76 Falsche Prozedur für dieses Programm
+$ ENOLCK
+77 Keine Dateisperren verfügbar
+$ ENOSYS
+78 Funktion nicht implementiert
+$ EFTYPE
+79 Ungültiger Dateityp oder Dateiformat
+$ EAUTH
+80 Authentifizierungsfehler
+$ ENEEDAUTH
+81 Authentikator benötigt
+$ EIDRM
+82 Identifizierung entfernt
+$ ENOMSG
+83 Keine Nachricht vom gewünschten Typ
+$ EOVERFLOW
+84 Wert zu groß, um in Datentyp zu speichern
+$ ECANCELED
+85 Operation abgebrochen
+$ EILSEQ
+86 Ungültige Byte-Sequenz
+$ ENOATTR
+87 Attribut nicht gefunden
+$ EDOOFUS
+88 Programmierfehler
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Verbindungsende
+$ SIGINT
+2 Unterbrechung
+$ SIGQUIT
+3 Programmende
+$ SIGILL
+4 Ungültiger Maschinenbefehl
+$ SIGTRAP
+5 Trace/BPT trap
+$ SIGABRT
+6 Abort trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Fließkommafehler
+$ SIGKILL
+9 Unbedingter Programmabbruch
+$ SIGBUS
+10 Bus-Zugriffsfehler
+$ SIGSEGV
+11 Illegaler Speicherzugriff
+$ SIGSYS
+12 Ungültiger Systemaufruf
+$ SIGPIPE
+13 Unterbrochene Pipe
+$ SIGALRM
+14 Wecker
+$ SIGTERM
+15 Beendet
+$ SIGURG
+16 Dringende Ein/Ausgabeanforderung
+$ SIGSTOP
+17 Gestoppt (Signal)
+$ SIGTSTP
+18 Gestoppt
+$ SIGCONT
+19 Fortgesetzt
+$ SIGCHLD
+20 Kindprozess beendet
+$ SIGTTIN
+21 Gestoppt (Eingabe)
+$ SIGTTOU
+22 Gestoppt (Ausgabe)
+$ SIGIO
+23 Ein/Ausgabe möglich
+$ SIGXCPU
+24 CPU-Zeitlimit überschritten
+$ SIGXFSZ
+25 Dateigrößenlimit überschritten
+$ SIGVTALRM
+26 Virtueller Wecker abgelaufen
+$ SIGPROF
+27 Profil-Wecker abgelaufen
+$ SIGWINCH
+28 Fenstergröße hat sich verändert
+$ SIGINFO
+29 Informationsanforderung
+$ SIGUSR1
+30 Benutzerdefiniertes Signal 1
+$ SIGUSR2
+31 Benutzerdefiniertes Signal 2
diff --git a/lib/libc/nls/el_GR.ISO8859-7.msg b/lib/libc/nls/el_GR.ISO8859-7.msg
new file mode 100644
index 0000000..ca84929
--- /dev/null
+++ b/lib/libc/nls/el_GR.ISO8859-7.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for C locale (template)
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Ìç åðéôñåðôÞ åíÝñãåéá
+$ ENOENT
+2 Äåí õðÜñ÷åé ôÝôïéï áñ÷åßï Þ êáôÜëïãïò
+$ ESRCH
+3 Ç äéåñãáóßá áõôÞ äåí õðÜñ÷åé
+$ EINTR
+4 Ç êëÞóç óõóôÞìáôïò äéáêüðçêå
+$ EIO
+5 ÓöÜëìá åéóüäïõ/åîüäïõ
+$ ENXIO
+6 Ç óõóêåõÞ äåí Ý÷åé ñõèìéóôåß
+$ E2BIG
+7 Ç ëßóôá ôùí ðáñáìÝôñùí åßíáé ðïëý ìåãÜëç
+$ ENOEXEC
+8 ËáíèáóìÝíç ìïñöÞ åêôåëÝóéìïõ
+$ EBADF
+9 Ðñïâëçìáôéêüò ðåñéãñáöÝáò áñ÷åßïõ
+$ ECHILD
+10 Äåí õðÜñ÷ïõí åîáñôþìåíåò äéåñãáóßåò
+$ EDEADLK
+11 Áðïöåý÷èçêå áäéÝîïäï ðüñïõ
+$ ENOMEM
+12 Áäõíáìßá åê÷þñçóçò ìíÞìçò
+$ EACCES
+13 ¶ñíçóç ðñüóâáóçò
+$ EFAULT
+14 ËÜèïò äéåýèõíóç
+$ ENOTBLK
+15 Áðáéôåßôáé óõóêåõÞ ôýðïõ block
+$ EBUSY
+16 ÓõóêåõÞ êáôåéëçììÝíç
+$ EEXIST
+17 Ôï áñ÷åßï õðÜñ÷åé
+$ EXDEV
+18 Óýíäåóìïò ìåôáîý óõóêåõþí
+$ ENODEV
+19 Ç ëåéôïõñãßá äåí õðïóôçñßæåôáé áðü ôç óõóêåõÞ
+$ ENOTDIR
+20 Äåí åßíáé êáôÜëïãïò
+$ EISDIR
+21 Åßíáé êáôÜëïãïò
+$ EINVAL
+22 Ìç Ýãêõñç ðáñÜìåôñïò
+$ ENFILE
+23 ÕðåñâïëéêÜ ðïëëÜ áíïéêôÜ áñ÷åßá óôï óýóôçìá
+$ EMFILE
+24 ÕðåñâïëéêÜ ðïëëÜ áíïéêôÜ áñ÷åßá
+$ ENOTTY
+25 ÁêáôÜëëçëï ioctl ãéá ôç óõóêåõÞ
+$ ETXTBSY
+26 Ôï áñ÷åßï êåéìÝíïõ åßíáé êáôåéëçììÝíï
+$ EFBIG
+27 Ðïëý ìåãÜëï áñ÷åßï
+$ ENOSPC
+28 Äåí Ý÷åé ìåßíåé åëåýèåñïò ÷þñïò óôç óõóêåõÞ
+$ ESPIPE
+29 ÁêáôÜëëçëç áíß÷íåõóç
+$ EROFS
+30 Ôï óýóôçìá áñ÷åßùí åßíáé ìüíï ãéá áíÜãíùóç
+$ EMLINK
+31 ÐÜñá ðïëëïß óýíäåóìïé
+$ EPIPE
+32 Äéáêïðåßóá óùëÞíùóç
+$ EDOM
+33 Ôï áñéèìçôéêü üñéóìá åßíáé åêôüò ïñßùí
+$ ERANGE
+34 Ðïëý ìåãÜëï áðïôÝëåóìá
+$ EAGAIN, EWOULDBLOCK
+35 Ï ðüñïò äåí åßíáé äéáèÝóéìïò ðñïóùñéíÜ
+$ EINPROGRESS
+36 Ç ëåéôïõñãßá âñßóêåôáé óå åîÝëéîç ôþñá
+$ EALREADY
+37 Ç ëåéôïõñãßá åßíáé Þäç óå åîÝëéîç
+$ ENOTSOCK
+38 Ëåéôïõñãßá õðïäï÷Þò óå ìç-õðïäï÷Þ
+$ EDESTADDRREQ
+39 Áðáéôåßôáé äéåýèõíóç ðñïïñéóìïý
+$ EMSGSIZE
+40 Ðïëý ìåãÜëï ìÞíõìá
+$ EPROTOTYPE
+41 ËÜèïò ôýðïõ ðñùôüêïëëï ãéá õðïäï÷Þ
+$ ENOPROTOOPT
+42 Ôï ðñùôüêïëëï äåí åßíáé äéáèÝóéìï
+$ EPROTONOSUPPORT
+43 Ôï ðñùôüêïëëï äåí õðïóôçñßæåôáé
+$ ESOCKTNOSUPPORT
+44 Ï ôýðïò ôçò õðïäï÷Þò äåí õðóôçñßæåôáé
+$ EOPNOTSUPP
+45 Ç ëåéôïõñãßá äåí õðïóôçñßæåôáé
+$ EPFNOSUPPORT
+46 Äåí õðïóôçñßæåôáé ç ïéêïãÝíåéá ðñùôïêüëëùí
+$ EAFNOSUPPORT
+47 Ç ïéêïãÝíåéá äéåõèýíóåùí äåí õðïóôçñßæåôáé áðü ôçí ïéêïãÝíåéá ðñùôïêüëëùí
+$ EADDRINUSE
+48 Ç äéåýèõíóç ÷ñçóéìïðïéåßôáé Þäç
+$ EADDRNOTAVAIL
+49 Äåí ìðïñåß íá ãßíåé áíÜèåóç ôçò æçôïýìåíçò äéåýèõíóçò
+$ ENETDOWN
+50 Ôï äßêôõï äåí ëåéôïõñãåß
+$ ENETUNREACH
+51 Äåí õðÜñ÷åé äéáäñïìÞ ðñïò ôï äßêôõï
+$ ENETRESET
+52 Ôï äßêôõï äéÝêïøå ôç óýíäåóç êáôÜ ôçí åðáíáöïñÜ
+$ ECONNABORTED
+53 Ôï ëïãéóìéêü ðñïêÜëåóå ôåñìáôéóìü ôçò óýíäåóçò
+$ ECONNRESET
+54 Ç óýíäåóç ôåñìáôßóôçêå áðü ôçí Üëëç ìåñéÜ
+$ ENOBUFS
+55 Äåí õðÜñ÷åé äéáèÝóéìïò ðñïóùñéíüò ÷þñïò
+$ EISCONN
+56 Ç õðïäï÷Þ Ý÷åé Þäç óõíäåèåß
+$ ENOTCONN
+57 Ç õðïäï÷Þ äåí Ý÷åé óõíäåèåß
+$ ESHUTDOWN
+58 Äåí åßíáé äõíáôÞ ç áðïóôïëÞ ìåôÜ ôïí ôåñìáôéóìü ôçò õðïäï÷Þò
+$ ETOOMANYREFS
+59 ÐÜñá ðïëëÝò áíáöïñÝò: äåí ìðïñåß íá ãßíåé óõíÝíùóç
+$ ETIMEDOUT
+60 ÔÝëïò ÷ñüíïõ äéáäéêáóßáò
+$ ECONNREFUSED
+61 ¶ñíçóç óýíäåóçò
+$ ELOOP
+62 ÐÜñá ðïëëÜ åðßðåäá óõìâïëéêþí óõíäÝóåùí
+$ ENAMETOOLONG
+63 Ðïëý ìåãÜëï üíïìá áñ÷åßïõ
+$ EHOSTDOWN
+64 Ôï óýóôçìá äåí åßíáé óå ëåéôïõñãßá
+$ EHOSTUNREACH
+65 Äåí õðÜñ÷åé äéáäñïìÞ ðñïò ôï óýóôçìá
+$ ENOTEMPTY
+66 Ï êáôÜëïãïò äåí åßíáé Üäåéïò
+$ EPROCLIM
+67 ÕðåñâïëéêÜ ðïëëÝò äéåñãáóßåò
+$ EUSERS
+68 ÕðåñâïëéêÜ ðïëëïß ÷ñÞóôåò
+$ EDQUOT
+69 ÕðÝñâáóç ïñßùí ÷ñÞóçò äßóêïõ
+$ ESTALE
+70 ¶êõñï handle áñ÷åßïõ óôï NFS
+$ EREMOTE
+71 ÐÜñá ðïëëÜ áðïìáêñõóìÝíá åðßðåäá óôç äéáäñïìÞ
+$ EBADRPC
+72 Ç äïìÞ RPC åßíáé ðñïâëçìáôéêÞ
+$ ERPCMISMATCH
+73 ËáíèáóìÝíç Ýêäïóç RPC
+$ EPROGUNAVAIL
+74 Ôï ðñüãñáììá RPC äåí åßíáé äéáèÝóéìï
+$ EPROGMISMATCH
+75 ËáíèáóìÝíç Ýêäïóç ðñïãñÜììáôïò
+$ EPROCUNAVAIL
+76 ÐñïâëçìáôéêÞ äéáäéêáóßá ãéá ôï ðñüãñáììá
+$ ENOLCK
+77 Äåí õðÜñ÷ïõí äéáèÝóéìá êëåéäþìáôá
+$ ENOSYS
+78 Ç ëåéôïõñãßá äåí Ý÷åé õëïðïéçèåß
+$ EFTYPE
+79 ËáíèáóìÝíïò ôýðïò Þ ìïñöÞ áñ÷åßïõ
+$ EAUTH
+80 ÓöÜëìá êáôÜ ôçí ðéóôïðïßçóç áõèåíôéêüôçôáò
+$ ENEEDAUTH
+81 Áðáéôåßôáé ðéóôïðïéçôÞò áõèåíôéêüôçôáò
+$ EIDRM
+82 Ôï áíáãíùñéóôéêü Ý÷åé áöáéñåèåß
+$ ENOMSG
+83 Äåí õðÜñ÷åé ìÞíõìá ôïõ êáèïñéóìÝíïõ ôýðïõ
+$ EOVERFLOW
+84 Ç ôéìÞ åßíáé ðïëý ìåãÜëç ãéá íá áðïèçêåõèåß óôïí ôýðï äåäïìÝíùí
+$ ECANCELED
+85 Ç ëåéôïõñãßá áêõñþèçêå
+$ EILSEQ
+86 Ìç-Ýãêõñç áêïëïõèßá bytes
+$ ENOATTR
+87 Ôï ÷áñáêôçñéóôéêü äåí âñÝèçêå
+$ EDOOFUS
+88 ÓöÜëìá ðñïãñáììáôéóìïý
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Êëåßóéìï
+$ SIGINT
+2 ÄéáêïðÞ
+$ SIGQUIT
+3 Ôåñìáôéóìüò
+$ SIGILL
+4 Ìç-Ýãêõñç åíôïëÞ
+$ SIGTRAP
+5 Ðáãßäá Trace/BPT
+$ SIGABRT
+6 Ðáãßäá áêýñùóçò
+$ SIGEMT
+7 Ðáãßäá EMT
+$ SIGFPE
+8 Åîáßñåóç êéíçôÞò õðïäéáóôïëÞò
+$ SIGKILL
+9 Ôåñìáôßóôçêå
+$ SIGBUS
+10 ÓöÜëìá äéáýëïõ
+$ SIGSEGV
+11 ÓöÜëìá Segmentation
+$ SIGSYS
+12 ÊáêÞ êëÞóç óõóôÞìáôïò
+$ SIGPIPE
+13 ÄéáêïðÞ pipe
+$ SIGALRM
+14 Ñïëüé åéäïðïßçóçò
+$ SIGTERM
+15 Ôåñìáôßóôçêå
+$ SIGURG
+16 ¸êôáêôç êáôÜóôáóç É/Ï
+$ SIGSTOP
+17 Óå áíáìïíÞ (óÞìá)
+$ SIGTSTP
+18 Óå áíáìïíÞ
+$ SIGCONT
+19 Óõíå÷ßæåôáé
+$ SIGCHLD
+20 ÔÝëïò åîáñôþìåíçò äéåñãáóßáò
+$ SIGTTIN
+21 ÄéáêïðÞ (åßóïäïò tty)
+$ SIGTTOU
+22 ÄéáêïðÞ (Ýîïäïò tty)
+$ SIGIO
+23 Äõíáôüôçôá I/O
+$ SIGXCPU
+24 ÎåðåñÜóôçêå ôï üñéï ÷ñÞóçò ôçò CPU
+$ SIGXFSZ
+25 ÎåðåñÜóôçêå ôï ìÝãéóôï ìÝãåèïò áñ÷åßïõ
+$ SIGVTALRM
+26 ÅîáíôëÞèçêå ï åéêïíéêüò ÷ñïíïìåôñçôÞò
+$ SIGPROF
+27 ÅîáíôëÞèçêå ï ÷ñïíïìåôñçôÞò profiling
+$ SIGWINCH
+28 Ôï ìÝãåèïò ôïõ ðáñáèýñïõ áëëÜæåé
+$ SIGINFO
+29 Áßôçóç ãéá ðëçñïöïñßá
+$ SIGUSR1
+30 ÓÞìá 1 êáèïñéóìÝíï áðü ôï ÷ñÞóôç
+$ SIGUSR2
+31 ÓÞìá 2 êáèïñéóìÝíï áðü ôï ÷ñÞóôç
diff --git a/lib/libc/nls/es_ES.ISO8859-1.msg b/lib/libc/nls/es_ES.ISO8859-1.msg
new file mode 100644
index 0000000..2687c17
--- /dev/null
+++ b/lib/libc/nls/es_ES.ISO8859-1.msg
@@ -0,0 +1,295 @@
+$ $FreeBSD$
+$
+$ Message catalog for es_ES.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operación no permitida
+$ ENOENT
+2 Fichero o directorio inexistente
+$ ESRCH
+3 Proceso inexistente
+$ EINTR
+4 Llamada del sistema interrumpida
+$ EIO
+5 Error de Entrada/Salida
+$ ENXIO
+6 Dispositivo no configurado
+$ E2BIG
+7 La lista de argumentos es demasiado larga
+$ ENOEXEC
+8 Error en el formato del ejecutable
+$ EBADF
+9 Descriptor incorrecto de fichero
+$ ECHILD
+10 No hay procesos hijo
+$ EDEADLK
+11 Se ha evitado el bloqueo del recurso
+$ ENOMEM
+12 No se pudo asignar memoria
+$ EACCES
+13 Permiso denegado
+$ EFAULT
+14 Dirección incorrecta
+$ ENOTBLK
+15 Se necesita un dispositivo de bloques
+$ EBUSY
+16 Dispositivo ocupado
+$ EEXIST
+17 El fichero ya existe
+$ EXDEV
+18 Enlace entre dispositivos
+$ ENODEV
+19 Operación inadecuada para este dispositivo
+$ ENOTDIR
+20 No es un directorio
+$ EISDIR
+21 Es un directorio
+$ EINVAL
+22 Argumento inadecuado
+$ ENFILE
+23 Hay demasiados ficheros abiertos en el sistema
+$ EMFILE
+24 Hay demasiados ficheros abiertos
+$ ENOTTY
+25 ioctl inapropiado para el dispositivo
+$ ETXTBSY
+26 Fichero de texto ocupado
+$ EFBIG
+27 Fichero demasiado grande
+$ ENOSPC
+28 No queda espacio libre en el dispositivo
+$ ESPIPE
+29 Búsqueda ilegal
+$ EROFS
+30 Sistema de ficheros de solo lectura
+$ EMLINK
+31 Demasiados enlaces
+$ EPIPE
+32 Canal (pipe) roto
+$ EDOM
+33 Argumento numérico fuera de rango
+$ ERANGE
+34 El resultado es demasiado grande
+$ EAGAIN, EWOULDBLOCK
+35 el recurso no está disponible temporalmente
+$ EINPROGRESS
+36 Operación en proceso
+$ EALREADY
+37 La operación ya se está ejecutando
+$ ENOTSOCK
+38 Operación de socket inaceptable para el dispositivo
+$ EDESTADDRREQ
+39 Se necesita una dirección de destino
+$ EMSGSIZE
+40 Mensaje demasiado largo
+$ EPROTOTYPE
+41 Tipo erróneo de protocolo para el socket
+$ ENOPROTOOPT
+42 Protocolo no disponible
+$ EPROTONOSUPPORT
+43 Protocolo no contemplado
+$ ESOCKTNOSUPPORT
+44 Tipo de socket no contemplado
+$ EOPNOTSUPP
+45 Operación no contemplada
+$ EPFNOSUPPORT
+46 Familia de protocolos no contemplada
+$ EAFNOSUPPORT
+47 Familia de direcciones no contemplada por la familia de protocolos
+$ EADDRINUSE
+48 La dirección ya está siendo usada
+$ EADDRNOTAVAIL
+49 No se pudo asignar la dirección requerida
+$ ENETDOWN
+50 La red no funciona
+$ ENETUNREACH
+51 No se ha podido acceder a la red
+$ ENETRESET
+52 La conexión de red se ha interrumpido al reinicializar
+$ ECONNABORTED
+53 Conexión perdida por problemas en el software
+$ ECONNRESET
+54 El interlocutor ha reinicializado la conexión
+$ ENOBUFS
+55 No queda espacio en el búfer
+$ EISCONN
+56 El socket ya estaba conectado
+$ ENOTCONN
+57 El socket no está conectado
+$ ESHUTDOWN
+58 No se puede enviar tras la desconexión del socket
+$ ETOOMANYREFS
+59 Demasiadas referencias: no se pueden unir
+$ ETIMEDOUT
+60 El tiempo de conexión ha expirado
+$ ECONNREFUSED
+61 Conexión rehusada
+$ ELOOP
+62 Demasiados niveles de enlaces simbólicos
+$ ENAMETOOLONG
+63 Nombre de fichero demasiado largo
+$ EHOSTDOWN
+64 La máquina está fuera de servicio
+$ EHOSTUNREACH
+65 No hay ruta hasta la máquina
+$ ENOTEMPTY
+66 Directorio no vacío
+$ EPROCLIM
+67 Demasiados procesos
+$ EUSERS
+68 Demasiados usuarios
+$ EDQUOT
+69 Cuota de disco sobrepasada
+$ ESTALE
+70 Descriptor de fichero NFS inválido
+$ EREMOTE
+71 Ruta con demasiados niveles
+$ EBADRPC
+72 La estructura de la RPC es errónea
+$ ERPCMISMATCH
+73 La versón de la RPC es errónea
+$ EPROGUNAVAIL
+74 La RPC no está accesible
+$ EPROGMISMATCH
+75 Versión errónea del programa
+$ EPROCUNAVAIL
+76 Procedimiento erróneo para el programa
+$ ENOLCK
+77 No hay bloqueos disponibles
+$ ENOSYS
+78 Función no realizada
+$ EFTYPE
+79 Tipo de fichero o formato inapropiado
+$ EAUTH
+80 Error de autentificación
+$ ENEEDAUTH
+81 Se necesita un autenticador
+$ EIDRM
+82 Identificador eliminado
+$ ENOMSG
+83 No hay mensajes del tipo deseado
+$ EOVERFLOW
+84 Valor demasiado grande para almacenarse en el tipo deseado
+$ ECANCELED
+85 Operación cancelada
+$ EILSEQ
+86 Secuencia de bytes ilegal
+$ ENOATTR
+87 Atributo no encontrado
+$ EDOOFUS
+88 Error de programación
+$ EBADMSG
+89 Mensaje inválido
+$ EMULTIHOP
+90 Intento de hop multiple
+$ ENOLINK
+91 El enlace se ha roto
+$ EPROTO
+92 Fallo de protocolo
+$ ENOTCAPABLE
+93 Habilidades insuficientes
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Fin de línea (Hangup)
+$ SIGINT
+2 Interrumpido
+$ SIGQUIT
+3 Terminado
+$ SIGILL
+4 Instrucción ilegal
+$ SIGTRAP
+5 Trace/BPT trap
+$ SIGABRT
+6 Abort trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Excepción de coma flotante
+$ SIGKILL
+9 Matado
+$ SIGBUS
+10 Error en el bus
+$ SIGSEGV
+11 Fallo de segmentación
+$ SIGSYS
+12 Llamada al sistema errónea
+$ SIGPIPE
+13 Canal (pipe) roto
+$ SIGALRM
+14 Alarma del reloj
+$ SIGTERM
+15 Terminado
+$ SIGURG
+16 Condición urgente de E/S
+$ SIGSTOP
+17 Detenido (señal)
+$ SIGTSTP
+18 Detenido
+$ SIGCONT
+19 Continuando
+$ SIGCHLD
+20 Proceso hijo terminado
+$ SIGTTIN
+21 Detenido (entrada tty)
+$ SIGTTOU
+22 Detenido (salida tty)
+$ SIGIO
+23 E/S posible
+$ SIGXCPU
+24 Se ha sobrepasado el tiempo límite de la CPU
+$ SIGXFSZ
+25 Se ha sobrepasado el límite de tamaño de fichero
+$ SIGVTALRM
+26 Temporizador virtual expirado
+$ SIGPROF
+27 Temporizador de perfilación expirado
+$ SIGWINCH
+28 Cambios en el tamaño de ventana
+$ SIGINFO
+29 Petición de información
+$ SIGUSR1
+30 Señal definida por el usuario n1
+$ SIGUSR2
+31 Señal definida por el usuario n2
+$
+$ gai_strerror() support catalog
+$
+$set 3
+$ 1 (obsoleto)
+1 Tipo de dirección no contemplado
+$ EAI_AGAIN
+2 Error transitorio en la resolución de nombres
+$ EAI_BADFLAGS
+3 Valor inválido de ai_flags
+$ EAI_FAIL
+4 Error no recuperable en la resolución de nombres
+$ EAI_FAMILY
+5 ai_family no contemplado
+$ EAI_MEMORY
+6 Error en la asignación de memoria
+$ 7 (obsoleto)
+7 No hay dirección asociada con el nombre de máquina
+$ EAI_NONAME
+8 No se dispone nombre de máquina, ni nombre de servicio
+$ EAI_SERVICE
+9 Nombre de servicio no contemplado en ai_socktype
+$ EAI_SOCKTYPE
+10 ai_socktype no contemplado
+$ EAI_SYSTEM
+11 Error de sistema devuelto en errno
+$ EAI_BADHINTS
+12 Valor inválido de hints
+$ EAI_PROTOCOL
+13 Protocolo resuelto desconocido
+$ EAI_OVERFLOW
+14 Búfer de argumentos sobrepasado
+$ 0
+32766 Éxito
+$ NL_MSGMAX
+32767 Error desconocido
diff --git a/lib/libc/nls/fi_FI.ISO8859-1.msg b/lib/libc/nls/fi_FI.ISO8859-1.msg
new file mode 100644
index 0000000..491f9a1
--- /dev/null
+++ b/lib/libc/nls/fi_FI.ISO8859-1.msg
@@ -0,0 +1,233 @@
+$ $FreeBSD$
+$
+$ Message catalog for fi_FI.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Toimintoa ei sallita
+$ ENOENT
+2 Tiedostoa tai hakemistoa ei löydy
+$ ESRCH
+3 Prosessia ei löydy
+$ EINTR
+4 Systeemikutsu keskeytyi
+$ EIO
+5 Syöttö/tulostusvirhe
+$ ENXIO
+6 Laitetta ei määritelty
+$ E2BIG
+7 Liikaa argumentteja
+$ ENOEXEC
+8 Tuntematon ohjelmatyyppi
+$ EBADF
+9 Virheellinen tiedosto-osoitin
+$ ECHILD
+10 Ei lapsiprosesseja
+$ EDEADLK
+11 Resurssin ristiinlukitus vältetty
+$ ENOMEM
+12 Muistinvaraus epäonnistui
+$ EACCES
+13 Lupa kielletty
+$ EFAULT
+14 Virheellinen osoite
+$ ENOTBLK
+15 Tarvitaan lohko-osoitettava laite
+$ EBUSY
+16 Laite käytössä
+$ EEXIST
+17 Tiedosto on jo olemassa
+$ EXDEV
+18 Laitteiden välinen linkki
+$ ENODEV
+19 Laite ei tue toimintoa
+$ ENOTDIR
+20 Kohde ei ole hakemisto
+$ EISDIR
+21 Kohde on hakemisto
+$ EINVAL
+22 Virheellinen argumentti
+$ ENFILE
+23 Järjestelmässä on liian monta avointa tiedostoa
+$ EMFILE
+24 Liian monta avointa tiedostoa
+$ ENOTTY
+25 Virheellinen ohjaustoiminto laitteelle
+$ ETXTBSY
+26 Tiedosto on käytössä
+$ EFBIG
+27 Tiedosto liian suuri
+$ ENOSPC
+28 Laitteella ei ole tilaa
+$ ESPIPE
+29 Virheellinen haku
+$ EROFS
+30 Vain luettava tiedostojärjestelmä
+$ EMLINK
+31 Liian monta linkkiä
+$ EPIPE
+32 Katkennut putki
+$ EDOM
+33 Numeerinen syöte virheellinen
+$ ERANGE
+34 Tulos liian suuri
+$ EAGAIN, EWOULDBLOCK
+35 Resurssi ei ole tilapäisesti saatavilla
+$ EINPROGRESS
+36 Toiminta on käynnissä
+$ EALREADY
+37 Toiminta oli jo käynnissä
+$ ENOTSOCK
+38 Socket-operaatio muulla kuin socketilla
+$ EDESTADDRREQ
+39 Tarvitaan kohdeosoite
+$ EMSGSIZE
+40 Sanoma liian pitkä
+$ EPROTOTYPE
+41 Väärä protokolla socketille
+$ ENOPROTOOPT
+42 Protokolla ei ole käytettävissä
+$ EPROTONOSUPPORT
+43 Protokollaa ei tueta
+$ ESOCKTNOSUPPORT
+44 Socket-tyyppiä ei tueta
+$ EOPNOTSUPP
+45 Toimintoa ei tueta
+$ EPFNOSUPPORT
+46 Protokollaperhettä ei tueta
+$ EAFNOSUPPORT
+47 Protokollaperhe ei tue osoiteperhettä
+$ EADDRINUSE
+48 Osoite on jo käytössä
+$ EADDRNOTAVAIL
+49 Ei pysty antamaan pyydettyä osoitetta
+$ ENETDOWN
+50 Verkko ei ole käytettävissä
+$ ENETUNREACH
+51 Verkkoon ei ole yhteyttä
+$ ENETRESET
+52 Verkko sulki yhteyden
+$ ECONNABORTED
+53 Ohjelmiston aiheuttama yhteyden keskeytyminen
+$ ECONNRESET
+54 Isäntä nollasi yhteyden
+$ ENOBUFS
+55 Puskuritila on lopussa
+$ EISCONN
+56 Yhteys on jo olemassa
+$ ENOTCONN
+57 Yhteyttä ei ole olemassa
+$ ESHUTDOWN
+58 Lähettäminen ei ole mahdollista yhteyden katkaisun jälkeen
+$ ETOOMANYREFS
+59 Liikaa viittauksia: ei voi yhdistää
+$ ETIMEDOUT
+60 Yhteyden aikavalvontakatkaisu
+$ ECONNREFUSED
+61 Yhteys hylätty
+$ ELOOP
+62 Liian monta peräkkäistä symbolista linkkiä
+$ ENAMETOOLONG
+63 Tiedoston nimi on liian pitkä
+$ EHOSTDOWN
+64 Isäntä ei vastaa
+$ EHOSTUNREACH
+65 Ei reittiä isäntään
+$ ENOTEMPTY
+66 Hakemisto ei ole tyhjä
+$ EPROCLIM
+67 Liian monta prosessia
+$ EUSERS
+68 Liian monta käyttäjää
+$ EDQUOT
+69 Levytilarajoitus ylittyi
+$ ESTALE
+70 Vanhentunut NFS-yhteys
+$ EREMOTE
+71 Liian monta verkkolevyä polussa
+$ EBADRPC
+72 Virheellinen RPC-pyyntö
+$ ERPCMISMATCH
+73 Väärä RPC-versio
+$ EPROGUNAVAIL
+74 RPC ei käytettävissä
+$ EPROGMISMATCH
+75 Väärä ohjelmaversio
+$ EPROCUNAVAIL
+76 Väärä RPC-pyyntö ohjelmalle
+$ ENOLCK
+77 Lukitus ei käytettävissä
+$ ENOSYS
+78 Toimintoa ei ole
+$ EFTYPE
+79 Väärä tiedostotyyppi tai -formaatti
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Katkaisu
+$ SIGINT
+2 Keskeytys
+$ SIGQUIT
+3 Lopetus
+$ SIGILL
+4 Laiton käsky
+$ SIGTRAP
+5 Jäljitys/BPT ansa
+$ SIGABRT
+6 Poistumisansa
+$ SIGEMT
+7 EMT-ansa
+$ SIGFPE
+8 Liukulukuvirhe
+$ SIGKILL
+9 Tapettu
+$ SIGBUS
+10 Väylävirhe
+$ SIGSEGV
+11 Suojausvirhe
+$ SIGSYS
+12 Virheellinen systeemikutsu
+$ SIGPIPE
+13 Katkennut putki
+$ SIGALRM
+14 Hälytyskello
+$ SIGTERM
+15 Lopetettu
+$ SIGURG
+16 Kiireellinen syöttö/tulostus
+$ SIGSTOP
+17 Pysäytetty (signaali)
+$ SIGTSTP
+18 Pysäytetty
+$ SIGCONT
+19 Jatkettu
+$ SIGCHLD
+20 Lapsiprosessi päättynyt
+$ SIGTTIN
+21 Pysäytetty (tty-syöte)
+$ SIGTTOU
+22 Pysäytetty (tty-tuloste)
+$ SIGIO
+23 Syöttö ja tulostus mahdollisia
+$ SIGXCPU
+24 Keskusyksikköaikarajoitus ylitetty
+$ SIGXFSZ
+25 Tiedoston kokorajoitus ylitetty
+$ SIGVTALRM
+26 Virtuaali-ajastin laukesi
+$ SIGPROF
+27 Profilointiajastin laukesi
+$ SIGWINCH
+28 Ikkunan koko muuttuu
+$ SIGINFO
+29 Informaatiopyyntö
+$ SIGUSR1
+30 Käyttäjän määriteltävä signaali 1
+$ SIGUSR2
+31 Käyttäjän määriteltävä signaali 2
+$ SIGPWR
+32 Virransaannin tilassa muutos
diff --git a/lib/libc/nls/fr_FR.ISO8859-1.msg b/lib/libc/nls/fr_FR.ISO8859-1.msg
new file mode 100644
index 0000000..35a8c4a
--- /dev/null
+++ b/lib/libc/nls/fr_FR.ISO8859-1.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for fr_FR.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Opération non autorisée
+$ ENOENT
+2 Fichier ou répertoire inexistant
+$ ESRCH
+3 Processus inconnu
+$ EINTR
+4 Appel système interrompu
+$ EIO
+5 Erreur d'entrée/sortie
+$ ENXIO
+6 Dispositif non configuré
+$ E2BIG
+7 Liste d'arguments trop longue
+$ ENOEXEC
+8 Format d'exécutable invalide
+$ EBADF
+9 Mauvais descripteur de fichier
+$ ECHILD
+10 Pas de processus fils
+$ EDEADLK
+11 Étreinte mortelle détectée
+$ ENOMEM
+12 Impossible d'allouer de la mémoire
+$ EACCES
+13 Permission refusée
+$ EFAULT
+14 Mauvaise adresse
+$ ENOTBLK
+15 Dispositif en mode bloc requis
+$ EBUSY
+16 Dispositif occupé
+$ EEXIST
+17 Le fichier existe
+$ EXDEV
+18 Lien inter-unités
+$ ENODEV
+19 Opération non supportée par le dispositif
+$ ENOTDIR
+20 Pas un répertoire
+$ EISDIR
+21 Est un répertoire
+$ EINVAL
+22 Argument invalide
+$ ENFILE
+23 Trop de fichiers ouverts sur le système
+$ EMFILE
+24 Trop de fichiers ouverts
+$ ENOTTY
+25 Fonction inadaptée au dispositif
+$ ETXTBSY
+26 Fichier en cours d'utilisation
+$ EFBIG
+27 Fichier trop grand
+$ ENOSPC
+28 Plus d'espace disponible
+$ ESPIPE
+29 Recherche illégale
+$ EROFS
+30 Système de fichier en lecture seulement
+$ EMLINK
+31 Trop de liens
+$ EPIPE
+32 Tube déconnecté
+$ EDOM
+33 Argument numérique hors définition
+$ ERANGE
+34 Résultat trop grand
+$ EAGAIN, EWOULDBLOCK
+35 Ressource indisponible temporairement
+$ EINPROGRESS
+36 Opération en cours
+$ EALREADY
+37 Opération déjà en cours
+$ ENOTSOCK
+38 Opération de type socket sur un descripteur de fichier
+$ EDESTADDRREQ
+39 Adresse de destination obligatoire
+$ EMSGSIZE
+40 Message trop long
+$ EPROTOTYPE
+41 Mauvais type de protocole pour la socket
+$ ENOPROTOOPT
+42 Protocole non disponible
+$ EPROTONOSUPPORT
+43 Protocole non supporté
+$ ESOCKTNOSUPPORT
+44 Type de socket non supporté
+$ EOPNOTSUPP
+45 Opération non supporté
+$ EPFNOSUPPORT
+46 Famille de protocole non supportée
+$ EAFNOSUPPORT
+47 Famille d'adresse non supportée par la famille de protocole
+$ EADDRINUSE
+48 Adresse en cours d'utilisation
+$ EADDRNOTAVAIL
+49 Impossible d'assigner l'adresse demandée
+$ ENETDOWN
+50 Plus de réseau
+$ ENETUNREACH
+51 Réseau inaccessible
+$ ENETRESET
+52 Connexion coupée par le réseau
+$ ECONNABORTED
+53 Connexion interrompue
+$ ECONNRESET
+54 Connexion interrompue par l'hôte distant
+$ ENOBUFS
+55 Tampon saturé
+$ EISCONN
+56 La socket est déjà connectée
+$ ENOTCONN
+57 La socket n'est pas connectée
+$ ESHUTDOWN
+58 Impossible d'envoyer après la coupure
+$ ETOOMANYREFS
+59 Trop de références : lien impossible
+$ ETIMEDOUT
+60 Dépassement du délai d'attente
+$ ECONNREFUSED
+61 Connexion refusée
+$ ELOOP
+62 Trop de niveaux de liens symboliques
+$ ENAMETOOLONG
+63 Nom de fichier trop long
+$ EHOSTDOWN
+64 Hôte distant arrêté
+$ EHOSTUNREACH
+65 Pas de route vers l'hôte distant
+$ ENOTEMPTY
+66 Répertoire non vide
+$ EPROCLIM
+67 Trop de processus
+$ EUSERS
+68 Trop d'utilisateurs
+$ EDQUOT
+69 Quota de disque dépassé
+$ ESTALE
+70 Identificateur de fichier NFS périmé
+$ EREMOTE
+71 Trop de niveaux extérieurs dans le path
+$ EBADRPC
+72 Mauvaise structure RPC
+$ ERPCMISMATCH
+73 Mauvaise version RPC
+$ EPROGUNAVAIL
+74 Prog. RPC indisponible
+$ EPROGMISMATCH
+75 Mauvaise version de programme
+$ EPROCUNAVAIL
+76 Mauvaise procédure pour le programme
+$ ENOLCK
+77 Plus de verrous disponibles
+$ ENOSYS
+78 Fonction non implémentée
+$ EFTYPE
+79 Type de fichier ou format inapproprié
+$ EAUTH
+80 Erreur d'authentification
+$ ENEEDAUTH
+81 Authentification requise
+$ EIDRM
+82 Identifiant retiré
+$ ENOMSG
+83 Aucun message du type souhaité
+$ EOVERFLOW
+84 Valeur trop grande pour le type de donnée
+$ ECANCELED
+85 Opération annulée
+$ EILSEQ
+86 Séquence d'octets illégale
+$ ENOATTR
+87 Attribut non trouvé
+$ EDOOFUS
+88 Erreur de programmation
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Fin de connexion
+$ SIGINT
+2 Interruption
+$ SIGQUIT
+3 Quitter
+$ SIGILL
+4 Instruction illégale
+$ SIGTRAP
+5 Trace/BPT trap
+$ SIGABRT
+6 Abort trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Exception sur virgule flottante
+$ SIGKILL
+9 Tué
+$ SIGBUS
+10 Bus error
+$ SIGSEGV
+11 Segmentation fault
+$ SIGSYS
+12 Bad system call
+$ SIGPIPE
+13 Broken pipe
+$ SIGALRM
+14 Alarm clock
+$ SIGTERM
+15 Terminé
+$ SIGURG
+16 Urgent I/O condition
+$ SIGSTOP
+17 Suspended (signal)
+$ SIGTSTP
+18 Suspended
+$ SIGCONT
+19 Continued
+$ SIGCHLD
+20 Child exited
+$ SIGTTIN
+21 Stopped (tty input)
+$ SIGTTOU
+22 Stopped (tty output)
+$ SIGIO
+23 I/O possible
+$ SIGXCPU
+24 Cputime limit exceeded
+$ SIGXFSZ
+25 Filesize limit exceeded
+$ SIGVTALRM
+26 Virtual timer expired
+$ SIGPROF
+27 Profiling timer expired
+$ SIGWINCH
+28 Window size changes
+$ SIGINFO
+29 Information request
+$ SIGUSR1
+30 User defined signal 1
+$ SIGUSR2
+31 User defined signal 2
diff --git a/lib/libc/nls/gl_ES.ISO8859-1.msg b/lib/libc/nls/gl_ES.ISO8859-1.msg
new file mode 100644
index 0000000..4255dc8
--- /dev/null
+++ b/lib/libc/nls/gl_ES.ISO8859-1.msg
@@ -0,0 +1,295 @@
+$ $FreeBSD$
+$
+$ Message catalog for gl_ES.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operación non permitida
+$ ENOENT
+2 Ficheiro ou directorio inexistente
+$ ESRCH
+3 Proceso inexistente
+$ EINTR
+4 Chamada do sistema interrompida
+$ EIO
+5 Erro de Entrada/Saída
+$ ENXIO
+6 Dispositivo non configurado
+$ E2BIG
+7 A lista de argumentos é demasiado larga
+$ ENOEXEC
+8 Erro no formato do executable
+$ EBADF
+9 Descriptor incorrecto de ficheiro
+$ ECHILD
+10 Non hai procesos fillos
+$ EDEADLK
+11 Evitouse o bloqueo do recurso
+$ ENOMEM
+12 Non se puido asignar memoria
+$ EACCES
+13 Permiso denegado
+$ EFAULT
+14 Dirección incorrecta
+$ ENOTBLK
+15 Precísase un dispositivo de bloques
+$ EBUSY
+16 Dispositivo ocupado
+$ EEXIST
+17 O ficheiro xa existe
+$ EXDEV
+18 Enlace entre dispositivos
+$ ENODEV
+19 Operación inadecuada para este dispositivo
+$ ENOTDIR
+20 Non é un directorio
+$ EISDIR
+21 É un directorio
+$ EINVAL
+22 Argumento inadecuado
+$ ENFILE
+23 Hai demasiados ficheiros abertos no sistema
+$ EMFILE
+24 Hai demasiados ficheiros abertos
+$ ENOTTY
+25 ioctl inapropiado para o dispositivo
+$ ETXTBSY
+26 Ficheiro de texto ocupado
+$ EFBIG
+27 Ficheiro demasiado grande
+$ ENOSPC
+28 Non queda espacio libre no dispositivo
+$ ESPIPE
+29 seek inválido
+$ EROFS
+30 Sistema de ficheiros de só lectura
+$ EMLINK
+31 Demasiados enlaces
+$ EPIPE
+32 Canal (pipe) roto
+$ EDOM
+33 Argumento numérico fóra de rango
+$ ERANGE
+34 O resultado é demasiado grande
+$ EAGAIN, EWOULDBLOCK
+35 O recurso non está dispoñible temporalmente
+$ EINPROGRESS
+36 Operación en proceso
+$ EALREADY
+37 A operación xa estase executando
+$ ENOTSOCK
+38 Operación de socket inaceptable para o dispositivo
+$ EDESTADDRREQ
+39 Precísase unha dirección de destino
+$ EMSGSIZE
+40 Mensaxe demasiado largo
+$ EPROTOTYPE
+41 Tipo malo de protocolo para o socket
+$ ENOPROTOOPT
+42 Protocolo non dispoñible
+$ EPROTONOSUPPORT
+43 Protocolo non contemplado
+$ ESOCKTNOSUPPORT
+44 Tipo de socket non contemplado
+$ EOPNOTSUPP
+45 Operación non contemplada
+$ EPFNOSUPPORT
+46 Familia de protocolos non contemplada
+$ EAFNOSUPPORT
+47 Familia de direcciones non contemplada pola familia de protocolos
+$ EADDRINUSE
+48 A dirección xa está en uso
+$ EADDRNOTAVAIL
+49 Non se puido asignar a dirección requerida
+$ ENETDOWN
+50 A rede non funciona
+$ ENETUNREACH
+51 Non se puido acceder á rede
+$ ENETRESET
+52 A conexión de rede interrompiuse ao reinicializar
+$ ECONNABORTED
+53 Conexión perdida por problemas no software
+$ ECONNRESET
+54 O interlocutor reinicializou a conexión
+$ ENOBUFS
+55 Non queda espacio no búfer
+$ EISCONN
+56 O socket xa estaba conectado
+$ ENOTCONN
+57 O socket non está conectado
+$ ESHUTDOWN
+58 Non se pode enviar tras a desconexión do socket
+$ ETOOMANYREFS
+59 Demasiadas referencias: non poden unirse
+$ ETIMEDOUT
+60 O tempo de conexión expirou
+$ ECONNREFUSED
+61 Conexión rexeitada
+$ ELOOP
+62 Demasiados niveles de enlaces simbólicos
+$ ENAMETOOLONG
+63 Nome de ficheiro demasiado largo
+$ EHOSTDOWN
+64 A máquina está fóra de servicio
+$ EHOSTUNREACH
+65 Non hai ruta ata a máquina
+$ ENOTEMPTY
+66 Directorio non baleiro
+$ EPROCLIM
+67 Demasiados procesos
+$ EUSERS
+68 Demasiados usuarios
+$ EDQUOT
+69 Cuota de disco sobrepasada
+$ ESTALE
+70 Descriptor de ficheiro NFS inválido
+$ EREMOTE
+71 Ruta con demasiados niveles
+$ EBADRPC
+72 A estructura da RPC é mala
+$ ERPCMISMATCH
+73 A versión da RPC é mala
+$ EPROGUNAVAIL
+74 A RPC non está accesible
+$ EPROGMISMATCH
+75 Versión mala do programa
+$ EPROCUNAVAIL
+76 Procedemento malo para o programa
+$ ENOLCK
+77 Non hai bloqueos dispoñibles
+$ ENOSYS
+78 Función non realizada
+$ EFTYPE
+79 Tipo de ficheiro ou formato inapropiado
+$ EAUTH
+80 Erro de autenticación
+$ ENEEDAUTH
+81 Precísase un autenticador
+$ EIDRM
+82 Identificador eliminado
+$ ENOMSG
+83 Non hai mensaxes do tipo desexado
+$ EOVERFLOW
+84 Valor demasiado grande para se almacenar no tipo desexado
+$ ECANCELED
+85 Operación cancelada
+$ EILSEQ
+86 Secuencia inválida de byte
+$ ENOATTR
+87 Atributo non encontrado
+$ EDOOFUS
+88 Erro de programación
+$ EBADMSG
+89 Mensaxe inválido
+$ EMULTIHOP
+90 Intento de Multihop
+$ ENOLINK
+91 Enlace fortaleceuse
+$ EPROTO
+92 Erro de protocolo
+$ ENOTCAPABLE
+93 Habilidades non suficientes
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Fin de liña (Hangup)
+$ SIGINT
+2 Interrompido
+$ SIGQUIT
+3 Terminado
+$ SIGILL
+4 Instrucción inválida
+$ SIGTRAP
+5 Trace/BPT trap
+$ SIGABRT
+6 Abort trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Excepción de coma flotante
+$ SIGKILL
+9 Matado
+$ SIGBUS
+10 Erro no bus
+$ SIGSEGV
+11 Fallo de segmentación
+$ SIGSYS
+12 Chamada ao sistema mala
+$ SIGPIPE
+13 Canal (pipe) roto
+$ SIGALRM
+14 Alarma do reloxo
+$ SIGTERM
+15 Terminado
+$ SIGURG
+16 Condición urxente de E/S
+$ SIGSTOP
+17 Detido (sinal)
+$ SIGTSTP
+18 Detido
+$ SIGCONT
+19 Continuando
+$ SIGCHLD
+20 Proceso fillo terminado
+$ SIGTTIN
+21 Detido (entrada tty)
+$ SIGTTOU
+22 Detido (sída tty)
+$ SIGIO
+23 E/S posible
+$ SIGXCPU
+24 Sobrepasouse o tempo límite da CPU
+$ SIGXFSZ
+25 Sobrepasouse o límite de tamaño de ficheiro
+$ SIGVTALRM
+26 Temporizador virtual caducado
+$ SIGPROF
+27 Temporizador de perfilación caducado
+$ SIGWINCH
+28 Cambios no tamaño de xanela
+$ SIGINFO
+29 Petición de información
+$ SIGUSR1
+30 Sinal definida polo usuario no. 1
+$ SIGUSR2
+31 Sinal definida polo usuario no. 2
+$
+$ gai_strerror() support catalog
+$
+$set 3
+$ 1 (obsoleto)
+1 Tipo de dirección non soportado
+$ EAI_AGAIN
+2 Erro temporal na resolución de nomes
+$ EAI_BADFLAGS
+3 Valor inválido de ai_flags
+$ EAI_FAIL
+4 Erro non recuperable na resolución de nomes
+$ EAI_FAMILY
+5 ai_family non soportado
+$ EAI_MEMORY
+6 Erro na asignación de memoria
+$ 7 (obsoleto)
+7 Non hai dirección asociada co nome de máquina
+$ EAI_NONAME
+8 Non se dispón nome de máquina, nin nome de servizo
+$ EAI_SERVICE
+9 Nome de servizo non soportado en ai_socktype
+$ EAI_SOCKTYPE
+10 ai_socktype non soportado
+$ EAI_SYSTEM
+11 Erro de sistema devolto en errno
+$ EAI_BADHINTS
+12 Valor inválido de hints
+$ EAI_PROTOCOL
+13 Protocolo resolto descoñecido
+$ EAI_OVERFLOW
+14 Búfer de argumentos excedido
+$ 0
+32766 Éxito
+$ NL_MSGMAX
+32767 Erro descoñecido
diff --git a/lib/libc/nls/hu_HU.ISO8859-2.msg b/lib/libc/nls/hu_HU.ISO8859-2.msg
new file mode 100644
index 0000000..330d486
--- /dev/null
+++ b/lib/libc/nls/hu_HU.ISO8859-2.msg
@@ -0,0 +1,295 @@
+$ $FreeBSD$
+$
+$ Message catalog for hu_HU.ISO8859-2 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Nem engedélyezett mûvelet
+$ ENOENT
+2 Fájl vagy könyvtár nem található
+$ ESRCH
+3 Processz nem található
+$ EINTR
+4 Megszakított rendszerhívás
+$ EIO
+5 B/K hiba
+$ ENXIO
+6 Konfigurálatlan eszköz
+$ E2BIG
+7 Túl hosszú argumentumlista
+$ ENOEXEC
+8 Hibás végrehajtható formátum
+$ EBADF
+9 Rossz fájlleíró
+$ ECHILD
+10 Nem létezõ gyermek processz
+$ EDEADLK
+11 Resource deadlock avoided
+$ ENOMEM
+12 Memória nem foglalható le
+$ EACCES
+13 Hozzáférés megtagadva
+$ EFAULT
+14 Rossz cím
+$ ENOTBLK
+15 Blokkos eszköz szükséges
+$ EBUSY
+16 Eszköz foglalt
+$ EEXIST
+17 Fájl létezik
+$ EXDEV
+18 Kereszthivatkozás eszközökön
+$ ENODEV
+19 A mûvelet nem támogatott az eszköz által
+$ ENOTDIR
+20 Nem könyvtár
+$ EISDIR
+21 Könyvtár
+$ EINVAL
+22 Érvénytelen argumentum
+$ ENFILE
+23 Túl sok megnyitott fájl a rendszerben
+$ EMFILE
+24 Túl sok megnyitott fájl
+$ ENOTTY
+25 Nem megfelelõ ioctl az eszközhöz
+$ ETXTBSY
+26 Szöveges fájl foglalt
+$ EFBIG
+27 Fájl túl nagy
+$ ENOSPC
+28 Nincs hely az eszközön
+$ ESPIPE
+29 Érvénytelen seek
+$ EROFS
+30 Csak olvasható fájlrendszer
+$ EMLINK
+31 Túl sok link
+$ EPIPE
+32 Hibás csõvezeték
+$ EDOM
+33 Numerikus argumentum nem esik a tartományba
+$ ERANGE
+34 Az esermény túl nagy
+$ EAGAIN, EWOULDBLOCK
+35 Az erõforrás ideiglenesen nem érhetõ el
+$ EINPROGRESS
+36 A mûvelet folyamatban van
+$ EALREADY
+37 A mûvelet már folyamatban van
+$ ENOTSOCK
+38 Socket mûvelet nem socketen
+$ EDESTADDRREQ
+39 Cél cím szükséges
+$ EMSGSIZE
+40 Túl hosszú üzenet
+$ EPROTOTYPE
+41 Rossz protokolltípus a sockethez
+$ ENOPROTOOPT
+42 Protokoll nem érhetõ el
+$ EPROTONOSUPPORT
+43 Protokoll nem támogatott
+$ ESOCKTNOSUPPORT
+44 Sockettípus nem támogatott
+$ EOPNOTSUPP
+45 Mûvelet nem támogatott
+$ EPFNOSUPPORT
+46 Protokollcsalád nem támogatott
+$ EAFNOSUPPORT
+47 A címcsalád nem támogatott a protokollcsalád által
+$ EADDRINUSE
+48 A cím már használatban van
+$ EADDRNOTAVAIL
+49 A kért cím nem osztható ki
+$ ENETDOWN
+50 A hálózat nem mûködik
+$ ENETUNREACH
+51 A hálózat nem érhetõ el
+$ ENETRESET
+52 A hálózat megszakította a kapcsolatot
+$ ECONNABORTED
+53 A szoftver megszakította a kapcsolatot
+$ ECONNRESET
+54 A kapcsolatot megszakította a peer
+$ ENOBUFS
+55 Nincs rendelkezésre álló pufferterület
+$ EISCONN
+56 A socket már kapcsolódva van
+$ ENOTCONN
+57 A socket nincs kapcsolódva
+$ ESHUTDOWN
+58 Nem küldhetõ el a socket lebontása után
+$ ETOOMANYREFS
+59 Túl sok hivatkozás: nem illeszthetõ össze
+$ ETIMEDOUT
+60 A mûvelet túllépte a rendelkezésre álló idõt
+$ ECONNREFUSED
+61 Kapcsolat elutasítva
+$ ELOOP
+62 Túl sok szint a szimbolikus linkekben
+$ ENAMETOOLONG
+63 Túl hosszú fájlnév
+$ EHOSTDOWN
+64 A kiszolgáló nem érhetõ el
+$ EHOSTUNREACH
+65 Nincs útvonal a kiszolgálóhoz
+$ ENOTEMPTY
+66 Könyvtár nem üres
+$ EPROCLIM
+67 Túl sok processz
+$ EUSERS
+68 Túl sok felhasználó
+$ EDQUOT
+69 A lemezkvóta túllépve
+$ ESTALE
+70 Elavult NFS fájlkezelõ
+$ EREMOTE
+71 Túl sok szint a távoli útvonalban
+$ EBADRPC
+72 Rossz RPC struktúra
+$ ERPCMISMATCH
+73 Rossz RPC verzió
+$ EPROGUNAVAIL
+74 RPC program nem érhetõ el
+$ EPROGMISMATCH
+75 Rossz programverzió
+$ EPROCUNAVAIL
+76 Rossz eljárás a programhoz
+$ ENOLCK
+77 Nincs elérhetõ zárolás
+$ ENOSYS
+78 Nem implementált funkció
+$ EFTYPE
+79 Nem megfelelõ fájltípus vagy formátum
+$ EAUTH
+80 Azonosítási hiba
+$ ENEEDAUTH
+81 Azonosítás szükséges
+$ EIDRM
+82 Azonosító eltávolítva
+$ ENOMSG
+83 Nincs üzenet a kívánt típusból
+$ EOVERFLOW
+84 Az érték túl nagy az adott adattípusban való tároláshoz
+$ ECANCELED
+85 Mûvelet törölva
+$ EILSEQ
+86 Érvénytelen bájtsorrend
+$ ENOATTR
+87 Attribútum nem található
+$ EDOOFUS
+88 Programozási hiba
+$ EBADMSG
+89 Helytelen üzenet
+$ EMULTIHOP
+90 Multihop kísérlet
+$ ENOLINK
+91 A kapcsolat szigorítva lett
+$ EPROTO
+92 Protokol hiba
+$ ENOTCAPABLE
+93 Elégtelen képességek
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Hangup
+$ SIGINT
+2 Megszakítás
+$ SIGQUIT
+3 Kilépés
+$ SIGILL
+4 Érvénytelen mûvelet
+$ SIGTRAP
+5 Trace/BPT csapda
+$ SIGABRT
+6 Abort csapda
+$ SIGEMT
+7 EMT csapda
+$ SIGFPE
+8 Lebegõpontos kivétel
+$ SIGKILL
+9 Megölve
+$ SIGBUS
+10 Busz hiba
+$ SIGSEGV
+11 Szegmentációs hiba
+$ SIGSYS
+12 Rossz rendszerhívás
+$ SIGPIPE
+13 Hibás csõvezeték
+$ SIGALRM
+14 Idõzítési riasztás
+$ SIGTERM
+15 Befejezve
+$ SIGURG
+16 Sürgõs B/K feltétel
+$ SIGSTOP
+17 Elaltatva (szignál)
+$ SIGTSTP
+18 Elaltatva
+$ SIGCONT
+19 Folytatva
+$ SIGCHLD
+20 Gyermek befejezõdött
+$ SIGTTIN
+21 Leállítva (tty bevitel)
+$ SIGTTOU
+22 Leállítva (tty kivitel)
+$ SIGIO
+23 B/K lehetséges
+$ SIGXCPU
+24 Processzoridõ-korlátozás túllépve
+$ SIGXFSZ
+25 ájlméret-korlátozás túllépve
+$ SIGVTALRM
+26 Virtuális idõzítõ lejárt
+$ SIGPROF
+27 Profilidõzítõ lejárt
+$ SIGWINCH
+28 Ablakméret-változások
+$ SIGINFO
+29 Információkérés
+$ SIGUSR1
+30 Felhasználói szignál 1
+$ SIGUSR2
+31 Felhasználói szignál 2
+$
+$ gai_strerror() support catalog
+$
+$set 3
+$ 1 (elavult)
+1 A hosztnévhez tartozó címcsalád nem támogatott
+$ EAI_AGAIN
+2 Ideiglenes hiba a névfeloldáskor
+$ EAI_BADFLAGS
+3 Érvénytelen ai_flags érték
+$ EAI_FAIL
+4 Nem helyreállítható hiba a névfeloldásban
+$ EAI_FAMILY
+5 ai_family nem támogatott
+$ EAI_MEMORY
+6 Memóriafoglalási hiba
+$ 7 (elavult)
+7 Nem tartozik cím í hosztnévhez
+$ EAI_NONAME
+8 Se hosztnév, se szolgáltatásnév nem áll rendelkezésre
+$ EAI_SERVICE
+9 Nem támogatott ai_socktype szolgáltatásnév
+$ EAI_SOCKTYPE
+10 ai_socktype nem támogatott
+$ EAI_SYSTEM
+11 Rendszerhiba jött vissza az errno változóban
+$ EAI_BADHINTS
+12 Érvénytelen hint érték
+$ EAI_PROTOCOL
+13 A feloldott protokol ismeretlen
+$ EAI_OVERFLOW
+14 Az argumentumok puffere túlcsordult
+$ 0
+32766 Siker
+$ NL_MSGMAX
+32767 Ismeretlen hiba
diff --git a/lib/libc/nls/it_IT.ISO8859-15.msg b/lib/libc/nls/it_IT.ISO8859-15.msg
new file mode 100644
index 0000000..da3734d
--- /dev/null
+++ b/lib/libc/nls/it_IT.ISO8859-15.msg
@@ -0,0 +1,231 @@
+$ $FreeBSD$
+$
+$ Message catalog for it_IT.ISO8859-15 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operazione non permessa
+$ ENOENT
+2 File o directory inesistente
+$ ESRCH
+3 Processo inesistente
+$ EINTR
+4 Chiamata di sistema interrotta
+$ EIO
+5 Errore di input/output
+$ ENXIO
+6 Periferica non configurata
+$ E2BIG
+7 Lista degli argomenti troppo lunga
+$ ENOEXEC
+8 Errore nel formato eseguibile
+$ EBADF
+9 Descrittore di file non valido
+$ ECHILD
+10 Nessun processo figlio
+$ EDEADLK
+11 Situazione di deadlock evitata
+$ ENOMEM
+12 Impossibile allocare memoria
+$ EACCES
+13 Permesso negato
+$ EFAULT
+14 Indirizzo non valido
+$ ENOTBLK
+15 Periferica a blocchi necessaria
+$ EBUSY
+16 Periferica occupata
+$ EEXIST
+17 Il file esiste
+$ EXDEV
+18 Link improprio
+$ ENODEV
+19 Operazione non supportata dalla periferica
+$ ENOTDIR
+20 Non è una directory
+$ EISDIR
+21 E' una directory
+$ EINVAL
+22 Argomento non valido
+$ ENFILE
+23 Troppi file aperti nel sistema
+$ EMFILE
+24 Troppi file aperti
+$ ENOTTY
+25 Ioctl inappropriata per la periferica
+$ ETXTBSY
+26 File di testo occupato
+$ EFBIG
+27 File troppo grande
+$ ENOSPC
+28 Spazio sulla periferica esaurito
+$ ESPIPE
+29 Ricerca non valida
+$ EROFS
+30 Filesystem di sola lettura
+$ EMLINK
+31 Troppi link
+$ EPIPE
+32 Pipe rotta
+$ EDOM
+33 Argomento numerico fuori dal dominio
+$ ERANGE
+34 Risultato troppo grande
+$ EAGAIN, EWOULDBLOCK
+35 Risorsa temporaneamente non disponibile
+$ EINPROGRESS
+36 Operazione in esecuzione
+$ EALREADY
+37 Operazione già in esecuzione
+$ ENOTSOCK
+38 Operazione sui socket eseguita su un non-socket
+$ EDESTADDRREQ
+39 Indirizzo destinazione necessario
+$ EMSGSIZE
+40 Messaggio troppo lungo
+$ EPROTOTYPE
+41 Tipo di protocollo non valido per il socket
+$ ENOPROTOOPT
+42 Protocollo non disponibile
+$ EPROTONOSUPPORT
+43 Protocollo non supportato
+$ ESOCKTNOSUPPORT
+44 Tipo di socket non supportato
+$ EOPNOTSUPP
+45 Operazione non supportata
+$ EPFNOSUPPORT
+46 Famiglia di protocolli non supportata
+$ EAFNOSUPPORT
+47 Famiglia di indirizzi non supportata dalla famiglia di protocolli
+$ EADDRINUSE
+48 Indirizzo già in uso
+$ EADDRNOTAVAIL
+49 Impossibile assegnare l'indirizzo richiesto
+$ ENETDOWN
+50 Network fuori uso
+$ ENETUNREACH
+51 Network non raggiungibile
+$ ENETRESET
+52 Network dropped connection on reset
+$ ECONNABORTED
+53 Interruzione della connessione causata dal software
+$ ECONNRESET
+54 Connessione azzerata dal corrispondente
+$ ENOBUFS
+55 Spazio del buffer esaurito
+$ EISCONN
+56 Socket già connesso
+$ ENOTCONN
+57 Socket non connesso
+$ ESHUTDOWN
+58 Impossibile inviare dopo la chiusura del socket
+$ ETOOMANYREFS
+59 Troppe referenze: impossibile raccordare
+$ ETIMEDOUT
+60 Connessione scaduta
+$ ECONNREFUSED
+61 Connection rifiutata
+$ ELOOP
+62 Troppi livelli di link simbolici
+$ ENAMETOOLONG
+63 Nome di file troppo lungo
+$ EHOSTDOWN
+64 Host fuori uso
+$ EHOSTUNREACH
+65 Host irraggiungibile
+$ ENOTEMPTY
+66 Directory non vuota
+$ EPROCLIM
+67 Troppi processi
+$ EUSERS
+68 Troppi utenti
+$ EDQUOT
+69 Quota disco superata
+$ ESTALE
+70 Manipolatore di file NFS scaduto
+$ EREMOTE
+71 Troppi livelli remoti nel path
+$ EBADRPC
+72 Struttura RPC non valida
+$ ERPCMISMATCH
+73 Versione RPC non corrispondente
+$ EPROGUNAVAIL
+74 Programma RPC non disponibile
+$ EPROGMISMATCH
+75 Versione del programma non corrispodente
+$ EPROCUNAVAIL
+76 Procedura non disponibile
+$ ENOLCK
+77 Nessun lock disponibile
+$ ENOSYS
+78 Funzione non implementata
+$ EFTYPE
+79 Tipo di file o formato inappropriato
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Hangup
+$ SIGINT
+2 Interruzione
+$ SIGQUIT
+3 Chiusura
+$ SIGILL
+4 Istruzione illegale
+$ SIGTRAP
+5 Trappola Trace/breakpoint
+$ SIGABRT
+6 Trappola abort()
+$ SIGEMT
+7 Trappola EMT
+$ SIGFPE
+8 Errore di virgola mobile
+$ SIGKILL
+9 Ucciso
+$ SIGBUS
+10 Errore di bus
+$ SIGSEGV
+11 Errore di segmentazione
+$ SIGSYS
+12 Chiamata di sistema non valida
+$ SIGPIPE
+13 Pipe rotta
+$ SIGALRM
+14 Sveglia
+$ SIGTERM
+15 Terminato
+$ SIGURG
+16 I/O urgente
+$ SIGSTOP
+17 Processo fermato
+$ SIGTSTP
+18 Stop da terminale
+$ SIGCONT
+19 Continuato
+$ SIGCHLD
+20 Processo figlio uscito
+$ SIGTTIN
+21 Input da terminale per processo in background
+$ SIGTTOU
+22 Output a terminale per processo in background
+$ SIGIO
+23 I/O possibile
+$ SIGXCPU
+24 Limite del tempo di CPU superato
+$ SIGXFSZ
+25 Limite della dimensione del file superato
+$ SIGVTALRM
+26 Timer virtuale scaduto
+$ SIGPROF
+27 Timer di profilo expired
+$ SIGWINCH
+28 Cambio di dimensione della finestra
+$ SIGINFO
+29 Richiesta di informazioni
+$ SIGUSR1
+30 Segnale definito dall'utente 1
+$ SIGUSR2
+31 Segnale definito dall'utente 2
diff --git a/lib/libc/nls/ja_JP.UTF-8.msg b/lib/libc/nls/ja_JP.UTF-8.msg
new file mode 100644
index 0000000..6be65fb
--- /dev/null
+++ b/lib/libc/nls/ja_JP.UTF-8.msg
@@ -0,0 +1,295 @@
+$ $FreeBSD$
+$
+$ Message catalog for ja_JP.UTF-8 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 許å¯ã•れã¦ã„ãªã„æ“作ã§ã™
+$ ENOENT
+2 ãã®ã‚ˆã†ãªãƒ•ァイルã¾ãŸã¯ãƒ‡ã‚£ãƒ¬ã‚¯ãƒˆãƒªã¯ã‚りã¾ã›ã‚“
+$ ESRCH
+3 ãã®ã‚ˆã†ãªãƒ—ロセスã¯ã‚りã¾ã›ã‚“
+$ EINTR
+4 システムコールãŒä¸­æ–­ã•れã¾ã—ãŸ
+$ EIO
+5 入出力エラーã§ã™
+$ ENXIO
+6 デãƒã‚¤ã‚¹ãŒæº–å‚™ã•れã¦ã„ã¾ã›ã‚“
+$ E2BIG
+7 引数ã®ãƒªã‚¹ãƒˆãŒé•·ã™ãŽã¾ã™
+$ ENOEXEC
+8 無効ãªå®Ÿè¡Œå½¢å¼ã§ã™
+$ EBADF
+9 無効ãªãƒ•ァイル記述å­ã§ã™
+$ ECHILD
+10 å­ãƒ—ロセスãŒã‚りã¾ã›ã‚“
+$ EDEADLK
+11 リソースデッドロックを回é¿ã—ã¾ã—ãŸ
+$ ENOMEM
+12 メモリã®å‰²ã‚Šå½“ã¦ãŒã§ãã¾ã›ã‚“
+$ EACCES
+13 ãƒ‘ãƒ¼ãƒŸãƒƒã‚·ãƒ§ãƒ³ãŒæ‹’çµ¶ã•れã¾ã—ãŸ
+$ EFAULT
+14 無効ãªã‚¢ãƒ‰ãƒ¬ã‚¹ã§ã™
+$ ENOTBLK
+15 ブロックデãƒã‚¤ã‚¹ãŒè¦æ±‚ã•れã¦ã„ã¾ã™
+$ EBUSY
+16 デãƒã‚¤ã‚¹ãŒãƒ“ジー状態ã§ã™
+$ EEXIST
+17 ファイルãŒå­˜åœ¨ã—ã¾ã™
+$ EXDEV
+18 デãƒã‚¤ã‚¹ã‚’ã¾ãŸãリンクã§ã™
+$ ENODEV
+19 デãƒã‚¤ã‚¹ãŒå¯¾å¿œã—ã¦ãªã„æ“作ã§ã™
+$ ENOTDIR
+20 ディレクトリã§ã¯ã‚りã¾ã›ã‚“
+$ EISDIR
+21 ディレクトリã§ã™
+$ EINVAL
+22 無効ãªå¼•æ•°ã§ã™
+$ ENFILE
+23 システム内ã§ã‚ªãƒ¼ãƒ—ンã•れã¦ã„るファイルãŒå¤šã™ãŽã¾ã™
+$ EMFILE
+24 オープンã—ã¦ã„るファイルãŒå¤šã™ãŽã¾ã™
+$ ENOTTY
+25 デãƒã‚¤ã‚¹ãŒå¯¾å¿œã—ã¦ã„ãªã„ ioctl ã§ã™
+$ ETXTBSY
+26 テキストファイルãŒãƒ“ジー状態ã§ã™
+$ EFBIG
+27 ファイルãŒå¤§ãã™ãŽã¾ã™
+$ ENOSPC
+28 デãƒã‚¤ã‚¹ã®ç©ºã領域ä¸è¶³ã§ã™
+$ ESPIPE
+29 無効ãªã‚·ãƒ¼ã‚¯ã§ã™
+$ EROFS
+30 読ã¿è¾¼ã¿å°‚用ファイルシステムã§ã™
+$ EMLINK
+31 リンク数ãŒå¤šã™ãŽã¾ã™
+$ EPIPE
+32 パイプãŒç ´å£Šã•れã¦ã¾ã—ãŸ
+$ EDOM
+33 数値引数ãŒç¯„囲外ã§ã™
+$ ERANGE
+34 çµæžœãŒå¤§ãéŽãŽã¾ã™
+$ EAGAIN, EWOULDBLOCK
+35 リソースãŒä¸€æ™‚çš„ã«åˆ©ç”¨ã§ãã¾ã›ã‚“
+$ EINPROGRESS
+36 æ“作ãŒç¾åœ¨é€²è¡Œä¸­ã§ã™
+$ EALREADY
+37 æ“ä½œã¯æ—¢ã«é€²è¡Œä¸­ã§ã™
+$ ENOTSOCK
+38 ソケットã§ãªã„ã‚‚ã®ã«ã¤ã„ã¦ã‚½ã‚±ãƒƒãƒˆæ“作を行ã„ã¾ã—ãŸ
+$ EDESTADDRREQ
+39 宛先アドレスãŒè¦æ±‚ã•れã¦ã„ã¾ã™
+$ EMSGSIZE
+40 メッセージãŒé•·ã™ãŽã¾ã™
+$ EPROTOTYPE
+41 ソケットãŒå¯¾å¿œã—ã¦ã„ãªã„プロトコルタイプã§ã™
+$ ENOPROTOOPT
+42 利用ã§ããªã„プロトコルã§ã™
+$ EPROTONOSUPPORT
+43 対応ã—ã¦ã„ãªã„プロトコルã§ã™
+$ ESOCKTNOSUPPORT
+44 対応ã—ã¦ã„ãªã„ソケットタイプã§ã™
+$ EOPNOTSUPP
+45 対応ã—ã¦ã„ãªã„æ“作ã§ã™
+$ EPFNOSUPPORT
+46 対応ã—ã¦ã„ãªã„プロトコルファミリã§ã™
+$ EAFNOSUPPORT
+47 プロトコルファミリãŒå¯¾å¿œã—ã¦ã„ãªã„ã‚¢ãƒ‰ãƒ¬ã‚¹ãƒ•ã‚¡ãƒŸãƒªãŒæŒ‡å®šã•れã¾ã—ãŸ
+$ EADDRINUSE
+48 ã‚¢ãƒ‰ãƒ¬ã‚¹ãŒæ—¢ã«ä½¿ç”¨ä¸­ã§ã™
+$ EADDRNOTAVAIL
+49 è¦æ±‚ã•れãŸã‚¢ãƒ‰ãƒ¬ã‚¹ã‚’割り当ã¦ã§ãã¾ã›ã‚“
+$ ENETDOWN
+50 ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ãŒãƒ€ã‚¦ãƒ³ã—ã¦ã„ã¾ã™
+$ ENETUNREACH
+51 ãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã«åˆ°é”ã§ãã¾ã›ã‚“
+$ ENETRESET
+52 リセットã«ã‚ˆã‚Šãƒãƒƒãƒˆãƒ¯ãƒ¼ã‚¯ã®æŽ¥ç¶šãŒå¤±ã‚れã¾ã—ãŸ
+$ ECONNABORTED
+53 ソフトウェアã«ã‚ˆã£ã¦æŽ¥ç¶šãŒåˆ‡æ–­ã•れã¾ã—ãŸ
+$ ECONNRESET
+54 接続ãŒé€šä¿¡ç›¸æ‰‹ã«ã‚ˆã£ã¦ãƒªã‚»ãƒƒãƒˆã•れã¾ã—ãŸ
+$ ENOBUFS
+55 ãƒãƒƒãƒ•ã‚¡ã®å®¹é‡ä¸è¶³ã§ã™
+$ EISCONN
+56 ã‚½ã‚±ãƒƒãƒˆã¯æ—¢ã«æŽ¥ç¶šã•れã¦ã„ã¾ã™
+$ ENOTCONN
+57 ã‚½ã‚±ãƒƒãƒˆã¯æŽ¥ç¶šã•れã¦ã„ã¾ã›ã‚“
+$ ESHUTDOWN
+58 ソケットã®ã‚·ãƒ£ãƒƒãƒˆãƒ€ã‚¦ãƒ³ã®å¾Œã§é€ä¿¡ãŒã§ãã¾ã›ã‚“
+$ ETOOMANYREFS
+59 処ç†é™ç•Œã‚’è¶…ãˆã‚‹å¤šé‡å‚ç…§ã§ã™
+$ ETIMEDOUT
+60 æ“作ãŒã‚¿ã‚¤ãƒ ã‚¢ã‚¦ãƒˆã—ã¾ã—ãŸ
+$ ECONNREFUSED
+61 æŽ¥ç¶šãŒæ‹’çµ¶ã•れã¾ã—ãŸ
+$ ELOOP
+62 処ç†é™ç•Œã‚’è¶…ãˆã‚‹ã‚·ãƒ³ãƒœãƒªãƒƒã‚¯ãƒªãƒ³ã‚¯ãƒ¬ãƒ™ãƒ«ã§ã™
+$ ENAMETOOLONG
+63 ファイルåãŒé•·ã™ãŽã¾ã™
+$ EHOSTDOWN
+64 ホストãŒãƒ€ã‚¦ãƒ³ã—ã¦ã„ã¾ã™
+$ EHOSTUNREACH
+65 ホストã¸ã®çµŒè·¯ãŒã‚りã¾ã›ã‚“
+$ ENOTEMPTY
+66 ディレクトリãŒç©ºã§ã¯ã‚りã¾ã›ã‚“
+$ EPROCLIM
+67 プロセスãŒå¤šã™ãŽã¾ã™
+$ EUSERS
+68 ユーザãŒå¤šã™ãŽã¾ã™
+$ EDQUOT
+69 ディスククォータãŒè¶…éŽã—ã¾ã—ãŸ
+$ ESTALE
+70 失効ã—㟠NFS ファイルãƒãƒ³ãƒ‰ãƒ«ã§ã™
+$ EREMOTE
+71 パス中ã®ãƒªãƒ¢ãƒ¼ãƒˆã®ãƒ¬ãƒ™ãƒ«ãŒå¤šã™ãŽã¾ã™
+$ EBADRPC
+72 無効㪠RPC 構造体ã§ã™
+$ ERPCMISMATCH
+73 RPC ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒé–“é•ã£ã¦ã„ã¾ã™
+$ EPROGUNAVAIL
+74 RPC プログラムãŒåˆ©ç”¨ã§ãã¾ã›ã‚“
+$ EPROGMISMATCH
+75 プログラムã®ãƒãƒ¼ã‚¸ãƒ§ãƒ³ãŒåˆã£ã¦ã„ã¾ã›ã‚“
+$ EPROCUNAVAIL
+76 プログラムã§ã¯åˆ©ç”¨ã§ããªã„ procedure ã§ã™
+$ ENOLCK
+77 ロックãŒåˆ©ç”¨ã§ãã¾ã›ã‚“
+$ ENOSYS
+78 関数ãŒå®Ÿè£…ã•れã¦ã„ã¾ã›ã‚“
+$ EFTYPE
+79 ファイルã®åž‹ã¾ãŸã¯å½¢å¼ãŒä¸é©åˆ‡ã§ã™
+$ EAUTH
+80 èªè¨¼ã‚¨ãƒ©ãƒ¼ã§ã™
+$ ENEEDAUTH
+81 èªè¨¼ç‰©ãŒå¿…è¦ã§ã™
+$ EIDRM
+82 識別å­ã¯å‰Šé™¤ã•れã¾ã—ãŸ
+$ ENOMSG
+83 è¦æ±‚ã•れãŸåž‹ã®ãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ãŒã‚りã¾ã›ã‚“
+$ EOVERFLOW
+84 ãƒ‡ãƒ¼ã‚¿åž‹ã«æ ¼ç´ã™ã‚‹ã«ã¯å¤§ãã™ãŽã‚‹å€¤ã§ã™
+$ ECANCELED
+85 処ç†ãŒã‚­ãƒ£ãƒ³ã‚»ãƒ«ã•れã¾ã—ãŸ
+$ EILSEQ
+86 䏿­£ãªãƒã‚¤ãƒˆåˆ—ã§ã™
+$ ENOATTR
+87 ãã®ã‚ˆã†ãªå±žæ€§ã¯ã‚りã¾ã›ã‚“
+$ EDOOFUS
+88 プログラミングエラーã§ã™
+$ EBADMSG
+89 無効ãªãƒ¡ãƒƒã‚»ãƒ¼ã‚¸ã§ã™
+$ EMULTIHOP
+90 マルãƒãƒ›ãƒƒãƒ—ãŒè©¦ã¿ã‚‰ã‚Œã¾ã—ãŸ
+$ ENOLINK
+91 リンクãŒåˆ‡æ–­ã•れã¦ã„ã¾ã™
+$ EPROTO
+92 プロトコルエラーã§ã™
+$ ENOTCAPABLE
+93 ケーパビリティãŒä¸è¶³ã§ã™
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 ãƒãƒ³ã‚°ã‚¢ãƒƒãƒ—
+$ SIGINT
+2 割り込ã¿
+$ SIGQUIT
+3 中断
+$ SIGILL
+4 䏿­£å‘½ä»¤
+$ SIGTRAP
+5 トレース/BPT トラップ
+$ SIGABRT
+6 アボートトラップ
+$ SIGEMT
+7 EMT トラップ
+$ SIGFPE
+8 æµ®å‹•å°æ•°ç‚¹ä¾‹å¤–
+$ SIGKILL
+9 Kill ã•れãŸ
+$ SIGBUS
+10 ãƒã‚¹ã‚¨ãƒ©ãƒ¼
+$ SIGSEGV
+11 セグメンテーションé•å
+$ SIGSYS
+12 存在ã—ãªã„システムコール
+$ SIGPIPE
+13 パイプ破壊
+$ SIGALRM
+14 アラームクロック
+$ SIGTERM
+15 終了
+$ SIGURG
+16 緊急入出力状æ³
+$ SIGSTOP
+17 ä¸€æ™‚åœæ­¢ (シグナル)
+$ SIGTSTP
+18 ä¸€æ™‚åœæ­¢
+$ SIGCONT
+19 継続
+$ SIGCHLD
+20 å­ãƒ—ロセスã®çµ‚了
+$ SIGTTIN
+21 ä¸€æ™‚åœæ­¢ (tty 入力)
+$ SIGTTOU
+22 ä¸€æ™‚åœæ­¢ (tty 出力)
+$ SIGIO
+23 入出力å¯èƒ½
+$ SIGXCPU
+24 CPU 時間ã®åˆ¶é™è¶…éŽ
+$ SIGXFSZ
+25 ファイルサイズã®åˆ¶é™è¶…éŽ
+$ SIGVTALRM
+26 ä»®æƒ³ã‚¿ã‚¤ãƒžã®æœŸé™è¶…éŽ
+$ SIGPROF
+27 ãƒ—ãƒ­ãƒ•ã‚¡ã‚¤ãƒ«ã‚¿ã‚¤ãƒžã®æœŸé™è¶…éŽ
+$ SIGWINCH
+28 ウィンドウサイズã®å¤‰åŒ–
+$ SIGINFO
+29 æƒ…å ±è¦æ±‚
+$ SIGUSR1
+30 ユーザ定義シグナル 1
+$ SIGUSR2
+31 ユーザ定義シグナル 2
+$
+$ gai_strerror() support catalog
+$
+$set 3
+$ 1 (obsolete)
+1 ホストåã®ã‚¢ãƒ‰ãƒ¬ã‚¹ãƒ•ァミリーã¯ã‚µãƒãƒ¼ãƒˆã•れã¾ã›ã‚“
+$ EAI_AGAIN
+2 åå‰è§£æ±ºã§ã®ä¸€æ™‚çš„ãªå¤±æ•—
+$ EAI_BADFLAGS
+3 ai_flags ã®å€¤ãŒç„¡åй
+$ EAI_FAIL
+4 åå‰è§£æ±ºã§ã®å›žå¾©ä¸èƒ½ãªå¤±æ•—
+$ EAI_FAMILY
+5 ai_family ã¯ã‚µãƒãƒ¼ãƒˆã•れã¾ã›ã‚“
+$ EAI_MEMORY
+6 メモリ割り当ã¦å¤±æ•—
+$ 7 (obsolete)
+7 ホストåã«å¯¾å¿œã™ã‚‹ã‚¢ãƒ‰ãƒ¬ã‚¹ã¯ã‚りã¾ã›ã‚“
+$ EAI_NONAME
+8 ホストåã‹ã‚µãƒ¼ãƒ“スåãŒæŒ‡å®šã•れãªã„ã€ã¾ãŸã¯ä¸æ˜Ž
+$ EAI_SERVICE
+9 サービスå㯠ai_socktype ã«å¯¾ã—ã¦ã‚µãƒãƒ¼ãƒˆã•れã¾ã›ã‚“
+$ EAI_SOCKTYPE
+10 ai_socktype ã¯ã‚µãƒãƒ¼ãƒˆã•れã¾ã›ã‚“
+$ EAI_SYSTEM
+11 システムエラーã€errno å‚ç…§
+$ EAI_BADHINTS
+12 hints ã®å€¤ãŒç„¡åй
+$ EAI_PROTOCOL
+13 解決ã•れãŸãƒ—ロトコルã¯ä¸æ˜Žã§ã™
+$ EAI_OVERFLOW
+14 引数ãƒãƒƒãƒ•ァオーãƒãƒ•ロー
+$ 0
+32766 æˆåŠŸ
+$ NL_MSGMAX
+32767 䏿˜Žãªã‚¨ãƒ©ãƒ¼
diff --git a/lib/libc/nls/ja_JP.eucJP.msg b/lib/libc/nls/ja_JP.eucJP.msg
new file mode 100644
index 0000000..e3fac48
--- /dev/null
+++ b/lib/libc/nls/ja_JP.eucJP.msg
@@ -0,0 +1,295 @@
+$ $FreeBSD$
+$
+$ Message catalog for ja_JP.eucJP locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 µö²Ä¤µ¤ì¤Æ¤¤¤Ê¤¤Áàºî¤Ç¤¹
+$ ENOENT
+2 ¤½¤Î¤è¤¦¤Ê¥Õ¥¡¥¤¥ë¤Þ¤¿¤Ï¥Ç¥£¥ì¥¯¥È¥ê¤Ï¤¢¤ê¤Þ¤»¤ó
+$ ESRCH
+3 ¤½¤Î¤è¤¦¤Ê¥×¥í¥»¥¹¤Ï¤¢¤ê¤Þ¤»¤ó
+$ EINTR
+4 ¥·¥¹¥Æ¥à¥³¡¼¥ë¤¬ÃæÃǤµ¤ì¤Þ¤·¤¿
+$ EIO
+5 Æþ½ÐÎÏ¥¨¥é¡¼¤Ç¤¹
+$ ENXIO
+6 ¥Ç¥Ð¥¤¥¹¤¬½àÈ÷¤µ¤ì¤Æ¤¤¤Þ¤»¤ó
+$ E2BIG
+7 °ú¿ô¤Î¥ê¥¹¥È¤¬Ä¹¤¹¤®¤Þ¤¹
+$ ENOEXEC
+8 ̵¸ú¤Ê¼Â¹Ô·Á¼°¤Ç¤¹
+$ EBADF
+9 ̵¸ú¤Ê¥Õ¥¡¥¤¥ëµ­½Ò»Ò¤Ç¤¹
+$ ECHILD
+10 »Ò¥×¥í¥»¥¹¤¬¤¢¤ê¤Þ¤»¤ó
+$ EDEADLK
+11 ¥ê¥½¡¼¥¹¥Ç¥Ã¥É¥í¥Ã¥¯¤ò²óÈò¤·¤Þ¤·¤¿
+$ ENOMEM
+12 ¥á¥â¥ê¤Î³ä¤êÅö¤Æ¤¬¤Ç¤­¤Þ¤»¤ó
+$ EACCES
+13 ¥Ñ¡¼¥ß¥Ã¥·¥ç¥ó¤¬µñÀ䤵¤ì¤Þ¤·¤¿
+$ EFAULT
+14 ̵¸ú¤Ê¥¢¥É¥ì¥¹¤Ç¤¹
+$ ENOTBLK
+15 ¥Ö¥í¥Ã¥¯¥Ç¥Ð¥¤¥¹¤¬Í׵ᤵ¤ì¤Æ¤¤¤Þ¤¹
+$ EBUSY
+16 ¥Ç¥Ð¥¤¥¹¤¬¥Ó¥¸¡¼¾õÂ֤Ǥ¹
+$ EEXIST
+17 ¥Õ¥¡¥¤¥ë¤¬Â¸ºß¤·¤Þ¤¹
+$ EXDEV
+18 ¥Ç¥Ð¥¤¥¹¤ò¤Þ¤¿¤°¥ê¥ó¥¯¤Ç¤¹
+$ ENODEV
+19 ¥Ç¥Ð¥¤¥¹¤¬Âбþ¤·¤Æ¤Ê¤¤Áàºî¤Ç¤¹
+$ ENOTDIR
+20 ¥Ç¥£¥ì¥¯¥È¥ê¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó
+$ EISDIR
+21 ¥Ç¥£¥ì¥¯¥È¥ê¤Ç¤¹
+$ EINVAL
+22 ̵¸ú¤Ê°ú¿ô¤Ç¤¹
+$ ENFILE
+23 ¥·¥¹¥Æ¥àÆâ¤Ç¥ª¡¼¥×¥ó¤µ¤ì¤Æ¤¤¤ë¥Õ¥¡¥¤¥ë¤¬Â¿¤¹¤®¤Þ¤¹
+$ EMFILE
+24 ¥ª¡¼¥×¥ó¤·¤Æ¤¤¤ë¥Õ¥¡¥¤¥ë¤¬Â¿¤¹¤®¤Þ¤¹
+$ ENOTTY
+25 ¥Ç¥Ð¥¤¥¹¤¬Âбþ¤·¤Æ¤¤¤Ê¤¤ ioctl ¤Ç¤¹
+$ ETXTBSY
+26 ¥Æ¥­¥¹¥È¥Õ¥¡¥¤¥ë¤¬¥Ó¥¸¡¼¾õÂ֤Ǥ¹
+$ EFBIG
+27 ¥Õ¥¡¥¤¥ë¤¬Â礭¤¹¤®¤Þ¤¹
+$ ENOSPC
+28 ¥Ç¥Ð¥¤¥¹¤Î¶õ¤­ÎΰèÉÔ­¤Ç¤¹
+$ ESPIPE
+29 ̵¸ú¤Ê¥·¡¼¥¯¤Ç¤¹
+$ EROFS
+30 ÆÉ¤ß¹þ¤ßÀìÍÑ¥Õ¥¡¥¤¥ë¥·¥¹¥Æ¥à¤Ç¤¹
+$ EMLINK
+31 ¥ê¥ó¥¯¿ô¤¬Â¿¤¹¤®¤Þ¤¹
+$ EPIPE
+32 ¥Ñ¥¤¥×¤¬Ç˲õ¤µ¤ì¤Æ¤Þ¤·¤¿
+$ EDOM
+33 ¿ôÃͰú¿ô¤¬Èϰϳ°¤Ç¤¹
+$ ERANGE
+34 ·ë²Ì¤¬Â礭²á¤®¤Þ¤¹
+$ EAGAIN, EWOULDBLOCK
+35 ¥ê¥½¡¼¥¹¤¬°ì»þŪ¤ËÍøÍѤǤ­¤Þ¤»¤ó
+$ EINPROGRESS
+36 Áàºî¤¬¸½ºß¿Ê¹ÔÃæ¤Ç¤¹
+$ EALREADY
+37 Áàºî¤Ï´û¤Ë¿Ê¹ÔÃæ¤Ç¤¹
+$ ENOTSOCK
+38 ¥½¥±¥Ã¥È¤Ç¤Ê¤¤¤â¤Î¤Ë¤Ä¤¤¤Æ¥½¥±¥Ã¥ÈÁàºî¤ò¹Ô¤¤¤Þ¤·¤¿
+$ EDESTADDRREQ
+39 °¸À襢¥É¥ì¥¹¤¬Í׵ᤵ¤ì¤Æ¤¤¤Þ¤¹
+$ EMSGSIZE
+40 ¥á¥Ã¥»¡¼¥¸¤¬Ä¹¤¹¤®¤Þ¤¹
+$ EPROTOTYPE
+41 ¥½¥±¥Ã¥È¤¬Âбþ¤·¤Æ¤¤¤Ê¤¤¥×¥í¥È¥³¥ë¥¿¥¤¥×¤Ç¤¹
+$ ENOPROTOOPT
+42 ÍøÍѤǤ­¤Ê¤¤¥×¥í¥È¥³¥ë¤Ç¤¹
+$ EPROTONOSUPPORT
+43 Âбþ¤·¤Æ¤¤¤Ê¤¤¥×¥í¥È¥³¥ë¤Ç¤¹
+$ ESOCKTNOSUPPORT
+44 Âбþ¤·¤Æ¤¤¤Ê¤¤¥½¥±¥Ã¥È¥¿¥¤¥×¤Ç¤¹
+$ EOPNOTSUPP
+45 Âбþ¤·¤Æ¤¤¤Ê¤¤Áàºî¤Ç¤¹
+$ EPFNOSUPPORT
+46 Âбþ¤·¤Æ¤¤¤Ê¤¤¥×¥í¥È¥³¥ë¥Õ¥¡¥ß¥ê¤Ç¤¹
+$ EAFNOSUPPORT
+47 ¥×¥í¥È¥³¥ë¥Õ¥¡¥ß¥ê¤¬Âбþ¤·¤Æ¤¤¤Ê¤¤¥¢¥É¥ì¥¹¥Õ¥¡¥ß¥ê¤¬»ØÄꤵ¤ì¤Þ¤·¤¿
+$ EADDRINUSE
+48 ¥¢¥É¥ì¥¹¤¬´û¤Ë»ÈÍÑÃæ¤Ç¤¹
+$ EADDRNOTAVAIL
+49 Í׵ᤵ¤ì¤¿¥¢¥É¥ì¥¹¤ò³ä¤êÅö¤Æ¤Ç¤­¤Þ¤»¤ó
+$ ENETDOWN
+50 ¥Í¥Ã¥È¥ï¡¼¥¯¤¬¥À¥¦¥ó¤·¤Æ¤¤¤Þ¤¹
+$ ENETUNREACH
+51 ¥Í¥Ã¥È¥ï¡¼¥¯¤ËÅþã¤Ç¤­¤Þ¤»¤ó
+$ ENETRESET
+52 ¥ê¥»¥Ã¥È¤Ë¤è¤ê¥Í¥Ã¥È¥ï¡¼¥¯¤ÎÀܳ¤¬¼º¤ï¤ì¤Þ¤·¤¿
+$ ECONNABORTED
+53 ¥½¥Õ¥È¥¦¥§¥¢¤Ë¤è¤Ã¤ÆÀܳ¤¬ÀÚÃǤµ¤ì¤Þ¤·¤¿
+$ ECONNRESET
+54 Àܳ¤¬ÄÌ¿®Áê¼ê¤Ë¤è¤Ã¤Æ¥ê¥»¥Ã¥È¤µ¤ì¤Þ¤·¤¿
+$ ENOBUFS
+55 ¥Ð¥Ã¥Õ¥¡¤ÎÍÆÎÌÉÔ­¤Ç¤¹
+$ EISCONN
+56 ¥½¥±¥Ã¥È¤Ï´û¤ËÀܳ¤µ¤ì¤Æ¤¤¤Þ¤¹
+$ ENOTCONN
+57 ¥½¥±¥Ã¥È¤ÏÀܳ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó
+$ ESHUTDOWN
+58 ¥½¥±¥Ã¥È¤Î¥·¥ã¥Ã¥È¥À¥¦¥ó¤Î¸å¤ÇÁ÷¿®¤¬¤Ç¤­¤Þ¤»¤ó
+$ ETOOMANYREFS
+59 ½èÍý¸Â³¦¤òͤ¨¤ë¿½Å»²¾È¤Ç¤¹
+$ ETIMEDOUT
+60 Áàºî¤¬¥¿¥¤¥à¥¢¥¦¥È¤·¤Þ¤·¤¿
+$ ECONNREFUSED
+61 Àܳ¤¬µñÀ䤵¤ì¤Þ¤·¤¿
+$ ELOOP
+62 ½èÍý¸Â³¦¤òͤ¨¤ë¥·¥ó¥Ü¥ê¥Ã¥¯¥ê¥ó¥¯¥ì¥Ù¥ë¤Ç¤¹
+$ ENAMETOOLONG
+63 ¥Õ¥¡¥¤¥ë̾¤¬Ä¹¤¹¤®¤Þ¤¹
+$ EHOSTDOWN
+64 ¥Û¥¹¥È¤¬¥À¥¦¥ó¤·¤Æ¤¤¤Þ¤¹
+$ EHOSTUNREACH
+65 ¥Û¥¹¥È¤Ø¤Î·ÐÏ©¤¬¤¢¤ê¤Þ¤»¤ó
+$ ENOTEMPTY
+66 ¥Ç¥£¥ì¥¯¥È¥ê¤¬¶õ¤Ç¤Ï¤¢¤ê¤Þ¤»¤ó
+$ EPROCLIM
+67 ¥×¥í¥»¥¹¤¬Â¿¤¹¤®¤Þ¤¹
+$ EUSERS
+68 ¥æ¡¼¥¶¤¬Â¿¤¹¤®¤Þ¤¹
+$ EDQUOT
+69 ¥Ç¥£¥¹¥¯¥¯¥©¡¼¥¿¤¬Ä¶²á¤·¤Þ¤·¤¿
+$ ESTALE
+70 ¼º¸ú¤·¤¿ NFS ¥Õ¥¡¥¤¥ë¥Ï¥ó¥É¥ë¤Ç¤¹
+$ EREMOTE
+71 ¥Ñ¥¹Ãæ¤Î¥ê¥â¡¼¥È¤Î¥ì¥Ù¥ë¤¬Â¿¤¹¤®¤Þ¤¹
+$ EBADRPC
+72 ̵¸ú¤Ê RPC ¹½Â¤ÂΤǤ¹
+$ ERPCMISMATCH
+73 RPC ¥Ð¡¼¥¸¥ç¥ó¤¬´Ö°ã¤Ã¤Æ¤¤¤Þ¤¹
+$ EPROGUNAVAIL
+74 RPC ¥×¥í¥°¥é¥à¤¬ÍøÍѤǤ­¤Þ¤»¤ó
+$ EPROGMISMATCH
+75 ¥×¥í¥°¥é¥à¤Î¥Ð¡¼¥¸¥ç¥ó¤¬¹ç¤Ã¤Æ¤¤¤Þ¤»¤ó
+$ EPROCUNAVAIL
+76 ¥×¥í¥°¥é¥à¤Ç¤ÏÍøÍѤǤ­¤Ê¤¤ procedure ¤Ç¤¹
+$ ENOLCK
+77 ¥í¥Ã¥¯¤¬ÍøÍѤǤ­¤Þ¤»¤ó
+$ ENOSYS
+78 ´Ø¿ô¤¬¼ÂÁõ¤µ¤ì¤Æ¤¤¤Þ¤»¤ó
+$ EFTYPE
+79 ¥Õ¥¡¥¤¥ë¤Î·¿¤Þ¤¿¤Ï·Á¼°¤¬ÉÔŬÀڤǤ¹
+$ EAUTH
+80 ǧ¾Ú¥¨¥é¡¼¤Ç¤¹
+$ ENEEDAUTH
+81 ǧ¾Úʪ¤¬É¬ÍפǤ¹
+$ EIDRM
+82 ¼±Ê̻ҤϺï½ü¤µ¤ì¤Þ¤·¤¿
+$ ENOMSG
+83 Í׵ᤵ¤ì¤¿·¿¤Î¥á¥Ã¥»¡¼¥¸¤¬¤¢¤ê¤Þ¤»¤ó
+$ EOVERFLOW
+84 ¥Ç¡¼¥¿·¿¤Ë³ÊǼ¤¹¤ë¤Ë¤ÏÂ礭¤¹¤®¤ëÃͤǤ¹
+$ ECANCELED
+85 ½èÍý¤¬¥­¥ã¥ó¥»¥ë¤µ¤ì¤Þ¤·¤¿
+$ EILSEQ
+86 ÉÔÀµ¤Ê¥Ð¥¤¥ÈÎó¤Ç¤¹
+$ ENOATTR
+87 ¤½¤Î¤è¤¦¤Ê°À­¤Ï¤¢¤ê¤Þ¤»¤ó
+$ EDOOFUS
+88 ¥×¥í¥°¥é¥ß¥ó¥°¥¨¥é¡¼¤Ç¤¹
+$ EBADMSG
+89 ̵¸ú¤Ê¥á¥Ã¥»¡¼¥¸¤Ç¤¹
+$ EMULTIHOP
+90 ¥Þ¥ë¥Á¥Û¥Ã¥×¤¬»î¤ß¤é¤ì¤Þ¤·¤¿
+$ ENOLINK
+91 ¥ê¥ó¥¯¤¬ÀÚÃǤµ¤ì¤Æ¤¤¤Þ¤¹
+$ EPROTO
+92 ¥×¥í¥È¥³¥ë¥¨¥é¡¼¤Ç¤¹
+$ ENOTCAPABLE
+93 ¥±¡¼¥Ñ¥Ó¥ê¥Æ¥£¤¬ÉÔ­¤Ç¤¹
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 ¥Ï¥ó¥°¥¢¥Ã¥×
+$ SIGINT
+2 ³ä¤ê¹þ¤ß
+$ SIGQUIT
+3 ̾̂
+$ SIGILL
+4 ÉÔÀµÌ¿Îá
+$ SIGTRAP
+5 ¥È¥ì¡¼¥¹/BPT ¥È¥é¥Ã¥×
+$ SIGABRT
+6 ¥¢¥Ü¡¼¥È¥È¥é¥Ã¥×
+$ SIGEMT
+7 EMT ¥È¥é¥Ã¥×
+$ SIGFPE
+8 ÉâÆ°¾®¿ôÅÀÎã³°
+$ SIGKILL
+9 Kill ¤µ¤ì¤¿
+$ SIGBUS
+10 ¥Ð¥¹¥¨¥é¡¼
+$ SIGSEGV
+11 ¥»¥°¥á¥ó¥Æ¡¼¥·¥ç¥ó°ãÈ¿
+$ SIGSYS
+12 ¸ºß¤·¤Ê¤¤¥·¥¹¥Æ¥à¥³¡¼¥ë
+$ SIGPIPE
+13 ¥Ñ¥¤¥×Ç˲õ
+$ SIGALRM
+14 ¥¢¥é¡¼¥à¥¯¥í¥Ã¥¯
+$ SIGTERM
+15 ½ªÎ»
+$ SIGURG
+16 ¶ÛµÞÆþ½ÐÎϾõ¶·
+$ SIGSTOP
+17 °ì»þÄä»ß (¥·¥°¥Ê¥ë)
+$ SIGTSTP
+18 °ì»þÄä»ß
+$ SIGCONT
+19 ·Ñ³
+$ SIGCHLD
+20 »Ò¥×¥í¥»¥¹¤Î½ªÎ»
+$ SIGTTIN
+21 °ì»þÄä»ß (tty ÆþÎÏ)
+$ SIGTTOU
+22 °ì»þÄä»ß (tty ½ÐÎÏ)
+$ SIGIO
+23 Æþ½ÐÎϲÄǽ
+$ SIGXCPU
+24 CPU »þ´Ö¤ÎÀ©¸ÂͲá
+$ SIGXFSZ
+25 ¥Õ¥¡¥¤¥ë¥µ¥¤¥º¤ÎÀ©¸ÂͲá
+$ SIGVTALRM
+26 ²¾ÁÛ¥¿¥¤¥Þ¤Î´ü¸ÂͲá
+$ SIGPROF
+27 ¥×¥í¥Õ¥¡¥¤¥ë¥¿¥¤¥Þ¤Î´ü¸ÂͲá
+$ SIGWINCH
+28 ¥¦¥£¥ó¥É¥¦¥µ¥¤¥º¤ÎÊѲ½
+$ SIGINFO
+29 ¾ðÊóÍ×µá
+$ SIGUSR1
+30 ¥æ¡¼¥¶ÄêµÁ¥·¥°¥Ê¥ë 1
+$ SIGUSR2
+31 ¥æ¡¼¥¶ÄêµÁ¥·¥°¥Ê¥ë 2
+$
+$ gai_strerror() support catalog
+$
+$set 3
+$ 1 (obsolete)
+1 ¥Û¥¹¥È̾¤Î¥¢¥É¥ì¥¹¥Õ¥¡¥ß¥ê¡¼¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó
+$ EAI_AGAIN
+2 ̾Á°²ò·è¤Ç¤Î°ì»þŪ¤Ê¼ºÇÔ
+$ EAI_BADFLAGS
+3 ai_flags ¤ÎÃͤ¬Ìµ¸ú
+$ EAI_FAIL
+4 ̾Á°²ò·è¤Ç¤Î²óÉüÉÔǽ¤Ê¼ºÇÔ
+$ EAI_FAMILY
+5 ai_family ¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó
+$ EAI_MEMORY
+6 ¥á¥â¥ê³ä¤êÅö¤Æ¼ºÇÔ
+$ 7 (obsolete)
+7 ¥Û¥¹¥È̾¤ËÂбþ¤¹¤ë¥¢¥É¥ì¥¹¤Ï¤¢¤ê¤Þ¤»¤ó
+$ EAI_NONAME
+8 ¥Û¥¹¥È̾¤«¥µ¡¼¥Ó¥¹Ì¾¤¬»ØÄꤵ¤ì¤Ê¤¤¡¢¤Þ¤¿¤ÏÉÔÌÀ
+$ EAI_SERVICE
+9 ¥µ¡¼¥Ó¥¹Ì¾¤Ï ai_socktype ¤ËÂФ·¤Æ¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó
+$ EAI_SOCKTYPE
+10 ai_socktype ¤Ï¥µ¥Ý¡¼¥È¤µ¤ì¤Þ¤»¤ó
+$ EAI_SYSTEM
+11 ¥·¥¹¥Æ¥à¥¨¥é¡¼¡¢errno »²¾È
+$ EAI_BADHINTS
+12 hints ¤ÎÃͤ¬Ìµ¸ú
+$ EAI_PROTOCOL
+13 ²ò·è¤µ¤ì¤¿¥×¥í¥È¥³¥ë¤ÏÉÔÌÀ¤Ç¤¹
+$ EAI_OVERFLOW
+14 °ú¿ô¥Ð¥Ã¥Õ¥¡¥ª¡¼¥Ð¥Õ¥í¡¼
+$ 0
+32766 À®¸ù
+$ NL_MSGMAX
+32767 ÉÔÌÀ¤Ê¥¨¥é¡¼
diff --git a/lib/libc/nls/ko_KR.UTF-8.msg b/lib/libc/nls/ko_KR.UTF-8.msg
new file mode 100644
index 0000000..60e8a12
--- /dev/null
+++ b/lib/libc/nls/ko_KR.UTF-8.msg
@@ -0,0 +1,295 @@
+$ $FreeBSD$
+$
+$ Message catalog for ko_KR.UTF-8 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 ëª…ë ¹ì´ í—ˆìš©ë˜ì§€ 않습니다
+$ ENOENT
+2 íŒŒì¼ ë˜ëŠ” 디렉터리가 없습니다
+$ ESRCH
+3 존재하지 않는 프로세스입니다
+$ EINTR
+4 시스템 í˜¸ì¶œì´ ì¤‘ë‹¨ë˜ì—ˆìŠµë‹ˆë‹¤
+$ EIO
+5 입출력 ì—러입니다
+$ ENXIO
+6 장치가 설정ë˜ì§€ 않았습니다
+$ E2BIG
+7 ì¸ìžê°€ 너무 ê¹ë‹ˆë‹¤
+$ ENOEXEC
+8 실행 íŒŒì¼ í˜•ì‹ì´ 잘못ë˜ì—ˆìŠµë‹ˆë‹¤
+$ EBADF
+9 ìž˜ëª»ëœ íŒŒì¼ ë””ìŠ¤í¬ë¦½í„°ìž…니다
+$ ECHILD
+10 ìžì‹ 프로세스가 없습니다
+$ EDEADLK
+11 ìžì› ë°ë“œë½ì„ 중단하였습니다
+$ ENOMEM
+12 메모리를 할당할 수 없습니다
+$ EACCES
+13 ê¶Œí•œì´ ì—†ìŠµë‹ˆë‹¤
+$ EFAULT
+14 ìž˜ëª»ëœ ì£¼ì†Œê°€ 지정ë˜ì—ˆìŠµë‹ˆë‹¤
+$ ENOTBLK
+15 블럭 장치여야 합니다
+$ EBUSY
+16 장치가 사용 중입니다
+$ EEXIST
+17 파ì¼ì´ ì´ë¯¸ 존재합니다
+$ EXDEV
+18 다른 장치 ê°„ì˜ ì—°ê²°ìž…ë‹ˆë‹¤
+$ ENODEV
+19 ê·¸ 장치가 ì§€ì›í•˜ì§€ 않는 명령입니다
+$ ENOTDIR
+20 디렉터리가 아닙니다
+$ EISDIR
+21 디렉터리입니다
+$ EINVAL
+22 ì¸ìžê°€ 잘못ë˜ì—ˆìŠµë‹ˆë‹¤
+$ ENFILE
+23 ì‹œìŠ¤í…œì— íŒŒì¼ì´ 너무 ë§Žì´ ì—´ë ¤ìžˆìŠµë‹ˆë‹¤
+$ EMFILE
+24 파ì¼ì´ 너무 ë§Žì´ ì—´ë ¤ìžˆìŠµë‹ˆë‹¤
+$ ENOTTY
+25 장치가 ì§€ì›í•˜ì§€ 않는 ioctl입니다
+$ ETXTBSY
+26 Text 파ì¼ì´ 사용 중입니다
+$ EFBIG
+27 파ì¼ì´ 너무 í½ë‹ˆë‹¤
+$ ENOSPC
+28 ìž¥ì¹˜ì— ì—¬ìœ  ê³µê°„ì´ ë‚¨ì•„ìžˆì§€ 않습니다
+$ ESPIPE
+29 ìž˜ëª»ëœ íƒìƒ‰ìž…니다
+$ EROFS
+30 ì½ê¸° ì „ìš© íŒŒì¼ ì‹œìŠ¤í…œìž…ë‹ˆë‹¤
+$ EMLINK
+31 ì—°ê²°ì´ ë„ˆë¬´ 많습니다
+$ EPIPE
+32 파ì´í”„ê°€ ëŠì–´ì¡ŒìŠµë‹ˆë‹¤
+$ EDOM
+33 수치 ì¸ìžê°€ ì˜ì—­ì„ 벗어났습니다
+$ ERANGE
+34 결과가 너무 í½ë‹ˆë‹¤
+$ EAGAIN, EWOULDBLOCK
+35 ìžì›ì„ 잠시 사용할 수 없습니다
+$ EINPROGRESS
+36 ìž‘ì—…ì´ ì§„í–‰ 중입니다
+$ EALREADY
+37 ìž‘ì—…ì´ ì´ë¯¸ ì§„í–‰ 중입니다
+$ ENOTSOCK
+38 ì†Œì¼“ì´ ì•„ë‹Œ ê°ì²´ì— 대한 소켓 작업입니다
+$ EDESTADDRREQ
+39 목ì ì§€ 주소가 필요합니다
+$ EMSGSIZE
+40 메시지가 너무 ê¹ë‹ˆë‹¤
+$ EPROTOTYPE
+41 ì†Œì¼“ì— ì‚¬ìš©í•  수 없는 프로토콜 유형입니다
+$ ENOPROTOOPT
+42 í”„ë¡œí† ì½œì„ ì‚¬ìš©í•  수 없습니다
+$ EPROTONOSUPPORT
+43 ì§€ì›í•˜ì§€ 않는 프로토콜입니다
+$ ESOCKTNOSUPPORT
+44 ì§€ì›í•˜ì§€ 않는 ì¢…ë¥˜ì˜ ì†Œì¼“ìž…ë‹ˆë‹¤
+$ EOPNOTSUPP
+45 ì§€ì›ë˜ì§€ 않는 명령입니다
+$ EPFNOSUPPORT
+46 ì§€ì›ë˜ì§€ 않는 프로토콜군입니다
+$ EAFNOSUPPORT
+47 프로토콜군ì—서 ì§€ì›ë˜ì§€ 않는 주소군입니다
+$ EADDRINUSE
+48 ì´ë¯¸ 사용 ì¤‘ì¸ ì£¼ì†Œìž…ë‹ˆë‹¤
+$ EADDRNOTAVAIL
+49 요청한 주소를 할당할 수 없습니다
+$ ENETDOWN
+50 네트워í¬ê°€ 단절ë˜ì—ˆìŠµë‹ˆë‹¤
+$ ENETUNREACH
+51 네트워í¬ì— ë„달할 수 없습니다
+$ ENETRESET
+52 네트워í¬ê°€ 재설정ë˜ì–´ ì ‘ì†ì´ ëŠì–´ì¡ŒìŠµë‹ˆë‹¤
+$ ECONNABORTED
+53 소프트웨어ì ì¸ ì´ìœ ë¡œ ì—°ê²°ì´ ëŠì–´ì¡ŒìŠµë‹ˆë‹¤
+$ ECONNRESET
+54 ìƒëŒ€ë°©ì´ ì—°ê²°ì„ ëŠì—ˆìŠµë‹ˆë‹¤
+$ ENOBUFS
+55 ë²„í¼ ê³µê°„ì´ ëª¨ìžëžë‹ˆë‹¤
+$ EISCONN
+56 ì†Œì¼“ì´ ì´ë¯¸ ì—°ê²°ë˜ìžˆìŠµë‹ˆë‹¤
+$ ENOTCONN
+57 ì†Œì¼“ì´ ì—°ê²°ë˜ì–´ 있지 않습니다
+$ ESHUTDOWN
+58 ì†Œì¼“ì´ ì´ë¯¸ 중단ë˜ì–´, ë” ì´ìƒ 전송할 수 없습니다
+$ ETOOMANYREFS
+59 참조수가 너무 많아 나눌 수 없습니다
+$ ETIMEDOUT
+60 ì‹œê°„ì´ ë„ˆë¬´ ë§Žì´ ì§€ë‚˜ ìž‘ì—…ì´ ì¤‘ë‹¨ë˜ì—ˆìŠµë‹ˆë‹¤
+$ ECONNREFUSED
+61 ì ‘ì†ì´ ê±°ë¶€ë˜ì—ˆìŠµë‹ˆë‹¤
+$ ELOOP
+62 심볼릭 ì—°ê²°ì´ ë„ˆë¬´ ë§Žì´ ê±°ì³ì„œ ì—°ê²°ë˜ì—ˆìŠµë‹ˆë‹¤
+$ ENAMETOOLONG
+63 íŒŒì¼ ì´ë¦„ì´ ë„ˆë¬´ ê¹ë‹ˆë‹¤
+$ EHOSTDOWN
+64 호스트가 죽었습니다
+$ EHOSTUNREACH
+65 호스트로 갈 경로가 없습니다
+$ ENOTEMPTY
+66 디렉터리가 비어있지 않습니다
+$ EPROCLIM
+67 프로세스가 너무 많습니다
+$ EUSERS
+68 사용ìžê°€ 너무 많습니다
+$ EDQUOT
+69 ë””ìŠ¤í¬ í• ë‹¹ëŸ‰ì„ ì´ˆê³¼í–ˆìŠµë‹ˆë‹¤
+$ ESTALE
+70 ëŠì–´ì§„ NFS 연결입니다
+$ EREMOTE
+71 너무 ë§Žì€ ê²½ë¡œë¡œ ì›ê²©ì— 접근하였습니다
+$ EBADRPC
+72 RPC 구조체가 잘못ë˜ì—ˆìŠµë‹ˆë‹¤
+$ ERPCMISMATCH
+73 RPC ë²„ì „ì´ ë§žì§€ 않습니다
+$ EPROGUNAVAIL
+74 RPC í”„ë¡œê·¸ëž¨ì´ ì—†ìŠµë‹ˆë‹¤
+$ EPROGMISMATCH
+75 프로그램 ë²„ì „ì´ ë§žì§€ 않습니다
+$ EPROCUNAVAIL
+76 í”„ë¡œê·¸ëž¨ì— ì›ê²© 프로시저가 없습니다
+$ ENOLCK
+77 ìž ê¸ˆì´ ë¶ˆê°€ëŠ¥í•©ë‹ˆë‹¤
+$ ENOSYS
+78 구현ë˜ì§€ ì•Šì€ ê¸°ëŠ¥ìž…ë‹ˆë‹¤
+$ EFTYPE
+79 ìž˜ëª»ëœ íŒŒì¼ ì¢…ë¥˜ì´ê±°ë‚˜ 형ì‹ì´ 잘못ë습니다
+$ EAUTH
+80 ì¸ì¦ì´ 실패했습니다
+$ ENEEDAUTH
+81 ì¸ì¦ 서버가 지정ë˜ì§€ 않았습니다
+$ EIDRM
+82 ì‹ë³„ìžê°€ 제거ë˜ì—ˆìŠµë‹ˆë‹¤
+$ ENOMSG
+83 ìš”ì²­ëœ í˜•ì‹ì˜ 메시지는 없습니다
+$ EOVERFLOW
+84 ë°ì´í„° 형ì‹ì— ì €ìž¥í•˜ê¸°ì— ë„ˆë¬´ í° ê°’ìž…ë‹ˆë‹¤
+$ ECANCELED
+85 ìž‘ì—…ì´ ì·¨ì†Œë˜ì—ˆìŠµë‹ˆë‹¤
+$ EILSEQ
+86 ë°”ì´íЏ ë°°ì—´ì´ ìž˜ëª»ë˜ì—ˆìŠµë‹ˆë‹¤
+$ ENOATTR
+87 ì†ì„±ì„ ì°¾ì„ ìˆ˜ 없습니다
+$ EDOOFUS
+88 í”„ë¡œê·¸ëž¨ìƒ ì˜¤ë¥˜ìž…ë‹ˆë‹¤
+$ EBADMSG
+89 ìž˜ëª»ëœ ë©”ì‹œì§€ìž…ë‹ˆë‹¤
+$ EMULTIHOP
+90 ë©€í‹°í™‰ì´ ì‹œë„ë˜ì—ˆìŠµë‹ˆë‹¤
+$ ENOLINK
+91 ì—°ê²°ì´ ëŠê²¼ìŠµë‹ˆë‹¤
+$ EPROTO
+92 í”„ë¡œí† ì½œì´ ìž˜ëª»ë˜ì—ˆìŠµë‹ˆë‹¤
+$ ENOTCAPABLE
+93 ì ‘ê·¼ ëŠ¥ë ¥ì´ ì¶©ë¶„ì¹˜ 않습니다
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 ëŠê¹€
+$ SIGINT
+2 중단
+$ SIGQUIT
+3 종료
+$ SIGILL
+4 ìž˜ëª»ëœ ëª…ë ¹
+$ SIGTRAP
+5 Trace/BPT 트랩
+$ SIGABRT
+6 Abort 트랩
+$ SIGEMT
+7 EMT 트랩
+$ SIGFPE
+8 ë¶€ë™ì†Œìˆ˜ì  ì—°ì‚° 예외
+$ SIGKILL
+9 강제종료
+$ SIGBUS
+10 버스 오류
+$ SIGSEGV
+11 세그먼테ì´ì…˜ 오류
+$ SIGSYS
+12 ìž˜ëª»ëœ ì‹œìŠ¤í…œ 호출
+$ SIGPIPE
+13 파ì´í”„ê°€ ëŠê¹€
+$ SIGALRM
+14 시간 경보
+$ SIGTERM
+15 종료ë¨
+$ SIGURG
+16 긴급 I/O 조건
+$ SIGSTOP
+17 ì¼ì‹œì •ì§€ (시그ë„)
+$ SIGTSTP
+18 ì¼ì‹œì •ì§€
+$ SIGCONT
+19 계ì†
+$ SIGCHLD
+20 ìžì‹ 프로세스 종료
+$ SIGTTIN
+21 ì •ì§€ (í„°ë¯¸ë„ ìž…ë ¥)
+$ SIGTTOU
+22 ì •ì§€ (í„°ë¯¸ë„ ì¶œë ¥)
+$ SIGIO
+23 I/O 가능
+$ SIGXCPU
+24 CPU 사용 시간 초과
+$ SIGXFSZ
+25 íŒŒì¼ ìš©ëŸ‰ 제한 초과
+$ SIGVTALRM
+26 ê°€ìƒ íƒ€ì´ë¨¸ 만료
+$ SIGPROF
+27 프로파ì¼ë§ 타ì´ë¨¸ 만료
+$ SIGWINCH
+28 ì°½ í¬ê¸° 변경
+$ SIGINFO
+29 정보 요청
+$ SIGUSR1
+30 ì‚¬ìš©ìž ì •ì˜ ì‹œê·¸ë„ 1
+$ SIGUSR2
+31 ì‚¬ìš©ìž ì •ì˜ ì‹œê·¸ë„ 2
+$
+$ gai_strerror() support catalog
+$
+$set 3
+$ 1 (obsolete)
+1 호스트 ì´ë¦„ì´ ì§€ì›í•˜ì§€ 않는 주소군입니다
+$ EAI_AGAIN
+2 주소 ë³€í™˜ì— ì¼ì‹œì ìœ¼ë¡œ 실패했습니다
+$ EAI_BADFLAGS
+3 ìž˜ëª»ëœ ai_flags입니다
+$ EAI_FAIL
+4 주소 ë³€í™˜ì— ì™„ì „ížˆ 실패했습니다
+$ EAI_FAMILY
+5 ì§€ì›ë˜ì§€ 않는 ai_family입니다
+$ EAI_MEMORY
+6 메모리 í• ë‹¹ì— ì‹¤íŒ¨í–ˆìŠµë‹ˆë‹¤
+$ 7 (obsolete)
+7 호스트 ì´ë¦„ê³¼ ì¼ì¹˜í•˜ëŠ” 주소가 없습니다
+$ EAI_NONAME
+8 호스트 ì´ë¦„ ë˜ëŠ” 서비스 ì´ë¦„ì´ ì§€ì •ë˜ì§€ 않았거나 알 수 없습니다
+$ EAI_SERVICE
+9 서비스 ì´ë¦„ì€ ai_socktypeì—서 ì§€ì›ë˜ì§€ 않습니다
+$ EAI_SOCKTYPE
+10 ì§€ì›ë˜ì§€ 않는 ai_socktype입니다
+$ EAI_SYSTEM
+11 시스템 오류가 errnoì— ë°˜í™˜ë˜ì—ˆìŠµë‹ˆë‹¤
+$ EAI_BADHINTS
+12 ìž˜ëª»ëœ hints입니다
+$ EAI_PROTOCOL
+13 알 수 없는 í”„ë¡œí† ì½œì´ ë³€í™˜ë˜ì—ˆìŠµë‹ˆë‹¤
+$ EAI_OVERFLOW
+14 ì¸ìž ë²„í¼ ê³µê°„ì´ ëª¨ìžëžë‹ˆë‹¤
+$ 0
+32766 성공
+$ NL_MSGMAX
+32767 알 수 없는 오류
diff --git a/lib/libc/nls/ko_KR.eucKR.msg b/lib/libc/nls/ko_KR.eucKR.msg
new file mode 100644
index 0000000..bb1fa30
--- /dev/null
+++ b/lib/libc/nls/ko_KR.eucKR.msg
@@ -0,0 +1,295 @@
+$ $FreeBSD$
+$
+$ Message catalog for ko_KR.eucKR locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 ¸í·ÉÀÌ Çã¿ëµÇÁö ¾Ê½À´Ï´Ù
+$ ENOENT
+2 ÆÄÀÏ ¶Ç´Â µð·ºÅ͸®°¡ ¾ø½À´Ï´Ù
+$ ESRCH
+3 Á¸ÀçÇÏÁö ¾Ê´Â ÇÁ·Î¼¼½ºÀÔ´Ï´Ù
+$ EINTR
+4 ½Ã½ºÅÛ È£ÃâÀÌ ÁߴܵǾú½À´Ï´Ù
+$ EIO
+5 ÀÔÃâ·Â ¿¡·¯ÀÔ´Ï´Ù
+$ ENXIO
+6 ÀåÄ¡°¡ ¼³Á¤µÇÁö ¾Ê¾Ò½À´Ï´Ù
+$ E2BIG
+7 ÀÎÀÚ°¡ ³Ê¹« ±é´Ï´Ù
+$ ENOEXEC
+8 ½ÇÇà ÆÄÀÏ Çü½ÄÀÌ À߸øµÇ¾ú½À´Ï´Ù
+$ EBADF
+9 À߸øµÈ ÆÄÀÏ µð½ºÅ©¸³ÅÍÀÔ´Ï´Ù
+$ ECHILD
+10 ÀÚ½Ä ÇÁ·Î¼¼½º°¡ ¾ø½À´Ï´Ù
+$ EDEADLK
+11 ÀÚ¿ø µ¥µå¶ôÀ» Áß´ÜÇÏ¿´½À´Ï´Ù
+$ ENOMEM
+12 ¸Þ¸ð¸®¸¦ ÇÒ´çÇÒ ¼ö ¾ø½À´Ï´Ù
+$ EACCES
+13 ±ÇÇÑÀÌ ¾ø½À´Ï´Ù
+$ EFAULT
+14 À߸øµÈ ÁÖ¼Ò°¡ ÁöÁ¤µÇ¾ú½À´Ï´Ù
+$ ENOTBLK
+15 ºí·° ÀåÄ¡¿©¾ß ÇÕ´Ï´Ù
+$ EBUSY
+16 ÀåÄ¡°¡ »ç¿ë ÁßÀÔ´Ï´Ù
+$ EEXIST
+17 ÆÄÀÏÀÌ ÀÌ¹Ì Á¸ÀçÇÕ´Ï´Ù
+$ EXDEV
+18 ´Ù¸¥ ÀåÄ¡ °£ÀÇ ¿¬°áÀÔ´Ï´Ù
+$ ENODEV
+19 ±× ÀåÄ¡°¡ Áö¿øÇÏÁö ¾Ê´Â ¸í·ÉÀÔ´Ï´Ù
+$ ENOTDIR
+20 µð·ºÅ͸®°¡ ¾Æ´Õ´Ï´Ù
+$ EISDIR
+21 µð·ºÅ͸®ÀÔ´Ï´Ù
+$ EINVAL
+22 ÀÎÀÚ°¡ À߸øµÇ¾ú½À´Ï´Ù
+$ ENFILE
+23 ½Ã½ºÅÛ¿¡ ÆÄÀÏÀÌ ³Ê¹« ¸¹ÀÌ ¿­·ÁÀÖ½À´Ï´Ù
+$ EMFILE
+24 ÆÄÀÏÀÌ ³Ê¹« ¸¹ÀÌ ¿­·ÁÀÖ½À´Ï´Ù
+$ ENOTTY
+25 ÀåÄ¡°¡ Áö¿øÇÏÁö ¾Ê´Â ioctlÀÔ´Ï´Ù
+$ ETXTBSY
+26 Text ÆÄÀÏÀÌ »ç¿ë ÁßÀÔ´Ï´Ù
+$ EFBIG
+27 ÆÄÀÏÀÌ ³Ê¹« Å®´Ï´Ù
+$ ENOSPC
+28 ÀåÄ¡¿¡ ¿©À¯ °ø°£ÀÌ ³²¾ÆÀÖÁö ¾Ê½À´Ï´Ù
+$ ESPIPE
+29 À߸øµÈ Ž»öÀÔ´Ï´Ù
+$ EROFS
+30 Àбâ Àü¿ë ÆÄÀÏ ½Ã½ºÅÛÀÔ´Ï´Ù
+$ EMLINK
+31 ¿¬°áÀÌ ³Ê¹« ¸¹½À´Ï´Ù
+$ EPIPE
+32 ÆÄÀÌÇÁ°¡ ²÷¾îÁ³½À´Ï´Ù
+$ EDOM
+33 ¼öÄ¡ ÀÎÀÚ°¡ ¿µ¿ªÀ» ¹þ¾î³µ½À´Ï´Ù
+$ ERANGE
+34 °á°ú°¡ ³Ê¹« Å®´Ï´Ù
+$ EAGAIN, EWOULDBLOCK
+35 ÀÚ¿øÀ» Àá½Ã »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù
+$ EINPROGRESS
+36 ÀÛ¾÷ÀÌ ÁøÇà ÁßÀÔ´Ï´Ù
+$ EALREADY
+37 ÀÛ¾÷ÀÌ ÀÌ¹Ì ÁøÇà ÁßÀÔ´Ï´Ù
+$ ENOTSOCK
+38 ¼ÒÄÏÀÌ ¾Æ´Ñ °´Ã¼¿¡ ´ëÇÑ ¼ÒÄÏ ÀÛ¾÷ÀÔ´Ï´Ù
+$ EDESTADDRREQ
+39 ¸ñÀûÁö ÁÖ¼Ò°¡ ÇÊ¿äÇÕ´Ï´Ù
+$ EMSGSIZE
+40 ¸Þ½ÃÁö°¡ ³Ê¹« ±é´Ï´Ù
+$ EPROTOTYPE
+41 ¼ÒÄÏ¿¡ »ç¿ëÇÒ ¼ö ¾ø´Â ÇÁ·ÎÅäÄÝ À¯ÇüÀÔ´Ï´Ù
+$ ENOPROTOOPT
+42 ÇÁ·ÎÅäÄÝÀ» »ç¿ëÇÒ ¼ö ¾ø½À´Ï´Ù
+$ EPROTONOSUPPORT
+43 Áö¿øÇÏÁö ¾Ê´Â ÇÁ·ÎÅäÄÝÀÔ´Ï´Ù
+$ ESOCKTNOSUPPORT
+44 Áö¿øÇÏÁö ¾Ê´Â Á¾·ùÀÇ ¼ÒÄÏÀÔ´Ï´Ù
+$ EOPNOTSUPP
+45 Áö¿øµÇÁö ¾Ê´Â ¸í·ÉÀÔ´Ï´Ù
+$ EPFNOSUPPORT
+46 Áö¿øµÇÁö ¾Ê´Â ÇÁ·ÎÅäÄݱºÀÔ´Ï´Ù
+$ EAFNOSUPPORT
+47 ÇÁ·ÎÅäÄݱº¿¡¼­ Áö¿øµÇÁö ¾Ê´Â ÁÖ¼Ò±ºÀÔ´Ï´Ù
+$ EADDRINUSE
+48 ÀÌ¹Ì »ç¿ë ÁßÀÎ ÁÖ¼ÒÀÔ´Ï´Ù
+$ EADDRNOTAVAIL
+49 ¿äûÇÑ ÁÖ¼Ò¸¦ ÇÒ´çÇÒ ¼ö ¾ø½À´Ï´Ù
+$ ENETDOWN
+50 ³×Æ®¿öÅ©°¡ ´ÜÀýµÇ¾ú½À´Ï´Ù
+$ ENETUNREACH
+51 ³×Æ®¿öÅ©¿¡ µµ´ÞÇÒ ¼ö ¾ø½À´Ï´Ù
+$ ENETRESET
+52 ³×Æ®¿öÅ©°¡ Àç¼³Á¤µÇ¾î Á¢¼ÓÀÌ ²÷¾îÁ³½À´Ï´Ù
+$ ECONNABORTED
+53 ¼ÒÇÁÆ®¿þ¾îÀûÀÎ ÀÌÀ¯·Î ¿¬°áÀÌ ²÷¾îÁ³½À´Ï´Ù
+$ ECONNRESET
+54 »ó´ë¹æÀÌ ¿¬°áÀ» ²÷¾ú½À´Ï´Ù
+$ ENOBUFS
+55 ¹öÆÛ °ø°£ÀÌ ¸ðÀÚ¶ø´Ï´Ù
+$ EISCONN
+56 ¼ÒÄÏÀÌ ÀÌ¹Ì ¿¬°áµÇÀÖ½À´Ï´Ù
+$ ENOTCONN
+57 ¼ÒÄÏÀÌ ¿¬°áµÇ¾î ÀÖÁö ¾Ê½À´Ï´Ù
+$ ESHUTDOWN
+58 ¼ÒÄÏÀÌ ÀÌ¹Ì ÁߴܵǾî, ´õ ÀÌ»ó Àü¼ÛÇÒ ¼ö ¾ø½À´Ï´Ù
+$ ETOOMANYREFS
+59 ÂüÁ¶¼ö°¡ ³Ê¹« ¸¹¾Æ ³ª´­ ¼ö ¾ø½À´Ï´Ù
+$ ETIMEDOUT
+60 ½Ã°£ÀÌ ³Ê¹« ¸¹ÀÌ Áö³ª ÀÛ¾÷ÀÌ ÁߴܵǾú½À´Ï´Ù
+$ ECONNREFUSED
+61 Á¢¼ÓÀÌ °ÅºÎµÇ¾ú½À´Ï´Ù
+$ ELOOP
+62 ½Éº¼¸¯ ¿¬°áÀÌ ³Ê¹« ¸¹ÀÌ °ÅÃļ­ ¿¬°áµÇ¾ú½À´Ï´Ù
+$ ENAMETOOLONG
+63 ÆÄÀÏ À̸§ÀÌ ³Ê¹« ±é´Ï´Ù
+$ EHOSTDOWN
+64 È£½ºÆ®°¡ Á×¾ú½À´Ï´Ù
+$ EHOSTUNREACH
+65 È£½ºÆ®·Î °¥ °æ·Î°¡ ¾ø½À´Ï´Ù
+$ ENOTEMPTY
+66 µð·ºÅ͸®°¡ ºñ¾îÀÖÁö ¾Ê½À´Ï´Ù
+$ EPROCLIM
+67 ÇÁ·Î¼¼½º°¡ ³Ê¹« ¸¹½À´Ï´Ù
+$ EUSERS
+68 »ç¿ëÀÚ°¡ ³Ê¹« ¸¹½À´Ï´Ù
+$ EDQUOT
+69 µð½ºÅ© ÇÒ´ç·®À» ÃʰúÇß½À´Ï´Ù
+$ ESTALE
+70 ²÷¾îÁø NFS ¿¬°áÀÔ´Ï´Ù
+$ EREMOTE
+71 ³Ê¹« ¸¹Àº °æ·Î·Î ¿ø°Ý¿¡ Á¢±ÙÇÏ¿´½À´Ï´Ù
+$ EBADRPC
+72 RPC ±¸Á¶Ã¼°¡ À߸øµÇ¾ú½À´Ï´Ù
+$ ERPCMISMATCH
+73 RPC ¹öÀüÀÌ ¸ÂÁö ¾Ê½À´Ï´Ù
+$ EPROGUNAVAIL
+74 RPC ÇÁ·Î±×·¥ÀÌ ¾ø½À´Ï´Ù
+$ EPROGMISMATCH
+75 ÇÁ·Î±×·¥ ¹öÀüÀÌ ¸ÂÁö ¾Ê½À´Ï´Ù
+$ EPROCUNAVAIL
+76 ÇÁ·Î±×·¥¿¡ ¿ø°Ý ÇÁ·Î½ÃÀú°¡ ¾ø½À´Ï´Ù
+$ ENOLCK
+77 Àá±ÝÀÌ ºÒ°¡´ÉÇÕ´Ï´Ù
+$ ENOSYS
+78 ±¸ÇöµÇÁö ¾ÊÀº ±â´ÉÀÔ´Ï´Ù
+$ EFTYPE
+79 À߸øµÈ ÆÄÀÏ Á¾·ùÀ̰ųª Çü½ÄÀÌ À߸øµÆ½À´Ï´Ù
+$ EAUTH
+80 ÀÎÁõÀÌ ½ÇÆÐÇß½À´Ï´Ù
+$ ENEEDAUTH
+81 ÀÎÁõ ¼­¹ö°¡ ÁöÁ¤µÇÁö ¾Ê¾Ò½À´Ï´Ù
+$ EIDRM
+82 ½Äº°ÀÚ°¡ Á¦°ÅµÇ¾ú½À´Ï´Ù
+$ ENOMSG
+83 ¿äûµÈ Çü½ÄÀÇ ¸Þ½ÃÁö´Â ¾ø½À´Ï´Ù
+$ EOVERFLOW
+84 µ¥ÀÌÅÍ Çü½Ä¿¡ ÀúÀåÇϱ⿡ ³Ê¹« Å« °ªÀÔ´Ï´Ù
+$ ECANCELED
+85 ÀÛ¾÷ÀÌ Ãë¼ÒµÇ¾ú½À´Ï´Ù
+$ EILSEQ
+86 ¹ÙÀÌÆ® ¹è¿­ÀÌ À߸øµÇ¾ú½À´Ï´Ù
+$ ENOATTR
+87 ¼Ó¼ºÀ» ãÀ» ¼ö ¾ø½À´Ï´Ù
+$ EDOOFUS
+88 ÇÁ·Î±×·¥»ó ¿À·ùÀÔ´Ï´Ù
+$ EBADMSG
+89 À߸øµÈ ¸Þ½ÃÁöÀÔ´Ï´Ù
+$ EMULTIHOP
+90 ¸ÖƼȩÀÌ ½ÃµµµÇ¾ú½À´Ï´Ù
+$ ENOLINK
+91 ¿¬°áÀÌ ²÷°å½À´Ï´Ù
+$ EPROTO
+92 ÇÁ·ÎÅäÄÝÀÌ À߸øµÇ¾ú½À´Ï´Ù
+$ ENOTCAPABLE
+93 Á¢±Ù ´É·ÂÀÌ ÃæºÐÄ¡ ¾Ê½À´Ï´Ù
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 ²÷±è
+$ SIGINT
+2 Áß´Ü
+$ SIGQUIT
+3 Á¾·á
+$ SIGILL
+4 À߸øµÈ ¸í·É
+$ SIGTRAP
+5 Trace/BPT Æ®·¦
+$ SIGABRT
+6 Abort Æ®·¦
+$ SIGEMT
+7 EMT Æ®·¦
+$ SIGFPE
+8 ºÎµ¿¼Ò¼öÁ¡ ¿¬»ê ¿¹¿Ü
+$ SIGKILL
+9 °­Á¦Á¾·á
+$ SIGBUS
+10 ¹ö½º ¿À·ù
+$ SIGSEGV
+11 ¼¼±×¸ÕÅ×ÀÌ¼Ç ¿À·ù
+$ SIGSYS
+12 À߸øµÈ ½Ã½ºÅÛ È£Ãâ
+$ SIGPIPE
+13 ÆÄÀÌÇÁ°¡ ²÷±è
+$ SIGALRM
+14 ½Ã°£ °æº¸
+$ SIGTERM
+15 Á¾·áµÊ
+$ SIGURG
+16 ±ä±Þ I/O Á¶°Ç
+$ SIGSTOP
+17 ÀϽÃÁ¤Áö (½Ã±×³Î)
+$ SIGTSTP
+18 ÀϽÃÁ¤Áö
+$ SIGCONT
+19 °è¼Ó
+$ SIGCHLD
+20 ÀÚ½Ä ÇÁ·Î¼¼½º Á¾·á
+$ SIGTTIN
+21 Á¤Áö (Å͹̳ΠÀÔ·Â)
+$ SIGTTOU
+22 Á¤Áö (Å͹̳ΠÃâ·Â)
+$ SIGIO
+23 I/O °¡´É
+$ SIGXCPU
+24 CPU »ç¿ë ½Ã°£ Ãʰú
+$ SIGXFSZ
+25 ÆÄÀÏ ¿ë·® Á¦ÇÑ Ãʰú
+$ SIGVTALRM
+26 °¡»ó ŸÀÌ¸Ó ¸¸·á
+$ SIGPROF
+27 ÇÁ·ÎÆÄÀϸµ ŸÀÌ¸Ó ¸¸·á
+$ SIGWINCH
+28 â Å©±â º¯°æ
+$ SIGINFO
+29 Á¤º¸ ¿äû
+$ SIGUSR1
+30 »ç¿ëÀÚ Á¤ÀÇ ½Ã±×³Î 1
+$ SIGUSR2
+31 »ç¿ëÀÚ Á¤ÀÇ ½Ã±×³Î 2
+$
+$ gai_strerror() support catalog
+$
+$set 3
+$ 1 (obsolete)
+1 È£½ºÆ® À̸§ÀÌ Áö¿øÇÏÁö ¾Ê´Â ÁÖ¼Ò±ºÀÔ´Ï´Ù
+$ EAI_AGAIN
+2 ÁÖ¼Ò º¯È¯¿¡ ÀϽÃÀûÀ¸·Î ½ÇÆÐÇß½À´Ï´Ù
+$ EAI_BADFLAGS
+3 À߸øµÈ ai_flagsÀÔ´Ï´Ù
+$ EAI_FAIL
+4 ÁÖ¼Ò º¯È¯¿¡ ¿ÏÀüÈ÷ ½ÇÆÐÇß½À´Ï´Ù
+$ EAI_FAMILY
+5 Áö¿øµÇÁö ¾Ê´Â ai_familyÀÔ´Ï´Ù
+$ EAI_MEMORY
+6 ¸Þ¸ð¸® ÇÒ´ç¿¡ ½ÇÆÐÇß½À´Ï´Ù
+$ 7 (obsolete)
+7 È£½ºÆ® À̸§°ú ÀÏÄ¡ÇÏ´Â ÁÖ¼Ò°¡ ¾ø½À´Ï´Ù
+$ EAI_NONAME
+8 È£½ºÆ® À̸§ ¶Ç´Â ¼­ºñ½º À̸§ÀÌ ÁöÁ¤µÇÁö ¾Ê¾Ò°Å³ª ¾Ë ¼ö ¾ø½À´Ï´Ù
+$ EAI_SERVICE
+9 ¼­ºñ½º À̸§Àº ai_socktype¿¡¼­ Áö¿øµÇÁö ¾Ê½À´Ï´Ù
+$ EAI_SOCKTYPE
+10 Áö¿øµÇÁö ¾Ê´Â ai_socktypeÀÔ´Ï´Ù
+$ EAI_SYSTEM
+11 ½Ã½ºÅÛ ¿À·ù°¡ errno¿¡ ¹ÝȯµÇ¾ú½À´Ï´Ù
+$ EAI_BADHINTS
+12 À߸øµÈ hintsÀÔ´Ï´Ù
+$ EAI_PROTOCOL
+13 ¾Ë ¼ö ¾ø´Â ÇÁ·ÎÅäÄÝÀÌ º¯È¯µÇ¾ú½À´Ï´Ù
+$ EAI_OVERFLOW
+14 ÀÎÀÚ ¹öÆÛ °ø°£ÀÌ ¸ðÀÚ¶ø´Ï´Ù
+$ 0
+32766 ¼º°ø
+$ NL_MSGMAX
+32767 ¾Ë ¼ö ¾ø´Â ¿À·ù
diff --git a/lib/libc/nls/mn_MN.UTF-8.msg b/lib/libc/nls/mn_MN.UTF-8.msg
new file mode 100644
index 0000000..29ab4c1
--- /dev/null
+++ b/lib/libc/nls/mn_MN.UTF-8.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for mn_MN.UTF-8 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 ҮйлдÑл зөвшөөрөгдөхгүй
+$ ENOENT
+2 Тийм файл ÑÑвÑл Ñан алга
+$ ESRCH
+3 Тийм процеÑÑ Ð±Ð°Ð¹Ñ…Ð³Ò¯Ð¹
+$ EINTR
+4 СиÑтемийн таÑалдÑан дуудлага
+$ EIO
+5 Оролт/гаралтын алдаа
+$ ENXIO
+6 Төхөөрөмж тохируулагдаагүй
+$ E2BIG
+7 Дагавар өгөгдлийн жагÑаалт Ñ…ÑÑ‚Ñрхий урт
+$ ENOEXEC
+8 Exec Ñ…ÑлбÑршилтийн алдаа
+$ EBADF
+9 Файлын буруу тодорхойлогч
+$ ECHILD
+10 ХүүхÑд процеÑÑ Ð°Ð»Ð³Ð°
+$ EDEADLK
+11 Эх Ò¯Ò¯ÑвÑрийн Ð³Ð°Ñ†Ð°Ð°Ð½Ð°Ð°Ñ Ð·Ð°Ð¹Ð»ÑхийÑÑн
+$ ENOMEM
+12 Санах ойд зай байрлуулж чадахгүй байна
+$ EACCES
+13 Ð—Ó©Ð²ÑˆÓ©Ó©Ñ€Ó©Ñ…Ó©Ó©Ñ Ñ‚Ð°Ñ‚Ð³Ð°Ð»Ð·Ñан
+$ EFAULT
+14 Буруу хаÑг
+$ ENOTBLK
+15 Блок төхөөрөмж шаардагдÑан
+$ EBUSY
+16 Төхөөрөмж завгүй
+$ EEXIST
+17 Файл байна
+$ EXDEV
+18 Төхөөрөмж хоорондын холбооÑ
+$ ENODEV
+19 Үйлдлийг төхөөрөмж дÑмжÑÑгүй
+$ ENOTDIR
+20 Сан биш
+$ EISDIR
+21 Сан мөн
+$ EINVAL
+22 Дагавар өгөгдөл буруу
+$ ENFILE
+23 СиÑтемд Ñ…ÑÑ‚Ñрхий олон нÑÑлттÑй файл байна
+$ EMFILE
+24 Ð¥ÑÑ‚Ñрхий олон нÑÑлттÑй файл байна
+$ ENOTTY
+25 ТөхөөрөмжтÑй тохирохгүй ioctl үйлдÑл
+$ ETXTBSY
+26 ТекÑÑ‚ файл завгүй
+$ EFBIG
+27 Файл Ñ…ÑÑ‚Ñрхий том
+$ ENOSPC
+28 Төхөөрөмж дÑÑÑ€ зай үлдÑÑнгүй
+$ ESPIPE
+29 Хайлт буруу
+$ EROFS
+30 Зөвхөн-уншигдах файлын ÑиÑтем
+$ EMLINK
+31 Ð¥ÑÑ‚Ñрхий олон Ñ…Ð¾Ð»Ð±Ð¾Ð¾Ñ Ð±Ð°Ð¹Ð½Ð°
+$ EPIPE
+32 ЭвдÑрхий хоолой
+$ EDOM
+33 Тоон дагавар өгөгдөл Ñ‚Ð°Ð»Ð±Ð°Ñ€Ð°Ð°Ñ Ð³Ð°Ð´Ð½Ð° байна
+$ ERANGE
+34 Үр дүн Ñ…ÑÑ‚Ñрхий том
+$ EAGAIN, EWOULDBLOCK
+35 Эх Ò¯Ò¯ÑвÑÑ€ түр зуур боломжгүй байна
+$ EINPROGRESS
+36 ҮйлдÑл одоо хийгдÑж байна
+$ EALREADY
+37 ҮйлдÑл аль Ñ…Ñдийн хийгдÑж байна
+$ ENOTSOCK
+38 Сокет Ð±ÑƒÑ Ð·Ò¯Ð¹Ð» дÑÑÑ€ Ñокет үйлдÑл
+$ EDESTADDRREQ
+39 Очих хаÑг шаардагдÑан
+$ EMSGSIZE
+40 Ð—ÑƒÑ€Ð²Ð°Ñ Ð¼ÑдÑÑ Ñ…ÑÑ‚Ñрхий урт
+$ EPROTOTYPE
+41 Сокетийн хувьд протокол буруу төрлийнх байна
+$ ENOPROTOOPT
+42 Протокол байхгүй
+$ EPROTONOSUPPORT
+43 Протокол дÑмжигдÑÑгүй
+$ ESOCKTNOSUPPORT
+44 Сокетийн төрөл дÑмжигдÑÑгүй
+$ EOPNOTSUPP
+45 ҮйлдÑл дÑмжигдÑÑгүй
+$ EPFNOSUPPORT
+46 Протоколын гÑÑ€ бүл дÑмжигдÑÑгүй
+$ EAFNOSUPPORT
+47 ХаÑгийн гÑÑ€ бүлийг протоколын гÑÑ€ бүл дÑмжÑÑгүй
+$ EADDRINUSE
+48 ХаÑг ашиглагдаж байна
+$ EADDRNOTAVAIL
+49 Ð¥Ò¯ÑÑÑн хаÑгийг өгч чадахгүй
+$ ENETDOWN
+50 СүлжÑÑ ÑƒÐ½Ð°Ñан байна
+$ ENETUNREACH
+51 СүлжÑÑнд хүрÑÑ… боломжгүй
+$ ENETRESET
+52 Салгалт хийгдÑÑ…Ñд ÑүлжÑÑ Ñ…Ð¾Ð»Ð±Ð¾Ð»Ñ‚Ñ‹Ð³ унагалаа
+$ ECONNABORTED
+53 Програм Ñ…Ð°Ð½Ð³Ð°Ð¼Ð¶Ð°Ð°Ñ Ð±Ð¾Ð»Ð¶ холболт зогÑлоо
+$ ECONNRESET
+54 Холболтыг харилцагч Ñалгалаа
+$ ENOBUFS
+55 Буфферийн зай байхгүй
+$ EISCONN
+56 Сокет аль Ñ…Ñдийн холбогдÑон
+$ ENOTCONN
+57 Сокет холбогдоогүй
+$ ESHUTDOWN
+58 Сокет унтарÑны дараа илгÑÑж чадахгүй
+$ ETOOMANYREFS
+59 Ð¥ÑÑ‚Ñрхий их хамаарлууд байна: залгаж чадахгүй
+$ ETIMEDOUT
+60 Үйлдлийн хугацаа дууÑÑан
+$ ECONNREFUSED
+61 Холболт Ñ‚Ð¾Ð³Ñ‚Ð¾Ð¾Ñ…Ð¾Ð¾Ñ Ñ‚Ð°Ñ‚Ð³Ð°Ð»Ð·Ð»Ð°Ð°
+$ ELOOP
+62 ТÑмдÑгт холбооÑуудын түвшин Ñ…ÑÑ‚Ñрхий олон байна
+$ ENAMETOOLONG
+63 Файлын нÑÑ€ Ñ…ÑÑ‚Ñрхий урт
+$ EHOSTDOWN
+64 Төв компьютер зогÑÑон байна
+$ EHOSTUNREACH
+65 Төв компьютер Ñ€Ò¯Ò¯ чиглүүлÑлт байхгүй
+$ ENOTEMPTY
+66 Сан хооÑон биш
+$ EPROCLIM
+67 Ð¥ÑÑ‚Ñрхий олон үйлдÑл байна
+$ EUSERS
+68 Ð¥ÑÑ‚Ñрхий олон Ñ…ÑÑ€ÑглÑгч байна
+$ EDQUOT
+69 ДиÑкийн Ñ…Ñзгаар Ñ…ÑмжÑÑ Ñ…ÑÑ‚ÑÑ€ÑÑн
+$ ESTALE
+70 ХуучирÑан NFS файлын жолоо
+$ EREMOTE
+71 Зам Ñ…ÑÑ‚Ñрхий алÑлагдÑан түвшинтÑй байна
+$ EBADRPC
+2 RPC бүтÑц буруу
+$ ERPCMISMATCH
+73 RPC-ийн хувилбар буруу
+$ EPROGUNAVAIL
+74 RPC програм байхгүй
+$ EPROGMISMATCH
+75 Програмын хувилбар буруу
+$ EPROCUNAVAIL
+76 Програмын хувьд процедур буруу
+$ ENOLCK
+77 ТүгжÑÑ Ð±Ð°Ð¹Ñ…Ð³Ò¯Ð¹
+$ ENOSYS
+78 Функц гүйцÑтгÑгдÑÑгүй
+$ EFTYPE
+79 Файлын төрөл ÑÑвÑл Ñ…ÑлбÑршилт тохироогүй
+$ EAUTH
+80 ÐÑвтрүүлÑÑ… алдаа
+$ ENEEDAUTH
+81 ÐÑвтррүүлÑгч Ñ…ÑÑ€ÑгтÑй
+$ EIDRM
+82 Танигч уÑтгагдÑан
+$ ENOMSG
+83 Ð¥Ò¯ÑÑÑн төрлийн Ð·ÑƒÑ€Ð²Ð°Ñ Ð¼ÑдÑÑ Ð±Ð°Ð¹Ñ…Ð³Ò¯Ð¹
+$ EOVERFLOW
+84 Утга нь өгөгдлийн төрөлд хадгалагдаж болохооргүй Ñ…ÑÑ‚Ñрхий том байна
+$ ECANCELED
+85 ҮйлдÑл зогÑоогдÑон
+$ EILSEQ
+86 Байтын дараалал буруу
+$ ENOATTR
+87 Ðтрибут олдÑонгүй
+$ EDOOFUS
+88 Програмчлалын алдаа
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 ЗогÑоох (Hangup)
+$ SIGINT
+2 ТаÑалдал
+$ SIGQUIT
+3 Гарах
+$ SIGILL
+4 Буруу заавар
+$ SIGTRAP
+5 Мөр/BPT занга
+$ SIGABRT
+6 ТаÑлан зогÑоох занга
+$ SIGEMT
+7 EMT занга
+$ SIGFPE
+8 Хөвөгч цÑгийн онцгой алдаа
+$ SIGKILL
+9 ХөнөөÑөн
+$ SIGBUS
+10 Шугамын алдаа
+$ SIGSEGV
+11 Сегментийн гÑмтÑл
+$ SIGSYS
+12 СиÑтемийн буруу дуудлага
+$ SIGPIPE
+13 ЭвдÑрхий хоолой
+$ SIGALRM
+14 СÑрүүлÑгт цаг
+$ SIGTERM
+15 ТөгÑÑөн
+$ SIGURG
+16 Яаралтай I/O нөхцөл
+$ SIGSTOP
+17 Түр зогÑÑон (дохио)
+$ SIGTSTP
+18 Түр зогÑÑон
+$ SIGCONT
+19 ҮргÑлжилÑÑн
+$ SIGCHLD
+20 ХүүхÑд процеÑÑ Ð³Ð°Ñ€Ñан
+$ SIGTTIN
+21 ЗогÑÑон (tty оролт)
+$ SIGTTOU
+22 ЗогÑÑон (tty гаралт)
+$ SIGIO
+23 I/O боломжтой
+$ SIGXCPU
+24 CPU-ийн хугацааны Ñ…Ñзгаар Ñ…ÑÑ‚ÑÑ€ÑÑн
+$ SIGXFSZ
+25 Файлын Ñ…ÑмжÑÑний Ñ…Ñзгаар Ñ…ÑÑ‚ÑÑ€ÑÑн
+$ SIGVTALRM
+26 Виртуал цаг Ñ…Ñмжигчийн хугацаа дууÑÑан
+$ SIGPROF
+27 Профил хийх цаг Ñ…Ñмжигчийн хугацаа дууÑÑан
+$ SIGWINCH
+28 Цонхны Ñ…ÑмжÑÑний өөрчлөлт
+$ SIGINFO
+29 МÑдÑÑллийн Ñ…Ò¯ÑÑлт
+$ SIGUSR1
+30 Ð¥ÑÑ€ÑглÑгчийн тодорхойлÑон дохио 1
+$ SIGUSR2
+31 Ð¥ÑÑ€ÑглÑгчийн тодорхойлÑон дохио 2
diff --git a/lib/libc/nls/msgcat.c b/lib/libc/nls/msgcat.c
new file mode 100644
index 0000000..4532e90
--- /dev/null
+++ b/lib/libc/nls/msgcat.c
@@ -0,0 +1,447 @@
+/***********************************************************
+Copyright 1990, by Alfalfa Software Incorporated, Cambridge, Massachusetts.
+Copyright 2010, Gabor Kovesdan <gabor@FreeBSD.org>
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that Alfalfa's name not be used in
+advertising or publicity pertaining to distribution of the software
+without specific, written prior permission.
+
+ALPHALPHA DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+ALPHALPHA BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+If you make any modifications, bugfixes or other changes to this software
+we'd appreciate it if you could send a copy to us so we can keep things
+up-to-date. Many thanks.
+ Kee Hinckley
+ Alfalfa Software, Inc.
+ 267 Allston St., #3
+ Cambridge, MA 02139 USA
+ nazgul@alfalfa.com
+
+******************************************************************/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define _NLS_PRIVATE
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mman.h>
+#include <sys/queue.h>
+
+#include <arpa/inet.h> /* for ntohl() */
+
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <locale.h>
+#include <nl_types.h>
+#include <pthread.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "../locale/setlocale.h" /* for ENCODING_LEN */
+
+#define _DEFAULT_NLS_PATH "/usr/share/nls/%L/%N.cat:/usr/share/nls/%N/%L:/usr/local/share/nls/%L/%N.cat:/usr/local/share/nls/%N/%L"
+
+#define RLOCK(fail) { int ret; \
+ if (__isthreaded && \
+ ((ret = _pthread_rwlock_rdlock(&rwlock)) != 0)) { \
+ errno = ret; \
+ return (fail); \
+ }}
+#define WLOCK(fail) { int ret; \
+ if (__isthreaded && \
+ ((ret = _pthread_rwlock_wrlock(&rwlock)) != 0)) { \
+ errno = ret; \
+ return (fail); \
+ }}
+#define UNLOCK { if (__isthreaded) \
+ _pthread_rwlock_unlock(&rwlock); }
+
+#define NLERR ((nl_catd) -1)
+#define NLRETERR(errc) { errno = errc; return (NLERR); }
+#define SAVEFAIL(n, l, e) { WLOCK(NLERR); \
+ np = malloc(sizeof(struct catentry)); \
+ if (np != NULL) { \
+ np->name = strdup(n); \
+ np->path = NULL; \
+ np->lang = (l == NULL) ? NULL : \
+ strdup(l); \
+ np->caterrno = e; \
+ SLIST_INSERT_HEAD(&cache, np, list); \
+ } \
+ UNLOCK; \
+ errno = e; \
+ }
+
+static nl_catd load_msgcat(const char *, const char *, const char *);
+
+static pthread_rwlock_t rwlock = PTHREAD_RWLOCK_INITIALIZER;
+
+struct catentry {
+ SLIST_ENTRY(catentry) list;
+ char *name;
+ char *path;
+ int caterrno;
+ nl_catd catd;
+ char *lang;
+ int refcount;
+};
+
+SLIST_HEAD(listhead, catentry) cache =
+ SLIST_HEAD_INITIALIZER(cache);
+
+nl_catd
+catopen(const char *name, int type)
+{
+ struct stat sbuf;
+ struct catentry *np;
+ char *base, *cptr, *cptr1, *lang, *nlspath, *pathP, *pcode;
+ char *plang, *pter, *tmpptr;
+ int saverr, spcleft;
+ char path[PATH_MAX];
+
+ /* sanity checking */
+ if (name == NULL || *name == '\0')
+ NLRETERR(EINVAL);
+
+ if (strchr(name, '/') != NULL)
+ /* have a pathname */
+ lang = NULL;
+ else {
+ if (type == NL_CAT_LOCALE)
+ lang = setlocale(LC_MESSAGES, NULL);
+ else
+ lang = getenv("LANG");
+
+ if (lang == NULL || *lang == '\0' || strlen(lang) > ENCODING_LEN ||
+ (lang[0] == '.' &&
+ (lang[1] == '\0' || (lang[1] == '.' && lang[2] == '\0'))) ||
+ strchr(lang, '/') != NULL)
+ lang = "C";
+ }
+
+ /* Try to get it from the cache first */
+ RLOCK(NLERR);
+ SLIST_FOREACH(np, &cache, list) {
+ if ((strcmp(np->name, name) == 0) &&
+ ((lang != NULL && np->lang != NULL &&
+ strcmp(np->lang, lang) == 0) || (np->lang == lang))) {
+ if (np->caterrno != 0) {
+ /* Found cached failing entry */
+ UNLOCK;
+ NLRETERR(np->caterrno);
+ } else {
+ /* Found cached successful entry */
+ np->refcount++;
+ UNLOCK;
+ return (np->catd);
+ }
+ }
+ }
+ UNLOCK;
+
+ /* is it absolute path ? if yes, load immediately */
+ if (strchr(name, '/') != NULL)
+ return (load_msgcat(name, name, lang));
+
+ /* sanity checking */
+ if ((plang = cptr1 = strdup(lang)) == NULL)
+ return (NLERR);
+ if ((cptr = strchr(cptr1, '@')) != NULL)
+ *cptr = '\0';
+ pter = pcode = "";
+ if ((cptr = strchr(cptr1, '_')) != NULL) {
+ *cptr++ = '\0';
+ pter = cptr1 = cptr;
+ }
+ if ((cptr = strchr(cptr1, '.')) != NULL) {
+ *cptr++ = '\0';
+ pcode = cptr;
+ }
+
+ if ((nlspath = getenv("NLSPATH")) == NULL || issetugid())
+ nlspath = _DEFAULT_NLS_PATH;
+
+ if ((base = cptr = strdup(nlspath)) == NULL) {
+ saverr = errno;
+ free(plang);
+ errno = saverr;
+ return (NLERR);
+ }
+
+ while ((nlspath = strsep(&cptr, ":")) != NULL) {
+ pathP = path;
+ if (*nlspath) {
+ for (; *nlspath; ++nlspath) {
+ if (*nlspath == '%') {
+ switch (*(nlspath + 1)) {
+ case 'l':
+ tmpptr = plang;
+ break;
+ case 't':
+ tmpptr = pter;
+ break;
+ case 'c':
+ tmpptr = pcode;
+ break;
+ case 'L':
+ tmpptr = lang;
+ break;
+ case 'N':
+ tmpptr = (char *)name;
+ break;
+ case '%':
+ ++nlspath;
+ /* FALLTHROUGH */
+ default:
+ if (pathP - path >=
+ sizeof(path) - 1)
+ goto too_long;
+ *(pathP++) = *nlspath;
+ continue;
+ }
+ ++nlspath;
+ put_tmpptr:
+ spcleft = sizeof(path) -
+ (pathP - path) - 1;
+ if (strlcpy(pathP, tmpptr, spcleft) >=
+ spcleft) {
+ too_long:
+ free(plang);
+ free(base);
+ SAVEFAIL(name, lang, ENAMETOOLONG);
+ NLRETERR(ENAMETOOLONG);
+ }
+ pathP += strlen(tmpptr);
+ } else {
+ if (pathP - path >= sizeof(path) - 1)
+ goto too_long;
+ *(pathP++) = *nlspath;
+ }
+ }
+ *pathP = '\0';
+ if (stat(path, &sbuf) == 0) {
+ free(plang);
+ free(base);
+ return (load_msgcat(path, name, lang));
+ }
+ } else {
+ tmpptr = (char *)name;
+ --nlspath;
+ goto put_tmpptr;
+ }
+ }
+ free(plang);
+ free(base);
+ SAVEFAIL(name, lang, ENOENT);
+ NLRETERR(ENOENT);
+}
+
+char *
+catgets(nl_catd catd, int set_id, int msg_id, const char *s)
+{
+ struct _nls_cat_hdr *cat_hdr;
+ struct _nls_msg_hdr *msg_hdr;
+ struct _nls_set_hdr *set_hdr;
+ int i, l, r, u;
+
+ if (catd == NULL || catd == NLERR) {
+ errno = EBADF;
+ /* LINTED interface problem */
+ return ((char *)s);
+ }
+
+ cat_hdr = (struct _nls_cat_hdr *)catd->__data;
+ set_hdr = (struct _nls_set_hdr *)(void *)((char *)catd->__data +
+ sizeof(struct _nls_cat_hdr));
+
+ /* binary search, see knuth algorithm b */
+ l = 0;
+ u = ntohl((u_int32_t)cat_hdr->__nsets) - 1;
+ while (l <= u) {
+ i = (l + u) / 2;
+ r = set_id - ntohl((u_int32_t)set_hdr[i].__setno);
+
+ if (r == 0) {
+ msg_hdr = (struct _nls_msg_hdr *)
+ (void *)((char *)catd->__data +
+ sizeof(struct _nls_cat_hdr) +
+ ntohl((u_int32_t)cat_hdr->__msg_hdr_offset));
+
+ l = ntohl((u_int32_t)set_hdr[i].__index);
+ u = l + ntohl((u_int32_t)set_hdr[i].__nmsgs) - 1;
+ while (l <= u) {
+ i = (l + u) / 2;
+ r = msg_id -
+ ntohl((u_int32_t)msg_hdr[i].__msgno);
+ if (r == 0) {
+ return ((char *) catd->__data +
+ sizeof(struct _nls_cat_hdr) +
+ ntohl((u_int32_t)
+ cat_hdr->__msg_txt_offset) +
+ ntohl((u_int32_t)
+ msg_hdr[i].__offset));
+ } else if (r < 0) {
+ u = i - 1;
+ } else {
+ l = i + 1;
+ }
+ }
+
+ /* not found */
+ goto notfound;
+
+ } else if (r < 0) {
+ u = i - 1;
+ } else {
+ l = i + 1;
+ }
+ }
+
+notfound:
+ /* not found */
+ errno = ENOMSG;
+ /* LINTED interface problem */
+ return ((char *)s);
+}
+
+int
+catclose(nl_catd catd)
+{
+ struct catentry *np;
+
+ /* sanity checking */
+ if (catd == NULL || catd == NLERR) {
+ errno = EBADF;
+ return (-1);
+ }
+
+ /* Remove from cache if not referenced any more */
+ WLOCK(-1);
+ SLIST_FOREACH(np, &cache, list) {
+ if (catd == np->catd) {
+ np->refcount--;
+ if (np->refcount == 0) {
+ munmap(catd->__data, (size_t)catd->__size);
+ free(catd);
+ SLIST_REMOVE(&cache, np, catentry, list);
+ free(np->name);
+ free(np->path);
+ free(np->lang);
+ free(np);
+ }
+ break;
+ }
+ }
+ UNLOCK;
+ return (0);
+}
+
+/*
+ * Internal support functions
+ */
+
+static nl_catd
+load_msgcat(const char *path, const char *name, const char *lang)
+{
+ struct stat st;
+ nl_catd catd;
+ struct catentry *np;
+ void *data;
+ int fd;
+
+ /* path/name will never be NULL here */
+
+ /*
+ * One more try in cache; if it was not found by name,
+ * it might still be found by absolute path.
+ */
+ RLOCK(NLERR);
+ SLIST_FOREACH(np, &cache, list) {
+ if ((np->path != NULL) && (strcmp(np->path, path) == 0)) {
+ np->refcount++;
+ UNLOCK;
+ return (np->catd);
+ }
+ }
+ UNLOCK;
+
+ if ((fd = _open(path, O_RDONLY)) == -1) {
+ SAVEFAIL(name, lang, errno);
+ NLRETERR(errno);
+ }
+
+ if (_fstat(fd, &st) != 0) {
+ _close(fd);
+ SAVEFAIL(name, lang, EFTYPE);
+ NLRETERR(EFTYPE);
+ }
+
+ /*
+ * If the file size cannot be held in size_t we cannot mmap()
+ * it to the memory. Probably, this will not be a problem given
+ * that catalog files are usually small.
+ */
+ if (st.st_size > SIZE_T_MAX) {
+ _close(fd);
+ SAVEFAIL(name, lang, EFBIG);
+ NLRETERR(EFBIG);
+ }
+
+ if ((data = mmap(0, (size_t)st.st_size, PROT_READ,
+ MAP_FILE|MAP_SHARED, fd, (off_t)0)) == MAP_FAILED) {
+ int saved_errno = errno;
+ _close(fd);
+ SAVEFAIL(name, lang, saved_errno);
+ NLRETERR(saved_errno);
+ }
+ _close(fd);
+
+ if (ntohl((u_int32_t)((struct _nls_cat_hdr *)data)->__magic) !=
+ _NLS_MAGIC) {
+ munmap(data, (size_t)st.st_size);
+ SAVEFAIL(name, lang, EFTYPE);
+ NLRETERR(EFTYPE);
+ }
+
+ if ((catd = malloc(sizeof (*catd))) == NULL) {
+ munmap(data, (size_t)st.st_size);
+ SAVEFAIL(name, lang, ENOMEM);
+ NLRETERR(ENOMEM);
+ }
+
+ catd->__data = data;
+ catd->__size = (int)st.st_size;
+
+ /* Caching opened catalog */
+ WLOCK(NLERR);
+ if ((np = malloc(sizeof(struct catentry))) != NULL) {
+ np->name = strdup(name);
+ np->path = strdup(path);
+ np->catd = catd;
+ np->lang = (lang == NULL) ? NULL : strdup(lang);
+ np->refcount = 1;
+ np->caterrno = 0;
+ SLIST_INSERT_HEAD(&cache, np, list);
+ }
+ UNLOCK;
+ return (catd);
+}
diff --git a/lib/libc/nls/nl_NL.ISO8859-1.msg b/lib/libc/nls/nl_NL.ISO8859-1.msg
new file mode 100644
index 0000000..2939116
--- /dev/null
+++ b/lib/libc/nls/nl_NL.ISO8859-1.msg
@@ -0,0 +1,294 @@
+$ $FreeBSD$
+$
+$ Message catalog for nl_NL.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Bewerking niet toegestaan
+$ ENOENT
+2 Bestand of map niet gevonden
+$ ESRCH
+3 Taak bestaat niet
+$ EINTR
+4 Onderbroken systeemaanroep
+$ EIO
+5 Invoer/uitvoer fout
+$ ENXIO
+6 Apparaat niet geconfigureerd
+$ E2BIG
+7 Argumentenlijst is te lang
+$ ENOEXEC
+8 Programma kan niet worden uitgevoerd
+$ EBADF
+9 Ongeldige bestandsverwijzing
+$ ECHILD
+10 Geen kindprocessen
+$ EDEADLK
+11 Een deadlock op een bron is vermeden
+$ ENOMEM
+12 Kan geen geheugen meer verkrijgen
+$ EACCES
+13 Toegang geweigerd
+$ EFAULT
+14 Ongeldig adres
+$ ENOTBLK
+15 Een per blok adresseerbaar apparaat is vereist
+$ EBUSY
+16 Apparaat is bezig
+$ EEXIST
+17 Bestand bestaat reeds
+$ EXDEV
+18 Verwijzing tussen verschillende apparaten
+$ ENODEV
+19 Bewerking wordt niet ondersteund door dit apparaat
+$ ENOTDIR
+20 Dit is geen map
+$ EISDIR
+21 Dit is een map
+$ EINVAL
+22 Ongeldig argument
+$ ENFILE
+23 Te veel open bestanden in het systeem
+$ EMFILE
+24 Te veel open bestanden
+$ ENOTTY
+25 ioctl niet van toepassing op dit apparaat
+$ ETXTBSY
+26 Programmabestand is bezig
+$ EFBIG
+27 Bestand is te groot
+$ ENOSPC
+28 Geen ruimte meer op dit apparaat
+$ ESPIPE
+29 Ongeldige zoekopdracht
+$ EROFS
+30 Van dit bestandssysteem kan alleen worden gelezen
+$ EMLINK
+31 Te veel bestandsverwijzingen
+$ EPIPE
+32 Gebroken pijp
+$ EDOM
+33 Numeriek argument valt buiten domein
+$ ERANGE
+34 Resultaat te groot of te klein
+$ EAGAIN, EWOULDBLOCK
+35 Middel tijdelijk onbeschikbaar
+$ EINPROGRESS
+36 Bewerking in gang gezet
+$ EALREADY
+37 Bewerking is al in gang gezet
+$ ENOTSOCK
+38 Voor deze bewerking is een contactpunt vereist
+$ EDESTADDRREQ
+39 Een bestemmingsadres is vereist
+$ EMSGSIZE
+40 Te groot bericht
+$ EPROTOTYPE
+41 Protocol past niet bij dit contactpunt
+$ ENOPROTOOPT
+42 Protocol is niet beschikbaar
+$ EPROTONOSUPPORT
+43 Protocol is niet ondersteund
+$ ESOCKTNOSUPPORT
+44 Dit soort contactpunt is niet ondersteund
+$ EOPNOTSUPP
+45 Bewerking niet ondersteund
+$ EPFNOSUPPORT
+46 Protocolfamilie niet ondersteund
+$ EAFNOSUPPORT
+47 Adressenfamilie niet ondersteund door protocolfamilie
+$ EADDRINUSE
+48 Adres is al in gebruik
+$ EADDRNOTAVAIL
+49 Het gevraagde adres kan niet worden toegekend
+$ ENETDOWN
+50 Netwerk is plat
+$ ENETUNREACH
+51 Netwerk is onbereikbaar
+$ ENETRESET
+52 Netwerk onderbrak verbinding tijdens herstart
+$ ECONNABORTED
+53 Verbroken verbinding veroorzaakt door software
+$ ECONNRESET
+54 Verbinding werd aan de andere kant verbroken
+$ ENOBUFS
+55 Geen bufferruimte meer beschikbaar
+$ EISCONN
+56 Contactpunt is al verbonden
+$ ENOTCONN
+57 Contactpunt is niet verbonden
+$ ESHUTDOWN
+58 Een afgesloten contactpunt kan geen gegevens meer verzenden
+$ ETOOMANYREFS
+59 Te veel verwijzingen: splitsen niet mogelijk
+$ ETIMEDOUT
+60 Verbinding te lang niet mogelijk
+$ ECONNREFUSED
+61 Verbinding geweigerd
+$ ELOOP
+62 Te veel niveaus van symbolische verwijzingen
+$ ENAMETOOLONG
+63 Bestandsnaam te lang
+$ EHOSTDOWN
+64 Bestemming niet actief
+$ EHOSTUNREACH
+65 Bestemming niet bereikbaar
+$ ENOTEMPTY
+66 Map is niet leeg
+$ EPROCLIM
+67 Te veel processen
+$ EUSERS
+68 Te veel gebruikers
+$ EDQUOT
+69 Schijfquota overschreden
+$ ESTALE
+70 Verlopen NFS-bestandsverwijzing
+$ EREMOTE
+71 Te veel verwijzingen op afstand in dit pad
+$ EBADRPC
+72 RPC-argumentstructuur is incorrect
+$ ERPCMISMATCH
+73 RPC-versie is verkeerd
+$ EPROGUNAVAIL
+74 RPC-programma niet beschikbaar
+$ EPROGMISMATCH
+75 Programmaversie is verkeerd
+$ EPROCUNAVAIL
+76 Taak kan niet door dit programma worden uitgevoerd
+$ ENOLCK
+77 Geen sloten beschikbaar
+$ ENOSYS
+78 Systeemfunctie is niet geimplementeerd
+$ EFTYPE
+79 Bestandsformaat niet van toepassing
+$ EAUTH
+80 Aanmeldingsfout
+$ ENEEDAUTH
+81 Aanmeldingsprocedure benodigd
+$ EIDRM
+82 De aanwijzer is verwijderd
+$ ENOMSG
+83 Geen bericht van het gewenste type
+$ EOVERFLOW
+84 Waarde te groot om te bewaren in gegevenstype
+$ ECANCELED
+85 Bewerking geannuleerd
+$ EILSEQ
+86 Ongeldige bytereeks
+$ ENOATTR
+87 Attribuut niet gevonden
+$ EDOOFUS
+88 Programmeerfout
+$ EBADMSG
+89 Verkeerd of defect bericht
+$ EMULTIHOP
+90 Multihopverzoek
+$ ENOLINK
+91 Verbinding werd verstoord
+$ EPROTO
+92 Protocolfout
+$ ENOTCAPABLE
+93 Onvoldoende mogelijkheden
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Opgehangen
+$ SIGINT
+2 Onderbroken
+$ SIGQUIT
+3 Opgegeven
+$ SIGILL
+4 Verboden instructie
+$ SIGTRAP
+5 Spoor/BPT-val
+$ SIGABRT
+6 Abort-val
+$ SIGEMT
+7 EMT-val
+$ SIGFPE
+8 Drijvende kommafout
+$ SIGKILL
+9 Gedood
+$ SIGBUS
+10 Busfout
+$ SIGSEGV
+11 Segmentatiefout
+$ SIGSYS
+12 Verkeerde systeemaanroep
+$ SIGPIPE
+13 Gebroken pijp
+$ SIGALRM
+14 Wekker
+$ SIGTERM
+15 Beeindigd
+$ SIGURG
+16 Dringende I/O opgemerkt
+$ SIGSTOP
+17 Gestopt (signaal)
+$ SIGTSTP
+18 Gestopt
+$ SIGCONT
+19 Voortgezet
+$ SIGCHLD
+20 Kindproces beeindigd
+$ SIGTTIN
+21 Gestopt (TTY-invoer)
+$ SIGTTOU
+22 Gestopt (TTY-uitvoer)
+$ SIGIO
+23 I/O mogelijk
+$ SIGXCPU
+24 Te veel CPU-tijd verbruikt
+$ SIGXFSZ
+25 Maximale bestandsgrootte overschreden
+$ SIGVTALRM
+26 Virtuele wekker
+$ SIGPROF
+27 Profiling-wekker
+$ SIGWINCH
+28 Venstergrootte veranderd
+$ SIGINFO
+29 Informatieverzoek
+$ SIGUSR1
+30 Gebruikersignaal 1
+$ SIGUSR2
+31 Gebruikersignaal 2
+$
+$ gai_strerror() support catalog
+$set 3
+$ 1 (obsolete)
+1 Adresfamilie voor hostnaam niet ondersteund
+$ EAI_AGAIN
+2 Tijdelijke fout in naamresolutie
+$ EAI_BADFLAGS
+3 Ongeldige waarde voor ai_flags
+$ EAI_FAIL
+4 Onherstelbare fout in naamresolutie
+$ EAI_FAMILY
+5 ai_familie niet ondersteund
+$ EAI_MEMORY
+6 Geheugenallocatiefout
+$ 7 (obsolete)
+7 Geen adres met hostnaam geassocieerd
+$ EAI_NONAME
+8 hostname noch servname gegeven, of onbekend
+$ EAI_SERVICE
+9 servname niet ondersteund voor ai_socktype
+$ EAI_SOCKTYPE
+10 ai_socktype niet ondersteund
+$ EAI_SYSTEM
+11 Systeemfout geretourneerd in errno
+$ EAI_BADHINTS
+12 Ongeldige waarde voor hints
+$ EAI_PROTOCOL
+13 Opgelost protocol is onbekend
+$ EAI_OVERFLOW
+14 Argumentbuffer overstroomd
+$ 0
+32766 Succes
+$ NL_MSGMAX
+32767 Onbekende fout
diff --git a/lib/libc/nls/no_NO.ISO8859-1.msg b/lib/libc/nls/no_NO.ISO8859-1.msg
new file mode 100644
index 0000000..2598f4d
--- /dev/null
+++ b/lib/libc/nls/no_NO.ISO8859-1.msg
@@ -0,0 +1,231 @@
+$ $FreeBSD$
+$
+$ Message catalog for no_NO.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operasjonen er ikke tillatt
+$ ENOENT
+2 Filen eller katalogen finnes ikke
+$ ESRCH
+3 Prosessen finnes ikke
+$ EINTR
+4 Avbrudt systemkall
+$ EIO
+5 I/O feil
+$ ENXIO
+6 Enheten er ikke konfigurert
+$ E2BIG
+7 Argumentlisten er for lang
+$ ENOEXEC
+8 Ukjent kjørbart format
+$ EBADF
+9 Ugyldig fildeskriptor
+$ ECHILD
+10 Ingen barneprosess
+$ EDEADLK
+11 Vranglås unngått
+$ ENOMEM
+12 Kan ikke allokere nok minne
+$ EACCES
+13 Ingen adgang
+$ EFAULT
+14 Ugyldig adresse
+$ ENOTBLK
+15 Blokk-enhet påkrevd
+$ EBUSY
+16 Enheten er opptatt
+$ EEXIST
+17 Filen finnes
+$ EXDEV
+18 Link mellom forskjellige enheter
+$ ENODEV
+19 Operasjonen er ikke støttet av enheten
+$ ENOTDIR
+20 Ikke en katalog
+$ EISDIR
+21 Er en katalog
+$ EINVAL
+22 Ugyldig argument
+$ ENFILE
+23 For mange åpne filer i systemet
+$ EMFILE
+24 For mange åpne filer
+$ ENOTTY
+25 Ugyldig ioctl for enheten
+$ ETXTBSY
+26 Kjørbar fil i bruk
+$ EFBIG
+27 Filen er for stor
+$ ENOSPC
+28 Ingen ledig plass på enheten
+$ ESPIPE
+29 Ugyldig seek operasjon
+$ EROFS
+30 Filsystemet er skrivebeskyttet
+$ EMLINK
+31 For mange linker
+$ EPIPE
+32 Brudt pipe
+$ EDOM
+33 Numerisk argument utenfor arbeidsområdet
+$ ERANGE
+34 Resultatet er for stort
+$ EAGAIN, EWOULDBLOCK
+35 Ressurs midlertidig utilgjengelig
+$ EINPROGRESS
+36 Operasjonen er nå i gang
+$ EALREADY
+37 Operasjonen er allerede i gang
+$ ENOTSOCK
+38 Deskriptoren er ikke en socket
+$ EDESTADDRREQ
+39 Mottakeradresse er påkrevd
+$ EMSGSIZE
+40 Meldingen er for lang
+$ EPROTOTYPE
+41 Ugyldig protokolltype for denne socketen
+$ ENOPROTOOPT
+42 Protokollen er ikke tilgjengelig
+$ EPROTONOSUPPORT
+43 Protokollen er ikke støttet
+$ ESOCKTNOSUPPORT
+44 Socket-typen er ikke støttet
+$ EOPNOTSUPP
+45 Operasjonen er ikke støttet
+$ EPFNOSUPPORT
+46 Protokollfamilien er ikke støttet
+$ EAFNOSUPPORT
+47 Adressetypen er ikke støttet av protokollfamilien
+$ EADDRINUSE
+48 Adressen er allerede i bruk
+$ EADDRNOTAVAIL
+49 Kan ikke bruke den ønskede adressen
+$ ENETDOWN
+50 Nettverket er nede
+$ ENETUNREACH
+51 Nettverket er utilgjengelig
+$ ENETRESET
+52 Nettverket kuttet forbindelsen ved reset
+$ ECONNABORTED
+53 Programvaren forårsaket brudd av forbindelsen
+$ ECONNRESET
+54 Forbindelsen avbrudt av korrespondenten
+$ ENOBUFS
+55 Buffer-plass ikke tilgjengelig
+$ EISCONN
+56 Socketen er allerede forbundet
+$ ENOTCONN
+57 Socketen er ikke forbundet
+$ ESHUTDOWN
+58 Kan ikke sende etter at socketen er tatt ned
+$ ETOOMANYREFS
+59 For mange referanser: kan ikke slå dem sammen
+$ ETIMEDOUT
+60 Tiden til forbindelsen utløp
+$ ECONNREFUSED
+61 Forbindelse nektet
+$ ELOOP
+62 For mange nivåer med symbolske linker
+$ ENAMETOOLONG
+63 Filnavnet er for langt
+$ EHOSTDOWN
+64 Maskinen er nede
+$ EHOSTUNREACH
+65 Ingen rute til maskinen
+$ ENOTEMPTY
+66 Katalogen er ikke tom
+$ EPROCLIM
+67 For mange prosesser
+$ EUSERS
+68 For mange brukere
+$ EDQUOT
+69 Diskkvote overskredet
+$ ESTALE
+70 Fastlåst NFS fildeskriptor
+$ EREMOTE
+71 For mange nivåer med remote i stien
+$ EBADRPC
+72 Ugyldig RPC struktur
+$ ERPCMISMATCH
+73 Feil RPC versjon
+$ EPROGUNAVAIL
+74 RPC program ikke tilgjengelig
+$ EPROGMISMATCH
+75 Feil programversjon
+$ EPROCUNAVAIL
+76 Prosedyren finnes ikke i programmet
+$ ENOLCK
+77 Ingen låsing tilgjengelig
+$ ENOSYS
+78 Funksjonen er ikke implementert
+$ EFTYPE
+79 Ugyldig filtype eller format
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Hangup
+$ SIGINT
+2 Avbrudd
+$ SIGQUIT
+3 Avslutt
+$ SIGILL
+4 Ugyldig instruksjon
+$ SIGTRAP
+5 Trace/BPT trap
+$ SIGABRT
+6 Abort trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Flyttallsfeil
+$ SIGKILL
+9 Drept
+$ SIGBUS
+10 Buss feil
+$ SIGSEGV
+11 Segmenteringsfeil
+$ SIGSYS
+12 Ugyldig systemkall
+$ SIGPIPE
+13 Brudt pipe
+$ SIGALRM
+14 Alarmklokke
+$ SIGTERM
+15 Terminert
+$ SIGURG
+16 Urgent I/O condition
+$ SIGSTOP
+17 Stoppet (signal)
+$ SIGTSTP
+18 Stoppet
+$ SIGCONT
+19 Fortsetter
+$ SIGCHLD
+20 Barn avsluttet
+$ SIGTTIN
+21 Stoppet (tty input)
+$ SIGTTOU
+22 Stoppet (tty output)
+$ SIGIO
+23 I/O mulig
+$ SIGXCPU
+24 CPU-tid overskredet
+$ SIGXFSZ
+25 Maksimal filstørrelse overskredet
+$ SIGVTALRM
+26 Virtuell timer utløpt
+$ SIGPROF
+27 Profileringstimer utløpt
+$ SIGWINCH
+28 Vindustørrelse endres
+$ SIGINFO
+29 Informasjonsforespørsel
+$ SIGUSR1
+30 Brukerdefinert signal 1
+$ SIGUSR2
+31 Brukerdefinert signal 2
diff --git a/lib/libc/nls/pl_PL.ISO8859-2.msg b/lib/libc/nls/pl_PL.ISO8859-2.msg
new file mode 100644
index 0000000..1c184b3
--- /dev/null
+++ b/lib/libc/nls/pl_PL.ISO8859-2.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for pl_PL.ISO8859-2 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operacja niedozwolona
+$ ENOENT
+2 Nie ma takiego pliku/katalogu
+$ ESRCH
+3 Nie ma takiego procesu
+$ EINTR
+4 Wywo³anie systemowe przerwane
+$ EIO
+5 B³±d wej¶cia/wyj¶cia
+$ ENXIO
+6 Nieskonfigurowane urz±dzenie
+$ E2BIG
+7 Zbyt d³uga lista argumentów
+$ ENOEXEC
+8 B³êdny format pliku wykonywalnego
+$ EBADF
+9 Z³y deskryptor pliku
+$ ECHILD
+10 Brak procesów potomnych
+$ EDEADLK
+11 Unikniêto zakleszczenia zasobów
+$ ENOMEM
+12 Brak pamiêci do przydzia³u
+$ EACCES
+13 Brak dostêpu
+$ EFAULT
+14 Z³y adres
+$ ENOTBLK
+15 Wymagane urz±dzenie blokowe
+$ EBUSY
+16 Urz±dzenie zajête
+$ EEXIST
+17 Plik istnieje
+$ EXDEV
+18 Dowi±zanie miedzy urz±dzeniami
+$ ENODEV
+19 Operacja nieobs³ugiwana przez urz±dzenie
+$ ENOTDIR
+20 To nie jest katalog
+$ EISDIR
+21 To jest katalog
+$ EINVAL
+22 B³êdny argument
+$ ENFILE
+23 Zbyt wiele otwartych plików w systemie
+$ EMFILE
+24 Zbyt wiele otwartych plików
+$ ENOTTY
+25 Niew³a¶ciwy dostêp do urz±dzenia
+$ ETXTBSY
+26 Plik wykonywalny jest zajêty
+$ EFBIG
+27 Zbyt du¿y plik
+$ ENOSPC
+28 Brak miejsca na urz±dzeniu
+$ ESPIPE
+29 Przesuniêcie niemo¿liwe
+$ EROFS
+30 System plików tylko do odczytu
+$ EMLINK
+31 Zbyt wiele dowi±zañ
+$ EPIPE
+32 Potok przerwany
+$ EDOM
+33 Argument liczbowy z poza zakresu
+$ ERANGE
+34 Wynik z poza zakresu
+$ EAGAIN, EWOULDBLOCK
+35 Zasoby chwilowo niedostêpne
+$ EINPROGRESS
+36 Operacja jest w³a¶nie wykonywana
+$ EALREADY
+37 Operacja jest ju¿ wykonywana
+$ ENOTSOCK
+38 Operacja na obiekcie, który nie jest gniazdem
+$ EDESTADDRREQ
+39 Wymagany adres przeznaczenia
+$ EMSGSIZE
+40 Wiadomo¶æ zbyt d³uga
+$ EPROTOTYPE
+41 Typ protoko³u nie pasuje do gniazda
+$ ENOPROTOOPT
+42 Protokó³ nie jest dostêpny
+$ EPROTONOSUPPORT
+43 Nieobs³ugiwany protokó³
+$ ESOCKTNOSUPPORT
+44 Nieobs³ugiwany typ gniazda
+$ EOPNOTSUPP
+45 Nieobs³ugiwana operacja
+$ EPFNOSUPPORT
+46 Nieobs³ugiwana rodzina protoko³ów
+$ EAFNOSUPPORT
+47 Rodzina adresów nie jest obs³ugiwana przez rodzinê protoko³ów
+$ EADDRINUSE
+48 Adres jest ju¿ w u¿yciu
+$ EADDRNOTAVAIL
+49 Adres nie mo¿e byæ przydzielony
+$ ENETDOWN
+50 Sieæ nie dzia³a
+$ ENETUNREACH
+51 Sieæ jest niedostêpna
+$ ENETRESET
+52 Sieæ przerwa³a po³±czenie po resecie
+$ ECONNABORTED
+53 Oprogramowanie spowodowa³o przerwanie po³±czenia
+$ ECONNRESET
+54 Po³±czenie zerwane przez drug± stronê
+$ ENOBUFS
+55 Brak miejsca w buforze
+$ EISCONN
+56 Gniazdo jest ju¿ po³±czone
+$ ENOTCONN
+57 Gniazdo nie jest po³±czone
+$ ESHUTDOWN
+58 Nie mo¿na wysy³aæ po zamkniêciu gniazda
+$ ETOOMANYREFS
+59 Za du¿o powi±zañ: dowi±zanie niemo¿liwe
+$ ETIMEDOUT
+60 Limit czasu operacji przekroczony
+$ ECONNREFUSED
+61 Po³±czenie odrzucone
+$ ELOOP
+62 Zbyt wiele wzajemnych dowi±zañ symbolicznych
+$ ENAMETOOLONG
+63 Zbyt d³uga nazwa pliku
+$ EHOSTDOWN
+64 Host jest wy³±czony
+$ EHOSTUNREACH
+65 Brak drogi do hosta
+$ ENOTEMPTY
+66 Katalog nie jest pusty
+$ EPROCLIM
+67 Zbyt wiele procesów
+$ EUSERS
+68 Zbyt wielu u¿ytkowników
+$ EDQUOT
+69 Przekroczono limit miejsca na dysku
+$ ESTALE
+70 Uchwyt pliku NFS jest nieaktualny
+$ EREMOTE
+71 Zbyt wiele poziomów zagnie¿d¿enia w ¶cie¿ce
+$ EBADRPC
+72 RPC b³êdna struktura
+$ ERPCMISMATCH
+73 RPC niekompatybilna wersja
+$ EPROGUNAVAIL
+74 RPC program niedostêpny
+$ EPROGMISMATCH
+75 Nieobs³ugiwana wersja programu
+$ EPROCUNAVAIL
+76 Nieobs³ugiwana procedura
+$ ENOLCK
+77 Wyczerpany limit blokad
+$ ENOSYS
+78 Nieobs³ugiwana funkcja
+$ EFTYPE
+79 Niew³a¶ciwy typ lub format pliku
+$ EAUTH
+80 B³±d uwierzytelnienia
+$ ENEEDAUTH
+81 Wymagane uwierzytelnienie
+$ EIDRM
+82 Identyfikator zosta³ usuniêty
+$ ENOMSG
+83 Brak komunikatu po¿±danego typu
+$ EOVERFLOW
+84 Warto¶æ zbyt du¿a dla zdefiniowanego typu danych
+$ ECANCELED
+85 Operacja anulowana
+$ EILSEQ
+86 B³êdna sekwencja bajtów
+$ ENOATTR
+87 Nie znaleziono atrybutu
+$ EDOOFUS
+88 Wewnêtrzny b³±d programu
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Roz³±czenie
+$ SIGINT
+2 Przerwanie
+$ SIGQUIT
+3 Wyj¶cie
+$ SIGILL
+4 Nieznana instrukcja
+$ SIGTRAP
+5 Pu³apka debuggera/BPT
+$ SIGABRT
+6 Przerwana pu³apka
+$ SIGEMT
+7 Pu³apka EMT
+$ SIGFPE
+8 B³±d w obliczeniach zmiennoprzecinkowych
+$ SIGKILL
+9 Unicestwiony
+$ SIGBUS
+10 B³±d szyny
+$ SIGSEGV
+11 Naruszenie ochrony pamiêci
+$ SIGSYS
+12 B³êdne wywo³anie systemowe
+$ SIGPIPE
+13 Przerwany potok
+$ SIGALRM
+14 Budzik
+$ SIGTERM
+15 Zakoñczony
+$ SIGURG
+16 Nag³y wypadek I/O
+$ SIGSTOP
+17 Zatrzymany (sygna³)
+$ SIGTSTP
+18 Zatrzymany
+$ SIGCONT
+19 Kontynuacja
+$ SIGCHLD
+20 Proces potomny zakoñczy³ pracê
+$ SIGTTIN
+21 Zatrzymany (wej¶cie z tty)
+$ SIGTTOU
+22 Zatrzymany (wyj¶cie z tty)
+$ SIGIO
+23 Wej/Wyj dozwolone
+$ SIGXCPU
+24 Przekroczony limit czasu procesora
+$ SIGXFSZ
+25 Przekroczony limit wielko¶ci pliku
+$ SIGVTALRM
+26 Alarm stopera wirtualnego
+$ SIGPROF
+27 Alarm stopera profiluj±cego
+$ SIGWINCH
+28 Zmiana rozmiaru okna
+$ SIGINFO
+29 ¯±danie informacji
+$ SIGUSR1
+30 Sygna³ u¿ytkownika 1
+$ SIGUSR2
+31 Sygna³ u¿ytkownika 2
diff --git a/lib/libc/nls/pt_BR.ISO8859-1.msg b/lib/libc/nls/pt_BR.ISO8859-1.msg
new file mode 100644
index 0000000..fb1c100
--- /dev/null
+++ b/lib/libc/nls/pt_BR.ISO8859-1.msg
@@ -0,0 +1,249 @@
+$ $FreeBSD$
+$
+$ Message catalog for pt_BR.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operação não permitida
+$ ENOENT
+2 Nenhum arquivo ou diretório encontrado
+$ ESRCH
+3 Nenhum processo encontrado
+$ EINTR
+4 Chamada de sistema interrompida
+$ EIO
+5 Erro de entrada/saída
+$ ENXIO
+6 Dispositivo não configurado
+$ E2BIG
+7 Lista de argumentos muito grande
+$ ENOEXEC
+8 Erro no formato de execução
+$ EBADF
+9 Erro no descritor de arquivo
+$ ECHILD
+10 Nenhum processo filho
+$ EDEADLK
+11 Bloqueio de recurso evitado
+$ ENOMEM
+12 Impossível alocar memória
+$ EACCES
+13 Permissão negada
+$ EFAULT
+14 Endereço errado
+$ ENOTBLK
+15 Dispositivo de bloco requerido
+$ EBUSY
+16 Dispositivo ocupado
+$ EEXIST
+17 Arquivo existe
+$ EXDEV
+18 Ligação entre dispositivos
+$ ENODEV
+19 Operação não suportada pelo dispositivo
+$ ENOTDIR
+20 Não é um diretório
+$ EISDIR
+21 É um diretório
+$ EINVAL
+22 Argumento inválido
+$ ENFILE
+23 Muitos arquivos abertos no sistema
+$ EMFILE
+24 Muitos arquivos abertos no sistema
+$ ENOTTY
+25 ioctl inapropriado para o dispositivo
+$ ETXTBSY
+26 Arquivo texto sendo utilizado
+$ EFBIG
+27 Arquivo muito grande
+$ ENOSPC
+28 Sem espaço no dispositivo
+$ ESPIPE
+29 seek ilegal
+$ EROFS
+30 Sistema de arquivos apenas para leitura
+$ EMLINK
+31 Muitos links
+$ EPIPE
+32 pipe quebrado
+$ EDOM
+33 Argumento numérico fora do domínio
+$ ERANGE
+34 Resultado muito grande
+$ EAGAIN, EWOULDBLOCK
+35 Recurso temporariamente indisponível
+$ EINPROGRESS
+36 Operação em progresso agora
+$ EALREADY
+37 Operação em progresso pronta
+$ ENOTSOCK
+38 Operação de socket em um não-socket
+$ EDESTADDRREQ
+39 Endereço de destino requerido
+$ EMSGSIZE
+40 Mensagem muito grande
+$ EPROTOTYPE
+41 Tipo de protocolo errado para socket
+$ ENOPROTOOPT
+42 Protocolo não disponível
+$ EPROTONOSUPPORT
+43 Protocolo não suportado
+$ ESOCKTNOSUPPORT
+44 Tipo de socket não suportado
+$ EOPNOTSUPP
+45 Operação não permitida
+$ EPFNOSUPPORT
+46 Família de protocolo não suportada
+$ EAFNOSUPPORT
+47 Família de endereços não suportada pela família de protocolos
+$ EADDRINUSE
+48 Endereço já está em uso
+$ EADDRNOTAVAIL
+49 Impossível obter endereço solicitado
+$ ENETDOWN
+50 Rede está parada
+$ ENETUNREACH
+51 Rede está inalcançável
+$ ENETRESET
+52 Conexão de rede perdida durante reset
+$ ECONNABORTED
+53 Conexão abortada por software
+$ ECONNRESET
+54 Conexão reiniciada pelo outro ponto
+$ ENOBUFS
+55 Sem espaço de buffer disponível
+$ EISCONN
+56 Socket já está conectado
+$ ENOTCONN
+57 Socket não está conectado
+$ ESHUTDOWN
+58 Impossível enviar depois que o socket foi finalizado
+$ ETOOMANYREFS
+59 Muitas referências: impossível ligar
+$ ETIMEDOUT
+60 Tempo de operação expirou
+$ ECONNREFUSED
+61 Conexão recusada
+$ ELOOP
+62 Muitos níveis de links simbólicos
+$ ENAMETOOLONG
+63 Nome de arquivo muito grande
+$ EHOSTDOWN
+64 Host está desligado
+$ EHOSTUNREACH
+65 Sem rota para o host
+$ ENOTEMPTY
+66 Diretório não está vazio
+$ EPROCLIM
+67 Muitos processos
+$ EUSERS
+68 Muitos usuários
+$ EDQUOT
+69 Quota de disco excedida
+$ ESTALE
+70 Manipulador de arquivo NFS velho
+$ EREMOTE
+71 Muitos níveis no caminho remoto
+$ EBADRPC
+72 Estrutura RPC incorreta
+$ ERPCMISMATCH
+73 Versão RPC incorreta
+$ EPROGUNAVAIL
+74 Programa RPC indisponível
+$ EPROGMISMATCH
+75 Versão do programa incorreta
+$ EPROCUNAVAIL
+76 Procedimento incorreto para o programa
+$ ENOLCK
+77 Nenhum lock disponível
+$ ENOSYS
+78 Função não implementada
+$ EFTYPE
+79 Tipo de arquivo ou formato inapropriados
+$ EAUTH
+80 Erro de autenticação
+$ ENEEDAUTH
+81 Necessidade de autenticador
+$ EIDRM
+82 Identificador removido
+$ ENOMSG
+83 Nenhuma mensagem do tipo desejado
+$ EOVERFLOW
+84 Valor muito grande para ser armazenado neste tipo de dado
+$ ECANCELED
+85 Operação cancelada
+$ EILSEQ
+86 Sequência de bytes ilegal
+$ ENOATTR
+87 Atributo não encontrado
+$ EDOOFUS
+88 Erro de programação
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Fim da linha (Hangup)
+$ SIGINT
+2 Interrupção
+$ SIGQUIT
+3 Saída
+$ SIGILL
+4 Instrução ilegal
+$ SIGTRAP
+5 Trap de Trace/BPT
+$ SIGABRT
+6 Abortar trap
+$ SIGEMT
+7 EMT trap
+$ SIGFPE
+8 Exceção de ponto flutuante
+$ SIGKILL
+9 Morreu
+$ SIGBUS
+10 Erro de barramento
+$ SIGSEGV
+11 Falha de segmentação
+$ SIGSYS
+12 Chamada de sistema incorreta
+$ SIGPIPE
+13 Pipe incorreto
+$ SIGALRM
+14 Alarme do relógio
+$ SIGTERM
+15 Terminado
+$ SIGURG
+16 Condição urgente de E/S
+$ SIGSTOP
+17 Suspendido (sinal)
+$ SIGTSTP
+18 Suspendido
+$ SIGCONT
+19 Continuado
+$ SIGCHLD
+20 Filho saiu
+$ SIGTTIN
+21 Parado (entrada de tty)
+$ SIGTTOU
+22 Parado (saída de tty)
+$ SIGIO
+23 E/S possível
+$ SIGXCPU
+24 Limite de tempo de CPU excedido
+$ SIGXFSZ
+25 Tamanho de arquivo excedido
+$ SIGVTALRM
+26 Temporizador virtual expirou
+$ SIGPROF
+27 Temporizador de profiling expirou
+$ SIGWINCH
+28 Mudança no tamanho de janela
+$ SIGINFO
+29 Requisição de informação
+$ SIGUSR1
+30 Sinal 1 definido pelo usuário
+$ SIGUSR2
+31 Sinal 2 definido pelo usuário
diff --git a/lib/libc/nls/ru_RU.KOI8-R.msg b/lib/libc/nls/ru_RU.KOI8-R.msg
new file mode 100644
index 0000000..48bc1d4
--- /dev/null
+++ b/lib/libc/nls/ru_RU.KOI8-R.msg
@@ -0,0 +1,266 @@
+$ $FreeBSD$
+$
+$ Message catalog for ru_RU.KOI8-R locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 ïÐÅÒÁÃÉÑ ÎÅ ÒÁÚÒÅÛÅÎÁ
+$ ENOENT
+2 îÅÔ ÔÁËÏÇÏ ÆÁÊÌÁ ÉÌÉ ËÁÔÁÌÏÇÁ
+$ ESRCH
+3 îÅÔ ÔÁËÏÇÏ ÐÒÏÃÅÓÓÁ
+$ EINTR
+4 ðÒÅÒ×ÁÎÎÙÊ ÓÉÓÔÅÍÎÙÊ ×ÙÚÏ×
+$ EIO
+5 ïÛÉÂËÁ ××ÏÄÁ/×Ù×ÏÄÁ
+$ ENXIO
+6 õÓÔÒÏÊÓÔ×Ï ÎÅ ÓËÏÎÆÉÇÕÒÉÒÏ×ÁÎÏ
+$ E2BIG
+7 óÌÉÛËÏÍ ÄÌÉÎÎÙÊ ÓÐÉÓÏË ÁÒÇÕÍÅÎÔÏ×
+$ ENOEXEC
+8 ïÛÉÂËÁ ÆÏÒÍÁÔÁ ×ÙÐÏÌÎÑÅÍÏÇÏ ÆÁÊÌÁ
+$ EBADF
+9 îÅËÏÒÒÅËÔÎÙÊ ÄÅÓËÒÉÐÔÏÒ ÆÁÊÌÁ
+$ ECHILD
+10 îÅÔ ÐÏÒÏÖÄÅÎÎÙÈ ÐÒÏÃÅÓÓÏ×
+$ EDEADLK
+11 ðÒÅÄÏÔ×ÒÁÝÅÎÁ ×ÚÁÉÍÎÁÑ ÂÌÏËÉÒÏ×ËÁ ÐÒÉ ÄÏÓÔÕÐÅ Ë ÒÅÓÕÒÓÕ
+$ ENOMEM
+12 îÅ×ÏÚÍÏÖÎÏ ×ÙÄÅÌÉÔØ ÐÁÍÑÔØ
+$ EACCES
+13 îÅÄÏÓÔÁÔÏÞÎÏ ÐÒÉ×ÉÌÅÇÉÊ
+$ EFAULT
+14 îÅËÏÒÒÅËÔÎÙÊ ÁÄÒÅÓ
+$ ENOTBLK
+15 îÅÏÂÈÏÄÉÍÏ ÕËÁÚÁÔØ ÂÌÏÞÎÏÅ ÕÓÔÒÏÊÓÔ×Ï
+$ EBUSY
+16 õÓÔÒÏÊÓÔ×Ï ÚÁÎÑÔÏ
+$ EEXIST
+17 æÁÊÌ ÓÕÝÅÓÔ×ÕÅÔ
+$ EXDEV
+18 óÓÙÌËÁ ÎÁ ÄÒÕÇÏÅ ÕÓÔÒÏÊÓÔ×Ï
+$ ENODEV
+19 ïÐÅÒÁÃÉÑ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ ÕÓÔÒÏÊÓÔ×ÏÍ
+$ ENOTDIR
+20 õËÁÚÁÎÎÙÊ ÆÁÊÌ ÎÅ Ñ×ÌÑÅÔÓÑ ËÁÔÁÌÏÇÏÍ
+$ EISDIR
+21 õËÁÚÁÎÎÙÊ ÆÁÊÌ Ñ×ÌÑÅÔÓÑ ËÁÔÁÌÏÇÏÍ
+$ EINVAL
+22 îÅÄÏÐÕÓÔÉÍÙÊ ÁÒÇÕÍÅÎÔ
+$ ENFILE
+23 óÌÉÛËÏÍ ÍÎÏÇÏ ÏÔËÒÙÔÙÈ ÆÁÊÌÏ× × ÓÉÓÔÅÍÅ
+$ EMFILE
+24 óÌÉÛËÏÍ ÍÎÏÇÏ ÏÔËÒÙÔÙÈ ÆÁÊÌÏ×
+$ ENOTTY
+25 ÷ÙÚÏ× ioctl ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ ÕÓÔÒÏÊÓÔ×ÏÍ
+$ ETXTBSY
+26 ôÅËÓÔÏ×ÙÊ ÆÁÊÌ ÚÁÎÑÔ
+$ EFBIG
+27 óÌÉÛËÏÍ ÂÏÌØÛÏÊ ÆÁÊÌ
+$ ENOSPC
+28 îÁ ÕÓÔÒÏÊÓÔ×Å ÎÅ ÏÓÔÁÌÏÓØ ÍÅÓÔÁ
+$ ESPIPE
+29 îÅÄÏÐÕÓÔÉÍÏÅ ÓÍÅÝÅÎÉÅ
+$ EROFS
+30 æÁÊÌÏ×ÁÑ ÓÉÓÔÅÍÁ ÔÏÌØËÏ ÄÌÑ ÞÔÅÎÉÑ
+$ EMLINK
+31 óÌÉÛËÏÍ ÍÎÏÇÏ ÓÓÙÌÏË
+$ EPIPE
+$ XXX???
+32 ëÁÎÁÌ ÒÁÚÒÕÛÅÎ
+$ EDOM
+33 îÅÄÏÐÕÓÔÉÍÏÅ ÚÎÁÞÅÎÉÅ ÞÉÓÌÏ×ÏÇÏ ÁÒÇÕÍÅÎÔÁ
+$ ERANGE
+34 óÌÉÛËÏÍ ÂÏÌØÛÏÊ ÒÅÚÕÌØÔÁÔ
+$ EAGAIN, EWOULDBLOCK
+35 òÅÓÕÒÓ ×ÒÅÍÅÎÎÏ ÎÅÄÏÓÔÕÐÅÎ
+$ EINPROGRESS
+36 ïÐÅÒÁÃÉÑ × ÐÒÏÃÅÓÓÅ ×ÙÐÏÌÎÅÎÉÑ
+$ EALREADY
+$ XXX???
+37 ïÐÅÒÁÃÉÑ ÕÖÅ ×ÙÐÏÌÎÑÅÔÓÑ
+$ ENOTSOCK
+38 ïÐÅÒÁÃÉÑ Ó ÓÏËÅÔÏÍ ÐÒÉÍÅÎÅÎÁ ÎÅ Ë ÓÏËÅÔÕ
+$ EDESTADDRREQ
+39 ôÒÅÂÕÅÔÓÑ ÃÅÌÅ×ÏÊ ÁÄÒÅÓ
+$ EMSGSIZE
+40 óÌÉÛËÏÍ ÄÌÉÎÎÏÅ ÓÏÏÂÝÅÎÉÅ
+$ EPROTOTYPE
+41 îÅ×ÅÒÎÙÊ ÔÉÐ ÐÒÏÔÏËÏÌÁ ÄÌÑ ÓÏËÅÔÁ
+$ ENOPROTOOPT
+42 ðÒÏÔÏËÏÌ ÎÅÄÏÓÔÕÐÅÎ
+$ EPROTONOSUPPORT
+43 ðÒÏÔÏËÏÌ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ
+$ ESOCKTNOSUPPORT
+44 üÔÏÔ ÔÉÐ ÓÏËÅÔÁ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ
+$ EOPNOTSUPP
+45 ïÐÅÒÁÃÉÑ ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ
+$ EPFNOSUPPORT
+46 óÅÍÅÊÓÔ×Ï ÐÒÏÔÏËÏÌÏ× ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ
+$ EAFNOSUPPORT
+47 óÅÍÅÊÓÔ×Ï ÁÄÒÅÓÏ× ÎÅ ÐÏÄÄÅÒÖÉ×ÁÅÔÓÑ ÓÅÍÅÊÓÔ×ÏÍ ÐÒÏÔÏËÏÌÏ×
+$ EADDRINUSE
+48 áÄÒÅÓ ÕÖÅ ÉÓÐÏÌØÚÕÅÔÓÑ
+$ EADDRNOTAVAIL
+49 îÅ ÍÏÇÕ ÎÁÚÎÁÞÉÔØ ÕËÁÚÁÎÎÙÊ ÁÄÒÅÓ
+$ ENETDOWN
+50 óÅÔØ ÎÅ ÒÁÂÏÔÁÅÔ
+$ ENETUNREACH
+51 óÅÔØ ÎÅÄÏÓÔÉÖÉÍÁ
+$ ENETRESET
+52 óÅÔØ ÚÁËÒÙÌÁ ÐÏÄËÌÀÞÅÎÉÅ ÐÒÉ ÓÂÒÏÓÅ
+$ ECONNABORTED
+53 ðÒÏÇÒÁÍÍÁ ×ÙÚ×ÁÌÁ Á×ÁÒÉÊÎÏÅ ÐÒÅËÒÁÝÅÎÉÅ ÐÏÄËÌÀÞÅÎÉÑ
+$ ECONNRESET
+54 ðÏÄËÌÀÞÅÎÉÅ ÓÂÒÏÛÅÎÏ ÐÒÏÔÉ×ÏÐÏÌÏÖÎÏÊ ÓÔÏÒÏÎÏÊ
+$ ENOBUFS
+55 îÅ ÏÓÔÁÌÏÓØ ÍÅÓÔÁ ÐÏÄ ÂÕÆÅÒ
+$ EISCONN
+56 óÏËÅÔ ÕÖÅ ÐÏÄËÌÀÞÅÎ
+$ ENOTCONN
+57 óÏËÅÔ ÎÅ ÐÏÄËÌÀÞÅÎ
+$ ESHUTDOWN
+58 îÅ ÍÏÇÕ ÐÏÓÌÁÔØ ÐÏÓÌÅ ÚÁËÒÙÔÉÑ ÓÏËÅÔÁ
+$ ETOOMANYREFS
+59 óÌÉÛËÏÍ ÍÎÏÇÏ ÓÓÙÌÏË: ÎÅ ÍÏÇÕ ÓÏÅÄÉÎÉÔØ
+$ ETIMEDOUT
+60 ïÐÅÒÁÃÉÑ ÐÒÅ×ÙÓÉÌÁ ÌÉÍÉÔ ×ÒÅÍÅÎÉ
+$ ECONNREFUSED
+61 ðÏÄËÌÀÞÅÎÉÅ ÏÔ×ÅÒÇÎÕÔÏ
+$ ELOOP
+62 óÌÉÛËÏÍ ÍÎÏÇÏ ÕÒÏ×ÎÅÊ ÓÉÍ×ÏÌØÎÙÈ ÓÓÙÌÏË
+$ ENAMETOOLONG
+63 óÌÉÛËÏÍ ÄÌÉÎÎÏÅ ÉÍÑ ÆÁÊÌÁ
+$ EHOSTDOWN
+64 èÏÓÔ ÎÅ ÒÁÂÏÔÁÅÔ
+$ EHOSTUNREACH
+65 îÅÔ ÍÁÒÛÒÕÔÁ Ë ÈÏÓÔÕ
+$ ENOTEMPTY
+66 ëÁÔÁÌÏÇ ÎÅ ÐÕÓÔ
+$ EPROCLIM
+67 óÌÉÛËÏÍ ÍÎÏÇÏ ÐÒÏÃÅÓÓÏ×
+$ EUSERS
+68 óÌÉÛËÏÍ ÍÎÏÇÏ ÐÏÌØÚÏ×ÁÔÅÌÅÊ
+$ EDQUOT
+69 ðÒÅ×ÚÏÊÄÅÎÁ ÄÉÓËÏ×ÁÑ Ë×ÏÔÁ
+$ ESTALE
+70 õÓÔÁÒÅ×ÛÉÊ ÄÅÓËÒÉÐÔÏÒ ÆÁÊÌÁ NFS
+$ EREMOTE
+71 óÌÉÛËÏÍ ÍÎÏÇÏ ÄÉÓÔÁÎÃÉÏÎÎÙÈ ÐÅÒÅÈÏÄÏ× × ÐÕÔÉ
+$ EBADRPC
+72 îÅËÏÒÒÅËÔÎÁÑ ÓÔÒÕËÔÕÒÁ RPC
+$ ERPCMISMATCH
+73 îÅ×ÅÒÎÁÑ ×ÅÒÓÉÑ RPC
+$ EPROGUNAVAIL
+74 ðÒÏÇÒÁÍÍÁ RPC ÎÅÄÏÓÔÕÐÎÁ
+$ EPROGMISMATCH
+75 îÅ×ÅÒÎÁÑ ×ÅÒÓÉÑ ÐÒÏÇÒÁÍÍÙ
+$ EPROCUNAVAIL
+76 îÅËÏÒÒÅËÔÎÁÑ ÐÒÏÃÅÄÕÒÁ ÄÌÑ ÐÒÏÇÒÁÍÍÙ
+$ ENOLCK
+77 âÌÏËÉÒÏ×ËÉ ÎÅÄÏÓÔÕÐÎÙ
+$ ENOSYS
+78 æÕÎËÃÉÑ ÎÅ ÒÅÁÌÉÚÏ×ÁÎÁ
+$ EFTYPE
+79 îÅÐÏÄÈÏÄÑÝÉÊ ÔÉÐ ÉÌÉ ÆÏÒÍÁÔ ÆÁÊÌÁ
+$ EAUTH
+80 ïÛÉÂËÁ ÁÕÔÅÎÔÉÆÉËÁÃÉÉ
+$ ENEEDAUTH
+81 îÅÏÂÈÏÄÉÍÏ ÕÄÏÓÔÏ×ÅÒÅÎÉÅ
+$ EIDRM
+82 éÄÅÎÔÉÆÉËÁÔÏÒ ÕÄÁÌÅÎ
+$ ENOMSG
+83 îÅÔ ÓÏÏÂÝÅÎÉÑ ÔÒÅÂÕÅÍÏÇÏ ÔÉÐÁ
+$ EOVERFLOW
+84 óÌÉÛËÏÍ ÂÏÌØÛÏÅ ÚÎÁÞÅÎÉÅ ÄÌÑ ÈÒÁÎÅÎÉÑ × ÕËÁÚÁÎÎÏÍ ÔÉÐÅ ÄÁÎÎÙÈ
+$ ECANCELED
+85 ïÐÅÒÁÃÉÑ ÏÔÍÅÎÅÎÁ
+$ EILSEQ
+86 îÅÄÏÐÕÓÔÉÍÁÑ ÐÏÓÌÅÄÏ×ÁÔÅÌØÎÏÓÔØ ÂÁÊÔÏ×
+$ ENOATTR
+87 áÔÒÉÂÕÔ ÎÅ ÎÁÊÄÅÎ
+$ EDOOFUS
+88 ïÛÉÂËÁ ÐÒÏÇÒÁÍÍÉÒÏ×ÁÎÉÑ
+$ EBADMSG
+89 ðÌÏÈÏÊ ÆÏÒÍÁÔ ÓÏÏÂÝÅÎÉÑ
+$ EMULTIHOP
+90 ðÏÐÙÔËÁ ÍÕÌØÔÉÈÏÐÁ
+$ ENOLINK
+91 ëÁÎÁÌ ÒÁÚÏÒ×ÁÎ
+$ EPROTO
+92 ïÛÉÂËÁ ÐÒÏÔÏËÏÌÁ
+$ ENOTCAPABLE
+93 îÅÄÏÓÔÁÔÏÞÎÏ ×ÏÚÍÏÖÎÏÓÔÅÊ
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+$ XXX: ïÔËÌÀÞÅÎÉÅ?
+1 òÁÚÒÙ× Ó×ÑÚÉ
+$ SIGINT
+2 ðÒÅÒÙ×ÁÎÉÅ ÐÏ ÓÉÇÎÁÌÕ
+$ SIGQUIT
+3 ÷ÙÈÏÄ
+$ SIGILL
+4 îÅÄÏÐÕÓÔÉÍÁÑ ÉÎÓÔÒÕËÃÉÑ
+$ SIGTRAP
+5 ìÏ×ÕÛËÁ ÔÒÁÓÓÉÒÏ×ËÉ/ÔÏÞËÉ ÏÓÔÁÎÏ×Á
+$ SIGABRT
+$ XXX: á×ÁÒÉÊÎÏÅ ÚÁ×ÅÒÛÅÎÉÅ
+6 ìÏ×ÕÛËÁ Á×ÁÒÉÊÎÏÇÏ ÐÒÅËÒÁÝÅÎÉÑ
+$ SIGEMT
+7 ìÏ×ÕÛËÁ EMT
+$ SIGFPE
+$ XXX: ïÛÉÂËÁ ÏÐÅÒÁÃÉÉ Ó ÐÌÁ×ÁÀÝÅÊ ÔÏÞËÏÊ?
+8 ïÛÉÂËÁ ÐÒÉ ÒÁÂÏÔÅ Ó ×ÅÝÅÓÔ×ÅÎÎÙÍ ÞÉÓÌÏÍ
+$ SIGKILL
+$ XXX: õÂÉÔ
+9 ðÒÉÎÕÄÉÔÅÌØÎÏ ÐÒÅËÒÁÝÅÎ
+$ SIGBUS
+$ XXX: ïÛÉÂËÁ ÁÄÒÅÓÁÃÉÉ ÎÁ ÛÉÎÅ
+10 ïÛÉÂËÁ ÛÉÎÙ
+$ SIGSEGV
+11 ïÛÉÂËÁ ÓÅÇÍÅÎÔÁÃÉÉ
+$ SIGSYS
+12 îÅÄÏÐÕÓÔÉÍÙÊ ÓÉÓÔÅÍÎÙÊ ×ÙÚÏ×
+$ SIGPIPE
+13 ëÁÎÁÌ ÒÁÚÒÕÛÅÎ
+$ SIGALRM
+14 óÒÁÂÏÔÁÌ ÔÁÊÍÅÒ
+$ SIGTERM
+15 úÁ×ÅÒÛÅÎ
+$ SIGURG
+16 îÅÏÂÈÏÄÉÍ ÓÒÏÞÎÙÊ ××ÏÄ-×Ù×ÏÄ
+$ SIGSTOP
+17 ðÒÉÏÓÔÁÎÏ×ËÁ (ÓÉÇÎÁÌ)
+$ SIGTSTP
+18 ðÒÉÏÓÔÁÎÏ×ËÁ
+$ SIGCONT
+19 ðÒÏÄÏÌÖÅÎÉÅ ÒÁÂÏÔÙ
+$ SIGCHLD
+20 úÁ×ÅÒÛÅÎÁ ÒÁÂÏÔÁ ÐÏÒÏÖÄÅÎÎÏÇÏ ÐÒÏÃÅÓÓÁ
+$ SIGTTIN
+21 ïÓÔÁÎÏ×ÌÅÎ (××ÏÄ Ó ÔÅÒÍÉÎÁÌÁ)
+$ SIGTTOU
+22 ïÓÔÁÎÏ×ÌÅÎ (×Ù×ÏÄ ÎÁ ÔÅÒÍÉÎÁÌ)
+$ SIGIO
+23 ÷×ÏÄ-×Ù×ÏÄ ×ÏÚÍÏÖÅÎ
+$ SIGXCPU
+24 ðÒÅ×ÙÛÅÎÏ ÏÇÒÁÎÉÞÅÎÉÅ ÐÒÏÃÅÓÓÏÒÎÏÇÏ ×ÒÅÍÅÎÉ
+$ SIGXFSZ
+25 ðÒÅ×ÙÛÅÎ ÍÁËÓÉÍÁÌØÎÙÊ ÒÁÚÍÅÒ ÆÁÊÌÁ
+$ SIGVTALRM
+26 éÓÔÅË ×ÉÒÔÕÁÌØÎÙÊ ÔÁÊÍÅÒ
+$ SIGPROF
+27 éÓÔÅË ÔÁÊÍÅÒ ÐÒÏÆÉÌÉÒÏ×ÁÎÉÑ
+$ SIGWINCH
+28 éÚÍÅÎÅÎÉÅ ÒÁÚÍÅÒÁ ÏËÎÁ
+$ SIGINFO
+29 úÁÐÒÏÓ ÉÎÆÏÒÍÁÃÉÉ
+$ SIGUSR1
+30 ðÏÌØÚÏ×ÁÔÅÌØÓËÉÊ ÓÉÇÎÁÌ 1
+$ SIGUSR2
+31 ðÏÌØÚÏ×ÁÔÅÌØÓËÉÊ ÓÉÇÎÁÌ 2
diff --git a/lib/libc/nls/sk_SK.ISO8859-2.msg b/lib/libc/nls/sk_SK.ISO8859-2.msg
new file mode 100644
index 0000000..8efa17d
--- /dev/null
+++ b/lib/libc/nls/sk_SK.ISO8859-2.msg
@@ -0,0 +1,267 @@
+$ $FreeBSD$
+$
+$ Message catalog for sk_SK.ISO8859-2 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Operácia nie je povolená
+$ ENOENT
+2 Neexistujúci súbor alebo adresár
+$ ESRCH
+3 Proces neexistuje
+$ EINTR
+4 Systémové volanie preru¹ené
+$ EIO
+5 Chyba vstupu/výstupu
+$ ENXIO
+6 Zariadenie nie je nakonfigurované
+$ E2BIG
+7 Príli¹ dlhý zoznam argumentov
+$ ENOEXEC
+8 Chybný formát spusteného súboru
+$ EBADF
+9 Chybný deskriptor súboru
+$ ECHILD
+10 Neexistuje ¾iaden potomok procesu
+$ EDEADLK
+11 Bolo zabránené zablokovaniu prostriedku
+$ ENOMEM
+12 Nie je mo¾né prideli» pamä»
+$ EACCES
+13 Prístup odmietnutý
+$ EFAULT
+14 Chybná adresa
+$ ENOTBLK
+15 Vy¾adované blokové zariadenie
+$ EBUSY
+16 Zariadenie je pou¾ívané
+$ EEXIST
+17 Súbor existuje
+$ EXDEV
+18 Odkaz medzi zariadeniami
+$ ENODEV
+19 Operácia nie je zariadením podporovaná
+$ ENOTDIR
+20 Nie je adresár
+$ EISDIR
+21 Je adresár
+$ EINVAL
+22 Chybný argument
+$ ENFILE
+23 Priveµa otvorených súborov v systéme
+$ EMFILE
+24 Priveµa otvorených súborov
+$ ENOTTY
+25 Nevhodné ioctl pre dané zariadenie
+$ ETXTBSY
+26 Textový súbor je pou¾ívaný
+$ EFBIG
+27 Súbor je príli¹ veµký
+$ ENOSPC
+28 Na zariadení nie je voµné miesto
+$ ESPIPE
+29 Neprípustné nastavenie pozície
+$ EROFS
+30 Súborový systém je len na èítanie
+$ EMLINK
+31 Priveµa odkazov
+$ EPIPE
+32 Preru¹ená rúra
+$ EDOM
+33 Èíselný argument mimo definièný obor
+$ ERANGE
+34 Výsledok príli¹ veµký alebo príli¹ malý
+$ EAGAIN, EWOULDBLOCK
+35 Zdroj je doèasne nedostupný
+$ EINPROGRESS
+36 Operácia práve prebieha
+$ EALREADY
+37 Operácia u¾ prebieha
+$ ENOTSOCK
+38 Socketová operácia na objekte, ktorý nie je socket
+$ EDESTADDRREQ
+39 Vy¾adovaná cieµová adresa
+$ EMSGSIZE
+40 Príli¹ dlhá správa
+$ EPROTOTYPE
+41 Protokol nie je socketom podporovaný
+$ ENOPROTOOPT
+42 Protokol nie je k dispozícii
+$ EPROTONOSUPPORT
+43 Protokol nie je podporovaný
+$ ESOCKTNOSUPPORT
+44 Typ socketu nie je podporovaný
+$ EOPNOTSUPP
+45 Operácia nie je podporovaná
+$ EPFNOSUPPORT
+46 Rodina protokolov nie je podporovaná
+$ EAFNOSUPPORT
+47 Rodina adries nie je podporovaná rodinou protokolov
+$ EADDRINUSE
+48 Adresa je u¾ pou¾ívaná
+$ EADDRNOTAVAIL
+49 Nie je mo¾né prideli» po¾adovanú adresu
+$ ENETDOWN
+50 Sie» je nefunkèná
+$ ENETUNREACH
+51 Sie» je nedostupná
+$ ENETRESET
+52 Sie» zru¹ila spojenie po resete
+$ ECONNABORTED
+53 Program spôsobil ukonèenie spojenia
+$ ECONNRESET
+54 Spojenie zru¹ené druhou stranou
+$ ENOBUFS
+55 Vyrovnávacia pamä» nie je k dispozícii
+$ EISCONN
+56 Socket je u¾ pripojený
+$ ENOTCONN
+57 Socket nie je pripojený
+$ ESHUTDOWN
+58 Nie je mo¾né posiela» po uzavretí socketu
+$ ETOOMANYREFS
+59 Príli¹ mnoho odkazov: nie je mo¾né spoji»
+$ ETIMEDOUT
+60 Èasový limit pre spojenie vypr¹al
+$ ECONNREFUSED
+61 Spojenie odmietnuté
+$ ELOOP
+62 Priveµa úrovní symbolických odkazov
+$ ENAMETOOLONG
+63 Meno súboru príli¹ dlhé
+$ EHOSTDOWN
+64 Vzdialený uzol je odpojený
+$ EHOSTUNREACH
+65 Neexistuje cesta k vzdialenému uzlu
+$ ENOTEMPTY
+66 Adresár nie je prázdny
+$ EPROCLIM
+67 Priveµa procesov
+$ EUSERS
+68 Priveµa pou¾ívateµov
+$ EDQUOT
+69 Disková kvóta prekroèená
+$ ESTALE
+70 Zastaralý NFS súborový ukazateµ
+$ EREMOTE
+71 Priveµa úrovní vzdialeného v ceste
+$ EBADRPC
+72 RPC ¹truktúra je chybná
+$ ERPCMISMATCH
+73 Chybná verzia RPC
+$ EPROGUNAVAIL
+74 RPC program nie je k dispozícii
+$ EPROGMISMATCH
+75 Chybná verzia RPC programu
+$ EPROCUNAVAIL
+76 Chybná RPC procedúra pre program
+$ ENOLCK
+77 Zámky nie sú k dispozícii
+$ ENOSYS
+78 Funkcia nie je implementovaná
+$ EFTYPE
+79 Nevhodný typ alebo formát súboru
+$ EAUTH
+80 Overenie práv neúspe¹né
+$ ENEEDAUTH
+81 Vy¾adovaný overovací objekt
+$ EIDRM
+82 Identifikátor odstránený
+$ ENOMSG
+83 Neexistuje správa ¾elaného typu
+$ EOVERFLOW
+84 Hodnota je pre daný dátový typ priveµká
+$ EILSEQ
+85 Neprípustná postupnos» bajtov
+$ ENOTSUP
+86 Nie je podporované
+$ ECANCELED
+87 Operácia zru¹ená
+$ EBADMSG
+88 Chybná alebo poru¹ená správa
+$ ENODATA
+89 ®iadna správa nie je k dispozícii
+$ ENOSR
+90 ®iadne STREAM zdroje
+$ ENOSTR
+91 Nie je STREAM
+$ ETIME
+92 Èasový limit pre STREAM ioctl vypr¹al
+$ ENOATTR
+93 Atribút nenájdený
+$ EMULTIHOP
+94 Pokus o spojenie cez viacero uzlov
+$ ENOLINK
+95 Odkaz bol pretrhnutý
+$ EPROTO
+96 Chyba protokolu
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Terminál odpojený
+$ SIGINT
+2 Preru¹enie
+$ SIGQUIT
+3 Koniec
+$ SIGILL
+4 Chybná in¹trukcia
+$ SIGTRAP
+5 Trasovacia/ladiaca in¹trukcia
+$ SIGABRT
+6 Násilné ukonèenie
+$ SIGEMT
+7 Emulovaná in¹trukcia
+$ SIGFPE
+8 Výnimka pohyblivej rádovej èiarky
+$ SIGKILL
+9 Zabité
+$ SIGBUS
+10 Chyba na zbernici
+$ SIGSEGV
+11 Chyba segmentácie
+$ SIGSYS
+12 Chybné systémové volanie
+$ SIGPIPE
+13 Preru¹ená rúra
+$ SIGALRM
+14 Budík
+$ SIGTERM
+15 Ukonèené
+$ SIGURG
+16 Naliehavý vstupný/výstupný stav
+$ SIGSTOP
+17 Pozastavené (signál)
+$ SIGTSTP
+18 Pozastavené
+$ SIGCONT
+19 Pokraèovanie
+$ SIGCHLD
+20 Potomok procesu ukonèený
+$ SIGTTIN
+21 Pozastavené (terminálový vstup)
+$ SIGTTOU
+22 Pozastavené (terminálový výstup)
+$ SIGIO
+23 Vstup/výstup mo¾ný
+$ SIGXCPU
+24 Prekroèený èasový limit pre procesor
+$ SIGXFSZ
+25 Prekroèený limit veµkosti súboru
+$ SIGVTALRM
+26 Vypr¹al virtuálny èasovaè
+$ SIGPROF
+27 Vypr¹al profilovací èasovaè
+$ SIGWINCH
+28 Veµkos» okna zmenená
+$ SIGINFO
+29 ®iados» o informáciu
+$ SIGUSR1
+30 Pou¾ívateµom definovaný signál 1
+$ SIGUSR2
+31 Pou¾ívateµom definovaný signál 2
+$ SIGPWR
+32 Zlyhanie/opakované spustenie napájania
diff --git a/lib/libc/nls/sv_SE.ISO8859-1.msg b/lib/libc/nls/sv_SE.ISO8859-1.msg
new file mode 100644
index 0000000..13cdd23
--- /dev/null
+++ b/lib/libc/nls/sv_SE.ISO8859-1.msg
@@ -0,0 +1,233 @@
+$ $FreeBSD$
+$
+$ Message catalog for sv_SE.ISO8859-1 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 Otillåten operation
+$ ENOENT
+2 Filen eller katalogen finns ej
+$ ESRCH
+3 Denna process finns ej
+$ EINTR
+4 Avbrutet systemanrop
+$ EIO
+5 In-/utmatningsfel
+$ ENXIO
+6 Enheten är ej konfigurerad
+$ E2BIG
+7 Argumentlistan är för lång
+$ ENOEXEC
+8 Ej körbar fil
+$ EBADF
+9 Felaktigt filhandtag
+$ ECHILD
+10 Inga barnprocesser
+$ EDEADLK
+11 Undvek resursdödläge
+$ ENOMEM
+12 Kan ej erhålla minne
+$ EACCES
+13 Tillstånd nekas
+$ EFAULT
+14 Felaktig adress
+$ ENOTBLK
+15 Blockenhet krävs
+$ EBUSY
+16 Enheten är upptagen
+$ EEXIST
+17 Filen finns redan
+$ EXDEV
+18 Länken korsar enheter
+$ ENODEV
+19 Enheten stöder ej operationen
+$ ENOTDIR
+20 Är ej en katalog
+$ EISDIR
+21 Är en katalog
+$ EINVAL
+22 Ogiltigt argument
+$ ENFILE
+23 För många öppna filer i systemet
+$ EMFILE
+24 För många öppna filer
+$ ENOTTY
+25 Olämplig ioctl för enheten
+$ ETXTBSY
+26 Programfilen är upptagen
+$ EFBIG
+27 Filen är för stor
+$ ENOSPC
+28 Inget utrymme kvar på enheten
+$ ESPIPE
+29 Otillåten sökning
+$ EROFS
+30 Skrivskyddat filsystem
+$ EMLINK
+31 För många länkar
+$ EPIPE
+32 Avbruten kommunikationskanal
+$ EDOM
+33 Numeriskt argument utanför domänen
+$ ERANGE
+34 Resultatet är för stort
+$ EAGAIN, EWOULDBLOCK
+35 Resursen är tillfälligt otillgänglig
+$ EINPROGRESS
+36 Operationen är igång
+$ EALREADY
+37 Operationen är redan igång
+$ ENOTSOCK
+38 Sockeloperation på icke-sockel
+$ EDESTADDRREQ
+39 Destinationsadress erfordras
+$ EMSGSIZE
+40 För långt meddelande
+$ EPROTOTYPE
+41 Fel protokolltyp för sockeln
+$ ENOPROTOOPT
+42 Protokollet otillgängligt
+$ EPROTONOSUPPORT
+43 Protokollet är ej understött
+$ ESOCKTNOSUPPORT
+44 Sockeltypen är ej understödd
+$ EOPNOTSUPP
+45 Operationen är ej understödd
+$ EPFNOSUPPORT
+46 Protokollfamiljen är ej understödd
+$ EAFNOSUPPORT
+47 Adressfamiljen är ej understödd av protokollfamiljen
+$ EADDRINUSE
+48 Adressen är upptagen
+$ EADDRNOTAVAIL
+49 Kan ej tilldela den begärda adressen
+$ ENETDOWN
+50 Nätverket fungerar inte
+$ ENETUNREACH
+51 Nätverket är ej kontaktbart
+$ ENETRESET
+52 Nätverket tappade kontakten vid återställningen
+$ ECONNABORTED
+53 Mjukvara orsakade nedkoppling
+$ ECONNRESET
+54 Motparten avbröt uppkopplingen
+$ ENOBUFS
+55 Inget buffertutrymme tillgängligt
+$ EISCONN
+56 Sockeln är redan uppkopplad
+$ ENOTCONN
+57 Sockeln är ej uppkopplad
+$ ESHUTDOWN
+58 Kan ej sända efter att sockeln nedkopplats
+$ ETOOMANYREFS
+59 För många referenser: kan inte delas
+$ ETIMEDOUT
+60 Uppkopplingstiden tog slut
+$ ECONNREFUSED
+61 Uppkopplingen nekad
+$ ELOOP
+62 För många nivåer av symboliska länkar
+$ ENAMETOOLONG
+63 Alldeles för långt filnamn
+$ EHOSTDOWN
+64 Värddatorn är nere
+$ EHOSTUNREACH
+65 Väg till värddatorn saknas
+$ ENOTEMPTY
+66 Katalogen ej tom
+$ EPROCLIM
+67 För många processer
+$ EUSERS
+68 För många användare
+$ EDQUOT
+69 Diskkvot överskriden
+$ ESTALE
+70 Inaktuellt NFS-filhandtag
+$ EREMOTE
+71 För många fjärrnivåer i sökvägen
+$ EBADRPC
+72 Felaktig RPC-struktur
+$ ERPCMISMATCH
+73 Felaktig RPC-version
+$ EPROGUNAVAIL
+74 RPC-programmet otillgängligt
+$ EPROGMISMATCH
+75 Fel programversion
+$ EPROCUNAVAIL
+76 Felaktig procedur för programmet
+$ ENOLCK
+77 Inga lås tillgängliga
+$ ENOSYS
+78 Funktionen är ej implementerad
+$ EFTYPE
+79 Olämplig filtyp eller format
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 Lägg på
+$ SIGINT
+2 Avbryt
+$ SIGQUIT
+3 Avsluta
+$ SIGILL
+4 Olaglig instruktion
+$ SIGTRAP
+5 Spår- eller brytpunktsfälla
+$ SIGABRT
+6 Avslutsfälla
+$ SIGEMT
+7 Emuleringsfälla
+$ SIGFPE
+8 Flyttalsavbrott
+$ SIGKILL
+9 Dräpt
+$ SIGBUS
+10 Bussfel
+$ SIGSEGV
+11 Segmentfel
+$ SIGSYS
+12 Felaktigt systemanrop
+$ SIGPIPE
+13 Avbruten kommunikationskanal
+$ SIGALRM
+14 Äggklocka
+$ SIGTERM
+15 Terminerad
+$ SIGURG
+16 Brådskande In/Ut-tillstånd
+$ SIGSTOP
+17 Stoppad (signal)
+$ SIGTSTP
+18 Stoppad
+$ SIGCONT
+19 Fortsätter
+$ SIGCHLD
+20 Barn avslutat
+$ SIGTTIN
+21 Stoppad (terminalinmatning)
+$ SIGTTOU
+22 Stoppad (terminalutmatning)
+$ SIGIO
+23 In- och utmatning möjlig
+$ SIGXCPU
+24 Cputidsgränsen överskriden
+$ SIGXFSZ
+25 Filstorleksgränsen överskriden
+$ SIGVTALRM
+26 Virtuella äggklockan ringde
+$ SIGPROF
+27 Profileringsäggklockan ringde
+$ SIGWINCH
+28 Fönsterstorleken ändras
+$ SIGINFO
+29 Informationsförfrågan
+$ SIGUSR1
+30 Användardefinierad signal 1
+$ SIGUSR2
+31 Användardefinierad signal 2
+$ SIGPWR
+32 Kraftbortfall/omstart
diff --git a/lib/libc/nls/uk_UA.UTF-8.msg b/lib/libc/nls/uk_UA.UTF-8.msg
new file mode 100644
index 0000000..af871d9
--- /dev/null
+++ b/lib/libc/nls/uk_UA.UTF-8.msg
@@ -0,0 +1,259 @@
+$ $FreeBSD$
+$
+$ Message catalog for uk_UA.UTF-8 locale
+$
+$ strerror() support catalog
+$
+$set 1
+$ EPERM
+1 ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð½Ðµ дозволена
+$ ENOENT
+2 Ðемає такого файлу або каталогу
+$ ESRCH
+3 Ðемає такого процеÑу
+$ EINTR
+4 Перервано виклик функції
+$ EIO
+5 Помилка вводу-виводу
+$ ENXIO
+6 Ðемає такого приÑтрою або адреÑи
+$ E2BIG
+7 Перелік аргументів надто довгий
+$ ENOEXEC
+8 Помилка формату виконуваного файлу
+$ EBADF
+9 Ðевірний деÑкриптор файлу
+$ ECHILD
+10 Ðемає дочірнього процеÑу
+$ EDEADLK
+11 Уникнуто взаємне Ð±Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ñ€ÐµÑурÑів
+$ ENOMEM
+12 Ðе доÑтатньо пам'Ñті
+$ EACCES
+13 Відмова у доÑтупі
+$ EFAULT
+14 Ðевірна адреÑа
+$ ENOTBLK
+15 Потрібен блочний приÑтрій
+$ EBUSY
+16 РеÑÑƒÑ€Ñ Ð·Ð°Ð¹Ð½Ñтий
+$ EEXIST
+17 Файл вже Ñ–Ñнує
+$ EXDEV
+18 ПоÑÐ¸Ð»Ð°Ð½Ð½Ñ Ð·Ð° межі приÑтрою
+$ ENODEV
+19 Ðемає такого приÑтрою
+$ ENOTDIR
+20 Це не каталог
+$ EISDIR
+21 Це каталог
+$ EINVAL
+22 Ðедозволений аргумент
+$ ENFILE
+23 Забагато відкритих файлів у ÑиÑтемі
+$ EMFILE
+24 Забагато відкритих файлів
+$ ENOTTY
+25 Це не термінал
+$ ETXTBSY
+26 ТекÑтовий файл зайнÑтий
+$ EFBIG
+27 Файл надто великий
+$ ENOSPC
+28 Ðе залишилоÑÑŒ міÑÑ†Ñ Ð½Ð° приÑтрої
+$ ESPIPE
+29 Ðедозволене позиціонуваннÑ
+$ EROFS
+30 Файлова ÑиÑтема лише Ð´Ð»Ñ Ñ‡Ð¸Ñ‚Ð°Ð½Ð½Ñ
+$ EMLINK
+31 Забагато поÑилань
+$ EPIPE
+32 Канал зруйновано
+$ EDOM
+33 Помилка облаÑті визначеннÑ
+$ ERANGE
+34 Результат надто великий
+$ EAGAIN, EWOULDBLOCK
+35 РеÑÑƒÑ€Ñ Ñ‚Ð¸Ð¼Ñ‡Ð°Ñово не доÑтупний
+$ EINPROGRESS
+36 ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ñƒ процеÑÑ– виконаннÑ
+$ EALREADY
+37 ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð²Ð¶Ðµ виконуєтьÑÑ
+$ ENOTSOCK
+38 Це не Ñокет
+$ EDESTADDRREQ
+39 Ðеобхідна адреÑа призначеннÑ
+$ EMSGSIZE
+40 ÐŸÐ¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð½Ð°Ð´Ñ‚Ð¾ довге
+$ EPROTOTYPE
+41 Помилковий тип протоколу Ð´Ð»Ñ Ñокету
+$ ENOPROTOOPT
+42 Ðемає такого протоколу
+$ EPROTONOSUPPORT
+43 Протокол не підтримуєтьÑÑ
+$ ESOCKTNOSUPPORT
+44 Цей тип Ñокету не підтримуєтьÑÑ
+$ EOPNOTSUPP
+45 ÐžÐ¿ÐµÑ€Ð°Ñ†Ñ–Ñ Ð½Ðµ підтримуєтьÑÑ
+$ EPFNOSUPPORT
+46 Родина протоколів не підтримуєтьÑÑ
+$ EAFNOSUPPORT
+47 Родина Ð°Ð´Ñ€ÐµÑ Ð½Ðµ підтримуєтьÑÑ Ð¿Ñ€Ð¾Ñ‚Ð¾ÐºÐ¾Ð»Ð¾Ð¼
+$ EADDRINUSE
+48 ÐдреÑа вже викориÑтовуєтьÑÑ
+$ EADDRNOTAVAIL
+49 ÐдреÑа недоÑÑжна
+$ ENETDOWN
+50 Мережа не працює
+$ ENETUNREACH
+51 Мережа недоÑÑжна
+$ ENETRESET
+52 З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð¾ мережею
+$ ECONNABORTED
+53 З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð¾
+$ ECONNRESET
+54 З'Ñ”Ð´Ð½Ð°Ð½Ð½Ñ Ð¿Ñ€Ð¸Ð¿Ð¸Ð½ÐµÐ½Ð¾ протилежною Ñтороною
+$ ENOBUFS
+55 Ðемає вільних буферів
+$ EISCONN
+56 Сокет вже під'єднано
+$ ENOTCONN
+57 Сокет не під'єднано
+$ ESHUTDOWN
+58 Ðе можу відіÑлати піÑÐ»Ñ Ð·Ð°ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ñокету протилежною Ñтороною
+$ ETOOMANYREFS
+59 Забагато поÑилань: не можу з'єднати
+$ ETIMEDOUT
+60 Вийшов ліміт чаÑу Ð´Ð»Ñ Ð·'єднаннÑ
+$ ECONNREFUSED
+61 Відмова у з'єднанні
+$ ELOOP
+62 Забагато рівнів Ñимволічних поÑилань
+$ ENAMETOOLONG
+63 Ім'Ñ Ñ„Ð°Ð¹Ð»Ñƒ надто довге
+$ EHOSTDOWN
+64 ХоÑÑ‚ не працює
+$ EHOSTUNREACH
+65 ХоÑÑ‚ недоÑÑжний
+$ ENOTEMPTY
+66 Каталог не порожній
+$ EPROCLIM
+67 Забагато процеÑів
+$ EUSERS
+68 Забагато кориÑтувачів
+$ EDQUOT
+69 Перевищена диÑкова квота
+$ ESTALE
+70 ЗаÑтарілий деÑкриптор файлу NFS
+$ EREMOTE
+71 Віддалений об'єкт
+$ EBADRPC
+72 Погана Ñтруктура RPC
+$ ERPCMISMATCH
+73 Ðевірна верÑÑ–Ñ RPC
+$ EPROGUNAVAIL
+74 Програма RPC недоÑÑжна
+$ EPROGMISMATCH
+75 Ðевірна верÑÑ–Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¸
+$ EPROCUNAVAIL
+76 Погана процедура Ð´Ð»Ñ Ð¿Ñ€Ð¾Ð³Ñ€Ð°Ð¼Ð¸
+$ ENOLCK
+77 Ð‘Ð»Ð¾ÐºÑƒÐ²Ð°Ð½Ð½Ñ Ð½Ðµ доÑтупне
+$ ENOSYS
+78 Функцію не реалізовано
+$ EFTYPE
+79 Ðепридатний тип чи формат файлу
+$ EAUTH
+80 Помилка аутентифікації
+$ ENEEDAUTH
+81 Потрібна аутентифікаціÑ
+$ EIDRM
+82 Ідентифікатор вилучено
+$ ENOMSG
+83 Ðемає Ð¿Ð¾Ð²Ñ–Ð´Ð¾Ð¼Ð»ÐµÐ½Ð½Ñ Ð±Ð°Ð¶Ð°Ð½Ð¾Ð³Ð¾ типу
+$ EOVERFLOW
+84 Завелике Ð·Ð½Ð°Ñ‡ÐµÐ½Ð½Ñ Ð´Ð»Ñ Ñ†ÑŒÐ¾Ð³Ð¾ типу даних
+$ ECANCELED
+85 Операцію ÑкаÑовано
+$ EILSEQ
+86 Ðедозволена поÑлідовніÑть байтів
+$ ENOATTR
+87 Ðтрибут не знайдено
+$ EDOOFUS
+88 Помилка програмуваннÑ
+$ EBADMSG
+89 Поганий формат повідомленнÑ
+$ EMULTIHOP XXX
+90 Спроба мултіхопу
+$ ENOLINK
+91 Мережовий канал розірвано
+$ EPROTO
+92 Помилка протоколу
+$ ENOTCAPABLE
+93 МожливоÑті недоÑтатні
+$
+$ strsignal() support catalog
+$
+$set 2
+$ SIGHUP
+1 ВідключеннÑ
+$ SIGINT
+2 ПерериваннÑ
+$ SIGQUIT
+3 Вихід
+$ SIGILL
+4 ÐеприпуÑтима інÑтрукціÑ
+$ SIGTRAP
+5 ПаÑтка траÑуваннÑ
+$ SIGABRT
+6 Ðварійне завершеннÑ
+$ SIGEMT
+7 ÐŸÐµÑ€ÐµÑ…Ð¾Ð¿Ð»ÐµÐ½Ð½Ñ ÐµÐ¼ÑƒÐ»ÑŒÐ¾Ð²Ð°Ð½Ð¾Ñ— інÑтрукції
+$ SIGFPE
+8 Помилка роботи з плаваючою крапкою
+$ SIGKILL
+9 Вбито
+$ SIGBUS
+10 Помилка шини
+$ SIGSEGV
+11 ÐŸÐ¾Ñ€ÑƒÑˆÐµÐ½Ð½Ñ Ñегментації
+$ SIGSYS
+12 Поганий ÑиÑтемний виклик
+$ SIGPIPE
+13 Канал зруйновано
+$ SIGALRM
+14 Таймер вичерпано
+$ SIGTERM
+15 ЗавершеннÑ
+$ SIGURG
+16 Ðевідкладний Ñтан на Ñокеті
+$ SIGSTOP
+17 Призупинено (Ñигнал)
+$ SIGTSTP
+18 Призупинено
+$ SIGCONT
+19 ÐŸÑ€Ð¾Ð´Ð¾Ð²Ð¶ÐµÐ½Ð½Ñ Ñ€Ð¾Ð±Ð¾Ñ‚Ð¸
+$ SIGCHLD
+20 Зміна ÑтатуÑу дочірнього процеÑу
+$ SIGTTIN
+21 Зупинено (ввід з терміналу)
+$ SIGTTOU
+22 Зупинено (вивід на термінал)
+$ SIGIO
+23 Ввід-вивід можливий
+$ SIGXCPU
+24 Перевищено ліміт процеÑорного чаÑу
+$ SIGXFSZ
+25 Перевищено ліміт макÑимального розміру файла
+$ SIGVTALRM
+26 Віртуальний таймер вичерпано
+$ SIGPROF
+27 Таймер Ð¿Ñ€Ð¾Ñ„Ñ–Ð»ÑŽÐ²Ð°Ð½Ð½Ñ Ð²Ð¸Ñ‡ÐµÑ€Ð¿Ð°Ð½Ð¾
+$ SIGWINCH
+28 Розмір вікна змінено
+$ SIGINFO
+29 Запит інформації
+$ SIGUSR1
+30 Сигнал кориÑтувача 1
+$ SIGUSR2
+31 Сигнал кориÑтувача 2
diff --git a/lib/libc/posix1e/Makefile.inc b/lib/libc/posix1e/Makefile.inc
new file mode 100644
index 0000000..c9d3ba5
--- /dev/null
+++ b/lib/libc/posix1e/Makefile.inc
@@ -0,0 +1,124 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/posix1e
+
+CFLAGS+=-D_ACL_PRIVATE
+
+# Copy kern/subr_acl_nfs4.c to the libc object directory.
+subr_acl_nfs4.c: ${.CURDIR}/../../sys/kern/subr_acl_nfs4.c
+ cat ${.ALLSRC} > ${.TARGET}
+
+SRCS+= acl_branding.c \
+ acl_calc_mask.c \
+ acl_copy.c \
+ acl_compat.c \
+ acl_delete.c \
+ acl_delete_entry.c \
+ acl_entry.c \
+ acl_flag.c \
+ acl_free.c \
+ acl_from_text.c \
+ acl_from_text_nfs4.c \
+ acl_get.c \
+ acl_id_to_name.c \
+ acl_init.c \
+ acl_perm.c \
+ acl_set.c \
+ acl_strip.c \
+ acl_support.c \
+ acl_support_nfs4.c \
+ acl_to_text.c \
+ acl_to_text_nfs4.c \
+ acl_valid.c \
+ extattr.c \
+ mac.c \
+ mac_exec.c \
+ mac_get.c \
+ mac_set.c \
+ subr_acl_nfs4.c
+
+SYM_MAPS+=${.CURDIR}/posix1e/Symbol.map
+
+MAN+= acl.3 \
+ acl_add_flag_np.3 \
+ acl_add_perm.3 \
+ acl_calc_mask.3 \
+ acl_clear_flags_np.3 \
+ acl_clear_perms.3 \
+ acl_copy_entry.3 \
+ acl_create_entry.3 \
+ acl_delete.3 \
+ acl_delete_entry.3 \
+ acl_delete_flag_np.3 \
+ acl_delete_perm.3 \
+ acl_dup.3 \
+ acl_free.3 \
+ acl_from_text.3 \
+ acl_get.3 \
+ acl_get_brand_np.3 \
+ acl_get_entry.3 \
+ acl_get_entry_type_np.3 \
+ acl_get_flagset_np.3 \
+ acl_get_flag_np.3 \
+ acl_get_permset.3 \
+ acl_get_perm_np.3 \
+ acl_get_qualifier.3 \
+ acl_get_tag_type.3 \
+ acl_init.3 \
+ acl_is_trivial_np.3 \
+ acl_set.3 \
+ acl_set_entry_type_np.3 \
+ acl_set_flagset_np.3 \
+ acl_set_permset.3 \
+ acl_set_qualifier.3 \
+ acl_set_tag_type.3 \
+ acl_strip_np.3 \
+ acl_to_text.3 \
+ acl_valid.3 \
+ extattr.3 \
+ mac.3 \
+ mac.conf.5 \
+ mac_free.3 \
+ mac_is_present.3 \
+ mac_get.3 \
+ mac_prepare.3 \
+ mac_set.3 \
+ mac_text.3 \
+ posix1e.3
+
+MLINKS+=acl_create_entry.3 acl_create_entry_np.3\
+ acl_delete.3 acl_delete_def_file.3 \
+ acl_delete.3 acl_delete_file_np.3 \
+ acl_delete.3 acl_delete_fd_np.3 \
+ acl_delete_entry.3 acl_delete_entry_np.3\
+ acl_get.3 acl_get_file.3 \
+ acl_get.3 acl_get_fd.3 \
+ acl_get.3 acl_get_fd_np.3 \
+ acl_get.3 acl_get_link_np.3 \
+ acl_set.3 acl_set_file.3 \
+ acl_set.3 acl_set_fd.3 \
+ acl_set.3 acl_set_fd_np.3 \
+ acl_set.3 acl_set_link_np.3 \
+ acl_to_text.3 acl_to_text_np.3 \
+ acl_valid.3 acl_valid_file_np.3 \
+ acl_valid.3 acl_valid_fd_np.3 \
+ extattr.3 extattr_namespace_to_string.3 \
+ extattr.3 extattr_string_to_namespace.3 \
+ mac_get.3 mac_get_fd.3 \
+ mac_get.3 mac_get_file.3 \
+ mac_get.3 mac_get_link.3 \
+ mac_get.3 mac_get_peer.3 \
+ mac_get.3 mac_get_pid.3 \
+ mac_get.3 mac_get_proc.3 \
+ mac_prepare.3 mac_prepare_file_label.3 \
+ mac_prepare.3 mac_prepare_ifnet_label.3 \
+ mac_prepare.3 mac_prepare_process_label.3 \
+ mac_prepare.3 mac_prepare_type.3 \
+ mac_set.3 mac_set_fd.3 \
+ mac_set.3 mac_set_file.3 \
+ mac_set.3 mac_set_link.3 \
+ mac_set.3 mac_set_proc.3 \
+ mac_text.3 mac_from_text.3 \
+ mac_text.3 mac_to_text.3
+
+CLEANFILES+= subr_acl_nfs4.c
diff --git a/lib/libc/posix1e/Symbol.map b/lib/libc/posix1e/Symbol.map
new file mode 100644
index 0000000..346c8ca
--- /dev/null
+++ b/lib/libc/posix1e/Symbol.map
@@ -0,0 +1,86 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ acl_calc_mask;
+ acl_copy_entry;
+ acl_copy_ext;
+ acl_copy_int;
+ acl_delete_def_file;
+ acl_delete_def_link_np;
+ acl_delete_file_np;
+ acl_delete_link_np;
+ acl_delete_fd_np;
+ acl_delete_entry;
+ acl_create_entry;
+ acl_get_entry;
+ acl_free;
+ acl_from_text;
+ acl_get_file;
+ acl_get_link_np;
+ acl_get_fd;
+ acl_get_fd_np;
+ acl_get_permset;
+ acl_get_qualifier;
+ acl_get_tag_type;
+ acl_init;
+ acl_dup;
+ acl_clear_perms;
+ acl_set_file;
+ acl_set_link_np;
+ acl_set_fd;
+ acl_set_fd_np;
+ acl_set_permset;
+ acl_set_qualifier;
+ acl_set_tag_type;
+ acl_to_text;
+ acl_valid;
+ acl_valid_file_np;
+ acl_valid_link_np;
+ acl_valid_fd_np;
+ extattr_namespace_to_string;
+ extattr_string_to_namespace;
+ mac_reload;
+ mac_free;
+ mac_from_text;
+ mac_to_text;
+ mac_prepare;
+ mac_prepare_type;
+ mac_prepare_ifnet_label;
+ mac_prepare_file_label;
+ mac_prepare_packet_label;
+ mac_prepare_process_label;
+ mac_is_present;
+ mac_execve;
+ mac_get_fd;
+ mac_get_file;
+ mac_get_link;
+ mac_get_peer;
+ mac_get_pid;
+ mac_get_proc;
+ mac_set_fd;
+ mac_set_file;
+ mac_set_link;
+ mac_set_proc;
+};
+
+FBSD_1.1 {
+ acl_add_flag_np;
+ acl_add_perm;
+ acl_clear_flags_np;
+ acl_create_entry_np;
+ acl_delete_entry_np;
+ acl_delete_flag_np;
+ acl_delete_perm;
+ acl_get_brand_np;
+ acl_get_entry_type_np;
+ acl_get_flag_np;
+ acl_get_flagset_np;
+ acl_get_perm_np;
+ acl_is_trivial_np;
+ acl_set_entry_type_np;
+ acl_set_flagset_np;
+ acl_strip_np;
+ acl_to_text_np;
+};
diff --git a/lib/libc/posix1e/acl.3 b/lib/libc/posix1e/acl.3
new file mode 100644
index 0000000..717df67
--- /dev/null
+++ b/lib/libc/posix1e/acl.3
@@ -0,0 +1,298 @@
+.\"-
+.\" Copyright (c) 2000, 2001, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL 3
+.Os
+.Sh NAME
+.Nm acl
+.Nd introduction to the POSIX.1e ACL security API
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Sh DESCRIPTION
+.Fx
+permits file systems to export Access Control Lists via the VFS, and
+provides a library for userland access to and manipulation of these ACLs.
+Not all file systems provide support for ACLs, and some may require that
+ACL support be explicitly enabled by the administrator.
+The library calls include routines to allocate, duplicate, retrieve, set,
+and validate ACLs associated with file objects.
+As well as the POSIX.1e routines, there are a number of non-portable
+extensions defined that allow for alternative ACL semantics than the
+POSIX.1e semantics, such as NFSv4, AFS, NTFS, Coda, and NWFS semantics.
+Where routines are non-standard, they are suffixed with _np to indicate that
+they are not portable.
+.Pp
+POSIX.1e describes a set of ACL manipulation routines to manage the
+contents of ACLs, as well as their relationships with files; almost
+all of these support routines are implemented in
+.Fx .
+.Pp
+Available functions, sorted by behavior, include:
+.Bl -tag -width indent
+.It Fn acl_add_flag_np
+This function is described in
+.Xr acl_add_flag_np 3 ,
+and may be used to add flags to a flagset.
+.It Fn acl_add_perm
+This function is described in
+.Xr acl_add_perm 3 ,
+and may be used to add permissions to a permission set.
+.It Fn acl_calc_mask
+This function is described in
+.Xr acl_calc_mask 3 ,
+and may be used to calculate and set the permissions associated with
+the
+.Dv ACL_MASK
+entry.
+.It Fn acl_clear_flags_np
+This function is described in
+.Xr acl_clear_flags_np 3 ,
+and may be used to clear all flags from a flagset.
+.It Fn acl_clear_perms
+This function is described in
+.Xr acl_clear_perms 3 ,
+and may be used to clear all permissions from a permission set.
+.It Fn acl_copy_entry
+This function is described in
+.Xr acl_copy_entry 3 ,
+and may be used to copy the contents of an ACL entry.
+.It Xo
+.Fn acl_create_entry ,
+.Fn acl_create_entry_np
+.Xc
+These functions are described in
+.Xr acl_create_entry 3 ,
+and may be used to create an empty entry in an ACL.
+.It Xo
+.Fn acl_delete_def_file ,
+.Fn acl_delete_def_link_np ,
+.Fn acl_delete_fd_np ,
+.Fn acl_delete_file_np ,
+.Fn acl_delete_link_np
+.Xc
+These functions are described in
+.Xr acl_delete 3 ,
+and may be used to delete ACLs from file system objects.
+.It Xo
+.Fn acl_delete_entry ,
+.Fn acl_delete_entry_np ,
+.Xc
+This functions are described in
+.Xr acl_delete_entry 3 ,
+and may be used to delete an entry from an ACL.
+.It Fn acl_delete_flag_np
+This function is described in
+.Xr acl_delete_flag_np 3 ,
+and may be used to delete flags from a flagset.
+.It Fn acl_delete_perm
+This function is described in
+.Xr acl_delete_perm 3 ,
+and may be used to delete permissions from a permset.
+.It Fn acl_dup
+This function is described in
+.Xr acl_dup 3 ,
+and may be used to duplicate an ACL structure.
+.It Fn acl_free
+This function is described in
+.Xr acl_free 3 ,
+and may be used to free userland working ACL storage.
+.It Fn acl_from_text
+This function is described in
+.Xr acl_from_text 3 ,
+and may be used to convert a text-form ACL into working ACL state, if
+the ACL has POSIX.1e or NFSv4 semantics.
+.It Fn acl_get_entry
+This function is described in
+.Xr acl_get_entry 3 ,
+and may be used to retrieve a designated ACL entry from an ACL.
+.It Xo
+.Fn acl_get_fd ,
+.Fn acl_get_fd_np ,
+.Fn acl_get_file ,
+.Fn acl_get_link_np
+.Xc
+These functions are described in
+.Xr acl_get 3 ,
+and may be used to retrieve ACLs from file system objects.
+.It Fn acl_get_entry_type_np
+This function is described in
+.Xr acl_get_entry_type_np 3 ,
+and may be used to retrieve an ACL type from an ACL entry.
+.It Fn acl_get_flagset_np
+This function is described in
+.Xr acl_get_flagset_np 3 ,
+and may be used to retrieve a flagset from an ACL entry.
+.It Fn acl_get_permset
+This function is described in
+.Xr acl_get_permset 3 ,
+and may be used to retrieve a permset from an ACL entry.
+.It Fn acl_get_qualifier
+This function is described in
+.Xr acl_get_qualifier 3 ,
+and may be used to retrieve the qualifier from an ACL entry.
+.It Fn acl_get_tag_type
+This function is described in
+.Xr acl_get_tag_type 3 ,
+and may be used to retrieve the tag type from an ACL entry.
+.It Fn acl_init
+This function is described in
+.Xr acl_init 3 ,
+and may be used to allocate a fresh (empty) ACL structure.
+.It Fn acl_is_trivial_np
+This function is described in
+.Xr acl_is_trivial_np 3 ,
+and may be used to find out whether ACL is trivial.
+.It Xo
+.Fn acl_set_fd ,
+.Fn acl_set_fd_np ,
+.Fn acl_set_file ,
+.Fn acl_set_link_np
+.Xc
+These functions are described in
+.Xr acl_set 3 ,
+and may be used to assign an ACL to a file system object.
+.It Fn acl_set_entry_type_np
+This function is described in
+.Xr acl_set_entry_type_np 3 ,
+and may be used to set the ACL type of an ACL entry.
+.It Fn acl_set_flagset_np
+This function is described in
+.Xr acl_set_flagset_np 3 ,
+and may be used to set the flags of an ACL entry from a flagset.
+.It Fn acl_set_permset
+This function is described in
+.Xr acl_set_permset 3 ,
+and may be used to set the permissions of an ACL entry from a permset.
+.It Fn acl_set_qualifier
+This function is described in
+.Xr acl_set_qualifier 3 ,
+and may be used to set the qualifier of an ACL.
+.It Fn acl_set_tag_type
+This function is described in
+.Xr acl_set_tag_type 3 ,
+and may be used to set the tag type of an ACL.
+.It Fn acl_strip_np
+This function is describe din
+.Xr acl-strip_np 3 ,
+and may be used to remove extended entries from an ACL.
+.It Xo
+.Fn acl_to_text ,
+.Fn acl_to_text_np
+.Xc
+These functions are described in
+.Xr acl_to_text 3 ,
+and may be used to generate a text-form of a POSIX.1e or NFSv4 semantics ACL.
+.It Xo
+.Fn acl_valid ,
+.Fn acl_valid_fd_np ,
+.Fn acl_valid_file_np ,
+.Fn acl_valid_link_np
+.Xc
+These functions are described in
+.Xr acl_valid 3 ,
+and may be used to validate an ACL as correct POSIX.1e-semantics, or
+as appropriate for a particular file system object regardless of semantics.
+.El
+.Pp
+Documentation of the internal kernel interfaces backing these calls may
+be found in
+.Xr acl 9 .
+The syscalls between the internal interfaces and the public library
+routines may change over time, and as such are not documented.
+They are not intended to be called directly without going through the
+library.
+.Sh SEE ALSO
+.Xr getfacl 1 ,
+.Xr setfacl 1 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_add_perm 3 ,
+.Xr acl_calc_mask 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_clear_perms 3 ,
+.Xr acl_copy_entry 3 ,
+.Xr acl_create_entry 3 ,
+.Xr acl_delete_entry 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_delete_perm 3 ,
+.Xr acl_dup 3 ,
+.Xr acl_free 3 ,
+.Xr acl_from_text 3 ,
+.Xr acl_get 3 ,
+.Xr acl_get_entry_type_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr acl_get_permset 3 ,
+.Xr acl_get_qualifier 3 ,
+.Xr acl_get_tag_type 3 ,
+.Xr acl_init 3 ,
+.Xr acl_is_trivial_np 3 ,
+.Xr acl_set 3 ,
+.Xr acl_set_entry_type_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr acl_set_permset 3 ,
+.Xr acl_set_qualifier 3 ,
+.Xr acl_set_tag_type 3 ,
+.Xr acl_strip_np 3 ,
+.Xr acl_to_text 3 ,
+.Xr acl_valid 3 ,
+.Xr posix1e 3 ,
+.Xr acl 9
+.Sh STANDARDS
+POSIX.1e assigns security labels to all objects, extending the security
+functionality described in POSIX.1.
+These additional labels provide fine-grained discretionary access control,
+fine-grained capabilities, and labels necessary for mandatory access
+control.
+POSIX.2c describes a set of userland utilities for manipulating these
+labels.
+.Pp
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion of the draft continues on the cross-platform POSIX.1e
+implementation mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ;
+.Fx 5.0
+was the first version to include a complete ACL implementation based
+on extended attributes for the UFS and UFS2 file systems.
+.Pp
+The
+.Xr getfacl 1
+and
+.Xr setfacl 1
+utilities describe the user tools that permit direct manipulation of complete
+file ACLs.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_add_flag_np.3 b/lib/libc/posix1e/acl_add_flag_np.3
new file mode 100644
index 0000000..057de03
--- /dev/null
+++ b/lib/libc/posix1e/acl_add_flag_np.3
@@ -0,0 +1,97 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_ADD_FLAG_NP 3
+.Os
+.Sh NAME
+.Nm acl_add_flag_np
+.Nd add flags to a flagset
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_add_flag_np "acl_flagset_t flagset_d" "acl_flag_t flag"
+.Sh DESCRIPTION
+The
+.Fn acl_add_flag_np
+function
+is a non-portable call that adds the flags contained in
+.Fa flags
+to the flagset
+.Fa flagset_d .
+.Pp
+Note: it is not considered an error to attempt to add flags
+that already exist in the flagset.
+.Pp
+Valid values are:
+.Bl -column -offset 3n "ACL_ENTRY_NO_PROPAGATE_INHERIT"
+.It ACL_ENTRY_FILE_INHERIT Ta "Will be inherited by files."
+.It ACL_ENTRY_DIRECTORY_INHERIT Ta "Will be inherited by directories."
+.It ACL_ENTRY_NO_PROPAGATE_INHERIT Ta "Will not propagate."
+.It ACL_ENTRY_INHERIT_ONLY Ta "Inherit-only."
+.El
+.Sh RETURN VALUES
+.Rv -std acl_add_flag_np
+.Sh ERRORS
+The
+.Fn acl_add_flag_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa flagset_d
+is not a valid descriptor for a flagset within an ACL entry.
+Argument
+.Fa flag
+does not contain a valid
+.Vt acl_flag_t
+value.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_add_flag_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_add_flag_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_add_perm.3 b/lib/libc/posix1e/acl_add_perm.3
new file mode 100644
index 0000000..564b83d
--- /dev/null
+++ b/lib/libc/posix1e/acl_add_perm.3
@@ -0,0 +1,129 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_ADD_PERM 3
+.Os
+.Sh NAME
+.Nm acl_add_perm
+.Nd add permissions to a permission set
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_add_perm "acl_permset_t permset_d" "acl_perm_t perm"
+.Sh DESCRIPTION
+The
+.Fn acl_add_perm
+function
+is a POSIX.1e call that adds the permission contained in
+.Fa perm
+to the permission set
+.Fa permset_d .
+.Pp
+Note: it is not considered an error to attempt to add permissions
+that already exist in the permission set.
+.Pp
+For POSIX.1e ACLs, valid values are:
+.Bl -column -offset 3n "ACL_WRITE_NAMED_ATTRS"
+.It ACL_EXECUTE Execute permission
+.It ACL_WRITE Write permission
+.It ACL_READ Read permission
+.El
+.Pp
+For NFSv4 ACLs, valid values are:
+.Bl -column -offset 3n "ACL_WRITE_NAMED_ATTRS"
+.It ACL_READ_DATA Ta "Read permission"
+.It ACL_LIST_DIRECTORY Ta "Same as ACL_READ_DATA"
+.It ACL_WRITE_DATA Ta "Write permission, or permission to create files"
+.It ACL_ADD_FILE Ta "Same as ACL_READ_DATA"
+.It ACL_APPEND_DATA Ta "Permission to create directories. Ignored for files"
+.It ACL_ADD_SUBDIRECTORY Ta "Same as ACL_APPEND_DATA"
+.It ACL_READ_NAMED_ATTRS Ta "Ignored"
+.It ACL_WRITE_NAMED_ATTRS Ta "Ignored"
+.It ACL_EXECUTE Ta "Execute permission"
+.It ACL_DELETE_CHILD Ta "Permission to delete files and subdirectories"
+.It ACL_READ_ATTRIBUTES Ta "Permission to read basic attributes"
+.It ACL_WRITE_ATTRIBUTES Ta "Permission to change basic attributes"
+.It ACL_DELETE Ta "Permission to delete the object this ACL is placed on"
+.It ACL_READ_ACL Ta "Permission to read ACL"
+.It ACL_WRITE_ACL Ta "Permission to change the ACL and file mode"
+.It ACL_SYNCHRONIZE Ta "Ignored"
+.El
+.Pp
+Calling
+.Fn acl_add_perm
+with
+.Fa perm
+equal to ACL_WRITE or ACL_READ brands the ACL as POSIX.
+Calling it with ACL_READ_DATA, ACL_LIST_DIRECTORY, ACL_WRITE_DATA,
+ACL_ADD_FILE, ACL_APPEND_DATA, ACL_ADD_SUBDIRECTORY, ACL_READ_NAMED_ATTRS,
+ACL_WRITE_NAMED_ATTRS, ACL_DELETE_CHILD, ACL_READ_ATTRIBUTES,
+ACL_WRITE_ATTRIBUTES, ACL_DELETE, ACL_READ_ACL, ACL_WRITE_ACL
+or ACL_SYNCHRONIZE brands the ACL as NFSv4.
+.Sh RETURN VALUES
+.Rv -std acl_add_perm
+.Sh ERRORS
+The
+.Fn acl_add_perm
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa permset_d
+is not a valid descriptor for a permission set within an ACL entry.
+Argument
+.Fa perm
+does not contain a valid
+.Vt acl_perm_t
+value.
+ACL is already branded differently.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_clear_perms 3 ,
+.Xr acl_delete_perm 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_get_permset 3 ,
+.Xr acl_set_permset 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_add_perm
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_add_perm
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_branding.c b/lib/libc/posix1e/acl_branding.c
new file mode 100644
index 0000000..84b0063
--- /dev/null
+++ b/lib/libc/posix1e/acl_branding.c
@@ -0,0 +1,169 @@
+/*-
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <errno.h>
+#include <sys/acl.h>
+
+#include "acl_support.h"
+
+/*
+ * An ugly detail of the implementation - fortunately not visible
+ * to the API users - is the "branding": libc needs to keep track
+ * of what "brand" ACL is: NFSv4, POSIX.1e or unknown. It happens
+ * automatically - for example, during acl_get_file(3) ACL gets
+ * branded according to the "type" argument; during acl_set_permset
+ * ACL, if its brand is unknown it gets branded as NFSv4 if any of the
+ * NFSv4 permissions that are not valid for POSIX.1e ACL are set etc.
+ * Branding information is used for printing out the ACL (acl_to_text(3)),
+ * veryfying acl_set_whatever arguments (checking against setting
+ * bits that are valid only for NFSv4 in ACL branded as POSIX.1e) etc.
+ */
+
+static acl_t
+entry2acl(acl_entry_t entry)
+{
+ acl_t aclp;
+
+ aclp = (acl_t)(((long)entry >> _ACL_T_ALIGNMENT_BITS) << _ACL_T_ALIGNMENT_BITS);
+
+ return (aclp);
+}
+
+/*
+ * Return brand of an ACL.
+ */
+int
+_acl_brand(const acl_t acl)
+{
+
+ return (acl->ats_brand);
+}
+
+int
+_entry_brand(const acl_entry_t entry)
+{
+
+ return (_acl_brand(entry2acl(entry)));
+}
+
+/*
+ * Return 1, iff branding ACL as "brand" is ok.
+ */
+int
+_acl_brand_may_be(const acl_t acl, int brand)
+{
+
+ if (_acl_brand(acl) == ACL_BRAND_UNKNOWN)
+ return (1);
+
+ if (_acl_brand(acl) == brand)
+ return (1);
+
+ return (0);
+}
+
+int
+_entry_brand_may_be(const acl_entry_t entry, int brand)
+{
+
+ return (_acl_brand_may_be(entry2acl(entry), brand));
+}
+
+/*
+ * Brand ACL as "brand".
+ */
+void
+_acl_brand_as(acl_t acl, int brand)
+{
+
+ assert(_acl_brand_may_be(acl, brand));
+
+ acl->ats_brand = brand;
+}
+
+void
+_entry_brand_as(const acl_entry_t entry, int brand)
+{
+
+ _acl_brand_as(entry2acl(entry), brand);
+}
+
+int
+_acl_type_not_valid_for_acl(const acl_t acl, acl_type_t type)
+{
+
+ switch (_acl_brand(acl)) {
+ case ACL_BRAND_NFS4:
+ if (type == ACL_TYPE_NFS4)
+ return (0);
+ break;
+
+ case ACL_BRAND_POSIX:
+ if (type == ACL_TYPE_ACCESS || type == ACL_TYPE_DEFAULT)
+ return (0);
+ break;
+
+ case ACL_BRAND_UNKNOWN:
+ return (0);
+ }
+
+ return (-1);
+}
+
+void
+_acl_brand_from_type(acl_t acl, acl_type_t type)
+{
+
+ switch (type) {
+ case ACL_TYPE_NFS4:
+ _acl_brand_as(acl, ACL_BRAND_NFS4);
+ break;
+ case ACL_TYPE_ACCESS:
+ case ACL_TYPE_DEFAULT:
+ _acl_brand_as(acl, ACL_BRAND_POSIX);
+ break;
+ default:
+ /* XXX: What to do here? */
+ break;
+ }
+}
+
+int
+acl_get_brand_np(acl_t acl, int *brand_p)
+{
+
+ if (acl == NULL || brand_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ *brand_p = _acl_brand(acl);
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_calc_mask.3 b/lib/libc/posix1e/acl_calc_mask.3
new file mode 100644
index 0000000..7bcdb40
--- /dev/null
+++ b/lib/libc/posix1e/acl_calc_mask.3
@@ -0,0 +1,98 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 10, 2001
+.Dt ACL_CALC_MASK 3
+.Os
+.Sh NAME
+.Nm acl_calc_mask
+.Nd calculate and set ACL mask permissions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_calc_mask "acl_t *acl_p"
+.Sh DESCRIPTION
+The
+.Fn acl_calc_mask
+function
+is a POSIX.1e call that calculates and set the permissions
+associated with the
+.Dv ACL_MASK
+ACL entry of the ACL referred to by
+.Fa acl_p .
+.Pp
+The value of new permissions are the union of the permissions
+granted by the
+.Dv ACL_GROUP , ACL_GROUP_OBJ , ACL_USER
+tag types which
+match processes in the file group class contained in the ACL
+referred to by
+.Fa acl_p .
+.Pp
+If the ACL referred to by
+.Fa acl_p
+already contains an
+.Dv ACL_MASK
+entry, its permissions shall be
+overwritten; if it does not contain an
+.Dv ACL_MASK
+entry, one shall
+be added.
+.Sh RETURN VALUES
+.Rv -std acl_calc_mask
+.Sh ERRORS
+The
+.Fn acl_calc_mask
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa acl_p
+does not point to a pointer to a valid ACL.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get_entry 3 ,
+.Xr acl_valid 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_calc_mask
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_calc_mask
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_calc_mask.c b/lib/libc/posix1e/acl_calc_mask.c
new file mode 100644
index 0000000..a2d1527
--- /dev/null
+++ b/lib/libc/posix1e/acl_calc_mask.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2001-2002 Chris D. Faulhaber
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+
+#include <errno.h>
+#include <stdio.h>
+
+#include "acl_support.h"
+
+/*
+ * acl_calc_mask() (23.4.2): calculate and set the permissions
+ * associated with the ACL_MASK ACL entry. If the ACL already
+ * contains an ACL_MASK entry, its permissions shall be
+ * overwritten; if not, one shall be added.
+ */
+int
+acl_calc_mask(acl_t *acl_p)
+{
+ struct acl *acl_int, *acl_int_new;
+ acl_t acl_new;
+ int i, mask_mode, mask_num;
+
+ /*
+ * (23.4.2.4) requires acl_p to point to a pointer to a valid ACL.
+ * Since one of the primary reasons to use this function would be
+ * to calculate the appropriate mask to obtain a valid ACL, we only
+ * perform sanity checks here and validate the ACL prior to
+ * returning.
+ */
+ if (acl_p == NULL || *acl_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (!_acl_brand_may_be(*acl_p, ACL_BRAND_POSIX)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _acl_brand_as(*acl_p, ACL_BRAND_POSIX);
+
+ acl_int = &(*acl_p)->ats_acl;
+ if ((acl_int->acl_cnt < 3) || (acl_int->acl_cnt > ACL_MAX_ENTRIES)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ acl_new = acl_dup(*acl_p);
+ if (acl_new == NULL)
+ return (-1);
+ acl_int_new = &acl_new->ats_acl;
+
+ mask_mode = 0;
+ mask_num = -1;
+
+ /* gather permissions and find a mask entry */
+ for (i = 0; i < acl_int_new->acl_cnt; i++) {
+ switch(acl_int_new->acl_entry[i].ae_tag) {
+ case ACL_USER:
+ case ACL_GROUP:
+ case ACL_GROUP_OBJ:
+ mask_mode |=
+ acl_int_new->acl_entry[i].ae_perm & ACL_PERM_BITS;
+ break;
+ case ACL_MASK:
+ mask_num = i;
+ break;
+ }
+ }
+
+ /* if a mask entry already exists, overwrite the perms */
+ if (mask_num != -1)
+ acl_int_new->acl_entry[mask_num].ae_perm = mask_mode;
+ else {
+ /* if no mask exists, check acl_cnt... */
+ if (acl_int_new->acl_cnt == ACL_MAX_ENTRIES) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ /* ...and add the mask entry */
+ acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_tag = ACL_MASK;
+ acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_id =
+ ACL_UNDEFINED_ID;
+ acl_int_new->acl_entry[acl_int_new->acl_cnt].ae_perm =
+ mask_mode;
+ acl_int_new->acl_cnt++;
+ }
+
+ if (acl_valid(acl_new) == -1) {
+ errno = EINVAL;
+ acl_free(acl_new);
+ return (-1);
+ }
+
+ **acl_p = *acl_new;
+ acl_free(acl_new);
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_clear_flags_np.3 b/lib/libc/posix1e/acl_clear_flags_np.3
new file mode 100644
index 0000000..0780e14
--- /dev/null
+++ b/lib/libc/posix1e/acl_clear_flags_np.3
@@ -0,0 +1,79 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_CLEAR_FLAGS_NP 3
+.Os
+.Sh NAME
+.Nm acl_clear_flags_np
+.Nd clear flags from a flagset
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_clear_flags_np "acl_flagset_t flagset_d"
+.Sh DESCRIPTION
+The
+.Fn acl_clear_flags_np
+function
+is a non-portable call that clears all flags from flagset
+.Fa flagset_d .
+.Sh RETURN VALUES
+.Rv -std acl_clear_flags_np
+.Sh ERRORS
+The
+.Fn acl_clear_flags_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa flagset_d
+is not a valid descriptor for a flagset.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_clear_flags_np
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_clear_flags_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_clear_perms.3 b/lib/libc/posix1e/acl_clear_perms.3
new file mode 100644
index 0000000..df82b6c
--- /dev/null
+++ b/lib/libc/posix1e/acl_clear_perms.3
@@ -0,0 +1,79 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 10, 2001
+.Dt ACL_CLEAR_PERMS 3
+.Os
+.Sh NAME
+.Nm acl_clear_perms
+.Nd clear permissions from a permission set
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_clear_perms "acl_permset_t permset_d"
+.Sh DESCRIPTION
+The
+.Fn acl_clear_perms
+function
+is a POSIX.1e call that clears all permissions from permissions set
+.Fa permset_d .
+.Sh RETURN VALUES
+.Rv -std acl_clear_perms
+.Sh ERRORS
+The
+.Fn acl_clear_perms
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa permset_d
+is not a valid descriptor for a permission set.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_perm 3 ,
+.Xr acl_delete_perm 3 ,
+.Xr acl_get_permset 3 ,
+.Xr acl_set_permset 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_clear_perms
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_clear_perms
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_compat.c b/lib/libc/posix1e/acl_compat.c
new file mode 100644
index 0000000..c433920
--- /dev/null
+++ b/lib/libc/posix1e/acl_compat.c
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2008 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/acl.h>
+
+/*
+ * Compatibility wrappers for applications compiled against libc from before
+ * NFSv4 ACLs were added.
+ */
+int
+__oldacl_get_perm_np(acl_permset_t permset_d, oldacl_perm_t perm)
+{
+
+ return (acl_get_perm_np(permset_d, perm));
+}
+
+int
+__oldacl_add_perm(acl_permset_t permset_d, oldacl_perm_t perm)
+{
+
+ return (acl_add_perm(permset_d, perm));
+}
+
+int
+__oldacl_delete_perm(acl_permset_t permset_d, oldacl_perm_t perm)
+{
+
+ return (acl_delete_perm(permset_d, perm));
+}
+
+__sym_compat(acl_get_perm_np, __oldacl_get_perm_np, FBSD_1.0);
+__sym_compat(acl_add_perm, __oldacl_add_perm, FBSD_1.0);
+__sym_compat(acl_delete_perm, __oldacl_delete_perm, FBSD_1.0);
diff --git a/lib/libc/posix1e/acl_copy.c b/lib/libc/posix1e/acl_copy.c
new file mode 100644
index 0000000..fc4c25d
--- /dev/null
+++ b/lib/libc/posix1e/acl_copy.c
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2001-2002 Chris D. Faulhaber
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+
+#include <errno.h>
+#include <string.h>
+
+#include "acl_support.h"
+
+/*
+ * acl_copy_entry() (23.4.4): copy the contents of ACL entry src_d to
+ * ACL entry dest_d
+ */
+int
+acl_copy_entry(acl_entry_t dest_d, acl_entry_t src_d)
+{
+
+ if (src_d == NULL || dest_d == NULL || src_d == dest_d) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /*
+ * Can we brand the new entry the same as the source entry?
+ */
+ if (!_entry_brand_may_be(dest_d, _entry_brand(src_d))) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ _entry_brand_as(dest_d, _entry_brand(src_d));
+
+ dest_d->ae_tag = src_d->ae_tag;
+ dest_d->ae_id = src_d->ae_id;
+ dest_d->ae_perm = src_d->ae_perm;
+ dest_d->ae_entry_type = src_d->ae_entry_type;
+ dest_d->ae_flags = src_d->ae_flags;
+
+ return (0);
+}
+
+ssize_t
+acl_copy_ext(void *buf_p, acl_t acl, ssize_t size)
+{
+
+ errno = ENOSYS;
+ return (-1);
+}
+
+acl_t
+acl_copy_int(const void *buf_p)
+{
+
+ errno = ENOSYS;
+ return (NULL);
+}
diff --git a/lib/libc/posix1e/acl_copy_entry.3 b/lib/libc/posix1e/acl_copy_entry.3
new file mode 100644
index 0000000..586b822
--- /dev/null
+++ b/lib/libc/posix1e/acl_copy_entry.3
@@ -0,0 +1,85 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 10, 2001
+.Dt ACL_COPY_ENTRY 3
+.Os
+.Sh NAME
+.Nm acl_copy_entry
+.Nd copy an ACL entry to another ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_copy_entry "acl_entry_t dest_d" "acl_entry_t src_d"
+.Sh DESCRIPTION
+The
+.Fn acl_copy_entry
+function
+is a POSIX.1e call that copies the contents of ACL entry
+.Fa src_d
+to ACL entry
+.Fa dest_d .
+.Sh RETURN VALUES
+.Rv -std acl_copy_entry
+.Sh ERRORS
+The
+.Fn acl_copy_entry
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa src_d
+or
+.Fa dest_d
+is not a valid descriptor for an ACL entry, or
+arguments
+.Fa src_d
+and
+.Fa dest_d
+reference the same ACL entry.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get_entry 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_copy_entry
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_copy_entry
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_create_entry.3 b/lib/libc/posix1e/acl_create_entry.3
new file mode 100644
index 0000000..784f687
--- /dev/null
+++ b/lib/libc/posix1e/acl_create_entry.3
@@ -0,0 +1,98 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_CREATE_ENTRY 3
+.Os
+.Sh NAME
+.Nm acl_create_entry
+.Nm acl_create_entry_np
+.Nd create a new ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_create_entry "acl_t *acl_p" "acl_entry_t *entry_p"
+.Ft int
+.Fn acl_create_entry_np "acl_t *acl_p" "acl_entry_t *entry_p" "int index"
+.Sh DESCRIPTION
+The
+.Fn acl_create_entry
+function
+is a POSIX.1e call that creates a new ACL entry in the ACL
+pointed to by
+.Fa acl_p .
+The
+.Fn acl_create_entry_np
+function is a non-portable version that creates the ACL entry
+at position
+.Fa index .
+Positions are numbered starting from zero, i.e. calling
+.Fn acl_create_entry_np
+with
+.Fa index
+argument equal to zero will prepend the entry to the ACL.
+.Sh RETURN VALUES
+.Rv -std acl_create_entry
+.Sh ERRORS
+The
+.Fn acl_create_entry
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa acl_p
+does not point to a pointer to a valid ACL.
+Argument
+.Fa index
+is out of bounds.
+.It Bq Er ENOMEM
+The ACL working storage requires more memory than is
+allowed by the hardware or system-imposed memory
+management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_delete_entry 3 ,
+.Xr acl_get_entry 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_create_entry
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_create_entry
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_delete.3 b/lib/libc/posix1e/acl_delete.3
new file mode 100644
index 0000000..fb2958b
--- /dev/null
+++ b/lib/libc/posix1e/acl_delete.3
@@ -0,0 +1,140 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 29, 2002
+.Dt ACL_DELETE 3
+.Os
+.Sh NAME
+.Nm acl_delete_def_file ,
+.Nm acl_delete_def_link_np ,
+.Nm acl_delete_fd_np ,
+.Nm acl_delete_file_np ,
+.Nm acl_delete_link_np
+.Nd delete an ACL from a file
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_delete_def_file "const char *path_p"
+.Ft int
+.Fn acl_delete_def_link_np "const char *path_p"
+.Ft int
+.Fn acl_delete_fd_np "int filedes" "acl_type_t type"
+.Ft int
+.Fn acl_delete_file_np "const char *path_p" "acl_type_t type"
+.Ft int
+.Fn acl_delete_link_np "const char *path_p" "acl_type_t type"
+.Sh DESCRIPTION
+The
+.Fn acl_delete_def_file ,
+.Fn acl_delete_def_link_np ,
+.Fn acl_delete_fd_np ,
+.Fn acl_delete_file_np ,
+and
+.Fn acl_delete_link_np
+each allow the deletion of an ACL from a file.
+The
+.Fn acl_delete_def_file
+function
+is a POSIX.1e call that deletes the default ACL from a file (normally a
+directory) by name; the remainder of the calls are non-portable extensions
+that permit the deletion of arbitrary ACL types from a file/directory
+either by path name or file descriptor.
+The
+.Fn _file
+variations follow a symlink if it occurs in the last segment of the
+path name; the
+.Fn _link
+variations operate on the symlink itself.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+If any of the following conditions occur, these functions shall return -1
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EACCES
+Search permission is denied for a component of the path prefix, or the
+object exists and the process does not have appropriate access rights.
+.It Bq Er EBADF
+The
+.Va fd
+argument is not a valid file descriptor.
+.It Bq Er EINVAL
+The ACL type passed is invalid for this file object.
+.It Bq Er ENAMETOOLONG
+A component of a pathname exceeded 255 characters, or an
+entire path name exceeded 1023 characters.
+.It Bq Er ENOENT
+The named object does not exist, or the
+.Va path_p
+argument points to an empty string.
+.It Bq Er ENOMEM
+Insufficient memory available to fulfill request.
+.It Bq Er ENOTDIR
+A component of the path prefix is not a directory.
+.Pp
+Argument
+.Va path_p
+must be a directory, and is not.
+.It Bq Er EOPNOTSUPP
+The file system does not support ACL deletion.
+.It Bq Er EPERM
+The process does not have appropriate privilege to perform the operation
+to delete an ACL.
+.It Bq Er EROFS
+The file system is read-only.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get 3 ,
+.Xr acl_set 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_delete.c b/lib/libc/posix1e/acl_delete.c
new file mode 100644
index 0000000..1bbadd5
--- /dev/null
+++ b/lib/libc/posix1e/acl_delete.c
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * acl_delete_def_file -- remove a default acl from a file
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+#include <sys/errno.h>
+
+#include "acl_support.h"
+
+int
+acl_delete_def_file(const char *path_p)
+{
+
+ return (__acl_delete_file(path_p, ACL_TYPE_DEFAULT));
+}
+
+int
+acl_delete_def_link_np(const char *path_p)
+{
+
+ return (__acl_delete_link(path_p, ACL_TYPE_DEFAULT));
+}
+
+int
+acl_delete_file_np(const char *path_p, acl_type_t type)
+{
+
+ type = _acl_type_unold(type);
+ return (__acl_delete_file(path_p, type));
+}
+
+int
+acl_delete_link_np(const char *path_p, acl_type_t type)
+{
+
+ type = _acl_type_unold(type);
+ return (__acl_delete_link(path_p, type));
+}
+
+int
+acl_delete_fd_np(int filedes, acl_type_t type)
+{
+
+ type = _acl_type_unold(type);
+ return (___acl_delete_fd(filedes, type));
+}
diff --git a/lib/libc/posix1e/acl_delete_entry.3 b/lib/libc/posix1e/acl_delete_entry.3
new file mode 100644
index 0000000..3705f07
--- /dev/null
+++ b/lib/libc/posix1e/acl_delete_entry.3
@@ -0,0 +1,101 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_DELETE_ENTRY 3
+.Os
+.Sh NAME
+.Nm acl_delete_entry ,
+.Nm acl_delete_entry_np ,
+.Nd delete an ACL entry from an ACL
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_delete_entry "acl_t acl" "acl_entry_t entry_d"
+.Ft int
+.Fn acl_delete_entry_np "acl_t acl" "int index"
+.Sh DESCRIPTION
+The
+.Fn acl_delete_entry
+function
+is a POSIX.1e call that removes the ACL entry
+.Fa entry_d
+from ACL
+.Fa acl .
+The
+.Fn acl_delete_entry_np
+function is a non-portable version that removes the ACL entry
+at position
+.Fa index
+from ACL
+.Fa acl .
+Positions are numbered starting from zero, i.e. calling
+.Fn acl_delete_entry_np
+with
+.Fa index
+argument equal to zero will remove the first ACL entry.
+.Sh RETURN VALUES
+.Rv -std acl_delete_entry
+.Sh ERRORS
+The
+.Fn acl_delete_entry
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa acl
+does not point to a valid ACL.
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry in
+.Fa acl .
+Argument
+.Fa index
+is out of bounds.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_copy_entry 3 ,
+.Xr acl_get_entry 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_delete_entry
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_delete_entry
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_delete_entry.c b/lib/libc/posix1e/acl_delete_entry.c
new file mode 100644
index 0000000..09b4507
--- /dev/null
+++ b/lib/libc/posix1e/acl_delete_entry.c
@@ -0,0 +1,162 @@
+/*
+ * Copyright (c) 2001-2002 Chris D. Faulhaber
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#include "acl_support.h"
+
+static int
+_entry_matches(const acl_entry_t a, const acl_entry_t b)
+{
+ /*
+ * There is a semantical difference here between NFSv4 and POSIX
+ * draft ACLs. In POSIX, there may be only one entry for the particular
+ * user or group. In NFSv4 ACL, there may be any number of them. We're
+ * trying to be more specific here in that case.
+ */
+ switch (_entry_brand(a)) {
+ case ACL_BRAND_NFS4:
+ if (a->ae_tag != b->ae_tag || a->ae_entry_type != b->ae_entry_type)
+ return (0);
+
+ /* If ae_ids matter, compare them as well. */
+ if (a->ae_tag == ACL_USER || a->ae_tag == ACL_GROUP) {
+ if (a->ae_id != b->ae_id)
+ return (0);
+ }
+
+ return (1);
+
+ default:
+ if ((a->ae_tag == b->ae_tag) && (a->ae_id == b->ae_id))
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * acl_delete_entry() (23.4.9): remove the ACL entry indicated by entry_d
+ * from acl.
+ */
+int
+acl_delete_entry(acl_t acl, acl_entry_t entry_d)
+{
+ struct acl *acl_int;
+ struct acl_entry entry_int;
+ int i, j, found = 0;
+
+ if (acl == NULL || entry_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ acl_int = &acl->ats_acl;
+
+ if (_entry_brand(entry_d) != _acl_brand(acl)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((acl->ats_acl.acl_cnt < 1) ||
+ (acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* Use a local copy to prevent deletion of more than this entry */
+ entry_int = *entry_d;
+
+ for (i = 0; i < acl->ats_acl.acl_cnt;) {
+ if (_entry_matches(&(acl->ats_acl.acl_entry[i]), &entry_int)) {
+ /* ...shift the remaining entries... */
+ for (j = i; j < acl->ats_acl.acl_cnt - 1; ++j)
+ acl->ats_acl.acl_entry[j] =
+ acl->ats_acl.acl_entry[j+1];
+ /* ...drop the count and zero the unused entry... */
+ acl->ats_acl.acl_cnt--;
+ bzero(&acl->ats_acl.acl_entry[j],
+ sizeof(struct acl_entry));
+ acl->ats_cur_entry = 0;
+
+ /* Continue with the loop to remove all maching entries. */
+ found = 1;
+ } else
+ i++;
+ }
+
+ if (found)
+ return (0);
+
+ errno = EINVAL;
+ return (-1);
+}
+
+int
+acl_delete_entry_np(acl_t acl, int offset)
+{
+ struct acl *acl_int;
+ int i;
+
+ if (acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ acl_int = &acl->ats_acl;
+
+ if (offset < 0 || offset >= acl_int->acl_cnt) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((acl->ats_acl.acl_cnt < 1) ||
+ (acl->ats_acl.acl_cnt > ACL_MAX_ENTRIES)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* ...shift the remaining entries... */
+ for (i = offset; i < acl->ats_acl.acl_cnt - 1; ++i)
+ acl->ats_acl.acl_entry[i] =
+ acl->ats_acl.acl_entry[i+1];
+ /* ...drop the count and zero the unused entry... */
+ acl->ats_acl.acl_cnt--;
+ bzero(&acl->ats_acl.acl_entry[i],
+ sizeof(struct acl_entry));
+ acl->ats_cur_entry = 0;
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_delete_flag_np.3 b/lib/libc/posix1e/acl_delete_flag_np.3
new file mode 100644
index 0000000..a288978
--- /dev/null
+++ b/lib/libc/posix1e/acl_delete_flag_np.3
@@ -0,0 +1,84 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 10, 2001
+.Dt ACL_DELETE_FLAG_NP 3
+.Os
+.Sh NAME
+.Nm acl_delete_flag_np
+.Nd delete flags from a flagset
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_delete_flag_np "acl_flagset_t flagset_d" "acl_flag_t flag"
+.Sh DESCRIPTION
+The
+.Fn acl_delete_flag_np
+function
+is a non-portable call that removes specific flags from flagset
+.Fa flags .
+.Sh RETURN VALUES
+.Rv -std acl_delete_flag_np
+.Sh ERRORS
+The
+.Fn acl_delete_flag_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa flagset_d
+is not a valid descriptor for a flagset.
+Argument
+.Fa flag
+does not contain a valid
+.Vt acl_flag_t
+value.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_clear_flag_nps 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_delete_flag_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_delete_flag_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_delete_perm.3 b/lib/libc/posix1e/acl_delete_perm.3
new file mode 100644
index 0000000..b6c7250
--- /dev/null
+++ b/lib/libc/posix1e/acl_delete_perm.3
@@ -0,0 +1,84 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 10, 2001
+.Dt ACL_DELETE_PERM 3
+.Os
+.Sh NAME
+.Nm acl_delete_perm
+.Nd delete permissions from a permission set
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_delete_perm "acl_permset_t permset_d" "acl_perm_t perm"
+.Sh DESCRIPTION
+The
+.Fn acl_delete_perm
+function
+is a POSIX.1e call that removes specific permissions from permissions set
+.Fa perm .
+.Sh RETURN VALUES
+.Rv -std acl_delete_perm
+.Sh ERRORS
+The
+.Fn acl_delete_perm
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa permset_d
+is not a valid descriptor for a permission set.
+Argument
+.Fa perm
+does not contain a valid
+.Vt acl_perm_t
+value.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_perm 3 ,
+.Xr acl_clear_perms 3 ,
+.Xr acl_get_permset 3 ,
+.Xr acl_set_permset 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_delete_perm
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_delete_perm
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_dup.3 b/lib/libc/posix1e/acl_dup.3
new file mode 100644
index 0000000..ae4ff4f
--- /dev/null
+++ b/lib/libc/posix1e/acl_dup.3
@@ -0,0 +1,110 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 28, 2000
+.Dt ACL_DUP 3
+.Os
+.Sh NAME
+.Nm acl_dup
+.Nd duplicate an ACL
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft acl_t
+.Fn acl_dup "acl_t acl"
+.Sh DESCRIPTION
+The
+.Fn acl_dup
+function returns a pointer to a copy of the ACL pointed to by the argument
+.Va acl .
+.Pp
+This function may cause memory to be allocated.
+The caller should free any
+releasable memory, when the new ACL is no longer required, by calling
+.Xr acl_free 3
+with the
+.Va (void*)acl_t
+as an argument.
+.Pp
+Any existing ACL pointers that refer to the ACL referred to by
+.Va acl
+shall continue to refer to the ACL.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+Upon successful completion, this function shall return a pointer to the
+duplicate ACL.
+Otherwise, a value of
+.Va (acl_t)NULL
+shall be returned, and
+.Va errno
+shall be set to indicate the error.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_init
+function shall return a value of
+.Va (acl_t)NULL
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Va acl
+does not point to a valid ACL.
+.It Bq Er ENOMEM
+The
+.Va acl_t
+to be returned requires more memory than is allowed by the hardware or
+system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_free 3 ,
+.Xr acl_get 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_entry.c b/lib/libc/posix1e/acl_entry.c
new file mode 100644
index 0000000..3f8ca62
--- /dev/null
+++ b/lib/libc/posix1e/acl_entry.c
@@ -0,0 +1,146 @@
+/*
+ * Copyright (c) 2001-2002 Chris D. Faulhaber
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+
+#include <errno.h>
+#include <stdlib.h>
+
+/*
+ * acl_create_entry() (23.4.7): create a new ACL entry in the ACL pointed
+ * to by acl_p.
+ */
+int
+acl_create_entry(acl_t *acl_p, acl_entry_t *entry_p)
+{
+ struct acl *acl_int;
+
+ if (acl_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ acl_int = &(*acl_p)->ats_acl;
+
+ /*
+ * +1, because we are checking if there is space left for one more
+ * entry.
+ */
+ if (acl_int->acl_cnt + 1 >= ACL_MAX_ENTRIES) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *entry_p = &acl_int->acl_entry[acl_int->acl_cnt++];
+
+ (**entry_p).ae_tag = ACL_UNDEFINED_TAG;
+ (**entry_p).ae_id = ACL_UNDEFINED_ID;
+ (**entry_p).ae_perm = ACL_PERM_NONE;
+ (**entry_p).ae_entry_type = 0;
+ (**entry_p).ae_flags = 0;
+
+ (*acl_p)->ats_cur_entry = 0;
+
+ return (0);
+}
+
+int
+acl_create_entry_np(acl_t *acl_p, acl_entry_t *entry_p, int offset)
+{
+ int i;
+ struct acl *acl_int;
+
+ if (acl_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ acl_int = &(*acl_p)->ats_acl;
+
+ if (acl_int->acl_cnt + 1 >= ACL_MAX_ENTRIES) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (offset < 0 || offset >= acl_int->acl_cnt) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* Make room for the new entry. */
+ for (i = acl_int->acl_cnt; i > offset; i--)
+ acl_int->acl_entry[i] = acl_int->acl_entry[i - 1];
+
+ acl_int->acl_cnt++;
+
+ *entry_p = &acl_int->acl_entry[offset];
+
+ (**entry_p).ae_tag = ACL_UNDEFINED_TAG;
+ (**entry_p).ae_id = ACL_UNDEFINED_ID;
+ (**entry_p).ae_perm = ACL_PERM_NONE;
+ (**entry_p).ae_entry_type = 0;
+ (**entry_p).ae_flags= 0;
+
+ (*acl_p)->ats_cur_entry = 0;
+
+ return (0);
+}
+
+/*
+ * acl_get_entry() (23.4.14): returns an ACL entry from an ACL
+ * indicated by entry_id.
+ */
+int
+acl_get_entry(acl_t acl, int entry_id, acl_entry_t *entry_p)
+{
+ struct acl *acl_int;
+
+ if (acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ acl_int = &acl->ats_acl;
+
+ switch(entry_id) {
+ case ACL_FIRST_ENTRY:
+ acl->ats_cur_entry = 0;
+ /* PASSTHROUGH */
+ case ACL_NEXT_ENTRY:
+ if (acl->ats_cur_entry >= acl->ats_acl.acl_cnt)
+ return 0;
+ *entry_p = &acl_int->acl_entry[acl->ats_cur_entry++];
+ return (1);
+ }
+
+ errno = EINVAL;
+ return (-1);
+}
diff --git a/lib/libc/posix1e/acl_flag.c b/lib/libc/posix1e/acl_flag.c
new file mode 100644
index 0000000..39e258d
--- /dev/null
+++ b/lib/libc/posix1e/acl_flag.c
@@ -0,0 +1,155 @@
+/*-
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <errno.h>
+#include <sys/acl.h>
+
+#include "acl_support.h"
+
+static int
+_flag_is_invalid(acl_flag_t flag)
+{
+
+ if ((flag & ACL_FLAGS_BITS) == flag)
+ return (0);
+
+ errno = EINVAL;
+
+ return (1);
+}
+
+int
+acl_add_flag_np(acl_flagset_t flagset_d, acl_flag_t flag)
+{
+
+ if (flagset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_flag_is_invalid(flag))
+ return (-1);
+
+ *flagset_d |= flag;
+
+ return (0);
+}
+
+int
+acl_clear_flags_np(acl_flagset_t flagset_d)
+{
+
+ if (flagset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *flagset_d |= 0;
+
+ return (0);
+}
+
+int
+acl_delete_flag_np(acl_flagset_t flagset_d, acl_flag_t flag)
+{
+
+ if (flagset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_flag_is_invalid(flag))
+ return (-1);
+
+ *flagset_d &= ~flag;
+
+ return (0);
+}
+
+int
+acl_get_flag_np(acl_flagset_t flagset_d, acl_flag_t flag)
+{
+
+ if (flagset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_flag_is_invalid(flag))
+ return (-1);
+
+ if (*flagset_d & flag)
+ return (1);
+
+ return (0);
+}
+
+int
+acl_get_flagset_np(acl_entry_t entry_d, acl_flagset_t *flagset_p)
+{
+
+ if (entry_d == NULL || flagset_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *flagset_p = &entry_d->ae_flags;
+
+ return (0);
+}
+
+int
+acl_set_flagset_np(acl_entry_t entry_d, acl_flagset_t flagset_d)
+{
+
+ if (entry_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ _entry_brand_as(entry_d, ACL_BRAND_NFS4);
+
+ if (_flag_is_invalid(*flagset_d))
+ return (-1);
+
+ entry_d->ae_flags = *flagset_d;
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_free.3 b/lib/libc/posix1e/acl_free.3
new file mode 100644
index 0000000..d64c72a
--- /dev/null
+++ b/lib/libc/posix1e/acl_free.3
@@ -0,0 +1,89 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 28, 2000
+.Dt ACL_FREE 3
+.Os
+.Sh NAME
+.Nm acl_free
+.Nd free ACL working state
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_free "void *obj_p"
+.Sh DESCRIPTION
+The
+.Fn acl_free
+call allows the freeing of ACL working space, such as is allocated by
+.Xr acl_dup 3 ,
+or
+.Xr acl_from_text 3 .
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+.Rv -std acl_free
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_free
+function shall return -1 and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value of the
+.Va obj_p
+argument is invalid.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_dup 3 ,
+.Xr acl_from_text 3 ,
+.Xr acl_get 3 ,
+.Xr acl_init 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_free.c b/lib/libc/posix1e/acl_free.c
new file mode 100644
index 0000000..6de41da
--- /dev/null
+++ b/lib/libc/posix1e/acl_free.c
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1999, 2000, 2001 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * acl_free -- free ACL objects from user memory
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+#include <sys/errno.h>
+#include <stdlib.h>
+
+/*
+ * acl_free() (23.4.12): free any releasable memory allocated to the
+ * ACL data object identified by obj_p.
+ */
+int
+acl_free(void *obj_p)
+{
+
+ if (obj_p) {
+ free(obj_p);
+ obj_p = NULL;
+ }
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_from_text.3 b/lib/libc/posix1e/acl_from_text.3
new file mode 100644
index 0000000..8b10784
--- /dev/null
+++ b/lib/libc/posix1e/acl_from_text.3
@@ -0,0 +1,130 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 28, 2000
+.Dt ACL_FROM_TEXT 3
+.Os
+.Sh NAME
+.Nm acl_from_text
+.Nd create an ACL from text
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft acl_t
+.Fn acl_from_text "const char *buf_p"
+.Sh DESCRIPTION
+The
+.Fn acl_from_text
+function converts the text form of an ACL referred to by
+.Va buf_p
+into the internal working structure for ACLs, appropriate for applying to
+files or manipulating.
+.Pp
+This function may cause memory to be allocated.
+The caller should free any
+releasable memory, when the new ACL is no longer required, by calling
+.Xr acl_free 3
+with the
+.Va (void *)acl_t
+as an argument.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+Upon successful completion, the function shall return a pointer to the
+internal representation of the ACL in working storage.
+Otherwise, a value
+of
+.Va (acl_t)NULL
+shall be returned, and
+.Va errno
+shall be set to indicate the error.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_from_text
+function shall return a value of
+.Va (acl_t)NULL
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Va buf_p
+cannot be translated into an ACL.
+.It Bq Er ENOMEM
+The ACL working storage requires more memory than is allowed by the
+hardware or system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_free 3 ,
+.Xr acl_get 3 ,
+.Xr acl_to_text 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
+.Sh BUGS
+The
+.Fn acl_from_text
+and
+.Fn acl_to_text
+functions
+rely on the
+.Xr getpwent 3
+library calls to manage username and uid mapping, as well as the
+.Xr getgrent 3
+library calls to manage groupname and gid mapping.
+These calls are not
+thread safe, and so transitively, neither are
+.Fn acl_from_text
+and
+.Fn acl_to_text .
+These functions may also interfere with stateful
+calls associated with the
+.Fn getpwent
+and
+.Fn getgrent
+calls.
diff --git a/lib/libc/posix1e/acl_from_text.c b/lib/libc/posix1e/acl_from_text.c
new file mode 100644
index 0000000..7f15463
--- /dev/null
+++ b/lib/libc/posix1e/acl_from_text.c
@@ -0,0 +1,313 @@
+/*-
+ * Copyright (c) 1999, 2000, 2001 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * acl_from_text: Convert a text-form ACL from a string to an acl_t.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+#include <sys/errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "acl_support.h"
+
+static acl_tag_t acl_string_to_tag(char *tag, char *qualifier);
+
+int _nfs4_acl_entry_from_text(acl_t aclp, char *entry);
+int _text_could_be_nfs4_acl(const char *entry);
+
+static acl_tag_t
+acl_string_to_tag(char *tag, char *qualifier)
+{
+
+ if (*qualifier == '\0') {
+ if ((!strcmp(tag, "user")) || (!strcmp(tag, "u"))) {
+ return (ACL_USER_OBJ);
+ } else
+ if ((!strcmp(tag, "group")) || (!strcmp(tag, "g"))) {
+ return (ACL_GROUP_OBJ);
+ } else
+ if ((!strcmp(tag, "mask")) || (!strcmp(tag, "m"))) {
+ return (ACL_MASK);
+ } else
+ if ((!strcmp(tag, "other")) || (!strcmp(tag, "o"))) {
+ return (ACL_OTHER);
+ } else
+ return(-1);
+ } else {
+ if ((!strcmp(tag, "user")) || (!strcmp(tag, "u"))) {
+ return(ACL_USER);
+ } else
+ if ((!strcmp(tag, "group")) || (!strcmp(tag, "g"))) {
+ return(ACL_GROUP);
+ } else
+ return(-1);
+ }
+}
+
+static int
+_posix1e_acl_entry_from_text(acl_t aclp, char *entry)
+{
+ acl_tag_t t;
+ acl_perm_t p;
+ char *tag, *qualifier, *permission;
+ uid_t id;
+ int error;
+
+ assert(_acl_brand(aclp) == ACL_BRAND_POSIX);
+
+ /* Split into three ':' delimited fields. */
+ tag = strsep(&entry, ":");
+ if (tag == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ tag = string_skip_whitespace(tag);
+ if ((*tag == '\0') && (!entry)) {
+ /*
+ * Is an entirely comment line, skip to next
+ * comma.
+ */
+ return (0);
+ }
+ string_trim_trailing_whitespace(tag);
+
+ qualifier = strsep(&entry, ":");
+ if (qualifier == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ qualifier = string_skip_whitespace(qualifier);
+ string_trim_trailing_whitespace(qualifier);
+
+ permission = strsep(&entry, ":");
+ if (permission == NULL || entry) {
+ errno = EINVAL;
+ return (-1);
+ }
+ permission = string_skip_whitespace(permission);
+ string_trim_trailing_whitespace(permission);
+
+ t = acl_string_to_tag(tag, qualifier);
+ if (t == -1) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ error = _posix1e_acl_string_to_perm(permission, &p);
+ if (error == -1) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ switch(t) {
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_MASK:
+ case ACL_OTHER:
+ if (*qualifier != '\0') {
+ errno = EINVAL;
+ return (-1);
+ }
+ id = 0;
+ break;
+
+ case ACL_USER:
+ case ACL_GROUP:
+ error = _acl_name_to_id(t, qualifier, &id);
+ if (error == -1)
+ return (-1);
+ break;
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+
+ error = _posix1e_acl_add_entry(aclp, t, id, p);
+ if (error == -1)
+ return (-1);
+
+ return (0);
+}
+
+static int
+_text_is_nfs4_entry(const char *entry)
+{
+ int count = 0;
+
+ assert(strlen(entry) > 0);
+
+ while (*entry != '\0') {
+ if (*entry == ':' || *entry == '@')
+ count++;
+ entry++;
+ }
+
+ if (count <= 2)
+ return (0);
+
+ return (1);
+}
+
+/*
+ * acl_from_text -- Convert a string into an ACL.
+ * Postpone most validity checking until the end and call acl_valid() to do
+ * that.
+ */
+acl_t
+acl_from_text(const char *buf_p)
+{
+ acl_t acl;
+ char *mybuf_p, *line, *cur, *notcomment, *comment, *entry;
+ int error;
+
+ /* Local copy we can mess up. */
+ mybuf_p = strdup(buf_p);
+ if (mybuf_p == NULL)
+ return(NULL);
+
+ acl = acl_init(3); /* XXX: WTF, 3? */
+ if (acl == NULL) {
+ free(mybuf_p);
+ return(NULL);
+ }
+
+ /* Outer loop: delimit at \n boundaries. */
+ cur = mybuf_p;
+ while ((line = strsep(&cur, "\n"))) {
+ /* Now split the line on the first # to strip out comments. */
+ comment = line;
+ notcomment = strsep(&comment, "#");
+
+ /* Inner loop: delimit at ',' boundaries. */
+ while ((entry = strsep(&notcomment, ","))) {
+
+ /* Skip empty lines. */
+ if (strlen(string_skip_whitespace(entry)) == 0)
+ continue;
+
+ if (_acl_brand(acl) == ACL_BRAND_UNKNOWN) {
+ if (_text_is_nfs4_entry(entry))
+ _acl_brand_as(acl, ACL_BRAND_NFS4);
+ else
+ _acl_brand_as(acl, ACL_BRAND_POSIX);
+ }
+
+ switch (_acl_brand(acl)) {
+ case ACL_BRAND_NFS4:
+ error = _nfs4_acl_entry_from_text(acl, entry);
+ break;
+
+ case ACL_BRAND_POSIX:
+ error = _posix1e_acl_entry_from_text(acl, entry);
+ break;
+
+ default:
+ error = EINVAL;
+ break;
+ }
+
+ if (error)
+ goto error_label;
+ }
+ }
+
+#if 0
+ /* XXX Should we only return ACLs valid according to acl_valid? */
+ /* Verify validity of the ACL we read in. */
+ if (acl_valid(acl) == -1) {
+ errno = EINVAL;
+ goto error_label;
+ }
+#endif
+
+ free(mybuf_p);
+ return(acl);
+
+error_label:
+ acl_free(acl);
+ free(mybuf_p);
+ return(NULL);
+}
+
+/*
+ * Given a username/groupname from a text form of an ACL, return the uid/gid
+ * XXX NOT THREAD SAFE, RELIES ON GETPWNAM, GETGRNAM
+ * XXX USES *PW* AND *GR* WHICH ARE STATEFUL AND THEREFORE THIS ROUTINE
+ * MAY HAVE SIDE-EFFECTS
+ */
+int
+_acl_name_to_id(acl_tag_t tag, char *name, uid_t *id)
+{
+ struct group *g;
+ struct passwd *p;
+ unsigned long l;
+ char *endp;
+
+ switch(tag) {
+ case ACL_USER:
+ p = getpwnam(name);
+ if (p == NULL) {
+ l = strtoul(name, &endp, 0);
+ if (*endp != '\0' || l != (unsigned long)(uid_t)l) {
+ errno = EINVAL;
+ return (-1);
+ }
+ *id = (uid_t)l;
+ return (0);
+ }
+ *id = p->pw_uid;
+ return (0);
+
+ case ACL_GROUP:
+ g = getgrnam(name);
+ if (g == NULL) {
+ l = strtoul(name, &endp, 0);
+ if (*endp != '\0' || l != (unsigned long)(gid_t)l) {
+ errno = EINVAL;
+ return (-1);
+ }
+ *id = (gid_t)l;
+ return (0);
+ }
+ *id = g->gr_gid;
+ return (0);
+
+ default:
+ return (EINVAL);
+ }
+}
diff --git a/lib/libc/posix1e/acl_from_text_nfs4.c b/lib/libc/posix1e/acl_from_text_nfs4.c
new file mode 100644
index 0000000..5a0b36a
--- /dev/null
+++ b/lib/libc/posix1e/acl_from_text_nfs4.c
@@ -0,0 +1,283 @@
+/*-
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#include <ctype.h>
+#include <err.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/acl.h>
+
+#include "acl_support.h"
+
+#define MAX_ENTRY_LENGTH 512
+
+/*
+ * Parse the tag field of ACL entry passed as "str". If qualifier
+ * needs to follow, then the variable referenced by "need_qualifier"
+ * is set to 1, otherwise it's set to 0.
+ */
+static int
+parse_tag(const char *str, acl_entry_t entry, int *need_qualifier)
+{
+
+ assert(need_qualifier != NULL);
+ *need_qualifier = 0;
+
+ if (strcmp(str, "owner@") == 0)
+ return (acl_set_tag_type(entry, ACL_USER_OBJ));
+ if (strcmp(str, "group@") == 0)
+ return (acl_set_tag_type(entry, ACL_GROUP_OBJ));
+ if (strcmp(str, "everyone@") == 0)
+ return (acl_set_tag_type(entry, ACL_EVERYONE));
+
+ *need_qualifier = 1;
+
+ if (strcmp(str, "user") == 0 || strcmp(str, "u") == 0)
+ return (acl_set_tag_type(entry, ACL_USER));
+ if (strcmp(str, "group") == 0 || strcmp(str, "g") == 0)
+ return (acl_set_tag_type(entry, ACL_GROUP));
+
+ warnx("malformed ACL: invalid \"tag\" field");
+
+ return (-1);
+}
+
+/*
+ * Parse the qualifier field of ACL entry passed as "str".
+ * If user or group name cannot be resolved, then the variable
+ * referenced by "need_qualifier" is set to 1; it will be checked
+ * later to figure out whether the appended_id is required.
+ */
+static int
+parse_qualifier(char *str, acl_entry_t entry, int *need_qualifier)
+{
+ int qualifier_length, error;
+ uid_t id;
+ acl_tag_t tag;
+
+ assert(need_qualifier != NULL);
+ *need_qualifier = 0;
+
+ qualifier_length = strlen(str);
+
+ if (qualifier_length == 0) {
+ warnx("malformed ACL: empty \"qualifier\" field");
+ return (-1);
+ }
+
+ error = acl_get_tag_type(entry, &tag);
+ if (error)
+ return (error);
+
+ error = _acl_name_to_id(tag, str, &id);
+ if (error) {
+ *need_qualifier = 1;
+ return (0);
+ }
+
+ return (acl_set_qualifier(entry, &id));
+}
+
+static int
+parse_access_mask(char *str, acl_entry_t entry)
+{
+ int error;
+ acl_perm_t perm;
+
+ error = _nfs4_parse_access_mask(str, &perm);
+ if (error)
+ return (error);
+
+ error = acl_set_permset(entry, &perm);
+
+ return (error);
+}
+
+static int
+parse_flags(char *str, acl_entry_t entry)
+{
+ int error;
+ acl_flag_t flags;
+
+ error = _nfs4_parse_flags(str, &flags);
+ if (error)
+ return (error);
+
+ error = acl_set_flagset_np(entry, &flags);
+
+ return (error);
+}
+
+static int
+parse_entry_type(const char *str, acl_entry_t entry)
+{
+
+ if (strcmp(str, "allow") == 0)
+ return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_ALLOW));
+ if (strcmp(str, "deny") == 0)
+ return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_DENY));
+ if (strcmp(str, "audit") == 0)
+ return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_AUDIT));
+ if (strcmp(str, "alarm") == 0)
+ return (acl_set_entry_type_np(entry, ACL_ENTRY_TYPE_ALARM));
+
+ warnx("malformed ACL: invalid \"type\" field");
+
+ return (-1);
+}
+
+static int
+parse_appended_id(char *str, acl_entry_t entry)
+{
+ int qualifier_length;
+ char *end;
+ id_t id;
+
+ qualifier_length = strlen(str);
+ if (qualifier_length == 0) {
+ warnx("malformed ACL: \"appended id\" field present, "
+ "but empty");
+ return (-1);
+ }
+
+ id = strtod(str, &end);
+ if (end - str != qualifier_length) {
+ warnx("malformed ACL: appended id is not a number");
+ return (-1);
+ }
+
+ return (acl_set_qualifier(entry, &id));
+}
+
+static int
+number_of_colons(const char *str)
+{
+ int count = 0;
+
+ while (*str != '\0') {
+ if (*str == ':')
+ count++;
+
+ str++;
+ }
+
+ return (count);
+}
+
+int
+_nfs4_acl_entry_from_text(acl_t aclp, char *str)
+{
+ int error, need_qualifier;
+ acl_entry_t entry;
+ char *field, *qualifier_field;
+
+ error = acl_create_entry(&aclp, &entry);
+ if (error)
+ return (error);
+
+ assert(_entry_brand(entry) == ACL_BRAND_NFS4);
+
+ if (str == NULL)
+ goto truncated_entry;
+ field = strsep(&str, ":");
+
+ field = string_skip_whitespace(field);
+ if ((*field == '\0') && (!str)) {
+ /*
+ * Is an entirely comment line, skip to next
+ * comma.
+ */
+ return (0);
+ }
+
+ error = parse_tag(field, entry, &need_qualifier);
+ if (error)
+ goto malformed_field;
+
+ if (need_qualifier) {
+ if (str == NULL)
+ goto truncated_entry;
+ qualifier_field = field = strsep(&str, ":");
+ error = parse_qualifier(field, entry, &need_qualifier);
+ if (error)
+ goto malformed_field;
+ }
+
+ if (str == NULL)
+ goto truncated_entry;
+ field = strsep(&str, ":");
+ error = parse_access_mask(field, entry);
+ if (error)
+ goto malformed_field;
+
+ if (str == NULL)
+ goto truncated_entry;
+ /* Do we have "flags" field? */
+ if (number_of_colons(str) > 0) {
+ field = strsep(&str, ":");
+ error = parse_flags(field, entry);
+ if (error)
+ goto malformed_field;
+ }
+
+ if (str == NULL)
+ goto truncated_entry;
+ field = strsep(&str, ":");
+ error = parse_entry_type(field, entry);
+ if (error)
+ goto malformed_field;
+
+ if (need_qualifier) {
+ if (str == NULL) {
+ warnx("malformed ACL: unknown user or group name "
+ "\"%s\"", qualifier_field);
+ goto truncated_entry;
+ }
+
+ error = parse_appended_id(str, entry);
+ if (error)
+ goto malformed_field;
+ }
+
+ return (0);
+
+truncated_entry:
+malformed_field:
+ acl_delete_entry(aclp, entry);
+ errno = EINVAL;
+ return (-1);
+}
diff --git a/lib/libc/posix1e/acl_get.3 b/lib/libc/posix1e/acl_get.3
new file mode 100644
index 0000000..ae0c48d
--- /dev/null
+++ b/lib/libc/posix1e/acl_get.3
@@ -0,0 +1,168 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_GET 3
+.Os
+.Sh NAME
+.Nm acl_get_fd ,
+.Nm acl_get_fd_np ,
+.Nm acl_get_file ,
+.Nm acl_get_link_np
+.Nd get an ACL for a file
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft acl_t
+.Fn acl_get_fd "int fd"
+.Ft acl_t
+.Fn acl_get_fd_np "int fd" "acl_type_t type"
+.Ft acl_t
+.Fn acl_get_file "const char *path_p" "acl_type_t type"
+.Ft acl_t
+.Fn acl_get_link_np "const char *path_p" "acl_type_t type"
+.Sh DESCRIPTION
+The
+.Fn acl_get_fd ,
+.Fn acl_get_file ,
+.Fn acl_get_link_np ,
+and
+.Fn acl_get_fd_np
+each allow the retrieval of an ACL from a file.
+The
+.Fn acl_get_fd
+is a POSIX.1e call that allows the retrieval of an ACL of type
+ACL_TYPE_ACCESS
+from a file descriptor.
+The
+.Fn acl_get_fd_np
+function
+is a non-portable form of
+.Fn acl_get_fd
+that allows the retrieval of any type of ACL from a file descriptor.
+The
+.Fn acl_get_file
+function is a POSIX.1e call that allows the retrieval of a
+specified type of ACL from a file by name;
+.Fn acl_get_link_np
+is a non-portable variation on
+.Fn acl_get_file
+which does not follow a symlink if the target of the call is a
+symlink.
+.Pp
+These functions may cause memory to be allocated.
+The caller should free
+any releasable memory, when the new ACL is no longer required, by calling
+.Xr acl_free 3
+with the
+.Va (void *)acl_t
+as an argument.
+.Pp
+The ACL in the working storage is an independent copy of the ACL associated
+with the object referred to by
+.Va fd .
+The ACL in the working storage shall not participate in any access control
+decisions.
+.Pp
+Valid values for the
+.Va type
+argument are:
+.Bl -column -offset 3n "ACL_TYPE_DEFAULT"
+.It ACL_TYPE_ACCESS POSIX.1e access ACL
+.It ACL_TYPE_DEFAULT POSIX.1e default ACL
+.It ACL_TYPE_NFS4 NFSv4 ACL
+.El
+.Pp
+The ACL returned will be branded accordingly.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+Upon successful completion, the function shall return a pointer to the ACL
+that was retrieved.
+Otherwise, a value of
+.Va (acl_t)NULL
+shall be returned, and
+.Va errno
+shall be set to indicate the error.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_get_fd
+function shall return a value of
+.Va (acl_t)NULL
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EACCES
+Search permission is denied for a component of the path prefix, or the
+object exists and the process does not have appropriate access rights.
+.It Bq Er EBADF
+The
+.Va fd
+argument is not a valid file descriptor.
+.It Bq Er EINVAL
+The ACL type passed is invalid for this file object.
+.It Bq Er ENAMETOOLONG
+A component of a pathname exceeded 255 characters, or an
+entire path name exceeded 1023 characters.
+.It Bq Er ENOENT
+The named object does not exist, or the
+.Va path_p
+argument points to an empty string.
+.It Bq Er ENOMEM
+Insufficient memory available to fulfill request.
+.It Bq Er EOPNOTSUPP
+The file system does not support ACL retrieval.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_free 3 ,
+.Xr acl_get 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_set 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_get.c b/lib/libc/posix1e/acl_get.c
new file mode 100644
index 0000000..b323501
--- /dev/null
+++ b/lib/libc/posix1e/acl_get.c
@@ -0,0 +1,216 @@
+/*-
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * acl_get_fd - syscall wrapper for retrieving access ACL by fd
+ * acl_get_fd_np - syscall wrapper for retrieving ACL by fd (non-POSIX)
+ * acl_get_file - syscall wrapper for retrieving ACL by filename
+ * acl_get_link_np - syscall wrapper for retrieving ACL by filename (NOFOLLOW)
+ * (non-POSIX)
+ * acl_get_perm_np() checks if a permission is in the specified
+ * permset (non-POSIX)
+ * acl_get_permset() returns the permission set in the ACL entry
+ * acl_get_qualifier() retrieves the qualifier of the tag from the ACL entry
+ * acl_get_tag_type() returns the tag type for the ACL entry entry_d
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "acl_support.h"
+
+acl_t
+acl_get_file(const char *path_p, acl_type_t type)
+{
+ acl_t aclp;
+ int error;
+
+ aclp = acl_init(ACL_MAX_ENTRIES);
+ if (aclp == NULL)
+ return (NULL);
+
+ type = _acl_type_unold(type);
+ error = __acl_get_file(path_p, type, &aclp->ats_acl);
+ if (error) {
+ acl_free(aclp);
+ return (NULL);
+ }
+
+ aclp->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES;
+ _acl_brand_from_type(aclp, type);
+
+ return (aclp);
+}
+
+acl_t
+acl_get_link_np(const char *path_p, acl_type_t type)
+{
+ acl_t aclp;
+ int error;
+
+ aclp = acl_init(ACL_MAX_ENTRIES);
+ if (aclp == NULL)
+ return (NULL);
+
+ type = _acl_type_unold(type);
+ error = __acl_get_link(path_p, type, &aclp->ats_acl);
+ if (error) {
+ acl_free(aclp);
+ return (NULL);
+ }
+
+ aclp->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES;
+ _acl_brand_from_type(aclp, type);
+
+ return (aclp);
+}
+
+acl_t
+acl_get_fd(int fd)
+{
+ if (fpathconf(fd, _PC_ACL_NFS4) == 1)
+ return (acl_get_fd_np(fd, ACL_TYPE_NFS4));
+
+ return (acl_get_fd_np(fd, ACL_TYPE_ACCESS));
+}
+
+acl_t
+acl_get_fd_np(int fd, acl_type_t type)
+{
+ acl_t aclp;
+ int error;
+
+ aclp = acl_init(ACL_MAX_ENTRIES);
+ if (aclp == NULL)
+ return (NULL);
+
+ type = _acl_type_unold(type);
+ error = ___acl_get_fd(fd, type, &aclp->ats_acl);
+ if (error) {
+ acl_free(aclp);
+ return (NULL);
+ }
+
+ aclp->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES;
+ _acl_brand_from_type(aclp, type);
+
+ return (aclp);
+}
+
+/*
+ * acl_get_permset() (23.4.17): return via permset_p a descriptor to
+ * the permission set in the ACL entry entry_d.
+ */
+int
+acl_get_permset(acl_entry_t entry_d, acl_permset_t *permset_p)
+{
+
+ if (entry_d == NULL || permset_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *permset_p = &entry_d->ae_perm;
+
+ return (0);
+}
+
+/*
+ * acl_get_qualifier() (23.4.18): retrieve the qualifier of the tag
+ * for the ACL entry entry_d.
+ */
+void *
+acl_get_qualifier(acl_entry_t entry_d)
+{
+ uid_t *retval;
+
+ if (entry_d == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ switch(entry_d->ae_tag) {
+ case ACL_USER:
+ case ACL_GROUP:
+ retval = malloc(sizeof(uid_t));
+ if (retval == NULL)
+ return (NULL);
+ *retval = entry_d->ae_id;
+ return (retval);
+ }
+
+ errno = EINVAL;
+ return (NULL);
+}
+
+/*
+ * acl_get_tag_type() (23.4.19): return the tag type for the ACL
+ * entry entry_p.
+ */
+int
+acl_get_tag_type(acl_entry_t entry_d, acl_tag_t *tag_type_p)
+{
+
+ if (entry_d == NULL || tag_type_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *tag_type_p = entry_d->ae_tag;
+
+ return (0);
+}
+
+int
+acl_get_entry_type_np(acl_entry_t entry_d, acl_entry_type_t *entry_type_p)
+{
+
+ if (entry_d == NULL || entry_type_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *entry_type_p = entry_d->ae_entry_type;
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_get_brand_np.3 b/lib/libc/posix1e/acl_get_brand_np.3
new file mode 100644
index 0000000..5caa40c
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_brand_np.3
@@ -0,0 +1,86 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_GET_BRAND_NP 3
+.Os
+.Sh NAME
+.Nm acl_get_brand_np
+.Nd retrieve the ACL brand from an ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_brand_np "acl_t acl" "int *brand_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_brand_np
+function
+is a non-portable call that returns the ACL brand for the ACL
+.Fa acl .
+Upon successful completion, the location referred to by the argument
+.Fa brand_p
+will be set to the ACL brand of the ACL
+.Fa acl .
+.Pp
+Branding is an internal mechanism intended to prevent mixing POSIX.1e
+and NFSv4 entries by mistake.
+It's also used by the libc to determine how to print out the ACL.
+The first call to function that is specific for one particular brand - POSIX.1e
+or NFSv4 - "brands" the ACL.
+After that, calling function specific to another brand will result in error.
+.Sh RETURN VALUES
+.Rv -std acl_get_brand_np
+.Sh ERRORS
+The
+.Fn acl_get_brand_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa acl
+does not point to a valid ACL.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_brand_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_brand_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_get_entry.3 b/lib/libc/posix1e/acl_get_entry.3
new file mode 100644
index 0000000..477b735
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_entry.3
@@ -0,0 +1,145 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 13, 2001
+.Dt ACL_GET_ENTRY 3
+.Os
+.Sh NAME
+.Nm acl_get_entry
+.Nd retrieve an ACL entry from an ACL
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_entry "acl_t acl" "int entry_id" "acl_entry_t *entry_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_entry
+function
+is a POSIX.1e call that retrieves a descriptor for an ACL entry
+specified by the argument
+.Fa entry_d
+within the ACL indicated by the argument
+.Fa acl .
+.Pp
+If the value of
+.Fa entry_id
+is
+.Dv ACL_FIRST_ENTRY ,
+then the function will return in
+.Fa entry_p
+a descriptor for the first ACL entry within
+.Fa acl .
+If a call is made to
+.Fn acl_get_entry
+with
+.Fa entry_id
+set to
+.Dv ACL_NEXT_ENTRY
+when there has not been either an initial successful call to
+.Fn acl_get_entry ,
+or a previous successful call to
+.Fn acl_create_entry ,
+.Fn acl_delete_entry ,
+.Fn acl_dup ,
+.Fn acl_from_text ,
+.Fn acl_get_fd ,
+.Fn acl_get_file ,
+.Fn acl_set_fd ,
+.Fn acl_set_file ,
+or
+.Fn acl_valid ,
+then the result is unspecified.
+.Sh RETURN VALUES
+If the
+.Fn acl_get_entry
+function successfully obtains an ACL entry, a value of 1 is returned.
+If the ACL has no ACL entries, the
+.Fn acl_get_entry
+returns a value of 0.
+If the value of
+.Fa entry_id
+is
+.Dv ACL_NEXT_ENTRY
+and the last ACL entry in the ACL has already been returned by a
+previous call to
+.Fn acl_get_entry ,
+a value of 0 will be returned until a successful call with
+.Fa entry_id
+of
+.Dv ACL_FIRST_ENTRY
+is made.
+Otherwise, a value of -1 will be returned and
+the global variable
+.Va errno
+will be set to indicate the error.
+.Sh ERRORS
+The
+.Fn acl_get_entry
+fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa acl
+does not point to a valid ACL.
+Argument
+.Fa entry_id
+is neither
+.Dv ACL_FIRST_ENTRY
+nor
+.Dv ACL_NEXT_ENTRY .
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_calc_mask 3 ,
+.Xr acl_create_entry 3 ,
+.Xr acl_delete_entry 3 ,
+.Xr acl_dup 3 ,
+.Xr acl_from_text 3 ,
+.Xr acl_get_fd 3 ,
+.Xr acl_get_file 3 ,
+.Xr acl_init 3 ,
+.Xr acl_set_fd 3 ,
+.Xr acl_set_file 3 ,
+.Xr acl_valid 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_entry
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_entry
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_get_entry_type_np.3 b/lib/libc/posix1e/acl_get_entry_type_np.3
new file mode 100644
index 0000000..eea4b17
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_entry_type_np.3
@@ -0,0 +1,80 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_GET_ENTRY_TYPE_NP 3
+.Os
+.Sh NAME
+.Nm acl_get_entry_type_np
+.Nd retrieve the ACL type from an NFSv4 ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_entry_type_np "acl_entry_t entry_d" "acl_entry_type_t *entry_type_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_entry_type_np
+function
+is a non-portable call that returns the ACL type for the NFSv4 ACL entry
+.Fa entry_d .
+Upon successful completion, the location referred to by the argument
+.Fa entry_type_p
+will be set to the ACL type of the ACL entry
+.Fa entry_d .
+.Sh RETURN VALUES
+.Rv -std acl_get_entry_type_np
+.Sh ERRORS
+The
+.Fn acl_get_entry_type_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an NFSv4 ACL entry;
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_set_entry_type_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_entry_type_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_entry_type_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_get_flag_np.3 b/lib/libc/posix1e/acl_get_flag_np.3
new file mode 100644
index 0000000..b57fd04
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_flag_np.3
@@ -0,0 +1,94 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_GET_FLAG_NP 3
+.Os
+.Sh NAME
+.Nm acl_get_flag_np
+.Nd check if a flag is set in a flagset
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_flag_np "acl_flagset_t flagset_d" "acl_flag_t flag"
+.Sh DESCRIPTION
+The
+.Fn acl_get_flag_np
+function
+is a non-portable function that checks if a flag is set in
+a flagset.
+.Sh RETURN VALUES
+If the flag in
+.Fa flag
+is set in the flagset
+.Fa flagset_d ,
+a value of
+1
+is returned, otherwise a value of
+0
+is returned.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_get_flag_np
+function will return a value of
+\-1
+and set global variable
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa flag
+does not contain a valid ACL flag or argument
+.Fa flagset_d
+is not a valid ACL flagset.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_flag_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_flag_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_get_flagset_np.3 b/lib/libc/posix1e/acl_get_flagset_np.3
new file mode 100644
index 0000000..221b93b
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_flagset_np.3
@@ -0,0 +1,83 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_GET_FLAGSET_NP 3
+.Os
+.Sh NAME
+.Nm acl_get_flagset_np
+.Nd retrieve flagset from an NFSv4 ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_flagset_np "acl_entry_t entry_d" "acl_flagset_t *flagset_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_flagset_np
+function
+is a non-portable call that returns via
+.Fa flagset_np_p
+a descriptor to the flagset in the ACL entry
+.Fa entry_d .
+Subsequent operations using the returned flagset operate
+on the flagset within the ACL entry.
+.Sh RETURN VALUES
+.Rv -std acl_get_flagset_np
+.Sh ERRORS
+The
+.Fn acl_get_flagset_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_set_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_flagset_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_flagset_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_get_perm_np.3 b/lib/libc/posix1e/acl_get_perm_np.3
new file mode 100644
index 0000000..de1c0b5
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_perm_np.3
@@ -0,0 +1,94 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 10, 2001
+.Dt ACL_GET_PERM_NP 3
+.Os
+.Sh NAME
+.Nm acl_get_perm_np
+.Nd "check if a permission is set in a permission set"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_perm_np "acl_permset_t permset_d" "acl_perm_t perm"
+.Sh DESCRIPTION
+The
+.Fn acl_get_perm_np
+function
+is a non-portable function that checks if a permission is set in
+a permission set.
+.Sh RETURN VALUES
+If the permission in
+.Fa perm
+is set in the permission set
+.Fa permset_d ,
+a value of
+1
+is returned, otherwise a value of
+0
+is returned.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_get_perm_np
+function will return a value of
+\-1
+and set global variable
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa perm
+does not contain a valid ACL permission or argument
+.Fa permset_d
+is not a valid ACL permset.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_perm 3 ,
+.Xr acl_clear_perms 3 ,
+.Xr acl_delete_perm 3 ,
+.Xr acl_get_permset 3 ,
+.Xr acl_set_permset 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_perm_np
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_perm_np
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_get_permset.3 b/lib/libc/posix1e/acl_get_permset.3
new file mode 100644
index 0000000..cf93b0a
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_permset.3
@@ -0,0 +1,83 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 10, 2001
+.Dt ACL_GET_PERMSET 3
+.Os
+.Sh NAME
+.Nm acl_get_permset
+.Nd retrieve permission set from an ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_permset "acl_entry_t entry_d" "acl_permset_t *permset_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_permset
+function
+is a POSIX.1e call that returns via
+.Fa permset_p
+a descriptor to the permission set in the ACL entry
+.Fa entry_d .
+Subsequent operations using the returned permission set operate
+on the permission set within the ACL entry.
+.Sh RETURN VALUES
+.Rv -std acl_get_permset
+.Sh ERRORS
+The
+.Fn acl_get_permset
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_perm 3 ,
+.Xr acl_clear_perms 3 ,
+.Xr acl_delete_perm 3 ,
+.Xr acl_set_permset 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_permset
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_permset
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_get_qualifier.3 b/lib/libc/posix1e/acl_get_qualifier.3
new file mode 100644
index 0000000..653a3b4
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_qualifier.3
@@ -0,0 +1,140 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 13, 2001
+.Dt ACL_GET_QUALIFIER 3
+.Os
+.Sh NAME
+.Nm acl_get_qualifier
+.Nd retrieve the qualifier from an ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft void *
+.Fn acl_get_qualifier "acl_entry_t entry_d"
+.Sh DESCRIPTION
+The
+.Fn acl_get_qualifier
+function
+is a POSIX.1e call that retrieves the qualifier of the tag for
+the ACL entry indicated by the argument
+.Fa entry_d
+into working storage and returns a pointer to that storage.
+.Pp
+If the value of the tag type in the ACL entry referred to by
+.Fa entry_d
+is
+.Dv ACL_USER ,
+then the value returned by
+.Fn acl_get_qualifier
+will be a pointer to type
+.Vt uid_t .
+.Pp
+If the value of the tag type in
+the ACL entry referred to by
+.Fa entry_d
+is
+.Dv ACL_GROUP ,
+then the value returned by
+.Fn acl_get_qualifier
+will be a pointer to type
+.Vt gid_t .
+.Pp
+If the value of the tag type in the ACL entry referred to by
+.Fa entry_d
+is
+.Dv ACL_UNDEFINED_TAG , ACL_USER_OBJ , ACL_GROUP_OBJ ,
+.Dv ACL_OTHER , ACL_MASK ,
+or an implementation-defined value for which a qualifier
+is not supported, then
+.Fn acl_get_qualifier
+will return a value of
+.Vt ( void * ) Ns Dv NULL
+and the function will fail.
+.Pp
+This function may cause memory to be allocated.
+The caller should
+free any releasable memory, when the new qualifier is no longer
+required, by calling
+.Fn acl_free
+with
+.Vt void *
+as the argument.
+.Sh RETURN VALUES
+The
+.Fn acl_get_qualifier
+function returns a pointer to the allocated storage if successful;
+otherwise a
+.Dv NULL
+pointer is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+The
+.Fn acl_get_qualifier
+fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+does not point to a valid descriptor for an ACL entry.
+The
+value of the tag type in the ACL entry referenced by argument
+.Fa entry_d
+is not
+.Dv ACL_USER
+or
+.Dv ACL_GROUP .
+.It Bq Er ENOMEM
+The value to be returned requires more memory than is allowed
+by the hardware or system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_create_entry 3 ,
+.Xr acl_free 3 ,
+.Xr acl_get_entry 3 ,
+.Xr acl_get_tag_type 3 ,
+.Xr acl_set_qualifier 3 ,
+.Xr acl_set_tag_type 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_qualifier
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_qualifier
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_get_tag_type.3 b/lib/libc/posix1e/acl_get_tag_type.3
new file mode 100644
index 0000000..4856c50
--- /dev/null
+++ b/lib/libc/posix1e/acl_get_tag_type.3
@@ -0,0 +1,85 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 10, 2001
+.Dt ACL_GET_TAG_TYPE 3
+.Os
+.Sh NAME
+.Nm acl_get_tag_type
+.Nd retrieve the tag type from an ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_get_tag_type "acl_entry_t entry_d" "acl_tag_t *tag_type_p"
+.Sh DESCRIPTION
+The
+.Fn acl_get_tag_type
+function
+is a POSIX.1e call that returns the tag type for the ACL entry
+.Fa entry_d .
+Upon successful completion, the location referred to by the argument
+.Fa tag_type_p
+will be set to the tag type of the ACL entry
+.Fa entry_d .
+.Sh RETURN VALUES
+.Rv -std acl_get_tag_type
+.Sh ERRORS
+The
+.Fn acl_get_tag_type
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry;
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_create_entry 3 ,
+.Xr acl_get_entry 3 ,
+.Xr acl_get_qualifier 3 ,
+.Xr acl_init 3 ,
+.Xr acl_set_qualifier 3 ,
+.Xr acl_set_tag_type 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_tag_type
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_tag_type
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_id_to_name.c b/lib/libc/posix1e/acl_id_to_name.c
new file mode 100644
index 0000000..aa10809
--- /dev/null
+++ b/lib/libc/posix1e/acl_id_to_name.c
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 1999-2001, 2008 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Support functionality for the POSIX.1e ACL interface
+ * These calls are intended only to be called within the library.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "acl_support.h"
+
+/*
+ * Given a uid/gid, return a username/groupname for the text form of an ACL.
+ * Note that we truncate user and group names, rather than error out, as
+ * this is consistent with other tools manipulating user and group names.
+ * XXX NOT THREAD SAFE, RELIES ON GETPWUID, GETGRGID
+ * XXX USES *PW* AND *GR* WHICH ARE STATEFUL AND THEREFORE THIS ROUTINE
+ * MAY HAVE SIDE-EFFECTS
+ */
+int
+_posix1e_acl_id_to_name(acl_tag_t tag, uid_t id, ssize_t buf_len, char *buf,
+ int flags)
+{
+ struct group *g;
+ struct passwd *p;
+ int i;
+
+ switch(tag) {
+ case ACL_USER:
+ if (flags & ACL_TEXT_NUMERIC_IDS)
+ p = NULL;
+ else
+ p = getpwuid(id);
+ if (!p)
+ i = snprintf(buf, buf_len, "%d", id);
+ else
+ i = snprintf(buf, buf_len, "%s", p->pw_name);
+
+ if (i < 0) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ return (0);
+
+ case ACL_GROUP:
+ if (flags & ACL_TEXT_NUMERIC_IDS)
+ g = NULL;
+ else
+ g = getgrgid(id);
+ if (g == NULL)
+ i = snprintf(buf, buf_len, "%d", id);
+ else
+ i = snprintf(buf, buf_len, "%s", g->gr_name);
+
+ if (i < 0) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ return (0);
+
+ default:
+ return (EINVAL);
+ }
+}
diff --git a/lib/libc/posix1e/acl_init.3 b/lib/libc/posix1e/acl_init.3
new file mode 100644
index 0000000..dba8923
--- /dev/null
+++ b/lib/libc/posix1e/acl_init.3
@@ -0,0 +1,111 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 28, 2000
+.Dt ACL_INIT 3
+.Os
+.Sh NAME
+.Nm acl_init
+.Nd initialize ACL working storage
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft acl_t
+.Fn acl_init "int count"
+.Sh DESCRIPTION
+The
+.Fn acl_init
+function allocates and initializes the working storage for an ACL of at
+least
+.Va count
+ACL entries.
+A pointer to the working storage is returned.
+The working
+storage allocated to contain the ACL is freed by a call to
+.Xr acl_free 3 .
+When the area is first allocated, it shall contain an ACL that contains
+no ACL entries.
+.Pp
+This function may cause memory to be allocated.
+The caller should free any
+releasable memory, when the new ACL is no longer required, by calling
+.Xr acl_free 3
+with the
+.Va (void*)acl_t
+as an argument.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+Upon successful completion, this function shall return a pointer to the
+working storage.
+Otherwise, a value of
+.Va (acl_t)NULL
+shall be returned, and
+.Va errno
+shall be set to indicate the error.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_init
+function shall return a value of
+.Va (acl_t)NULL
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value of count is less than zero.
+.It Bq Er ENOMEM
+The
+.Va acl_t
+to be returned requires more memory than is allowed by the hardware or
+system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_free 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_init.c b/lib/libc/posix1e/acl_init.c
new file mode 100644
index 0000000..4fe4037
--- /dev/null
+++ b/lib/libc/posix1e/acl_init.c
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 1999, 2000, 2001 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * acl_init -- return a fresh acl structure
+ * acl_dup -- duplicate an acl and return the new copy
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "acl_support.h"
+
+#ifndef CTASSERT
+#define CTASSERT(x) _CTASSERT(x, __LINE__)
+#define _CTASSERT(x, y) __CTASSERT(x, y)
+#define __CTASSERT(x, y) typedef char __assert_ ## y [(x) ? 1 : -1]
+#endif
+
+CTASSERT(1 << _ACL_T_ALIGNMENT_BITS > sizeof(struct acl_t_struct));
+
+acl_t
+acl_init(int count)
+{
+ int error;
+ acl_t acl;
+
+ if (count > ACL_MAX_ENTRIES) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+ if (count < 0) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ error = posix_memalign((void *)&acl, 1 << _ACL_T_ALIGNMENT_BITS,
+ sizeof(struct acl_t_struct));
+ if (error)
+ return (NULL);
+
+ bzero(acl, sizeof(struct acl_t_struct));
+ acl->ats_brand = ACL_BRAND_UNKNOWN;
+ acl->ats_acl.acl_maxcnt = ACL_MAX_ENTRIES;
+
+ return (acl);
+}
+
+acl_t
+acl_dup(acl_t acl)
+{
+ acl_t acl_new;
+
+ acl_new = acl_init(ACL_MAX_ENTRIES);
+ if (acl_new != NULL) {
+ *acl_new = *acl;
+ acl->ats_cur_entry = 0;
+ acl_new->ats_cur_entry = 0;
+ }
+
+ return (acl_new);
+}
diff --git a/lib/libc/posix1e/acl_is_trivial_np.3 b/lib/libc/posix1e/acl_is_trivial_np.3
new file mode 100644
index 0000000..4ad1a63
--- /dev/null
+++ b/lib/libc/posix1e/acl_is_trivial_np.3
@@ -0,0 +1,86 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 13, 2010
+.Dt ACL_STRIP_NP 3
+.Os
+.Sh NAME
+.Nm acl_is_trivial_np
+.Nd determine whether ACL is trivial
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_is_trivial_np "const acl_t aclp" "int *trivialp"
+.Sh DESCRIPTION
+The
+.Fn acl_is_trivial
+function determines whether the ACL pointed to by the argument
+.Va acl
+is trivial.
+Upon successful completion, the location referred to by the argument
+.Fa trivialp
+will be set to 1, if the ACL
+.Fa aclp
+points to is trivial, or 0 if it's not.
+.Pp
+ACL is trivial if it can be fully expressed as a file mode without loosing
+any access rules.
+For POSIX.1e ACLs, ACL is trivial if it has the three required entries,
+one for owner, one for owning group, and one for other.
+For NFSv4 ACLs, ACL is trivial if is identical to the ACL generated by
+.Fn acl_strip_np 3
+from the file mode.
+Files that have non-trivial ACL have a plus sign appended after mode bits
+in "ls -l" output.
+.Sh RETURN VALUES
+.Rv -std acl_get_tag_type
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_is_trivial_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_perm.c b/lib/libc/posix1e/acl_perm.c
new file mode 100644
index 0000000..ad2f47e
--- /dev/null
+++ b/lib/libc/posix1e/acl_perm.c
@@ -0,0 +1,128 @@
+/*
+ * Copyright (c) 2001-2002 Chris D. Faulhaber
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+
+#include <errno.h>
+#include <string.h>
+
+static int
+_perm_is_invalid(acl_perm_t perm)
+{
+
+ /* Check if more than a single bit is set. */
+ if ((perm & -perm) == perm &&
+ (perm & (ACL_POSIX1E_BITS | ACL_NFS4_PERM_BITS)) == perm)
+ return (0);
+
+ errno = EINVAL;
+
+ return (1);
+}
+
+/*
+ * acl_add_perm() (23.4.1): add the permission contained in perm to the
+ * permission set permset_d
+ */
+int
+acl_add_perm(acl_permset_t permset_d, acl_perm_t perm)
+{
+
+ if (permset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_perm_is_invalid(perm))
+ return (-1);
+
+ *permset_d |= perm;
+
+ return (0);
+}
+
+/*
+ * acl_clear_perms() (23.4.3): clear all permisions from the permission
+ * set permset_d
+ */
+int
+acl_clear_perms(acl_permset_t permset_d)
+{
+
+ if (permset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ *permset_d = ACL_PERM_NONE;
+
+ return (0);
+}
+
+/*
+ * acl_delete_perm() (23.4.10): remove the permission in perm from the
+ * permission set permset_d
+ */
+int
+acl_delete_perm(acl_permset_t permset_d, acl_perm_t perm)
+{
+
+ if (permset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_perm_is_invalid(perm))
+ return (-1);
+
+ *permset_d &= ~perm;
+
+ return (0);
+}
+
+int
+acl_get_perm_np(acl_permset_t permset_d, acl_perm_t perm)
+{
+
+ if (permset_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (_perm_is_invalid(perm))
+ return (-1);
+
+ if (*permset_d & perm)
+ return (1);
+
+ return (0);
+}
diff --git a/lib/libc/posix1e/acl_set.3 b/lib/libc/posix1e/acl_set.3
new file mode 100644
index 0000000..7450dc9
--- /dev/null
+++ b/lib/libc/posix1e/acl_set.3
@@ -0,0 +1,157 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_SET 3
+.Os
+.Sh NAME
+.Nm acl_set_fd ,
+.Nm acl_set_fd_np ,
+.Nm acl_set_file ,
+.Nm acl_set_link_np
+.Nd set an ACL for a file
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_set_fd "int fd" "acl_t acl"
+.Ft int
+.Fn acl_set_fd_np "int fd" "acl_t acl" "acl_type_t type"
+.Ft int
+.Fn acl_set_file "const char *path_p" "acl_type_t type" "acl_t acl"
+.Ft int
+.Fn acl_set_link_np "const char *path_p" "acl_type_t type" "acl_t acl"
+.Sh DESCRIPTION
+The
+.Fn acl_set_fd ,
+.Fn acl_set_fd_np ,
+.Fn acl_set_file ,
+and
+.Fn acl_set_link_np
+each associate an ACL with an object referred to by
+.Va fd
+or
+.Va path_p .
+The
+.Fn acl_set_fd_np
+and
+.Fn acl_set_link_np
+functions are not POSIX.1e calls.
+The
+.Fn acl_set_fd
+function allows only the setting of ACLs of type ACL_TYPE_ACCESS
+where as
+.Fn acl_set_fd_np
+allows the setting of ACLs of any type.
+The
+.Fn acl_set_link_np
+function acts on a symlink rather than its target, if the target of the
+path is a symlink.
+.Pp
+Valid values for the
+.Va type
+argument are:
+.Bl -column -offset 3n "ACL_TYPE_DEFAULT"
+.It ACL_TYPE_ACCESS POSIX.1e access ACL
+.It ACL_TYPE_DEFAULT POSIX.1e default ACL
+.It ACL_TYPE_NFS4 NFSv4 ACL
+.El
+.Pp
+Trying to set ACL_TYPE_NFS4 with
+.Va acl
+branded as POSIX.1e, or ACL_TYPE_ACCESS or ACL_TYPE_DEFAULT with ACL
+branded as NFSv4, will result in error.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+If any of the following conditions occur, these functions shall return
+-1 and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EACCES
+Search permission is denied for a component of the path prefix, or the
+object exists and the process does not have appropriate access rights.
+.It Bq Er EBADF
+The
+.Va fd
+argument is not a valid file descriptor.
+.It Bq Er EINVAL
+Argument
+.Va acl
+does not point to a valid ACL for this object, or the ACL type
+specified in
+.Va type
+is invalid for this object, or there is branding mismatch.
+.It Bq Er ENAMETOOLONG
+A component of a pathname exceeded 255 characters, or an
+entire path name exceeded 1023 characters.
+.It Bq Er ENOENT
+The named object does not exist, or the
+.Va path_p
+argument points to an empty string.
+.It Bq Er ENOMEM
+Insufficient memory available to fulfill request.
+.It Bq Er ENOSPC
+The directory or file system that would contain the new ACL cannot be
+extended, or the file system is out of file allocation resources.
+.It Bq Er EOPNOTSUPP
+The file system does not support ACL retrieval.
+.It Bq Er EROFS
+This function requires modification of a file system which is currently
+read-only.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_delete 3 ,
+.Xr acl_get 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_valid 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_set.c b/lib/libc/posix1e/acl_set.c
new file mode 100644
index 0000000..fdc12b6
--- /dev/null
+++ b/lib/libc/posix1e/acl_set.c
@@ -0,0 +1,253 @@
+/*-
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * acl_set_file -- set a file/directory ACL by name
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "acl_support.h"
+
+/*
+ * For POSIX.1e-semantic ACLs, do a presort so the kernel doesn't have to
+ * (the POSIX.1e semantic code will reject unsorted ACL submission). If it's
+ * not a semantic that the library knows about, just submit it flat and
+ * assume the caller knows what they're up to.
+ */
+int
+acl_set_file(const char *path_p, acl_type_t type, acl_t acl)
+{
+
+ if (acl == NULL || path_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ type = _acl_type_unold(type);
+ if (_acl_type_not_valid_for_acl(acl, type)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (_posix1e_acl(acl, type))
+ _posix1e_acl_sort(acl);
+
+ acl->ats_cur_entry = 0;
+
+ return (__acl_set_file(path_p, type, &acl->ats_acl));
+}
+
+int
+acl_set_link_np(const char *path_p, acl_type_t type, acl_t acl)
+{
+
+ if (acl == NULL || path_p == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ type = _acl_type_unold(type);
+ if (_acl_type_not_valid_for_acl(acl, type)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (_posix1e_acl(acl, type))
+ _posix1e_acl_sort(acl);
+
+ acl->ats_cur_entry = 0;
+
+ return (__acl_set_link(path_p, type, &acl->ats_acl));
+}
+
+int
+acl_set_fd(int fd, acl_t acl)
+{
+
+ if (fpathconf(fd, _PC_ACL_NFS4) == 1)
+ return (acl_set_fd_np(fd, acl, ACL_TYPE_NFS4));
+
+ return (acl_set_fd_np(fd, acl, ACL_TYPE_ACCESS));
+}
+
+int
+acl_set_fd_np(int fd, acl_t acl, acl_type_t type)
+{
+
+ if (acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ type = _acl_type_unold(type);
+ if (_acl_type_not_valid_for_acl(acl, type)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (_posix1e_acl(acl, type))
+ _posix1e_acl_sort(acl);
+
+ acl->ats_cur_entry = 0;
+
+ return (___acl_set_fd(fd, type, &acl->ats_acl));
+}
+
+/*
+ * acl_set_permset() (23.4.23): sets the permissions of ACL entry entry_d
+ * with the permissions in permset_d
+ */
+int
+acl_set_permset(acl_entry_t entry_d, acl_permset_t permset_d)
+{
+
+ if (!entry_d) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((*permset_d & ACL_POSIX1E_BITS) != *permset_d) {
+ if ((*permset_d & ACL_NFS4_PERM_BITS) != *permset_d) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _entry_brand_as(entry_d, ACL_BRAND_NFS4);
+ }
+
+ entry_d->ae_perm = *permset_d;
+
+ return (0);
+}
+
+/*
+ * acl_set_qualifier() sets the qualifier (ae_id) of the tag for
+ * ACL entry entry_d to the value referred to by tag_qualifier_p
+ */
+int
+acl_set_qualifier(acl_entry_t entry_d, const void *tag_qualifier_p)
+{
+
+ if (!entry_d || !tag_qualifier_p) {
+ errno = EINVAL;
+ return (-1);
+ }
+ switch(entry_d->ae_tag) {
+ case ACL_USER:
+ case ACL_GROUP:
+ entry_d->ae_id = *(uid_t *)tag_qualifier_p;
+ break;
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+
+ return (0);
+}
+
+/*
+ * acl_set_tag_type() sets the tag type for ACL entry entry_d to the
+ * value of tag_type
+ */
+int
+acl_set_tag_type(acl_entry_t entry_d, acl_tag_t tag_type)
+{
+
+ if (entry_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ switch(tag_type) {
+ case ACL_OTHER:
+ case ACL_MASK:
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_POSIX)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _entry_brand_as(entry_d, ACL_BRAND_POSIX);
+ break;
+ case ACL_EVERYONE:
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _entry_brand_as(entry_d, ACL_BRAND_NFS4);
+ break;
+ }
+
+ switch(tag_type) {
+ case ACL_USER_OBJ:
+ case ACL_USER:
+ case ACL_GROUP_OBJ:
+ case ACL_GROUP:
+ case ACL_MASK:
+ case ACL_OTHER:
+ case ACL_EVERYONE:
+ entry_d->ae_tag = tag_type;
+ return (0);
+ }
+
+ errno = EINVAL;
+ return (-1);
+}
+
+int
+acl_set_entry_type_np(acl_entry_t entry_d, acl_entry_type_t entry_type)
+{
+
+ if (entry_d == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (!_entry_brand_may_be(entry_d, ACL_BRAND_NFS4)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _entry_brand_as(entry_d, ACL_BRAND_NFS4);
+
+ switch (entry_type) {
+ case ACL_ENTRY_TYPE_ALLOW:
+ case ACL_ENTRY_TYPE_DENY:
+ case ACL_ENTRY_TYPE_AUDIT:
+ case ACL_ENTRY_TYPE_ALARM:
+ entry_d->ae_entry_type = entry_type;
+ return (0);
+ }
+
+ errno = EINVAL;
+ return (-1);
+}
diff --git a/lib/libc/posix1e/acl_set_entry_type_np.3 b/lib/libc/posix1e/acl_set_entry_type_np.3
new file mode 100644
index 0000000..648775d
--- /dev/null
+++ b/lib/libc/posix1e/acl_set_entry_type_np.3
@@ -0,0 +1,94 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_SET_ENTRY_TYPE_NP 3
+.Os
+.Sh NAME
+.Nm acl_set_entry_type_np
+.Nd set NFSv4 ACL entry type
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_set_entry_type_np "acl_entry_t entry_d" "acl_entry_type_t entry_type"
+.Sh DESCRIPTION
+The
+.Fn acl_set_entry_type_np
+function
+is a non-portable call that sets the type of the ACL entry
+.Fa entry_d
+to the value referred to by
+.Fa entry_type .
+.Pp
+Valid values are:
+.Bl -column -offset 3n "ACL_ENTRY_TYPE_ALLOW"
+.It ACL_ENTRY_TYPE_ALLOW Ta "allow" type entry
+.It ACL_ENTRY_TYPE_DENY Ta "deny" type entry
+.El
+.Pp
+This call brands the ACL as NFSv4.
+.Sh RETURN VALUES
+.Rv -std acl_set_entry_type_np
+.Sh ERRORS
+The
+.Fn acl_set_entry_type_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+The value pointed to by
+.Fa entry_type
+is not valid.
+ACL is already branded as POSIX.1e.
+.It Bq Er ENOMEM
+The value to be returned requires more memory than is allowed
+by the hardware or system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_get_entry_type_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_entry_type_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_entry_type_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_set_flagset_np.3 b/lib/libc/posix1e/acl_set_flagset_np.3
new file mode 100644
index 0000000..386665d
--- /dev/null
+++ b/lib/libc/posix1e/acl_set_flagset_np.3
@@ -0,0 +1,85 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_SET_FLAGSET_NP 3
+.Os
+.Sh NAME
+.Nm acl_set_flagset_np
+.Nd set the flags of an NFSv4 ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_set_flagset_np "acl_entry_t entry_d" "acl_flagset_t flagset_d"
+.Sh DESCRIPTION
+The
+.Fn acl_set_flagset_np
+function
+is a non-portable call that sets the flags of ACL entry
+.Fa entry_d
+with the flags contained in
+.Fa flagset_d .
+.Pp
+This call brands the ACL as NFSv4.
+.Sh RETURN VALUES
+.Rv -std acl_set_flagset_np
+.Sh ERRORS
+The
+.Fn acl_set_flagset_np
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+ACL is already branded as POSIX.1e.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_flag_np 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_clear_flags_np 3 ,
+.Xr acl_delete_flag_np 3 ,
+.Xr acl_get_flagset_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_set_flagset_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+The
+.Fn acl_set_flagset_np
+function was written by
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_set_permset.3 b/lib/libc/posix1e/acl_set_permset.3
new file mode 100644
index 0000000..0cf6581
--- /dev/null
+++ b/lib/libc/posix1e/acl_set_permset.3
@@ -0,0 +1,81 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 10, 2001
+.Dt ACL_SET_PERMSET 3
+.Os
+.Sh NAME
+.Nm acl_set_permset
+.Nd set the permissions of an ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_set_permset "acl_entry_t entry_d" "acl_permset_t permset_d"
+.Sh DESCRIPTION
+The
+.Fn acl_set_permset
+function
+is a POSIX.1e call that sets the permissions of ACL entry
+.Fa entry_d
+with the permissions contained in
+.Fa permset_d .
+.Sh RETURN VALUES
+.Rv -std acl_set_permset
+.Sh ERRORS
+The
+.Fn acl_set_permset
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_add_perm 3 ,
+.Xr acl_clear_perms 3 ,
+.Xr acl_delete_perm 3 ,
+.Xr acl_get_permset 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_set_permset
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_set_permset
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_set_qualifier.3 b/lib/libc/posix1e/acl_set_qualifier.3
new file mode 100644
index 0000000..47a60d8
--- /dev/null
+++ b/lib/libc/posix1e/acl_set_qualifier.3
@@ -0,0 +1,91 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 10, 2001
+.Dt ACL_SET_QUALIFIER 3
+.Os
+.Sh NAME
+.Nm acl_set_qualifier
+.Nd set ACL tag qualifier
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_set_qualifier "acl_entry_t entry_d" "const void *tag_qualifier_p"
+.Sh DESCRIPTION
+The
+.Fn acl_set_qualifier
+function
+is a POSIX.1e call that sets the qualifier of the tag for the ACL entry
+.Fa entry_d
+to the value referred to by
+.Fa tag_qualifier_p .
+.Sh RETURN VALUES
+.Rv -std acl_set_qualifier
+.Sh ERRORS
+The
+.Fn acl_set_qualifier
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+The tag type of the
+ACL entry
+.Fa entry_d
+is not
+.Dv ACL_USER
+or
+.Dv ACL_GROUP .
+The value pointed to by
+.Fa tag_qualifier_p
+is not valid.
+.It Bq Er ENOMEM
+The value to be returned requires more memory than is allowed
+by the hardware or system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get_qualifier 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_get_qualifier
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_get_qualifier
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_set_tag_type.3 b/lib/libc/posix1e/acl_set_tag_type.3
new file mode 100644
index 0000000..79526a0
--- /dev/null
+++ b/lib/libc/posix1e/acl_set_tag_type.3
@@ -0,0 +1,102 @@
+.\"-
+.\" Copyright (c) 2001 Chris D. Faulhaber
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_SET_TAG_TYPE 3
+.Os
+.Sh NAME
+.Nm acl_set_tag_type
+.Nd set the tag type of an ACL entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_set_tag_type "acl_entry_t entry_d" "acl_tag_t tag_type"
+.Sh DESCRIPTION
+The
+.Fn acl_set_tag_type
+function
+is a POSIX.1e call that sets the ACL tag type of ACL entry
+.Fa entry_d
+to the value of
+.Fa tag_type .
+.Pp
+Valid values are:
+.Bl -column -offset 3n "ACL_OTHER_OBJ"
+.It ACL_USER_OBJ Ta "Permissions apply to file owner"
+.It ACL_USER Ta "Permissions apply to additional user specified by qualifier"
+.It ACL_GROUP_OBJ Ta "Permissions apply to file group"
+.It ACL_GROUP Ta "Permissions apply to additional group specified by qualifier"
+.It ACL_MASK Ta "Permissions specify mask"
+.It ACL_OTHER Ta Permissions apply to "other"
+.It ACL_OTHER_OBJ Ta "Same as ACL_OTHER"
+.It ACL_EVERYONE Ta Permissions apply to "everyone@"
+.El
+.Pp
+Calling
+.Fn acl_set_tag_type
+with
+.Fa tag_type
+equal to ACL_MASK, ACL_OTHER or ACL_OTHER_OBJ brands the ACL as POSIX.1e.
+Calling it with ACL_EVERYONE brands the ACL as NFSv4.
+.Sh RETURN VALUES
+.Rv -std acl_set_tag_type
+.Sh ERRORS
+The
+.Fn acl_set_tag_type
+function fails if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Fa entry_d
+is not a valid descriptor for an ACL entry.
+Argument
+.Fa tag_type
+is not a valid ACL tag type.
+ACL is already branded differently.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get_brand_np 3 ,
+.Xr acl_get_tag_type 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_set_tag_type
+function was added in
+.Fx 5.0 .
+.Sh AUTHORS
+The
+.Fn acl_set_tag_type
+function was written by
+.An Chris D. Faulhaber Aq jedgar@fxp.org .
diff --git a/lib/libc/posix1e/acl_size.c b/lib/libc/posix1e/acl_size.c
new file mode 100644
index 0000000..27ad651
--- /dev/null
+++ b/lib/libc/posix1e/acl_size.c
@@ -0,0 +1,43 @@
+/*
+ * Copyright (c) 2001-2002 Chris D. Faulhaber
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+
+#include <errno.h>
+
+ssize_t
+acl_size(acl_t acl)
+{
+
+ errno = ENOSYS;
+ return (-1);
+}
diff --git a/lib/libc/posix1e/acl_strip.c b/lib/libc/posix1e/acl_strip.c
new file mode 100644
index 0000000..ae37b38
--- /dev/null
+++ b/lib/libc/posix1e/acl_strip.c
@@ -0,0 +1,225 @@
+/*-
+ * Copyright (c) 2001 Chris D. Faulhaber
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stdio.h>
+#include <assert.h>
+#include <sys/acl.h>
+#include <sys/stat.h>
+
+#include "acl_support.h"
+
+/*
+ * These routines from sys/kern/subr_acl_nfs4.c are used by both kernel
+ * and libc.
+ */
+void acl_nfs4_sync_mode_from_acl(mode_t *_mode, const struct acl *aclp);
+void acl_nfs4_trivial_from_mode_libc(struct acl *aclp, int file_owner_id,
+ int canonical_six);
+
+static acl_t
+_nfs4_acl_strip_np(const acl_t aclp, int canonical_six)
+{
+ acl_t newacl;
+ mode_t mode = 0;
+
+ newacl = acl_init(ACL_MAX_ENTRIES);
+ if (newacl == NULL) {
+ errno = ENOMEM;
+ return (NULL);
+ }
+
+ _acl_brand_as(newacl, ACL_BRAND_NFS4);
+
+ acl_nfs4_sync_mode_from_acl(&mode, &(aclp->ats_acl));
+ acl_nfs4_trivial_from_mode_libc(&(newacl->ats_acl), mode, canonical_six);
+
+ return (newacl);
+}
+
+static acl_t
+_posix1e_acl_strip_np(const acl_t aclp, int recalculate_mask)
+{
+ acl_t acl_new, acl_old;
+ acl_entry_t entry, entry_new;
+ acl_permset_t perm;
+ acl_tag_t tag;
+ int entry_id, have_mask_entry;
+
+ assert(_acl_brand(aclp) == ACL_BRAND_POSIX);
+
+ acl_old = acl_dup(aclp);
+ if (acl_old == NULL)
+ return (NULL);
+
+ assert(_acl_brand(acl_old) == ACL_BRAND_POSIX);
+
+ have_mask_entry = 0;
+ acl_new = acl_init(ACL_MAX_ENTRIES);
+ if (acl_new == NULL)
+ return (NULL);
+ tag = ACL_UNDEFINED_TAG;
+
+ /* only save the default user/group/other entries */
+ entry_id = ACL_FIRST_ENTRY;
+ while (acl_get_entry(acl_old, entry_id, &entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+
+ assert(_entry_brand(entry) == ACL_BRAND_POSIX);
+
+ if (acl_get_tag_type(entry, &tag) == -1)
+ return (NULL);
+
+ switch(tag) {
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_OTHER:
+ if (acl_get_tag_type(entry, &tag) == -1)
+ return (NULL);
+ if (acl_get_permset(entry, &perm) == -1)
+ return (NULL);
+ if (acl_create_entry(&acl_new, &entry_new) == -1)
+ return (NULL);
+ if (acl_set_tag_type(entry_new, tag) == -1)
+ return (NULL);
+ if (acl_set_permset(entry_new, perm) == -1)
+ return (NULL);
+ if (acl_copy_entry(entry_new, entry) == -1)
+ return (NULL);
+ assert(_entry_brand(entry_new) == ACL_BRAND_POSIX);
+ break;
+ case ACL_MASK:
+ have_mask_entry = 1;
+ break;
+ default:
+ break;
+ }
+ }
+
+ assert(_acl_brand(acl_new) == ACL_BRAND_POSIX);
+
+ if (have_mask_entry && recalculate_mask) {
+ if (acl_calc_mask(&acl_new) == -1)
+ return (NULL);
+ }
+
+ return (acl_new);
+}
+
+acl_t
+acl_strip_np(const acl_t aclp, int recalculate_mask)
+{
+ switch (_acl_brand(aclp)) {
+ case ACL_BRAND_NFS4:
+ return (_nfs4_acl_strip_np(aclp, 0));
+
+ case ACL_BRAND_POSIX:
+ return (_posix1e_acl_strip_np(aclp, recalculate_mask));
+
+ default:
+ errno = EINVAL;
+ return (NULL);
+ }
+}
+
+/*
+ * Return 1, if ACL is trivial, 0 otherwise.
+ *
+ * ACL is trivial, iff its meaning could be fully expressed using just file
+ * mode. In other words, ACL is trivial iff it doesn't have "+" to the right
+ * of the mode bits in "ls -l" output ;-)
+ */
+int
+acl_is_trivial_np(const acl_t aclp, int *trivialp)
+{
+ acl_t tmpacl;
+ int differs;
+
+ if (aclp == NULL || trivialp == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ switch (_acl_brand(aclp)) {
+ case ACL_BRAND_POSIX:
+ if (aclp->ats_acl.acl_cnt == 3)
+ *trivialp = 1;
+ else
+ *trivialp = 0;
+
+ return (0);
+
+ case ACL_BRAND_NFS4:
+ /*
+ * If the ACL has more than canonical six entries,
+ * it's non trivial by definition.
+ */
+ if (aclp->ats_acl.acl_cnt > 6) {
+ *trivialp = 0;
+ return (0);
+ }
+
+ /*
+ * Calculate trivial ACL - using acl_strip_np(3) - and compare
+ * with the original.
+ */
+ tmpacl = _nfs4_acl_strip_np(aclp, 0);
+ if (tmpacl == NULL)
+ return (-1);
+
+ differs = _acl_differs(aclp, tmpacl);
+ acl_free(tmpacl);
+
+ if (differs == 0) {
+ *trivialp = 1;
+ return (0);
+ }
+
+ /*
+ * Try again with an old-style, "canonical six" trivial ACL.
+ */
+ tmpacl = _nfs4_acl_strip_np(aclp, 1);
+ if (tmpacl == NULL)
+ return (-1);
+
+ differs = _acl_differs(aclp, tmpacl);
+ acl_free(tmpacl);
+
+ if (differs)
+ *trivialp = 0;
+ else
+ *trivialp = 1;
+
+ return (0);
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+}
diff --git a/lib/libc/posix1e/acl_strip_np.3 b/lib/libc/posix1e/acl_strip_np.3
new file mode 100644
index 0000000..cc6c65b
--- /dev/null
+++ b/lib/libc/posix1e/acl_strip_np.3
@@ -0,0 +1,109 @@
+.\"-
+.\" Copyright (c) 2008, 2009 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_STRIP_NP 3
+.Os
+.Sh NAME
+.Nm acl_strip_np
+.Nd strip extended entries from an ACL
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft acl_t
+.Fn acl_strip_np "const acl_t acl" "int recalculate_mask"
+.Sh DESCRIPTION
+The
+.Fn acl_strip_np
+function returns a pointer to a trivial ACL computed from the ACL pointed
+to by the argument
+.Va acl .
+.Pp
+This function may cause memory to be allocated.
+The caller should free any
+releasable memory, when the new ACL is no longer required, by calling
+.Xr acl_free 3
+with the
+.Va (void*)acl_t
+as an argument.
+.Pp
+Any existing ACL pointers that refer to the ACL referred to by
+.Va acl
+shall continue to refer to the ACL.
+.Sh RETURN VALUES
+Upon successful completion, this function shall return a pointer to the
+newly allocated ACL.
+Otherwise, a value of
+.Va (acl_t)NULL
+shall be returned, and
+.Va errno
+shall be set to indicate the error.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_init
+function shall return a value of
+.Va (acl_t)NULL
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Va acl
+does not point to a valid ACL.
+.It Bq Er ENOMEM
+The
+.Va acl_t
+to be returned requires more memory than is allowed by the hardware or
+system-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_is_trivial_np 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 .
+The
+.Fn acl_strip_np
+function was added in
+.Fx 8.0 .
+.Sh AUTHORS
+.An Edward Tomasz Napierala Aq trasz@FreeBSD.org .
diff --git a/lib/libc/posix1e/acl_support.c b/lib/libc/posix1e/acl_support.c
new file mode 100644
index 0000000..9f5404c
--- /dev/null
+++ b/lib/libc/posix1e/acl_support.c
@@ -0,0 +1,418 @@
+/*-
+ * Copyright (c) 1999-2001, 2008 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * Support functionality for the POSIX.1e ACL interface
+ * These calls are intended only to be called within the library.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+#include <errno.h>
+#include <grp.h>
+#include <pwd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "acl_support.h"
+
+#define ACL_STRING_PERM_WRITE 'w'
+#define ACL_STRING_PERM_READ 'r'
+#define ACL_STRING_PERM_EXEC 'x'
+#define ACL_STRING_PERM_NONE '-'
+
+/*
+ * Return 0, if both ACLs are identical.
+ */
+int
+_acl_differs(const acl_t a, const acl_t b)
+{
+ int i;
+ struct acl_entry *entrya, *entryb;
+
+ assert(_acl_brand(a) == _acl_brand(b));
+ assert(_acl_brand(a) != ACL_BRAND_UNKNOWN);
+ assert(_acl_brand(b) != ACL_BRAND_UNKNOWN);
+
+ if (a->ats_acl.acl_cnt != b->ats_acl.acl_cnt)
+ return (1);
+
+ for (i = 0; i < b->ats_acl.acl_cnt; i++) {
+ entrya = &(a->ats_acl.acl_entry[i]);
+ entryb = &(b->ats_acl.acl_entry[i]);
+
+ if (entrya->ae_tag != entryb->ae_tag ||
+ entrya->ae_id != entryb->ae_id ||
+ entrya->ae_perm != entryb->ae_perm ||
+ entrya->ae_entry_type != entryb->ae_entry_type ||
+ entrya->ae_flags != entryb->ae_flags)
+ return (1);
+ }
+
+ return (0);
+}
+
+/*
+ * _posix1e_acl_entry_compare -- compare two acl_entry structures to
+ * determine the order they should appear in. Used by _posix1e_acl_sort to
+ * sort ACL entries into the kernel-desired order -- i.e., the order useful
+ * for evaluation and O(n) validity checking. Beter to have an O(nlogn) sort
+ * in userland and an O(n) in kernel than to have both in kernel.
+ */
+typedef int (*compare)(const void *, const void *);
+static int
+_posix1e_acl_entry_compare(struct acl_entry *a, struct acl_entry *b)
+{
+
+ assert(_entry_brand(a) == ACL_BRAND_POSIX);
+ assert(_entry_brand(b) == ACL_BRAND_POSIX);
+
+ /*
+ * First, sort between tags -- conveniently defined in the correct
+ * order for verification.
+ */
+ if (a->ae_tag < b->ae_tag)
+ return (-1);
+ if (a->ae_tag > b->ae_tag)
+ return (1);
+
+ /*
+ * Next compare uids/gids on appropriate types.
+ */
+
+ if (a->ae_tag == ACL_USER || a->ae_tag == ACL_GROUP) {
+ if (a->ae_id < b->ae_id)
+ return (-1);
+ if (a->ae_id > b->ae_id)
+ return (1);
+
+ /* shouldn't be equal, fall through to the invalid case */
+ }
+
+ /*
+ * Don't know how to sort multiple entries of the rest--either it's
+ * a bad entry, or there shouldn't be more than one. Ignore and the
+ * validity checker can get it later.
+ */
+ return (0);
+}
+
+/*
+ * _posix1e_acl_sort -- sort ACL entries in POSIX.1e-formatted ACLs.
+ */
+void
+_posix1e_acl_sort(acl_t acl)
+{
+ struct acl *acl_int;
+
+ acl_int = &acl->ats_acl;
+
+ qsort(&acl_int->acl_entry[0], acl_int->acl_cnt,
+ sizeof(struct acl_entry), (compare) _posix1e_acl_entry_compare);
+}
+
+/*
+ * acl_posix1e -- in what situations should we acl_sort before submission?
+ * We apply posix1e ACL semantics for any ACL of type ACL_TYPE_ACCESS or
+ * ACL_TYPE_DEFAULT
+ */
+int
+_posix1e_acl(acl_t acl, acl_type_t type)
+{
+
+ if (_acl_brand(acl) != ACL_BRAND_POSIX)
+ return (0);
+
+ return ((type == ACL_TYPE_ACCESS) || (type == ACL_TYPE_DEFAULT));
+}
+
+/*
+ * _posix1e_acl_check -- given an ACL, check its validity. This is mirrored
+ * from code in sys/kern/kern_acl.c, and if changes are made in one, they
+ * should be made in the other also. This copy of acl_check is made
+ * available * in userland for the benefit of processes wanting to check ACLs
+ * for validity before submitting them to the kernel, or for performing
+ * in userland file system checking. Needless to say, the kernel makes
+ * the real checks on calls to get/setacl.
+ *
+ * See the comments in kernel for explanation -- just briefly, it assumes
+ * an already sorted ACL, and checks based on that assumption. The
+ * POSIX.1e interface, acl_valid(), will perform the sort before calling
+ * this. Returns 0 on success, EINVAL on failure.
+ */
+int
+_posix1e_acl_check(acl_t acl)
+{
+ struct acl *acl_int;
+ struct acl_entry *entry; /* current entry */
+ uid_t highest_uid=0, highest_gid=0;
+ int stage = ACL_USER_OBJ;
+ int i = 0;
+ int count_user_obj=0, count_user=0, count_group_obj=0,
+ count_group=0, count_mask=0, count_other=0;
+
+ acl_int = &acl->ats_acl;
+
+ /* printf("_posix1e_acl_check: checking acl with %d entries\n",
+ acl->acl_cnt); */
+ while (i < acl_int->acl_cnt) {
+ entry = &acl_int->acl_entry[i];
+
+ if ((entry->ae_perm | ACL_PERM_BITS) != ACL_PERM_BITS)
+ return (EINVAL);
+
+ switch(entry->ae_tag) {
+ case ACL_USER_OBJ:
+ /* printf("_posix1e_acl_check: %d: ACL_USER_OBJ\n",
+ i); */
+ if (stage > ACL_USER_OBJ)
+ return (EINVAL);
+ stage = ACL_USER;
+ count_user_obj++;
+ break;
+
+ case ACL_USER:
+ /* printf("_posix1e_acl_check: %d: ACL_USER\n", i); */
+ if (stage > ACL_USER)
+ return (EINVAL);
+ stage = ACL_USER;
+ if (count_user && (entry->ae_id <= highest_uid))
+ return (EINVAL);
+ highest_uid = entry->ae_id;
+ count_user++;
+ break;
+
+ case ACL_GROUP_OBJ:
+ /* printf("_posix1e_acl_check: %d: ACL_GROUP_OBJ\n",
+ i); */
+ if (stage > ACL_GROUP_OBJ)
+ return (EINVAL);
+ stage = ACL_GROUP;
+ count_group_obj++;
+ break;
+
+ case ACL_GROUP:
+ /* printf("_posix1e_acl_check: %d: ACL_GROUP\n", i); */
+ if (stage > ACL_GROUP)
+ return (EINVAL);
+ stage = ACL_GROUP;
+ if (count_group && (entry->ae_id <= highest_gid))
+ return (EINVAL);
+ highest_gid = entry->ae_id;
+ count_group++;
+ break;
+
+ case ACL_MASK:
+ /* printf("_posix1e_acl_check: %d: ACL_MASK\n", i); */
+ if (stage > ACL_MASK)
+ return (EINVAL);
+ stage = ACL_MASK;
+ count_mask++;
+ break;
+
+ case ACL_OTHER:
+ /* printf("_posix1e_acl_check: %d: ACL_OTHER\n", i); */
+ if (stage > ACL_OTHER)
+ return (EINVAL);
+ stage = ACL_OTHER;
+ count_other++;
+ break;
+
+ default:
+ /* printf("_posix1e_acl_check: %d: INVALID\n", i); */
+ return (EINVAL);
+ }
+ i++;
+ }
+
+ if (count_user_obj != 1)
+ return (EINVAL);
+
+ if (count_group_obj != 1)
+ return (EINVAL);
+
+ if (count_mask != 0 && count_mask != 1)
+ return (EINVAL);
+
+ if (count_other != 1)
+ return (EINVAL);
+
+ return (0);
+}
+
+/*
+ * Given a right-shifted permission (i.e., direct ACL_PERM_* mask), fill
+ * in a string describing the permissions.
+ */
+int
+_posix1e_acl_perm_to_string(acl_perm_t perm, ssize_t buf_len, char *buf)
+{
+
+ if (buf_len < _POSIX1E_ACL_STRING_PERM_MAXSIZE + 1) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ if ((perm | ACL_PERM_BITS) != ACL_PERM_BITS) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ buf[3] = 0; /* null terminate */
+
+ if (perm & ACL_READ)
+ buf[0] = ACL_STRING_PERM_READ;
+ else
+ buf[0] = ACL_STRING_PERM_NONE;
+
+ if (perm & ACL_WRITE)
+ buf[1] = ACL_STRING_PERM_WRITE;
+ else
+ buf[1] = ACL_STRING_PERM_NONE;
+
+ if (perm & ACL_EXECUTE)
+ buf[2] = ACL_STRING_PERM_EXEC;
+ else
+ buf[2] = ACL_STRING_PERM_NONE;
+
+ return (0);
+}
+
+/*
+ * given a string, return a permission describing it
+ */
+int
+_posix1e_acl_string_to_perm(char *string, acl_perm_t *perm)
+{
+ acl_perm_t myperm = ACL_PERM_NONE;
+ char *ch;
+
+ ch = string;
+ while (*ch) {
+ switch(*ch) {
+ case ACL_STRING_PERM_READ:
+ myperm |= ACL_READ;
+ break;
+ case ACL_STRING_PERM_WRITE:
+ myperm |= ACL_WRITE;
+ break;
+ case ACL_STRING_PERM_EXEC:
+ myperm |= ACL_EXECUTE;
+ break;
+ case ACL_STRING_PERM_NONE:
+ break;
+ default:
+ return (EINVAL);
+ }
+ ch++;
+ }
+
+ *perm = myperm;
+ return (0);
+}
+
+/*
+ * Add an ACL entry without doing much checking, et al
+ */
+int
+_posix1e_acl_add_entry(acl_t acl, acl_tag_t tag, uid_t id, acl_perm_t perm)
+{
+ struct acl *acl_int;
+ struct acl_entry *e;
+
+ acl_int = &acl->ats_acl;
+
+ if (acl_int->acl_cnt >= ACL_MAX_ENTRIES) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ e = &(acl_int->acl_entry[acl_int->acl_cnt]);
+ e->ae_perm = perm;
+ e->ae_tag = tag;
+ e->ae_id = id;
+ acl_int->acl_cnt++;
+
+ return (0);
+}
+
+/*
+ * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new"
+ * counterpart. It's neccessary for the old (pre-NFSv4 ACLs) binaries
+ * to work with new libc and kernel. Fixing 'type' for old binaries with
+ * old libc and new kernel is being done by kern/vfs_acl.c:type_unold().
+ */
+int
+_acl_type_unold(acl_type_t type)
+{
+
+ switch (type) {
+ case ACL_TYPE_ACCESS_OLD:
+ return (ACL_TYPE_ACCESS);
+ case ACL_TYPE_DEFAULT_OLD:
+ return (ACL_TYPE_DEFAULT);
+ default:
+ return (type);
+ }
+}
+
+char *
+string_skip_whitespace(char *string)
+{
+
+ while (*string && ((*string == ' ') || (*string == '\t')))
+ string++;
+
+ return (string);
+}
+
+void
+string_trim_trailing_whitespace(char *string)
+{
+ char *end;
+
+ if (*string == '\0')
+ return;
+
+ end = string + strlen(string) - 1;
+
+ while (end != string) {
+ if ((*end == ' ') || (*end == '\t')) {
+ *end = '\0';
+ end--;
+ } else {
+ return;
+ }
+ }
+
+ return;
+}
diff --git a/lib/libc/posix1e/acl_support.h b/lib/libc/posix1e/acl_support.h
new file mode 100644
index 0000000..11fa29b
--- /dev/null
+++ b/lib/libc/posix1e/acl_support.h
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 1999, 2000, 2001 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+/*
+ * Support functionality for the POSIX.1e ACL interface
+ * These calls are intended only to be called within the library.
+ */
+#ifndef _ACL_SUPPORT_H
+#define _ACL_SUPPORT_H
+
+#define _POSIX1E_ACL_STRING_PERM_MAXSIZE 3 /* read, write, exec */
+#define _ACL_T_ALIGNMENT_BITS 13
+
+int _acl_type_unold(acl_type_t type);
+int _acl_differs(const acl_t a, const acl_t b);
+int _acl_type_not_valid_for_acl(const acl_t acl, acl_type_t type);
+void _acl_brand_from_type(acl_t acl, acl_type_t type);
+int _acl_brand(const acl_t acl);
+int _entry_brand(const acl_entry_t entry);
+int _acl_brand_may_be(const acl_t acl, int brand);
+int _entry_brand_may_be(const acl_entry_t entry, int brand);
+void _acl_brand_as(acl_t acl, int brand);
+void _entry_brand_as(const acl_entry_t entry, int brand);
+int _nfs4_format_flags(char *str, size_t size, acl_flag_t var, int verbose);
+int _nfs4_format_access_mask(char *str, size_t size, acl_perm_t var, int verbose);
+int _nfs4_parse_flags(const char *str, acl_flag_t *var);
+int _nfs4_parse_access_mask(const char *str, acl_perm_t *var);
+int _posix1e_acl_check(acl_t acl);
+void _posix1e_acl_sort(acl_t acl);
+int _posix1e_acl(acl_t acl, acl_type_t type);
+int _posix1e_acl_id_to_name(acl_tag_t tag, uid_t id, ssize_t buf_len,
+ char *buf, int flags);
+int _posix1e_acl_perm_to_string(acl_perm_t perm, ssize_t buf_len,
+ char *buf);
+int _posix1e_acl_string_to_perm(char *string, acl_perm_t *perm);
+int _posix1e_acl_add_entry(acl_t acl, acl_tag_t tag, uid_t id,
+ acl_perm_t perm);
+char *string_skip_whitespace(char *string);
+void string_trim_trailing_whitespace(char *string);
+int _acl_name_to_id(acl_tag_t tag, char *name, uid_t *id);
+
+#endif
diff --git a/lib/libc/posix1e/acl_support_nfs4.c b/lib/libc/posix1e/acl_support_nfs4.c
new file mode 100644
index 0000000..4878b43
--- /dev/null
+++ b/lib/libc/posix1e/acl_support_nfs4.c
@@ -0,0 +1,260 @@
+/*-
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <err.h>
+#include <sys/acl.h>
+#include "acl_support.h"
+
+struct flagnames_struct {
+ uint32_t flag;
+ const char *name;
+ char letter;
+};
+
+struct flagnames_struct a_flags[] =
+ {{ ACL_ENTRY_FILE_INHERIT, "file_inherit", 'f'},
+ { ACL_ENTRY_DIRECTORY_INHERIT, "dir_inherit", 'd'},
+ { ACL_ENTRY_INHERIT_ONLY, "inherit_only", 'i'},
+ { ACL_ENTRY_NO_PROPAGATE_INHERIT, "no_propagate", 'n'},
+ { ACL_ENTRY_SUCCESSFUL_ACCESS, "successfull_access", 'S'},
+ { ACL_ENTRY_FAILED_ACCESS, "failed_access", 'F'},
+ /*
+ * There is no ACE_IDENTIFIER_GROUP here - SunOS does not show it
+ * in the "flags" field. There is no ACE_OWNER, ACE_GROUP or
+ * ACE_EVERYONE either, for obvious reasons.
+ */
+ { 0, 0, 0}};
+
+struct flagnames_struct a_access_masks[] =
+ {{ ACL_READ_DATA, "read_data", 'r'},
+ { ACL_WRITE_DATA, "write_data", 'w'},
+ { ACL_EXECUTE, "execute", 'x'},
+ { ACL_APPEND_DATA, "append_data", 'p'},
+ { ACL_DELETE_CHILD, "delete_child", 'D'},
+ { ACL_DELETE, "delete", 'd'},
+ { ACL_READ_ATTRIBUTES, "read_attributes", 'a'},
+ { ACL_WRITE_ATTRIBUTES, "write_attributes", 'A'},
+ { ACL_READ_NAMED_ATTRS, "read_xattr", 'R'},
+ { ACL_WRITE_NAMED_ATTRS, "write_xattr", 'W'},
+ { ACL_READ_ACL, "read_acl", 'c'},
+ { ACL_WRITE_ACL, "write_acl", 'C'},
+ { ACL_WRITE_OWNER, "write_owner", 'o'},
+ { ACL_SYNCHRONIZE, "synchronize", 's'},
+ { ACL_FULL_SET, "full_set", '\0'},
+ { ACL_MODIFY_SET, "modify_set", '\0'},
+ { ACL_READ_SET, "read_set", '\0'},
+ { ACL_WRITE_SET, "write_set", '\0'},
+ { 0, 0, 0}};
+
+static const char *
+format_flag(uint32_t *var, const struct flagnames_struct *flags)
+{
+
+ for (; flags->name != 0; flags++) {
+ if ((flags->flag & *var) == 0)
+ continue;
+
+ *var &= ~flags->flag;
+ return (flags->name);
+ }
+
+ return (NULL);
+}
+
+static int
+format_flags_verbose(char *str, size_t size, uint32_t var,
+ const struct flagnames_struct *flags)
+{
+ size_t off = 0;
+ const char *tmp;
+
+ while ((tmp = format_flag(&var, flags)) != NULL) {
+ off += snprintf(str + off, size - off, "%s/", tmp);
+ assert (off < size);
+ }
+
+ /* If there were any flags added... */
+ if (off > 0) {
+ off--;
+ /* ... then remove the last slash. */
+ assert(str[off] == '/');
+ }
+
+ str[off] = '\0';
+
+ return (0);
+}
+
+static int
+format_flags_compact(char *str, size_t size, uint32_t var,
+ const struct flagnames_struct *flags)
+{
+ size_t i;
+
+ for (i = 0; flags[i].letter != '\0'; i++) {
+ assert(i < size);
+ if ((flags[i].flag & var) == 0)
+ str[i] = '-';
+ else
+ str[i] = flags[i].letter;
+ }
+
+ str[i] = '\0';
+
+ return (0);
+}
+
+static int
+parse_flags_verbose(const char *strp, uint32_t *var,
+ const struct flagnames_struct *flags, const char *flags_name,
+ int *try_compact)
+{
+ int i, found, ever_found = 0;
+ char *str, *flag;
+
+ str = strdup(strp);
+ *try_compact = 0;
+ *var = 0;
+
+ while (str != NULL) {
+ flag = strsep(&str, "/:");
+
+ found = 0;
+ for (i = 0; flags[i].name != NULL; i++) {
+ if (strcmp(flags[i].name, flag) == 0) {
+ *var |= flags[i].flag;
+ found = 1;
+ ever_found = 1;
+ }
+ }
+
+ if (!found) {
+ if (ever_found)
+ warnx("malformed ACL: \"%s\" field contains "
+ "invalid flag \"%s\"", flags_name, flag);
+ else
+ *try_compact = 1;
+ free(str);
+ return (-1);
+ }
+ }
+
+ free(str);
+ return (0);
+}
+
+static int
+parse_flags_compact(const char *str, uint32_t *var,
+ const struct flagnames_struct *flags, const char *flags_name)
+{
+ int i, j, found;
+
+ *var = 0;
+
+ for (i = 0;; i++) {
+ if (str[i] == '\0')
+ return (0);
+
+ /* Ignore minus signs. */
+ if (str[i] == '-')
+ continue;
+
+ found = 0;
+
+ for (j = 0; flags[j].name != NULL; j++) {
+ if (flags[j].letter == str[i]) {
+ *var |= flags[j].flag;
+ found = 1;
+ break;
+ }
+ }
+
+ if (!found) {
+ warnx("malformed ACL: \"%s\" field contains "
+ "invalid flag \"%c\"", flags_name, str[i]);
+ return (-1);
+ }
+ }
+}
+
+int
+_nfs4_format_flags(char *str, size_t size, acl_flag_t var, int verbose)
+{
+
+ if (verbose)
+ return (format_flags_verbose(str, size, var, a_flags));
+
+ return (format_flags_compact(str, size, var, a_flags));
+}
+
+int
+_nfs4_format_access_mask(char *str, size_t size, acl_perm_t var, int verbose)
+{
+
+ if (verbose)
+ return (format_flags_verbose(str, size, var, a_access_masks));
+
+ return (format_flags_compact(str, size, var, a_access_masks));
+}
+
+int
+_nfs4_parse_flags(const char *str, acl_flag_t *flags)
+{
+ int error, try_compact;
+ int tmpflags;
+
+ error = parse_flags_verbose(str, &tmpflags, a_flags, "flags", &try_compact);
+ if (error && try_compact)
+ error = parse_flags_compact(str, &tmpflags, a_flags, "flags");
+
+ *flags = tmpflags;
+
+ return (error);
+}
+
+int
+_nfs4_parse_access_mask(const char *str, acl_perm_t *perms)
+{
+ int error, try_compact;
+ int tmpperms;
+
+ error = parse_flags_verbose(str, &tmpperms, a_access_masks,
+ "access permissions", &try_compact);
+ if (error && try_compact)
+ error = parse_flags_compact(str, &tmpperms,
+ a_access_masks, "access permissions");
+
+ *perms = tmpperms;
+
+ return (error);
+}
diff --git a/lib/libc/posix1e/acl_to_text.3 b/lib/libc/posix1e/acl_to_text.3
new file mode 100644
index 0000000..08fec20
--- /dev/null
+++ b/lib/libc/posix1e/acl_to_text.3
@@ -0,0 +1,158 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 25, 2009
+.Dt ACL_TO_TEXT 3
+.Os
+.Sh NAME
+.Nm acl_to_text ,
+.Nm acl_to_text_np
+.Nd convert an ACL to text
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft char *
+.Fn acl_to_text "acl_t acl" "ssize_t *len_p"
+.Ft char *
+.Fn acl_to_text_np "acl_t acl" "ssize_t *len_p" "int flags"
+.Sh DESCRIPTION
+The
+.Fn acl_to_text
+and
+.Fn acl_to_text_np
+functions translate the ACL pointed to by argument
+.Va acl
+into a NULL terminated character string.
+If the pointer
+.Va len_p
+is not NULL, then the function shall return the length of the string (not
+including the NULL terminator) in the location pointed to by
+.Va len_p .
+If the ACL is POSIX.1e, the format of the text string returned by
+.Fn acl_to_text
+shall be the POSIX.1e long ACL form. If the ACL is NFSv4, the format
+of the text string shall be the compact form, unless the
+.Va ACL_TEXT_VERBOSE
+flag is given.
+.Pp
+The flags specified are formed by
+.Em or Ns 'ing
+the following values
+.Bl -column -offset 3n "ACL_TEXT_NUMERIC_IDS"
+.It ACL_TEXT_VERBOSE Ta "Format ACL using verbose form"
+.It ACL_TEXT_NUMERIC_IDS Ta "Do not resolve IDs into user or group names"
+.It ACL_TEXT_APPEND_ID Ta "In addition to user and group names, append numeric IDs"
+.El
+.Pp
+This function allocates any memory necessary to contain the string and
+returns a pointer to the string.
+The caller should free any releasable
+memory, when the new string is no longer required, by calling
+.Xr acl_free 3
+with the
+.Va (void*)char
+as an argument.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+Upon successful completion, the function shall return a pointer to the
+long text form of an ACL.
+Otherwise, a value of
+.Va (char*)NULL
+shall be returned and
+.Va errno
+shall be set to indicate the error.
+.Sh ERRORS
+If any of the following conditions occur, the
+.Fn acl_to_text
+function shall return a value of
+.Va (acl_t)NULL
+and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Argument
+.Va acl
+does not point to a valid ACL.
+.Pp
+The ACL denoted by
+.Va acl
+contains one or more improperly formed ACL entries, or for some other
+reason cannot be translated into a text form of an ACL.
+.It Bq Er ENOMEM
+The character string to be returned requires more memory than is allowed
+by the hardware or software-imposed memory management constraints.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_free 3 ,
+.Xr acl_from_text 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
+.Sh BUGS
+The
+.Fn acl_from_text
+and
+.Fn acl_to_text
+functions
+rely on the
+.Xr getpwent 3
+library calls to manage username and uid mapping, as well as the
+.Xr getgrent 3
+library calls to manage groupname and gid mapping.
+These calls are not
+thread safe, and so transitively, neither are
+.Fn acl_from_text
+and
+.Fn acl_to_text .
+These functions may also interfere with stateful
+calls associated with the
+.Fn getpwent
+and
+.Fn getgrent
+calls.
diff --git a/lib/libc/posix1e/acl_to_text.c b/lib/libc/posix1e/acl_to_text.c
new file mode 100644
index 0000000..e5fd1f7
--- /dev/null
+++ b/lib/libc/posix1e/acl_to_text.c
@@ -0,0 +1,261 @@
+/*-
+ * Copyright (c) 1999-2002 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * acl_to_text - return a text string with a text representation of the acl
+ * in it.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+#include <sys/errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "acl_support.h"
+
+/*
+ * acl_to_text - generate a text form of an acl
+ * spec says nothing about output ordering, so leave in acl order
+ *
+ * This function will not produce nice results if it is called with
+ * a non-POSIX.1e semantics ACL.
+ */
+
+char *_nfs4_acl_to_text_np(const acl_t acl, ssize_t *len_p, int flags);
+
+static char *
+_posix1e_acl_to_text(acl_t acl, ssize_t *len_p, int flags)
+{
+ struct acl *acl_int;
+ char *buf, *tmpbuf;
+ char name_buf[MAXLOGNAME];
+ char perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1],
+ effective_perm_buf[_POSIX1E_ACL_STRING_PERM_MAXSIZE+1];
+ int i, error, len;
+ uid_t ae_id;
+ acl_tag_t ae_tag;
+ acl_perm_t ae_perm, effective_perm, mask_perm;
+
+ buf = strdup("");
+ if (buf == NULL)
+ return(NULL);
+
+ acl_int = &acl->ats_acl;
+
+ mask_perm = ACL_PERM_BITS; /* effective is regular if no mask */
+ for (i = 0; i < acl_int->acl_cnt; i++)
+ if (acl_int->acl_entry[i].ae_tag == ACL_MASK)
+ mask_perm = acl_int->acl_entry[i].ae_perm;
+
+ for (i = 0; i < acl_int->acl_cnt; i++) {
+ ae_tag = acl_int->acl_entry[i].ae_tag;
+ ae_id = acl_int->acl_entry[i].ae_id;
+ ae_perm = acl_int->acl_entry[i].ae_perm;
+
+ switch(ae_tag) {
+ case ACL_USER_OBJ:
+ error = _posix1e_acl_perm_to_string(ae_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
+ if (error)
+ goto error_label;
+ len = asprintf(&tmpbuf, "%suser::%s\n", buf,
+ perm_buf);
+ if (len == -1)
+ goto error_label;
+ free(buf);
+ buf = tmpbuf;
+ break;
+
+ case ACL_USER:
+ error = _posix1e_acl_perm_to_string(ae_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
+ if (error)
+ goto error_label;
+
+ error = _posix1e_acl_id_to_name(ae_tag, ae_id,
+ MAXLOGNAME, name_buf, flags);
+ if (error)
+ goto error_label;
+
+ effective_perm = ae_perm & mask_perm;
+ if (effective_perm != ae_perm) {
+ error = _posix1e_acl_perm_to_string(
+ effective_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1,
+ effective_perm_buf);
+ if (error)
+ goto error_label;
+ len = asprintf(&tmpbuf, "%suser:%s:%s\t\t# "
+ "effective: %s\n",
+ buf, name_buf, perm_buf,
+ effective_perm_buf);
+ } else {
+ len = asprintf(&tmpbuf, "%suser:%s:%s\n", buf,
+ name_buf, perm_buf);
+ }
+ if (len == -1)
+ goto error_label;
+ free(buf);
+ buf = tmpbuf;
+ break;
+
+ case ACL_GROUP_OBJ:
+ error = _posix1e_acl_perm_to_string(ae_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
+ if (error)
+ goto error_label;
+
+ effective_perm = ae_perm & mask_perm;
+ if (effective_perm != ae_perm) {
+ error = _posix1e_acl_perm_to_string(
+ effective_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1,
+ effective_perm_buf);
+ if (error)
+ goto error_label;
+ len = asprintf(&tmpbuf, "%sgroup::%s\t\t# "
+ "effective: %s\n",
+ buf, perm_buf, effective_perm_buf);
+ } else {
+ len = asprintf(&tmpbuf, "%sgroup::%s\n", buf,
+ perm_buf);
+ }
+ if (len == -1)
+ goto error_label;
+ free(buf);
+ buf = tmpbuf;
+ break;
+
+ case ACL_GROUP:
+ error = _posix1e_acl_perm_to_string(ae_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
+ if (error)
+ goto error_label;
+
+ error = _posix1e_acl_id_to_name(ae_tag, ae_id,
+ MAXLOGNAME, name_buf, flags);
+ if (error)
+ goto error_label;
+
+ effective_perm = ae_perm & mask_perm;
+ if (effective_perm != ae_perm) {
+ error = _posix1e_acl_perm_to_string(
+ effective_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1,
+ effective_perm_buf);
+ if (error)
+ goto error_label;
+ len = asprintf(&tmpbuf, "%sgroup:%s:%s\t\t# "
+ "effective: %s\n",
+ buf, name_buf, perm_buf,
+ effective_perm_buf);
+ } else {
+ len = asprintf(&tmpbuf, "%sgroup:%s:%s\n", buf,
+ name_buf, perm_buf);
+ }
+ if (len == -1)
+ goto error_label;
+ free(buf);
+ buf = tmpbuf;
+ break;
+
+ case ACL_MASK:
+ error = _posix1e_acl_perm_to_string(ae_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
+ if (error)
+ goto error_label;
+
+ len = asprintf(&tmpbuf, "%smask::%s\n", buf,
+ perm_buf);
+ if (len == -1)
+ goto error_label;
+ free(buf);
+ buf = tmpbuf;
+ break;
+
+ case ACL_OTHER:
+ error = _posix1e_acl_perm_to_string(ae_perm,
+ _POSIX1E_ACL_STRING_PERM_MAXSIZE+1, perm_buf);
+ if (error)
+ goto error_label;
+
+ len = asprintf(&tmpbuf, "%sother::%s\n", buf,
+ perm_buf);
+ if (len == -1)
+ goto error_label;
+ free(buf);
+ buf = tmpbuf;
+ break;
+
+ default:
+ errno = EINVAL;
+ goto error_label;
+ }
+ }
+
+ if (len_p) {
+ *len_p = strlen(buf);
+ }
+ return (buf);
+
+error_label:
+ /* jump to here sets errno already, we just clean up */
+ if (buf) free(buf);
+ return (NULL);
+}
+
+char *
+acl_to_text_np(acl_t acl, ssize_t *len_p, int flags)
+{
+
+ if (acl == NULL) {
+ errno = EINVAL;
+ return(NULL);
+ }
+
+ switch (_acl_brand(acl)) {
+ case ACL_BRAND_POSIX:
+ return (_posix1e_acl_to_text(acl, len_p, flags));
+ case ACL_BRAND_NFS4:
+ return (_nfs4_acl_to_text_np(acl, len_p, flags));
+ default:
+ errno = EINVAL;
+ return (NULL);
+ }
+}
+
+char *
+acl_to_text(acl_t acl, ssize_t *len_p)
+{
+
+ return (acl_to_text_np(acl, len_p, 0));
+}
diff --git a/lib/libc/posix1e/acl_to_text_nfs4.c b/lib/libc/posix1e/acl_to_text_nfs4.c
new file mode 100644
index 0000000..f9945ab
--- /dev/null
+++ b/lib/libc/posix1e/acl_to_text_nfs4.c
@@ -0,0 +1,264 @@
+/*-
+ * Copyright (c) 2008, 2009 Edward Tomasz Napierała <trasz@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <assert.h>
+#include <string.h>
+#include <pwd.h>
+#include <grp.h>
+#include <sys/syscall.h>
+#include <sys/types.h>
+#include <sys/acl.h>
+
+#include "acl_support.h"
+
+#define MAX_ENTRY_LENGTH 512
+
+static int
+format_who(char *str, size_t size, const acl_entry_t entry, int numeric)
+{
+ int error;
+ acl_tag_t tag;
+ struct passwd *pwd;
+ struct group *grp;
+ uid_t *id;
+
+ error = acl_get_tag_type(entry, &tag);
+ if (error)
+ return (error);
+
+ switch (tag) {
+ case ACL_USER_OBJ:
+ snprintf(str, size, "owner@");
+ break;
+
+ case ACL_USER:
+ id = (uid_t *)acl_get_qualifier(entry);
+ if (id == NULL)
+ return (-1);
+ /* XXX: Thread-unsafe. */
+ if (!numeric)
+ pwd = getpwuid(*id);
+ else
+ pwd = NULL;
+ if (pwd == NULL)
+ snprintf(str, size, "user:%d", (unsigned int)*id);
+ else
+ snprintf(str, size, "user:%s", pwd->pw_name);
+ break;
+
+ case ACL_GROUP_OBJ:
+ snprintf(str, size, "group@");
+ break;
+
+ case ACL_GROUP:
+ id = (uid_t *)acl_get_qualifier(entry);
+ if (id == NULL)
+ return (-1);
+ /* XXX: Thread-unsafe. */
+ if (!numeric)
+ grp = getgrgid(*id);
+ else
+ grp = NULL;
+ if (grp == NULL)
+ snprintf(str, size, "group:%d", (unsigned int)*id);
+ else
+ snprintf(str, size, "group:%s", grp->gr_name);
+ break;
+
+ case ACL_EVERYONE:
+ snprintf(str, size, "everyone@");
+ break;
+
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+format_entry_type(char *str, size_t size, const acl_entry_t entry)
+{
+ int error;
+ acl_entry_type_t entry_type;
+
+ error = acl_get_entry_type_np(entry, &entry_type);
+ if (error)
+ return (error);
+
+ switch (entry_type) {
+ case ACL_ENTRY_TYPE_ALLOW:
+ snprintf(str, size, "allow");
+ break;
+ case ACL_ENTRY_TYPE_DENY:
+ snprintf(str, size, "deny");
+ break;
+ case ACL_ENTRY_TYPE_AUDIT:
+ snprintf(str, size, "audit");
+ break;
+ case ACL_ENTRY_TYPE_ALARM:
+ snprintf(str, size, "alarm");
+ break;
+ default:
+ return (-1);
+ }
+
+ return (0);
+}
+
+static int
+format_additional_id(char *str, size_t size, const acl_entry_t entry)
+{
+ int error;
+ acl_tag_t tag;
+ uid_t *id;
+
+ error = acl_get_tag_type(entry, &tag);
+ if (error)
+ return (error);
+
+ switch (tag) {
+ case ACL_USER_OBJ:
+ case ACL_GROUP_OBJ:
+ case ACL_EVERYONE:
+ str[0] = '\0';
+ break;
+
+ default:
+ id = (uid_t *)acl_get_qualifier(entry);
+ if (id == NULL)
+ return (-1);
+ snprintf(str, size, ":%d", (unsigned int)*id);
+ }
+
+ return (0);
+}
+
+static int
+format_entry(char *str, size_t size, const acl_entry_t entry, int flags)
+{
+ size_t off = 0, min_who_field_length = 18;
+ acl_permset_t permset;
+ acl_flagset_t flagset;
+ int error, len;
+ char buf[MAX_ENTRY_LENGTH + 1];
+
+ assert(_entry_brand(entry) == ACL_BRAND_NFS4);
+
+ error = acl_get_flagset_np(entry, &flagset);
+ if (error)
+ return (error);
+
+ error = acl_get_permset(entry, &permset);
+ if (error)
+ return (error);
+
+ error = format_who(buf, sizeof(buf), entry,
+ flags & ACL_TEXT_NUMERIC_IDS);
+ if (error)
+ return (error);
+ len = strlen(buf);
+ if (len < min_who_field_length)
+ len = min_who_field_length;
+ off += snprintf(str + off, size - off, "%*s:", len, buf);
+
+ error = _nfs4_format_access_mask(buf, sizeof(buf), *permset,
+ flags & ACL_TEXT_VERBOSE);
+ if (error)
+ return (error);
+ off += snprintf(str + off, size - off, "%s:", buf);
+
+ error = _nfs4_format_flags(buf, sizeof(buf), *flagset,
+ flags & ACL_TEXT_VERBOSE);
+ if (error)
+ return (error);
+ off += snprintf(str + off, size - off, "%s:", buf);
+
+ error = format_entry_type(buf, sizeof(buf), entry);
+ if (error)
+ return (error);
+ off += snprintf(str + off, size - off, "%s", buf);
+
+ if (flags & ACL_TEXT_APPEND_ID) {
+ error = format_additional_id(buf, sizeof(buf), entry);
+ if (error)
+ return (error);
+ off += snprintf(str + off, size - off, "%s", buf);
+ }
+
+ off += snprintf(str + off, size - off, "\n");
+
+ /* Make sure we didn't truncate anything. */
+ assert (off < size);
+
+ return (0);
+}
+
+char *
+_nfs4_acl_to_text_np(const acl_t aclp, ssize_t *len_p, int flags)
+{
+ int error, off = 0, size, entry_id = ACL_FIRST_ENTRY;
+ char *str;
+ acl_entry_t entry;
+
+ if (aclp->ats_acl.acl_cnt == 0)
+ return strdup("");
+
+ size = aclp->ats_acl.acl_cnt * MAX_ENTRY_LENGTH;
+ str = malloc(size);
+ if (str == NULL)
+ return (NULL);
+
+ while (acl_get_entry(aclp, entry_id, &entry) == 1) {
+ entry_id = ACL_NEXT_ENTRY;
+
+ assert(off < size);
+
+ error = format_entry(str + off, size - off, entry, flags);
+ if (error) {
+ free(str);
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ off = strlen(str);
+ }
+
+ assert(off < size);
+ str[off] = '\0';
+
+ if (len_p != NULL)
+ *len_p = off;
+
+ return (str);
+}
diff --git a/lib/libc/posix1e/acl_valid.3 b/lib/libc/posix1e/acl_valid.3
new file mode 100644
index 0000000..83f7746
--- /dev/null
+++ b/lib/libc/posix1e/acl_valid.3
@@ -0,0 +1,170 @@
+.\"-
+.\" Copyright (c) 2000, 2002 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed by Robert Watson for the TrustedBSD Project.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 29, 2002
+.Dt ACL_VALID 3
+.Os
+.Sh NAME
+.Nm acl_valid ,
+.Nm acl_valid_fd_np ,
+.Nm acl_valid_file_np ,
+.Nm acl_valid_link_np
+.Nd validate an ACL
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.Ft int
+.Fn acl_valid "acl_t acl"
+.Ft int
+.Fn acl_valid_fd_np "int fd" "acl_type_t type" "acl_t acl"
+.Ft int
+.Fn acl_valid_file_np "const char *path_p" "acl_type_t type" "acl_t acl"
+.Ft int
+.Fn acl_valid_link_np "const char *path_p" "acl_type_t type" "acl_t acl"
+.Sh DESCRIPTION
+These functions check that the ACL referred to by the argument
+.Va acl
+is valid.
+The POSIX.1e routine,
+.Fn acl_valid ,
+checks this validity only with POSIX.1e ACL semantics, and irrespective
+of the context in which the ACL is to be used.
+The non-portable forms,
+.Fn acl_valid_fd_np ,
+.Fn acl_valid_file_np ,
+and
+.Fn acl_valid_link_np
+allow an ACL to be checked in the context of a specific acl type,
+.Va type ,
+and file system object.
+In environments where additional ACL types are
+supported than just POSIX.1e, this makes more sense.
+Whereas
+.Fn acl_valid_file_np
+will follow the symlink if the specified path is to a symlink,
+.Fn acl_valid_link_np
+will not.
+.Pp
+For POSIX.1e semantics, the checks include:
+.Bl -bullet
+.It
+The three required entries
+.Dv ( ACL_USER_OBJ , ACL_GROUP_OBJ ,
+and
+.Dv ACL_OTHER )
+shall exist exactly once in the ACL.
+If the ACL contains any
+.Dv ACL_USER , ACL_GROUP ,
+or any other
+implementation-defined entries in the file group class
+then one
+.Dv ACL_MASK
+entry shall also be required.
+The ACL shall contain at most one
+.Dv ACL_MASK
+entry.
+.It
+The qualifier field shall be unique among all entries of
+the same POSIX.1e ACL facility defined tag type.
+The
+tag type field shall contain valid values including any
+implementation-defined values.
+Validation of the values
+of the qualifier field is implementation-defined.
+.El
+.Pp
+The POSIX.1e
+.Fn acl_valid
+function may reorder the ACL for the purposes of verification; the
+non-portable validation functions will not.
+.Sh IMPLEMENTATION NOTES
+.Fx Ns 's
+support for POSIX.1e interfaces and features is still under
+development at this time.
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+If any of the following conditions occur, these functions shall return
+-1 and set
+.Va errno
+to the corresponding value:
+.Bl -tag -width Er
+.It Bq Er EACCES
+Search permission is denied for a component of the path prefix, or the
+object exists and the process does not have appropriate access rights.
+.It Bq Er EBADF
+The
+.Va fd
+argument is not a valid file descriptor.
+.It Bq Er EINVAL
+Argument
+.Va acl
+does not point to a valid ACL.
+.Pp
+One or more of the required ACL entries is not present in
+.Va acl .
+.Pp
+The ACL contains entries that are not unique.
+.Pp
+The file system rejects the ACL based on fs-specific semantics issues.
+.It Bq Er ENAMETOOLONG
+A component of a pathname exceeded 255 characters, or an
+entire path name exceeded 1023 characters.
+.It Bq Er ENOENT
+The named object does not exist, or the
+.Va path_p
+argument points to an empty string.
+.It Bq Er ENOMEM
+Insufficient memory available to fulfill request.
+.It Bq Er EOPNOTSUPP
+The file system does not support ACL retrieval.
+.El
+.Sh SEE ALSO
+.Xr acl 3 ,
+.Xr acl_get 3 ,
+.Xr acl_init 3 ,
+.Xr acl_set 3 ,
+.Xr posix1e 3
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion
+of the draft continues on the cross-platform POSIX.1e implementation
+mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation
+page for more information.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ,
+and development continues.
+.Sh AUTHORS
+.An Robert N M Watson
diff --git a/lib/libc/posix1e/acl_valid.c b/lib/libc/posix1e/acl_valid.c
new file mode 100644
index 0000000..d4cb872
--- /dev/null
+++ b/lib/libc/posix1e/acl_valid.c
@@ -0,0 +1,124 @@
+/*-
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * acl_valid -- POSIX.1e ACL check routine
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include "namespace.h"
+#include <sys/acl.h>
+#include "un-namespace.h"
+#include <sys/errno.h>
+#include <stdlib.h>
+
+#include "acl_support.h"
+
+/*
+ * acl_valid: accepts an ACL, returns 0 on valid ACL, -1 for invalid,
+ * and errno set to EINVAL.
+ *
+ * Implemented by calling the acl_check routine in acl_support, which
+ * requires ordering. We call acl_support's _posix1e_acl_sort to make this
+ * true. POSIX.1e allows acl_valid() to reorder the ACL as it sees fit.
+ *
+ * This call is deprecated, as it doesn't ask whether the ACL is valid
+ * for a particular target. However, this call is standardized, unlike
+ * the other two forms.
+ */
+int
+acl_valid(acl_t acl)
+{
+ int error;
+
+ if (acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (!_acl_brand_may_be(acl, ACL_BRAND_POSIX)) {
+ errno = EINVAL;
+ return (-1);
+ }
+ _posix1e_acl_sort(acl);
+ error = _posix1e_acl_check(acl);
+ if (error) {
+ errno = error;
+ return (-1);
+ } else {
+ return (0);
+ }
+}
+
+int
+acl_valid_file_np(const char *pathp, acl_type_t type, acl_t acl)
+{
+
+ if (pathp == NULL || acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ type = _acl_type_unold(type);
+ if (_posix1e_acl(acl, type))
+ _posix1e_acl_sort(acl);
+
+ return (__acl_aclcheck_file(pathp, type, &acl->ats_acl));
+}
+
+int
+acl_valid_link_np(const char *pathp, acl_type_t type, acl_t acl)
+{
+
+ if (pathp == NULL || acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ type = _acl_type_unold(type);
+ if (_posix1e_acl(acl, type))
+ _posix1e_acl_sort(acl);
+
+ return (__acl_aclcheck_link(pathp, type, &acl->ats_acl));
+}
+
+int
+acl_valid_fd_np(int fd, acl_type_t type, acl_t acl)
+{
+
+ if (acl == NULL) {
+ errno = EINVAL;
+ return (-1);
+ }
+ type = _acl_type_unold(type);
+ if (_posix1e_acl(acl, type))
+ _posix1e_acl_sort(acl);
+
+ acl->ats_cur_entry = 0;
+
+ return (___acl_aclcheck_fd(fd, type, &acl->ats_acl));
+}
diff --git a/lib/libc/posix1e/extattr.3 b/lib/libc/posix1e/extattr.3
new file mode 100644
index 0000000..5e60686
--- /dev/null
+++ b/lib/libc/posix1e/extattr.3
@@ -0,0 +1,100 @@
+.\"
+.\" Copyright (c) 2001 Dima Dorfman <dd@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 24, 2001
+.Dt EXTATTR 3
+.Os
+.Sh NAME
+.Nm extattr_namespace_to_string ,
+.Nm extattr_string_to_namespace
+.Nd convert an extended attribute namespace identifier to a string and
+vice versa
+.Sh LIBRARY
+.Lb libutil
+.Sh SYNOPSIS
+.In sys/extattr.h
+.In libutil.h
+.Ft int
+.Fn extattr_namespace_to_string "int attrnamespace" "char **string"
+.Ft int
+.Fn extattr_string_to_namespace "const char *string" "int *attrnamespace"
+.Sh DESCRIPTION
+The
+.Fn extattr_namespace_to_string
+function converts a VFS extended attribute identifier to a human-readable
+string;
+the
+.Fn extattr_string_to_namespace
+function undoes the aforementioned operation,
+and converts a human-readable string representing a namespace to a
+namespace identifier.
+Although a file system may implement arbitrary namespaces,
+these functions only support the
+.Dv EXTATTR_NAMESPACE_USER
+.Pq Dq user
+and
+.Dv EXTATTR_NAMESPACE_SYSTEM
+.Pq Dq system
+namespaces,
+which are defined in
+.Xr extattr 9 .
+.Pp
+These functions are meant to be used in error reporting and other
+interactive tasks.
+For example,
+instead of printing the integer identifying an extended attribute in
+an error message,
+a program might use
+.Fn extattr_namespace_to_string
+to obtain a human-readable representation.
+Likewise,
+instead of requiring a user to enter the integer representing a namespace,
+an interactive program might ask for a name and use
+.Fn extattr_string_to_namespace
+to get the desired identifier.
+.Sh RETURN VALUES
+If any of the calls are unsuccessful, the value \-1 is returned
+and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The requested namespace could not be identified.
+.El
+.Sh SEE ALSO
+.Xr extattr 2 ,
+.Xr getextattr 8 ,
+.Xr setextattr 8 ,
+.Xr extattr 9
+.Sh HISTORY
+Extended attribute support was developed as part of the
+.Tn TrustedBSD
+Project, and introduced in
+.Fx 5.0 .
+It was developed to support security extensions requiring additional labels
+to be associated with each file or directory.
diff --git a/lib/libc/posix1e/extattr.c b/lib/libc/posix1e/extattr.c
new file mode 100644
index 0000000..5a9ddce
--- /dev/null
+++ b/lib/libc/posix1e/extattr.c
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 2001 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
+ * TrustedBSD: Utility functions for extended attributes.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/extattr.h>
+
+#include <errno.h>
+#include <libutil.h>
+#include <string.h>
+
+int
+extattr_namespace_to_string(int attrnamespace, char **string)
+{
+
+ switch(attrnamespace) {
+ case EXTATTR_NAMESPACE_USER:
+ if (string != NULL)
+ *string = strdup(EXTATTR_NAMESPACE_USER_STRING);
+ return (0);
+
+ case EXTATTR_NAMESPACE_SYSTEM:
+ if (string != NULL)
+ *string = strdup(EXTATTR_NAMESPACE_SYSTEM_STRING);
+ return (0);
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+}
+
+int
+extattr_string_to_namespace(const char *string, int *attrnamespace)
+{
+
+ if (!strcmp(string, EXTATTR_NAMESPACE_USER_STRING)) {
+ if (attrnamespace != NULL)
+ *attrnamespace = EXTATTR_NAMESPACE_USER;
+ return (0);
+ } else if (!strcmp(string, EXTATTR_NAMESPACE_SYSTEM_STRING)) {
+ if (attrnamespace != NULL)
+ *attrnamespace = EXTATTR_NAMESPACE_SYSTEM;
+ return (0);
+ } else {
+ errno = EINVAL;
+ return (-1);
+ }
+}
diff --git a/lib/libc/posix1e/mac.3 b/lib/libc/posix1e/mac.3
new file mode 100644
index 0000000..af162f8
--- /dev/null
+++ b/lib/libc/posix1e/mac.3
@@ -0,0 +1,176 @@
+.\" Copyright (c) 2001, 2003 Networks Associates Technology, Inc.
+.\" Copyright (c) 2009 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed for the FreeBSD Project by Chris
+.\" Costello at Safeport Network Services and Network Associates
+.\" Laboratories, the Security Research Division of Network Associates,
+.\" Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part
+.\" of the DARPA CHATS research program.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 7, 2009
+.Dt MAC 3
+.Os
+.Sh NAME
+.Nm mac
+.Nd introduction to the MAC security API
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/mac.h
+.Pp
+In the kernel configuration file:
+.Cd "options MAC"
+.Sh DESCRIPTION
+Mandatory Access Control labels describe confidentiality, integrity, and
+other security attributes of operating system objects, overriding
+discretionary access control.
+Not all system objects support MAC labeling, and MAC policies must be
+explicitly enabled by the administrator.
+This API, based on POSIX.1e, includes routines to retrieve, manipulate, set,
+and convert to and from text the MAC labels on files and processes.
+.Pp
+MAC labels consist of a set of (name, value) tuples, representing security
+attributes from MAC policies.
+For example, this label contains security labels defined by two policies,
+.Xr mac_biba 4
+and
+.Xr mac_mls 4 :
+.Bd -literal -offset indent
+biba/low,mls/low
+.Ed
+.Pp
+Further syntax and semantics of MAC labels may be found in
+.Xr maclabel 7 .
+.Pp
+Applications operate on labels stored in
+.Vt mac_t ,
+but can convert between this internal format and a text format for the
+purposes of presentation to uses or external storage.
+When querying a label on an object, a
+.Vt mac_t
+must first be prepared using the interfaces described in
+.Xr mac_prepare 3 ,
+allowing the application to declare which policies it wishes to interrogate.
+The application writer can also rely on default label names declared in
+.Xr mac.conf 5 .
+.Pp
+When finished with a
+.Vt mac_t ,
+the application must call
+.Xr mac_free 3
+to release its storage.
+.Pp
+The following functions are defined:
+.Bl -tag -width indent
+.It Fn mac_is_present
+This function, described in
+.Xr mac_is_present 3 ,
+allows applications to test whether MAC is configured, as well as whether
+specific policies are configured.
+.It Fn mac_get_fd , Fn mac_get_file , Fn mac_get_link , Fn mac_get_peer
+These functions, described in
+.Xr mac_get 3 ,
+retrieve the MAC labels associated with file descriptors, files, and socket
+peers.
+.It Fn mac_get_pid , Fn mac_get_proc
+These functions, described in
+.Xr mac_get 3 ,
+retrieve the MAC labels associated with processes.
+.It Fn mac_set_fd , Fn mac_set_file , Fn mac_set_link
+These functions, described in
+.Xr mac_set 3 ,
+set the MAC labels associated with file descriptors and files.
+.It Fn mac_set_proc
+This function, described in
+.Xr mac_set 3 ,
+sets the MAC label associated with the current process.
+.It Fn mac_free
+This function, described in
+.Xr mac_free 3 ,
+frees working MAC label storage.
+.It Fn mac_from_text
+This function, described in
+.Xr mac_text 3 ,
+converts a text-form MAC label into working MAC label storage,
+.Vt mac_t .
+.It Fn mac_prepare , Fn mac_prepare_file_label , Fn mac_prepare_ifnet_label , Fn mac_prepare_process_label , Fn mac_prepare_type
+These functions, described in
+.Xr mac_prepare 3 ,
+allocate working storage for MAC label operations.
+.Xr mac_prepare 3
+prepares a label based on caller-specified label names; the other calls
+rely on the default configuration specified in
+.Xr mac.conf 5 .
+.It Fn mac_to_text
+This function is described in
+.Xr mac_text 3 ,
+and may be used to convert a
+.Vt mac_t
+into a text-form MAC label.
+.El
+.Sh FILES
+.Bl -tag -width ".Pa /etc/mac.conf" -compact
+.It Pa /etc/mac.conf
+MAC library configuration file, documented in
+.Xr mac.conf 5 .
+Provides default behavior for applications aware of MAC labels on
+system objects, but without policy-specific knowledge.
+.El
+.Sh SEE ALSO
+.Xr mac_free 3 ,
+.Xr mac_get 3 ,
+.Xr mac_is_present 3 ,
+.Xr mac_prepare 3 ,
+.Xr mac_set 3 ,
+.Xr mac_text 3 ,
+.Xr posix1e 3 ,
+.Xr mac 4 ,
+.Xr mac.conf 5 ,
+.Xr mac 9
+.Sh STANDARDS
+These APIs are loosely based on the APIs described in POSIX.1e, as described
+in IEEE POSIX.1e draft 17.
+However, the resemblance of these APIs to the POSIX APIs is loose, as the
+POSIX APIs were unable to express some notions required for flexible and
+extensible access control.
+.Sh HISTORY
+Support for Mandatory Access Control was introduced in
+.Fx 5.0
+as part of the
+.Tn TrustedBSD
+Project.
+.Sh BUGS
+The
+.Tn TrustedBSD
+MAC Framework and associated policies, interfaces, and
+applications are considered to be an experimental feature in
+.Fx .
+Sites considering production deployment should keep the experimental
+status of these services in mind during any deployment process.
+See also
+.Xr mac 9
+for related considerations regarding the kernel framework.
diff --git a/lib/libc/posix1e/mac.c b/lib/libc/posix1e/mac.c
new file mode 100644
index 0000000..62a74ee
--- /dev/null
+++ b/lib/libc/posix1e/mac.c
@@ -0,0 +1,449 @@
+/*
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
+ * Copyright (c) 2002, 2003 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * This software was developed for the FreeBSD Project in part by Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
+ * as part of the DARPA CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <sys/sysctl.h>
+
+#include <dlfcn.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <sys/mac.h>
+
+static int internal_initialized;
+
+/*
+ * Maintain a list of default label preparations for various object
+ * types. Each name will appear only once in the list.
+ *
+ * XXXMAC: Not thread-safe.
+ */
+static LIST_HEAD(, label_default) label_default_head;
+struct label_default {
+ char *ld_name;
+ char *ld_labels;
+ LIST_ENTRY(label_default) ld_entries;
+};
+
+static void
+mac_destroy_labels(void)
+{
+ struct label_default *ld;
+
+ while ((ld = LIST_FIRST(&label_default_head))) {
+ free(ld->ld_name);
+ free(ld->ld_labels);
+ LIST_REMOVE(ld, ld_entries);
+ free(ld);
+ }
+}
+
+static void
+mac_destroy_internal(void)
+{
+
+ mac_destroy_labels();
+
+ internal_initialized = 0;
+}
+
+static int
+mac_add_type(const char *name, const char *labels)
+{
+ struct label_default *ld, *ld_new;
+ char *name_dup, *labels_dup;
+
+ /*
+ * Speculatively allocate all the memory now to avoid allocating
+ * later when we will someday hold a mutex.
+ */
+ name_dup = strdup(name);
+ if (name_dup == NULL) {
+ errno = ENOMEM;
+ return (-1);
+ }
+ labels_dup = strdup(labels);
+ if (labels_dup == NULL) {
+ free(name_dup);
+ errno = ENOMEM;
+ return (-1);
+ }
+ ld_new = malloc(sizeof(*ld));
+ if (ld_new == NULL) {
+ free(name_dup);
+ free(labels_dup);
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ /*
+ * If the type is already present, replace the current entry
+ * rather than add a new instance.
+ */
+ for (ld = LIST_FIRST(&label_default_head); ld != NULL;
+ ld = LIST_NEXT(ld, ld_entries)) {
+ if (strcmp(name, ld->ld_name) == 0)
+ break;
+ }
+
+ if (ld != NULL) {
+ free(ld->ld_labels);
+ ld->ld_labels = labels_dup;
+ labels_dup = NULL;
+ } else {
+ ld = ld_new;
+ ld->ld_name = name_dup;
+ ld->ld_labels = labels_dup;
+
+ ld_new = NULL;
+ name_dup = NULL;
+ labels_dup = NULL;
+
+ LIST_INSERT_HEAD(&label_default_head, ld, ld_entries);
+ }
+
+ if (name_dup != NULL)
+ free(name_dup);
+ if (labels_dup != NULL)
+ free(labels_dup);
+ if (ld_new != NULL)
+ free(ld_new);
+
+ return (0);
+}
+
+static char *
+next_token(char **string)
+{
+ char *token;
+
+ token = strsep(string, " \t");
+ while (token != NULL && *token == '\0')
+ token = strsep(string, " \t");
+
+ return (token);
+}
+
+static int
+mac_init_internal(int ignore_errors)
+{
+ const char *filename;
+ char line[LINE_MAX];
+ FILE *file;
+ int error;
+
+ error = 0;
+
+ LIST_INIT(&label_default_head);
+
+ if (!issetugid() && getenv("MAC_CONFFILE") != NULL)
+ filename = getenv("MAC_CONFFILE");
+ else
+ filename = MAC_CONFFILE;
+ file = fopen(filename, "r");
+ if (file == NULL)
+ return (0);
+
+ while (fgets(line, LINE_MAX, file)) {
+ char *comment, *parse, *statement;
+
+ if (line[strlen(line)-1] == '\n')
+ line[strlen(line)-1] = '\0';
+ else {
+ if (ignore_errors)
+ continue;
+ fclose(file);
+ error = EINVAL;
+ goto just_return;
+ }
+
+ /* Remove any comment. */
+ comment = line;
+ parse = strsep(&comment, "#");
+
+ /* Blank lines OK. */
+ statement = next_token(&parse);
+ if (statement == NULL)
+ continue;
+
+ if (strcmp(statement, "default_labels") == 0) {
+ char *name, *labels;
+
+ name = next_token(&parse);
+ labels = next_token(&parse);
+ if (name == NULL || labels == NULL ||
+ next_token(&parse) != NULL) {
+ if (ignore_errors)
+ continue;
+ error = EINVAL;
+ fclose(file);
+ goto just_return;
+ }
+
+ if (mac_add_type(name, labels) == -1) {
+ if (ignore_errors)
+ continue;
+ fclose(file);
+ goto just_return;
+ }
+ } else if (strcmp(statement, "default_ifnet_labels") == 0 ||
+ strcmp(statement, "default_file_labels") == 0 ||
+ strcmp(statement, "default_process_labels") == 0) {
+ char *labels, *type;
+
+ if (strcmp(statement, "default_ifnet_labels") == 0)
+ type = "ifnet";
+ else if (strcmp(statement, "default_file_labels") == 0)
+ type = "file";
+ else if (strcmp(statement, "default_process_labels") ==
+ 0)
+ type = "process";
+
+ labels = next_token(&parse);
+ if (labels == NULL || next_token(&parse) != NULL) {
+ if (ignore_errors)
+ continue;
+ error = EINVAL;
+ fclose(file);
+ goto just_return;
+ }
+
+ if (mac_add_type(type, labels) == -1) {
+ if (ignore_errors)
+ continue;
+ fclose(file);
+ goto just_return;
+ }
+ } else {
+ if (ignore_errors)
+ continue;
+ fclose(file);
+ error = EINVAL;
+ goto just_return;
+ }
+ }
+
+ fclose(file);
+
+ internal_initialized = 1;
+
+just_return:
+ if (error != 0)
+ mac_destroy_internal();
+ return (error);
+}
+
+static int
+mac_maybe_init_internal(void)
+{
+
+ if (!internal_initialized)
+ return (mac_init_internal(1));
+ else
+ return (0);
+}
+
+int
+mac_reload(void)
+{
+
+ if (internal_initialized)
+ mac_destroy_internal();
+ return (mac_init_internal(0));
+}
+
+int
+mac_free(struct mac *mac)
+{
+
+ if (mac->m_string != NULL)
+ free(mac->m_string);
+ free(mac);
+
+ return (0);
+}
+
+int
+mac_from_text(struct mac **mac, const char *text)
+{
+
+ *mac = (struct mac *) malloc(sizeof(**mac));
+ if (*mac == NULL)
+ return (ENOMEM);
+
+ (*mac)->m_string = strdup(text);
+ if ((*mac)->m_string == NULL) {
+ free(*mac);
+ *mac = NULL;
+ return (ENOMEM);
+ }
+
+ (*mac)->m_buflen = strlen((*mac)->m_string)+1;
+
+ return (0);
+}
+
+int
+mac_to_text(struct mac *mac, char **text)
+{
+
+ *text = strdup(mac->m_string);
+ if (*text == NULL)
+ return (ENOMEM);
+ return (0);
+}
+
+int
+mac_prepare(struct mac **mac, const char *elements)
+{
+
+ if (strlen(elements) >= MAC_MAX_LABEL_BUF_LEN)
+ return (EINVAL);
+
+ *mac = (struct mac *) malloc(sizeof(**mac));
+ if (*mac == NULL)
+ return (ENOMEM);
+
+ (*mac)->m_string = malloc(MAC_MAX_LABEL_BUF_LEN);
+ if ((*mac)->m_string == NULL) {
+ free(*mac);
+ *mac = NULL;
+ return (ENOMEM);
+ }
+
+ strcpy((*mac)->m_string, elements);
+ (*mac)->m_buflen = MAC_MAX_LABEL_BUF_LEN;
+
+ return (0);
+}
+
+int
+mac_prepare_type(struct mac **mac, const char *name)
+{
+ struct label_default *ld;
+ int error;
+
+ error = mac_maybe_init_internal();
+ if (error != 0)
+ return (error);
+
+ for (ld = LIST_FIRST(&label_default_head); ld != NULL;
+ ld = LIST_NEXT(ld, ld_entries)) {
+ if (strcmp(name, ld->ld_name) == 0)
+ return (mac_prepare(mac, ld->ld_labels));
+ }
+
+ errno = ENOENT;
+ return (-1); /* XXXMAC: ENOLABEL */
+}
+
+int
+mac_prepare_ifnet_label(struct mac **mac)
+{
+
+ return (mac_prepare_type(mac, "ifnet"));
+}
+
+int
+mac_prepare_file_label(struct mac **mac)
+{
+
+ return (mac_prepare_type(mac, "file"));
+}
+
+int
+mac_prepare_packet_label(struct mac **mac)
+{
+
+ return (mac_prepare_type(mac, "packet"));
+}
+
+int
+mac_prepare_process_label(struct mac **mac)
+{
+
+ return (mac_prepare_type(mac, "process"));
+}
+
+/*
+ * Simply test whether the TrustedBSD/MAC MIB tree is present; if so,
+ * return 1 to indicate that the system has MAC enabled overall or for
+ * a given policy.
+ */
+int
+mac_is_present(const char *policyname)
+{
+ int mib[5];
+ size_t siz;
+ char *mibname;
+ int error;
+
+ if (policyname != NULL) {
+ if (policyname[strcspn(policyname, ".=")] != '\0') {
+ errno = EINVAL;
+ return (-1);
+ }
+ mibname = malloc(sizeof("security.mac.") - 1 +
+ strlen(policyname) + sizeof(".enabled"));
+ if (mibname == NULL)
+ return (-1);
+ strcpy(mibname, "security.mac.");
+ strcat(mibname, policyname);
+ strcat(mibname, ".enabled");
+ siz = 5;
+ error = sysctlnametomib(mibname, mib, &siz);
+ free(mibname);
+ } else {
+ siz = 3;
+ error = sysctlnametomib("security.mac", mib, &siz);
+ }
+ if (error == -1) {
+ switch (errno) {
+ case ENOTDIR:
+ case ENOENT:
+ return (0);
+ default:
+ return (error);
+ }
+ }
+ return (1);
+}
diff --git a/lib/libc/posix1e/mac.conf.5 b/lib/libc/posix1e/mac.conf.5
new file mode 100644
index 0000000..a8dfba2
--- /dev/null
+++ b/lib/libc/posix1e/mac.conf.5
@@ -0,0 +1,123 @@
+.\" Copyright (c) 2003 Networks Associates Technology, Inc.
+.\" All rights reserved.
+.\"
+.\" This software was developed for the FreeBSD Project in part by Network
+.\" Associates Laboratories, the Security Research Division of Network
+.\" Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
+.\" as part of the DARPA CHATS research program.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd April 19, 2003
+.Dt MAC.CONF 5
+.Os
+.Sh NAME
+.Nm mac.conf
+.Nd format of the MAC library configuration file
+.Sh DESCRIPTION
+The
+.Nm
+file configures the default label elements to be used by policy-agnostic
+applications that operate on MAC labels.
+A file contains a series of default label sets specified by object class,
+in addition to blank lines and comments preceded by a
+.Ql #
+symbol.
+.Pp
+Currently, the implementation supports two syntax styles for label
+element declaration.
+The old (deprecated) syntax consists of a
+single line with two fields separated by white space: the object
+class name, and a list of label elements as used by the
+.Xr mac_prepare 3
+library calls prior to an application invocation of a function from
+.Xr mac_get 3 .
+.Pp
+The newer more preferred syntax consists of three fields separated by
+white space: the label group, object class name and a list of
+label elements.
+.Pp
+Label element names may optionally begin with a
+.Ql \&?
+symbol to indicate that a failure to retrieve the label element for
+an object should be silently ignored, and improves usability if the
+set of MAC policies may change over time.
+.Sh FILES
+.Bl -tag -width ".Pa /etc/mac.conf" -compact
+.It Pa /etc/mac.conf
+MAC library configuration file.
+.El
+.Sh EXAMPLES
+The following example configures user applications to operate with
+four MAC policies:
+.Xr mac_biba 4 ,
+.Xr mac_mls 4 ,
+SEBSD,
+and
+.Xr mac_partition 4 .
+.Bd -literal -offset indent
+#
+# Default label set to be used by simple MAC applications
+
+default_labels file ?biba,?lomac,?mls,?sebsd
+default_labels ifnet ?biba,?lomac,?mls,?sebsd
+default_labels process ?biba,?lomac,?mls,?partition,?sebsd
+default_labels socket ?biba,?lomac,?mls
+
+#
+# Deprecated (old) syntax
+
+default_file_labels ?biba,?mls,?sebsd
+default_ifnet_labels ?biba,?mls,?sebsd
+default_process_labels ?biba,?mls,partition,?sebsd
+.Ed
+.Pp
+In this example, userland applications will attempt to retrieve Biba,
+MLS, and SEBSD labels for all object classes; for processes, they will
+additionally attempt to retrieve a Partition identifier.
+In all cases except the Partition identifier, failure to retrieve a
+label due to the respective policy not being present will be ignored.
+.Sh SEE ALSO
+.Xr mac 3 ,
+.Xr mac_get 3 ,
+.Xr mac_prepare 3 ,
+.Xr mac 4 ,
+.Xr mac 9
+.Sh HISTORY
+Support for Mandatory Access Control was introduced in
+.Fx 5.0
+as part of the
+.Tn TrustedBSD
+Project.
+.Sh BUGS
+The
+.Tn TrustedBSD
+MAC Framework and associated policies, interfaces, and
+applications are considered to be an experimental feature in
+.Fx .
+Sites considering production deployment should keep the experimental
+status of these services in mind during any deployment process.
+See also
+.Xr mac 9
+for related considerations regarding the kernel framework.
diff --git a/lib/libc/posix1e/mac_exec.c b/lib/libc/posix1e/mac_exec.c
new file mode 100644
index 0000000..f57d1ce
--- /dev/null
+++ b/lib/libc/posix1e/mac_exec.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2002 Networks Associates Technology, Inc.
+ * All rights reserved.
+ *
+ * This software was developed for the FreeBSD Project in part by Network
+ * Associates Laboratories, the Security Research Division of Network
+ * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
+ * as part of the DARPA CHATS research program.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/mac.h>
+
+extern int __mac_execve(char *fname, char **argv, char **envv,
+ struct mac *mac_p);
+
+int
+mac_execve(char *fname, char **argv, char **envv, struct mac *label)
+{
+
+ return (__mac_execve(fname, argv, envv, label));
+}
diff --git a/lib/libc/posix1e/mac_free.3 b/lib/libc/posix1e/mac_free.3
new file mode 100644
index 0000000..78118a1
--- /dev/null
+++ b/lib/libc/posix1e/mac_free.3
@@ -0,0 +1,99 @@
+.\" Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
+.\" All rights reserved.
+.\"
+.\" This software was developed for the FreeBSD Project by Chris
+.\" Costello at Safeport Network Services and NAI Labs, the Security
+.\" Research Division of Network Associates, Inc. under DARPA/SPAWAR
+.\" contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+.\" research program.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. The name of the author may not be used to endorse or promote
+.\" products derived from this software without specific prior written
+.\" permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 21, 2001
+.Dt MAC_FREE 3
+.Os
+.Sh NAME
+.Nm mac_free
+.Nd free MAC label
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/mac.h
+.Ft int
+.Fn mac_free "mac_t label"
+.Sh DESCRIPTION
+The
+.Fn mac_free
+function frees the storage allocated to contain a
+.Vt mac_t .
+.Sh RETURN VALUES
+The
+.Fn mac_free
+function always returns 0.
+WARNING: see the notes in the
+.Sx BUGS
+section regarding the use of this
+function.
+.Sh SEE ALSO
+.Xr mac 3 ,
+.Xr mac_get 3 ,
+.Xr mac_prepare 3 ,
+.Xr mac_set 3 ,
+.Xr mac_text 3 ,
+.Xr posix1e 3 ,
+.Xr mac 4 ,
+.Xr mac 9
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion of the draft
+continues on the cross-platform POSIX.1e implementation mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation page
+for more information.
+.Sh HISTORY
+Support for Mandatory Access Control was introduced in
+.Fx 5.0
+as part of the
+.Tn TrustedBSD
+Project.
+.Sh BUGS
+POSIX.1e specifies that
+.Fn mac_free
+will be used to free text strings created using
+.Xr mac_to_text 3 .
+Because
+.Vt mac_t
+is a complex structure in the
+.Tn TrustedBSD
+implementation,
+.Fn mac_free
+is specific to
+.Vt mac_3 ,
+and must not be used to free the character strings returned from
+.Fn mac_to_text .
+Doing so may result in undefined behavior.
diff --git a/lib/libc/posix1e/mac_get.3 b/lib/libc/posix1e/mac_get.3
new file mode 100644
index 0000000..35fa72b
--- /dev/null
+++ b/lib/libc/posix1e/mac_get.3
@@ -0,0 +1,152 @@
+.\" Copyright (c) 2001, 2004 Networks Associates Technology, Inc.
+.\" All rights reserved.
+.\"
+.\" This software was developed for the FreeBSD Project by Chris
+.\" Costello at Safeport Network Services and NAI Labs, the Security
+.\" Research Division of Network Associates, Inc. under DARPA/SPAWAR
+.\" contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+.\" research program.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 21, 2001
+.Dt MAC_GET 3
+.Os
+.Sh NAME
+.Nm mac_get_file ,
+.Nm mac_get_link ,
+.Nm mac_get_fd ,
+.Nm mac_get_peer ,
+.Nm mac_get_pid ,
+.Nm mac_get_proc
+.Nd get the label of a file, socket, socket peer or process
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/mac.h
+.Ft int
+.Fn mac_get_file "const char *path" "mac_t label"
+.Ft int
+.Fn mac_get_link "const char *path" "mac_t label"
+.Ft int
+.Fn mac_get_fd "int fd" "mac_t label"
+.Ft int
+.Fn mac_get_peer "int fd" "mac_t label"
+.Ft int
+.Fn mac_get_pid "pid_t pid" "mac_t label"
+.Ft int
+.Fn mac_get_proc "mac_t label"
+.Sh DESCRIPTION
+The
+.Fn mac_get_file
+system call returns the label associated with a file specified by
+pathname.
+The
+.Fn mac_get_link
+function is the same as
+.Fn mac_get_file ,
+except that it does not follow symlinks.
+.Pp
+The
+.Fn mac_get_fd
+system call returns the label associated with an object referenced by
+the specified file descriptor.
+Note that in the case of a file system socket, the label returned will
+be the socket label, which may be different from the label of the
+on-disk node acting as a rendezvous for the socket.
+The
+.Fn mac_get_peer
+system call returns the label associated with the remote endpoint of
+a socket; the exact semantics of this call will depend on the protocol
+domain, communications type, and endpoint; typically this label will
+be cached when a connection-oriented protocol instance is first set up,
+and is undefined for datagram protocols.
+.Pp
+The
+.Fn mac_get_pid
+and
+.Fn mac_get_proc
+system calls return the process label associated with an arbitrary
+process ID, or the current process.
+.Pp
+Label storage for use with these calls must first be allocated and
+prepared using the
+.Xr mac_prepare 3
+functions.
+When an application is done using a label, the memory may be returned
+using
+.Xr mac_free 3 .
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EACCES
+A component of
+.Fa path
+is not searchable,
+or MAC read access to the file
+is denied.
+.It Bq Er EINVAL
+The requested label operation is not valid for the object referenced by
+.Fa fd .
+.It Bq Er ENAMETOOLONG
+The pathname pointed to by
+.Fa path
+exceeds
+.Dv PATH_MAX ,
+or a component of the pathname exceeds
+.Dv NAME_MAX .
+.It Bq Er ENOENT
+A component of
+.Fa path
+does not exist.
+.It Bq Er ENOMEM
+Insufficient memory is available
+to allocate a new MAC label structure.
+.It Bq Er ENOTDIR
+A component of
+.Fa path
+is not a directory.
+.El
+.Sh SEE ALSO
+.Xr mac 3 ,
+.Xr mac_free 3 ,
+.Xr mac_prepare 3 ,
+.Xr mac_set 3 ,
+.Xr mac_text 3 ,
+.Xr posix1e 3 ,
+.Xr mac 4 ,
+.Xr mac 9
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion of the draft
+continues on the cross-platform POSIX.1e implementation mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation page
+for more information.
+.Sh HISTORY
+Support for Mandatory Access Control was introduced in
+.Fx 5.0
+as part of the
+.Tn TrustedBSD
+Project.
diff --git a/lib/libc/posix1e/mac_get.c b/lib/libc/posix1e/mac_get.c
new file mode 100644
index 0000000..b641fc0
--- /dev/null
+++ b/lib/libc/posix1e/mac_get.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The names of the authors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/mac.h>
+#include <sys/socket.h>
+
+extern int __mac_get_fd(int fd, struct mac *mac_p);
+extern int __mac_get_file(const char *path_p, struct mac *mac_p);
+extern int __mac_get_link(const char *path_p, struct mac *mac_p);
+extern int __mac_get_pid(pid_t pid, struct mac *mac_p);
+extern int __mac_get_proc(struct mac *mac_p);
+
+int
+mac_get_fd(int fd, struct mac *label)
+{
+
+ return (__mac_get_fd(fd, label));
+}
+
+int
+mac_get_file(const char *path, struct mac *label)
+{
+
+ return (__mac_get_file(path, label));
+}
+
+int
+mac_get_link(const char *path, struct mac *label)
+{
+
+ return (__mac_get_link(path, label));
+}
+
+int
+mac_get_peer(int fd, struct mac *label)
+{
+ socklen_t len;
+
+ len = sizeof(*label);
+ return (getsockopt(fd, SOL_SOCKET, SO_PEERLABEL, label, &len));
+}
+
+int
+mac_get_pid(pid_t pid, struct mac *label)
+{
+
+ return (__mac_get_pid(pid, label));
+}
+
+int
+mac_get_proc(struct mac *label)
+{
+
+ return (__mac_get_proc(label));
+}
diff --git a/lib/libc/posix1e/mac_is_present.3 b/lib/libc/posix1e/mac_is_present.3
new file mode 100644
index 0000000..96d8cbf
--- /dev/null
+++ b/lib/libc/posix1e/mac_is_present.3
@@ -0,0 +1,87 @@
+.\" Copyright (c) 2002 Networks Associates Technology, Inc.
+.\" All rights reserved.
+.\"
+.\" This software was developed for the FreeBSD Project by Chris
+.\" Costello at Safeport Network Services and NAI Labs, the Security
+.\" Research Division of Network Associates, Inc. under DARPA/SPAWAR
+.\" contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+.\" research program.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 7, 2006
+.Dt MAC_IS_PRESENT 3
+.Os
+.Sh NAME
+.Nm mac_is_present
+.Nd report whether the running system has MAC support
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/mac.h
+.Ft int
+.Fn mac_is_present "const char *policyname"
+.Sh DESCRIPTION
+The
+.Fn mac_is_present
+function determines whether the currently-running kernel supports MAC for
+a given policy or not.
+If
+.Fa policyname
+is
+.Pf non- Dv NULL ,
+the presence of the named policy
+(e.g.\&
+.Dq Li biba ,
+.Dq Li mls ,
+.Dq Li te )
+is checked, otherwise the presence of any MAC policies at all is checked.
+.Sh RETURN VALUES
+If the system supports the given MAC policy, the value 1 is returned.
+If the specified MAC policy is not supported, the value 0 is returned.
+If an error occurs, the value \-1 is returned.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value of
+.Fa policyname
+is not valid.
+.It Bq Er ENOMEM
+Insufficient memory was available to allocate internal storage.
+.El
+.Sh SEE ALSO
+.Xr mac 3 ,
+.Xr mac_free 3 ,
+.Xr mac_get 3 ,
+.Xr mac_prepare 3 ,
+.Xr mac_set 3 ,
+.Xr mac_text 3 ,
+.Xr mac 4 ,
+.Xr mac 9
+.Sh HISTORY
+Support for Mandatory Access Control was introduced in
+.Fx 5.0
+as part of the
+.Tn TrustedBSD
+Project.
diff --git a/lib/libc/posix1e/mac_prepare.3 b/lib/libc/posix1e/mac_prepare.3
new file mode 100644
index 0000000..8e694de
--- /dev/null
+++ b/lib/libc/posix1e/mac_prepare.3
@@ -0,0 +1,126 @@
+.\" Copyright (c) 2002, 2003 Networks Associates Technology, Inc.
+.\" All rights reserved.
+.\"
+.\" This software was developed for the FreeBSD Project by Chris
+.\" Costello at Safeport Network Services and Network Associates Labs,
+.\" the Security Research Division of Network Associates, Inc. under
+.\" DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the
+.\" DARPA CHATS research program.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 22, 2003
+.Dt MAC_PREPARE 3
+.Os
+.Sh NAME
+.Nm mac_prepare , mac_prepare_type , mac_prepare_file_label ,
+.Nm mac_prepare_ifnet_label , mac_prepare_process_label
+.Nd allocate appropriate storage for
+.Vt mac_t
+.Sh SYNOPSIS
+.In sys/mac.h
+.Ft int
+.Fn mac_prepare "mac_t *mac" "const char *elements"
+.Ft int
+.Fn mac_prepare_type "mac_t *mac" "const char *name"
+.Ft int
+.Fn mac_prepare_file_label "mac_t *mac"
+.Ft int
+.Fn mac_prepare_ifnet_label "mac_t *mac"
+.Ft int
+.Fn mac_prepare_process_label "mac_t *mac"
+.Sh DESCRIPTION
+The
+.Nm
+family of functions allocates the appropriate amount of storage and initializes
+.Fa *mac
+for use by
+.Xr mac_get 3 .
+When the resulting label is passed into the
+.Xr mac_get 3
+functions, the kernel will attempt to fill in the label elements specified
+when the label was prepared.
+Elements are specified in a nul-terminated string, using commas to
+delimit fields.
+Element names may be prefixed with the
+.Dv ?
+character to indicate that a failure by the kernel to retrieve that
+element should not be considered fatal.
+.Pp
+The
+.Fn mac_prepare
+function accepts a list of policy names as a parameter, and allocates the
+storage to fit those label elements accordingly.
+The remaining functions in the family make use of system defaults defined
+in
+.Xr mac.conf 5
+instead of an explicit
+.Va elements
+argument, deriving the default from the specified object type.
+.Pp
+.Fn mac_prepare_type
+allocates the storage to fit an object label of the type specified by
+the
+.Va name
+argument.
+The
+.Fn mac_prepare_file_label ,
+.Fn mac_prepare_ifnet_label ,
+and
+.Fn mac_prepare_process_label
+functions are equivalent to invocations of
+.Fn mac_prepare_type
+with arguments of
+.Qq file ,
+.Qq ifnet ,
+and
+.Qq process
+respectively.
+.Sh RETURN VALUES
+.Rv -std
+.Sh SEE ALSO
+.Xr mac 3 ,
+.Xr mac_free 3 ,
+.Xr mac_get 3 ,
+.Xr mac_is_present 3 ,
+.Xr mac_set 3 ,
+.Xr mac 4 ,
+.Xr mac.conf 5 ,
+.Xr maclabel 7
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion of the draft
+continues on the cross-platform POSIX.1e implementation mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation page
+for more information.
+.Sh HISTORY
+Support for Mandatory Access Control was introduced in
+.Fx 5.0
+as part of the
+.Tn TrustedBSD
+Project.
+Support for generic object types first appeared in
+.Fx 5.2 .
diff --git a/lib/libc/posix1e/mac_set.3 b/lib/libc/posix1e/mac_set.3
new file mode 100644
index 0000000..0b245a0
--- /dev/null
+++ b/lib/libc/posix1e/mac_set.3
@@ -0,0 +1,149 @@
+.\" Copyright (c) 2001 Networks Associates Technology, Inc.
+.\" All rights reserved.
+.\"
+.\" This software was developed for the FreeBSD Project by Chris
+.\" Costello at Safeport Network Services and NAI Labs, the Security
+.\" Research Division of Network Associates, Inc. under DARPA/SPAWAR
+.\" contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+.\" research program.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 14, 2003
+.Dt MAC_SET 3
+.Os
+.Sh NAME
+.Nm mac_set_file ,
+.Nm mac_set_fd ,
+.Nm mac_set_proc
+.Nd set the MAC label for a file or process
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/mac.h
+.Ft int
+.Fn mac_set_file "const char *path" "mac_t label"
+.Ft int
+.Fn mac_set_link "const char *path" "mac_t label"
+.Ft int
+.Fn mac_set_fd "int fd" "mac_t label"
+.Ft int
+.Fn mac_set_proc "mac_t label"
+.Sh DESCRIPTION
+The
+.Fn mac_set_file
+and
+.Fn mac_set_fd
+functions associate a MAC label
+specified by
+.Fa label
+to the file referenced to by
+.Fa path_p ,
+or to the file descriptor
+.Fa fd ,
+respectively.
+Note that when a file descriptor references a socket, label operations
+on the file descriptor act on the socket, not on the file that may
+have been used as a rendezvous when binding the socket.
+The
+.Fn mac_set_link
+function is the same as
+.Fn mac_set_file ,
+except that it does not follow symlinks.
+.Pp
+The
+.Fn mac_set_proc
+function associates the MAC label
+specified by
+.Fa label
+to the calling process.
+.Pp
+A process is allowed to set a label for a file
+only if it has MAC write access to the file,
+and its effective user ID is equal to
+the owner of the file,
+or has appropriate privileges.
+.Sh RETURN VALUES
+.Rv -std mac_set_fd mac_set_file mac_set_link mac_set_proc
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EACCES
+MAC write access to the file is denied.
+.It Bq Er EBADF
+The
+.Fa fd
+argument
+is not a valid file descriptor.
+.It Bq Er EINVAL
+The
+.Fa label
+argument
+is not a valid MAC label, or the object referenced by
+.Fa fd
+is not appropriate for label operations.
+.It Bq Er EOPNOTSUPP
+Setting MAC labels is not supported
+by the file referenced by
+.Fa fd .
+.It Bq Er EPERM
+The calling process had insufficient privilege
+to change the MAC label.
+.It Bq Er EROFS
+File system for the object being modified
+is read only.
+.It Bq Er ENAMETOOLONG
+.\" XXX POSIX_NO_TRUNC?
+The length of the pathname in
+.Fa path_p
+exceeds
+.Dv PATH_MAX ,
+or a component of the pathname
+is longer than
+.Dv NAME_MAX .
+.It Bq Er ENOENT
+The file referenced by
+.Fa path_p
+does not exist.
+.It Bq Er ENOTDIR
+A component of the pathname
+referenced by
+.Fa path_p
+is not a directory.
+.El
+.Sh SEE ALSO
+.Xr mac 3 ,
+.Xr mac_free 3 ,
+.Xr mac_get 3 ,
+.Xr mac_is_present 3 ,
+.Xr mac_prepare 3 ,
+.Xr mac_text 3 ,
+.Xr posix1e 3 ,
+.Xr mac 4 ,
+.Xr mac 9
+.Sh HISTORY
+Support for Mandatory Access Control was introduced in
+.Fx 5.0
+as part of the
+.Tn TrustedBSD
+Project.
diff --git a/lib/libc/posix1e/mac_set.c b/lib/libc/posix1e/mac_set.c
new file mode 100644
index 0000000..c657f10
--- /dev/null
+++ b/lib/libc/posix1e/mac_set.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
+ * All rights reserved.
+ *
+ * This software was developed by Robert Watson for the TrustedBSD Project.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The names of the authors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/mac.h>
+
+extern int __mac_set_fd(int fd, struct mac *mac_p);
+extern int __mac_set_file(const char *path_p, struct mac *mac_p);
+extern int __mac_set_link(const char *path_p, struct mac *mac_p);
+extern int __mac_set_proc(struct mac *mac_p);
+
+int
+mac_set_fd(int fd, struct mac *label)
+{
+
+ return (__mac_set_fd(fd, label));
+}
+
+int
+mac_set_file(const char *path, struct mac *label)
+{
+
+ return (__mac_set_file(path, label));
+}
+
+int
+mac_set_link(const char *path, struct mac *label)
+{
+
+ return (__mac_set_link(path, label));
+}
+
+int
+mac_set_proc(struct mac *label)
+{
+
+ return (__mac_set_proc(label));
+}
diff --git a/lib/libc/posix1e/mac_text.3 b/lib/libc/posix1e/mac_text.3
new file mode 100644
index 0000000..dde6ccf
--- /dev/null
+++ b/lib/libc/posix1e/mac_text.3
@@ -0,0 +1,117 @@
+.\" Copyright (c) 2001 Networks Associates Technology, Inc.
+.\" All rights reserved.
+.\"
+.\" This software was developed for the FreeBSD Project by Chris
+.\" Costello at Safeport Network Services and NAI Labs, the Security
+.\" Research Division of Network Associates, Inc. under DARPA/SPAWAR
+.\" contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
+.\" research program.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 21, 2001
+.Dt MAC_TEXT 3
+.Os
+.Sh NAME
+.Nm mac_from_text ,
+.Nm mac_to_text
+.Nd convert MAC label to/from text representation
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/mac.h
+.Ft int
+.Fn mac_from_text "mac_t *mac" "const char *text"
+.Ft int
+.Fn mac_to_text "mac_t label" "char **text"
+.Sh DESCRIPTION
+The
+.Fn mac_from_text
+function converts the text representation of a label
+into the internal policy label format
+.Pq Vt mac_t
+and places it in
+.Fa *mac ,
+which must later be freed with
+.Xr free 3 .
+.Pp
+The
+.Fn mac_to_text
+function allocates storage for
+.Fa *text ,
+which will be set to the text representation of
+.Fa label .
+.Pp
+Refer to
+.Xr maclabel 7
+for the MAC label format.
+.Sh RETURN VALUES
+.Rv -std mac_from_text mac_to_text
+.Sh COMPATIBILITY
+POSIX.1e does not define
+a format for text representations
+of MAC labels.
+.Pp
+POSIX.1e requires that text strings allocated using
+.Fn mac_to_text
+be freed using
+.Xr mac_free 3 ;
+in the
+.Fx
+implementation, they must be freed using
+.Xr free 3 ,
+as
+.Xr mac_free 3
+is used only to free memory used for type
+.Vt mac_t .
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+Insufficient memory was available
+to allocate internal storage.
+.El
+.Sh SEE ALSO
+.Xr free 3 ,
+.Xr mac 3 ,
+.Xr mac_get 3 ,
+.Xr mac_is_present 3 ,
+.Xr mac_prepare 3 ,
+.Xr mac_set 3 ,
+.Xr posix1e 3 ,
+.Xr mac 4 ,
+.Xr maclabel 7
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+Discussion of the draft
+continues on the cross-platform POSIX.1e implementation mailing list.
+To join this list, see the
+.Fx
+POSIX.1e implementation page
+for more information.
+.Sh HISTORY
+Support for Mandatory Access Control was introduced in
+.Fx 5.0
+as part of the
+.Tn TrustedBSD
+Project.
diff --git a/lib/libc/posix1e/posix1e.3 b/lib/libc/posix1e/posix1e.3
new file mode 100644
index 0000000..84ce2ec
--- /dev/null
+++ b/lib/libc/posix1e/posix1e.3
@@ -0,0 +1,112 @@
+.\"-
+.\" Copyright (c) 2000, 2009 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 7, 2009
+.Dt POSIX1E 3
+.Os
+.Sh NAME
+.Nm posix1e
+.Nd introduction to the POSIX.1e security API
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/acl.h
+.In sys/mac.h
+.Sh DESCRIPTION
+POSIX.1e describes five security extensions to the POSIX.1 API: Access
+Control Lists (ACLs), Auditing, Capabilities, Mandatory Access Control, and
+Information Flow Labels.
+While IEEE POSIX.1e D17 specification has not been standardized, several of
+its interfaces are widely used.
+.Pp
+.Fx
+implements POSIX.1e interface for access control lists, described in
+.Xr acl 3 ,
+and supports ACLs on the
+.Xr ffs 7
+file system; ACLs must be administratively enabled using
+.Xr tunefs 8 .
+.Pp
+.Fx
+implements a POSIX.1e-like mandatory access control interface, described in
+.Xr mac 3 ,
+although with a number of extensions and important semantic differences.
+.Pp
+.Fx
+does not implement the POSIX.1e audit, privilege (capability), or information
+flow label APIs.
+However,
+.Fx
+does implement the
+.Xr libbsm
+audit API.
+.Sh ENVIRONMENT
+POSIX.1e assigns security attributes to all objects, extending the security
+functionality described in POSIX.1.
+These additional attributes store fine-grained discretionary access control
+information and mandatory access control labels; for files, they are stored
+in extended attributes, described in
+.Xr extattr 3 .
+.Pp
+POSIX.2c describes
+a set of userland utilities for manipulating these attributes, including
+.Xr getfacl 1
+and
+.Xr setfacl 1
+for access control lists, and
+.Xr getfmac 8
+and
+.Xr setfmac 8
+for mandatory access control labels.
+.Sh SEE ALSO
+.Xr getfacl 1 ,
+.Xr setfacl 1 ,
+.Xr extattr 2 ,
+.Xr acl 3 ,
+.Xr extattr 3 ,
+.Xr libbsm 3 ,
+.Xr mac 3 ,
+.Xr ffs 7 ,
+.Xr getfmac 8 ,
+.Xr setfmac 8 ,
+.Xr tunefs 8 ,
+.Xr acl 9 ,
+.Xr extattr 9 ,
+.Xr mac 9
+.Sh STANDARDS
+POSIX.1e is described in IEEE POSIX.1e draft 17.
+.Sh HISTORY
+POSIX.1e support was introduced in
+.Fx 4.0 ;
+most features were available as of
+.Fx 5.0 .
+.Sh AUTHORS
+.An Robert N M Watson
+.An Chris D. Faulhaber
+.An Thomas Moestl
+.An Ilmar S Habibulin
diff --git a/lib/libc/powerpc/Makefile.inc b/lib/libc/powerpc/Makefile.inc
new file mode 100644
index 0000000..453726a
--- /dev/null
+++ b/lib/libc/powerpc/Makefile.inc
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+# Long double is 64-bits
+MDSRCS+=machdep_ldisd.c
+SYM_MAPS+=${.CURDIR}/powerpc/Symbol.map
diff --git a/lib/libc/powerpc/SYS.h b/lib/libc/powerpc/SYS.h
new file mode 100644
index 0000000..0bd793f
--- /dev/null
+++ b/lib/libc/powerpc/SYS.h
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 2002 Benno Rice. All rights reserved.
+ * Copyright (c) 2002 David E. O'Brien. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $NetBSD: SYS.h,v 1.8 2002/01/14 00:55:56 thorpej Exp $
+ * $FreeBSD$
+ */
+
+#include <sys/syscall.h>
+#include <machine/asm.h>
+
+#define _SYSCALL(name) \
+ .text; \
+ .align 2; \
+ li 0,(__CONCAT(SYS_, name)); \
+ sc
+
+#define SYSCALL(name) \
+ .text; \
+ .align 2; \
+2: b PIC_PLT(CNAME(HIDENAME(cerror))); \
+ENTRY(__CONCAT(__sys_, name)); \
+ WEAK_REFERENCE(__CONCAT(__sys_, name), name); \
+ WEAK_REFERENCE(__CONCAT(__sys_, name), __CONCAT(_, name));\
+ _SYSCALL(name); \
+ bso 2b
+
+#define PSEUDO(name) \
+ .text; \
+ .align 2; \
+ENTRY(__CONCAT(__sys_, name)); \
+ WEAK_REFERENCE(__CONCAT(__sys_, name), __CONCAT(_, name));\
+ _SYSCALL(name); \
+ bnslr; \
+ b PIC_PLT(CNAME(HIDENAME(cerror)))
+
+#define RSYSCALL(name) \
+ .text; \
+ .align 2; \
+2: b PIC_PLT(CNAME(HIDENAME(cerror))); \
+ENTRY(__CONCAT(__sys_, name)); \
+ WEAK_REFERENCE(__CONCAT(__sys_, name), name); \
+ WEAK_REFERENCE(__CONCAT(__sys_, name), __CONCAT(_, name));\
+ _SYSCALL(name); \
+ bnslr; \
+ b PIC_PLT(CNAME(HIDENAME(cerror)))
diff --git a/lib/libc/powerpc/Symbol.map b/lib/libc/powerpc/Symbol.map
new file mode 100644
index 0000000..14b4811
--- /dev/null
+++ b/lib/libc/powerpc/Symbol.map
@@ -0,0 +1,58 @@
+/*
+ * $FreeBSD$
+ */
+
+/*
+ * This only needs to contain symbols that are not listed in
+ * symbol maps from other parts of libc (i.e., not found in
+ * stdlib/Symbol.map, string/Symbol.map, sys/Symbol.map, ...).
+ */
+FBSD_1.0 {
+ /* PSEUDO syscalls */
+ _exit;
+
+ _mcount;
+ _setjmp;
+ _longjmp;
+ fabs;
+ __flt_rounds;
+ fpgetmask;
+ fpgetround;
+ fpgetsticky;
+ fpsetmask;
+ fpsetround;
+ __infinity;
+ __nan;
+ makecontext;
+ setjmp;
+ longjmp;
+ sigsetjmp;
+ siglongjmp;
+ htonl;
+ htons;
+ ntohl;
+ ntohs;
+ brk;
+ exect;
+ sbrk;
+ vfork;
+};
+
+FBSDprivate_1.0 {
+ /* PSEUDO syscalls */
+ __sys_getlogin;
+ _getlogin;
+ __sys_exit;
+
+ _set_tp;
+ _fpgetsticky;
+ __makecontext;
+ __longjmp;
+ signalcontext;
+ __signalcontext;
+ __syncicache;
+ _end;
+ .curbrk;
+ .minbrk;
+ .cerror;
+};
diff --git a/lib/libc/powerpc/_fpmath.h b/lib/libc/powerpc/_fpmath.h
new file mode 100644
index 0000000..6d80eb4
--- /dev/null
+++ b/lib/libc/powerpc/_fpmath.h
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+union IEEEl2bits {
+ long double e;
+ struct {
+ unsigned int sign :1;
+ unsigned int exp :11;
+ unsigned int manh :20;
+ unsigned int manl :32;
+ } bits;
+};
+
+#define mask_nbit_l(u) ((void)0)
+#define LDBL_IMPLICIT_NBIT
+#define LDBL_NBIT 0
+
+#define LDBL_MANH_SIZE 20
+#define LDBL_MANL_SIZE 32
+
+#define LDBL_TO_ARRAY32(u, a) do { \
+ (a)[0] = (uint32_t)(u).bits.manl; \
+ (a)[1] = (uint32_t)(u).bits.manh; \
+} while(0)
diff --git a/lib/libc/powerpc/arith.h b/lib/libc/powerpc/arith.h
new file mode 100644
index 0000000..8e2c9ec
--- /dev/null
+++ b/lib/libc/powerpc/arith.h
@@ -0,0 +1,16 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * NOTE: The definitions in this file must be correct or strtod(3) and
+ * floating point formats in printf(3) will break! The file can be
+ * generated by running contrib/gdtoa/arithchk.c on the target
+ * architecture. See contrib/gdtoa/gdtoaimp.h for details.
+ */
+
+#define IEEE_MC68k
+#define Arith_Kind_ASL 2
+#define Double_Align
diff --git a/lib/libc/powerpc/gd_qnan.h b/lib/libc/powerpc/gd_qnan.h
new file mode 100644
index 0000000..d70d8c3
--- /dev/null
+++ b/lib/libc/powerpc/gd_qnan.h
@@ -0,0 +1,21 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * This file can be generated by compiling and running contrib/gdtoa/qnan.c
+ * on the target architecture after arith.h has been generated.
+ *
+ * $FreeBSD$
+ */
+
+#define f_QNAN 0x7fc00000
+#define d_QNAN0 0x7ff80000
+#define d_QNAN1 0x0
+#define ld_QNAN0 0x7ff80000
+#define ld_QNAN1 0x0
+#define ld_QNAN2 0x0
+#define ld_QNAN3 0x0
+#define ldus_QNAN0 0x7ff8
+#define ldus_QNAN1 0x0
+#define ldus_QNAN2 0x0
+#define ldus_QNAN3 0x0
+#define ldus_QNAN4 0x0
diff --git a/lib/libc/powerpc/gen/Makefile.inc b/lib/libc/powerpc/gen/Makefile.inc
new file mode 100644
index 0000000..79a2746
--- /dev/null
+++ b/lib/libc/powerpc/gen/Makefile.inc
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+SRCS += _ctx_start.S fabs.S flt_rounds.c fpgetmask.c fpgetround.c \
+ fpgetsticky.c fpsetmask.c fpsetround.c getcontextx.c \
+ infinity.c ldexp.c makecontext.c _setjmp.S \
+ setjmp.S sigsetjmp.S signalcontext.c syncicache.c \
+ _set_tp.c
+
+
diff --git a/lib/libc/powerpc/gen/_ctx_start.S b/lib/libc/powerpc/gen/_ctx_start.S
new file mode 100644
index 0000000..2d3cfcf
--- /dev/null
+++ b/lib/libc/powerpc/gen/_ctx_start.S
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2004 Suleiman Souhlal
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+ #include <machine/asm.h>
+
+ __FBSDID("$FreeBSD$");
+
+ .globl CNAME(_ctx_done)
+ .globl CNAME(abort)
+
+ ENTRY(_ctx_start)
+ mtlr %r14
+ blrl /* branch to start function */
+ mr %r3,%r15 /* pass pointer to ucontext as argument */
+ bl PIC_PLT(CNAME(_ctx_done)) /* branch to ctxt completion func */
+ /*
+ * we should never return from the
+ * above branch.
+ */
+ bl PIC_PLT(CNAME(abort)) /* abort */
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc/gen/_set_tp.c b/lib/libc/powerpc/gen/_set_tp.c
new file mode 100644
index 0000000..5a89698
--- /dev/null
+++ b/lib/libc/powerpc/gen/_set_tp.c
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+void
+_set_tp(void *tpval)
+{
+ register void *tp __asm__("r2");
+
+ __asm __volatile("mr %0,%1" : "=r"(tp) : "r"((char*)tpval + 0x7008));
+}
diff --git a/lib/libc/powerpc/gen/_setjmp.S b/lib/libc/powerpc/gen/_setjmp.S
new file mode 100644
index 0000000..bbf8644
--- /dev/null
+++ b/lib/libc/powerpc/gen/_setjmp.S
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: _setjmp.S,v 1.1 1997/03/29 20:55:53 thorpej Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * C library -- _setjmp, _longjmp
+ *
+ * _longjmp(a,v)
+ * will generate a "return(v?v:1)" from the last call to
+ * _setjmp(a)
+ * by restoring registers from the stack.
+ * The previous signal state is NOT restored.
+ *
+ * jmpbuf layout:
+ * +------------+
+ * | unused |
+ * +------------+
+ * | unused |
+ * | |
+ * | (4 words) |
+ * | |
+ * +------------+
+ * | saved regs |
+ * | ... |
+ */
+
+ENTRY(_setjmp)
+ mflr %r11
+ mfcr %r12
+ mr %r10,%r1
+ mr %r9,%r2
+ stmw %r9,20(%r3)
+ li %r3,0
+ blr
+
+ENTRY(_longjmp)
+ lmw %r9,20(%r3)
+ mtlr %r11
+ mtcr %r12
+ mr %r1,%r10
+ or. %r3,%r4,%r4
+ bnelr
+ li %r3,1
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc/gen/fabs.S b/lib/libc/powerpc/gen/fabs.S
new file mode 100644
index 0000000..7891012
--- /dev/null
+++ b/lib/libc/powerpc/gen/fabs.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2004 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * double fabs(double)
+ */
+ENTRY(fabs)
+ fabs %f1,%f1
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc/gen/flt_rounds.c b/lib/libc/powerpc/gen/flt_rounds.c
new file mode 100644
index 0000000..6294be7
--- /dev/null
+++ b/lib/libc/powerpc/gen/flt_rounds.c
@@ -0,0 +1,56 @@
+/* $NetBSD: flt_rounds.c,v 1.4.10.3 2002/03/22 20:41:53 nathanw Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <machine/float.h>
+
+#ifndef _SOFT_FLOAT
+static const int map[] = {
+ 1, /* round to nearest */
+ 0, /* round to zero */
+ 2, /* round to positive infinity */
+ 3 /* round to negative infinity */
+};
+
+int
+__flt_rounds()
+{
+ uint64_t fpscr;
+
+ __asm__ __volatile("mffs %0" : "=f"(fpscr));
+ return map[(fpscr & 0x03)];
+}
+#endif
diff --git a/lib/libc/powerpc/gen/fpgetmask.c b/lib/libc/powerpc/gen/fpgetmask.c
new file mode 100644
index 0000000..b67b1bc
--- /dev/null
+++ b/lib/libc/powerpc/gen/fpgetmask.c
@@ -0,0 +1,48 @@
+/* $NetBSD: fpgetmask.c,v 1.3 2002/01/13 21:45:47 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dan Winship.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <ieeefp.h>
+
+#ifndef _SOFT_FLOAT
+fp_except_t
+fpgetmask()
+{
+ u_int64_t fpscr;
+
+ __asm__("mffs %0" : "=f"(fpscr));
+ return ((fp_except_t)((fpscr >> 3) & 0x1f));
+}
+#endif
diff --git a/lib/libc/powerpc/gen/fpgetround.c b/lib/libc/powerpc/gen/fpgetround.c
new file mode 100644
index 0000000..097e82a
--- /dev/null
+++ b/lib/libc/powerpc/gen/fpgetround.c
@@ -0,0 +1,48 @@
+/* $NetBSD: fpgetround.c,v 1.3 2002/01/13 21:45:47 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dan Winship.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <ieeefp.h>
+
+#ifndef _SOFT_FLOAT
+fp_rnd_t
+fpgetround()
+{
+ u_int64_t fpscr;
+
+ __asm__("mffs %0" : "=f"(fpscr));
+ return ((fp_rnd_t)(fpscr & 0x3));
+}
+#endif
diff --git a/lib/libc/powerpc/gen/fpgetsticky.c b/lib/libc/powerpc/gen/fpgetsticky.c
new file mode 100644
index 0000000..57152ac
--- /dev/null
+++ b/lib/libc/powerpc/gen/fpgetsticky.c
@@ -0,0 +1,54 @@
+/* $NetBSD: fpgetsticky.c,v 1.3 2002/01/13 21:45:48 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dan Winship.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+
+#include "namespace.h"
+
+#include <sys/types.h>
+#include <ieeefp.h>
+
+#ifndef _SOFT_FLOAT
+#ifdef __weak_alias
+__weak_alias(fpgetsticky,_fpgetsticky)
+#endif
+
+fp_except_t
+fpgetsticky()
+{
+ u_int64_t fpscr;
+
+ __asm__ __volatile("mffs %0" : "=f"(fpscr));
+ return ((fp_except_t)((fpscr >> 25) & 0x1f));
+}
+#endif
diff --git a/lib/libc/powerpc/gen/fpsetmask.c b/lib/libc/powerpc/gen/fpsetmask.c
new file mode 100644
index 0000000..81cd19e
--- /dev/null
+++ b/lib/libc/powerpc/gen/fpsetmask.c
@@ -0,0 +1,52 @@
+/* $NetBSD: fpsetmask.c,v 1.3 2002/01/13 21:45:48 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dan Winship.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <ieeefp.h>
+
+#ifndef _SOFT_FLOAT
+fp_except_t
+fpsetmask(fp_except_t mask)
+{
+ u_int64_t fpscr;
+ fp_rnd_t old;
+
+ __asm__("mffs %0" : "=f"(fpscr));
+ old = (fp_rnd_t)((fpscr >> 3) & 0x1f);
+ fpscr = (fpscr & 0xffffff07) | (mask << 3);
+ __asm__ __volatile("mtfsf 0xff,%0" :: "f"(fpscr));
+ return (old);
+}
+#endif
diff --git a/lib/libc/powerpc/gen/fpsetround.c b/lib/libc/powerpc/gen/fpsetround.c
new file mode 100644
index 0000000..17f70a0
--- /dev/null
+++ b/lib/libc/powerpc/gen/fpsetround.c
@@ -0,0 +1,52 @@
+/* $NetBSD: fpsetround.c,v 1.3 2002/01/13 21:45:48 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dan Winship.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <ieeefp.h>
+
+#ifndef _SOFT_FLOAT
+fp_rnd_t
+fpsetround(fp_rnd_t rnd_dir)
+{
+ u_int64_t fpscr;
+ fp_rnd_t old;
+
+ __asm__ __volatile("mffs %0" : "=f"(fpscr));
+ old = (fp_rnd_t)(fpscr & 0x3);
+ fpscr = (fpscr & 0xfffffffc) | rnd_dir;
+ __asm__ __volatile("mtfsf 0xff,%0" :: "f"(fpscr));
+ return (old);
+}
+#endif
diff --git a/lib/libc/powerpc/gen/getcontextx.c b/lib/libc/powerpc/gen/getcontextx.c
new file mode 100644
index 0000000..307978a
--- /dev/null
+++ b/lib/libc/powerpc/gen/getcontextx.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int
+__getcontextx_size(void)
+{
+
+ return (sizeof(ucontext_t));
+}
+
+int
+__fillcontextx(char *ctx)
+{
+ ucontext_t *ucp;
+
+ ucp = (ucontext_t *)ctx;
+ return (getcontext(ucp));
+}
+
+__weak_reference(__getcontextx, getcontextx);
+
+ucontext_t *
+__getcontextx(void)
+{
+ char *ctx;
+ int error;
+
+ ctx = malloc(__getcontextx_size());
+ if (ctx == NULL)
+ return (NULL);
+ if (__fillcontextx(ctx) == -1) {
+ error = errno;
+ free(ctx);
+ errno = error;
+ return (NULL);
+ }
+ return ((ucontext_t *)ctx);
+}
diff --git a/lib/libc/powerpc/gen/infinity.c b/lib/libc/powerpc/gen/infinity.c
new file mode 100644
index 0000000..cf1695e
--- /dev/null
+++ b/lib/libc/powerpc/gen/infinity.c
@@ -0,0 +1,17 @@
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: infinity.c,v 1.2 1998/11/14 19:31:02 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+/* infinity.c */
+
+#include <math.h>
+
+/* bytes for +Infinity on powerpc */
+const union __infinity_un __infinity = { { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } };
+
+/* bytes for NaN */
+const union __nan_un __nan = { { 0xff, 0xc0, 0, 0 } };
diff --git a/lib/libc/powerpc/gen/makecontext.c b/lib/libc/powerpc/gen/makecontext.c
new file mode 100644
index 0000000..d66e824
--- /dev/null
+++ b/lib/libc/powerpc/gen/makecontext.c
@@ -0,0 +1,120 @@
+/*
+ * Copyright (c) 2004 Suleiman Souhlal
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ucontext.h>
+
+__weak_reference(__makecontext, makecontext);
+
+void _ctx_done(ucontext_t *ucp);
+void _ctx_start(void);
+
+void
+_ctx_done(ucontext_t *ucp)
+{
+ if (ucp->uc_link == NULL)
+ exit(0);
+ else {
+ /* invalidate context */
+ ucp->uc_mcontext.mc_len = 0;
+
+ setcontext((const ucontext_t *)ucp->uc_link);
+
+ abort(); /* should never return from above call */
+ }
+}
+
+void
+__makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...)
+{
+ mcontext_t *mc;
+ char *sp;
+ va_list ap;
+ int i, regargs, stackargs;
+
+ /* Sanity checks */
+ if ((ucp == NULL) || (argc < 0) || (argc > NCARGS)
+ || (ucp->uc_stack.ss_sp == NULL)
+ || (ucp->uc_stack.ss_size < MINSIGSTKSZ)) {
+ /* invalidate context */
+ ucp->uc_mcontext.mc_len = 0;
+ return;
+ }
+
+ /*
+ * The stack must have space for the frame pointer, saved
+ * link register, overflow arguments, and be 16-byte
+ * aligned.
+ */
+ stackargs = (argc > 8) ? argc - 8 : 0;
+ sp = (char *) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size
+ - sizeof(uint32_t)*(stackargs + 2);
+ sp = (char *)((uint32_t)sp & ~0x1f);
+
+ mc = &ucp->uc_mcontext;
+
+ /*
+ * Up to 8 register args. Assumes all args are 32-bit and
+ * integer only. Not sure how to cater for floating point,
+ * although 64-bit args will work if aligned correctly
+ * in the arg list.
+ */
+ regargs = (argc > 8) ? 8 : argc;
+ va_start(ap, argc);
+ for (i = 0; i < regargs; i++)
+ mc->mc_gpr[3 + i] = va_arg(ap, uint32_t);
+
+ /*
+ * Overflow args go onto the stack
+ */
+ if (argc > 8) {
+ uint32_t *argp;
+
+ /* Skip past frame pointer and saved LR */
+ argp = (uint32_t *)sp + 2;
+
+ for (i = 0; i < stackargs; i++)
+ *argp++ = va_arg(ap, uint32_t);
+ }
+ va_end(ap);
+
+ /*
+ * Use caller-saved regs 14/15 to hold params that _ctx_start
+ * will use to invoke the user-supplied func
+ */
+ mc->mc_srr0 = (uint32_t) _ctx_start;
+ mc->mc_gpr[1] = (uint32_t) sp; /* new stack pointer */
+ mc->mc_gpr[14] = (uint32_t) start; /* r14 <- start */
+ mc->mc_gpr[15] = (uint32_t) ucp; /* r15 <- ucp */
+}
diff --git a/lib/libc/powerpc/gen/setjmp.S b/lib/libc/powerpc/gen/setjmp.S
new file mode 100644
index 0000000..6df4f93
--- /dev/null
+++ b/lib/libc/powerpc/gen/setjmp.S
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: setjmp.S,v 1.3 1998/10/03 12:30:38 tsubai Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/syscall.h>
+
+/*
+ * C library -- setjmp, longjmp
+ *
+ * longjmp(a,v)
+ * will generate a "return(v?v:1)" from the last call to
+ * setjmp(a)
+ * by restoring registers from the stack.
+ * The previous signal state is restored.
+ *
+ * jmpbuf layout:
+ * +------------+
+ * | unused |
+ * +------------+
+ * | sig state |
+ * | |
+ * | (4 words) |
+ * | |
+ * +------------+
+ * | saved regs |
+ * | ... |
+ */
+
+ENTRY(setjmp)
+ mr %r6,%r3
+ li %r3,1 /* SIG_BLOCK, but doesn't matter */
+ /* since set == NULL */
+ li %r4,0 /* set = NULL */
+ mr %r5,%r6 /* &oset */
+ addi %r5,%r5,4
+ li %r0, SYS_sigprocmask /*sigprocmask(SIG_BLOCK, NULL, &oset)*/
+ sc /*assume no error XXX */
+ mflr %r11 /* r11 <- link reg */
+ mfcr %r12 /* r12 <- condition reg */
+ mr %r10,%r1 /* r10 <- stackptr */
+ mr %r9,%r2 /* r9 <- global ptr */
+ stmw %r9,20(%r6)
+ li %r3,0 /* return (0) */
+ blr
+
+ WEAK_REFERENCE(CNAME(__longjmp), longjmp)
+ENTRY(__longjmp)
+ lmw %r9,20(%r3) /* restore regs */
+ mr %r6,%r4 /* save val param */
+ mtlr %r11 /* r11 -> link reg */
+ mtcr %r12 /* r12 -> condition reg */
+ mr %r1,%r10 /* r10 -> stackptr */
+ mr %r4,%r3
+ li %r3,3 /* SIG_SETMASK */
+ addi %r4,%r4,4 /* &set */
+ li %r5,0 /* oset = NULL */
+ li %r0,SYS_sigprocmask /* sigprocmask(SIG_SET, &set, NULL) */
+ sc /* assume no error XXX */
+ or. %r3,%r6,%r6
+ bnelr
+ li %r3,1
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc/gen/signalcontext.c b/lib/libc/powerpc/gen/signalcontext.c
new file mode 100644
index 0000000..30e2be8
--- /dev/null
+++ b/lib/libc/powerpc/gen/signalcontext.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2004 Marcel Moolenaar, Peter Grehan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/ucontext.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <strings.h>
+
+typedef void (*handler_t)(uint32_t, uint32_t, uint32_t);
+
+/* Prototypes */
+static void ctx_wrapper(ucontext_t *ucp, handler_t func, uint32_t sig,
+ uint32_t sig_si, uint32_t sig_uc);
+
+__weak_reference(__signalcontext, signalcontext);
+
+int
+__signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func)
+{
+ siginfo_t *sig_si;
+ ucontext_t *sig_uc;
+ uint32_t sp;
+
+ /* Bail out if we don't have a valid ucontext pointer. */
+ if (ucp == NULL)
+ abort();
+
+ /*
+ * Build a 16-byte-aligned signal frame
+ */
+ sp = (ucp->uc_mcontext.mc_gpr[1] - sizeof(ucontext_t)) & ~15UL;
+ sig_uc = (ucontext_t *)sp;
+ bcopy(ucp, sig_uc, sizeof(*sig_uc));
+ sp = (sp - sizeof(siginfo_t)) & ~15UL;
+ sig_si = (siginfo_t *)sp;
+ bzero(sig_si, sizeof(*sig_si));
+ sig_si->si_signo = sig;
+
+ /*
+ * Subtract 8 bytes from stack to allow for frameptr
+ */
+ sp -= 2*sizeof(uint32_t);
+ sp &= ~15UL;
+
+ /*
+ * Setup the ucontext of the signal handler.
+ */
+ bzero(&ucp->uc_mcontext, sizeof(ucp->uc_mcontext));
+ ucp->uc_link = sig_uc;
+ sigdelset(&ucp->uc_sigmask, sig);
+
+ ucp->uc_mcontext.mc_vers = _MC_VERSION;
+ ucp->uc_mcontext.mc_len = sizeof(struct __mcontext);
+ ucp->uc_mcontext.mc_srr0 = (uint32_t) ctx_wrapper;
+ ucp->uc_mcontext.mc_gpr[1] = (uint32_t) sp;
+ ucp->uc_mcontext.mc_gpr[3] = (uint32_t) func;
+ ucp->uc_mcontext.mc_gpr[4] = (uint32_t) sig;
+ ucp->uc_mcontext.mc_gpr[5] = (uint32_t) sig_si;
+ ucp->uc_mcontext.mc_gpr[6] = (uint32_t) sig_uc;
+
+ return (0);
+}
+
+static void
+ctx_wrapper(ucontext_t *ucp, handler_t func, uint32_t sig, uint32_t sig_si,
+ uint32_t sig_uc)
+{
+
+ (*func)(sig, sig_si, sig_uc);
+ if (ucp->uc_link == NULL)
+ exit(0);
+ setcontext((const ucontext_t *)ucp->uc_link);
+ /* should never get here */
+ abort();
+ /* NOTREACHED */
+}
diff --git a/lib/libc/powerpc/gen/sigsetjmp.S b/lib/libc/powerpc/gen/sigsetjmp.S
new file mode 100644
index 0000000..9639dd1
--- /dev/null
+++ b/lib/libc/powerpc/gen/sigsetjmp.S
@@ -0,0 +1,98 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: sigsetjmp.S,v 1.4 1998/10/03 12:30:38 tsubai Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * C library -- sigsetjmp, siglongjmp
+ *
+ * siglongjmp(a,v)
+ * will generate a "return(v?v:1)" from the last call to
+ * sigsetjmp(a, savemask)
+ * by restoring registers from the stack.
+ * The previous signal state is restored if savemask is non-zero
+ *
+ * jmpbuf layout:
+ * +------------+
+ * | savemask |
+ * +------------+
+ * | sig state |
+ * | |
+ * | (4 words) |
+ * | |
+ * +------------+
+ * | saved regs |
+ * | ... |
+ */
+
+
+#include <sys/syscall.h>
+
+ENTRY(sigsetjmp)
+ mr %r6,%r3
+ stw %r4,0(%r3)
+ or. %r7,%r4,%r4
+ beq 1f
+ li %r3,1 /* SIG_BLOCK, but doesn't matter */
+ /* since set == NULL */
+ li %r4,0 /* set = NULL */
+ mr %r5,%r6 /* &oset */
+ addi %r5,%r5,4
+ li %r0, SYS_sigprocmask /* sigprocmask(SIG_BLOCK, NULL, &oset)*/
+ sc /* assume no error XXX */
+1:
+ mflr %r11
+ mfcr %r12
+ mr %r10,%r1
+ mr %r9,%r2
+ stmw %r9,20(%r6)
+ li %r3,0
+ blr
+
+ENTRY(siglongjmp)
+ lmw %r9,20(%r3)
+ lwz %r7,0(%r3)
+ mr %r6,%r4
+ mtlr %r11
+ mtcr %r12
+ mr %r1,%r10
+ or. %r7,%r7,%r7
+ beq 1f
+ mr %r4,%r3
+ li %r3,3 /* SIG_SETMASK */
+ addi %r4,%r4,4 /* &set */
+ li %r5,0 /* oset = NULL */
+ li %r0,SYS_sigprocmask /* sigprocmask(SIG_SET, &set, NULL) */
+ sc /* assume no error XXX */
+1:
+ or. %r3,%r6,%r6
+ bnelr
+ li %r3,1
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc/gen/syncicache.c b/lib/libc/powerpc/gen/syncicache.c
new file mode 100644
index 0000000..434dcec
--- /dev/null
+++ b/lib/libc/powerpc/gen/syncicache.c
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (C) 1995-1997, 1999 Wolfgang Solfrank.
+ * Copyright (C) 1995-1997, 1999 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $NetBSD: syncicache.c,v 1.2 1999/05/05 12:36:40 tsubai Exp $
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/param.h>
+#if defined(_KERNEL) || defined(_STANDALONE)
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <vm/vm.h>
+#endif
+#include <sys/sysctl.h>
+
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+
+#ifdef _STANDALONE
+int cacheline_size = 32;
+#endif
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#include <stdlib.h>
+
+int cacheline_size = 0;
+
+static void getcachelinesize(void);
+
+static void
+getcachelinesize()
+{
+ static int cachemib[] = { CTL_MACHDEP, CPU_CACHELINE };
+ int clen;
+
+ clen = sizeof(cacheline_size);
+
+ if (sysctl(cachemib, sizeof(cachemib) / sizeof(cachemib[0]),
+ &cacheline_size, &clen, NULL, 0) < 0 || !cacheline_size) {
+ abort();
+ }
+}
+#endif
+
+void
+__syncicache(void *from, int len)
+{
+ int l, off;
+ char *p;
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+ if (!cacheline_size)
+ getcachelinesize();
+#endif
+
+ off = (u_int)from & (cacheline_size - 1);
+ l = len += off;
+ p = (char *)from - off;
+
+ do {
+ __asm __volatile ("dcbst 0,%0" :: "r"(p));
+ p += cacheline_size;
+ } while ((l -= cacheline_size) > 0);
+ __asm __volatile ("sync");
+ p = (char *)from - off;
+ do {
+ __asm __volatile ("icbi 0,%0" :: "r"(p));
+ p += cacheline_size;
+ } while ((len -= cacheline_size) > 0);
+ __asm __volatile ("sync; isync");
+}
+
diff --git a/lib/libc/powerpc/softfloat/milieu.h b/lib/libc/powerpc/softfloat/milieu.h
new file mode 100644
index 0000000..e2e43b1
--- /dev/null
+++ b/lib/libc/powerpc/softfloat/milieu.h
@@ -0,0 +1,49 @@
+/* $NetBSD: milieu.h,v 1.1 2000/12/29 20:13:54 bjh21 Exp $ */
+/* $FreeBSD$ */
+
+/*
+===============================================================================
+
+This C header file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+Include common integer types and flags.
+-------------------------------------------------------------------------------
+*/
+#include "powerpc-gcc.h"
+
+/*
+-------------------------------------------------------------------------------
+Symbolic Boolean literals.
+-------------------------------------------------------------------------------
+*/
+enum {
+ FALSE = 0,
+ TRUE = 1
+};
diff --git a/lib/libc/powerpc/softfloat/powerpc-gcc.h b/lib/libc/powerpc/softfloat/powerpc-gcc.h
new file mode 100644
index 0000000..e2f8680
--- /dev/null
+++ b/lib/libc/powerpc/softfloat/powerpc-gcc.h
@@ -0,0 +1,92 @@
+/* $NetBSD: arm-gcc.h,v 1.2 2001/02/21 18:09:25 bjh21 Exp $ */
+/* $FreeBSD$ */
+
+/*
+-------------------------------------------------------------------------------
+One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined.
+-------------------------------------------------------------------------------
+*/
+#define BIGENDIAN
+
+/*
+-------------------------------------------------------------------------------
+The macro `BITS64' can be defined to indicate that 64-bit integer types are
+supported by the compiler.
+-------------------------------------------------------------------------------
+*/
+#define BITS64
+
+/*
+-------------------------------------------------------------------------------
+Each of the following `typedef's defines the most convenient type that holds
+integers of at least as many bits as specified. For example, `uint8' should
+be the most convenient type that can hold unsigned integers of as many as
+8 bits. The `flag' type must be able to hold either a 0 or 1. For most
+implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
+to the same as `int'.
+-------------------------------------------------------------------------------
+*/
+typedef int flag;
+typedef unsigned int uint8;
+typedef int int8;
+typedef unsigned int uint16;
+typedef int int16;
+typedef unsigned int uint32;
+typedef signed int int32;
+#ifdef BITS64
+typedef unsigned long long int uint64;
+typedef signed long long int int64;
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Each of the following `typedef's defines a type that holds integers
+of _exactly_ the number of bits specified. For instance, for most
+implementation of C, `bits16' and `sbits16' should be `typedef'ed to
+`unsigned short int' and `signed short int' (or `short int'), respectively.
+-------------------------------------------------------------------------------
+*/
+typedef unsigned char bits8;
+typedef signed char sbits8;
+typedef unsigned short int bits16;
+typedef signed short int sbits16;
+typedef unsigned int bits32;
+typedef signed int sbits32;
+#ifdef BITS64
+typedef unsigned long long int bits64;
+typedef signed long long int sbits64;
+#endif
+
+#ifdef BITS64
+/*
+-------------------------------------------------------------------------------
+The `LIT64' macro takes as its argument a textual integer literal and
+if necessary ``marks'' the literal as having a 64-bit integer type.
+For example, the GNU C Compiler (`gcc') requires that 64-bit literals be
+appended with the letters `LL' standing for `long long', which is `gcc's
+name for the 64-bit integer type. Some compilers may allow `LIT64' to be
+defined as the identity macro: `#define LIT64( a ) a'.
+-------------------------------------------------------------------------------
+*/
+#define LIT64( a ) a##LL
+#endif
+
+/*
+-------------------------------------------------------------------------------
+The macro `INLINE' can be used before functions that should be inlined. If
+a compiler does not support explicit inlining, this macro should be defined
+to be `static'.
+-------------------------------------------------------------------------------
+*/
+#define INLINE static __inline
+
+/*
+-------------------------------------------------------------------------------
+The ARM FPA is odd in that it stores doubles high-order word first, no matter
+what the endianness of the CPU. VFP is sane.
+-------------------------------------------------------------------------------
+*/
+#if defined(SOFTFLOAT_FOR_GCC)
+#define FLOAT64_DEMANGLE(a) (a)
+#define FLOAT64_MANGLE(a) (a)
+#endif
diff --git a/lib/libc/powerpc/softfloat/softfloat.h b/lib/libc/powerpc/softfloat/softfloat.h
new file mode 100644
index 0000000..6b9c9b0
--- /dev/null
+++ b/lib/libc/powerpc/softfloat/softfloat.h
@@ -0,0 +1,307 @@
+/* $NetBSD: softfloat.h,v 1.6 2002/05/12 13:12:46 bjh21 Exp $ */
+/* $FreeBSD$ */
+
+/* This is a derivative work. */
+
+/*
+===============================================================================
+
+This C header file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+The macro `FLOATX80' must be defined to enable the extended double-precision
+floating-point format `floatx80'. If this macro is not defined, the
+`floatx80' type will not be defined, and none of the functions that either
+input or output the `floatx80' type will be defined. The same applies to
+the `FLOAT128' macro and the quadruple-precision format `float128'.
+-------------------------------------------------------------------------------
+*/
+/* #define FLOATX80 */
+/* #define FLOAT128 */
+
+#include <machine/ieeefp.h>
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point types.
+-------------------------------------------------------------------------------
+*/
+typedef unsigned int float32;
+typedef unsigned long long float64;
+#ifdef FLOATX80
+typedef struct {
+ unsigned short high;
+ unsigned long long low;
+} floatx80;
+#endif
+#ifdef FLOAT128
+typedef struct {
+ unsigned long long high, low;
+} float128;
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point underflow tininess-detection mode.
+-------------------------------------------------------------------------------
+*/
+#ifndef SOFTFLOAT_FOR_GCC
+extern int8 float_detect_tininess;
+#endif
+enum {
+ float_tininess_after_rounding = 0,
+ float_tininess_before_rounding = 1
+};
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point rounding mode.
+-------------------------------------------------------------------------------
+*/
+extern fp_rnd_t float_rounding_mode;
+enum {
+ float_round_nearest_even = FP_RN,
+ float_round_to_zero = FP_RZ,
+ float_round_down = FP_RM,
+ float_round_up = FP_RP
+};
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point exception flags.
+-------------------------------------------------------------------------------
+*/
+typedef fp_except_t fp_except;
+
+extern fp_except float_exception_flags;
+extern fp_except float_exception_mask;
+enum {
+ float_flag_inexact = FP_X_IMP,
+ float_flag_underflow = FP_X_UFL,
+ float_flag_overflow = FP_X_OFL,
+ float_flag_divbyzero = FP_X_DZ,
+ float_flag_invalid = FP_X_INV
+};
+
+/*
+-------------------------------------------------------------------------------
+Routine to raise any or all of the software IEC/IEEE floating-point
+exception flags.
+-------------------------------------------------------------------------------
+*/
+void float_raise( fp_except );
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE integer-to-floating-point conversion routines.
+-------------------------------------------------------------------------------
+*/
+float32 int32_to_float32( int );
+float64 int32_to_float64( int );
+#ifdef FLOATX80
+floatx80 int32_to_floatx80( int );
+#endif
+#ifdef FLOAT128
+float128 int32_to_float128( int );
+#endif
+float32 int64_to_float32( long long );
+float64 int64_to_float64( long long );
+#ifdef FLOATX80
+floatx80 int64_to_floatx80( long long );
+#endif
+#ifdef FLOAT128
+float128 int64_to_float128( long long );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE single-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float32_to_int32( float32 );
+int float32_to_int32_round_to_zero( float32 );
+unsigned int float32_to_uint32_round_to_zero( float32 );
+long long float32_to_int64( float32 );
+long long float32_to_int64_round_to_zero( float32 );
+float64 float32_to_float64( float32 );
+#ifdef FLOATX80
+floatx80 float32_to_floatx80( float32 );
+#endif
+#ifdef FLOAT128
+float128 float32_to_float128( float32 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE single-precision operations.
+-------------------------------------------------------------------------------
+*/
+float32 float32_round_to_int( float32 );
+float32 float32_add( float32, float32 );
+float32 float32_sub( float32, float32 );
+float32 float32_mul( float32, float32 );
+float32 float32_div( float32, float32 );
+float32 float32_rem( float32, float32 );
+float32 float32_sqrt( float32 );
+int float32_eq( float32, float32 );
+int float32_le( float32, float32 );
+int float32_lt( float32, float32 );
+int float32_eq_signaling( float32, float32 );
+int float32_le_quiet( float32, float32 );
+int float32_lt_quiet( float32, float32 );
+#ifndef SOFTFLOAT_FOR_GCC
+int float32_is_signaling_nan( float32 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE double-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float64_to_int32( float64 );
+int float64_to_int32_round_to_zero( float64 );
+unsigned int float64_to_uint32_round_to_zero( float64 );
+long long float64_to_int64( float64 );
+long long float64_to_int64_round_to_zero( float64 );
+float32 float64_to_float32( float64 );
+#ifdef FLOATX80
+floatx80 float64_to_floatx80( float64 );
+#endif
+#ifdef FLOAT128
+float128 float64_to_float128( float64 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE double-precision operations.
+-------------------------------------------------------------------------------
+*/
+float64 float64_round_to_int( float64 );
+float64 float64_add( float64, float64 );
+float64 float64_sub( float64, float64 );
+float64 float64_mul( float64, float64 );
+float64 float64_div( float64, float64 );
+float64 float64_rem( float64, float64 );
+float64 float64_sqrt( float64 );
+int float64_eq( float64, float64 );
+int float64_le( float64, float64 );
+int float64_lt( float64, float64 );
+int float64_eq_signaling( float64, float64 );
+int float64_le_quiet( float64, float64 );
+int float64_lt_quiet( float64, float64 );
+#ifndef SOFTFLOAT_FOR_GCC
+int float64_is_signaling_nan( float64 );
+#endif
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int floatx80_to_int32( floatx80 );
+int floatx80_to_int32_round_to_zero( floatx80 );
+long long floatx80_to_int64( floatx80 );
+long long floatx80_to_int64_round_to_zero( floatx80 );
+float32 floatx80_to_float32( floatx80 );
+float64 floatx80_to_float64( floatx80 );
+#ifdef FLOAT128
+float128 floatx80_to_float128( floatx80 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision rounding precision. Valid
+values are 32, 64, and 80.
+-------------------------------------------------------------------------------
+*/
+extern int floatx80_rounding_precision;
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision operations.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_round_to_int( floatx80 );
+floatx80 floatx80_add( floatx80, floatx80 );
+floatx80 floatx80_sub( floatx80, floatx80 );
+floatx80 floatx80_mul( floatx80, floatx80 );
+floatx80 floatx80_div( floatx80, floatx80 );
+floatx80 floatx80_rem( floatx80, floatx80 );
+floatx80 floatx80_sqrt( floatx80 );
+int floatx80_eq( floatx80, floatx80 );
+int floatx80_le( floatx80, floatx80 );
+int floatx80_lt( floatx80, floatx80 );
+int floatx80_eq_signaling( floatx80, floatx80 );
+int floatx80_le_quiet( floatx80, floatx80 );
+int floatx80_lt_quiet( floatx80, floatx80 );
+int floatx80_is_signaling_nan( floatx80 );
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE quadruple-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float128_to_int32( float128 );
+int float128_to_int32_round_to_zero( float128 );
+long long float128_to_int64( float128 );
+long long float128_to_int64_round_to_zero( float128 );
+float32 float128_to_float32( float128 );
+float64 float128_to_float64( float128 );
+#ifdef FLOATX80
+floatx80 float128_to_floatx80( float128 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE quadruple-precision operations.
+-------------------------------------------------------------------------------
+*/
+float128 float128_round_to_int( float128 );
+float128 float128_add( float128, float128 );
+float128 float128_sub( float128, float128 );
+float128 float128_mul( float128, float128 );
+float128 float128_div( float128, float128 );
+float128 float128_rem( float128, float128 );
+float128 float128_sqrt( float128 );
+int float128_eq( float128, float128 );
+int float128_le( float128, float128 );
+int float128_lt( float128, float128 );
+int float128_eq_signaling( float128, float128 );
+int float128_le_quiet( float128, float128 );
+int float128_lt_quiet( float128, float128 );
+int float128_is_signaling_nan( float128 );
+
+#endif
+
diff --git a/lib/libc/powerpc/sys/Makefile.inc b/lib/libc/powerpc/sys/Makefile.inc
new file mode 100644
index 0000000..5193cc2
--- /dev/null
+++ b/lib/libc/powerpc/sys/Makefile.inc
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+MDASM+= brk.S cerror.S exect.S pipe.S ptrace.S sbrk.S setlogin.S
+
+# Don't generate default code for these syscalls:
+NOASM= break.o exit.o getlogin.o openbsd_poll.o sstk.o yield.o
+
+PSEUDO= _getlogin.o _exit.o
+.if !defined(WITHOUT_SYSCALL_COMPAT)
+PSEUDO+= _pread.o _pwrite.o _lseek.o _mmap.o _ftruncate.o _truncate.o
+.endif
diff --git a/lib/libc/powerpc/sys/brk.S b/lib/libc/powerpc/sys/brk.S
new file mode 100644
index 0000000..018eec9
--- /dev/null
+++ b/lib/libc/powerpc/sys/brk.S
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: brk.S,v 1.9 2000/06/26 06:25:43 kleink Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl HIDENAME(curbrk)
+ .globl HIDENAME(minbrk)
+ .globl CNAME(_end)
+
+ .data
+HIDENAME(minbrk):
+ .long CNAME(_end)
+
+ .text
+
+ENTRY(brk)
+#ifdef PIC
+ mflr %r10
+ bl _GLOBAL_OFFSET_TABLE_@local-4
+ mflr %r9
+ mtlr %r10
+ lwz %r5,HIDENAME(minbrk)@got(%r9)
+ lwz %r6,0(%r5)
+#else
+ lis %r5,HIDENAME(minbrk)@ha
+ lwz %r6,HIDENAME(minbrk)@l(%r5)
+#endif
+ cmplw %r6,%r3 /* if (minbrk <= r3) */
+ bgt 0f
+ mr %r6,%r3 /* r6 = r3 */
+0:
+ mr %r3,%r6 /* new break value */
+ li %r0,SYS_break
+ sc /* assume, that r5 is kept */
+ bso 1f
+#ifdef PIC
+ lwz %r7,HIDENAME(curbrk)@got(%r9)
+ stw %r6,0(%r7)
+#else
+ lis %r7,HIDENAME(curbrk)@ha /* record new break */
+ stw %r6,HIDENAME(curbrk)@l(%r7)
+#endif
+ blr /* return 0 */
+
+1:
+ b PIC_PLT(HIDENAME(cerror))
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc/sys/cerror.S b/lib/libc/powerpc/sys/cerror.S
new file mode 100644
index 0000000..7667cb8
--- /dev/null
+++ b/lib/libc/powerpc/sys/cerror.S
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: cerror.S,v 1.5 2000/01/27 14:58:48 kleink Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl HIDENAME(cerror)
+ .globl CNAME(__error)
+
+ /*
+ * The __error() function is thread aware. For non-threaded
+ * programs and the initial threaded in threaded programs,
+ * it returns a pointer to the global errno variable.
+ */
+HIDENAME(cerror):
+ mflr %r0
+ stwu %r1,-16(%r1) /* allocate new stack frame */
+ stw %r0,20(%r1) /* and save lr, r31 */
+ stw %r31,8(%r1)
+ mr %r31,%r3 /* stash errval in callee-saved register */
+ bl PIC_PLT(CNAME(__error))
+ stw %r31,0(%r3) /* store errval into &errno */
+ lwz %r0,20(%r1)
+ lwz %r31,8(%r1)
+ mtlr %r0
+ la %r1,16(%r1)
+ li %r3,-1
+ li %r4,-1
+ blr /* return to callers caller */
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc/sys/exect.S b/lib/libc/powerpc/sys/exect.S
new file mode 100644
index 0000000..3c39b3c
--- /dev/null
+++ b/lib/libc/powerpc/sys/exect.S
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: exect.S,v 1.3 1998/05/25 15:28:03 ws Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ENTRY(exect)
+ li %r0,SYS_execve
+ sc
+ bso 1f
+ blr
+1:
+ b PIC_PLT(HIDENAME(cerror))
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc/sys/pipe.S b/lib/libc/powerpc/sys/pipe.S
new file mode 100644
index 0000000..3f6d9a4
--- /dev/null
+++ b/lib/libc/powerpc/sys/pipe.S
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: pipe.S,v 1.6 2000/09/28 08:38:54 kleink Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ENTRY(pipe)
+ mr %r5,%r3 /* save pointer */
+ li %r0,SYS_pipe
+ sc /* r5 is preserved */
+ bso 1f
+ stw %r3,0(%r5) /* success, store fds */
+ stw %r4,4(%r5)
+ li %r3,0
+ blr /* and return 0 */
+1:
+ b PIC_PLT(HIDENAME(cerror))
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc/sys/ptrace.S b/lib/libc/powerpc/sys/ptrace.S
new file mode 100644
index 0000000..0bc25c9
--- /dev/null
+++ b/lib/libc/powerpc/sys/ptrace.S
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: ptrace.S,v 1.3 2000/02/23 20:16:57 kleink Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ENTRY(ptrace)
+ mflr %r0
+ stwu %r1,-32(%r1)
+ stw %r0,36(%r1)
+ stw %r3,8(%r1)
+ stw %r4,12(%r1)
+ stw %r5,16(%r1)
+ stw %r6,20(%r1)
+
+ bl PIC_PLT(CNAME(__error))
+ li %r7,0
+ stw %r7,0(%r3)
+
+ lwz %r3,8(%r1)
+ lwz %r4,12(%r1)
+ lwz %r5,16(%r1)
+ lwz %r0,36(%r1)
+ lwz %r6,20(%r1)
+ mtlr %r0
+ la %r1,32(%r1)
+ li %r0,SYS_ptrace
+ sc
+ bso 1f
+ blr
+1:
+ b PIC_PLT(HIDENAME(cerror))
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc/sys/sbrk.S b/lib/libc/powerpc/sys/sbrk.S
new file mode 100644
index 0000000..a5e4020
--- /dev/null
+++ b/lib/libc/powerpc/sys/sbrk.S
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: sbrk.S,v 1.8 2000/06/26 06:25:44 kleink Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl HIDENAME(curbrk)
+ .globl CNAME(_end)
+
+ .data
+HIDENAME(curbrk):
+ .long CNAME(_end)
+
+ .text
+ENTRY(sbrk)
+
+#ifdef PIC
+ mflr %r10
+ bl _GLOBAL_OFFSET_TABLE_@local-4
+ mflr %r5
+ mtlr %r10
+ lwz %r5,HIDENAME(curbrk)@got(%r5)
+ lwz %r6,0(%r5)
+#else
+ lis %r5,HIDENAME(curbrk)@ha
+ lwz %r6,HIDENAME(curbrk)@l(%r5) /* r6 = old break */
+#endif
+ cmpwi %r3,0 /* sbrk(0) - return curbrk */
+ beq 1f
+ add %r3,%r3,%r6
+ mr %r7,%r3 /* r7 = new break */
+ li %r0,SYS_break
+ sc /* break(new_break) */
+ bso 2f
+#ifdef PIC
+ stw %r7,0(%r5)
+#else
+ stw %r7,HIDENAME(curbrk)@l(%r5) /* record new break */
+#endif
+1:
+ mr %r3,%r6 /* set return value */
+ blr
+2:
+ b PIC_PLT(HIDENAME(cerror))
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc/sys/setlogin.S b/lib/libc/powerpc/sys/setlogin.S
new file mode 100644
index 0000000..e0d6d3c
--- /dev/null
+++ b/lib/libc/powerpc/sys/setlogin.S
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: setlogin.S,v 1.3 1998/11/24 11:14:57 tsubai Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl CNAME(_logname_valid) /* in _getlogin() */
+
+SYSCALL(setlogin)
+#ifdef PIC
+ mflr %r10
+ bl _GLOBAL_OFFSET_TABLE_@local-4
+ mflr %r4
+ lwz %r4,CNAME(_logname_valid)@got(%r4)
+ li %r5,%r0
+ stw %r5,0(%r4)
+ mtlr %r10
+#else
+ lis %r4,CNAME(_logname_valid)@ha
+ li %r5,0
+ stw %r5,CNAME(_logname_valid)@l(%r4)
+#endif
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc64/Makefile.inc b/lib/libc/powerpc64/Makefile.inc
new file mode 100644
index 0000000..e4ccbb9
--- /dev/null
+++ b/lib/libc/powerpc64/Makefile.inc
@@ -0,0 +1,5 @@
+# $FreeBSD$
+
+# Long double is 64-bits
+MDSRCS+=machdep_ldisd.c
+SYM_MAPS+=${.CURDIR}/powerpc64/Symbol.map
diff --git a/lib/libc/powerpc64/SYS.h b/lib/libc/powerpc64/SYS.h
new file mode 100644
index 0000000..8b3281f
--- /dev/null
+++ b/lib/libc/powerpc64/SYS.h
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 2002 Benno Rice. All rights reserved.
+ * Copyright (c) 2002 David E. O'Brien. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $NetBSD: SYS.h,v 1.8 2002/01/14 00:55:56 thorpej Exp $
+ * $FreeBSD$
+ */
+
+#include <sys/syscall.h>
+#include <machine/asm.h>
+
+#define _SYSCALL(name) \
+ .text; \
+ .align 2; \
+ li 0,(__CONCAT(SYS_, name)); \
+ sc
+
+#define SYSCALL(name) \
+ .text; \
+ .align 2; \
+2: mflr %r0; \
+ std %r0,16(%r1); \
+ stdu %r1,-48(%r1); \
+ bl CNAME(HIDENAME(cerror)); \
+ nop; \
+ addi %r1,%r1,48; \
+ ld %r0,16(%r1); \
+ mtlr %r0; \
+ blr; \
+ENTRY(__CONCAT(__sys_, name)); \
+ WEAK_REFERENCE(__CONCAT(__sys_, name), name); \
+ WEAK_REFERENCE(__CONCAT(__sys_, name), __CONCAT(_, name)); \
+ _SYSCALL(name); \
+ bso 2b
+
+#define PSEUDO(name) \
+ .text; \
+ .align 2; \
+ENTRY(__CONCAT(__sys_, name)); \
+ WEAK_REFERENCE(__CONCAT(__sys_, name), __CONCAT(_, name)); \
+ _SYSCALL(name); \
+ bnslr; \
+ mflr %r0; \
+ std %r0,16(%r1); \
+ stdu %r1,-48(%r1); \
+ bl CNAME(HIDENAME(cerror)); \
+ nop; \
+ addi %r1,%r1,48; \
+ ld %r0,16(%r1); \
+ mtlr %r0; \
+ blr;
+
+#define RSYSCALL(name) \
+ .text; \
+ .align 2; \
+ENTRY(__CONCAT(__sys_, name)); \
+ WEAK_REFERENCE(__CONCAT(__sys_, name), name); \
+ WEAK_REFERENCE(__CONCAT(__sys_, name), __CONCAT(_, name));\
+ _SYSCALL(name); \
+ bnslr; \
+ \
+ mflr %r0; \
+ std %r0,16(%r1); \
+ stdu %r1,-48(%r1); \
+ bl CNAME(HIDENAME(cerror)); \
+ nop; \
+ addi %r1,%r1,48; \
+ ld %r0,16(%r1); \
+ mtlr %r0; \
+ blr;
diff --git a/lib/libc/powerpc64/Symbol.map b/lib/libc/powerpc64/Symbol.map
new file mode 100644
index 0000000..018a193
--- /dev/null
+++ b/lib/libc/powerpc64/Symbol.map
@@ -0,0 +1,58 @@
+/*
+ * $FreeBSD$
+ */
+
+/*
+ * This only needs to contain symbols that are not listed in
+ * symbol maps from other parts of libc (i.e., not found in
+ * stdlib/Symbol.map, string/Symbol.map, sys/Symbol.map, ...).
+ */
+FBSD_1.0 {
+ /* PSEUDO syscalls */
+ _exit;
+
+ _mcount;
+ _setjmp;
+ _longjmp;
+ fabs;
+ __flt_rounds;
+ fpgetmask;
+ fpgetround;
+ fpgetsticky;
+ fpsetmask;
+ fpsetround;
+ __infinity;
+ __nan;
+ makecontext;
+ setjmp;
+ longjmp;
+ sigsetjmp;
+ siglongjmp;
+ htonl;
+ htons;
+ ntohl;
+ ntohs;
+ brk;
+ exect;
+ sbrk;
+ vfork;
+};
+
+FBSDprivate_1.0 {
+ /* PSEUDO syscalls */
+ __sys_getlogin;
+ _getlogin;
+ __sys_exit;
+
+ _set_tp;
+ _fpgetsticky;
+ __makecontext;
+ __longjmp;
+ signalcontext;
+ __signalcontext;
+ __syncicache;
+ _end;
+ _curbrk;
+ _minbrk;
+ _cerror;
+};
diff --git a/lib/libc/powerpc64/_fpmath.h b/lib/libc/powerpc64/_fpmath.h
new file mode 100644
index 0000000..6d80eb4
--- /dev/null
+++ b/lib/libc/powerpc64/_fpmath.h
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+union IEEEl2bits {
+ long double e;
+ struct {
+ unsigned int sign :1;
+ unsigned int exp :11;
+ unsigned int manh :20;
+ unsigned int manl :32;
+ } bits;
+};
+
+#define mask_nbit_l(u) ((void)0)
+#define LDBL_IMPLICIT_NBIT
+#define LDBL_NBIT 0
+
+#define LDBL_MANH_SIZE 20
+#define LDBL_MANL_SIZE 32
+
+#define LDBL_TO_ARRAY32(u, a) do { \
+ (a)[0] = (uint32_t)(u).bits.manl; \
+ (a)[1] = (uint32_t)(u).bits.manh; \
+} while(0)
diff --git a/lib/libc/powerpc64/arith.h b/lib/libc/powerpc64/arith.h
new file mode 100644
index 0000000..8e2c9ec
--- /dev/null
+++ b/lib/libc/powerpc64/arith.h
@@ -0,0 +1,16 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * NOTE: The definitions in this file must be correct or strtod(3) and
+ * floating point formats in printf(3) will break! The file can be
+ * generated by running contrib/gdtoa/arithchk.c on the target
+ * architecture. See contrib/gdtoa/gdtoaimp.h for details.
+ */
+
+#define IEEE_MC68k
+#define Arith_Kind_ASL 2
+#define Double_Align
diff --git a/lib/libc/powerpc64/gd_qnan.h b/lib/libc/powerpc64/gd_qnan.h
new file mode 100644
index 0000000..d70d8c3
--- /dev/null
+++ b/lib/libc/powerpc64/gd_qnan.h
@@ -0,0 +1,21 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * This file can be generated by compiling and running contrib/gdtoa/qnan.c
+ * on the target architecture after arith.h has been generated.
+ *
+ * $FreeBSD$
+ */
+
+#define f_QNAN 0x7fc00000
+#define d_QNAN0 0x7ff80000
+#define d_QNAN1 0x0
+#define ld_QNAN0 0x7ff80000
+#define ld_QNAN1 0x0
+#define ld_QNAN2 0x0
+#define ld_QNAN3 0x0
+#define ldus_QNAN0 0x7ff8
+#define ldus_QNAN1 0x0
+#define ldus_QNAN2 0x0
+#define ldus_QNAN3 0x0
+#define ldus_QNAN4 0x0
diff --git a/lib/libc/powerpc64/gen/Makefile.inc b/lib/libc/powerpc64/gen/Makefile.inc
new file mode 100644
index 0000000..79a2746
--- /dev/null
+++ b/lib/libc/powerpc64/gen/Makefile.inc
@@ -0,0 +1,9 @@
+# $FreeBSD$
+
+SRCS += _ctx_start.S fabs.S flt_rounds.c fpgetmask.c fpgetround.c \
+ fpgetsticky.c fpsetmask.c fpsetround.c getcontextx.c \
+ infinity.c ldexp.c makecontext.c _setjmp.S \
+ setjmp.S sigsetjmp.S signalcontext.c syncicache.c \
+ _set_tp.c
+
+
diff --git a/lib/libc/powerpc64/gen/_ctx_start.S b/lib/libc/powerpc64/gen/_ctx_start.S
new file mode 100644
index 0000000..79df041
--- /dev/null
+++ b/lib/libc/powerpc64/gen/_ctx_start.S
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2004 Suleiman Souhlal
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+ #include <machine/asm.h>
+
+ __FBSDID("$FreeBSD$");
+
+ .globl CNAME(_ctx_done)
+ .globl CNAME(abort)
+
+ ENTRY(_ctx_start)
+ ld %r2,8(%r14)
+ ld %r14,0(%r14)
+ mtlr %r14
+ blrl /* branch to start function */
+ mr %r3,%r15 /* pass pointer to ucontext as argument */
+ nop
+ bl CNAME(_ctx_done) /* branch to ctxt completion func */
+ /*
+ * we should never return from the
+ * above branch.
+ */
+ nop
+ bl CNAME(abort) /* abort */
+ nop
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc64/gen/_set_tp.c b/lib/libc/powerpc64/gen/_set_tp.c
new file mode 100644
index 0000000..9adb6a5
--- /dev/null
+++ b/lib/libc/powerpc64/gen/_set_tp.c
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+void
+_set_tp(void *tpval)
+{
+ register void *tp __asm__("r13");
+
+ __asm __volatile("mr %0,%1" : "=r"(tp) : "r"((char*)tpval + 0x7010));
+}
diff --git a/lib/libc/powerpc64/gen/_setjmp.S b/lib/libc/powerpc64/gen/_setjmp.S
new file mode 100644
index 0000000..ac0555e
--- /dev/null
+++ b/lib/libc/powerpc64/gen/_setjmp.S
@@ -0,0 +1,117 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: _setjmp.S,v 1.1 1997/03/29 20:55:53 thorpej Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * C library -- _setjmp, _longjmp
+ *
+ * _longjmp(a,v)
+ * will generate a "return(v?v:1)" from the last call to
+ * _setjmp(a)
+ * by restoring registers from the stack.
+ * The previous signal state is NOT restored.
+ *
+ * jmpbuf layout:
+ * +------------+
+ * | unused |
+ * +------------+
+ * | unused |
+ * | |
+ * | (4 words) |
+ * | |
+ * +------------+
+ * | saved regs |
+ * | ... |
+ */
+
+ENTRY(_setjmp)
+ mflr %r11
+ mfcr %r12
+ mr %r10,%r1
+ mr %r9,%r2
+ std %r9,40 + 0*8(%r3)
+ std %r10,40 + 1*8(%r3)
+ std %r11,40 + 2*8(%r3)
+ std %r12,40 + 3*8(%r3)
+ std %r13,40 + 4*8(%r3)
+ std %r14,40 + 5*8(%r3)
+ std %r15,40 + 6*8(%r3)
+ std %r16,40 + 7*8(%r3)
+ std %r17,40 + 8*8(%r3)
+ std %r18,40 + 9*8(%r3)
+ std %r19,40 + 10*8(%r3)
+ std %r20,40 + 11*8(%r3)
+ std %r21,40 + 12*8(%r3)
+ std %r22,40 + 13*8(%r3)
+ std %r23,40 + 14*8(%r3)
+ std %r24,40 + 15*8(%r3)
+ std %r25,40 + 16*8(%r3)
+ std %r26,40 + 17*8(%r3)
+ std %r27,40 + 18*8(%r3)
+ std %r28,40 + 19*8(%r3)
+ std %r29,40 + 20*8(%r3)
+ std %r30,40 + 21*8(%r3)
+ std %r31,40 + 22*8(%r3)
+ li %r3,0
+ blr
+
+ENTRY(_longjmp)
+ ld %r9,40 + 0*8(%r3)
+ ld %r10,40 + 1*8(%r3)
+ ld %r11,40 + 2*8(%r3)
+ ld %r12,40 + 3*8(%r3)
+ ld %r14,40 + 5*8(%r3)
+ ld %r15,40 + 6*8(%r3)
+ ld %r16,40 + 7*8(%r3)
+ ld %r17,40 + 8*8(%r3)
+ ld %r18,40 + 9*8(%r3)
+ ld %r19,40 + 10*8(%r3)
+ ld %r20,40 + 11*8(%r3)
+ ld %r21,40 + 12*8(%r3)
+ ld %r22,40 + 13*8(%r3)
+ ld %r23,40 + 14*8(%r3)
+ ld %r24,40 + 15*8(%r3)
+ ld %r25,40 + 16*8(%r3)
+ ld %r26,40 + 17*8(%r3)
+ ld %r27,40 + 18*8(%r3)
+ ld %r28,40 + 19*8(%r3)
+ ld %r29,40 + 20*8(%r3)
+ ld %r30,40 + 21*8(%r3)
+ ld %r31,40 + 22*8(%r3)
+
+ mtlr %r11
+ mtcr %r12
+ mr %r2,%r9
+ mr %r1,%r10
+ or. %r3,%r4,%r4
+ bnelr
+ li %r3,1
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc64/gen/fabs.S b/lib/libc/powerpc64/gen/fabs.S
new file mode 100644
index 0000000..7891012
--- /dev/null
+++ b/lib/libc/powerpc64/gen/fabs.S
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2004 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * double fabs(double)
+ */
+ENTRY(fabs)
+ fabs %f1,%f1
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc64/gen/flt_rounds.c b/lib/libc/powerpc64/gen/flt_rounds.c
new file mode 100644
index 0000000..6294be7
--- /dev/null
+++ b/lib/libc/powerpc64/gen/flt_rounds.c
@@ -0,0 +1,56 @@
+/* $NetBSD: flt_rounds.c,v 1.4.10.3 2002/03/22 20:41:53 nathanw Exp $ */
+
+/*
+ * Copyright (c) 1996 Mark Brinicombe
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Mark Brinicombe
+ * for the NetBSD Project.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <machine/float.h>
+
+#ifndef _SOFT_FLOAT
+static const int map[] = {
+ 1, /* round to nearest */
+ 0, /* round to zero */
+ 2, /* round to positive infinity */
+ 3 /* round to negative infinity */
+};
+
+int
+__flt_rounds()
+{
+ uint64_t fpscr;
+
+ __asm__ __volatile("mffs %0" : "=f"(fpscr));
+ return map[(fpscr & 0x03)];
+}
+#endif
diff --git a/lib/libc/powerpc64/gen/fpgetmask.c b/lib/libc/powerpc64/gen/fpgetmask.c
new file mode 100644
index 0000000..aa7623b
--- /dev/null
+++ b/lib/libc/powerpc64/gen/fpgetmask.c
@@ -0,0 +1,55 @@
+/* $NetBSD: fpgetmask.c,v 1.3 2002/01/13 21:45:47 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dan Winship.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <ieeefp.h>
+
+#ifndef _SOFT_FLOAT
+fp_except_t
+fpgetmask()
+{
+ u_int64_t fpscr;
+
+ __asm__("mffs %0" : "=f"(fpscr));
+ return ((fp_except_t)((fpscr >> 3) & 0x1f));
+}
+#endif
diff --git a/lib/libc/powerpc64/gen/fpgetround.c b/lib/libc/powerpc64/gen/fpgetround.c
new file mode 100644
index 0000000..5381378
--- /dev/null
+++ b/lib/libc/powerpc64/gen/fpgetround.c
@@ -0,0 +1,55 @@
+/* $NetBSD: fpgetround.c,v 1.3 2002/01/13 21:45:47 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dan Winship.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <ieeefp.h>
+
+#ifndef _SOFT_FLOAT
+fp_rnd_t
+fpgetround()
+{
+ u_int64_t fpscr;
+
+ __asm__("mffs %0" : "=f"(fpscr));
+ return ((fp_rnd_t)(fpscr & 0x3));
+}
+#endif
diff --git a/lib/libc/powerpc64/gen/fpgetsticky.c b/lib/libc/powerpc64/gen/fpgetsticky.c
new file mode 100644
index 0000000..feb2ccc
--- /dev/null
+++ b/lib/libc/powerpc64/gen/fpgetsticky.c
@@ -0,0 +1,61 @@
+/* $NetBSD: fpgetsticky.c,v 1.3 2002/01/13 21:45:48 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dan Winship.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/cdefs.h>
+
+#include "namespace.h"
+
+#include <sys/types.h>
+#include <ieeefp.h>
+
+#ifndef _SOFT_FLOAT
+#ifdef __weak_alias
+__weak_alias(fpgetsticky,_fpgetsticky)
+#endif
+
+fp_except_t
+fpgetsticky()
+{
+ u_int64_t fpscr;
+
+ __asm__ __volatile("mffs %0" : "=f"(fpscr));
+ return ((fp_except_t)((fpscr >> 25) & 0x1f));
+}
+#endif
diff --git a/lib/libc/powerpc64/gen/fpsetmask.c b/lib/libc/powerpc64/gen/fpsetmask.c
new file mode 100644
index 0000000..e1433a5
--- /dev/null
+++ b/lib/libc/powerpc64/gen/fpsetmask.c
@@ -0,0 +1,59 @@
+/* $NetBSD: fpsetmask.c,v 1.3 2002/01/13 21:45:48 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dan Winship.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <ieeefp.h>
+
+#ifndef _SOFT_FLOAT
+fp_except_t
+fpsetmask(fp_except_t mask)
+{
+ u_int64_t fpscr;
+ fp_rnd_t old;
+
+ __asm__("mffs %0" : "=f"(fpscr));
+ old = (fp_rnd_t)((fpscr >> 3) & 0x1f);
+ fpscr = (fpscr & 0xffffff07) | (mask << 3);
+ __asm__ __volatile("mtfsf 0xff,%0" :: "f"(fpscr));
+ return (old);
+}
+#endif
diff --git a/lib/libc/powerpc64/gen/fpsetround.c b/lib/libc/powerpc64/gen/fpsetround.c
new file mode 100644
index 0000000..b4f00d4
--- /dev/null
+++ b/lib/libc/powerpc64/gen/fpsetround.c
@@ -0,0 +1,59 @@
+/* $NetBSD: fpsetround.c,v 1.3 2002/01/13 21:45:48 thorpej Exp $ */
+
+/*
+ * Copyright (c) 1999 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dan Winship.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <ieeefp.h>
+
+#ifndef _SOFT_FLOAT
+fp_rnd_t
+fpsetround(fp_rnd_t rnd_dir)
+{
+ u_int64_t fpscr;
+ fp_rnd_t old;
+
+ __asm__ __volatile("mffs %0" : "=f"(fpscr));
+ old = (fp_rnd_t)(fpscr & 0x3);
+ fpscr = (fpscr & 0xfffffffc) | rnd_dir;
+ __asm__ __volatile("mtfsf 0xff,%0" :: "f"(fpscr));
+ return (old);
+}
+#endif
diff --git a/lib/libc/powerpc64/gen/getcontextx.c b/lib/libc/powerpc64/gen/getcontextx.c
new file mode 100644
index 0000000..307978a
--- /dev/null
+++ b/lib/libc/powerpc64/gen/getcontextx.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int
+__getcontextx_size(void)
+{
+
+ return (sizeof(ucontext_t));
+}
+
+int
+__fillcontextx(char *ctx)
+{
+ ucontext_t *ucp;
+
+ ucp = (ucontext_t *)ctx;
+ return (getcontext(ucp));
+}
+
+__weak_reference(__getcontextx, getcontextx);
+
+ucontext_t *
+__getcontextx(void)
+{
+ char *ctx;
+ int error;
+
+ ctx = malloc(__getcontextx_size());
+ if (ctx == NULL)
+ return (NULL);
+ if (__fillcontextx(ctx) == -1) {
+ error = errno;
+ free(ctx);
+ errno = error;
+ return (NULL);
+ }
+ return ((ucontext_t *)ctx);
+}
diff --git a/lib/libc/powerpc64/gen/infinity.c b/lib/libc/powerpc64/gen/infinity.c
new file mode 100644
index 0000000..cf1695e
--- /dev/null
+++ b/lib/libc/powerpc64/gen/infinity.c
@@ -0,0 +1,17 @@
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: infinity.c,v 1.2 1998/11/14 19:31:02 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+/* infinity.c */
+
+#include <math.h>
+
+/* bytes for +Infinity on powerpc */
+const union __infinity_un __infinity = { { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } };
+
+/* bytes for NaN */
+const union __nan_un __nan = { { 0xff, 0xc0, 0, 0 } };
diff --git a/lib/libc/powerpc64/gen/makecontext.c b/lib/libc/powerpc64/gen/makecontext.c
new file mode 100644
index 0000000..b01c5c1
--- /dev/null
+++ b/lib/libc/powerpc64/gen/makecontext.c
@@ -0,0 +1,118 @@
+/*
+ * Copyright (c) 2004 Suleiman Souhlal
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ucontext.h>
+
+__weak_reference(__makecontext, makecontext);
+
+void _ctx_done(ucontext_t *ucp);
+void _ctx_start(void);
+
+void
+_ctx_done(ucontext_t *ucp)
+{
+ if (ucp->uc_link == NULL)
+ exit(0);
+ else {
+ /* invalidate context */
+ ucp->uc_mcontext.mc_len = 0;
+
+ setcontext((const ucontext_t *)ucp->uc_link);
+
+ abort(); /* should never return from above call */
+ }
+}
+
+void
+__makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...)
+{
+ mcontext_t *mc;
+ char *sp;
+ va_list ap;
+ int i, regargs, stackargs;
+
+ /* Sanity checks */
+ if ((ucp == NULL) || (argc < 0) || (argc > NCARGS)
+ || (ucp->uc_stack.ss_sp == NULL)
+ || (ucp->uc_stack.ss_size < MINSIGSTKSZ)) {
+ /* invalidate context */
+ ucp->uc_mcontext.mc_len = 0;
+ return;
+ }
+
+ /*
+ * The stack must have space for the frame pointer, saved
+ * link register, overflow arguments, and be 16-byte
+ * aligned.
+ */
+ stackargs = (argc > 8) ? argc - 8 : 0;
+ sp = (char *) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size
+ - sizeof(uintptr_t)*(stackargs + 2);
+ sp = (char *)((uintptr_t)sp & ~0x1f);
+
+ mc = &ucp->uc_mcontext;
+
+ /*
+ * Up to 8 register args. Assumes all args are 64-bit and
+ * integer only. Not sure how to cater for floating point.
+ */
+ regargs = (argc > 8) ? 8 : argc;
+ va_start(ap, argc);
+ for (i = 0; i < regargs; i++)
+ mc->mc_gpr[3 + i] = va_arg(ap, uint64_t);
+
+ /*
+ * Overflow args go onto the stack
+ */
+ if (argc > 8) {
+ uint64_t *argp;
+
+ /* Skip past frame pointer and saved LR */
+ argp = (uint64_t *)sp + 6;
+
+ for (i = 0; i < stackargs; i++)
+ *argp++ = va_arg(ap, uint64_t);
+ }
+ va_end(ap);
+
+ /*
+ * Use caller-saved regs 14/15 to hold params that _ctx_start
+ * will use to invoke the user-supplied func
+ */
+ mc->mc_srr0 = *(uintptr_t *)_ctx_start;
+ mc->mc_gpr[1] = (uintptr_t) sp; /* new stack pointer */
+ mc->mc_gpr[14] = (uintptr_t) start; /* r14 <- start */
+ mc->mc_gpr[15] = (uintptr_t) ucp; /* r15 <- ucp */
+}
diff --git a/lib/libc/powerpc64/gen/setjmp.S b/lib/libc/powerpc64/gen/setjmp.S
new file mode 100644
index 0000000..8fe2852
--- /dev/null
+++ b/lib/libc/powerpc64/gen/setjmp.S
@@ -0,0 +1,136 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: setjmp.S,v 1.3 1998/10/03 12:30:38 tsubai Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/syscall.h>
+
+/*
+ * C library -- setjmp, longjmp
+ *
+ * longjmp(a,v)
+ * will generate a "return(v?v:1)" from the last call to
+ * setjmp(a)
+ * by restoring registers from the stack.
+ * The previous signal state is restored.
+ *
+ * jmpbuf layout:
+ * +------------+
+ * | unused |
+ * +------------+
+ * | sig state |
+ * | |
+ * | (4 words) |
+ * | |
+ * +------------+
+ * | saved regs |
+ * | ... |
+ */
+
+ENTRY(setjmp)
+ mr %r6,%r3
+ li %r3,1 /* SIG_BLOCK, but doesn't matter */
+ /* since set == NULL */
+ li %r4,0 /* set = NULL */
+ mr %r5,%r6 /* &oset */
+ addi %r5,%r5,4
+ li %r0, SYS_sigprocmask /*sigprocmask(SIG_BLOCK, NULL, &oset)*/
+ sc /*assume no error XXX */
+ mflr %r11 /* r11 <- link reg */
+ mfcr %r12 /* r12 <- condition reg */
+ mr %r10,%r1 /* r10 <- stackptr */
+ mr %r9,%r2 /* r9 <- global ptr */
+
+ std %r9,40 + 0*8(%r6)
+ std %r10,40 + 1*8(%r6)
+ std %r11,40 + 2*8(%r6)
+ std %r12,40 + 3*8(%r6)
+ std %r13,40 + 4*8(%r6)
+ std %r14,40 + 5*8(%r6)
+ std %r15,40 + 6*8(%r6)
+ std %r16,40 + 7*8(%r6)
+ std %r17,40 + 8*8(%r6)
+ std %r18,40 + 9*8(%r6)
+ std %r19,40 + 10*8(%r6)
+ std %r20,40 + 11*8(%r6)
+ std %r21,40 + 12*8(%r6)
+ std %r22,40 + 13*8(%r6)
+ std %r23,40 + 14*8(%r6)
+ std %r24,40 + 15*8(%r6)
+ std %r25,40 + 16*8(%r6)
+ std %r26,40 + 17*8(%r6)
+ std %r27,40 + 18*8(%r6)
+ std %r28,40 + 19*8(%r6)
+ std %r29,40 + 20*8(%r6)
+ std %r30,40 + 21*8(%r6)
+ std %r31,40 + 22*8(%r6)
+
+ li %r3,0 /* return (0) */
+ blr
+
+ WEAK_REFERENCE(__longjmp, longjmp)
+ENTRY(__longjmp)
+ ld %r9,40 + 0*8(%r3)
+ ld %r10,40 + 1*8(%r3)
+ ld %r11,40 + 2*8(%r3)
+ ld %r12,40 + 3*8(%r3)
+ ld %r14,40 + 5*8(%r3)
+ ld %r15,40 + 6*8(%r3)
+ ld %r16,40 + 7*8(%r3)
+ ld %r17,40 + 8*8(%r3)
+ ld %r18,40 + 9*8(%r3)
+ ld %r19,40 + 10*8(%r3)
+ ld %r20,40 + 11*8(%r3)
+ ld %r21,40 + 12*8(%r3)
+ ld %r22,40 + 13*8(%r3)
+ ld %r23,40 + 14*8(%r3)
+ ld %r24,40 + 15*8(%r3)
+ ld %r25,40 + 16*8(%r3)
+ ld %r26,40 + 17*8(%r3)
+ ld %r27,40 + 18*8(%r3)
+ ld %r28,40 + 19*8(%r3)
+ ld %r29,40 + 20*8(%r3)
+ ld %r30,40 + 21*8(%r3)
+ ld %r31,40 + 22*8(%r3)
+ mr %r6,%r4 /* save val param */
+ mtlr %r11 /* r11 -> link reg */
+ mtcr %r12 /* r12 -> condition reg */
+ mr %r2,%r9 /* r9 -> global ptr */
+ mr %r1,%r10 /* r10 -> stackptr */
+ mr %r4,%r3
+ li %r3,3 /* SIG_SETMASK */
+ addi %r4,%r4,4 /* &set */
+ li %r5,0 /* oset = NULL */
+ li %r0,SYS_sigprocmask /* sigprocmask(SIG_SET, &set, NULL) */
+ sc /* assume no error XXX */
+ or. %r3,%r6,%r6
+ bnelr
+ li %r3,1
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc64/gen/signalcontext.c b/lib/libc/powerpc64/gen/signalcontext.c
new file mode 100644
index 0000000..fad9ee1
--- /dev/null
+++ b/lib/libc/powerpc64/gen/signalcontext.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (c) 2004 Marcel Moolenaar, Peter Grehan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/ucontext.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <strings.h>
+
+typedef void (*handler_t)(uint32_t, uint32_t, uint32_t);
+
+/* Prototypes */
+static void ctx_wrapper(ucontext_t *ucp, handler_t func, uint32_t sig,
+ uint32_t sig_si, uint32_t sig_uc);
+
+__weak_reference(__signalcontext, signalcontext);
+
+int
+__signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func)
+{
+ siginfo_t *sig_si;
+ ucontext_t *sig_uc;
+ uintptr_t sp;
+
+ /* Bail out if we don't have a valid ucontext pointer. */
+ if (ucp == NULL)
+ abort();
+
+ /*
+ * Build a 16-byte-aligned signal frame
+ */
+ sp = (ucp->uc_mcontext.mc_gpr[1] - sizeof(ucontext_t)) & ~15UL;
+ sig_uc = (ucontext_t *)sp;
+ bcopy(ucp, sig_uc, sizeof(*sig_uc));
+ sp = (sp - sizeof(siginfo_t)) & ~15UL;
+ sig_si = (siginfo_t *)sp;
+ bzero(sig_si, sizeof(*sig_si));
+ sig_si->si_signo = sig;
+
+ /*
+ * Subtract 48 bytes from stack to allow for frameptr
+ */
+ sp -= 6*sizeof(uint64_t);
+ sp &= ~15UL;
+
+ /*
+ * Setup the ucontext of the signal handler.
+ */
+ bzero(&ucp->uc_mcontext, sizeof(ucp->uc_mcontext));
+ ucp->uc_link = sig_uc;
+ sigdelset(&ucp->uc_sigmask, sig);
+
+ ucp->uc_mcontext.mc_vers = _MC_VERSION;
+ ucp->uc_mcontext.mc_len = sizeof(struct __mcontext);
+ ucp->uc_mcontext.mc_srr0 = (uint64_t) ctx_wrapper;
+ ucp->uc_mcontext.mc_gpr[1] = (uint64_t) sp;
+ ucp->uc_mcontext.mc_gpr[3] = (uint64_t) func;
+ ucp->uc_mcontext.mc_gpr[4] = (uint64_t) sig;
+ ucp->uc_mcontext.mc_gpr[5] = (uint64_t) sig_si;
+ ucp->uc_mcontext.mc_gpr[6] = (uint64_t) sig_uc;
+
+ return (0);
+}
+
+static void
+ctx_wrapper(ucontext_t *ucp, handler_t func, uint32_t sig, uint32_t sig_si,
+ uint32_t sig_uc)
+{
+
+ (*func)(sig, sig_si, sig_uc);
+ if (ucp->uc_link == NULL)
+ exit(0);
+ setcontext((const ucontext_t *)ucp->uc_link);
+ /* should never get here */
+ abort();
+ /* NOTREACHED */
+}
diff --git a/lib/libc/powerpc64/gen/sigsetjmp.S b/lib/libc/powerpc64/gen/sigsetjmp.S
new file mode 100644
index 0000000..d5341ea
--- /dev/null
+++ b/lib/libc/powerpc64/gen/sigsetjmp.S
@@ -0,0 +1,145 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: sigsetjmp.S,v 1.4 1998/10/03 12:30:38 tsubai Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * C library -- sigsetjmp, siglongjmp
+ *
+ * siglongjmp(a,v)
+ * will generate a "return(v?v:1)" from the last call to
+ * sigsetjmp(a, savemask)
+ * by restoring registers from the stack.
+ * The previous signal state is restored if savemask is non-zero
+ *
+ * jmpbuf layout:
+ * +------------+
+ * | savemask |
+ * +------------+
+ * | sig state |
+ * | |
+ * | (4 words) |
+ * | |
+ * +------------+
+ * | saved regs |
+ * | ... |
+ */
+
+
+#include <sys/syscall.h>
+
+ENTRY(sigsetjmp)
+ mr %r6,%r3
+ stw %r4,0(%r3)
+ or. %r7,%r4,%r4
+ beq 1f
+ li %r3,1 /* SIG_BLOCK, but doesn't matter */
+ /* since set == NULL */
+ li %r4,0 /* set = NULL */
+ mr %r5,%r6 /* &oset */
+ addi %r5,%r5,4
+ li %r0, SYS_sigprocmask /* sigprocmask(SIG_BLOCK, NULL, &oset)*/
+ sc /* assume no error XXX */
+1:
+ mflr %r11
+ mfcr %r12
+ mr %r10,%r1
+ mr %r9,%r2
+
+ std %r9,40 + 0*8(%r6)
+ std %r10,40 + 1*8(%r6)
+ std %r11,40 + 2*8(%r6)
+ std %r12,40 + 3*8(%r6)
+ std %r13,40 + 4*8(%r6)
+ std %r14,40 + 5*8(%r6)
+ std %r15,40 + 6*8(%r6)
+ std %r16,40 + 7*8(%r6)
+ std %r17,40 + 8*8(%r6)
+ std %r18,40 + 9*8(%r6)
+ std %r19,40 + 10*8(%r6)
+ std %r20,40 + 11*8(%r6)
+ std %r21,40 + 12*8(%r6)
+ std %r22,40 + 13*8(%r6)
+ std %r23,40 + 14*8(%r6)
+ std %r24,40 + 15*8(%r6)
+ std %r25,40 + 16*8(%r6)
+ std %r26,40 + 17*8(%r6)
+ std %r27,40 + 18*8(%r6)
+ std %r28,40 + 19*8(%r6)
+ std %r29,40 + 20*8(%r6)
+ std %r30,40 + 21*8(%r6)
+ std %r31,40 + 22*8(%r6)
+
+ li %r3,0
+ blr
+
+ENTRY(siglongjmp)
+ ld %r9,40 + 0*8(%r3)
+ ld %r10,40 + 1*8(%r3)
+ ld %r11,40 + 2*8(%r3)
+ ld %r12,40 + 3*8(%r3)
+ ld %r14,40 + 5*8(%r3)
+ ld %r15,40 + 6*8(%r3)
+ ld %r16,40 + 7*8(%r3)
+ ld %r17,40 + 8*8(%r3)
+ ld %r18,40 + 9*8(%r3)
+ ld %r19,40 + 10*8(%r3)
+ ld %r20,40 + 11*8(%r3)
+ ld %r21,40 + 12*8(%r3)
+ ld %r22,40 + 13*8(%r3)
+ ld %r23,40 + 14*8(%r3)
+ ld %r24,40 + 15*8(%r3)
+ ld %r25,40 + 16*8(%r3)
+ ld %r26,40 + 17*8(%r3)
+ ld %r27,40 + 18*8(%r3)
+ ld %r28,40 + 19*8(%r3)
+ ld %r29,40 + 20*8(%r3)
+ ld %r30,40 + 21*8(%r3)
+ ld %r31,40 + 22*8(%r3)
+
+ lwz %r7,0(%r3)
+ mr %r6,%r4
+ mtlr %r11
+ mtcr %r12
+ mr %r2,%r9
+ mr %r1,%r10
+ or. %r7,%r7,%r7
+ beq 1f
+ mr %r4,%r3
+ li %r3,3 /* SIG_SETMASK */
+ addi %r4,%r4,4 /* &set */
+ li %r5,0 /* oset = NULL */
+ li %r0,SYS_sigprocmask /* sigprocmask(SIG_SET, &set, NULL) */
+ sc /* assume no error XXX */
+1:
+ or. %r3,%r6,%r6
+ bnelr
+ li %r3,1
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc64/gen/syncicache.c b/lib/libc/powerpc64/gen/syncicache.c
new file mode 100644
index 0000000..1267c9f
--- /dev/null
+++ b/lib/libc/powerpc64/gen/syncicache.c
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (C) 1995-1997, 1999 Wolfgang Solfrank.
+ * Copyright (C) 1995-1997, 1999 TooLs GmbH.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by TooLs GmbH.
+ * 4. The name of TooLs GmbH may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY TOOLS GMBH ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL TOOLS GMBH BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $NetBSD: syncicache.c,v 1.2 1999/05/05 12:36:40 tsubai Exp $
+ */
+
+#ifndef lint
+static const char rcsid[] =
+ "$FreeBSD$";
+#endif /* not lint */
+
+#include <sys/param.h>
+#if defined(_KERNEL) || defined(_STANDALONE)
+#include <sys/time.h>
+#include <sys/proc.h>
+#include <vm/vm.h>
+#endif
+#include <sys/sysctl.h>
+
+#include <machine/cpu.h>
+#include <machine/md_var.h>
+
+#ifdef _STANDALONE
+int cacheline_size = 32;
+#endif
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+#include <stdlib.h>
+
+int cacheline_size = 0;
+
+static void getcachelinesize(void);
+
+static void
+getcachelinesize()
+{
+ static int cachemib[] = { CTL_MACHDEP, CPU_CACHELINE };
+ long clen;
+
+ clen = sizeof(cacheline_size);
+
+ if (sysctl(cachemib, sizeof(cachemib) / sizeof(cachemib[0]),
+ &cacheline_size, &clen, NULL, 0) < 0 || !cacheline_size) {
+ abort();
+ }
+}
+#endif
+
+void
+__syncicache(void *from, int len)
+{
+ off_t l, off;
+ char *p;
+
+#if !defined(_KERNEL) && !defined(_STANDALONE)
+ if (!cacheline_size)
+ getcachelinesize();
+#endif
+
+ off = (uintptr_t)from & (cacheline_size - 1);
+ l = len += off;
+ p = (char *)from - off;
+
+ do {
+ __asm __volatile ("dcbst 0,%0" :: "r"(p));
+ p += cacheline_size;
+ } while ((l -= cacheline_size) > 0);
+ __asm __volatile ("sync");
+ p = (char *)from - off;
+ do {
+ __asm __volatile ("icbi 0,%0" :: "r"(p));
+ p += cacheline_size;
+ } while ((len -= cacheline_size) > 0);
+ __asm __volatile ("sync; isync");
+}
+
diff --git a/lib/libc/powerpc64/softfloat/milieu.h b/lib/libc/powerpc64/softfloat/milieu.h
new file mode 100644
index 0000000..e2e43b1
--- /dev/null
+++ b/lib/libc/powerpc64/softfloat/milieu.h
@@ -0,0 +1,49 @@
+/* $NetBSD: milieu.h,v 1.1 2000/12/29 20:13:54 bjh21 Exp $ */
+/* $FreeBSD$ */
+
+/*
+===============================================================================
+
+This C header file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+Include common integer types and flags.
+-------------------------------------------------------------------------------
+*/
+#include "powerpc-gcc.h"
+
+/*
+-------------------------------------------------------------------------------
+Symbolic Boolean literals.
+-------------------------------------------------------------------------------
+*/
+enum {
+ FALSE = 0,
+ TRUE = 1
+};
diff --git a/lib/libc/powerpc64/softfloat/powerpc-gcc.h b/lib/libc/powerpc64/softfloat/powerpc-gcc.h
new file mode 100644
index 0000000..e2f8680
--- /dev/null
+++ b/lib/libc/powerpc64/softfloat/powerpc-gcc.h
@@ -0,0 +1,92 @@
+/* $NetBSD: arm-gcc.h,v 1.2 2001/02/21 18:09:25 bjh21 Exp $ */
+/* $FreeBSD$ */
+
+/*
+-------------------------------------------------------------------------------
+One of the macros `BIGENDIAN' or `LITTLEENDIAN' must be defined.
+-------------------------------------------------------------------------------
+*/
+#define BIGENDIAN
+
+/*
+-------------------------------------------------------------------------------
+The macro `BITS64' can be defined to indicate that 64-bit integer types are
+supported by the compiler.
+-------------------------------------------------------------------------------
+*/
+#define BITS64
+
+/*
+-------------------------------------------------------------------------------
+Each of the following `typedef's defines the most convenient type that holds
+integers of at least as many bits as specified. For example, `uint8' should
+be the most convenient type that can hold unsigned integers of as many as
+8 bits. The `flag' type must be able to hold either a 0 or 1. For most
+implementations of C, `flag', `uint8', and `int8' should all be `typedef'ed
+to the same as `int'.
+-------------------------------------------------------------------------------
+*/
+typedef int flag;
+typedef unsigned int uint8;
+typedef int int8;
+typedef unsigned int uint16;
+typedef int int16;
+typedef unsigned int uint32;
+typedef signed int int32;
+#ifdef BITS64
+typedef unsigned long long int uint64;
+typedef signed long long int int64;
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Each of the following `typedef's defines a type that holds integers
+of _exactly_ the number of bits specified. For instance, for most
+implementation of C, `bits16' and `sbits16' should be `typedef'ed to
+`unsigned short int' and `signed short int' (or `short int'), respectively.
+-------------------------------------------------------------------------------
+*/
+typedef unsigned char bits8;
+typedef signed char sbits8;
+typedef unsigned short int bits16;
+typedef signed short int sbits16;
+typedef unsigned int bits32;
+typedef signed int sbits32;
+#ifdef BITS64
+typedef unsigned long long int bits64;
+typedef signed long long int sbits64;
+#endif
+
+#ifdef BITS64
+/*
+-------------------------------------------------------------------------------
+The `LIT64' macro takes as its argument a textual integer literal and
+if necessary ``marks'' the literal as having a 64-bit integer type.
+For example, the GNU C Compiler (`gcc') requires that 64-bit literals be
+appended with the letters `LL' standing for `long long', which is `gcc's
+name for the 64-bit integer type. Some compilers may allow `LIT64' to be
+defined as the identity macro: `#define LIT64( a ) a'.
+-------------------------------------------------------------------------------
+*/
+#define LIT64( a ) a##LL
+#endif
+
+/*
+-------------------------------------------------------------------------------
+The macro `INLINE' can be used before functions that should be inlined. If
+a compiler does not support explicit inlining, this macro should be defined
+to be `static'.
+-------------------------------------------------------------------------------
+*/
+#define INLINE static __inline
+
+/*
+-------------------------------------------------------------------------------
+The ARM FPA is odd in that it stores doubles high-order word first, no matter
+what the endianness of the CPU. VFP is sane.
+-------------------------------------------------------------------------------
+*/
+#if defined(SOFTFLOAT_FOR_GCC)
+#define FLOAT64_DEMANGLE(a) (a)
+#define FLOAT64_MANGLE(a) (a)
+#endif
diff --git a/lib/libc/powerpc64/softfloat/softfloat.h b/lib/libc/powerpc64/softfloat/softfloat.h
new file mode 100644
index 0000000..6b9c9b0
--- /dev/null
+++ b/lib/libc/powerpc64/softfloat/softfloat.h
@@ -0,0 +1,307 @@
+/* $NetBSD: softfloat.h,v 1.6 2002/05/12 13:12:46 bjh21 Exp $ */
+/* $FreeBSD$ */
+
+/* This is a derivative work. */
+
+/*
+===============================================================================
+
+This C header file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+The macro `FLOATX80' must be defined to enable the extended double-precision
+floating-point format `floatx80'. If this macro is not defined, the
+`floatx80' type will not be defined, and none of the functions that either
+input or output the `floatx80' type will be defined. The same applies to
+the `FLOAT128' macro and the quadruple-precision format `float128'.
+-------------------------------------------------------------------------------
+*/
+/* #define FLOATX80 */
+/* #define FLOAT128 */
+
+#include <machine/ieeefp.h>
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point types.
+-------------------------------------------------------------------------------
+*/
+typedef unsigned int float32;
+typedef unsigned long long float64;
+#ifdef FLOATX80
+typedef struct {
+ unsigned short high;
+ unsigned long long low;
+} floatx80;
+#endif
+#ifdef FLOAT128
+typedef struct {
+ unsigned long long high, low;
+} float128;
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point underflow tininess-detection mode.
+-------------------------------------------------------------------------------
+*/
+#ifndef SOFTFLOAT_FOR_GCC
+extern int8 float_detect_tininess;
+#endif
+enum {
+ float_tininess_after_rounding = 0,
+ float_tininess_before_rounding = 1
+};
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point rounding mode.
+-------------------------------------------------------------------------------
+*/
+extern fp_rnd_t float_rounding_mode;
+enum {
+ float_round_nearest_even = FP_RN,
+ float_round_to_zero = FP_RZ,
+ float_round_down = FP_RM,
+ float_round_up = FP_RP
+};
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point exception flags.
+-------------------------------------------------------------------------------
+*/
+typedef fp_except_t fp_except;
+
+extern fp_except float_exception_flags;
+extern fp_except float_exception_mask;
+enum {
+ float_flag_inexact = FP_X_IMP,
+ float_flag_underflow = FP_X_UFL,
+ float_flag_overflow = FP_X_OFL,
+ float_flag_divbyzero = FP_X_DZ,
+ float_flag_invalid = FP_X_INV
+};
+
+/*
+-------------------------------------------------------------------------------
+Routine to raise any or all of the software IEC/IEEE floating-point
+exception flags.
+-------------------------------------------------------------------------------
+*/
+void float_raise( fp_except );
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE integer-to-floating-point conversion routines.
+-------------------------------------------------------------------------------
+*/
+float32 int32_to_float32( int );
+float64 int32_to_float64( int );
+#ifdef FLOATX80
+floatx80 int32_to_floatx80( int );
+#endif
+#ifdef FLOAT128
+float128 int32_to_float128( int );
+#endif
+float32 int64_to_float32( long long );
+float64 int64_to_float64( long long );
+#ifdef FLOATX80
+floatx80 int64_to_floatx80( long long );
+#endif
+#ifdef FLOAT128
+float128 int64_to_float128( long long );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE single-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float32_to_int32( float32 );
+int float32_to_int32_round_to_zero( float32 );
+unsigned int float32_to_uint32_round_to_zero( float32 );
+long long float32_to_int64( float32 );
+long long float32_to_int64_round_to_zero( float32 );
+float64 float32_to_float64( float32 );
+#ifdef FLOATX80
+floatx80 float32_to_floatx80( float32 );
+#endif
+#ifdef FLOAT128
+float128 float32_to_float128( float32 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE single-precision operations.
+-------------------------------------------------------------------------------
+*/
+float32 float32_round_to_int( float32 );
+float32 float32_add( float32, float32 );
+float32 float32_sub( float32, float32 );
+float32 float32_mul( float32, float32 );
+float32 float32_div( float32, float32 );
+float32 float32_rem( float32, float32 );
+float32 float32_sqrt( float32 );
+int float32_eq( float32, float32 );
+int float32_le( float32, float32 );
+int float32_lt( float32, float32 );
+int float32_eq_signaling( float32, float32 );
+int float32_le_quiet( float32, float32 );
+int float32_lt_quiet( float32, float32 );
+#ifndef SOFTFLOAT_FOR_GCC
+int float32_is_signaling_nan( float32 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE double-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float64_to_int32( float64 );
+int float64_to_int32_round_to_zero( float64 );
+unsigned int float64_to_uint32_round_to_zero( float64 );
+long long float64_to_int64( float64 );
+long long float64_to_int64_round_to_zero( float64 );
+float32 float64_to_float32( float64 );
+#ifdef FLOATX80
+floatx80 float64_to_floatx80( float64 );
+#endif
+#ifdef FLOAT128
+float128 float64_to_float128( float64 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE double-precision operations.
+-------------------------------------------------------------------------------
+*/
+float64 float64_round_to_int( float64 );
+float64 float64_add( float64, float64 );
+float64 float64_sub( float64, float64 );
+float64 float64_mul( float64, float64 );
+float64 float64_div( float64, float64 );
+float64 float64_rem( float64, float64 );
+float64 float64_sqrt( float64 );
+int float64_eq( float64, float64 );
+int float64_le( float64, float64 );
+int float64_lt( float64, float64 );
+int float64_eq_signaling( float64, float64 );
+int float64_le_quiet( float64, float64 );
+int float64_lt_quiet( float64, float64 );
+#ifndef SOFTFLOAT_FOR_GCC
+int float64_is_signaling_nan( float64 );
+#endif
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int floatx80_to_int32( floatx80 );
+int floatx80_to_int32_round_to_zero( floatx80 );
+long long floatx80_to_int64( floatx80 );
+long long floatx80_to_int64_round_to_zero( floatx80 );
+float32 floatx80_to_float32( floatx80 );
+float64 floatx80_to_float64( floatx80 );
+#ifdef FLOAT128
+float128 floatx80_to_float128( floatx80 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision rounding precision. Valid
+values are 32, 64, and 80.
+-------------------------------------------------------------------------------
+*/
+extern int floatx80_rounding_precision;
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision operations.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_round_to_int( floatx80 );
+floatx80 floatx80_add( floatx80, floatx80 );
+floatx80 floatx80_sub( floatx80, floatx80 );
+floatx80 floatx80_mul( floatx80, floatx80 );
+floatx80 floatx80_div( floatx80, floatx80 );
+floatx80 floatx80_rem( floatx80, floatx80 );
+floatx80 floatx80_sqrt( floatx80 );
+int floatx80_eq( floatx80, floatx80 );
+int floatx80_le( floatx80, floatx80 );
+int floatx80_lt( floatx80, floatx80 );
+int floatx80_eq_signaling( floatx80, floatx80 );
+int floatx80_le_quiet( floatx80, floatx80 );
+int floatx80_lt_quiet( floatx80, floatx80 );
+int floatx80_is_signaling_nan( floatx80 );
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE quadruple-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+int float128_to_int32( float128 );
+int float128_to_int32_round_to_zero( float128 );
+long long float128_to_int64( float128 );
+long long float128_to_int64_round_to_zero( float128 );
+float32 float128_to_float32( float128 );
+float64 float128_to_float64( float128 );
+#ifdef FLOATX80
+floatx80 float128_to_floatx80( float128 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE quadruple-precision operations.
+-------------------------------------------------------------------------------
+*/
+float128 float128_round_to_int( float128 );
+float128 float128_add( float128, float128 );
+float128 float128_sub( float128, float128 );
+float128 float128_mul( float128, float128 );
+float128 float128_div( float128, float128 );
+float128 float128_rem( float128, float128 );
+float128 float128_sqrt( float128 );
+int float128_eq( float128, float128 );
+int float128_le( float128, float128 );
+int float128_lt( float128, float128 );
+int float128_eq_signaling( float128, float128 );
+int float128_le_quiet( float128, float128 );
+int float128_lt_quiet( float128, float128 );
+int float128_is_signaling_nan( float128 );
+
+#endif
+
diff --git a/lib/libc/powerpc64/sys/Makefile.inc b/lib/libc/powerpc64/sys/Makefile.inc
new file mode 100644
index 0000000..5193cc2
--- /dev/null
+++ b/lib/libc/powerpc64/sys/Makefile.inc
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+MDASM+= brk.S cerror.S exect.S pipe.S ptrace.S sbrk.S setlogin.S
+
+# Don't generate default code for these syscalls:
+NOASM= break.o exit.o getlogin.o openbsd_poll.o sstk.o yield.o
+
+PSEUDO= _getlogin.o _exit.o
+.if !defined(WITHOUT_SYSCALL_COMPAT)
+PSEUDO+= _pread.o _pwrite.o _lseek.o _mmap.o _ftruncate.o _truncate.o
+.endif
diff --git a/lib/libc/powerpc64/sys/brk.S b/lib/libc/powerpc64/sys/brk.S
new file mode 100644
index 0000000..675b400
--- /dev/null
+++ b/lib/libc/powerpc64/sys/brk.S
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: brk.S,v 1.9 2000/06/26 06:25:43 kleink Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl HIDENAME(curbrk)
+ .globl HIDENAME(minbrk)
+ .globl CNAME(_end)
+
+ .data
+ .align 3
+HIDENAME(minbrk):
+ .llong CNAME(_end)
+
+ .text
+
+ENTRY(brk)
+ addis %r6,%r2,HIDENAME(minbrk)@toc@ha
+ ld %r6,HIDENAME(minbrk)@toc@l(%r6)
+ cmpld %r6,%r3 /* if (minbrk <= r3) */
+ bgt 0f
+ mr %r6,%r3 /* r6 = r3 */
+0:
+ mr %r3,%r6 /* new break value */
+ li %r0,SYS_break
+ sc /* assume, that r5 is kept */
+ bso 1f
+
+ /* record new break */
+ addis %r7,%r2,HIDENAME(curbrk)@toc@ha
+ std %r6,HIDENAME(curbrk)@toc@l(%r7)
+
+ blr /* return 0 */
+
+1:
+ mflr %r0
+ std %r0,16(%r1)
+ stdu %r1,-48(%r1)
+ bl HIDENAME(cerror)
+ nop
+ ld %r1,0(%r1)
+ ld %r0,16(%r1)
+ mtlr %r0
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc64/sys/cerror.S b/lib/libc/powerpc64/sys/cerror.S
new file mode 100644
index 0000000..515d7e5
--- /dev/null
+++ b/lib/libc/powerpc64/sys/cerror.S
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: cerror.S,v 1.5 2000/01/27 14:58:48 kleink Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl HIDENAME(cerror)
+ .globl CNAME(__error)
+
+ /*
+ * The __error() function is thread aware. For non-threaded
+ * programs and the initial threaded in threaded programs,
+ * it returns a pointer to the global errno variable.
+ */
+ENTRY_NOPROF(HIDENAME(cerror))
+ mflr %r0
+ std %r0,16(%r1) /* save lr */
+ stdu %r1,-64(%r1) /* allocate new stack frame */
+ std %r31,48(%r1)
+
+ mr %r31,%r3 /* stash errval in callee-saved register */
+ bl CNAME(__error)
+ nop
+ stw %r31,0(%r3) /* store errval into &errno */
+
+ ld %r31,48(%r1)
+ ld %r1,0(%r1)
+ ld %r0,16(%r1)
+ mtlr %r0
+ li %r3,-1
+ li %r4,-1
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc64/sys/exect.S b/lib/libc/powerpc64/sys/exect.S
new file mode 100644
index 0000000..aa34b9e
--- /dev/null
+++ b/lib/libc/powerpc64/sys/exect.S
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: exect.S,v 1.3 1998/05/25 15:28:03 ws Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ENTRY(exect)
+ li %r0,SYS_execve
+ sc
+ bso 1f
+ blr
+1:
+ mflr %r0
+ std %r0,16(%r1)
+ stdu %r1,-48(%r1)
+ bl HIDENAME(cerror)
+ nop
+ ld %r1,0(%r1)
+ ld %r0,16(%r1)
+ mtlr %r0
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc64/sys/pipe.S b/lib/libc/powerpc64/sys/pipe.S
new file mode 100644
index 0000000..efd3dd6
--- /dev/null
+++ b/lib/libc/powerpc64/sys/pipe.S
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: pipe.S,v 1.6 2000/09/28 08:38:54 kleink Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ENTRY(pipe)
+ mr %r5,%r3 /* save pointer */
+ li %r0,SYS_pipe
+ sc /* r5 is preserved */
+ bso 1f
+ stw %r3,0(%r5) /* success, store fds */
+ stw %r4,4(%r5)
+ li %r3,0
+ blr /* and return 0 */
+1:
+ mflr %r0
+ std %r0,16(%r1)
+ stdu %r1,-48(%r1)
+ bl HIDENAME(cerror)
+ nop
+ ld %r1,0(%r1)
+ ld %r0,16(%r1)
+ mtlr %r0
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc64/sys/ptrace.S b/lib/libc/powerpc64/sys/ptrace.S
new file mode 100644
index 0000000..ede00e7
--- /dev/null
+++ b/lib/libc/powerpc64/sys/ptrace.S
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: ptrace.S,v 1.3 2000/02/23 20:16:57 kleink Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ENTRY(ptrace)
+ mflr %r0
+ std %r0,16(%r1)
+ stdu %r1,-80(%r1)
+ stw %r3,48(%r1)
+ stw %r4,52(%r1)
+ std %r5,56(%r1)
+ stw %r6,64(%r1)
+
+ bl CNAME(__error)
+ nop
+ li %r7,0
+ stw %r7,0(%r3)
+
+ lwz %r3,48(%r1)
+ lwz %r4,52(%r1)
+ ld %r5,56(%r1)
+ lwz %r6,64(%r1)
+ ld %r1,0(%r1)
+ ld %r0,16(%r1)
+ mtlr %r0
+ li %r0,SYS_ptrace
+ sc
+ bso 1f
+ blr
+1:
+ stdu %r1,-48(%r1) /* lr already saved */
+ bl HIDENAME(cerror)
+ nop
+ ld %r1,0(%r1)
+ ld %r0,16(%r1)
+ mtlr %r0
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc64/sys/sbrk.S b/lib/libc/powerpc64/sys/sbrk.S
new file mode 100644
index 0000000..e147493
--- /dev/null
+++ b/lib/libc/powerpc64/sys/sbrk.S
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: sbrk.S,v 1.8 2000/06/26 06:25:44 kleink Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl HIDENAME(curbrk)
+ .globl CNAME(_end)
+
+ .data
+ .align 3
+HIDENAME(curbrk):
+ .llong CNAME(_end)
+
+ .text
+ENTRY(sbrk)
+ addis %r5,%r2,HIDENAME(curbrk)@toc@ha
+ addi %r5,%r5,HIDENAME(curbrk)@toc@l
+ ld %r6,0(%r5) /* r6 = old break */
+ cmpdi %r3,0 /* sbrk(0) - return curbrk */
+ beq 1f
+ add %r3,%r3,%r6
+ mr %r7,%r3 /* r7 = new break */
+ li %r0,SYS_break
+ sc /* break(new_break) */
+ bso 2f
+ std %r7,0(%r5)
+1:
+ mr %r3,%r6 /* set return value */
+ blr
+2:
+ mflr %r0
+ std %r0,16(%r1)
+ stdu %r1,-48(%r1)
+ bl HIDENAME(cerror)
+ nop
+ ld %r1,0(%r1)
+ ld %r0,16(%r1)
+ mtlr %r0
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/powerpc64/sys/setlogin.S b/lib/libc/powerpc64/sys/setlogin.S
new file mode 100644
index 0000000..6183407
--- /dev/null
+++ b/lib/libc/powerpc64/sys/setlogin.S
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2002 Peter Grehan.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/* $NetBSD: setlogin.S,v 1.3 1998/11/24 11:14:57 tsubai Exp $ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl CNAME(_logname_valid) /* in _getlogin() */
+
+SYSCALL(setlogin)
+ addis %r4,%r2,CNAME(_logname_valid)@toc@ha
+ li %r5,0
+ stw %r5,CNAME(_logname_valid)@toc@l(%r4)
+ blr
+
+ .section .note.GNU-stack,"",%progbits
diff --git a/lib/libc/quad/Makefile.inc b/lib/libc/quad/Makefile.inc
new file mode 100644
index 0000000..016fa34
--- /dev/null
+++ b/lib/libc/quad/Makefile.inc
@@ -0,0 +1,21 @@
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+# Quad support, if needed
+.PATH: ${.CURDIR}/${LIBC_ARCH}/quad ${.CURDIR}/quad
+
+.if ${LIBC_ARCH} == "i386"
+
+SRCS+= cmpdi2.c divdi3.c moddi3.c qdivrem.c ucmpdi2.c udivdi3.c umoddi3.c
+
+.else
+
+SRCS+= adddi3.c anddi3.c ashldi3.c ashrdi3.c cmpdi2.c divdi3.c fixdfdi.c \
+ fixsfdi.c fixunsdfdi.c fixunssfdi.c floatdidf.c floatdisf.c \
+ floatunsdidf.c iordi3.c lshldi3.c lshrdi3.c moddi3.c muldi3.c \
+ negdi2.c notdi2.c qdivrem.c subdi3.c ucmpdi2.c udivdi3.c umoddi3.c \
+ xordi3.c
+
+.endif
+
+SYM_MAPS+=${.CURDIR}/quad/Symbol.map
diff --git a/lib/libc/quad/Symbol.map b/lib/libc/quad/Symbol.map
new file mode 100644
index 0000000..82ad940
--- /dev/null
+++ b/lib/libc/quad/Symbol.map
@@ -0,0 +1,38 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ /*
+ * These symbols really shouldn't be exported since they should
+ * be pulled from libgcc, but the build of some applications is
+ * broken and they expect to see them in libc. glibc exports
+ * them, but they do not appear to be exported in Solaris.
+ */
+ __adddi3;
+ __anddi3;
+ __ashldi3;
+ __ashrdi3;
+ __cmpdi2;
+ __divdi3;
+ __fixdfdi;
+ __fixsfdi;
+ __fixunsdfdi;
+ __fixunssfdi;
+ __floatdidf;
+ __floatdisf;
+ __floatunsdidf;
+ __iordi3;
+ __lshldi3;
+ __lshrdi3;
+ __moddi3;
+ __muldi3;
+ __negdi2;
+ __one_cmpldi2;
+ __qdivrem;
+ __subdi3;
+ __ucmpdi2;
+ __udivdi3;
+ __umoddi3;
+ __xordi3;
+};
diff --git a/lib/libc/quad/TESTS/Makefile b/lib/libc/quad/TESTS/Makefile
new file mode 100644
index 0000000..5834f21e
--- /dev/null
+++ b/lib/libc/quad/TESTS/Makefile
@@ -0,0 +1,11 @@
+# @(#)Makefile 8.1 (Berkeley) 6/4/93
+
+all: mul divrem
+
+MUL= mul.c ../muldi3.c
+mul: ${MUL}
+ gcc -g -DSPARC_XXX ${MUL} -o ${.TARGET}
+
+DIVREM= divrem.c ../qdivrem.c
+divrem: ${DIVREM}
+ gcc -g -DSPARC_XXX ${DIVREM} -o ${.TARGET}
diff --git a/lib/libc/quad/TESTS/divrem.c b/lib/libc/quad/TESTS/divrem.c
new file mode 100644
index 0000000..a9471a2e
--- /dev/null
+++ b/lib/libc/quad/TESTS/divrem.c
@@ -0,0 +1,76 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1992, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)divrem.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+
+main()
+{
+ union { long long q; unsigned long v[2]; } a, b, q, r;
+ char buf[300];
+ extern long long __qdivrem(unsigned long long, unsigned long long,
+ unsigned long long *);
+
+ for (;;) {
+ printf("> ");
+ if (fgets(buf, sizeof buf, stdin) == NULL)
+ break;
+ if (sscanf(buf, "%lu:%lu %lu:%lu",
+ &a.v[0], &a.v[1], &b.v[0], &b.v[1]) != 4 &&
+ sscanf(buf, "0x%lx:%lx 0x%lx:%lx",
+ &a.v[0], &a.v[1], &b.v[0], &b.v[1]) != 4) {
+ printf("eh?\n");
+ continue;
+ }
+ q.q = __qdivrem(a.q, b.q, &r.q);
+ printf("%lx:%lx /%% %lx:%lx => q=%lx:%lx r=%lx:%lx\n",
+ a.v[0], a.v[1], b.v[0], b.v[1],
+ q.v[0], q.v[1], r.v[0], r.v[1]);
+ printf(" = %lX%08lX / %lX%08lX => %lX%08lX\n\
+ = %lX%08lX %% %lX%08lX => %lX%08lX\n",
+ a.v[0], a.v[1], b.v[0], b.v[1], q.v[0], q.v[1],
+ a.v[0], a.v[1], b.v[0], b.v[1], r.v[0], r.v[1]);
+ }
+ exit(0);
+}
diff --git a/lib/libc/quad/TESTS/mul.c b/lib/libc/quad/TESTS/mul.c
new file mode 100644
index 0000000..ba543be
--- /dev/null
+++ b/lib/libc/quad/TESTS/mul.c
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef lint
+static char copyright[] =
+"@(#) Copyright (c) 1992, 1993\n\
+ The Regents of the University of California. All rights reserved.\n";
+#endif /* not lint */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)mul.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+
+main()
+{
+ union { long long q; unsigned long v[2]; } a, b, m;
+ char buf[300];
+ extern long long __muldi3(long long, long long);
+
+ for (;;) {
+ printf("> ");
+ if (fgets(buf, sizeof buf, stdin) == NULL)
+ break;
+ if (sscanf(buf, "%lu:%lu %lu:%lu",
+ &a.v[0], &a.v[1], &b.v[0], &b.v[1]) != 4 &&
+ sscanf(buf, "0x%lx:%lx 0x%lx:%lx",
+ &a.v[0], &a.v[1], &b.v[0], &b.v[1]) != 4) {
+ printf("eh?\n");
+ continue;
+ }
+ m.q = __muldi3(a.q, b.q);
+ printf("%lx:%lx * %lx:%lx => %lx:%lx\n",
+ a.v[0], a.v[1], b.v[0], b.v[1], m.v[0], m.v[1]);
+ printf(" = %lX%08lX * %lX%08lX => %lX%08lX\n",
+ a.v[0], a.v[1], b.v[0], b.v[1], m.v[0], m.v[1]);
+ }
+ exit(0);
+}
diff --git a/lib/libc/quad/adddi3.c b/lib/libc/quad/adddi3.c
new file mode 100644
index 0000000..4071221
--- /dev/null
+++ b/lib/libc/quad/adddi3.c
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)adddi3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Add two quads. This is trivial since a one-bit carry from a single
+ * u_long addition x+y occurs if and only if the sum x+y is less than
+ * either x or y (the choice to compare with x or y is arbitrary).
+ */
+quad_t
+__adddi3(a, b)
+ quad_t a, b;
+{
+ union uu aa, bb, sum;
+
+ aa.q = a;
+ bb.q = b;
+ sum.ul[L] = aa.ul[L] + bb.ul[L];
+ sum.ul[H] = aa.ul[H] + bb.ul[H] + (sum.ul[L] < bb.ul[L]);
+ return (sum.q);
+}
diff --git a/lib/libc/quad/anddi3.c b/lib/libc/quad/anddi3.c
new file mode 100644
index 0000000..575a35c
--- /dev/null
+++ b/lib/libc/quad/anddi3.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)anddi3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return a & b, in quad.
+ */
+quad_t
+__anddi3(a, b)
+ quad_t a, b;
+{
+ union uu aa, bb;
+
+ aa.q = a;
+ bb.q = b;
+ aa.ul[0] &= bb.ul[0];
+ aa.ul[1] &= bb.ul[1];
+ return (aa.q);
+}
diff --git a/lib/libc/quad/ashldi3.c b/lib/libc/quad/ashldi3.c
new file mode 100644
index 0000000..c2fd874
--- /dev/null
+++ b/lib/libc/quad/ashldi3.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ashldi3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Shift a (signed) quad value left (arithmetic shift left).
+ * This is the same as logical shift left!
+ */
+quad_t
+__ashldi3(a, shift)
+ quad_t a;
+ qshift_t shift;
+{
+ union uu aa;
+
+ aa.q = a;
+ if (shift >= LONG_BITS) {
+ aa.ul[H] = shift >= QUAD_BITS ? 0 :
+ aa.ul[L] << (shift - LONG_BITS);
+ aa.ul[L] = 0;
+ } else if (shift > 0) {
+ aa.ul[H] = (aa.ul[H] << shift) |
+ (aa.ul[L] >> (LONG_BITS - shift));
+ aa.ul[L] <<= shift;
+ }
+ return (aa.q);
+}
diff --git a/lib/libc/quad/ashrdi3.c b/lib/libc/quad/ashrdi3.c
new file mode 100644
index 0000000..b5b1efd
--- /dev/null
+++ b/lib/libc/quad/ashrdi3.c
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ashrdi3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Shift a (signed) quad value right (arithmetic shift right).
+ */
+quad_t
+__ashrdi3(a, shift)
+ quad_t a;
+ qshift_t shift;
+{
+ union uu aa;
+
+ aa.q = a;
+ if (shift >= LONG_BITS) {
+ long s;
+
+ /*
+ * Smear bits rightward using the machine's right-shift
+ * method, whether that is sign extension or zero fill,
+ * to get the `sign word' s. Note that shifting by
+ * LONG_BITS is undefined, so we shift (LONG_BITS-1),
+ * then 1 more, to get our answer.
+ */
+ s = (aa.sl[H] >> (LONG_BITS - 1)) >> 1;
+ aa.ul[L] = shift >= QUAD_BITS ? s :
+ aa.sl[H] >> (shift - LONG_BITS);
+ aa.ul[H] = s;
+ } else if (shift > 0) {
+ aa.ul[L] = (aa.ul[L] >> shift) |
+ (aa.ul[H] << (LONG_BITS - shift));
+ aa.sl[H] >>= shift;
+ }
+ return (aa.q);
+}
diff --git a/lib/libc/quad/cmpdi2.c b/lib/libc/quad/cmpdi2.c
new file mode 100644
index 0000000..10cb48c
--- /dev/null
+++ b/lib/libc/quad/cmpdi2.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)cmpdi2.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return 0, 1, or 2 as a <, =, > b respectively.
+ * Both a and b are considered signed---which means only the high word is
+ * signed.
+ */
+int
+__cmpdi2(a, b)
+ quad_t a, b;
+{
+ union uu aa, bb;
+
+ aa.q = a;
+ bb.q = b;
+ return (aa.sl[H] < bb.sl[H] ? 0 : aa.sl[H] > bb.sl[H] ? 2 :
+ aa.ul[L] < bb.ul[L] ? 0 : aa.ul[L] > bb.ul[L] ? 2 : 1);
+}
diff --git a/lib/libc/quad/divdi3.c b/lib/libc/quad/divdi3.c
new file mode 100644
index 0000000..4142056
--- /dev/null
+++ b/lib/libc/quad/divdi3.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)divdi3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Divide two signed quads.
+ * ??? if -1/2 should produce -1 on this machine, this code is wrong
+ */
+quad_t
+__divdi3(a, b)
+ quad_t a, b;
+{
+ u_quad_t ua, ub, uq;
+ int neg;
+
+ if (a < 0)
+ ua = -(u_quad_t)a, neg = 1;
+ else
+ ua = a, neg = 0;
+ if (b < 0)
+ ub = -(u_quad_t)b, neg ^= 1;
+ else
+ ub = b;
+ uq = __qdivrem(ua, ub, (u_quad_t *)0);
+ return (neg ? -uq : uq);
+}
diff --git a/lib/libc/quad/fixdfdi.c b/lib/libc/quad/fixdfdi.c
new file mode 100644
index 0000000..2e3c18d
--- /dev/null
+++ b/lib/libc/quad/fixdfdi.c
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fixdfdi.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Convert double to (signed) quad.
+ * We clamp anything that is out of range.
+ */
+quad_t
+__fixdfdi(x)
+ double x;
+{
+ if (x < 0)
+ if (x <= QUAD_MIN)
+ return (QUAD_MIN);
+ else
+ return ((quad_t)-(u_quad_t)-x);
+ else
+ if (x >= QUAD_MAX)
+ return (QUAD_MAX);
+ else
+ return ((quad_t)(u_quad_t)x);
+}
diff --git a/lib/libc/quad/fixsfdi.c b/lib/libc/quad/fixsfdi.c
new file mode 100644
index 0000000..15ab68b
--- /dev/null
+++ b/lib/libc/quad/fixsfdi.c
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 1992 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fixsfdi.c 5.1 (Berkeley) 7/7/92";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Convert float to (signed) quad.
+ * We clamp anything that is out of range.
+ *
+ * N.B.: must use new ANSI syntax (sorry).
+ */
+long long
+__fixsfdi(float x)
+{
+ if (x < 0)
+ if (x <= QUAD_MIN)
+ return (QUAD_MIN);
+ else
+ return ((quad_t)-(u_quad_t)-x);
+ else
+ if (x >= QUAD_MAX)
+ return (QUAD_MAX);
+ else
+ return ((quad_t)(u_quad_t)x);
+}
diff --git a/lib/libc/quad/fixunsdfdi.c b/lib/libc/quad/fixunsdfdi.c
new file mode 100644
index 0000000..7b6c05e
--- /dev/null
+++ b/lib/libc/quad/fixunsdfdi.c
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fixunsdfdi.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+#define ONE_FOURTH (1 << (LONG_BITS - 2))
+#define ONE_HALF (ONE_FOURTH * 2.0)
+#define ONE (ONE_FOURTH * 4.0)
+
+/*
+ * Convert double to (unsigned) quad.
+ * Not sure what to do with negative numbers---for now, anything out
+ * of range becomes UQUAD_MAX.
+ */
+u_quad_t
+__fixunsdfdi(x)
+ double x;
+{
+ double toppart;
+ union uu t;
+
+ if (x < 0)
+ return (UQUAD_MAX); /* ??? should be 0? ERANGE??? */
+#ifdef notdef /* this falls afoul of a GCC bug */
+ if (x >= UQUAD_MAX)
+ return (UQUAD_MAX);
+#else /* so we wire in 2^64-1 instead */
+ if (x >= 18446744073709551615.0)
+ return (UQUAD_MAX);
+#endif
+ /*
+ * Get the upper part of the result. Note that the divide
+ * may round up; we want to avoid this if possible, so we
+ * subtract `1/2' first.
+ */
+ toppart = (x - ONE_HALF) / ONE;
+ /*
+ * Now build a u_quad_t out of the top part. The difference
+ * between x and this is the bottom part (this may introduce
+ * a few fuzzy bits, but what the heck). With any luck this
+ * difference will be nonnegative: x should wind up in the
+ * range [0..ULONG_MAX]. For paranoia, we assume [LONG_MIN..
+ * 2*ULONG_MAX] instead.
+ */
+ t.ul[H] = (unsigned long)toppart;
+ t.ul[L] = 0;
+ x -= (double)t.uq;
+ if (x < 0) {
+ t.ul[H]--;
+ x += ULONG_MAX;
+ }
+ if (x > ULONG_MAX) {
+ t.ul[H]++;
+ x -= ULONG_MAX;
+ }
+ t.ul[L] = (u_long)x;
+ return (t.uq);
+}
diff --git a/lib/libc/quad/fixunssfdi.c b/lib/libc/quad/fixunssfdi.c
new file mode 100644
index 0000000..9b13c79
--- /dev/null
+++ b/lib/libc/quad/fixunssfdi.c
@@ -0,0 +1,98 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fixunssfdi.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+#define ONE_FOURTH (1 << (LONG_BITS - 2))
+#define ONE_HALF (ONE_FOURTH * 2.0)
+#define ONE (ONE_FOURTH * 4.0)
+
+/*
+ * Convert float to (unsigned) quad. We do most of our work in double,
+ * out of sheer paranoia.
+ *
+ * Not sure what to do with negative numbers---for now, anything out
+ * of range becomes UQUAD_MAX.
+ *
+ * N.B.: must use new ANSI syntax (sorry).
+ */
+u_quad_t
+__fixunssfdi(float f)
+{
+ double x, toppart;
+ union uu t;
+
+ if (f < 0)
+ return (UQUAD_MAX); /* ??? should be 0? ERANGE??? */
+#ifdef notdef /* this falls afoul of a GCC bug */
+ if (f >= UQUAD_MAX)
+ return (UQUAD_MAX);
+#else /* so we wire in 2^64-1 instead */
+ if (f >= 18446744073709551615.0)
+ return (UQUAD_MAX);
+#endif
+ x = f;
+ /*
+ * Get the upper part of the result. Note that the divide
+ * may round up; we want to avoid this if possible, so we
+ * subtract `1/2' first.
+ */
+ toppart = (x - ONE_HALF) / ONE;
+ /*
+ * Now build a u_quad_t out of the top part. The difference
+ * between x and this is the bottom part (this may introduce
+ * a few fuzzy bits, but what the heck). With any luck this
+ * difference will be nonnegative: x should wind up in the
+ * range [0..ULONG_MAX]. For paranoia, we assume [LONG_MIN..
+ * 2*ULONG_MAX] instead.
+ */
+ t.ul[H] = (unsigned long)toppart;
+ t.ul[L] = 0;
+ x -= (double)t.uq;
+ if (x < 0) {
+ t.ul[H]--;
+ x += ULONG_MAX;
+ }
+ if (x > ULONG_MAX) {
+ t.ul[H]++;
+ x -= ULONG_MAX;
+ }
+ t.ul[L] = (u_long)x;
+ return (t.uq);
+}
diff --git a/lib/libc/quad/floatdidf.c b/lib/libc/quad/floatdidf.c
new file mode 100644
index 0000000..7167715
--- /dev/null
+++ b/lib/libc/quad/floatdidf.c
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)floatdidf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Convert (signed) quad to double.
+ */
+double
+__floatdidf(x)
+ quad_t x;
+{
+ double d;
+ union uu u;
+ int neg;
+
+ /*
+ * Get an unsigned number first, by negating if necessary.
+ */
+ if (x < 0)
+ u.q = -x, neg = 1;
+ else
+ u.q = x, neg = 0;
+
+ /*
+ * Now u.ul[H] has the factor of 2^32 (or whatever) and u.ul[L]
+ * has the units. Ideally we could just set d, add LONG_BITS to
+ * its exponent, and then add the units, but this is portable
+ * code and does not know how to get at an exponent. Machine-
+ * specific code may be able to do this more efficiently.
+ */
+ d = (double)u.ul[H] * ((1 << (LONG_BITS - 2)) * 4.0);
+ d += u.ul[L];
+
+ return (neg ? -d : d);
+}
diff --git a/lib/libc/quad/floatdisf.c b/lib/libc/quad/floatdisf.c
new file mode 100644
index 0000000..0cf7af8
--- /dev/null
+++ b/lib/libc/quad/floatdisf.c
@@ -0,0 +1,74 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)floatdisf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Convert (signed) quad to float.
+ */
+float
+__floatdisf(x)
+ quad_t x;
+{
+ float f;
+ union uu u;
+ int neg;
+
+ /*
+ * Get an unsigned number first, by negating if necessary.
+ */
+ if (x < 0)
+ u.q = -x, neg = 1;
+ else
+ u.q = x, neg = 0;
+
+ /*
+ * Now u.ul[H] has the factor of 2^32 (or whatever) and u.ul[L]
+ * has the units. Ideally we could just set f, add LONG_BITS to
+ * its exponent, and then add the units, but this is portable
+ * code and does not know how to get at an exponent. Machine-
+ * specific code may be able to do this more efficiently.
+ *
+ * Using double here may be excessive paranoia.
+ */
+ f = (double)u.ul[H] * ((1 << (LONG_BITS - 2)) * 4.0);
+ f += u.ul[L];
+
+ return (neg ? -f : f);
+}
diff --git a/lib/libc/quad/floatunsdidf.c b/lib/libc/quad/floatunsdidf.c
new file mode 100644
index 0000000..264cd62
--- /dev/null
+++ b/lib/libc/quad/floatunsdidf.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)floatunsdidf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Convert (unsigned) quad to double.
+ * This is exactly like floatdidf.c except that negatives never occur.
+ */
+double
+__floatunsdidf(x)
+ u_quad_t x;
+{
+ double d;
+ union uu u;
+
+ u.uq = x;
+ d = (double)u.ul[H] * ((1 << (LONG_BITS - 2)) * 4.0);
+ d += u.ul[L];
+ return (d);
+}
diff --git a/lib/libc/quad/iordi3.c b/lib/libc/quad/iordi3.c
new file mode 100644
index 0000000..5f4c67c
--- /dev/null
+++ b/lib/libc/quad/iordi3.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)iordi3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return a | b, in quad.
+ */
+quad_t
+__iordi3(a, b)
+ quad_t a, b;
+{
+ union uu aa, bb;
+
+ aa.q = a;
+ bb.q = b;
+ aa.ul[0] |= bb.ul[0];
+ aa.ul[1] |= bb.ul[1];
+ return (aa.q);
+}
diff --git a/lib/libc/quad/lshldi3.c b/lib/libc/quad/lshldi3.c
new file mode 100644
index 0000000..56fb059
--- /dev/null
+++ b/lib/libc/quad/lshldi3.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)lshldi3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Shift an (unsigned) quad value left (logical shift left).
+ * This is the same as arithmetic shift left!
+ */
+quad_t
+__lshldi3(a, shift)
+ quad_t a;
+ qshift_t shift;
+{
+ union uu aa;
+
+ aa.q = a;
+ if (shift >= LONG_BITS) {
+ aa.ul[H] = shift >= QUAD_BITS ? 0 :
+ aa.ul[L] << (shift - LONG_BITS);
+ aa.ul[L] = 0;
+ } else if (shift > 0) {
+ aa.ul[H] = (aa.ul[H] << shift) |
+ (aa.ul[L] >> (LONG_BITS - shift));
+ aa.ul[L] <<= shift;
+ }
+ return (aa.q);
+}
diff --git a/lib/libc/quad/lshrdi3.c b/lib/libc/quad/lshrdi3.c
new file mode 100644
index 0000000..4fc9362
--- /dev/null
+++ b/lib/libc/quad/lshrdi3.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)lshrdi3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Shift an (unsigned) quad value right (logical shift right).
+ */
+quad_t
+__lshrdi3(a, shift)
+ quad_t a;
+ qshift_t shift;
+{
+ union uu aa;
+
+ aa.q = a;
+ if (shift >= LONG_BITS) {
+ aa.ul[L] = shift >= QUAD_BITS ? 0 :
+ aa.ul[H] >> (shift - LONG_BITS);
+ aa.ul[H] = 0;
+ } else if (shift > 0) {
+ aa.ul[L] = (aa.ul[L] >> shift) |
+ (aa.ul[H] << (LONG_BITS - shift));
+ aa.ul[H] >>= shift;
+ }
+ return (aa.q);
+}
diff --git a/lib/libc/quad/moddi3.c b/lib/libc/quad/moddi3.c
new file mode 100644
index 0000000..9dbf1c3
--- /dev/null
+++ b/lib/libc/quad/moddi3.c
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)moddi3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two signed quads.
+ *
+ * XXX
+ * If -1/2 should produce -1 on this machine, this code is wrong.
+ */
+quad_t
+__moddi3(a, b)
+ quad_t a, b;
+{
+ u_quad_t ua, ub, ur;
+ int neg;
+
+ if (a < 0)
+ ua = -(u_quad_t)a, neg = 1;
+ else
+ ua = a, neg = 0;
+ if (b < 0)
+ ub = -(u_quad_t)b;
+ else
+ ub = b;
+ (void)__qdivrem(ua, ub, &ur);
+ return (neg ? -ur : ur);
+}
diff --git a/lib/libc/quad/muldi3.c b/lib/libc/quad/muldi3.c
new file mode 100644
index 0000000..05c84b9
--- /dev/null
+++ b/lib/libc/quad/muldi3.c
@@ -0,0 +1,244 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)muldi3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Multiply two quads.
+ *
+ * Our algorithm is based on the following. Split incoming quad values
+ * u and v (where u,v >= 0) into
+ *
+ * u = 2^n u1 * u0 (n = number of bits in `u_long', usu. 32)
+ *
+ * and
+ *
+ * v = 2^n v1 * v0
+ *
+ * Then
+ *
+ * uv = 2^2n u1 v1 + 2^n u1 v0 + 2^n v1 u0 + u0 v0
+ * = 2^2n u1 v1 + 2^n (u1 v0 + v1 u0) + u0 v0
+ *
+ * Now add 2^n u1 v1 to the first term and subtract it from the middle,
+ * and add 2^n u0 v0 to the last term and subtract it from the middle.
+ * This gives:
+ *
+ * uv = (2^2n + 2^n) (u1 v1) +
+ * (2^n) (u1 v0 - u1 v1 + u0 v1 - u0 v0) +
+ * (2^n + 1) (u0 v0)
+ *
+ * Factoring the middle a bit gives us:
+ *
+ * uv = (2^2n + 2^n) (u1 v1) + [u1v1 = high]
+ * (2^n) (u1 - u0) (v0 - v1) + [(u1-u0)... = mid]
+ * (2^n + 1) (u0 v0) [u0v0 = low]
+ *
+ * The terms (u1 v1), (u1 - u0) (v0 - v1), and (u0 v0) can all be done
+ * in just half the precision of the original. (Note that either or both
+ * of (u1 - u0) or (v0 - v1) may be negative.)
+ *
+ * This algorithm is from Knuth vol. 2 (2nd ed), section 4.3.3, p. 278.
+ *
+ * Since C does not give us a `long * long = quad' operator, we split
+ * our input quads into two longs, then split the two longs into two
+ * shorts. We can then calculate `short * short = long' in native
+ * arithmetic.
+ *
+ * Our product should, strictly speaking, be a `long quad', with 128
+ * bits, but we are going to discard the upper 64. In other words,
+ * we are not interested in uv, but rather in (uv mod 2^2n). This
+ * makes some of the terms above vanish, and we get:
+ *
+ * (2^n)(high) + (2^n)(mid) + (2^n + 1)(low)
+ *
+ * or
+ *
+ * (2^n)(high + mid + low) + low
+ *
+ * Furthermore, `high' and `mid' can be computed mod 2^n, as any factor
+ * of 2^n in either one will also vanish. Only `low' need be computed
+ * mod 2^2n, and only because of the final term above.
+ */
+static quad_t __lmulq(u_long, u_long);
+
+quad_t
+__muldi3(a, b)
+ quad_t a, b;
+{
+ union uu u, v, low, prod;
+ u_long high, mid, udiff, vdiff;
+ int negall, negmid;
+#define u1 u.ul[H]
+#define u0 u.ul[L]
+#define v1 v.ul[H]
+#define v0 v.ul[L]
+
+ /*
+ * Get u and v such that u, v >= 0. When this is finished,
+ * u1, u0, v1, and v0 will be directly accessible through the
+ * longword fields.
+ */
+ if (a >= 0)
+ u.q = a, negall = 0;
+ else
+ u.q = -a, negall = 1;
+ if (b >= 0)
+ v.q = b;
+ else
+ v.q = -b, negall ^= 1;
+
+ if (u1 == 0 && v1 == 0) {
+ /*
+ * An (I hope) important optimization occurs when u1 and v1
+ * are both 0. This should be common since most numbers
+ * are small. Here the product is just u0*v0.
+ */
+ prod.q = __lmulq(u0, v0);
+ } else {
+ /*
+ * Compute the three intermediate products, remembering
+ * whether the middle term is negative. We can discard
+ * any upper bits in high and mid, so we can use native
+ * u_long * u_long => u_long arithmetic.
+ */
+ low.q = __lmulq(u0, v0);
+
+ if (u1 >= u0)
+ negmid = 0, udiff = u1 - u0;
+ else
+ negmid = 1, udiff = u0 - u1;
+ if (v0 >= v1)
+ vdiff = v0 - v1;
+ else
+ vdiff = v1 - v0, negmid ^= 1;
+ mid = udiff * vdiff;
+
+ high = u1 * v1;
+
+ /*
+ * Assemble the final product.
+ */
+ prod.ul[H] = high + (negmid ? -mid : mid) + low.ul[L] +
+ low.ul[H];
+ prod.ul[L] = low.ul[L];
+ }
+ return (negall ? -prod.q : prod.q);
+#undef u1
+#undef u0
+#undef v1
+#undef v0
+}
+
+/*
+ * Multiply two 2N-bit longs to produce a 4N-bit quad, where N is half
+ * the number of bits in a long (whatever that is---the code below
+ * does not care as long as quad.h does its part of the bargain---but
+ * typically N==16).
+ *
+ * We use the same algorithm from Knuth, but this time the modulo refinement
+ * does not apply. On the other hand, since N is half the size of a long,
+ * we can get away with native multiplication---none of our input terms
+ * exceeds (ULONG_MAX >> 1).
+ *
+ * Note that, for u_long l, the quad-precision result
+ *
+ * l << N
+ *
+ * splits into high and low longs as HHALF(l) and LHUP(l) respectively.
+ */
+static quad_t
+__lmulq(u_long u, u_long v)
+{
+ u_long u1, u0, v1, v0, udiff, vdiff, high, mid, low;
+ u_long prodh, prodl, was;
+ union uu prod;
+ int neg;
+
+ u1 = HHALF(u);
+ u0 = LHALF(u);
+ v1 = HHALF(v);
+ v0 = LHALF(v);
+
+ low = u0 * v0;
+
+ /* This is the same small-number optimization as before. */
+ if (u1 == 0 && v1 == 0)
+ return (low);
+
+ if (u1 >= u0)
+ udiff = u1 - u0, neg = 0;
+ else
+ udiff = u0 - u1, neg = 1;
+ if (v0 >= v1)
+ vdiff = v0 - v1;
+ else
+ vdiff = v1 - v0, neg ^= 1;
+ mid = udiff * vdiff;
+
+ high = u1 * v1;
+
+ /* prod = (high << 2N) + (high << N); */
+ prodh = high + HHALF(high);
+ prodl = LHUP(high);
+
+ /* if (neg) prod -= mid << N; else prod += mid << N; */
+ if (neg) {
+ was = prodl;
+ prodl -= LHUP(mid);
+ prodh -= HHALF(mid) + (prodl > was);
+ } else {
+ was = prodl;
+ prodl += LHUP(mid);
+ prodh += HHALF(mid) + (prodl < was);
+ }
+
+ /* prod += low << N */
+ was = prodl;
+ prodl += LHUP(low);
+ prodh += HHALF(low) + (prodl < was);
+ /* ... + low; */
+ if ((prodl += low) < low)
+ prodh++;
+
+ /* return 4N-bit product */
+ prod.ul[H] = prodh;
+ prod.ul[L] = prodl;
+ return (prod.q);
+}
diff --git a/lib/libc/quad/negdi2.c b/lib/libc/quad/negdi2.c
new file mode 100644
index 0000000..6af1ea9
--- /dev/null
+++ b/lib/libc/quad/negdi2.c
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)negdi2.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return -a (or, equivalently, 0 - a), in quad. See subdi3.c.
+ */
+quad_t
+__negdi2(a)
+ quad_t a;
+{
+ union uu aa, res;
+
+ aa.q = a;
+ res.ul[L] = -aa.ul[L];
+ res.ul[H] = -aa.ul[H] - (res.ul[L] > 0);
+ return (res.q);
+}
diff --git a/lib/libc/quad/notdi2.c b/lib/libc/quad/notdi2.c
new file mode 100644
index 0000000..b5480bc
--- /dev/null
+++ b/lib/libc/quad/notdi2.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)notdi2.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return ~a. For some reason gcc calls this `one's complement' rather
+ * than `not'.
+ */
+quad_t
+__one_cmpldi2(a)
+ quad_t a;
+{
+ union uu aa;
+
+ aa.q = a;
+ aa.ul[0] = ~aa.ul[0];
+ aa.ul[1] = ~aa.ul[1];
+ return (aa.q);
+}
diff --git a/lib/libc/quad/qdivrem.c b/lib/libc/quad/qdivrem.c
new file mode 100644
index 0000000..e8e3c98
--- /dev/null
+++ b/lib/libc/quad/qdivrem.c
@@ -0,0 +1,277 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)qdivrem.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Multiprecision divide. This algorithm is from Knuth vol. 2 (2nd ed),
+ * section 4.3.1, pp. 257--259.
+ */
+
+#include "quad.h"
+
+#define B (1 << HALF_BITS) /* digit base */
+
+/* Combine two `digits' to make a single two-digit number. */
+#define COMBINE(a, b) (((u_long)(a) << HALF_BITS) | (b))
+
+/* select a type for digits in base B: use unsigned short if they fit */
+#if ULONG_MAX == 0xffffffff && USHRT_MAX >= 0xffff
+typedef unsigned short digit;
+#else
+typedef u_long digit;
+#endif
+
+/*
+ * Shift p[0]..p[len] left `sh' bits, ignoring any bits that
+ * `fall out' the left (there never will be any such anyway).
+ * We may assume len >= 0. NOTE THAT THIS WRITES len+1 DIGITS.
+ */
+static void
+shl(digit *p, int len, int sh)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ p[i] = LHALF(p[i] << sh) | (p[i + 1] >> (HALF_BITS - sh));
+ p[i] = LHALF(p[i] << sh);
+}
+
+/*
+ * __qdivrem(u, v, rem) returns u/v and, optionally, sets *rem to u%v.
+ *
+ * We do this in base 2-sup-HALF_BITS, so that all intermediate products
+ * fit within u_long. As a consequence, the maximum length dividend and
+ * divisor are 4 `digits' in this base (they are shorter if they have
+ * leading zeros).
+ */
+u_quad_t
+__qdivrem(uq, vq, arq)
+ u_quad_t uq, vq, *arq;
+{
+ union uu tmp;
+ digit *u, *v, *q;
+ digit v1, v2;
+ u_long qhat, rhat, t;
+ int m, n, d, j, i;
+ digit uspace[5], vspace[5], qspace[5];
+
+ /*
+ * Take care of special cases: divide by zero, and u < v.
+ */
+ if (vq == 0) {
+ /* divide by zero. */
+ static volatile const unsigned int zero = 0;
+
+ tmp.ul[H] = tmp.ul[L] = 1 / zero;
+ if (arq)
+ *arq = uq;
+ return (tmp.q);
+ }
+ if (uq < vq) {
+ if (arq)
+ *arq = uq;
+ return (0);
+ }
+ u = &uspace[0];
+ v = &vspace[0];
+ q = &qspace[0];
+
+ /*
+ * Break dividend and divisor into digits in base B, then
+ * count leading zeros to determine m and n. When done, we
+ * will have:
+ * u = (u[1]u[2]...u[m+n]) sub B
+ * v = (v[1]v[2]...v[n]) sub B
+ * v[1] != 0
+ * 1 < n <= 4 (if n = 1, we use a different division algorithm)
+ * m >= 0 (otherwise u < v, which we already checked)
+ * m + n = 4
+ * and thus
+ * m = 4 - n <= 2
+ */
+ tmp.uq = uq;
+ u[0] = 0;
+ u[1] = HHALF(tmp.ul[H]);
+ u[2] = LHALF(tmp.ul[H]);
+ u[3] = HHALF(tmp.ul[L]);
+ u[4] = LHALF(tmp.ul[L]);
+ tmp.uq = vq;
+ v[1] = HHALF(tmp.ul[H]);
+ v[2] = LHALF(tmp.ul[H]);
+ v[3] = HHALF(tmp.ul[L]);
+ v[4] = LHALF(tmp.ul[L]);
+ for (n = 4; v[1] == 0; v++) {
+ if (--n == 1) {
+ u_long rbj; /* r*B+u[j] (not root boy jim) */
+ digit q1, q2, q3, q4;
+
+ /*
+ * Change of plan, per exercise 16.
+ * r = 0;
+ * for j = 1..4:
+ * q[j] = floor((r*B + u[j]) / v),
+ * r = (r*B + u[j]) % v;
+ * We unroll this completely here.
+ */
+ t = v[2]; /* nonzero, by definition */
+ q1 = u[1] / t;
+ rbj = COMBINE(u[1] % t, u[2]);
+ q2 = rbj / t;
+ rbj = COMBINE(rbj % t, u[3]);
+ q3 = rbj / t;
+ rbj = COMBINE(rbj % t, u[4]);
+ q4 = rbj / t;
+ if (arq)
+ *arq = rbj % t;
+ tmp.ul[H] = COMBINE(q1, q2);
+ tmp.ul[L] = COMBINE(q3, q4);
+ return (tmp.q);
+ }
+ }
+
+ /*
+ * By adjusting q once we determine m, we can guarantee that
+ * there is a complete four-digit quotient at &qspace[1] when
+ * we finally stop.
+ */
+ for (m = 4 - n; u[1] == 0; u++)
+ m--;
+ for (i = 4 - m; --i >= 0;)
+ q[i] = 0;
+ q += 4 - m;
+
+ /*
+ * Here we run Program D, translated from MIX to C and acquiring
+ * a few minor changes.
+ *
+ * D1: choose multiplier 1 << d to ensure v[1] >= B/2.
+ */
+ d = 0;
+ for (t = v[1]; t < B / 2; t <<= 1)
+ d++;
+ if (d > 0) {
+ shl(&u[0], m + n, d); /* u <<= d */
+ shl(&v[1], n - 1, d); /* v <<= d */
+ }
+ /*
+ * D2: j = 0.
+ */
+ j = 0;
+ v1 = v[1]; /* for D3 -- note that v[1..n] are constant */
+ v2 = v[2]; /* for D3 */
+ do {
+ digit uj0, uj1, uj2;
+
+ /*
+ * D3: Calculate qhat (\^q, in TeX notation).
+ * Let qhat = min((u[j]*B + u[j+1])/v[1], B-1), and
+ * let rhat = (u[j]*B + u[j+1]) mod v[1].
+ * While rhat < B and v[2]*qhat > rhat*B+u[j+2],
+ * decrement qhat and increase rhat correspondingly.
+ * Note that if rhat >= B, v[2]*qhat < rhat*B.
+ */
+ uj0 = u[j + 0]; /* for D3 only -- note that u[j+...] change */
+ uj1 = u[j + 1]; /* for D3 only */
+ uj2 = u[j + 2]; /* for D3 only */
+ if (uj0 == v1) {
+ qhat = B;
+ rhat = uj1;
+ goto qhat_too_big;
+ } else {
+ u_long n = COMBINE(uj0, uj1);
+ qhat = n / v1;
+ rhat = n % v1;
+ }
+ while (v2 * qhat > COMBINE(rhat, uj2)) {
+ qhat_too_big:
+ qhat--;
+ if ((rhat += v1) >= B)
+ break;
+ }
+ /*
+ * D4: Multiply and subtract.
+ * The variable `t' holds any borrows across the loop.
+ * We split this up so that we do not require v[0] = 0,
+ * and to eliminate a final special case.
+ */
+ for (t = 0, i = n; i > 0; i--) {
+ t = u[i + j] - v[i] * qhat - t;
+ u[i + j] = LHALF(t);
+ t = (B - HHALF(t)) & (B - 1);
+ }
+ t = u[j] - t;
+ u[j] = LHALF(t);
+ /*
+ * D5: test remainder.
+ * There is a borrow if and only if HHALF(t) is nonzero;
+ * in that (rare) case, qhat was too large (by exactly 1).
+ * Fix it by adding v[1..n] to u[j..j+n].
+ */
+ if (HHALF(t)) {
+ qhat--;
+ for (t = 0, i = n; i > 0; i--) { /* D6: add back. */
+ t += u[i + j] + v[i];
+ u[i + j] = LHALF(t);
+ t = HHALF(t);
+ }
+ u[j] = LHALF(u[j] + t);
+ }
+ q[j] = qhat;
+ } while (++j <= m); /* D7: loop on j. */
+
+ /*
+ * If caller wants the remainder, we have to calculate it as
+ * u[m..m+n] >> d (this is at most n digits and thus fits in
+ * u[m+1..m+n], but we may need more source digits).
+ */
+ if (arq) {
+ if (d) {
+ for (i = m + n; i > m; --i)
+ u[i] = (u[i] >> d) |
+ LHALF(u[i - 1] << (HALF_BITS - d));
+ u[i] = 0;
+ }
+ tmp.ul[H] = COMBINE(uspace[1], uspace[2]);
+ tmp.ul[L] = COMBINE(uspace[3], uspace[4]);
+ *arq = tmp.q;
+ }
+
+ tmp.ul[H] = COMBINE(qspace[1], qspace[2]);
+ tmp.ul[L] = COMBINE(qspace[3], qspace[4]);
+ return (tmp.q);
+}
diff --git a/lib/libc/quad/quad.h b/lib/libc/quad/quad.h
new file mode 100644
index 0000000..d496fc6
--- /dev/null
+++ b/lib/libc/quad/quad.h
@@ -0,0 +1,103 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)quad.h 8.1 (Berkeley) 6/4/93
+ * $FreeBSD$
+ */
+
+/*
+ * Quad arithmetic.
+ *
+ * This library makes the following assumptions:
+ *
+ * - The type long long (aka quad_t) exists.
+ *
+ * - A quad variable is exactly twice as long as `long'.
+ *
+ * - The machine's arithmetic is two's complement.
+ *
+ * This library can provide 128-bit arithmetic on a machine with 128-bit
+ * quads and 64-bit longs, for instance, or 96-bit arithmetic on machines
+ * with 48-bit longs.
+ */
+
+#include <sys/types.h>
+#include <limits.h>
+
+/*
+ * Depending on the desired operation, we view a `long long' (aka quad_t) in
+ * one or more of the following formats.
+ */
+union uu {
+ quad_t q; /* as a (signed) quad */
+ quad_t uq; /* as an unsigned quad */
+ long sl[2]; /* as two signed longs */
+ u_long ul[2]; /* as two unsigned longs */
+};
+
+/*
+ * Define high and low longwords.
+ */
+#define H _QUAD_HIGHWORD
+#define L _QUAD_LOWWORD
+
+/*
+ * Total number of bits in a quad_t and in the pieces that make it up.
+ * These are used for shifting, and also below for halfword extraction
+ * and assembly.
+ */
+#define QUAD_BITS (sizeof(quad_t) * CHAR_BIT)
+#define LONG_BITS (sizeof(long) * CHAR_BIT)
+#define HALF_BITS (sizeof(long) * CHAR_BIT / 2)
+
+/*
+ * Extract high and low shortwords from longword, and move low shortword of
+ * longword to upper half of long, i.e., produce the upper longword of
+ * ((quad_t)(x) << (number_of_bits_in_long/2)). (`x' must actually be u_long.)
+ *
+ * These are used in the multiply code, to split a longword into upper
+ * and lower halves, and to reassemble a product as a quad_t, shifted left
+ * (sizeof(long)*CHAR_BIT/2).
+ */
+#define HHALF(x) ((x) >> HALF_BITS)
+#define LHALF(x) ((x) & ((1 << HALF_BITS) - 1))
+#define LHUP(x) ((x) << HALF_BITS)
+
+int __cmpdi2(quad_t a, quad_t b);
+quad_t __divdi3(quad_t a, quad_t b);
+quad_t __moddi3(quad_t a, quad_t b);
+u_quad_t __qdivrem(u_quad_t u, u_quad_t v, u_quad_t *rem);
+int __ucmpdi2(u_quad_t a, u_quad_t b);
+u_quad_t __udivdi3(u_quad_t a, u_quad_t b);
+u_quad_t __umoddi3(u_quad_t a, u_quad_t b);
+
+typedef unsigned int qshift_t;
diff --git a/lib/libc/quad/subdi3.c b/lib/libc/quad/subdi3.c
new file mode 100644
index 0000000..b31f040
--- /dev/null
+++ b/lib/libc/quad/subdi3.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)subdi3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Subtract two quad values. This is trivial since a one-bit carry
+ * from a single u_long difference x-y occurs if and only if (x-y) > x.
+ */
+quad_t
+__subdi3(a, b)
+ quad_t a, b;
+{
+ union uu aa, bb, diff;
+
+ aa.q = a;
+ bb.q = b;
+ diff.ul[L] = aa.ul[L] - bb.ul[L];
+ diff.ul[H] = aa.ul[H] - bb.ul[H] - (diff.ul[L] > aa.ul[L]);
+ return (diff.q);
+}
diff --git a/lib/libc/quad/ucmpdi2.c b/lib/libc/quad/ucmpdi2.c
new file mode 100644
index 0000000..6605896
--- /dev/null
+++ b/lib/libc/quad/ucmpdi2.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ucmpdi2.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return 0, 1, or 2 as a <, =, > b respectively.
+ * Neither a nor b are considered signed.
+ */
+int
+__ucmpdi2(a, b)
+ u_quad_t a, b;
+{
+ union uu aa, bb;
+
+ aa.uq = a;
+ bb.uq = b;
+ return (aa.ul[H] < bb.ul[H] ? 0 : aa.ul[H] > bb.ul[H] ? 2 :
+ aa.ul[L] < bb.ul[L] ? 0 : aa.ul[L] > bb.ul[L] ? 2 : 1);
+}
diff --git a/lib/libc/quad/udivdi3.c b/lib/libc/quad/udivdi3.c
new file mode 100644
index 0000000..8b5a788
--- /dev/null
+++ b/lib/libc/quad/udivdi3.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)udivdi3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Divide two unsigned quads.
+ */
+u_quad_t
+__udivdi3(a, b)
+ u_quad_t a, b;
+{
+
+ return (__qdivrem(a, b, (u_quad_t *)0));
+}
diff --git a/lib/libc/quad/umoddi3.c b/lib/libc/quad/umoddi3.c
new file mode 100644
index 0000000..29ce2cb
--- /dev/null
+++ b/lib/libc/quad/umoddi3.c
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)umoddi3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return remainder after dividing two unsigned quads.
+ */
+u_quad_t
+__umoddi3(a, b)
+ u_quad_t a, b;
+{
+ u_quad_t r;
+
+ (void)__qdivrem(a, b, &r);
+ return (r);
+}
diff --git a/lib/libc/quad/xordi3.c b/lib/libc/quad/xordi3.c
new file mode 100644
index 0000000..ec7f6bd
--- /dev/null
+++ b/lib/libc/quad/xordi3.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)xordi3.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "quad.h"
+
+/*
+ * Return a ^ b, in quad.
+ */
+quad_t
+__xordi3(a, b)
+ quad_t a, b;
+{
+ union uu aa, bb;
+
+ aa.q = a;
+ bb.q = b;
+ aa.ul[0] ^= bb.ul[0];
+ aa.ul[1] ^= bb.ul[1];
+ return (aa.q);
+}
diff --git a/lib/libc/regex/COPYRIGHT b/lib/libc/regex/COPYRIGHT
new file mode 100644
index 0000000..574f6bc
--- /dev/null
+++ b/lib/libc/regex/COPYRIGHT
@@ -0,0 +1,56 @@
+Copyright 1992, 1993, 1994 Henry Spencer. All rights reserved.
+This software is not subject to any license of the American Telephone
+and Telegraph Company or of the Regents of the University of California.
+
+Permission is granted to anyone to use this software for any purpose on
+any computer system, and to alter it and redistribute it, subject
+to the following restrictions:
+
+1. The author is not responsible for the consequences of use of this
+ software, no matter how awful, even if they arise from flaws in it.
+
+2. The origin of this software must not be misrepresented, either by
+ explicit claim or by omission. Since few users ever read sources,
+ credits must appear in the documentation.
+
+3. Altered versions must be plainly marked as such, and must not be
+ misrepresented as being the original software. Since few users
+ ever read sources, credits must appear in the documentation.
+
+4. This notice may not be removed or altered.
+
+=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+/*-
+ * Copyright (c) 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)COPYRIGHT 8.1 (Berkeley) 3/16/94
+ */
diff --git a/lib/libc/regex/Makefile.inc b/lib/libc/regex/Makefile.inc
new file mode 100644
index 0000000..a2e23eb
--- /dev/null
+++ b/lib/libc/regex/Makefile.inc
@@ -0,0 +1,17 @@
+# from @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+# regex sources
+.PATH: ${.CURDIR}/regex
+
+CFLAGS+=-DPOSIX_MISTAKE
+
+SRCS+= regcomp.c regerror.c regexec.c regfree.c
+
+SYM_MAPS+=${.CURDIR}/regex/Symbol.map
+
+MAN+= regex.3
+MAN+= re_format.7
+
+MLINKS+=regex.3 regcomp.3 regex.3 regexec.3 regex.3 regerror.3
+MLINKS+=regexec.3 regfree.3
diff --git a/lib/libc/regex/Symbol.map b/lib/libc/regex/Symbol.map
new file mode 100644
index 0000000..5821f62
--- /dev/null
+++ b/lib/libc/regex/Symbol.map
@@ -0,0 +1,10 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ regcomp;
+ regerror;
+ regexec;
+ regfree;
+};
diff --git a/lib/libc/regex/WHATSNEW b/lib/libc/regex/WHATSNEW
new file mode 100644
index 0000000..f4301d3
--- /dev/null
+++ b/lib/libc/regex/WHATSNEW
@@ -0,0 +1,94 @@
+# @(#)WHATSNEW 8.3 (Berkeley) 3/18/94
+
+New in alpha3.4: The complex bug alluded to below has been fixed (in a
+slightly kludgey temporary way that may hurt efficiency a bit; this is
+another "get it out the door for 4.4" release). The tests at the end of
+the tests file have accordingly been uncommented. The primary sign of
+the bug was that something like a?b matching ab matched b rather than ab.
+(The bug was essentially specific to this exact situation, else it would
+have shown up earlier.)
+
+New in alpha3.3: The definition of word boundaries has been altered
+slightly, to more closely match the usual programming notion that "_"
+is an alphabetic. Stuff used for pre-ANSI systems is now in a subdir,
+and the makefile no longer alludes to it in mysterious ways. The
+makefile has generally been cleaned up some. Fixes have been made
+(again!) so that the regression test will run without -DREDEBUG, at
+the cost of weaker checking. A workaround for a bug in some folks'
+<assert.h> has been added. And some more things have been added to
+tests, including a couple right at the end which are commented out
+because the code currently flunks them (complex bug; fix coming).
+Plus the usual minor cleanup.
+
+New in alpha3.2: Assorted bits of cleanup and portability improvement
+(the development base is now a BSDI system using GCC instead of an ancient
+Sun system, and the newer compiler exposed some glitches). Fix for a
+serious bug that affected REs using many [] (including REG_ICASE REs
+because of the way they are implemented), *sometimes*, depending on
+memory-allocation patterns. The header-file prototypes no longer name
+the parameters, avoiding possible name conflicts. The possibility that
+some clot has defined CHAR_MIN as (say) `-128' instead of `(-128)' is
+now handled gracefully. "uchar" is no longer used as an internal type
+name (too many people have the same idea). Still the same old lousy
+performance, alas.
+
+New in alpha3.1: Basically nothing, this release is just a bookkeeping
+convenience. Stay tuned.
+
+New in alpha3.0: Performance is no better, alas, but some fixes have been
+made and some functionality has been added. (This is basically the "get
+it out the door in time for 4.4" release.) One bug fix: regfree() didn't
+free the main internal structure (how embarrassing). It is now possible
+to put NULs in either the RE or the target string, using (resp.) a new
+REG_PEND flag and the old REG_STARTEND flag. The REG_NOSPEC flag to
+regcomp() makes all characters ordinary, so you can match a literal
+string easily (this will become more useful when performance improves!).
+There are now primitives to match beginnings and ends of words, although
+the syntax is disgusting and so is the implementation. The REG_ATOI
+debugging interface has changed a bit. And there has been considerable
+internal cleanup of various kinds.
+
+New in alpha2.3: Split change list out of README, and moved flags notes
+into Makefile. Macro-ized the name of regex(7) in regex(3), since it has
+to change for 4.4BSD. Cleanup work in engine.c, and some new regression
+tests to catch tricky cases thereof.
+
+New in alpha2.2: Out-of-date manpages updated. Regerror() acquires two
+small extensions -- REG_ITOA and REG_ATOI -- which avoid debugging kludges
+in my own test program and might be useful to others for similar purposes.
+The regression test will now compile (and run) without REDEBUG. The
+BRE \$ bug is fixed. Most uses of "uchar" are gone; it's all chars now.
+Char/uchar parameters are now written int/unsigned, to avoid possible
+portability problems with unpromoted parameters. Some unsigned casts have
+been introduced to minimize portability problems with shifting into sign
+bits.
+
+New in alpha2.1: Lots of little stuff, cleanup and fixes. The one big
+thing is that regex.h is now generated, using mkh, rather than being
+supplied in the distribution; due to circularities in dependencies,
+you have to build regex.h explicitly by "make h". The two known bugs
+have been fixed (and the regression test now checks for them), as has a
+problem with assertions not being suppressed in the absence of REDEBUG.
+No performance work yet.
+
+New in alpha2: Backslash-anything is an ordinary character, not an
+error (except, of course, for the handful of backslashed metacharacters
+in BREs), which should reduce script breakage. The regression test
+checks *where* null strings are supposed to match, and has generally
+been tightened up somewhat. Small bug fixes in parameter passing (not
+harmful, but technically errors) and some other areas. Debugging
+invoked by defining REDEBUG rather than not defining NDEBUG.
+
+New in alpha+3: full prototyping for internal routines, using a little
+helper program, mkh, which extracts prototypes given in stylized comments.
+More minor cleanup. Buglet fix: it's CHAR_BIT, not CHAR_BITS. Simple
+pre-screening of input when a literal string is known to be part of the
+RE; this does wonders for performance.
+
+New in alpha+2: minor bits of cleanup. Notably, the number "32" for the
+word width isn't hardwired into regexec.c any more, the public header
+file prototypes the functions if __STDC__ is defined, and some small typos
+in the manpages have been fixed.
+
+New in alpha+1: improvements to the manual pages, and an important
+extension, the REG_STARTEND option to regexec().
diff --git a/lib/libc/regex/cname.h b/lib/libc/regex/cname.h
new file mode 100644
index 0000000..7087bcb
--- /dev/null
+++ b/lib/libc/regex/cname.h
@@ -0,0 +1,138 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)cname.h 8.3 (Berkeley) 3/20/94
+ * $FreeBSD$
+ */
+
+/* character-name table */
+static struct cname {
+ char *name;
+ char code;
+} cnames[] = {
+ {"NUL", '\0'},
+ {"SOH", '\001'},
+ {"STX", '\002'},
+ {"ETX", '\003'},
+ {"EOT", '\004'},
+ {"ENQ", '\005'},
+ {"ACK", '\006'},
+ {"BEL", '\007'},
+ {"alert", '\007'},
+ {"BS", '\010'},
+ {"backspace", '\b'},
+ {"HT", '\011'},
+ {"tab", '\t'},
+ {"LF", '\012'},
+ {"newline", '\n'},
+ {"VT", '\013'},
+ {"vertical-tab", '\v'},
+ {"FF", '\014'},
+ {"form-feed", '\f'},
+ {"CR", '\015'},
+ {"carriage-return", '\r'},
+ {"SO", '\016'},
+ {"SI", '\017'},
+ {"DLE", '\020'},
+ {"DC1", '\021'},
+ {"DC2", '\022'},
+ {"DC3", '\023'},
+ {"DC4", '\024'},
+ {"NAK", '\025'},
+ {"SYN", '\026'},
+ {"ETB", '\027'},
+ {"CAN", '\030'},
+ {"EM", '\031'},
+ {"SUB", '\032'},
+ {"ESC", '\033'},
+ {"IS4", '\034'},
+ {"FS", '\034'},
+ {"IS3", '\035'},
+ {"GS", '\035'},
+ {"IS2", '\036'},
+ {"RS", '\036'},
+ {"IS1", '\037'},
+ {"US", '\037'},
+ {"space", ' '},
+ {"exclamation-mark", '!'},
+ {"quotation-mark", '"'},
+ {"number-sign", '#'},
+ {"dollar-sign", '$'},
+ {"percent-sign", '%'},
+ {"ampersand", '&'},
+ {"apostrophe", '\''},
+ {"left-parenthesis", '('},
+ {"right-parenthesis", ')'},
+ {"asterisk", '*'},
+ {"plus-sign", '+'},
+ {"comma", ','},
+ {"hyphen", '-'},
+ {"hyphen-minus", '-'},
+ {"period", '.'},
+ {"full-stop", '.'},
+ {"slash", '/'},
+ {"solidus", '/'},
+ {"zero", '0'},
+ {"one", '1'},
+ {"two", '2'},
+ {"three", '3'},
+ {"four", '4'},
+ {"five", '5'},
+ {"six", '6'},
+ {"seven", '7'},
+ {"eight", '8'},
+ {"nine", '9'},
+ {"colon", ':'},
+ {"semicolon", ';'},
+ {"less-than-sign", '<'},
+ {"equals-sign", '='},
+ {"greater-than-sign", '>'},
+ {"question-mark", '?'},
+ {"commercial-at", '@'},
+ {"left-square-bracket", '['},
+ {"backslash", '\\'},
+ {"reverse-solidus", '\\'},
+ {"right-square-bracket",']'},
+ {"circumflex", '^'},
+ {"circumflex-accent", '^'},
+ {"underscore", '_'},
+ {"low-line", '_'},
+ {"grave-accent", '`'},
+ {"left-brace", '{'},
+ {"left-curly-bracket", '{'},
+ {"vertical-line", '|'},
+ {"right-brace", '}'},
+ {"right-curly-bracket", '}'},
+ {"tilde", '~'},
+ {"DEL", '\177'},
+ {NULL, 0}
+};
diff --git a/lib/libc/regex/engine.c b/lib/libc/regex/engine.c
new file mode 100644
index 0000000..2a1a75e
--- /dev/null
+++ b/lib/libc/regex/engine.c
@@ -0,0 +1,1191 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)engine.c 8.5 (Berkeley) 3/20/94
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * The matching engine and friends. This file is #included by regexec.c
+ * after suitable #defines of a variety of macros used herein, so that
+ * different state representations can be used without duplicating masses
+ * of code.
+ */
+
+#ifdef SNAMES
+#define matcher smatcher
+#define fast sfast
+#define slow sslow
+#define dissect sdissect
+#define backref sbackref
+#define step sstep
+#define print sprint
+#define at sat
+#define match smat
+#endif
+#ifdef LNAMES
+#define matcher lmatcher
+#define fast lfast
+#define slow lslow
+#define dissect ldissect
+#define backref lbackref
+#define step lstep
+#define print lprint
+#define at lat
+#define match lmat
+#endif
+#ifdef MNAMES
+#define matcher mmatcher
+#define fast mfast
+#define slow mslow
+#define dissect mdissect
+#define backref mbackref
+#define step mstep
+#define print mprint
+#define at mat
+#define match mmat
+#endif
+
+/* another structure passed up and down to avoid zillions of parameters */
+struct match {
+ struct re_guts *g;
+ int eflags;
+ regmatch_t *pmatch; /* [nsub+1] (0 element unused) */
+ const char *offp; /* offsets work from here */
+ const char *beginp; /* start of string -- virtual NUL precedes */
+ const char *endp; /* end of string -- virtual NUL here */
+ const char *coldp; /* can be no match starting before here */
+ const char **lastpos; /* [nplus+1] */
+ STATEVARS;
+ states st; /* current states */
+ states fresh; /* states for a fresh start */
+ states tmp; /* temporary */
+ states empty; /* empty set of states */
+ mbstate_t mbs; /* multibyte conversion state */
+};
+
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === engine.c === */
+static int matcher(struct re_guts *g, const char *string, size_t nmatch, regmatch_t pmatch[], int eflags);
+static const char *dissect(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
+static const char *backref(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst, sopno lev, int);
+static const char *fast(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
+static const char *slow(struct match *m, const char *start, const char *stop, sopno startst, sopno stopst);
+static states step(struct re_guts *g, sopno start, sopno stop, states bef, wint_t ch, states aft);
+#define MAX_RECURSION 100
+#define BOL (OUT-1)
+#define EOL (BOL-1)
+#define BOLEOL (BOL-2)
+#define NOTHING (BOL-3)
+#define BOW (BOL-4)
+#define EOW (BOL-5)
+#define BADCHAR (BOL-6)
+#define NONCHAR(c) ((c) <= OUT)
+#ifdef REDEBUG
+static void print(struct match *m, const char *caption, states st, int ch, FILE *d);
+#endif
+#ifdef REDEBUG
+static void at(struct match *m, const char *title, const char *start, const char *stop, sopno startst, sopno stopst);
+#endif
+#ifdef REDEBUG
+static const char *pchar(int ch);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
+
+#ifdef REDEBUG
+#define SP(t, s, c) print(m, t, s, c, stdout)
+#define AT(t, p1, p2, s1, s2) at(m, t, p1, p2, s1, s2)
+#define NOTE(str) { if (m->eflags&REG_TRACE) printf("=%s\n", (str)); }
+#else
+#define SP(t, s, c) /* nothing */
+#define AT(t, p1, p2, s1, s2) /* nothing */
+#define NOTE(s) /* nothing */
+#endif
+
+/*
+ - matcher - the actual matching engine
+ == static int matcher(struct re_guts *g, const char *string, \
+ == size_t nmatch, regmatch_t pmatch[], int eflags);
+ */
+static int /* 0 success, REG_NOMATCH failure */
+matcher(struct re_guts *g,
+ const char *string,
+ size_t nmatch,
+ regmatch_t pmatch[],
+ int eflags)
+{
+ const char *endp;
+ int i;
+ struct match mv;
+ struct match *m = &mv;
+ const char *dp;
+ const sopno gf = g->firststate+1; /* +1 for OEND */
+ const sopno gl = g->laststate;
+ const char *start;
+ const char *stop;
+ /* Boyer-Moore algorithms variables */
+ const char *pp;
+ int cj, mj;
+ const char *mustfirst;
+ const char *mustlast;
+ int *matchjump;
+ int *charjump;
+
+ /* simplify the situation where possible */
+ if (g->cflags&REG_NOSUB)
+ nmatch = 0;
+ if (eflags&REG_STARTEND) {
+ start = string + pmatch[0].rm_so;
+ stop = string + pmatch[0].rm_eo;
+ } else {
+ start = string;
+ stop = start + strlen(start);
+ }
+ if (stop < start)
+ return(REG_INVARG);
+
+ /* prescreening; this does wonders for this rather slow code */
+ if (g->must != NULL) {
+ if (g->charjump != NULL && g->matchjump != NULL) {
+ mustfirst = g->must;
+ mustlast = g->must + g->mlen - 1;
+ charjump = g->charjump;
+ matchjump = g->matchjump;
+ pp = mustlast;
+ for (dp = start+g->mlen-1; dp < stop;) {
+ /* Fast skip non-matches */
+ while (dp < stop && charjump[(int)*dp])
+ dp += charjump[(int)*dp];
+
+ if (dp >= stop)
+ break;
+
+ /* Greedy matcher */
+ /* We depend on not being used for
+ * for strings of length 1
+ */
+ while (*--dp == *--pp && pp != mustfirst);
+
+ if (*dp == *pp)
+ break;
+
+ /* Jump to next possible match */
+ mj = matchjump[pp - mustfirst];
+ cj = charjump[(int)*dp];
+ dp += (cj < mj ? mj : cj);
+ pp = mustlast;
+ }
+ if (pp != mustfirst)
+ return(REG_NOMATCH);
+ } else {
+ for (dp = start; dp < stop; dp++)
+ if (*dp == g->must[0] &&
+ stop - dp >= g->mlen &&
+ memcmp(dp, g->must, (size_t)g->mlen) == 0)
+ break;
+ if (dp == stop) /* we didn't find g->must */
+ return(REG_NOMATCH);
+ }
+ }
+
+ /* match struct setup */
+ m->g = g;
+ m->eflags = eflags;
+ m->pmatch = NULL;
+ m->lastpos = NULL;
+ m->offp = string;
+ m->beginp = start;
+ m->endp = stop;
+ STATESETUP(m, 4);
+ SETUP(m->st);
+ SETUP(m->fresh);
+ SETUP(m->tmp);
+ SETUP(m->empty);
+ CLEAR(m->empty);
+ ZAPSTATE(&m->mbs);
+
+ /* Adjust start according to moffset, to speed things up */
+ if (g->moffset > -1)
+ start = ((dp - g->moffset) < start) ? start : dp - g->moffset;
+
+ SP("mloop", m->st, *start);
+
+ /* this loop does only one repetition except for backrefs */
+ for (;;) {
+ endp = fast(m, start, stop, gf, gl);
+ if (endp == NULL) { /* a miss */
+ if (m->pmatch != NULL)
+ free((char *)m->pmatch);
+ if (m->lastpos != NULL)
+ free((char *)m->lastpos);
+ STATETEARDOWN(m);
+ return(REG_NOMATCH);
+ }
+ if (nmatch == 0 && !g->backrefs)
+ break; /* no further info needed */
+
+ /* where? */
+ assert(m->coldp != NULL);
+ for (;;) {
+ NOTE("finding start");
+ endp = slow(m, m->coldp, stop, gf, gl);
+ if (endp != NULL)
+ break;
+ assert(m->coldp < m->endp);
+ m->coldp += XMBRTOWC(NULL, m->coldp,
+ m->endp - m->coldp, &m->mbs, 0);
+ }
+ if (nmatch == 1 && !g->backrefs)
+ break; /* no further info needed */
+
+ /* oh my, he wants the subexpressions... */
+ if (m->pmatch == NULL)
+ m->pmatch = (regmatch_t *)malloc((m->g->nsub + 1) *
+ sizeof(regmatch_t));
+ if (m->pmatch == NULL) {
+ STATETEARDOWN(m);
+ return(REG_ESPACE);
+ }
+ for (i = 1; i <= m->g->nsub; i++)
+ m->pmatch[i].rm_so = m->pmatch[i].rm_eo = -1;
+ if (!g->backrefs && !(m->eflags&REG_BACKR)) {
+ NOTE("dissecting");
+ dp = dissect(m, m->coldp, endp, gf, gl);
+ } else {
+ if (g->nplus > 0 && m->lastpos == NULL)
+ m->lastpos = malloc((g->nplus+1) *
+ sizeof(const char *));
+ if (g->nplus > 0 && m->lastpos == NULL) {
+ free(m->pmatch);
+ STATETEARDOWN(m);
+ return(REG_ESPACE);
+ }
+ NOTE("backref dissect");
+ dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0);
+ }
+ if (dp != NULL)
+ break;
+
+ /* uh-oh... we couldn't find a subexpression-level match */
+ assert(g->backrefs); /* must be back references doing it */
+ assert(g->nplus == 0 || m->lastpos != NULL);
+ for (;;) {
+ if (dp != NULL || endp <= m->coldp)
+ break; /* defeat */
+ NOTE("backoff");
+ endp = slow(m, m->coldp, endp-1, gf, gl);
+ if (endp == NULL)
+ break; /* defeat */
+ /* try it on a shorter possibility */
+#ifndef NDEBUG
+ for (i = 1; i <= m->g->nsub; i++) {
+ assert(m->pmatch[i].rm_so == -1);
+ assert(m->pmatch[i].rm_eo == -1);
+ }
+#endif
+ NOTE("backoff dissect");
+ dp = backref(m, m->coldp, endp, gf, gl, (sopno)0, 0);
+ }
+ assert(dp == NULL || dp == endp);
+ if (dp != NULL) /* found a shorter one */
+ break;
+
+ /* despite initial appearances, there is no match here */
+ NOTE("false alarm");
+ /* recycle starting later */
+ start = m->coldp + XMBRTOWC(NULL, m->coldp,
+ stop - m->coldp, &m->mbs, 0);
+ assert(start <= stop);
+ }
+
+ /* fill in the details if requested */
+ if (nmatch > 0) {
+ pmatch[0].rm_so = m->coldp - m->offp;
+ pmatch[0].rm_eo = endp - m->offp;
+ }
+ if (nmatch > 1) {
+ assert(m->pmatch != NULL);
+ for (i = 1; i < nmatch; i++)
+ if (i <= m->g->nsub)
+ pmatch[i] = m->pmatch[i];
+ else {
+ pmatch[i].rm_so = -1;
+ pmatch[i].rm_eo = -1;
+ }
+ }
+
+ if (m->pmatch != NULL)
+ free((char *)m->pmatch);
+ if (m->lastpos != NULL)
+ free((char *)m->lastpos);
+ STATETEARDOWN(m);
+ return(0);
+}
+
+/*
+ - dissect - figure out what matched what, no back references
+ == static const char *dissect(struct match *m, const char *start, \
+ == const char *stop, sopno startst, sopno stopst);
+ */
+static const char * /* == stop (success) always */
+dissect(struct match *m,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst)
+{
+ int i;
+ sopno ss; /* start sop of current subRE */
+ sopno es; /* end sop of current subRE */
+ const char *sp; /* start of string matched by it */
+ const char *stp; /* string matched by it cannot pass here */
+ const char *rest; /* start of rest of string */
+ const char *tail; /* string unmatched by rest of RE */
+ sopno ssub; /* start sop of subsubRE */
+ sopno esub; /* end sop of subsubRE */
+ const char *ssp; /* start of string matched by subsubRE */
+ const char *sep; /* end of string matched by subsubRE */
+ const char *oldssp; /* previous ssp */
+ const char *dp;
+
+ AT("diss", start, stop, startst, stopst);
+ sp = start;
+ for (ss = startst; ss < stopst; ss = es) {
+ /* identify end of subRE */
+ es = ss;
+ switch (OP(m->g->strip[es])) {
+ case OPLUS_:
+ case OQUEST_:
+ es += OPND(m->g->strip[es]);
+ break;
+ case OCH_:
+ while (OP(m->g->strip[es]) != O_CH)
+ es += OPND(m->g->strip[es]);
+ break;
+ }
+ es++;
+
+ /* figure out what it matched */
+ switch (OP(m->g->strip[ss])) {
+ case OEND:
+ assert(nope);
+ break;
+ case OCHAR:
+ sp += XMBRTOWC(NULL, sp, stop - start, &m->mbs, 0);
+ break;
+ case OBOL:
+ case OEOL:
+ case OBOW:
+ case OEOW:
+ break;
+ case OANY:
+ case OANYOF:
+ sp += XMBRTOWC(NULL, sp, stop - start, &m->mbs, 0);
+ break;
+ case OBACK_:
+ case O_BACK:
+ assert(nope);
+ break;
+ /* cases where length of match is hard to find */
+ case OQUEST_:
+ stp = stop;
+ for (;;) {
+ /* how long could this one be? */
+ rest = slow(m, sp, stp, ss, es);
+ assert(rest != NULL); /* it did match */
+ /* could the rest match the rest? */
+ tail = slow(m, rest, stop, es, stopst);
+ if (tail == stop)
+ break; /* yes! */
+ /* no -- try a shorter match for this one */
+ stp = rest - 1;
+ assert(stp >= sp); /* it did work */
+ }
+ ssub = ss + 1;
+ esub = es - 1;
+ /* did innards match? */
+ if (slow(m, sp, rest, ssub, esub) != NULL) {
+ dp = dissect(m, sp, rest, ssub, esub);
+ assert(dp == rest);
+ } else /* no */
+ assert(sp == rest);
+ sp = rest;
+ break;
+ case OPLUS_:
+ stp = stop;
+ for (;;) {
+ /* how long could this one be? */
+ rest = slow(m, sp, stp, ss, es);
+ assert(rest != NULL); /* it did match */
+ /* could the rest match the rest? */
+ tail = slow(m, rest, stop, es, stopst);
+ if (tail == stop)
+ break; /* yes! */
+ /* no -- try a shorter match for this one */
+ stp = rest - 1;
+ assert(stp >= sp); /* it did work */
+ }
+ ssub = ss + 1;
+ esub = es - 1;
+ ssp = sp;
+ oldssp = ssp;
+ for (;;) { /* find last match of innards */
+ sep = slow(m, ssp, rest, ssub, esub);
+ if (sep == NULL || sep == ssp)
+ break; /* failed or matched null */
+ oldssp = ssp; /* on to next try */
+ ssp = sep;
+ }
+ if (sep == NULL) {
+ /* last successful match */
+ sep = ssp;
+ ssp = oldssp;
+ }
+ assert(sep == rest); /* must exhaust substring */
+ assert(slow(m, ssp, sep, ssub, esub) == rest);
+ dp = dissect(m, ssp, sep, ssub, esub);
+ assert(dp == sep);
+ sp = rest;
+ break;
+ case OCH_:
+ stp = stop;
+ for (;;) {
+ /* how long could this one be? */
+ rest = slow(m, sp, stp, ss, es);
+ assert(rest != NULL); /* it did match */
+ /* could the rest match the rest? */
+ tail = slow(m, rest, stop, es, stopst);
+ if (tail == stop)
+ break; /* yes! */
+ /* no -- try a shorter match for this one */
+ stp = rest - 1;
+ assert(stp >= sp); /* it did work */
+ }
+ ssub = ss + 1;
+ esub = ss + OPND(m->g->strip[ss]) - 1;
+ assert(OP(m->g->strip[esub]) == OOR1);
+ for (;;) { /* find first matching branch */
+ if (slow(m, sp, rest, ssub, esub) == rest)
+ break; /* it matched all of it */
+ /* that one missed, try next one */
+ assert(OP(m->g->strip[esub]) == OOR1);
+ esub++;
+ assert(OP(m->g->strip[esub]) == OOR2);
+ ssub = esub + 1;
+ esub += OPND(m->g->strip[esub]);
+ if (OP(m->g->strip[esub]) == OOR2)
+ esub--;
+ else
+ assert(OP(m->g->strip[esub]) == O_CH);
+ }
+ dp = dissect(m, sp, rest, ssub, esub);
+ assert(dp == rest);
+ sp = rest;
+ break;
+ case O_PLUS:
+ case O_QUEST:
+ case OOR1:
+ case OOR2:
+ case O_CH:
+ assert(nope);
+ break;
+ case OLPAREN:
+ i = OPND(m->g->strip[ss]);
+ assert(0 < i && i <= m->g->nsub);
+ m->pmatch[i].rm_so = sp - m->offp;
+ break;
+ case ORPAREN:
+ i = OPND(m->g->strip[ss]);
+ assert(0 < i && i <= m->g->nsub);
+ m->pmatch[i].rm_eo = sp - m->offp;
+ break;
+ default: /* uh oh */
+ assert(nope);
+ break;
+ }
+ }
+
+ assert(sp == stop);
+ return(sp);
+}
+
+/*
+ - backref - figure out what matched what, figuring in back references
+ == static const char *backref(struct match *m, const char *start, \
+ == const char *stop, sopno startst, sopno stopst, sopno lev);
+ */
+static const char * /* == stop (success) or NULL (failure) */
+backref(struct match *m,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst,
+ sopno lev, /* PLUS nesting level */
+ int rec)
+{
+ int i;
+ sopno ss; /* start sop of current subRE */
+ const char *sp; /* start of string matched by it */
+ sopno ssub; /* start sop of subsubRE */
+ sopno esub; /* end sop of subsubRE */
+ const char *ssp; /* start of string matched by subsubRE */
+ const char *dp;
+ size_t len;
+ int hard;
+ sop s;
+ regoff_t offsave;
+ cset *cs;
+ wint_t wc;
+
+ AT("back", start, stop, startst, stopst);
+ sp = start;
+
+ /* get as far as we can with easy stuff */
+ hard = 0;
+ for (ss = startst; !hard && ss < stopst; ss++)
+ switch (OP(s = m->g->strip[ss])) {
+ case OCHAR:
+ if (sp == stop)
+ return(NULL);
+ sp += XMBRTOWC(&wc, sp, stop - sp, &m->mbs, BADCHAR);
+ if (wc != OPND(s))
+ return(NULL);
+ break;
+ case OANY:
+ if (sp == stop)
+ return(NULL);
+ sp += XMBRTOWC(&wc, sp, stop - sp, &m->mbs, BADCHAR);
+ if (wc == BADCHAR)
+ return (NULL);
+ break;
+ case OANYOF:
+ if (sp == stop)
+ return (NULL);
+ cs = &m->g->sets[OPND(s)];
+ sp += XMBRTOWC(&wc, sp, stop - sp, &m->mbs, BADCHAR);
+ if (wc == BADCHAR || !CHIN(cs, wc))
+ return(NULL);
+ break;
+ case OBOL:
+ if ( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
+ (sp < m->endp && *(sp-1) == '\n' &&
+ (m->g->cflags&REG_NEWLINE)) )
+ { /* yes */ }
+ else
+ return(NULL);
+ break;
+ case OEOL:
+ if ( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
+ (sp < m->endp && *sp == '\n' &&
+ (m->g->cflags&REG_NEWLINE)) )
+ { /* yes */ }
+ else
+ return(NULL);
+ break;
+ case OBOW:
+ if (( (sp == m->beginp && !(m->eflags&REG_NOTBOL)) ||
+ (sp < m->endp && *(sp-1) == '\n' &&
+ (m->g->cflags&REG_NEWLINE)) ||
+ (sp > m->beginp &&
+ !ISWORD(*(sp-1))) ) &&
+ (sp < m->endp && ISWORD(*sp)) )
+ { /* yes */ }
+ else
+ return(NULL);
+ break;
+ case OEOW:
+ if (( (sp == m->endp && !(m->eflags&REG_NOTEOL)) ||
+ (sp < m->endp && *sp == '\n' &&
+ (m->g->cflags&REG_NEWLINE)) ||
+ (sp < m->endp && !ISWORD(*sp)) ) &&
+ (sp > m->beginp && ISWORD(*(sp-1))) )
+ { /* yes */ }
+ else
+ return(NULL);
+ break;
+ case O_QUEST:
+ break;
+ case OOR1: /* matches null but needs to skip */
+ ss++;
+ s = m->g->strip[ss];
+ do {
+ assert(OP(s) == OOR2);
+ ss += OPND(s);
+ } while (OP(s = m->g->strip[ss]) != O_CH);
+ /* note that the ss++ gets us past the O_CH */
+ break;
+ default: /* have to make a choice */
+ hard = 1;
+ break;
+ }
+ if (!hard) { /* that was it! */
+ if (sp != stop)
+ return(NULL);
+ return(sp);
+ }
+ ss--; /* adjust for the for's final increment */
+
+ /* the hard stuff */
+ AT("hard", sp, stop, ss, stopst);
+ s = m->g->strip[ss];
+ switch (OP(s)) {
+ case OBACK_: /* the vilest depths */
+ i = OPND(s);
+ assert(0 < i && i <= m->g->nsub);
+ if (m->pmatch[i].rm_eo == -1)
+ return(NULL);
+ assert(m->pmatch[i].rm_so != -1);
+ len = m->pmatch[i].rm_eo - m->pmatch[i].rm_so;
+ if (len == 0 && rec++ > MAX_RECURSION)
+ return(NULL);
+ assert(stop - m->beginp >= len);
+ if (sp > stop - len)
+ return(NULL); /* not enough left to match */
+ ssp = m->offp + m->pmatch[i].rm_so;
+ if (memcmp(sp, ssp, len) != 0)
+ return(NULL);
+ while (m->g->strip[ss] != SOP(O_BACK, i))
+ ss++;
+ return(backref(m, sp+len, stop, ss+1, stopst, lev, rec));
+ break;
+ case OQUEST_: /* to null or not */
+ dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
+ if (dp != NULL)
+ return(dp); /* not */
+ return(backref(m, sp, stop, ss+OPND(s)+1, stopst, lev, rec));
+ break;
+ case OPLUS_:
+ assert(m->lastpos != NULL);
+ assert(lev+1 <= m->g->nplus);
+ m->lastpos[lev+1] = sp;
+ return(backref(m, sp, stop, ss+1, stopst, lev+1, rec));
+ break;
+ case O_PLUS:
+ if (sp == m->lastpos[lev]) /* last pass matched null */
+ return(backref(m, sp, stop, ss+1, stopst, lev-1, rec));
+ /* try another pass */
+ m->lastpos[lev] = sp;
+ dp = backref(m, sp, stop, ss-OPND(s)+1, stopst, lev, rec);
+ if (dp == NULL)
+ return(backref(m, sp, stop, ss+1, stopst, lev-1, rec));
+ else
+ return(dp);
+ break;
+ case OCH_: /* find the right one, if any */
+ ssub = ss + 1;
+ esub = ss + OPND(s) - 1;
+ assert(OP(m->g->strip[esub]) == OOR1);
+ for (;;) { /* find first matching branch */
+ dp = backref(m, sp, stop, ssub, esub, lev, rec);
+ if (dp != NULL)
+ return(dp);
+ /* that one missed, try next one */
+ if (OP(m->g->strip[esub]) == O_CH)
+ return(NULL); /* there is none */
+ esub++;
+ assert(OP(m->g->strip[esub]) == OOR2);
+ ssub = esub + 1;
+ esub += OPND(m->g->strip[esub]);
+ if (OP(m->g->strip[esub]) == OOR2)
+ esub--;
+ else
+ assert(OP(m->g->strip[esub]) == O_CH);
+ }
+ break;
+ case OLPAREN: /* must undo assignment if rest fails */
+ i = OPND(s);
+ assert(0 < i && i <= m->g->nsub);
+ offsave = m->pmatch[i].rm_so;
+ m->pmatch[i].rm_so = sp - m->offp;
+ dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
+ if (dp != NULL)
+ return(dp);
+ m->pmatch[i].rm_so = offsave;
+ return(NULL);
+ break;
+ case ORPAREN: /* must undo assignment if rest fails */
+ i = OPND(s);
+ assert(0 < i && i <= m->g->nsub);
+ offsave = m->pmatch[i].rm_eo;
+ m->pmatch[i].rm_eo = sp - m->offp;
+ dp = backref(m, sp, stop, ss+1, stopst, lev, rec);
+ if (dp != NULL)
+ return(dp);
+ m->pmatch[i].rm_eo = offsave;
+ return(NULL);
+ break;
+ default: /* uh oh */
+ assert(nope);
+ break;
+ }
+
+ /* "can't happen" */
+ assert(nope);
+ /* NOTREACHED */
+ return "shut up gcc";
+}
+
+/*
+ - fast - step through the string at top speed
+ == static const char *fast(struct match *m, const char *start, \
+ == const char *stop, sopno startst, sopno stopst);
+ */
+static const char * /* where tentative match ended, or NULL */
+fast( struct match *m,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst)
+{
+ states st = m->st;
+ states fresh = m->fresh;
+ states tmp = m->tmp;
+ const char *p = start;
+ wint_t c;
+ wint_t lastc; /* previous c */
+ wint_t flagch;
+ int i;
+ const char *coldp; /* last p after which no match was underway */
+ size_t clen;
+
+ CLEAR(st);
+ SET1(st, startst);
+ SP("fast", st, *p);
+ st = step(m->g, startst, stopst, st, NOTHING, st);
+ ASSIGN(fresh, st);
+ SP("start", st, *p);
+ coldp = NULL;
+ if (start == m->beginp)
+ c = OUT;
+ else {
+ /*
+ * XXX Wrong if the previous character was multi-byte.
+ * Newline never is (in encodings supported by FreeBSD),
+ * so this only breaks the ISWORD tests below.
+ */
+ c = (uch)*(start - 1);
+ }
+ for (;;) {
+ /* next character */
+ lastc = c;
+ if (p == m->endp) {
+ clen = 0;
+ c = OUT;
+ } else
+ clen = XMBRTOWC(&c, p, m->endp - p, &m->mbs, BADCHAR);
+ if (EQ(st, fresh))
+ coldp = p;
+
+ /* is there an EOL and/or BOL between lastc and c? */
+ flagch = '\0';
+ i = 0;
+ if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||
+ (lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
+ flagch = BOL;
+ i = m->g->nbol;
+ }
+ if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||
+ (c == OUT && !(m->eflags&REG_NOTEOL)) ) {
+ flagch = (flagch == BOL) ? BOLEOL : EOL;
+ i += m->g->neol;
+ }
+ if (i != 0) {
+ for (; i > 0; i--)
+ st = step(m->g, startst, stopst, st, flagch, st);
+ SP("boleol", st, c);
+ }
+
+ /* how about a word boundary? */
+ if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
+ (c != OUT && ISWORD(c)) ) {
+ flagch = BOW;
+ }
+ if ( (lastc != OUT && ISWORD(lastc)) &&
+ (flagch == EOL || (c != OUT && !ISWORD(c))) ) {
+ flagch = EOW;
+ }
+ if (flagch == BOW || flagch == EOW) {
+ st = step(m->g, startst, stopst, st, flagch, st);
+ SP("boweow", st, c);
+ }
+
+ /* are we done? */
+ if (ISSET(st, stopst) || p == stop || clen > stop - p)
+ break; /* NOTE BREAK OUT */
+
+ /* no, we must deal with this character */
+ ASSIGN(tmp, st);
+ ASSIGN(st, fresh);
+ assert(c != OUT);
+ st = step(m->g, startst, stopst, tmp, c, st);
+ SP("aft", st, c);
+ assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
+ p += clen;
+ }
+
+ assert(coldp != NULL);
+ m->coldp = coldp;
+ if (ISSET(st, stopst))
+ return(p+XMBRTOWC(NULL, p, stop - p, &m->mbs, 0));
+ else
+ return(NULL);
+}
+
+/*
+ - slow - step through the string more deliberately
+ == static const char *slow(struct match *m, const char *start, \
+ == const char *stop, sopno startst, sopno stopst);
+ */
+static const char * /* where it ended */
+slow( struct match *m,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst)
+{
+ states st = m->st;
+ states empty = m->empty;
+ states tmp = m->tmp;
+ const char *p = start;
+ wint_t c;
+ wint_t lastc; /* previous c */
+ wint_t flagch;
+ int i;
+ const char *matchp; /* last p at which a match ended */
+ size_t clen;
+
+ AT("slow", start, stop, startst, stopst);
+ CLEAR(st);
+ SET1(st, startst);
+ SP("sstart", st, *p);
+ st = step(m->g, startst, stopst, st, NOTHING, st);
+ matchp = NULL;
+ if (start == m->beginp)
+ c = OUT;
+ else {
+ /*
+ * XXX Wrong if the previous character was multi-byte.
+ * Newline never is (in encodings supported by FreeBSD),
+ * so this only breaks the ISWORD tests below.
+ */
+ c = (uch)*(start - 1);
+ }
+ for (;;) {
+ /* next character */
+ lastc = c;
+ if (p == m->endp) {
+ c = OUT;
+ clen = 0;
+ } else
+ clen = XMBRTOWC(&c, p, m->endp - p, &m->mbs, BADCHAR);
+
+ /* is there an EOL and/or BOL between lastc and c? */
+ flagch = '\0';
+ i = 0;
+ if ( (lastc == '\n' && m->g->cflags&REG_NEWLINE) ||
+ (lastc == OUT && !(m->eflags&REG_NOTBOL)) ) {
+ flagch = BOL;
+ i = m->g->nbol;
+ }
+ if ( (c == '\n' && m->g->cflags&REG_NEWLINE) ||
+ (c == OUT && !(m->eflags&REG_NOTEOL)) ) {
+ flagch = (flagch == BOL) ? BOLEOL : EOL;
+ i += m->g->neol;
+ }
+ if (i != 0) {
+ for (; i > 0; i--)
+ st = step(m->g, startst, stopst, st, flagch, st);
+ SP("sboleol", st, c);
+ }
+
+ /* how about a word boundary? */
+ if ( (flagch == BOL || (lastc != OUT && !ISWORD(lastc))) &&
+ (c != OUT && ISWORD(c)) ) {
+ flagch = BOW;
+ }
+ if ( (lastc != OUT && ISWORD(lastc)) &&
+ (flagch == EOL || (c != OUT && !ISWORD(c))) ) {
+ flagch = EOW;
+ }
+ if (flagch == BOW || flagch == EOW) {
+ st = step(m->g, startst, stopst, st, flagch, st);
+ SP("sboweow", st, c);
+ }
+
+ /* are we done? */
+ if (ISSET(st, stopst))
+ matchp = p;
+ if (EQ(st, empty) || p == stop || clen > stop - p)
+ break; /* NOTE BREAK OUT */
+
+ /* no, we must deal with this character */
+ ASSIGN(tmp, st);
+ ASSIGN(st, empty);
+ assert(c != OUT);
+ st = step(m->g, startst, stopst, tmp, c, st);
+ SP("saft", st, c);
+ assert(EQ(step(m->g, startst, stopst, st, NOTHING, st), st));
+ p += clen;
+ }
+
+ return(matchp);
+}
+
+
+/*
+ - step - map set of states reachable before char to set reachable after
+ == static states step(struct re_guts *g, sopno start, sopno stop, \
+ == states bef, int ch, states aft);
+ == #define BOL (OUT-1)
+ == #define EOL (BOL-1)
+ == #define BOLEOL (BOL-2)
+ == #define NOTHING (BOL-3)
+ == #define BOW (BOL-4)
+ == #define EOW (BOL-5)
+ == #define BADCHAR (BOL-6)
+ == #define NONCHAR(c) ((c) <= OUT)
+ */
+static states
+step(struct re_guts *g,
+ sopno start, /* start state within strip */
+ sopno stop, /* state after stop state within strip */
+ states bef, /* states reachable before */
+ wint_t ch, /* character or NONCHAR code */
+ states aft) /* states already known reachable after */
+{
+ cset *cs;
+ sop s;
+ sopno pc;
+ onestate here; /* note, macros know this name */
+ sopno look;
+ int i;
+
+ for (pc = start, INIT(here, pc); pc != stop; pc++, INC(here)) {
+ s = g->strip[pc];
+ switch (OP(s)) {
+ case OEND:
+ assert(pc == stop-1);
+ break;
+ case OCHAR:
+ /* only characters can match */
+ assert(!NONCHAR(ch) || ch != OPND(s));
+ if (ch == OPND(s))
+ FWD(aft, bef, 1);
+ break;
+ case OBOL:
+ if (ch == BOL || ch == BOLEOL)
+ FWD(aft, bef, 1);
+ break;
+ case OEOL:
+ if (ch == EOL || ch == BOLEOL)
+ FWD(aft, bef, 1);
+ break;
+ case OBOW:
+ if (ch == BOW)
+ FWD(aft, bef, 1);
+ break;
+ case OEOW:
+ if (ch == EOW)
+ FWD(aft, bef, 1);
+ break;
+ case OANY:
+ if (!NONCHAR(ch))
+ FWD(aft, bef, 1);
+ break;
+ case OANYOF:
+ cs = &g->sets[OPND(s)];
+ if (!NONCHAR(ch) && CHIN(cs, ch))
+ FWD(aft, bef, 1);
+ break;
+ case OBACK_: /* ignored here */
+ case O_BACK:
+ FWD(aft, aft, 1);
+ break;
+ case OPLUS_: /* forward, this is just an empty */
+ FWD(aft, aft, 1);
+ break;
+ case O_PLUS: /* both forward and back */
+ FWD(aft, aft, 1);
+ i = ISSETBACK(aft, OPND(s));
+ BACK(aft, aft, OPND(s));
+ if (!i && ISSETBACK(aft, OPND(s))) {
+ /* oho, must reconsider loop body */
+ pc -= OPND(s) + 1;
+ INIT(here, pc);
+ }
+ break;
+ case OQUEST_: /* two branches, both forward */
+ FWD(aft, aft, 1);
+ FWD(aft, aft, OPND(s));
+ break;
+ case O_QUEST: /* just an empty */
+ FWD(aft, aft, 1);
+ break;
+ case OLPAREN: /* not significant here */
+ case ORPAREN:
+ FWD(aft, aft, 1);
+ break;
+ case OCH_: /* mark the first two branches */
+ FWD(aft, aft, 1);
+ assert(OP(g->strip[pc+OPND(s)]) == OOR2);
+ FWD(aft, aft, OPND(s));
+ break;
+ case OOR1: /* done a branch, find the O_CH */
+ if (ISSTATEIN(aft, here)) {
+ for (look = 1;
+ OP(s = g->strip[pc+look]) != O_CH;
+ look += OPND(s))
+ assert(OP(s) == OOR2);
+ FWD(aft, aft, look + 1);
+ }
+ break;
+ case OOR2: /* propagate OCH_'s marking */
+ FWD(aft, aft, 1);
+ if (OP(g->strip[pc+OPND(s)]) != O_CH) {
+ assert(OP(g->strip[pc+OPND(s)]) == OOR2);
+ FWD(aft, aft, OPND(s));
+ }
+ break;
+ case O_CH: /* just empty */
+ FWD(aft, aft, 1);
+ break;
+ default: /* ooooops... */
+ assert(nope);
+ break;
+ }
+ }
+
+ return(aft);
+}
+
+#ifdef REDEBUG
+/*
+ - print - print a set of states
+ == #ifdef REDEBUG
+ == static void print(struct match *m, const char *caption, states st, \
+ == int ch, FILE *d);
+ == #endif
+ */
+static void
+print(struct match *m,
+ const char *caption,
+ states st,
+ int ch,
+ FILE *d)
+{
+ struct re_guts *g = m->g;
+ int i;
+ int first = 1;
+
+ if (!(m->eflags&REG_TRACE))
+ return;
+
+ fprintf(d, "%s", caption);
+ if (ch != '\0')
+ fprintf(d, " %s", pchar(ch));
+ for (i = 0; i < g->nstates; i++)
+ if (ISSET(st, i)) {
+ fprintf(d, "%s%d", (first) ? "\t" : ", ", i);
+ first = 0;
+ }
+ fprintf(d, "\n");
+}
+
+/*
+ - at - print current situation
+ == #ifdef REDEBUG
+ == static void at(struct match *m, const char *title, const char *start, \
+ == const char *stop, sopno startst, sopno stopst);
+ == #endif
+ */
+static void
+at( struct match *m,
+ const char *title,
+ const char *start,
+ const char *stop,
+ sopno startst,
+ sopno stopst)
+{
+ if (!(m->eflags&REG_TRACE))
+ return;
+
+ printf("%s %s-", title, pchar(*start));
+ printf("%s ", pchar(*stop));
+ printf("%ld-%ld\n", (long)startst, (long)stopst);
+}
+
+#ifndef PCHARDONE
+#define PCHARDONE /* never again */
+/*
+ - pchar - make a character printable
+ == #ifdef REDEBUG
+ == static const char *pchar(int ch);
+ == #endif
+ *
+ * Is this identical to regchar() over in debug.c? Well, yes. But a
+ * duplicate here avoids having a debugging-capable regexec.o tied to
+ * a matching debug.o, and this is convenient. It all disappears in
+ * the non-debug compilation anyway, so it doesn't matter much.
+ */
+static const char * /* -> representation */
+pchar(int ch)
+{
+ static char pbuf[10];
+
+ if (isprint((uch)ch) || ch == ' ')
+ sprintf(pbuf, "%c", ch);
+ else
+ sprintf(pbuf, "\\%o", ch);
+ return(pbuf);
+}
+#endif
+#endif
+
+#undef matcher
+#undef fast
+#undef slow
+#undef dissect
+#undef backref
+#undef step
+#undef print
+#undef at
+#undef match
diff --git a/lib/libc/regex/grot/Makefile b/lib/libc/regex/grot/Makefile
new file mode 100644
index 0000000..3e41724
--- /dev/null
+++ b/lib/libc/regex/grot/Makefile
@@ -0,0 +1,98 @@
+# $FreeBSD$
+# You probably want to take -DREDEBUG out of CFLAGS, and put something like
+# -O in, *after* testing (-DREDEBUG strengthens testing by enabling a lot of
+# internal assertion checking). Take -Dconst= out for an ANSI compiler.
+# Do not take -DPOSIX_MISTAKE out. REGCFLAGS isn't important to you (it's
+# for my use in some special contexts).
+
+PATHS= ${.CURDIR}/.. ${.CURDIR}/../../locale ${.CURDIR}/../../../../include
+.PATH: ${PATHS}
+
+CFLAGS+= -DPOSIX_MISTAKE -DREDEBUG $(REGCFLAGS)
+.for incpath in ${PATHS}
+CFLAGS+= -I${incpath}
+.endfor
+
+# If you have an ANSI compiler, take -o out of MKHFLAGS. If you want
+# the Berkeley __P macro, put -b in.
+MKHFLAGS =
+
+LDFLAGS =
+
+# If you have an ANSI environment, take limits.h and stdlib.h out of
+# HMISSING and take memmove out of SRCMISSING and OBJMISSING.
+HMISSING =
+SRCMISSING = split.c
+OBJMISSING = split.o
+H = cname.h regex2.h utils.h $(HMISSING)
+REGSRC = regcomp.c regerror.c regexec.c regfree.c engine.c
+SRC = $(REGSRC) debug.c main.c $(SRCMISSING)
+
+# Internal stuff, should not need changing.
+OBJPRODN = regcomp.o regexec.o regerror.o regfree.o
+OBJS = $(OBJPRODN) debug.o main.o $(OBJMISSING)
+
+# Stuff that matters only if you're trying to lint the package.
+LINTFLAGS = -I. -Dstatic= -Dconst= -DREDEBUG
+LINTC = regcomp.c regexec.c regerror.c regfree.c debug.c main.c $(SRCMISSING)
+JUNKLINT =possible pointer alignment|null effect
+
+.SUFFIXES: .ih .h
+.c.ih:
+ sh mkh $(MKHFLAGS) -p $< >$@
+
+default: r
+
+re: $(OBJS)
+ $(CC) $(CFLAGS) $(LDFLAGS) $(OBJS) -o $@
+
+o: $(OBJPRODN)
+
+REGEXHSRC = ../regex2.h ../reg*.c
+h: $(REGEXHSRC)
+ sh mkh $(MKHFLAGS) -i _REGEX_H_ $(REGEXHSRC) >regex.tmp
+ cmp -s regex.tmp regex.h 2>/dev/null || cp regex.tmp regex.h
+ rm -f regex.tmp
+
+regex.h: h
+
+regcomp.o regexec.o regfree.o debug.o: utils.h regex.h regex2.h
+regcomp.o: cname.h regcomp.ih
+regexec.o: engine.c engine.ih
+regerror.o: regerror.ih
+regerror.o: utils.h
+debug.o: debug.ih
+main.o: main.ih
+
+r: re tests
+ ./re <tests
+ ./re -el <tests
+ ./re -er <tests
+
+ra: ./re tests
+ -./re <tests
+ -./re -el <tests
+ -./re -er <tests
+
+rx: ./re tests
+ ./re -x <tests
+ ./re -x -el <tests
+ ./re -x -er <tests
+
+t: ./re tests
+ -time ./re <tests
+ -time ./re -cs <tests
+ -time ./re -el <tests
+ -time ./re -cs -el <tests
+
+l: $(LINTC)
+ lint $(LINTFLAGS) -h $(LINTC) 2>&1 | egrep -v '$(JUNKLINT)' | tee lint
+
+clean: tidy
+ rm -f *.o *.s *.ih re
+
+tidy:
+ rm -f junk* core regex.tmp lint
+
+spotless: clean
+ rm -f regex.h
diff --git a/lib/libc/regex/grot/debug.c b/lib/libc/regex/grot/debug.c
new file mode 100644
index 0000000..caa2ca3
--- /dev/null
+++ b/lib/libc/regex/grot/debug.c
@@ -0,0 +1,212 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <regex.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "utils.h"
+#include "regex2.h"
+#include "debug.ih"
+
+/*
+ - regprint - print a regexp for debugging
+ == void regprint(regex_t *r, FILE *d);
+ */
+void
+regprint(r, d)
+regex_t *r;
+FILE *d;
+{
+ struct re_guts *g = r->re_g;
+ int i;
+ int c;
+ int last;
+
+ fprintf(d, "%ld states", (long)g->nstates);
+ fprintf(d, ", first %ld last %ld", (long)g->firststate,
+ (long)g->laststate);
+ if (g->iflags&USEBOL)
+ fprintf(d, ", USEBOL");
+ if (g->iflags&USEEOL)
+ fprintf(d, ", USEEOL");
+ if (g->iflags&BAD)
+ fprintf(d, ", BAD");
+ if (g->nsub > 0)
+ fprintf(d, ", nsub=%ld", (long)g->nsub);
+ if (g->must != NULL)
+ fprintf(d, ", must(%ld) `%*s'", (long)g->mlen, (int)g->mlen,
+ g->must);
+ if (g->backrefs)
+ fprintf(d, ", backrefs");
+ if (g->nplus > 0)
+ fprintf(d, ", nplus %ld", (long)g->nplus);
+ fprintf(d, "\n");
+ s_print(g, d);
+}
+
+/*
+ - s_print - print the strip for debugging
+ == static void s_print(struct re_guts *g, FILE *d);
+ */
+static void
+s_print(g, d)
+struct re_guts *g;
+FILE *d;
+{
+ sop *s;
+ cset *cs;
+ int i;
+ int done = 0;
+ sop opnd;
+ int col = 0;
+ int last;
+ sopno offset = 2;
+# define GAP() { if (offset % 5 == 0) { \
+ if (col > 40) { \
+ fprintf(d, "\n\t"); \
+ col = 0; \
+ } else { \
+ fprintf(d, " "); \
+ col++; \
+ } \
+ } else \
+ col++; \
+ offset++; \
+ }
+
+ if (OP(g->strip[0]) != OEND)
+ fprintf(d, "missing initial OEND!\n");
+ for (s = &g->strip[1]; !done; s++) {
+ opnd = OPND(*s);
+ switch (OP(*s)) {
+ case OEND:
+ fprintf(d, "\n");
+ done = 1;
+ break;
+ case OCHAR:
+ if (strchr("\\|()^$.[+*?{}!<> ", (char)opnd) != NULL)
+ fprintf(d, "\\%c", (char)opnd);
+ else
+ fprintf(d, "%s", regchar((char)opnd));
+ break;
+ case OBOL:
+ fprintf(d, "^");
+ break;
+ case OEOL:
+ fprintf(d, "$");
+ break;
+ case OBOW:
+ fprintf(d, "\\{");
+ break;
+ case OEOW:
+ fprintf(d, "\\}");
+ break;
+ case OANY:
+ fprintf(d, ".");
+ break;
+ case OANYOF:
+ fprintf(d, "[(%ld)", (long)opnd);
+#if 0
+ cs = &g->sets[opnd];
+ last = -1;
+ for (i = 0; i < g->csetsize+1; i++) /* +1 flushes */
+ if (CHIN(cs, i) && i < g->csetsize) {
+ if (last < 0) {
+ fprintf(d, "%s", regchar(i));
+ last = i;
+ }
+ } else {
+ if (last >= 0) {
+ if (last != i-1)
+ fprintf(d, "-%s",
+ regchar(i-1));
+ last = -1;
+ }
+ }
+#endif
+ fprintf(d, "]");
+ break;
+ case OBACK_:
+ fprintf(d, "(\\<%ld>", (long)opnd);
+ break;
+ case O_BACK:
+ fprintf(d, "<%ld>\\)", (long)opnd);
+ break;
+ case OPLUS_:
+ fprintf(d, "(+");
+ if (OP(*(s+opnd)) != O_PLUS)
+ fprintf(d, "<%ld>", (long)opnd);
+ break;
+ case O_PLUS:
+ if (OP(*(s-opnd)) != OPLUS_)
+ fprintf(d, "<%ld>", (long)opnd);
+ fprintf(d, "+)");
+ break;
+ case OQUEST_:
+ fprintf(d, "(?");
+ if (OP(*(s+opnd)) != O_QUEST)
+ fprintf(d, "<%ld>", (long)opnd);
+ break;
+ case O_QUEST:
+ if (OP(*(s-opnd)) != OQUEST_)
+ fprintf(d, "<%ld>", (long)opnd);
+ fprintf(d, "?)");
+ break;
+ case OLPAREN:
+ fprintf(d, "((<%ld>", (long)opnd);
+ break;
+ case ORPAREN:
+ fprintf(d, "<%ld>))", (long)opnd);
+ break;
+ case OCH_:
+ fprintf(d, "<");
+ if (OP(*(s+opnd)) != OOR2)
+ fprintf(d, "<%ld>", (long)opnd);
+ break;
+ case OOR1:
+ if (OP(*(s-opnd)) != OOR1 && OP(*(s-opnd)) != OCH_)
+ fprintf(d, "<%ld>", (long)opnd);
+ fprintf(d, "|");
+ break;
+ case OOR2:
+ fprintf(d, "|");
+ if (OP(*(s+opnd)) != OOR2 && OP(*(s+opnd)) != O_CH)
+ fprintf(d, "<%ld>", (long)opnd);
+ break;
+ case O_CH:
+ if (OP(*(s-opnd)) != OOR1)
+ fprintf(d, "<%ld>", (long)opnd);
+ fprintf(d, ">");
+ break;
+ default:
+ fprintf(d, "!%d(%d)!", OP(*s), opnd);
+ break;
+ }
+ if (!done)
+ GAP();
+ }
+}
+
+/*
+ - regchar - make a character printable
+ == static char *regchar(int ch);
+ */
+static char * /* -> representation */
+regchar(ch)
+int ch;
+{
+ static char buf[10];
+
+ if (isprint(ch) || ch == ' ')
+ sprintf(buf, "%c", ch);
+ else
+ sprintf(buf, "\\%o", ch);
+ return(buf);
+}
diff --git a/lib/libc/regex/grot/main.c b/lib/libc/regex/grot/main.c
new file mode 100644
index 0000000..9563de4
--- /dev/null
+++ b/lib/libc/regex/grot/main.c
@@ -0,0 +1,513 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <regex.h>
+#include <assert.h>
+
+#include "main.ih"
+
+char *progname;
+int debug = 0;
+int line = 0;
+int status = 0;
+
+int copts = REG_EXTENDED;
+int eopts = 0;
+regoff_t startoff = 0;
+regoff_t endoff = 0;
+
+
+extern int split();
+extern void regprint();
+
+/*
+ - main - do the simple case, hand off to regress() for regression
+ */
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ regex_t re;
+# define NS 10
+ regmatch_t subs[NS];
+ char erbuf[100];
+ int err;
+ size_t len;
+ int c;
+ int errflg = 0;
+ int i;
+ extern int optind;
+ extern char *optarg;
+
+ progname = argv[0];
+
+ while ((c = getopt(argc, argv, "c:e:S:E:x")) != -1)
+ switch (c) {
+ case 'c': /* compile options */
+ copts = options('c', optarg);
+ break;
+ case 'e': /* execute options */
+ eopts = options('e', optarg);
+ break;
+ case 'S': /* start offset */
+ startoff = (regoff_t)atoi(optarg);
+ break;
+ case 'E': /* end offset */
+ endoff = (regoff_t)atoi(optarg);
+ break;
+ case 'x': /* Debugging. */
+ debug++;
+ break;
+ case '?':
+ default:
+ errflg++;
+ break;
+ }
+ if (errflg) {
+ fprintf(stderr, "usage: %s ", progname);
+ fprintf(stderr, "[-c copt][-C][-d] [re]\n");
+ exit(2);
+ }
+
+ if (optind >= argc) {
+ regress(stdin);
+ exit(status);
+ }
+
+ err = regcomp(&re, argv[optind++], copts);
+ if (err) {
+ len = regerror(err, &re, erbuf, sizeof(erbuf));
+ fprintf(stderr, "error %s, %d/%d `%s'\n",
+ eprint(err), len, sizeof(erbuf), erbuf);
+ exit(status);
+ }
+ regprint(&re, stdout);
+
+ if (optind >= argc) {
+ regfree(&re);
+ exit(status);
+ }
+
+ if (eopts&REG_STARTEND) {
+ subs[0].rm_so = startoff;
+ subs[0].rm_eo = strlen(argv[optind]) - endoff;
+ }
+ err = regexec(&re, argv[optind], (size_t)NS, subs, eopts);
+ if (err) {
+ len = regerror(err, &re, erbuf, sizeof(erbuf));
+ fprintf(stderr, "error %s, %d/%d `%s'\n",
+ eprint(err), len, sizeof(erbuf), erbuf);
+ exit(status);
+ }
+ if (!(copts&REG_NOSUB)) {
+ len = (int)(subs[0].rm_eo - subs[0].rm_so);
+ if (subs[0].rm_so != -1) {
+ if (len != 0)
+ printf("match `%.*s'\n", len,
+ argv[optind] + subs[0].rm_so);
+ else
+ printf("match `'@%.1s\n",
+ argv[optind] + subs[0].rm_so);
+ }
+ for (i = 1; i < NS; i++)
+ if (subs[i].rm_so != -1)
+ printf("(%d) `%.*s'\n", i,
+ (int)(subs[i].rm_eo - subs[i].rm_so),
+ argv[optind] + subs[i].rm_so);
+ }
+ exit(status);
+}
+
+/*
+ - regress - main loop of regression test
+ == void regress(FILE *in);
+ */
+void
+regress(in)
+FILE *in;
+{
+ char inbuf[1000];
+# define MAXF 10
+ char *f[MAXF];
+ int nf;
+ int i;
+ char erbuf[100];
+ size_t ne;
+ char *badpat = "invalid regular expression";
+# define SHORT 10
+ char *bpname = "REG_BADPAT";
+ regex_t re;
+
+ while (fgets(inbuf, sizeof(inbuf), in) != NULL) {
+ line++;
+ if (inbuf[0] == '#' || inbuf[0] == '\n')
+ continue; /* NOTE CONTINUE */
+ inbuf[strlen(inbuf)-1] = '\0'; /* get rid of stupid \n */
+ if (debug)
+ fprintf(stdout, "%d:\n", line);
+ nf = split(inbuf, f, MAXF, "\t\t");
+ if (nf < 3) {
+ fprintf(stderr, "bad input, line %d\n", line);
+ exit(1);
+ }
+ for (i = 0; i < nf; i++)
+ if (strcmp(f[i], "\"\"") == 0)
+ f[i] = "";
+ if (nf <= 3)
+ f[3] = NULL;
+ if (nf <= 4)
+ f[4] = NULL;
+ try(f[0], f[1], f[2], f[3], f[4], options('c', f[1]));
+ if (opt('&', f[1])) /* try with either type of RE */
+ try(f[0], f[1], f[2], f[3], f[4],
+ options('c', f[1]) &~ REG_EXTENDED);
+ }
+
+ ne = regerror(REG_BADPAT, (regex_t *)NULL, erbuf, sizeof(erbuf));
+ if (strcmp(erbuf, badpat) != 0 || ne != strlen(badpat)+1) {
+ fprintf(stderr, "end: regerror() test gave `%s' not `%s'\n",
+ erbuf, badpat);
+ status = 1;
+ }
+ ne = regerror(REG_BADPAT, (regex_t *)NULL, erbuf, (size_t)SHORT);
+ if (strncmp(erbuf, badpat, SHORT-1) != 0 || erbuf[SHORT-1] != '\0' ||
+ ne != strlen(badpat)+1) {
+ fprintf(stderr, "end: regerror() short test gave `%s' not `%.*s'\n",
+ erbuf, SHORT-1, badpat);
+ status = 1;
+ }
+ ne = regerror(REG_ITOA|REG_BADPAT, (regex_t *)NULL, erbuf, sizeof(erbuf));
+ if (strcmp(erbuf, bpname) != 0 || ne != strlen(bpname)+1) {
+ fprintf(stderr, "end: regerror() ITOA test gave `%s' not `%s'\n",
+ erbuf, bpname);
+ status = 1;
+ }
+ re.re_endp = bpname;
+ ne = regerror(REG_ATOI, &re, erbuf, sizeof(erbuf));
+ if (atoi(erbuf) != (int)REG_BADPAT) {
+ fprintf(stderr, "end: regerror() ATOI test gave `%s' not `%ld'\n",
+ erbuf, (long)REG_BADPAT);
+ status = 1;
+ } else if (ne != strlen(erbuf)+1) {
+ fprintf(stderr, "end: regerror() ATOI test len(`%s') = %ld\n",
+ erbuf, (long)REG_BADPAT);
+ status = 1;
+ }
+}
+
+/*
+ - try - try it, and report on problems
+ == void try(char *f0, char *f1, char *f2, char *f3, char *f4, int opts);
+ */
+void
+try(f0, f1, f2, f3, f4, opts)
+char *f0;
+char *f1;
+char *f2;
+char *f3;
+char *f4;
+int opts; /* may not match f1 */
+{
+ regex_t re;
+# define NSUBS 10
+ regmatch_t subs[NSUBS];
+# define NSHOULD 15
+ char *should[NSHOULD];
+ int nshould;
+ char erbuf[100];
+ int err;
+ int len;
+ char *type = (opts & REG_EXTENDED) ? "ERE" : "BRE";
+ int i;
+ char *grump;
+ char f0copy[1000];
+ char f2copy[1000];
+
+ strcpy(f0copy, f0);
+ re.re_endp = (opts&REG_PEND) ? f0copy + strlen(f0copy) : NULL;
+ fixstr(f0copy);
+ err = regcomp(&re, f0copy, opts);
+ if (err != 0 && (!opt('C', f1) || err != efind(f2))) {
+ /* unexpected error or wrong error */
+ len = regerror(err, &re, erbuf, sizeof(erbuf));
+ fprintf(stderr, "%d: %s error %s, %d/%d `%s'\n",
+ line, type, eprint(err), len,
+ sizeof(erbuf), erbuf);
+ status = 1;
+ } else if (err == 0 && opt('C', f1)) {
+ /* unexpected success */
+ fprintf(stderr, "%d: %s should have given REG_%s\n",
+ line, type, f2);
+ status = 1;
+ err = 1; /* so we won't try regexec */
+ }
+
+ if (err != 0) {
+ regfree(&re);
+ return;
+ }
+
+ strcpy(f2copy, f2);
+ fixstr(f2copy);
+
+ if (options('e', f1)&REG_STARTEND) {
+ if (strchr(f2, '(') == NULL || strchr(f2, ')') == NULL)
+ fprintf(stderr, "%d: bad STARTEND syntax\n", line);
+ subs[0].rm_so = strchr(f2, '(') - f2 + 1;
+ subs[0].rm_eo = strchr(f2, ')') - f2;
+ }
+ err = regexec(&re, f2copy, NSUBS, subs, options('e', f1));
+
+ if (err != 0 && (f3 != NULL || err != REG_NOMATCH)) {
+ /* unexpected error or wrong error */
+ len = regerror(err, &re, erbuf, sizeof(erbuf));
+ fprintf(stderr, "%d: %s exec error %s, %d/%d `%s'\n",
+ line, type, eprint(err), len,
+ sizeof(erbuf), erbuf);
+ status = 1;
+ } else if (err != 0) {
+ /* nothing more to check */
+ } else if (f3 == NULL) {
+ /* unexpected success */
+ fprintf(stderr, "%d: %s exec should have failed\n",
+ line, type);
+ status = 1;
+ err = 1; /* just on principle */
+ } else if (opts&REG_NOSUB) {
+ /* nothing more to check */
+ } else if ((grump = check(f2, subs[0], f3)) != NULL) {
+ fprintf(stderr, "%d: %s %s\n", line, type, grump);
+ status = 1;
+ err = 1;
+ }
+
+ if (err != 0 || f4 == NULL) {
+ regfree(&re);
+ return;
+ }
+
+ for (i = 1; i < NSHOULD; i++)
+ should[i] = NULL;
+ nshould = split(f4, should+1, NSHOULD-1, ",");
+ if (nshould == 0) {
+ nshould = 1;
+ should[1] = "";
+ }
+ for (i = 1; i < NSUBS; i++) {
+ grump = check(f2, subs[i], should[i]);
+ if (grump != NULL) {
+ fprintf(stderr, "%d: %s $%d %s\n", line,
+ type, i, grump);
+ status = 1;
+ err = 1;
+ }
+ }
+
+ regfree(&re);
+}
+
+/*
+ - options - pick options out of a regression-test string
+ == int options(int type, char *s);
+ */
+int
+options(type, s)
+int type; /* 'c' compile, 'e' exec */
+char *s;
+{
+ char *p;
+ int o = (type == 'c') ? copts : eopts;
+ char *legal = (type == 'c') ? "bisnmp" : "^$#tl";
+
+ for (p = s; *p != '\0'; p++)
+ if (strchr(legal, *p) != NULL)
+ switch (*p) {
+ case 'b':
+ o &= ~REG_EXTENDED;
+ break;
+ case 'i':
+ o |= REG_ICASE;
+ break;
+ case 's':
+ o |= REG_NOSUB;
+ break;
+ case 'n':
+ o |= REG_NEWLINE;
+ break;
+ case 'm':
+ o &= ~REG_EXTENDED;
+ o |= REG_NOSPEC;
+ break;
+ case 'p':
+ o |= REG_PEND;
+ break;
+ case '^':
+ o |= REG_NOTBOL;
+ break;
+ case '$':
+ o |= REG_NOTEOL;
+ break;
+ case '#':
+ o |= REG_STARTEND;
+ break;
+ case 't': /* trace */
+ o |= REG_TRACE;
+ break;
+ case 'l': /* force long representation */
+ o |= REG_LARGE;
+ break;
+ case 'r': /* force backref use */
+ o |= REG_BACKR;
+ break;
+ }
+ return(o);
+}
+
+/*
+ - opt - is a particular option in a regression string?
+ == int opt(int c, char *s);
+ */
+int /* predicate */
+opt(c, s)
+int c;
+char *s;
+{
+ return(strchr(s, c) != NULL);
+}
+
+/*
+ - fixstr - transform magic characters in strings
+ == void fixstr(char *p);
+ */
+void
+fixstr(p)
+char *p;
+{
+ if (p == NULL)
+ return;
+
+ for (; *p != '\0'; p++)
+ if (*p == 'N')
+ *p = '\n';
+ else if (*p == 'T')
+ *p = '\t';
+ else if (*p == 'S')
+ *p = ' ';
+ else if (*p == 'Z')
+ *p = '\0';
+}
+
+/*
+ - check - check a substring match
+ == char *check(char *str, regmatch_t sub, char *should);
+ */
+char * /* NULL or complaint */
+check(str, sub, should)
+char *str;
+regmatch_t sub;
+char *should;
+{
+ int len;
+ int shlen;
+ char *p;
+ static char grump[500];
+ char *at = NULL;
+
+ if (should != NULL && strcmp(should, "-") == 0)
+ should = NULL;
+ if (should != NULL && should[0] == '@') {
+ at = should + 1;
+ should = "";
+ }
+
+ /* check rm_so and rm_eo for consistency */
+ if (sub.rm_so > sub.rm_eo || (sub.rm_so == -1 && sub.rm_eo != -1) ||
+ (sub.rm_so != -1 && sub.rm_eo == -1) ||
+ (sub.rm_so != -1 && sub.rm_so < 0) ||
+ (sub.rm_eo != -1 && sub.rm_eo < 0) ) {
+ sprintf(grump, "start %ld end %ld", (long)sub.rm_so,
+ (long)sub.rm_eo);
+ return(grump);
+ }
+
+ /* check for no match */
+ if (sub.rm_so == -1 && should == NULL)
+ return(NULL);
+ if (sub.rm_so == -1)
+ return("did not match");
+
+ /* check for in range */
+ if (sub.rm_eo > strlen(str)) {
+ sprintf(grump, "start %ld end %ld, past end of string",
+ (long)sub.rm_so, (long)sub.rm_eo);
+ return(grump);
+ }
+
+ len = (int)(sub.rm_eo - sub.rm_so);
+ shlen = (int)strlen(should);
+ p = str + sub.rm_so;
+
+ /* check for not supposed to match */
+ if (should == NULL) {
+ sprintf(grump, "matched `%.*s'", len, p);
+ return(grump);
+ }
+
+ /* check for wrong match */
+ if (len != shlen || strncmp(p, should, (size_t)shlen) != 0) {
+ sprintf(grump, "matched `%.*s' instead", len, p);
+ return(grump);
+ }
+ if (shlen > 0)
+ return(NULL);
+
+ /* check null match in right place */
+ if (at == NULL)
+ return(NULL);
+ shlen = strlen(at);
+ if (shlen == 0)
+ shlen = 1; /* force check for end-of-string */
+ if (strncmp(p, at, shlen) != 0) {
+ sprintf(grump, "matched null at `%.20s'", p);
+ return(grump);
+ }
+ return(NULL);
+}
+
+/*
+ - eprint - convert error number to name
+ == static char *eprint(int err);
+ */
+static char *
+eprint(err)
+int err;
+{
+ static char epbuf[100];
+ size_t len;
+
+ len = regerror(REG_ITOA|err, (regex_t *)NULL, epbuf, sizeof(epbuf));
+ assert(len <= sizeof(epbuf));
+ return(epbuf);
+}
+
+/*
+ - efind - convert error name to number
+ == static int efind(char *name);
+ */
+static int
+efind(name)
+char *name;
+{
+ static char efbuf[100];
+ size_t n;
+ regex_t re;
+
+ sprintf(efbuf, "REG_%s", name);
+ assert(strlen(efbuf) < sizeof(efbuf));
+ re.re_endp = efbuf;
+ (void) regerror(REG_ATOI, &re, efbuf, sizeof(efbuf));
+ return(atoi(efbuf));
+}
diff --git a/lib/libc/regex/grot/mkh b/lib/libc/regex/grot/mkh
new file mode 100755
index 0000000..1deba79
--- /dev/null
+++ b/lib/libc/regex/grot/mkh
@@ -0,0 +1,77 @@
+#! /bin/sh
+# mkh - pull headers out of C source
+# $FreeBSD$
+PATH=/bin:/usr/bin ; export PATH
+
+# egrep pattern to pick out marked lines
+egrep='^ =([ ]|$)'
+
+# Sed program to process marked lines into lines for the header file.
+# The markers have already been removed. Two things are done here: removal
+# of backslashed newlines, and some fudging of comments. The first is done
+# because -o needs to have prototypes on one line to strip them down.
+# Getting comments into the output is tricky; we turn C++-style // comments
+# into /* */ comments, after altering any existing */'s to avoid trouble.
+peel=' /\\$/N
+ /\\\n[ ]*/s///g
+ /\/\//s;\*/;* /;g
+ /\/\//s;//\(.*\);/*\1 */;'
+
+for a
+do
+ case "$a" in
+ -o) # old (pre-function-prototype) compiler
+ # add code to comment out argument lists
+ peel="$peel
+ "'/^\([^#\/][^\/]*[a-zA-Z0-9_)]\)(\(.*\))/s;;\1(/*\2*/);'
+ shift
+ ;;
+ -b) # funny Berkeley __P macro
+ peel="$peel
+ "'/^\([^#\/][^\/]*[a-zA-Z0-9_)]\)(\(.*\))/s;;\1 __P((\2));'
+ shift
+ ;;
+ -s) # compiler doesn't like `static foo();'
+ # add code to get rid of the `static'
+ peel="$peel
+ "'/^static[ ][^\/]*[a-zA-Z0-9_)](.*)/s;static.;;'
+ shift
+ ;;
+ -p) # private declarations
+ egrep='^ ==([ ]|$)'
+ shift
+ ;;
+ -i) # wrap in #ifndef, argument is name
+ ifndef="$2"
+ shift ; shift
+ ;;
+ *) break
+ ;;
+ esac
+done
+
+if test " $ifndef" != " "
+then
+ echo "#ifndef $ifndef"
+ echo "#define $ifndef /* never again */"
+fi
+echo "/* ========= begin header generated by $0 ========= */"
+echo '#ifdef __cplusplus'
+echo 'extern "C" {'
+echo '#endif'
+for f
+do
+ echo
+ echo "/* === $f === */"
+ egrep "$egrep" $f | sed 's/^ ==*[ ]//;s/^ ==*$//' | sed "$peel"
+ echo
+done
+echo '#ifdef __cplusplus'
+echo '}'
+echo '#endif'
+echo "/* ========= end header generated by $0 ========= */"
+if test " $ifndef" != " "
+then
+ echo "#endif"
+fi
+exit 0
diff --git a/lib/libc/regex/grot/split.c b/lib/libc/regex/grot/split.c
new file mode 100644
index 0000000..70e0ec5
--- /dev/null
+++ b/lib/libc/regex/grot/split.c
@@ -0,0 +1,319 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <string.h>
+
+/*
+ - split - divide a string into fields, like awk split()
+ = int split(char *string, char *fields[], int nfields, char *sep);
+ */
+int /* number of fields, including overflow */
+split(string, fields, nfields, sep)
+char *string;
+char *fields[]; /* list is not NULL-terminated */
+int nfields; /* number of entries available in fields[] */
+char *sep; /* "" white, "c" single char, "ab" [ab]+ */
+{
+ char *p = string;
+ char c; /* latest character */
+ char sepc = sep[0];
+ char sepc2;
+ int fn;
+ char **fp = fields;
+ char *sepp;
+ int trimtrail;
+
+ /* white space */
+ if (sepc == '\0') {
+ while ((c = *p++) == ' ' || c == '\t')
+ continue;
+ p--;
+ trimtrail = 1;
+ sep = " \t"; /* note, code below knows this is 2 long */
+ sepc = ' ';
+ } else
+ trimtrail = 0;
+ sepc2 = sep[1]; /* now we can safely pick this up */
+
+ /* catch empties */
+ if (*p == '\0')
+ return(0);
+
+ /* single separator */
+ if (sepc2 == '\0') {
+ fn = nfields;
+ for (;;) {
+ *fp++ = p;
+ fn--;
+ if (fn == 0)
+ break;
+ while ((c = *p++) != sepc)
+ if (c == '\0')
+ return(nfields - fn);
+ *(p-1) = '\0';
+ }
+ /* we have overflowed the fields vector -- just count them */
+ fn = nfields;
+ for (;;) {
+ while ((c = *p++) != sepc)
+ if (c == '\0')
+ return(fn);
+ fn++;
+ }
+ /* not reached */
+ }
+
+ /* two separators */
+ if (sep[2] == '\0') {
+ fn = nfields;
+ for (;;) {
+ *fp++ = p;
+ fn--;
+ while ((c = *p++) != sepc && c != sepc2)
+ if (c == '\0') {
+ if (trimtrail && **(fp-1) == '\0')
+ fn++;
+ return(nfields - fn);
+ }
+ if (fn == 0)
+ break;
+ *(p-1) = '\0';
+ while ((c = *p++) == sepc || c == sepc2)
+ continue;
+ p--;
+ }
+ /* we have overflowed the fields vector -- just count them */
+ fn = nfields;
+ while (c != '\0') {
+ while ((c = *p++) == sepc || c == sepc2)
+ continue;
+ p--;
+ fn++;
+ while ((c = *p++) != '\0' && c != sepc && c != sepc2)
+ continue;
+ }
+ /* might have to trim trailing white space */
+ if (trimtrail) {
+ p--;
+ while ((c = *--p) == sepc || c == sepc2)
+ continue;
+ p++;
+ if (*p != '\0') {
+ if (fn == nfields+1)
+ *p = '\0';
+ fn--;
+ }
+ }
+ return(fn);
+ }
+
+ /* n separators */
+ fn = 0;
+ for (;;) {
+ if (fn < nfields)
+ *fp++ = p;
+ fn++;
+ for (;;) {
+ c = *p++;
+ if (c == '\0')
+ return(fn);
+ sepp = sep;
+ while ((sepc = *sepp++) != '\0' && sepc != c)
+ continue;
+ if (sepc != '\0') /* it was a separator */
+ break;
+ }
+ if (fn < nfields)
+ *(p-1) = '\0';
+ for (;;) {
+ c = *p++;
+ sepp = sep;
+ while ((sepc = *sepp++) != '\0' && sepc != c)
+ continue;
+ if (sepc == '\0') /* it wasn't a separator */
+ break;
+ }
+ p--;
+ }
+
+ /* not reached */
+}
+
+#ifdef TEST_SPLIT
+
+
+/*
+ * test program
+ * pgm runs regression
+ * pgm sep splits stdin lines by sep
+ * pgm str sep splits str by sep
+ * pgm str sep n splits str by sep n times
+ */
+int
+main(argc, argv)
+int argc;
+char *argv[];
+{
+ char buf[512];
+ int n;
+# define MNF 10
+ char *fields[MNF];
+
+ if (argc > 4)
+ for (n = atoi(argv[3]); n > 0; n--) {
+ (void) strcpy(buf, argv[1]);
+ }
+ else if (argc > 3)
+ for (n = atoi(argv[3]); n > 0; n--) {
+ (void) strcpy(buf, argv[1]);
+ (void) split(buf, fields, MNF, argv[2]);
+ }
+ else if (argc > 2)
+ dosplit(argv[1], argv[2]);
+ else if (argc > 1)
+ while (fgets(buf, sizeof(buf), stdin) != NULL) {
+ buf[strlen(buf)-1] = '\0'; /* stomp newline */
+ dosplit(buf, argv[1]);
+ }
+ else
+ regress();
+
+ exit(0);
+}
+
+dosplit(string, seps)
+char *string;
+char *seps;
+{
+# define NF 5
+ char *fields[NF];
+ int nf;
+
+ nf = split(string, fields, NF, seps);
+ print(nf, NF, fields);
+}
+
+print(nf, nfp, fields)
+int nf;
+int nfp;
+char *fields[];
+{
+ int fn;
+ int bound;
+
+ bound = (nf > nfp) ? nfp : nf;
+ printf("%d:\t", nf);
+ for (fn = 0; fn < bound; fn++)
+ printf("\"%s\"%s", fields[fn], (fn+1 < nf) ? ", " : "\n");
+}
+
+#define RNF 5 /* some table entries know this */
+struct {
+ char *str;
+ char *seps;
+ int nf;
+ char *fi[RNF];
+} tests[] = {
+ "", " ", 0, { "" },
+ " ", " ", 2, { "", "" },
+ "x", " ", 1, { "x" },
+ "xy", " ", 1, { "xy" },
+ "x y", " ", 2, { "x", "y" },
+ "abc def g ", " ", 5, { "abc", "def", "", "g", "" },
+ " a bcd", " ", 4, { "", "", "a", "bcd" },
+ "a b c d e f", " ", 6, { "a", "b", "c", "d", "e f" },
+ " a b c d ", " ", 6, { "", "a", "b", "c", "d " },
+
+ "", " _", 0, { "" },
+ " ", " _", 2, { "", "" },
+ "x", " _", 1, { "x" },
+ "x y", " _", 2, { "x", "y" },
+ "ab _ cd", " _", 2, { "ab", "cd" },
+ " a_b c ", " _", 5, { "", "a", "b", "c", "" },
+ "a b c_d e f", " _", 6, { "a", "b", "c", "d", "e f" },
+ " a b c d ", " _", 6, { "", "a", "b", "c", "d " },
+
+ "", " _~", 0, { "" },
+ " ", " _~", 2, { "", "" },
+ "x", " _~", 1, { "x" },
+ "x y", " _~", 2, { "x", "y" },
+ "ab _~ cd", " _~", 2, { "ab", "cd" },
+ " a_b c~", " _~", 5, { "", "a", "b", "c", "" },
+ "a b_c d~e f", " _~", 6, { "a", "b", "c", "d", "e f" },
+ "~a b c d ", " _~", 6, { "", "a", "b", "c", "d " },
+
+ "", " _~-", 0, { "" },
+ " ", " _~-", 2, { "", "" },
+ "x", " _~-", 1, { "x" },
+ "x y", " _~-", 2, { "x", "y" },
+ "ab _~- cd", " _~-", 2, { "ab", "cd" },
+ " a_b c~", " _~-", 5, { "", "a", "b", "c", "" },
+ "a b_c-d~e f", " _~-", 6, { "a", "b", "c", "d", "e f" },
+ "~a-b c d ", " _~-", 6, { "", "a", "b", "c", "d " },
+
+ "", " ", 0, { "" },
+ " ", " ", 2, { "", "" },
+ "x", " ", 1, { "x" },
+ "xy", " ", 1, { "xy" },
+ "x y", " ", 2, { "x", "y" },
+ "abc def g ", " ", 4, { "abc", "def", "g", "" },
+ " a bcd", " ", 3, { "", "a", "bcd" },
+ "a b c d e f", " ", 6, { "a", "b", "c", "d", "e f" },
+ " a b c d ", " ", 6, { "", "a", "b", "c", "d " },
+
+ "", "", 0, { "" },
+ " ", "", 0, { "" },
+ "x", "", 1, { "x" },
+ "xy", "", 1, { "xy" },
+ "x y", "", 2, { "x", "y" },
+ "abc def g ", "", 3, { "abc", "def", "g" },
+ "\t a bcd", "", 2, { "a", "bcd" },
+ " a \tb\t c ", "", 3, { "a", "b", "c" },
+ "a b c d e ", "", 5, { "a", "b", "c", "d", "e" },
+ "a b\tc d e f", "", 6, { "a", "b", "c", "d", "e f" },
+ " a b c d e f ", "", 6, { "a", "b", "c", "d", "e f " },
+
+ NULL, NULL, 0, { NULL },
+};
+
+regress()
+{
+ char buf[512];
+ int n;
+ char *fields[RNF+1];
+ int nf;
+ int i;
+ int printit;
+ char *f;
+
+ for (n = 0; tests[n].str != NULL; n++) {
+ (void) strcpy(buf, tests[n].str);
+ fields[RNF] = NULL;
+ nf = split(buf, fields, RNF, tests[n].seps);
+ printit = 0;
+ if (nf != tests[n].nf) {
+ printf("split `%s' by `%s' gave %d fields, not %d\n",
+ tests[n].str, tests[n].seps, nf, tests[n].nf);
+ printit = 1;
+ } else if (fields[RNF] != NULL) {
+ printf("split() went beyond array end\n");
+ printit = 1;
+ } else {
+ for (i = 0; i < nf && i < RNF; i++) {
+ f = fields[i];
+ if (f == NULL)
+ f = "(NULL)";
+ if (strcmp(f, tests[n].fi[i]) != 0) {
+ printf("split `%s' by `%s' field %d is `%s', not `%s'\n",
+ tests[n].str, tests[n].seps,
+ i, fields[i], tests[n].fi[i]);
+ printit = 1;
+ }
+ }
+ }
+ if (printit)
+ print(nf, RNF, fields);
+ }
+}
+#endif
diff --git a/lib/libc/regex/grot/tests b/lib/libc/regex/grot/tests
new file mode 100644
index 0000000..050e7b2
--- /dev/null
+++ b/lib/libc/regex/grot/tests
@@ -0,0 +1,477 @@
+# regular expression test set
+# $FreeBSD$
+# Lines are at least three fields, separated by one or more tabs. "" stands
+# for an empty field. First field is an RE. Second field is flags. If
+# C flag given, regcomp() is expected to fail, and the third field is the
+# error name (minus the leading REG_).
+#
+# Otherwise it is expected to succeed, and the third field is the string to
+# try matching it against. If there is no fourth field, the match is
+# expected to fail. If there is a fourth field, it is the substring that
+# the RE is expected to match. If there is a fifth field, it is a comma-
+# separated list of what the subexpressions should match, with - indicating
+# no match for that one. In both the fourth and fifth fields, a (sub)field
+# starting with @ indicates that the (sub)expression is expected to match
+# a null string followed by the stuff after the @; this provides a way to
+# test where null strings match. The character `N' in REs and strings
+# is newline, `S' is space, `T' is tab, `Z' is NUL.
+#
+# The full list of flags:
+# - placeholder, does nothing
+# b RE is a BRE, not an ERE
+# & try it as both an ERE and a BRE
+# C regcomp() error expected, third field is error name
+# i REG_ICASE
+# m ("mundane") REG_NOSPEC
+# s REG_NOSUB (not really testable)
+# n REG_NEWLINE
+# ^ REG_NOTBOL
+# $ REG_NOTEOL
+# # REG_STARTEND (see below)
+# p REG_PEND
+#
+# For REG_STARTEND, the start/end offsets are those of the substring
+# enclosed in ().
+
+# basics
+a & a a
+abc & abc abc
+abc|de - abc abc
+a|b|c - abc a
+
+# parentheses and perversions thereof
+a(b)c - abc abc
+a\(b\)c b abc abc
+a( C EPAREN
+a( b a( a(
+a\( - a( a(
+a\( bC EPAREN
+a\(b bC EPAREN
+a(b C EPAREN
+a(b b a(b a(b
+# gag me with a right parenthesis -- 1003.2 goofed here (my fault, partly)
+a) - a) a)
+) - ) )
+# end gagging (in a just world, those *should* give EPAREN)
+a) b a) a)
+a\) bC EPAREN
+\) bC EPAREN
+a()b - ab ab
+a\(\)b b ab ab
+
+# anchoring and REG_NEWLINE
+^abc$ & abc abc
+a^b - a^b
+a^b b a^b a^b
+a$b - a$b
+a$b b a$b a$b
+^ & abc @abc
+$ & abc @
+^$ & "" @
+$^ - "" @
+\($\)\(^\) b "" @
+# stop retching, those are legitimate (although disgusting)
+^^ - "" @
+$$ - "" @
+b$ & abNc
+b$ &n abNc b
+^b$ & aNbNc
+^b$ &n aNbNc b
+^$ &n aNNb @Nb
+^$ n abc
+^$ n abcN @
+$^ n aNNb @Nb
+\($\)\(^\) bn aNNb @Nb
+^^ n^ aNNb @Nb
+$$ n aNNb @NN
+^a ^ a
+a$ $ a
+^a ^n aNb
+^b ^n aNb b
+a$ $n bNa
+b$ $n bNa b
+a*(^b$)c* - b b
+a*\(^b$\)c* b b b
+
+# certain syntax errors and non-errors
+| C EMPTY
+| b | |
+* C BADRPT
+* b * *
++ C BADRPT
+? C BADRPT
+"" &C EMPTY
+() - abc @abc
+\(\) b abc @abc
+a||b C EMPTY
+|ab C EMPTY
+ab| C EMPTY
+(|a)b C EMPTY
+(a|)b C EMPTY
+(*a) C BADRPT
+(+a) C BADRPT
+(?a) C BADRPT
+({1}a) C BADRPT
+\(\{1\}a\) bC BADRPT
+(a|*b) C BADRPT
+(a|+b) C BADRPT
+(a|?b) C BADRPT
+(a|{1}b) C BADRPT
+^* C BADRPT
+^* b * *
+^+ C BADRPT
+^? C BADRPT
+^{1} C BADRPT
+^\{1\} bC BADRPT
+
+# metacharacters, backslashes
+a.c & abc abc
+a[bc]d & abd abd
+a\*c & a*c a*c
+a\\b & a\b a\b
+a\\\*b & a\*b a\*b
+a\bc & abc abc
+a\ &C EESCAPE
+a\\bc & a\bc a\bc
+\{ bC BADRPT
+# trailing $ is a peculiar special case for the BRE code
+a$ & a a
+a$ & a$
+a\$ & a
+a\$ & a$ a$
+a\\$ & a
+a\\$ & a$
+a\\$ & a\$
+a\\$ & a\ a\
+
+# back references, ugh
+a\(b\)\2c bC ESUBREG
+a\(b\1\)c bC ESUBREG
+a\(b*\)c\1d b abbcbbd abbcbbd bb
+a\(b*\)c\1d b abbcbd
+a\(b*\)c\1d b abbcbbbd
+^\(.\)\1 b abc
+a\([bc]\)\1d b abcdabbd abbd b
+a\(\([bc]\)\2\)*d b abbccd abbccd
+a\(\([bc]\)\2\)*d b abbcbd
+# actually, this next one probably ought to fail, but the spec is unclear
+a\(\(b\)*\2\)*d b abbbd abbbd
+# here is a case that no NFA implementation does right
+\(ab*\)[ab]*\1 b ababaaa ababaaa a
+# check out normal matching in the presence of back refs
+\(a\)\1bcd b aabcd aabcd
+\(a\)\1bc*d b aabcd aabcd
+\(a\)\1bc*d b aabd aabd
+\(a\)\1bc*d b aabcccd aabcccd
+\(a\)\1bc*[ce]d b aabcccd aabcccd
+^\(a\)\1b\(c\)*cd$ b aabcccd aabcccd
+\(b*\)\(a*\1\)* b ab a
+\([^_]*\)\(_*\1\)* b foo_foo_bar_bar_bar_baz foo_foo foo,_foo
+\([^_]*\)\(_*\1\)* b bar_bar_bar_baz bar_bar_bar bar,_bar
+\([^_]*\)\(_*\1\)* b foo_bar_baz foo foo
+\(.*\)\1 b "" ""
+\(.*\)\1 b a ""
+\(.*\)\1 b aa aa
+\(.*\)\1 b aaa aa
+\(.*\)\1 b aaaa aaaa
+\([^_]*\)\1 b "" ""
+\([^_]*\)\1 b a ""
+\([^_]*\)\1 b aa aa
+\([^_]*\)\1 b aaa aa
+\([^_]*\)\1 b aaaa aaaa
+foo\(.*\)bar\1 b foolbarl foolbarl l
+foo\(.*\)bar\1 b foobar foobar ""
+\(\(.\)b\)*\1 b aba
+\(\(.\)b\)*\1 b abba
+\(\(.\)b\)*\1 b abbba
+\(\(.\)b\)*\1 b abbbba bbbb bb,b
+\(\(.\)b\)*\1 b abbbbba abbbbb bb,b
+\(\(.\)b\)*\1 b abbbbbba abbbbb bb,b
+\(\(.\)b\)*\1 b abbbbbbbbbbbbbba abbbbbbbbbbbbb bb,b
+\(\(.\)b\)*\1 b abbbbbbbbbbbbbbba abbbbbbbbbbbbbbb bb,b
+
+# ordinary repetitions
+ab*c & abc abc
+ab+c - abc abc
+ab?c - abc abc
+a\(*\)b b a*b a*b
+a\(**\)b b ab ab
+a\(***\)b bC BADRPT
+*a b *a *a
+**a b a a
+***a bC BADRPT
+
+# the dreaded bounded repetitions
+{ & { {
+{abc & {abc {abc
+{1 C BADRPT
+{1} C BADRPT
+a{b & a{b a{b
+a{1}b - ab ab
+a\{1\}b b ab ab
+a{1,}b - ab ab
+a\{1,\}b b ab ab
+a{1,2}b - aab aab
+a\{1,2\}b b aab aab
+a{1 C EBRACE
+a\{1 bC EBRACE
+a{1a C EBRACE
+a\{1a bC EBRACE
+a{1a} C BADBR
+a\{1a\} bC BADBR
+a{,2} - a{,2} a{,2}
+a\{,2\} bC BADBR
+a{,} - a{,} a{,}
+a\{,\} bC BADBR
+a{1,x} C BADBR
+a\{1,x\} bC BADBR
+a{1,x C EBRACE
+a\{1,x bC EBRACE
+a{300} C BADBR
+a\{300\} bC BADBR
+a{1,0} C BADBR
+a\{1,0\} bC BADBR
+ab{0,0}c - abcac ac
+ab\{0,0\}c b abcac ac
+ab{0,1}c - abcac abc
+ab\{0,1\}c b abcac abc
+ab{0,3}c - abbcac abbc
+ab\{0,3\}c b abbcac abbc
+ab{1,1}c - acabc abc
+ab\{1,1\}c b acabc abc
+ab{1,3}c - acabc abc
+ab\{1,3\}c b acabc abc
+ab{2,2}c - abcabbc abbc
+ab\{2,2\}c b abcabbc abbc
+ab{2,4}c - abcabbc abbc
+ab\{2,4\}c b abcabbc abbc
+((a{1,10}){1,10}){1,10} - a a a,a
+((a{1,10}){1,10}){1,10}bb - aaaaaaaaaaaaaaaaaaaaaaaaaaaaaabb aaaaaaaaaaaaaaaaaaaaaaaaaaaaaabb
+
+# multiple repetitions
+a** &C BADRPT
+a++ C BADRPT
+a?? C BADRPT
+a*+ C BADRPT
+a*? C BADRPT
+a+* C BADRPT
+a+? C BADRPT
+a?* C BADRPT
+a?+ C BADRPT
+a{1}{1} C BADRPT
+a*{1} C BADRPT
+a+{1} C BADRPT
+a?{1} C BADRPT
+a{1}* C BADRPT
+a{1}+ C BADRPT
+a{1}? C BADRPT
+a*{b} - a{b} a{b}
+a\{1\}\{1\} bC BADRPT
+a*\{1\} bC BADRPT
+a\{1\}* bC BADRPT
+
+# brackets, and numerous perversions thereof
+a[b]c & abc abc
+a[ab]c & abc abc
+a[^ab]c & adc adc
+a[]b]c & a]c a]c
+a[[b]c & a[c a[c
+a[-b]c & a-c a-c
+a[^]b]c & adc adc
+a[^-b]c & adc adc
+a[b-]c & a-c a-c
+a[b &C EBRACK
+a[] &C EBRACK
+a[1-3]c & a2c a2c
+a[3-1]c &C ERANGE
+a[1-3-5]c &C ERANGE
+a[[.-.]--]c & a-c a-c
+a[1- &C ERANGE
+a[[. &C EBRACK
+a[[.x &C EBRACK
+a[[.x. &C EBRACK
+a[[.x.] &C EBRACK
+a[[.x.]] & ax ax
+a[[.x,.]] &C ECOLLATE
+a[[.one.]]b & a1b a1b
+a[[.notdef.]]b &C ECOLLATE
+a[[.].]]b & a]b a]b
+a[[:alpha:]]c & abc abc
+a[[:notdef:]]c &C ECTYPE
+a[[: &C EBRACK
+a[[:alpha &C EBRACK
+a[[:alpha:] &C EBRACK
+a[[:alpha,:] &C ECTYPE
+a[[:]:]]b &C ECTYPE
+a[[:-:]]b &C ECTYPE
+a[[:alph:]] &C ECTYPE
+a[[:alphabet:]] &C ECTYPE
+[[:alnum:]]+ - -%@a0X- a0X
+[[:alpha:]]+ - -%@aX0- aX
+[[:blank:]]+ - aSSTb SST
+[[:cntrl:]]+ - aNTb NT
+[[:digit:]]+ - a019b 019
+[[:graph:]]+ - Sa%bS a%b
+[[:lower:]]+ - AabC ab
+[[:print:]]+ - NaSbN aSb
+[[:punct:]]+ - S%-&T %-&
+[[:space:]]+ - aSNTb SNT
+[[:upper:]]+ - aBCd BC
+[[:xdigit:]]+ - p0f3Cq 0f3C
+a[[=b=]]c & abc abc
+a[[= &C EBRACK
+a[[=b &C EBRACK
+a[[=b= &C EBRACK
+a[[=b=] &C EBRACK
+a[[=b,=]] &C ECOLLATE
+a[[=one=]]b & a1b a1b
+
+# complexities
+a(((b)))c - abc abc
+a(b|(c))d - abd abd
+a(b*|c)d - abbd abbd
+# just gotta have one DFA-buster, of course
+a[ab]{20} - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab
+# and an inline expansion in case somebody gets tricky
+a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab] - aaaaabaaaabaaaabaaaab aaaaabaaaabaaaabaaaab
+# and in case somebody just slips in an NFA...
+a[ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab][ab](wee|week)(knights|night) - aaaaabaaaabaaaabaaaabweeknights aaaaabaaaabaaaabaaaabweeknights
+# fish for anomalies as the number of states passes 32
+12345678901234567890123456789 - a12345678901234567890123456789b 12345678901234567890123456789
+123456789012345678901234567890 - a123456789012345678901234567890b 123456789012345678901234567890
+1234567890123456789012345678901 - a1234567890123456789012345678901b 1234567890123456789012345678901
+12345678901234567890123456789012 - a12345678901234567890123456789012b 12345678901234567890123456789012
+123456789012345678901234567890123 - a123456789012345678901234567890123b 123456789012345678901234567890123
+# and one really big one, beyond any plausible word width
+1234567890123456789012345678901234567890123456789012345678901234567890 - a1234567890123456789012345678901234567890123456789012345678901234567890b 1234567890123456789012345678901234567890123456789012345678901234567890
+# fish for problems as brackets go past 8
+[ab][cd][ef][gh][ij][kl][mn] - xacegikmoq acegikm
+[ab][cd][ef][gh][ij][kl][mn][op] - xacegikmoq acegikmo
+[ab][cd][ef][gh][ij][kl][mn][op][qr] - xacegikmoqy acegikmoq
+[ab][cd][ef][gh][ij][kl][mn][op][q] - xacegikmoqy acegikmoq
+
+# subtleties of matching
+abc & xabcy abc
+a\(b\)?c\1d b acd
+aBc i Abc Abc
+a[Bc]*d i abBCcd abBCcd
+0[[:upper:]]1 &i 0a1 0a1
+0[[:lower:]]1 &i 0A1 0A1
+a[^b]c &i abc
+a[^b]c &i aBc
+a[^b]c &i adc adc
+[a]b[c] - abc abc
+[a]b[a] - aba aba
+[abc]b[abc] - abc abc
+[abc]b[abd] - abd abd
+a(b?c)+d - accd accd
+(wee|week)(knights|night) - weeknights weeknights
+(we|wee|week|frob)(knights|night|day) - weeknights weeknights
+a[bc]d - xyzaaabcaababdacd abd
+a[ab]c - aaabc abc
+abc s abc abc
+
+# subexpressions
+a(b)(c)d - abcd abcd b,c
+a(((b)))c - abc abc b,b,b
+a(b|(c))d - abd abd b,-
+a(b*|c|e)d - abbd abbd bb
+a(b*|c|e)d - acd acd c
+a(b*|c|e)d - ad ad @d
+a(b?)c - abc abc b
+a(b?)c - ac ac @c
+a(b+)c - abc abc b
+a(b+)c - abbbc abbbc bbb
+a(b*)c - ac ac @c
+(a|ab)(bc([de]+)f|cde) - abcdef abcdef a,bcdef,de
+# the regression tester only asks for 9 subexpressions
+a(b)(c)(d)(e)(f)(g)(h)(i)(j)k - abcdefghijk abcdefghijk b,c,d,e,f,g,h,i,j
+a(b)(c)(d)(e)(f)(g)(h)(i)(j)(k)l - abcdefghijkl abcdefghijkl b,c,d,e,f,g,h,i,j,k
+a([bc]?)c - abc abc b
+a([bc]?)c - ac ac @c
+a([bc]+)c - abc abc b
+a([bc]+)c - abcc abcc bc
+a([bc]+)bc - abcbc abcbc bc
+a(bb+|b)b - abb abb b
+a(bbb+|bb+|b)b - abb abb b
+a(bbb+|bb+|b)b - abbb abbb bb
+a(bbb+|bb+|b)bb - abbb abbb b
+(.*).* - abcdef abcdef abcdef
+(a*)* - bc @b @b
+
+# do we get the right subexpression when it is used more than once?
+a(b|c)*d - ad ad -
+a(b|c)*d - abcd abcd c
+a(b|c)+d - abd abd b
+a(b|c)+d - abcd abcd c
+a(b|c?)+d - ad ad @d
+a(b|c?)+d - abcd abcd @d
+a(b|c){0,0}d - ad ad -
+a(b|c){0,1}d - ad ad -
+a(b|c){0,1}d - abd abd b
+a(b|c){0,2}d - ad ad -
+a(b|c){0,2}d - abcd abcd c
+a(b|c){0,}d - ad ad -
+a(b|c){0,}d - abcd abcd c
+a(b|c){1,1}d - abd abd b
+a(b|c){1,1}d - acd acd c
+a(b|c){1,2}d - abd abd b
+a(b|c){1,2}d - abcd abcd c
+a(b|c){1,}d - abd abd b
+a(b|c){1,}d - abcd abcd c
+a(b|c){2,2}d - acbd acbd b
+a(b|c){2,2}d - abcd abcd c
+a(b|c){2,4}d - abcd abcd c
+a(b|c){2,4}d - abcbd abcbd b
+a(b|c){2,4}d - abcbcd abcbcd c
+a(b|c){2,}d - abcd abcd c
+a(b|c){2,}d - abcbd abcbd b
+a(b+|((c)*))+d - abd abd @d,@d,-
+a(b+|((c)*))+d - abcd abcd @d,@d,-
+
+# check out the STARTEND option
+[abc] &# a(b)c b
+[abc] &# a(d)c
+[abc] &# a(bc)d b
+[abc] &# a(dc)d c
+. &# a()c
+b.*c &# b(bc)c bc
+b.* &# b(bc)c bc
+.*c &# b(bc)c bc
+
+# plain strings, with the NOSPEC flag
+abc m abc abc
+abc m xabcy abc
+abc m xyz
+a*b m aba*b a*b
+a*b m ab
+"" mC EMPTY
+
+# cases involving NULs
+aZb & a a
+aZb &p a
+aZb &p# (aZb) aZb
+aZ*b &p# (ab) ab
+a.b &# (aZb) aZb
+a.* &# (aZb)c aZb
+
+# word boundaries (ick)
+[[:<:]]a & a a
+[[:<:]]a & ba
+[[:<:]]a & -a a
+a[[:>:]] & a a
+a[[:>:]] & ab
+a[[:>:]] & a- a
+[[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc abc
+[[:<:]]a.c[[:>:]] & axcd-dayc-dazce-abc-q abc
+[[:<:]]a.c[[:>:]] & axc-dayc-dazce-abc axc
+
+# past problems
+(A[1])|(A[2])|(A[3])|(A[4])|(A[5])|(A[6])|(A[7])|(A[8])|(A[9])|(A[A]) - A1 A1
+abcdefghijklmnop i abcdefghijklmnop abcdefghijklmnop
+abcdefghijklmnopqrstuv i abcdefghijklmnopqrstuv abcdefghijklmnopqrstuv
+(ALAK)|(ALT[AB])|(CC[123]1)|(CM[123]1)|(GAMC)|(LC[23][EO ])|(SEM[1234])|(SL[ES][12])|(SLWW)|(SLF )|(SLDT)|(VWH[12])|(WH[34][EW])|(WP1[ESN]) - CC11 CC11
+CC[13]1|a{21}[23][EO][123][Es][12]a{15}aa[34][EW]aaaaaaa[X]a - CC11 CC11
+# PR 130504
+(.|())(b) - ab ab
+(()|.)(b) - ab ab
diff --git a/lib/libc/regex/re_format.7 b/lib/libc/regex/re_format.7
new file mode 100644
index 0000000..a2a527d
--- /dev/null
+++ b/lib/libc/regex/re_format.7
@@ -0,0 +1,483 @@
+.\" Copyright (c) 1992, 1993, 1994 Henry Spencer.
+.\" Copyright (c) 1992, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Henry Spencer.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by the University of
+.\" California, Berkeley and its contributors.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)re_format.7 8.3 (Berkeley) 3/20/94
+.\" $FreeBSD$
+.\"
+.Dd March 20, 1994
+.Dt RE_FORMAT 7
+.Os
+.Sh NAME
+.Nm re_format
+.Nd POSIX 1003.2 regular expressions
+.Sh DESCRIPTION
+Regular expressions
+.Pq Dq RE Ns s ,
+as defined in
+.St -p1003.2 ,
+come in two forms:
+modern REs (roughly those of
+.Xr egrep 1 ;
+1003.2 calls these
+.Dq extended
+REs)
+and obsolete REs (roughly those of
+.Xr ed 1 ;
+1003.2
+.Dq basic
+REs).
+Obsolete REs mostly exist for backward compatibility in some old programs;
+they will be discussed at the end.
+.St -p1003.2
+leaves some aspects of RE syntax and semantics open;
+`\(dd' marks decisions on these aspects that
+may not be fully portable to other
+.St -p1003.2
+implementations.
+.Pp
+A (modern) RE is one\(dd or more non-empty\(dd
+.Em branches ,
+separated by
+.Ql \&| .
+It matches anything that matches one of the branches.
+.Pp
+A branch is one\(dd or more
+.Em pieces ,
+concatenated.
+It matches a match for the first, followed by a match for the second, etc.
+.Pp
+A piece is an
+.Em atom
+possibly followed
+by a single\(dd
+.Ql \&* ,
+.Ql \&+ ,
+.Ql \&? ,
+or
+.Em bound .
+An atom followed by
+.Ql \&*
+matches a sequence of 0 or more matches of the atom.
+An atom followed by
+.Ql \&+
+matches a sequence of 1 or more matches of the atom.
+An atom followed by
+.Ql ?\&
+matches a sequence of 0 or 1 matches of the atom.
+.Pp
+A
+.Em bound
+is
+.Ql \&{
+followed by an unsigned decimal integer,
+possibly followed by
+.Ql \&,
+possibly followed by another unsigned decimal integer,
+always followed by
+.Ql \&} .
+The integers must lie between 0 and
+.Dv RE_DUP_MAX
+(255\(dd) inclusive,
+and if there are two of them, the first may not exceed the second.
+An atom followed by a bound containing one integer
+.Em i
+and no comma matches
+a sequence of exactly
+.Em i
+matches of the atom.
+An atom followed by a bound
+containing one integer
+.Em i
+and a comma matches
+a sequence of
+.Em i
+or more matches of the atom.
+An atom followed by a bound
+containing two integers
+.Em i
+and
+.Em j
+matches
+a sequence of
+.Em i
+through
+.Em j
+(inclusive) matches of the atom.
+.Pp
+An atom is a regular expression enclosed in
+.Ql ()
+(matching a match for the
+regular expression),
+an empty set of
+.Ql ()
+(matching the null string)\(dd,
+a
+.Em bracket expression
+(see below),
+.Ql .\&
+(matching any single character),
+.Ql \&^
+(matching the null string at the beginning of a line),
+.Ql \&$
+(matching the null string at the end of a line), a
+.Ql \e
+followed by one of the characters
+.Ql ^.[$()|*+?{\e
+(matching that character taken as an ordinary character),
+a
+.Ql \e
+followed by any other character\(dd
+(matching that character taken as an ordinary character,
+as if the
+.Ql \e
+had not been present\(dd),
+or a single character with no other significance (matching that character).
+A
+.Ql \&{
+followed by a character other than a digit is an ordinary
+character, not the beginning of a bound\(dd.
+It is illegal to end an RE with
+.Ql \e .
+.Pp
+A
+.Em bracket expression
+is a list of characters enclosed in
+.Ql [] .
+It normally matches any single character from the list (but see below).
+If the list begins with
+.Ql \&^ ,
+it matches any single character
+(but see below)
+.Em not
+from the rest of the list.
+If two characters in the list are separated by
+.Ql \&- ,
+this is shorthand
+for the full
+.Em range
+of characters between those two (inclusive) in the
+collating sequence,
+.No e.g. Ql [0-9]
+in ASCII matches any decimal digit.
+It is illegal\(dd for two ranges to share an
+endpoint,
+.No e.g. Ql a-c-e .
+Ranges are very collating-sequence-dependent,
+and portable programs should avoid relying on them.
+.Pp
+To include a literal
+.Ql \&]
+in the list, make it the first character
+(following a possible
+.Ql \&^ ) .
+To include a literal
+.Ql \&- ,
+make it the first or last character,
+or the second endpoint of a range.
+To use a literal
+.Ql \&-
+as the first endpoint of a range,
+enclose it in
+.Ql [.\&
+and
+.Ql .]\&
+to make it a collating element (see below).
+With the exception of these and some combinations using
+.Ql \&[
+(see next paragraphs), all other special characters, including
+.Ql \e ,
+lose their special significance within a bracket expression.
+.Pp
+Within a bracket expression, a collating element (a character,
+a multi-character sequence that collates as if it were a single character,
+or a collating-sequence name for either)
+enclosed in
+.Ql [.\&
+and
+.Ql .]\&
+stands for the
+sequence of characters of that collating element.
+The sequence is a single element of the bracket expression's list.
+A bracket expression containing a multi-character collating element
+can thus match more than one character,
+e.g.\& if the collating sequence includes a
+.Ql ch
+collating element,
+then the RE
+.Ql [[.ch.]]*c
+matches the first five characters
+of
+.Ql chchcc .
+.Pp
+Within a bracket expression, a collating element enclosed in
+.Ql [=
+and
+.Ql =]
+is an equivalence class, standing for the sequences of characters
+of all collating elements equivalent to that one, including itself.
+(If there are no other equivalent collating elements,
+the treatment is as if the enclosing delimiters were
+.Ql [.\&
+and
+.Ql .] . )
+For example, if
+.Ql x
+and
+.Ql y
+are the members of an equivalence class,
+then
+.Ql [[=x=]] ,
+.Ql [[=y=]] ,
+and
+.Ql [xy]
+are all synonymous.
+An equivalence class may not\(dd be an endpoint
+of a range.
+.Pp
+Within a bracket expression, the name of a
+.Em character class
+enclosed in
+.Ql [:
+and
+.Ql :]
+stands for the list of all characters belonging to that
+class.
+Standard character class names are:
+.Bl -column "alnum" "digit" "xdigit" -offset indent
+.It Em "alnum digit punct"
+.It Em "alpha graph space"
+.It Em "blank lower upper"
+.It Em "cntrl print xdigit"
+.El
+.Pp
+These stand for the character classes defined in
+.Xr ctype 3 .
+A locale may provide others.
+A character class may not be used as an endpoint of a range.
+.Pp
+A bracketed expression like
+.Ql [[:class:]]
+can be used to match a single character that belongs to a character
+class.
+The reverse, matching any character that does not belong to a specific
+class, the negation operator of bracket expressions may be used:
+.Ql [^[:class:]] .
+.Pp
+There are two special cases\(dd of bracket expressions:
+the bracket expressions
+.Ql [[:<:]]
+and
+.Ql [[:>:]]
+match the null string at the beginning and end of a word respectively.
+A word is defined as a sequence of word characters
+which is neither preceded nor followed by
+word characters.
+A word character is an
+.Em alnum
+character (as defined by
+.Xr ctype 3 )
+or an underscore.
+This is an extension,
+compatible with but not specified by
+.St -p1003.2 ,
+and should be used with
+caution in software intended to be portable to other systems.
+.Pp
+In the event that an RE could match more than one substring of a given
+string,
+the RE matches the one starting earliest in the string.
+If the RE could match more than one substring starting at that point,
+it matches the longest.
+Subexpressions also match the longest possible substrings, subject to
+the constraint that the whole match be as long as possible,
+with subexpressions starting earlier in the RE taking priority over
+ones starting later.
+Note that higher-level subexpressions thus take priority over
+their lower-level component subexpressions.
+.Pp
+Match lengths are measured in characters, not collating elements.
+A null string is considered longer than no match at all.
+For example,
+.Ql bb*
+matches the three middle characters of
+.Ql abbbc ,
+.Ql (wee|week)(knights|nights)
+matches all ten characters of
+.Ql weeknights ,
+when
+.Ql (.*).*\&
+is matched against
+.Ql abc
+the parenthesized subexpression
+matches all three characters, and
+when
+.Ql (a*)*
+is matched against
+.Ql bc
+both the whole RE and the parenthesized
+subexpression match the null string.
+.Pp
+If case-independent matching is specified,
+the effect is much as if all case distinctions had vanished from the
+alphabet.
+When an alphabetic that exists in multiple cases appears as an
+ordinary character outside a bracket expression, it is effectively
+transformed into a bracket expression containing both cases,
+.No e.g. Ql x
+becomes
+.Ql [xX] .
+When it appears inside a bracket expression, all case counterparts
+of it are added to the bracket expression, so that (e.g.)
+.Ql [x]
+becomes
+.Ql [xX]
+and
+.Ql [^x]
+becomes
+.Ql [^xX] .
+.Pp
+No particular limit is imposed on the length of REs\(dd.
+Programs intended to be portable should not employ REs longer
+than 256 bytes,
+as an implementation can refuse to accept such REs and remain
+POSIX-compliant.
+.Pp
+Obsolete
+.Pq Dq basic
+regular expressions differ in several respects.
+.Ql \&|
+is an ordinary character and there is no equivalent
+for its functionality.
+.Ql \&+
+and
+.Ql ?\&
+are ordinary characters, and their functionality
+can be expressed using bounds
+.No ( Ql {1,}
+or
+.Ql {0,1}
+respectively).
+Also note that
+.Ql x+
+in modern REs is equivalent to
+.Ql xx* .
+The delimiters for bounds are
+.Ql \e{
+and
+.Ql \e} ,
+with
+.Ql \&{
+and
+.Ql \&}
+by themselves ordinary characters.
+The parentheses for nested subexpressions are
+.Ql \e(
+and
+.Ql \e) ,
+with
+.Ql \&(
+and
+.Ql \&)
+by themselves ordinary characters.
+.Ql \&^
+is an ordinary character except at the beginning of the
+RE or\(dd the beginning of a parenthesized subexpression,
+.Ql \&$
+is an ordinary character except at the end of the
+RE or\(dd the end of a parenthesized subexpression,
+and
+.Ql \&*
+is an ordinary character if it appears at the beginning of the
+RE or the beginning of a parenthesized subexpression
+(after a possible leading
+.Ql \&^ ) .
+Finally, there is one new type of atom, a
+.Em back reference :
+.Ql \e
+followed by a non-zero decimal digit
+.Em d
+matches the same sequence of characters
+matched by the
+.Em d Ns th
+parenthesized subexpression
+(numbering subexpressions by the positions of their opening parentheses,
+left to right),
+so that (e.g.)
+.Ql \e([bc]\e)\e1
+matches
+.Ql bb
+or
+.Ql cc
+but not
+.Ql bc .
+.Sh SEE ALSO
+.Xr regex 3
+.Rs
+.%T Regular Expression Notation
+.%R IEEE Std
+.%N 1003.2
+.%P section 2.8
+.Re
+.Sh BUGS
+Having two kinds of REs is a botch.
+.Pp
+The current
+.St -p1003.2
+spec says that
+.Ql \&)
+is an ordinary character in
+the absence of an unmatched
+.Ql \&( ;
+this was an unintentional result of a wording error,
+and change is likely.
+Avoid relying on it.
+.Pp
+Back references are a dreadful botch,
+posing major problems for efficient implementations.
+They are also somewhat vaguely defined
+(does
+.Ql a\e(\e(b\e)*\e2\e)*d
+match
+.Ql abbbd ? ) .
+Avoid using them.
+.Pp
+.St -p1003.2
+specification of case-independent matching is vague.
+The
+.Dq one case implies all cases
+definition given above
+is current consensus among implementors as to the right interpretation.
+.Pp
+The syntax for word boundaries is incredibly ugly.
diff --git a/lib/libc/regex/regcomp.c b/lib/libc/regex/regcomp.c
new file mode 100644
index 0000000..68ffa66
--- /dev/null
+++ b/lib/libc/regex/regcomp.c
@@ -0,0 +1,1784 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)regcomp.c 8.5 (Berkeley) 3/20/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regcomp.c 8.5 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <regex.h>
+#include <runetype.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "collate.h"
+
+#include "utils.h"
+#include "regex2.h"
+
+#include "cname.h"
+
+/*
+ * parse structure, passed up and down to avoid global variables and
+ * other clumsinesses
+ */
+struct parse {
+ char *next; /* next character in RE */
+ char *end; /* end of string (-> NUL normally) */
+ int error; /* has an error been seen? */
+ sop *strip; /* malloced strip */
+ sopno ssize; /* malloced strip size (allocated) */
+ sopno slen; /* malloced strip length (used) */
+ int ncsalloc; /* number of csets allocated */
+ struct re_guts *g;
+# define NPAREN 10 /* we need to remember () 1-9 for back refs */
+ sopno pbegin[NPAREN]; /* -> ( ([0] unused) */
+ sopno pend[NPAREN]; /* -> ) ([0] unused) */
+};
+
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regcomp.c === */
+static void p_ere(struct parse *p, int stop);
+static void p_ere_exp(struct parse *p);
+static void p_str(struct parse *p);
+static void p_bre(struct parse *p, int end1, int end2);
+static int p_simp_re(struct parse *p, int starordinary);
+static int p_count(struct parse *p);
+static void p_bracket(struct parse *p);
+static void p_b_term(struct parse *p, cset *cs);
+static void p_b_cclass(struct parse *p, cset *cs);
+static void p_b_eclass(struct parse *p, cset *cs);
+static wint_t p_b_symbol(struct parse *p);
+static wint_t p_b_coll_elem(struct parse *p, wint_t endc);
+static wint_t othercase(wint_t ch);
+static void bothcases(struct parse *p, wint_t ch);
+static void ordinary(struct parse *p, wint_t ch);
+static void nonnewline(struct parse *p);
+static void repeat(struct parse *p, sopno start, int from, int to);
+static int seterr(struct parse *p, int e);
+static cset *allocset(struct parse *p);
+static void freeset(struct parse *p, cset *cs);
+static void CHadd(struct parse *p, cset *cs, wint_t ch);
+static void CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max);
+static void CHaddtype(struct parse *p, cset *cs, wctype_t wct);
+static wint_t singleton(cset *cs);
+static sopno dupl(struct parse *p, sopno start, sopno finish);
+static void doemit(struct parse *p, sop op, size_t opnd);
+static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos);
+static void dofwd(struct parse *p, sopno pos, sop value);
+static int enlarge(struct parse *p, sopno size);
+static void stripsnug(struct parse *p, struct re_guts *g);
+static void findmust(struct parse *p, struct re_guts *g);
+static int altoffset(sop *scan, int offset);
+static void computejumps(struct parse *p, struct re_guts *g);
+static void computematchjumps(struct parse *p, struct re_guts *g);
+static sopno pluscount(struct parse *p, struct re_guts *g);
+static wint_t wgetnext(struct parse *p);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
+
+static char nuls[10]; /* place to point scanner in event of error */
+
+/*
+ * macros for use with parse structure
+ * BEWARE: these know that the parse structure is named `p' !!!
+ */
+#define PEEK() (*p->next)
+#define PEEK2() (*(p->next+1))
+#define MORE() (p->next < p->end)
+#define MORE2() (p->next+1 < p->end)
+#define SEE(c) (MORE() && PEEK() == (c))
+#define SEETWO(a, b) (MORE() && MORE2() && PEEK() == (a) && PEEK2() == (b))
+#define EAT(c) ((SEE(c)) ? (NEXT(), 1) : 0)
+#define EATTWO(a, b) ((SEETWO(a, b)) ? (NEXT2(), 1) : 0)
+#define NEXT() (p->next++)
+#define NEXT2() (p->next += 2)
+#define NEXTn(n) (p->next += (n))
+#define GETNEXT() (*p->next++)
+#define WGETNEXT() wgetnext(p)
+#define SETERROR(e) seterr(p, (e))
+#define REQUIRE(co, e) ((co) || SETERROR(e))
+#define MUSTSEE(c, e) (REQUIRE(MORE() && PEEK() == (c), e))
+#define MUSTEAT(c, e) (REQUIRE(MORE() && GETNEXT() == (c), e))
+#define MUSTNOTSEE(c, e) (REQUIRE(!MORE() || PEEK() != (c), e))
+#define EMIT(op, sopnd) doemit(p, (sop)(op), (size_t)(sopnd))
+#define INSERT(op, pos) doinsert(p, (sop)(op), HERE()-(pos)+1, pos)
+#define AHEAD(pos) dofwd(p, pos, HERE()-(pos))
+#define ASTERN(sop, pos) EMIT(sop, HERE()-pos)
+#define HERE() (p->slen)
+#define THERE() (p->slen - 1)
+#define THERETHERE() (p->slen - 2)
+#define DROP(n) (p->slen -= (n))
+
+#ifndef NDEBUG
+static int never = 0; /* for use in asserts; shuts lint up */
+#else
+#define never 0 /* some <assert.h>s have bugs too */
+#endif
+
+/* Macro used by computejump()/computematchjump() */
+#define MIN(a,b) ((a)<(b)?(a):(b))
+
+/*
+ - regcomp - interface for parser and compilation
+ = extern int regcomp(regex_t *, const char *, int);
+ = #define REG_BASIC 0000
+ = #define REG_EXTENDED 0001
+ = #define REG_ICASE 0002
+ = #define REG_NOSUB 0004
+ = #define REG_NEWLINE 0010
+ = #define REG_NOSPEC 0020
+ = #define REG_PEND 0040
+ = #define REG_DUMP 0200
+ */
+int /* 0 success, otherwise REG_something */
+regcomp(regex_t * __restrict preg,
+ const char * __restrict pattern,
+ int cflags)
+{
+ struct parse pa;
+ struct re_guts *g;
+ struct parse *p = &pa;
+ int i;
+ size_t len;
+#ifdef REDEBUG
+# define GOODFLAGS(f) (f)
+#else
+# define GOODFLAGS(f) ((f)&~REG_DUMP)
+#endif
+
+ cflags = GOODFLAGS(cflags);
+ if ((cflags&REG_EXTENDED) && (cflags&REG_NOSPEC))
+ return(REG_INVARG);
+
+ if (cflags&REG_PEND) {
+ if (preg->re_endp < pattern)
+ return(REG_INVARG);
+ len = preg->re_endp - pattern;
+ } else
+ len = strlen((char *)pattern);
+
+ /* do the mallocs early so failure handling is easy */
+ g = (struct re_guts *)malloc(sizeof(struct re_guts));
+ if (g == NULL)
+ return(REG_ESPACE);
+ p->ssize = len/(size_t)2*(size_t)3 + (size_t)1; /* ugh */
+ p->strip = (sop *)malloc(p->ssize * sizeof(sop));
+ p->slen = 0;
+ if (p->strip == NULL) {
+ free((char *)g);
+ return(REG_ESPACE);
+ }
+
+ /* set things up */
+ p->g = g;
+ p->next = (char *)pattern; /* convenience; we do not modify it */
+ p->end = p->next + len;
+ p->error = 0;
+ p->ncsalloc = 0;
+ for (i = 0; i < NPAREN; i++) {
+ p->pbegin[i] = 0;
+ p->pend[i] = 0;
+ }
+ g->sets = NULL;
+ g->ncsets = 0;
+ g->cflags = cflags;
+ g->iflags = 0;
+ g->nbol = 0;
+ g->neol = 0;
+ g->must = NULL;
+ g->moffset = -1;
+ g->charjump = NULL;
+ g->matchjump = NULL;
+ g->mlen = 0;
+ g->nsub = 0;
+ g->backrefs = 0;
+
+ /* do it */
+ EMIT(OEND, 0);
+ g->firststate = THERE();
+ if (cflags&REG_EXTENDED)
+ p_ere(p, OUT);
+ else if (cflags&REG_NOSPEC)
+ p_str(p);
+ else
+ p_bre(p, OUT, OUT);
+ EMIT(OEND, 0);
+ g->laststate = THERE();
+
+ /* tidy up loose ends and fill things in */
+ stripsnug(p, g);
+ findmust(p, g);
+ /* only use Boyer-Moore algorithm if the pattern is bigger
+ * than three characters
+ */
+ if(g->mlen > 3) {
+ computejumps(p, g);
+ computematchjumps(p, g);
+ if(g->matchjump == NULL && g->charjump != NULL) {
+ free(g->charjump);
+ g->charjump = NULL;
+ }
+ }
+ g->nplus = pluscount(p, g);
+ g->magic = MAGIC2;
+ preg->re_nsub = g->nsub;
+ preg->re_g = g;
+ preg->re_magic = MAGIC1;
+#ifndef REDEBUG
+ /* not debugging, so can't rely on the assert() in regexec() */
+ if (g->iflags&BAD)
+ SETERROR(REG_ASSERT);
+#endif
+
+ /* win or lose, we're done */
+ if (p->error != 0) /* lose */
+ regfree(preg);
+ return(p->error);
+}
+
+/*
+ - p_ere - ERE parser top level, concatenation and alternation
+ == static void p_ere(struct parse *p, int_t stop);
+ */
+static void
+p_ere(struct parse *p,
+ int stop) /* character this ERE should end at */
+{
+ char c;
+ sopno prevback;
+ sopno prevfwd;
+ sopno conc;
+ int first = 1; /* is this the first alternative? */
+
+ for (;;) {
+ /* do a bunch of concatenated expressions */
+ conc = HERE();
+ while (MORE() && (c = PEEK()) != '|' && c != stop)
+ p_ere_exp(p);
+ (void)REQUIRE(HERE() != conc, REG_EMPTY); /* require nonempty */
+
+ if (!EAT('|'))
+ break; /* NOTE BREAK OUT */
+
+ if (first) {
+ INSERT(OCH_, conc); /* offset is wrong */
+ prevfwd = conc;
+ prevback = conc;
+ first = 0;
+ }
+ ASTERN(OOR1, prevback);
+ prevback = THERE();
+ AHEAD(prevfwd); /* fix previous offset */
+ prevfwd = HERE();
+ EMIT(OOR2, 0); /* offset is very wrong */
+ }
+
+ if (!first) { /* tail-end fixups */
+ AHEAD(prevfwd);
+ ASTERN(O_CH, prevback);
+ }
+
+ assert(!MORE() || SEE(stop));
+}
+
+/*
+ - p_ere_exp - parse one subERE, an atom possibly followed by a repetition op
+ == static void p_ere_exp(struct parse *p);
+ */
+static void
+p_ere_exp(struct parse *p)
+{
+ char c;
+ wint_t wc;
+ sopno pos;
+ int count;
+ int count2;
+ sopno subno;
+ int wascaret = 0;
+
+ assert(MORE()); /* caller should have ensured this */
+ c = GETNEXT();
+
+ pos = HERE();
+ switch (c) {
+ case '(':
+ (void)REQUIRE(MORE(), REG_EPAREN);
+ p->g->nsub++;
+ subno = p->g->nsub;
+ if (subno < NPAREN)
+ p->pbegin[subno] = HERE();
+ EMIT(OLPAREN, subno);
+ if (!SEE(')'))
+ p_ere(p, ')');
+ if (subno < NPAREN) {
+ p->pend[subno] = HERE();
+ assert(p->pend[subno] != 0);
+ }
+ EMIT(ORPAREN, subno);
+ (void)MUSTEAT(')', REG_EPAREN);
+ break;
+#ifndef POSIX_MISTAKE
+ case ')': /* happens only if no current unmatched ( */
+ /*
+ * You may ask, why the ifndef? Because I didn't notice
+ * this until slightly too late for 1003.2, and none of the
+ * other 1003.2 regular-expression reviewers noticed it at
+ * all. So an unmatched ) is legal POSIX, at least until
+ * we can get it fixed.
+ */
+ SETERROR(REG_EPAREN);
+ break;
+#endif
+ case '^':
+ EMIT(OBOL, 0);
+ p->g->iflags |= USEBOL;
+ p->g->nbol++;
+ wascaret = 1;
+ break;
+ case '$':
+ EMIT(OEOL, 0);
+ p->g->iflags |= USEEOL;
+ p->g->neol++;
+ break;
+ case '|':
+ SETERROR(REG_EMPTY);
+ break;
+ case '*':
+ case '+':
+ case '?':
+ SETERROR(REG_BADRPT);
+ break;
+ case '.':
+ if (p->g->cflags&REG_NEWLINE)
+ nonnewline(p);
+ else
+ EMIT(OANY, 0);
+ break;
+ case '[':
+ p_bracket(p);
+ break;
+ case '\\':
+ (void)REQUIRE(MORE(), REG_EESCAPE);
+ wc = WGETNEXT();
+ ordinary(p, wc);
+ break;
+ case '{': /* okay as ordinary except if digit follows */
+ (void)REQUIRE(!MORE() || !isdigit((uch)PEEK()), REG_BADRPT);
+ /* FALLTHROUGH */
+ default:
+ p->next--;
+ wc = WGETNEXT();
+ ordinary(p, wc);
+ break;
+ }
+
+ if (!MORE())
+ return;
+ c = PEEK();
+ /* we call { a repetition if followed by a digit */
+ if (!( c == '*' || c == '+' || c == '?' ||
+ (c == '{' && MORE2() && isdigit((uch)PEEK2())) ))
+ return; /* no repetition, we're done */
+ NEXT();
+
+ (void)REQUIRE(!wascaret, REG_BADRPT);
+ switch (c) {
+ case '*': /* implemented as +? */
+ /* this case does not require the (y|) trick, noKLUDGE */
+ INSERT(OPLUS_, pos);
+ ASTERN(O_PLUS, pos);
+ INSERT(OQUEST_, pos);
+ ASTERN(O_QUEST, pos);
+ break;
+ case '+':
+ INSERT(OPLUS_, pos);
+ ASTERN(O_PLUS, pos);
+ break;
+ case '?':
+ /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+ INSERT(OCH_, pos); /* offset slightly wrong */
+ ASTERN(OOR1, pos); /* this one's right */
+ AHEAD(pos); /* fix the OCH_ */
+ EMIT(OOR2, 0); /* offset very wrong... */
+ AHEAD(THERE()); /* ...so fix it */
+ ASTERN(O_CH, THERETHERE());
+ break;
+ case '{':
+ count = p_count(p);
+ if (EAT(',')) {
+ if (isdigit((uch)PEEK())) {
+ count2 = p_count(p);
+ (void)REQUIRE(count <= count2, REG_BADBR);
+ } else /* single number with comma */
+ count2 = INFINITY;
+ } else /* just a single number */
+ count2 = count;
+ repeat(p, pos, count, count2);
+ if (!EAT('}')) { /* error heuristics */
+ while (MORE() && PEEK() != '}')
+ NEXT();
+ (void)REQUIRE(MORE(), REG_EBRACE);
+ SETERROR(REG_BADBR);
+ }
+ break;
+ }
+
+ if (!MORE())
+ return;
+ c = PEEK();
+ if (!( c == '*' || c == '+' || c == '?' ||
+ (c == '{' && MORE2() && isdigit((uch)PEEK2())) ) )
+ return;
+ SETERROR(REG_BADRPT);
+}
+
+/*
+ - p_str - string (no metacharacters) "parser"
+ == static void p_str(struct parse *p);
+ */
+static void
+p_str(struct parse *p)
+{
+ (void)REQUIRE(MORE(), REG_EMPTY);
+ while (MORE())
+ ordinary(p, WGETNEXT());
+}
+
+/*
+ - p_bre - BRE parser top level, anchoring and concatenation
+ == static void p_bre(struct parse *p, int end1, \
+ == int end2);
+ * Giving end1 as OUT essentially eliminates the end1/end2 check.
+ *
+ * This implementation is a bit of a kludge, in that a trailing $ is first
+ * taken as an ordinary character and then revised to be an anchor.
+ * The amount of lookahead needed to avoid this kludge is excessive.
+ */
+static void
+p_bre(struct parse *p,
+ int end1, /* first terminating character */
+ int end2) /* second terminating character */
+{
+ sopno start = HERE();
+ int first = 1; /* first subexpression? */
+ int wasdollar = 0;
+
+ if (EAT('^')) {
+ EMIT(OBOL, 0);
+ p->g->iflags |= USEBOL;
+ p->g->nbol++;
+ }
+ while (MORE() && !SEETWO(end1, end2)) {
+ wasdollar = p_simp_re(p, first);
+ first = 0;
+ }
+ if (wasdollar) { /* oops, that was a trailing anchor */
+ DROP(1);
+ EMIT(OEOL, 0);
+ p->g->iflags |= USEEOL;
+ p->g->neol++;
+ }
+
+ (void)REQUIRE(HERE() != start, REG_EMPTY); /* require nonempty */
+}
+
+/*
+ - p_simp_re - parse a simple RE, an atom possibly followed by a repetition
+ == static int p_simp_re(struct parse *p, int starordinary);
+ */
+static int /* was the simple RE an unbackslashed $? */
+p_simp_re(struct parse *p,
+ int starordinary) /* is a leading * an ordinary character? */
+{
+ int c;
+ int count;
+ int count2;
+ sopno pos;
+ int i;
+ wint_t wc;
+ sopno subno;
+# define BACKSL (1<<CHAR_BIT)
+
+ pos = HERE(); /* repetion op, if any, covers from here */
+
+ assert(MORE()); /* caller should have ensured this */
+ c = GETNEXT();
+ if (c == '\\') {
+ (void)REQUIRE(MORE(), REG_EESCAPE);
+ c = BACKSL | GETNEXT();
+ }
+ switch (c) {
+ case '.':
+ if (p->g->cflags&REG_NEWLINE)
+ nonnewline(p);
+ else
+ EMIT(OANY, 0);
+ break;
+ case '[':
+ p_bracket(p);
+ break;
+ case BACKSL|'{':
+ SETERROR(REG_BADRPT);
+ break;
+ case BACKSL|'(':
+ p->g->nsub++;
+ subno = p->g->nsub;
+ if (subno < NPAREN)
+ p->pbegin[subno] = HERE();
+ EMIT(OLPAREN, subno);
+ /* the MORE here is an error heuristic */
+ if (MORE() && !SEETWO('\\', ')'))
+ p_bre(p, '\\', ')');
+ if (subno < NPAREN) {
+ p->pend[subno] = HERE();
+ assert(p->pend[subno] != 0);
+ }
+ EMIT(ORPAREN, subno);
+ (void)REQUIRE(EATTWO('\\', ')'), REG_EPAREN);
+ break;
+ case BACKSL|')': /* should not get here -- must be user */
+ case BACKSL|'}':
+ SETERROR(REG_EPAREN);
+ break;
+ case BACKSL|'1':
+ case BACKSL|'2':
+ case BACKSL|'3':
+ case BACKSL|'4':
+ case BACKSL|'5':
+ case BACKSL|'6':
+ case BACKSL|'7':
+ case BACKSL|'8':
+ case BACKSL|'9':
+ i = (c&~BACKSL) - '0';
+ assert(i < NPAREN);
+ if (p->pend[i] != 0) {
+ assert(i <= p->g->nsub);
+ EMIT(OBACK_, i);
+ assert(p->pbegin[i] != 0);
+ assert(OP(p->strip[p->pbegin[i]]) == OLPAREN);
+ assert(OP(p->strip[p->pend[i]]) == ORPAREN);
+ (void) dupl(p, p->pbegin[i]+1, p->pend[i]);
+ EMIT(O_BACK, i);
+ } else
+ SETERROR(REG_ESUBREG);
+ p->g->backrefs = 1;
+ break;
+ case '*':
+ (void)REQUIRE(starordinary, REG_BADRPT);
+ /* FALLTHROUGH */
+ default:
+ p->next--;
+ wc = WGETNEXT();
+ ordinary(p, wc);
+ break;
+ }
+
+ if (EAT('*')) { /* implemented as +? */
+ /* this case does not require the (y|) trick, noKLUDGE */
+ INSERT(OPLUS_, pos);
+ ASTERN(O_PLUS, pos);
+ INSERT(OQUEST_, pos);
+ ASTERN(O_QUEST, pos);
+ } else if (EATTWO('\\', '{')) {
+ count = p_count(p);
+ if (EAT(',')) {
+ if (MORE() && isdigit((uch)PEEK())) {
+ count2 = p_count(p);
+ (void)REQUIRE(count <= count2, REG_BADBR);
+ } else /* single number with comma */
+ count2 = INFINITY;
+ } else /* just a single number */
+ count2 = count;
+ repeat(p, pos, count, count2);
+ if (!EATTWO('\\', '}')) { /* error heuristics */
+ while (MORE() && !SEETWO('\\', '}'))
+ NEXT();
+ (void)REQUIRE(MORE(), REG_EBRACE);
+ SETERROR(REG_BADBR);
+ }
+ } else if (c == '$') /* $ (but not \$) ends it */
+ return(1);
+
+ return(0);
+}
+
+/*
+ - p_count - parse a repetition count
+ == static int p_count(struct parse *p);
+ */
+static int /* the value */
+p_count(struct parse *p)
+{
+ int count = 0;
+ int ndigits = 0;
+
+ while (MORE() && isdigit((uch)PEEK()) && count <= DUPMAX) {
+ count = count*10 + (GETNEXT() - '0');
+ ndigits++;
+ }
+
+ (void)REQUIRE(ndigits > 0 && count <= DUPMAX, REG_BADBR);
+ return(count);
+}
+
+/*
+ - p_bracket - parse a bracketed character list
+ == static void p_bracket(struct parse *p);
+ */
+static void
+p_bracket(struct parse *p)
+{
+ cset *cs;
+ wint_t ch;
+
+ /* Dept of Truly Sickening Special-Case Kludges */
+ if (p->next + 5 < p->end && strncmp(p->next, "[:<:]]", 6) == 0) {
+ EMIT(OBOW, 0);
+ NEXTn(6);
+ return;
+ }
+ if (p->next + 5 < p->end && strncmp(p->next, "[:>:]]", 6) == 0) {
+ EMIT(OEOW, 0);
+ NEXTn(6);
+ return;
+ }
+
+ if ((cs = allocset(p)) == NULL)
+ return;
+
+ if (p->g->cflags&REG_ICASE)
+ cs->icase = 1;
+ if (EAT('^'))
+ cs->invert = 1;
+ if (EAT(']'))
+ CHadd(p, cs, ']');
+ else if (EAT('-'))
+ CHadd(p, cs, '-');
+ while (MORE() && PEEK() != ']' && !SEETWO('-', ']'))
+ p_b_term(p, cs);
+ if (EAT('-'))
+ CHadd(p, cs, '-');
+ (void)MUSTEAT(']', REG_EBRACK);
+
+ if (p->error != 0) /* don't mess things up further */
+ return;
+
+ if (cs->invert && p->g->cflags&REG_NEWLINE)
+ cs->bmp['\n' >> 3] |= 1 << ('\n' & 7);
+
+ if ((ch = singleton(cs)) != OUT) { /* optimize singleton sets */
+ ordinary(p, ch);
+ freeset(p, cs);
+ } else
+ EMIT(OANYOF, (int)(cs - p->g->sets));
+}
+
+/*
+ - p_b_term - parse one term of a bracketed character list
+ == static void p_b_term(struct parse *p, cset *cs);
+ */
+static void
+p_b_term(struct parse *p, cset *cs)
+{
+ char c;
+ wint_t start, finish;
+ wint_t i;
+ struct xlocale_collate *table =
+ (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE];
+
+ /* classify what we've got */
+ switch ((MORE()) ? PEEK() : '\0') {
+ case '[':
+ c = (MORE2()) ? PEEK2() : '\0';
+ break;
+ case '-':
+ SETERROR(REG_ERANGE);
+ return; /* NOTE RETURN */
+ break;
+ default:
+ c = '\0';
+ break;
+ }
+
+ switch (c) {
+ case ':': /* character class */
+ NEXT2();
+ (void)REQUIRE(MORE(), REG_EBRACK);
+ c = PEEK();
+ (void)REQUIRE(c != '-' && c != ']', REG_ECTYPE);
+ p_b_cclass(p, cs);
+ (void)REQUIRE(MORE(), REG_EBRACK);
+ (void)REQUIRE(EATTWO(':', ']'), REG_ECTYPE);
+ break;
+ case '=': /* equivalence class */
+ NEXT2();
+ (void)REQUIRE(MORE(), REG_EBRACK);
+ c = PEEK();
+ (void)REQUIRE(c != '-' && c != ']', REG_ECOLLATE);
+ p_b_eclass(p, cs);
+ (void)REQUIRE(MORE(), REG_EBRACK);
+ (void)REQUIRE(EATTWO('=', ']'), REG_ECOLLATE);
+ break;
+ default: /* symbol, ordinary character, or range */
+ start = p_b_symbol(p);
+ if (SEE('-') && MORE2() && PEEK2() != ']') {
+ /* range */
+ NEXT();
+ if (EAT('-'))
+ finish = '-';
+ else
+ finish = p_b_symbol(p);
+ } else
+ finish = start;
+ if (start == finish)
+ CHadd(p, cs, start);
+ else {
+ if (table->__collate_load_error) {
+ (void)REQUIRE((uch)start <= (uch)finish, REG_ERANGE);
+ CHaddrange(p, cs, start, finish);
+ } else {
+ (void)REQUIRE(__collate_range_cmp(table, start, finish) <= 0, REG_ERANGE);
+ for (i = 0; i <= UCHAR_MAX; i++) {
+ if ( __collate_range_cmp(table, start, i) <= 0
+ && __collate_range_cmp(table, i, finish) <= 0
+ )
+ CHadd(p, cs, i);
+ }
+ }
+ }
+ break;
+ }
+}
+
+/*
+ - p_b_cclass - parse a character-class name and deal with it
+ == static void p_b_cclass(struct parse *p, cset *cs);
+ */
+static void
+p_b_cclass(struct parse *p, cset *cs)
+{
+ char *sp = p->next;
+ size_t len;
+ wctype_t wct;
+ char clname[16];
+
+ while (MORE() && isalpha((uch)PEEK()))
+ NEXT();
+ len = p->next - sp;
+ if (len >= sizeof(clname) - 1) {
+ SETERROR(REG_ECTYPE);
+ return;
+ }
+ memcpy(clname, sp, len);
+ clname[len] = '\0';
+ if ((wct = wctype(clname)) == 0) {
+ SETERROR(REG_ECTYPE);
+ return;
+ }
+ CHaddtype(p, cs, wct);
+}
+
+/*
+ - p_b_eclass - parse an equivalence-class name and deal with it
+ == static void p_b_eclass(struct parse *p, cset *cs);
+ *
+ * This implementation is incomplete. xxx
+ */
+static void
+p_b_eclass(struct parse *p, cset *cs)
+{
+ wint_t c;
+
+ c = p_b_coll_elem(p, '=');
+ CHadd(p, cs, c);
+}
+
+/*
+ - p_b_symbol - parse a character or [..]ed multicharacter collating symbol
+ == static wint_t p_b_symbol(struct parse *p);
+ */
+static wint_t /* value of symbol */
+p_b_symbol(struct parse *p)
+{
+ wint_t value;
+
+ (void)REQUIRE(MORE(), REG_EBRACK);
+ if (!EATTWO('[', '.'))
+ return(WGETNEXT());
+
+ /* collating symbol */
+ value = p_b_coll_elem(p, '.');
+ (void)REQUIRE(EATTWO('.', ']'), REG_ECOLLATE);
+ return(value);
+}
+
+/*
+ - p_b_coll_elem - parse a collating-element name and look it up
+ == static wint_t p_b_coll_elem(struct parse *p, wint_t endc);
+ */
+static wint_t /* value of collating element */
+p_b_coll_elem(struct parse *p,
+ wint_t endc) /* name ended by endc,']' */
+{
+ char *sp = p->next;
+ struct cname *cp;
+ int len;
+ mbstate_t mbs;
+ wchar_t wc;
+ size_t clen;
+
+ while (MORE() && !SEETWO(endc, ']'))
+ NEXT();
+ if (!MORE()) {
+ SETERROR(REG_EBRACK);
+ return(0);
+ }
+ len = p->next - sp;
+ for (cp = cnames; cp->name != NULL; cp++)
+ if (strncmp(cp->name, sp, len) == 0 && cp->name[len] == '\0')
+ return(cp->code); /* known name */
+ memset(&mbs, 0, sizeof(mbs));
+ if ((clen = mbrtowc(&wc, sp, len, &mbs)) == len)
+ return (wc); /* single character */
+ else if (clen == (size_t)-1 || clen == (size_t)-2)
+ SETERROR(REG_ILLSEQ);
+ else
+ SETERROR(REG_ECOLLATE); /* neither */
+ return(0);
+}
+
+/*
+ - othercase - return the case counterpart of an alphabetic
+ == static wint_t othercase(wint_t ch);
+ */
+static wint_t /* if no counterpart, return ch */
+othercase(wint_t ch)
+{
+ assert(iswalpha(ch));
+ if (iswupper(ch))
+ return(towlower(ch));
+ else if (iswlower(ch))
+ return(towupper(ch));
+ else /* peculiar, but could happen */
+ return(ch);
+}
+
+/*
+ - bothcases - emit a dualcase version of a two-case character
+ == static void bothcases(struct parse *p, wint_t ch);
+ *
+ * Boy, is this implementation ever a kludge...
+ */
+static void
+bothcases(struct parse *p, wint_t ch)
+{
+ char *oldnext = p->next;
+ char *oldend = p->end;
+ char bracket[3 + MB_LEN_MAX];
+ size_t n;
+ mbstate_t mbs;
+
+ assert(othercase(ch) != ch); /* p_bracket() would recurse */
+ p->next = bracket;
+ memset(&mbs, 0, sizeof(mbs));
+ n = wcrtomb(bracket, ch, &mbs);
+ assert(n != (size_t)-1);
+ bracket[n] = ']';
+ bracket[n + 1] = '\0';
+ p->end = bracket+n+1;
+ p_bracket(p);
+ assert(p->next == p->end);
+ p->next = oldnext;
+ p->end = oldend;
+}
+
+/*
+ - ordinary - emit an ordinary character
+ == static void ordinary(struct parse *p, wint_t ch);
+ */
+static void
+ordinary(struct parse *p, wint_t ch)
+{
+ cset *cs;
+
+ if ((p->g->cflags&REG_ICASE) && iswalpha(ch) && othercase(ch) != ch)
+ bothcases(p, ch);
+ else if ((ch & OPDMASK) == ch)
+ EMIT(OCHAR, ch);
+ else {
+ /*
+ * Kludge: character is too big to fit into an OCHAR operand.
+ * Emit a singleton set.
+ */
+ if ((cs = allocset(p)) == NULL)
+ return;
+ CHadd(p, cs, ch);
+ EMIT(OANYOF, (int)(cs - p->g->sets));
+ }
+}
+
+/*
+ - nonnewline - emit REG_NEWLINE version of OANY
+ == static void nonnewline(struct parse *p);
+ *
+ * Boy, is this implementation ever a kludge...
+ */
+static void
+nonnewline(struct parse *p)
+{
+ char *oldnext = p->next;
+ char *oldend = p->end;
+ char bracket[4];
+
+ p->next = bracket;
+ p->end = bracket+3;
+ bracket[0] = '^';
+ bracket[1] = '\n';
+ bracket[2] = ']';
+ bracket[3] = '\0';
+ p_bracket(p);
+ assert(p->next == bracket+3);
+ p->next = oldnext;
+ p->end = oldend;
+}
+
+/*
+ - repeat - generate code for a bounded repetition, recursively if needed
+ == static void repeat(struct parse *p, sopno start, int from, int to);
+ */
+static void
+repeat(struct parse *p,
+ sopno start, /* operand from here to end of strip */
+ int from, /* repeated from this number */
+ int to) /* to this number of times (maybe INFINITY) */
+{
+ sopno finish = HERE();
+# define N 2
+# define INF 3
+# define REP(f, t) ((f)*8 + (t))
+# define MAP(n) (((n) <= 1) ? (n) : ((n) == INFINITY) ? INF : N)
+ sopno copy;
+
+ if (p->error != 0) /* head off possible runaway recursion */
+ return;
+
+ assert(from <= to);
+
+ switch (REP(MAP(from), MAP(to))) {
+ case REP(0, 0): /* must be user doing this */
+ DROP(finish-start); /* drop the operand */
+ break;
+ case REP(0, 1): /* as x{1,1}? */
+ case REP(0, N): /* as x{1,n}? */
+ case REP(0, INF): /* as x{1,}? */
+ /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+ INSERT(OCH_, start); /* offset is wrong... */
+ repeat(p, start+1, 1, to);
+ ASTERN(OOR1, start);
+ AHEAD(start); /* ... fix it */
+ EMIT(OOR2, 0);
+ AHEAD(THERE());
+ ASTERN(O_CH, THERETHERE());
+ break;
+ case REP(1, 1): /* trivial case */
+ /* done */
+ break;
+ case REP(1, N): /* as x?x{1,n-1} */
+ /* KLUDGE: emit y? as (y|) until subtle bug gets fixed */
+ INSERT(OCH_, start);
+ ASTERN(OOR1, start);
+ AHEAD(start);
+ EMIT(OOR2, 0); /* offset very wrong... */
+ AHEAD(THERE()); /* ...so fix it */
+ ASTERN(O_CH, THERETHERE());
+ copy = dupl(p, start+1, finish+1);
+ assert(copy == finish+4);
+ repeat(p, copy, 1, to-1);
+ break;
+ case REP(1, INF): /* as x+ */
+ INSERT(OPLUS_, start);
+ ASTERN(O_PLUS, start);
+ break;
+ case REP(N, N): /* as xx{m-1,n-1} */
+ copy = dupl(p, start, finish);
+ repeat(p, copy, from-1, to-1);
+ break;
+ case REP(N, INF): /* as xx{n-1,INF} */
+ copy = dupl(p, start, finish);
+ repeat(p, copy, from-1, to);
+ break;
+ default: /* "can't happen" */
+ SETERROR(REG_ASSERT); /* just in case */
+ break;
+ }
+}
+
+/*
+ - wgetnext - helper function for WGETNEXT() macro. Gets the next wide
+ - character from the parse struct, signals a REG_ILLSEQ error if the
+ - character can't be converted. Returns the number of bytes consumed.
+ */
+static wint_t
+wgetnext(struct parse *p)
+{
+ mbstate_t mbs;
+ wchar_t wc;
+ size_t n;
+
+ memset(&mbs, 0, sizeof(mbs));
+ n = mbrtowc(&wc, p->next, p->end - p->next, &mbs);
+ if (n == (size_t)-1 || n == (size_t)-2) {
+ SETERROR(REG_ILLSEQ);
+ return (0);
+ }
+ if (n == 0)
+ n = 1;
+ p->next += n;
+ return (wc);
+}
+
+/*
+ - seterr - set an error condition
+ == static int seterr(struct parse *p, int e);
+ */
+static int /* useless but makes type checking happy */
+seterr(struct parse *p, int e)
+{
+ if (p->error == 0) /* keep earliest error condition */
+ p->error = e;
+ p->next = nuls; /* try to bring things to a halt */
+ p->end = nuls;
+ return(0); /* make the return value well-defined */
+}
+
+/*
+ - allocset - allocate a set of characters for []
+ == static cset *allocset(struct parse *p);
+ */
+static cset *
+allocset(struct parse *p)
+{
+ cset *cs, *ncs;
+
+ ncs = realloc(p->g->sets, (p->g->ncsets + 1) * sizeof(*ncs));
+ if (ncs == NULL) {
+ SETERROR(REG_ESPACE);
+ return (NULL);
+ }
+ p->g->sets = ncs;
+ cs = &p->g->sets[p->g->ncsets++];
+ memset(cs, 0, sizeof(*cs));
+
+ return(cs);
+}
+
+/*
+ - freeset - free a now-unused set
+ == static void freeset(struct parse *p, cset *cs);
+ */
+static void
+freeset(struct parse *p, cset *cs)
+{
+ cset *top = &p->g->sets[p->g->ncsets];
+
+ free(cs->wides);
+ free(cs->ranges);
+ free(cs->types);
+ memset(cs, 0, sizeof(*cs));
+ if (cs == top-1) /* recover only the easy case */
+ p->g->ncsets--;
+}
+
+/*
+ - singleton - Determine whether a set contains only one character,
+ - returning it if so, otherwise returning OUT.
+ */
+static wint_t
+singleton(cset *cs)
+{
+ wint_t i, s, n;
+
+ for (i = n = 0; i < NC; i++)
+ if (CHIN(cs, i)) {
+ n++;
+ s = i;
+ }
+ if (n == 1)
+ return (s);
+ if (cs->nwides == 1 && cs->nranges == 0 && cs->ntypes == 0 &&
+ cs->icase == 0)
+ return (cs->wides[0]);
+ /* Don't bother handling the other cases. */
+ return (OUT);
+}
+
+/*
+ - CHadd - add character to character set.
+ */
+static void
+CHadd(struct parse *p, cset *cs, wint_t ch)
+{
+ wint_t nch, *newwides;
+ assert(ch >= 0);
+ if (ch < NC)
+ cs->bmp[ch >> 3] |= 1 << (ch & 7);
+ else {
+ newwides = realloc(cs->wides, (cs->nwides + 1) *
+ sizeof(*cs->wides));
+ if (newwides == NULL) {
+ SETERROR(REG_ESPACE);
+ return;
+ }
+ cs->wides = newwides;
+ cs->wides[cs->nwides++] = ch;
+ }
+ if (cs->icase) {
+ if ((nch = towlower(ch)) < NC)
+ cs->bmp[nch >> 3] |= 1 << (nch & 7);
+ if ((nch = towupper(ch)) < NC)
+ cs->bmp[nch >> 3] |= 1 << (nch & 7);
+ }
+}
+
+/*
+ - CHaddrange - add all characters in the range [min,max] to a character set.
+ */
+static void
+CHaddrange(struct parse *p, cset *cs, wint_t min, wint_t max)
+{
+ crange *newranges;
+
+ for (; min < NC && min <= max; min++)
+ CHadd(p, cs, min);
+ if (min >= max)
+ return;
+ newranges = realloc(cs->ranges, (cs->nranges + 1) *
+ sizeof(*cs->ranges));
+ if (newranges == NULL) {
+ SETERROR(REG_ESPACE);
+ return;
+ }
+ cs->ranges = newranges;
+ cs->ranges[cs->nranges].min = min;
+ cs->ranges[cs->nranges].min = max;
+ cs->nranges++;
+}
+
+/*
+ - CHaddtype - add all characters of a certain type to a character set.
+ */
+static void
+CHaddtype(struct parse *p, cset *cs, wctype_t wct)
+{
+ wint_t i;
+ wctype_t *newtypes;
+
+ for (i = 0; i < NC; i++)
+ if (iswctype(i, wct))
+ CHadd(p, cs, i);
+ newtypes = realloc(cs->types, (cs->ntypes + 1) *
+ sizeof(*cs->types));
+ if (newtypes == NULL) {
+ SETERROR(REG_ESPACE);
+ return;
+ }
+ cs->types = newtypes;
+ cs->types[cs->ntypes++] = wct;
+}
+
+/*
+ - dupl - emit a duplicate of a bunch of sops
+ == static sopno dupl(struct parse *p, sopno start, sopno finish);
+ */
+static sopno /* start of duplicate */
+dupl(struct parse *p,
+ sopno start, /* from here */
+ sopno finish) /* to this less one */
+{
+ sopno ret = HERE();
+ sopno len = finish - start;
+
+ assert(finish >= start);
+ if (len == 0)
+ return(ret);
+ if (!enlarge(p, p->ssize + len)) /* this many unexpected additions */
+ return(ret);
+ (void) memcpy((char *)(p->strip + p->slen),
+ (char *)(p->strip + start), (size_t)len*sizeof(sop));
+ p->slen += len;
+ return(ret);
+}
+
+/*
+ - doemit - emit a strip operator
+ == static void doemit(struct parse *p, sop op, size_t opnd);
+ *
+ * It might seem better to implement this as a macro with a function as
+ * hard-case backup, but it's just too big and messy unless there are
+ * some changes to the data structures. Maybe later.
+ */
+static void
+doemit(struct parse *p, sop op, size_t opnd)
+{
+ /* avoid making error situations worse */
+ if (p->error != 0)
+ return;
+
+ /* deal with oversize operands ("can't happen", more or less) */
+ assert(opnd < 1<<OPSHIFT);
+
+ /* deal with undersized strip */
+ if (p->slen >= p->ssize)
+ if (!enlarge(p, (p->ssize+1) / 2 * 3)) /* +50% */
+ return;
+
+ /* finally, it's all reduced to the easy case */
+ p->strip[p->slen++] = SOP(op, opnd);
+}
+
+/*
+ - doinsert - insert a sop into the strip
+ == static void doinsert(struct parse *p, sop op, size_t opnd, sopno pos);
+ */
+static void
+doinsert(struct parse *p, sop op, size_t opnd, sopno pos)
+{
+ sopno sn;
+ sop s;
+ int i;
+
+ /* avoid making error situations worse */
+ if (p->error != 0)
+ return;
+
+ sn = HERE();
+ EMIT(op, opnd); /* do checks, ensure space */
+ assert(HERE() == sn+1);
+ s = p->strip[sn];
+
+ /* adjust paren pointers */
+ assert(pos > 0);
+ for (i = 1; i < NPAREN; i++) {
+ if (p->pbegin[i] >= pos) {
+ p->pbegin[i]++;
+ }
+ if (p->pend[i] >= pos) {
+ p->pend[i]++;
+ }
+ }
+
+ memmove((char *)&p->strip[pos+1], (char *)&p->strip[pos],
+ (HERE()-pos-1)*sizeof(sop));
+ p->strip[pos] = s;
+}
+
+/*
+ - dofwd - complete a forward reference
+ == static void dofwd(struct parse *p, sopno pos, sop value);
+ */
+static void
+dofwd(struct parse *p, sopno pos, sop value)
+{
+ /* avoid making error situations worse */
+ if (p->error != 0)
+ return;
+
+ assert(value < 1<<OPSHIFT);
+ p->strip[pos] = OP(p->strip[pos]) | value;
+}
+
+/*
+ - enlarge - enlarge the strip
+ == static int enlarge(struct parse *p, sopno size);
+ */
+static int
+enlarge(struct parse *p, sopno size)
+{
+ sop *sp;
+
+ if (p->ssize >= size)
+ return 1;
+
+ sp = (sop *)realloc(p->strip, size*sizeof(sop));
+ if (sp == NULL) {
+ SETERROR(REG_ESPACE);
+ return 0;
+ }
+ p->strip = sp;
+ p->ssize = size;
+ return 1;
+}
+
+/*
+ - stripsnug - compact the strip
+ == static void stripsnug(struct parse *p, struct re_guts *g);
+ */
+static void
+stripsnug(struct parse *p, struct re_guts *g)
+{
+ g->nstates = p->slen;
+ g->strip = (sop *)realloc((char *)p->strip, p->slen * sizeof(sop));
+ if (g->strip == NULL) {
+ SETERROR(REG_ESPACE);
+ g->strip = p->strip;
+ }
+}
+
+/*
+ - findmust - fill in must and mlen with longest mandatory literal string
+ == static void findmust(struct parse *p, struct re_guts *g);
+ *
+ * This algorithm could do fancy things like analyzing the operands of |
+ * for common subsequences. Someday. This code is simple and finds most
+ * of the interesting cases.
+ *
+ * Note that must and mlen got initialized during setup.
+ */
+static void
+findmust(struct parse *p, struct re_guts *g)
+{
+ sop *scan;
+ sop *start;
+ sop *newstart;
+ sopno newlen;
+ sop s;
+ char *cp;
+ int offset;
+ char buf[MB_LEN_MAX];
+ size_t clen;
+ mbstate_t mbs;
+
+ /* avoid making error situations worse */
+ if (p->error != 0)
+ return;
+
+ /*
+ * It's not generally safe to do a ``char'' substring search on
+ * multibyte character strings, but it's safe for at least
+ * UTF-8 (see RFC 3629).
+ */
+ if (MB_CUR_MAX > 1 &&
+ strcmp(_CurrentRuneLocale->__encoding, "UTF-8") != 0)
+ return;
+
+ /* find the longest OCHAR sequence in strip */
+ newlen = 0;
+ offset = 0;
+ g->moffset = 0;
+ scan = g->strip + 1;
+ do {
+ s = *scan++;
+ switch (OP(s)) {
+ case OCHAR: /* sequence member */
+ if (newlen == 0) { /* new sequence */
+ memset(&mbs, 0, sizeof(mbs));
+ newstart = scan - 1;
+ }
+ clen = wcrtomb(buf, OPND(s), &mbs);
+ if (clen == (size_t)-1)
+ goto toohard;
+ newlen += clen;
+ break;
+ case OPLUS_: /* things that don't break one */
+ case OLPAREN:
+ case ORPAREN:
+ break;
+ case OQUEST_: /* things that must be skipped */
+ case OCH_:
+ offset = altoffset(scan, offset);
+ scan--;
+ do {
+ scan += OPND(s);
+ s = *scan;
+ /* assert() interferes w debug printouts */
+ if (OP(s) != O_QUEST && OP(s) != O_CH &&
+ OP(s) != OOR2) {
+ g->iflags |= BAD;
+ return;
+ }
+ } while (OP(s) != O_QUEST && OP(s) != O_CH);
+ /* FALLTHROUGH */
+ case OBOW: /* things that break a sequence */
+ case OEOW:
+ case OBOL:
+ case OEOL:
+ case O_QUEST:
+ case O_CH:
+ case OEND:
+ if (newlen > g->mlen) { /* ends one */
+ start = newstart;
+ g->mlen = newlen;
+ if (offset > -1) {
+ g->moffset += offset;
+ offset = newlen;
+ } else
+ g->moffset = offset;
+ } else {
+ if (offset > -1)
+ offset += newlen;
+ }
+ newlen = 0;
+ break;
+ case OANY:
+ if (newlen > g->mlen) { /* ends one */
+ start = newstart;
+ g->mlen = newlen;
+ if (offset > -1) {
+ g->moffset += offset;
+ offset = newlen;
+ } else
+ g->moffset = offset;
+ } else {
+ if (offset > -1)
+ offset += newlen;
+ }
+ if (offset > -1)
+ offset++;
+ newlen = 0;
+ break;
+ case OANYOF: /* may or may not invalidate offset */
+ /* First, everything as OANY */
+ if (newlen > g->mlen) { /* ends one */
+ start = newstart;
+ g->mlen = newlen;
+ if (offset > -1) {
+ g->moffset += offset;
+ offset = newlen;
+ } else
+ g->moffset = offset;
+ } else {
+ if (offset > -1)
+ offset += newlen;
+ }
+ if (offset > -1)
+ offset++;
+ newlen = 0;
+ break;
+ toohard:
+ default:
+ /* Anything here makes it impossible or too hard
+ * to calculate the offset -- so we give up;
+ * save the last known good offset, in case the
+ * must sequence doesn't occur later.
+ */
+ if (newlen > g->mlen) { /* ends one */
+ start = newstart;
+ g->mlen = newlen;
+ if (offset > -1)
+ g->moffset += offset;
+ else
+ g->moffset = offset;
+ }
+ offset = -1;
+ newlen = 0;
+ break;
+ }
+ } while (OP(s) != OEND);
+
+ if (g->mlen == 0) { /* there isn't one */
+ g->moffset = -1;
+ return;
+ }
+
+ /* turn it into a character string */
+ g->must = malloc((size_t)g->mlen + 1);
+ if (g->must == NULL) { /* argh; just forget it */
+ g->mlen = 0;
+ g->moffset = -1;
+ return;
+ }
+ cp = g->must;
+ scan = start;
+ memset(&mbs, 0, sizeof(mbs));
+ while (cp < g->must + g->mlen) {
+ while (OP(s = *scan++) != OCHAR)
+ continue;
+ clen = wcrtomb(cp, OPND(s), &mbs);
+ assert(clen != (size_t)-1);
+ cp += clen;
+ }
+ assert(cp == g->must + g->mlen);
+ *cp++ = '\0'; /* just on general principles */
+}
+
+/*
+ - altoffset - choose biggest offset among multiple choices
+ == static int altoffset(sop *scan, int offset);
+ *
+ * Compute, recursively if necessary, the largest offset among multiple
+ * re paths.
+ */
+static int
+altoffset(sop *scan, int offset)
+{
+ int largest;
+ int try;
+ sop s;
+
+ /* If we gave up already on offsets, return */
+ if (offset == -1)
+ return -1;
+
+ largest = 0;
+ try = 0;
+ s = *scan++;
+ while (OP(s) != O_QUEST && OP(s) != O_CH) {
+ switch (OP(s)) {
+ case OOR1:
+ if (try > largest)
+ largest = try;
+ try = 0;
+ break;
+ case OQUEST_:
+ case OCH_:
+ try = altoffset(scan, try);
+ if (try == -1)
+ return -1;
+ scan--;
+ do {
+ scan += OPND(s);
+ s = *scan;
+ if (OP(s) != O_QUEST && OP(s) != O_CH &&
+ OP(s) != OOR2)
+ return -1;
+ } while (OP(s) != O_QUEST && OP(s) != O_CH);
+ /* We must skip to the next position, or we'll
+ * leave altoffset() too early.
+ */
+ scan++;
+ break;
+ case OANYOF:
+ case OCHAR:
+ case OANY:
+ try++;
+ case OBOW:
+ case OEOW:
+ case OLPAREN:
+ case ORPAREN:
+ case OOR2:
+ break;
+ default:
+ try = -1;
+ break;
+ }
+ if (try == -1)
+ return -1;
+ s = *scan++;
+ }
+
+ if (try > largest)
+ largest = try;
+
+ return largest+offset;
+}
+
+/*
+ - computejumps - compute char jumps for BM scan
+ == static void computejumps(struct parse *p, struct re_guts *g);
+ *
+ * This algorithm assumes g->must exists and is has size greater than
+ * zero. It's based on the algorithm found on Computer Algorithms by
+ * Sara Baase.
+ *
+ * A char jump is the number of characters one needs to jump based on
+ * the value of the character from the text that was mismatched.
+ */
+static void
+computejumps(struct parse *p, struct re_guts *g)
+{
+ int ch;
+ int mindex;
+
+ /* Avoid making errors worse */
+ if (p->error != 0)
+ return;
+
+ g->charjump = (int*) malloc((NC + 1) * sizeof(int));
+ if (g->charjump == NULL) /* Not a fatal error */
+ return;
+ /* Adjust for signed chars, if necessary */
+ g->charjump = &g->charjump[-(CHAR_MIN)];
+
+ /* If the character does not exist in the pattern, the jump
+ * is equal to the number of characters in the pattern.
+ */
+ for (ch = CHAR_MIN; ch < (CHAR_MAX + 1); ch++)
+ g->charjump[ch] = g->mlen;
+
+ /* If the character does exist, compute the jump that would
+ * take us to the last character in the pattern equal to it
+ * (notice that we match right to left, so that last character
+ * is the first one that would be matched).
+ */
+ for (mindex = 0; mindex < g->mlen; mindex++)
+ g->charjump[(int)g->must[mindex]] = g->mlen - mindex - 1;
+}
+
+/*
+ - computematchjumps - compute match jumps for BM scan
+ == static void computematchjumps(struct parse *p, struct re_guts *g);
+ *
+ * This algorithm assumes g->must exists and is has size greater than
+ * zero. It's based on the algorithm found on Computer Algorithms by
+ * Sara Baase.
+ *
+ * A match jump is the number of characters one needs to advance based
+ * on the already-matched suffix.
+ * Notice that all values here are minus (g->mlen-1), because of the way
+ * the search algorithm works.
+ */
+static void
+computematchjumps(struct parse *p, struct re_guts *g)
+{
+ int mindex; /* General "must" iterator */
+ int suffix; /* Keeps track of matching suffix */
+ int ssuffix; /* Keeps track of suffixes' suffix */
+ int* pmatches; /* pmatches[k] points to the next i
+ * such that i+1...mlen is a substring
+ * of k+1...k+mlen-i-1
+ */
+
+ /* Avoid making errors worse */
+ if (p->error != 0)
+ return;
+
+ pmatches = (int*) malloc(g->mlen * sizeof(unsigned int));
+ if (pmatches == NULL) {
+ g->matchjump = NULL;
+ return;
+ }
+
+ g->matchjump = (int*) malloc(g->mlen * sizeof(unsigned int));
+ if (g->matchjump == NULL) /* Not a fatal error */
+ return;
+
+ /* Set maximum possible jump for each character in the pattern */
+ for (mindex = 0; mindex < g->mlen; mindex++)
+ g->matchjump[mindex] = 2*g->mlen - mindex - 1;
+
+ /* Compute pmatches[] */
+ for (mindex = g->mlen - 1, suffix = g->mlen; mindex >= 0;
+ mindex--, suffix--) {
+ pmatches[mindex] = suffix;
+
+ /* If a mismatch is found, interrupting the substring,
+ * compute the matchjump for that position. If no
+ * mismatch is found, then a text substring mismatched
+ * against the suffix will also mismatch against the
+ * substring.
+ */
+ while (suffix < g->mlen
+ && g->must[mindex] != g->must[suffix]) {
+ g->matchjump[suffix] = MIN(g->matchjump[suffix],
+ g->mlen - mindex - 1);
+ suffix = pmatches[suffix];
+ }
+ }
+
+ /* Compute the matchjump up to the last substring found to jump
+ * to the beginning of the largest must pattern prefix matching
+ * it's own suffix.
+ */
+ for (mindex = 0; mindex <= suffix; mindex++)
+ g->matchjump[mindex] = MIN(g->matchjump[mindex],
+ g->mlen + suffix - mindex);
+
+ ssuffix = pmatches[suffix];
+ while (suffix < g->mlen) {
+ while (suffix <= ssuffix && suffix < g->mlen) {
+ g->matchjump[suffix] = MIN(g->matchjump[suffix],
+ g->mlen + ssuffix - suffix);
+ suffix++;
+ }
+ if (suffix < g->mlen)
+ ssuffix = pmatches[ssuffix];
+ }
+
+ free(pmatches);
+}
+
+/*
+ - pluscount - count + nesting
+ == static sopno pluscount(struct parse *p, struct re_guts *g);
+ */
+static sopno /* nesting depth */
+pluscount(struct parse *p, struct re_guts *g)
+{
+ sop *scan;
+ sop s;
+ sopno plusnest = 0;
+ sopno maxnest = 0;
+
+ if (p->error != 0)
+ return(0); /* there may not be an OEND */
+
+ scan = g->strip + 1;
+ do {
+ s = *scan++;
+ switch (OP(s)) {
+ case OPLUS_:
+ plusnest++;
+ break;
+ case O_PLUS:
+ if (plusnest > maxnest)
+ maxnest = plusnest;
+ plusnest--;
+ break;
+ }
+ } while (OP(s) != OEND);
+ if (plusnest != 0)
+ g->iflags |= BAD;
+ return(maxnest);
+}
diff --git a/lib/libc/regex/regerror.c b/lib/libc/regex/regerror.c
new file mode 100644
index 0000000..b9b773c
--- /dev/null
+++ b/lib/libc/regex/regerror.c
@@ -0,0 +1,174 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)regerror.c 8.4 (Berkeley) 3/20/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regerror.c 8.4 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <string.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <regex.h>
+
+#include "utils.h"
+
+/* ========= begin header generated by ./mkh ========= */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* === regerror.c === */
+static char *regatoi(const regex_t *preg, char *localbuf);
+
+#ifdef __cplusplus
+}
+#endif
+/* ========= end header generated by ./mkh ========= */
+/*
+ = #define REG_NOMATCH 1
+ = #define REG_BADPAT 2
+ = #define REG_ECOLLATE 3
+ = #define REG_ECTYPE 4
+ = #define REG_EESCAPE 5
+ = #define REG_ESUBREG 6
+ = #define REG_EBRACK 7
+ = #define REG_EPAREN 8
+ = #define REG_EBRACE 9
+ = #define REG_BADBR 10
+ = #define REG_ERANGE 11
+ = #define REG_ESPACE 12
+ = #define REG_BADRPT 13
+ = #define REG_EMPTY 14
+ = #define REG_ASSERT 15
+ = #define REG_INVARG 16
+ = #define REG_ILLSEQ 17
+ = #define REG_ATOI 255 // convert name to number (!)
+ = #define REG_ITOA 0400 // convert number to name (!)
+ */
+static struct rerr {
+ int code;
+ char *name;
+ char *explain;
+} rerrs[] = {
+ {REG_NOMATCH, "REG_NOMATCH", "regexec() failed to match"},
+ {REG_BADPAT, "REG_BADPAT", "invalid regular expression"},
+ {REG_ECOLLATE, "REG_ECOLLATE", "invalid collating element"},
+ {REG_ECTYPE, "REG_ECTYPE", "invalid character class"},
+ {REG_EESCAPE, "REG_EESCAPE", "trailing backslash (\\)"},
+ {REG_ESUBREG, "REG_ESUBREG", "invalid backreference number"},
+ {REG_EBRACK, "REG_EBRACK", "brackets ([ ]) not balanced"},
+ {REG_EPAREN, "REG_EPAREN", "parentheses not balanced"},
+ {REG_EBRACE, "REG_EBRACE", "braces not balanced"},
+ {REG_BADBR, "REG_BADBR", "invalid repetition count(s)"},
+ {REG_ERANGE, "REG_ERANGE", "invalid character range"},
+ {REG_ESPACE, "REG_ESPACE", "out of memory"},
+ {REG_BADRPT, "REG_BADRPT", "repetition-operator operand invalid"},
+ {REG_EMPTY, "REG_EMPTY", "empty (sub)expression"},
+ {REG_ASSERT, "REG_ASSERT", "\"can't happen\" -- you found a bug"},
+ {REG_INVARG, "REG_INVARG", "invalid argument to regex routine"},
+ {REG_ILLSEQ, "REG_ILLSEQ", "illegal byte sequence"},
+ {0, "", "*** unknown regexp error code ***"}
+};
+
+/*
+ - regerror - the interface to error numbers
+ = extern size_t regerror(int, const regex_t *, char *, size_t);
+ */
+/* ARGSUSED */
+size_t
+regerror(int errcode,
+ const regex_t * __restrict preg,
+ char * __restrict errbuf,
+ size_t errbuf_size)
+{
+ struct rerr *r;
+ size_t len;
+ int target = errcode &~ REG_ITOA;
+ char *s;
+ char convbuf[50];
+
+ if (errcode == REG_ATOI)
+ s = regatoi(preg, convbuf);
+ else {
+ for (r = rerrs; r->code != 0; r++)
+ if (r->code == target)
+ break;
+
+ if (errcode&REG_ITOA) {
+ if (r->code != 0)
+ (void) strcpy(convbuf, r->name);
+ else
+ sprintf(convbuf, "REG_0x%x", target);
+ assert(strlen(convbuf) < sizeof(convbuf));
+ s = convbuf;
+ } else
+ s = r->explain;
+ }
+
+ len = strlen(s) + 1;
+ if (errbuf_size > 0) {
+ if (errbuf_size > len)
+ (void) strcpy(errbuf, s);
+ else {
+ (void) strncpy(errbuf, s, errbuf_size-1);
+ errbuf[errbuf_size-1] = '\0';
+ }
+ }
+
+ return(len);
+}
+
+/*
+ - regatoi - internal routine to implement REG_ATOI
+ == static char *regatoi(const regex_t *preg, char *localbuf);
+ */
+static char *
+regatoi(const regex_t *preg, char *localbuf)
+{
+ struct rerr *r;
+
+ for (r = rerrs; r->code != 0; r++)
+ if (strcmp(r->name, preg->re_endp) == 0)
+ break;
+ if (r->code == 0)
+ return("0");
+
+ sprintf(localbuf, "%d", r->code);
+ return(localbuf);
+}
diff --git a/lib/libc/regex/regex.3 b/lib/libc/regex/regex.3
new file mode 100644
index 0000000..ea1ba25
--- /dev/null
+++ b/lib/libc/regex/regex.3
@@ -0,0 +1,727 @@
+.\" Copyright (c) 1992, 1993, 1994 Henry Spencer.
+.\" Copyright (c) 1992, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Henry Spencer.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)regex.3 8.4 (Berkeley) 3/20/94
+.\" $FreeBSD$
+.\"
+.Dd August 17, 2005
+.Dt REGEX 3
+.Os
+.Sh NAME
+.Nm regcomp ,
+.Nm regexec ,
+.Nm regerror ,
+.Nm regfree
+.Nd regular-expression library
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In regex.h
+.Ft int
+.Fo regcomp
+.Fa "regex_t * restrict preg" "const char * restrict pattern" "int cflags"
+.Fc
+.Ft int
+.Fo regexec
+.Fa "const regex_t * restrict preg" "const char * restrict string"
+.Fa "size_t nmatch" "regmatch_t pmatch[restrict]" "int eflags"
+.Fc
+.Ft size_t
+.Fo regerror
+.Fa "int errcode" "const regex_t * restrict preg"
+.Fa "char * restrict errbuf" "size_t errbuf_size"
+.Fc
+.Ft void
+.Fn regfree "regex_t *preg"
+.Sh DESCRIPTION
+These routines implement
+.St -p1003.2
+regular expressions
+.Pq Do RE Dc Ns s ;
+see
+.Xr re_format 7 .
+The
+.Fn regcomp
+function
+compiles an RE written as a string into an internal form,
+.Fn regexec
+matches that internal form against a string and reports results,
+.Fn regerror
+transforms error codes from either into human-readable messages,
+and
+.Fn regfree
+frees any dynamically-allocated storage used by the internal form
+of an RE.
+.Pp
+The header
+.In regex.h
+declares two structure types,
+.Ft regex_t
+and
+.Ft regmatch_t ,
+the former for compiled internal forms and the latter for match reporting.
+It also declares the four functions,
+a type
+.Ft regoff_t ,
+and a number of constants with names starting with
+.Dq Dv REG_ .
+.Pp
+The
+.Fn regcomp
+function
+compiles the regular expression contained in the
+.Fa pattern
+string,
+subject to the flags in
+.Fa cflags ,
+and places the results in the
+.Ft regex_t
+structure pointed to by
+.Fa preg .
+The
+.Fa cflags
+argument
+is the bitwise OR of zero or more of the following flags:
+.Bl -tag -width REG_EXTENDED
+.It Dv REG_EXTENDED
+Compile modern
+.Pq Dq extended
+REs,
+rather than the obsolete
+.Pq Dq basic
+REs that
+are the default.
+.It Dv REG_BASIC
+This is a synonym for 0,
+provided as a counterpart to
+.Dv REG_EXTENDED
+to improve readability.
+.It Dv REG_NOSPEC
+Compile with recognition of all special characters turned off.
+All characters are thus considered ordinary,
+so the
+.Dq RE
+is a literal string.
+This is an extension,
+compatible with but not specified by
+.St -p1003.2 ,
+and should be used with
+caution in software intended to be portable to other systems.
+.Dv REG_EXTENDED
+and
+.Dv REG_NOSPEC
+may not be used
+in the same call to
+.Fn regcomp .
+.It Dv REG_ICASE
+Compile for matching that ignores upper/lower case distinctions.
+See
+.Xr re_format 7 .
+.It Dv REG_NOSUB
+Compile for matching that need only report success or failure,
+not what was matched.
+.It Dv REG_NEWLINE
+Compile for newline-sensitive matching.
+By default, newline is a completely ordinary character with no special
+meaning in either REs or strings.
+With this flag,
+.Ql [^
+bracket expressions and
+.Ql .\&
+never match newline,
+a
+.Ql ^\&
+anchor matches the null string after any newline in the string
+in addition to its normal function,
+and the
+.Ql $\&
+anchor matches the null string before any newline in the
+string in addition to its normal function.
+.It Dv REG_PEND
+The regular expression ends,
+not at the first NUL,
+but just before the character pointed to by the
+.Va re_endp
+member of the structure pointed to by
+.Fa preg .
+The
+.Va re_endp
+member is of type
+.Ft "const char *" .
+This flag permits inclusion of NULs in the RE;
+they are considered ordinary characters.
+This is an extension,
+compatible with but not specified by
+.St -p1003.2 ,
+and should be used with
+caution in software intended to be portable to other systems.
+.El
+.Pp
+When successful,
+.Fn regcomp
+returns 0 and fills in the structure pointed to by
+.Fa preg .
+One member of that structure
+(other than
+.Va re_endp )
+is publicized:
+.Va re_nsub ,
+of type
+.Ft size_t ,
+contains the number of parenthesized subexpressions within the RE
+(except that the value of this member is undefined if the
+.Dv REG_NOSUB
+flag was used).
+If
+.Fn regcomp
+fails, it returns a non-zero error code;
+see
+.Sx DIAGNOSTICS .
+.Pp
+The
+.Fn regexec
+function
+matches the compiled RE pointed to by
+.Fa preg
+against the
+.Fa string ,
+subject to the flags in
+.Fa eflags ,
+and reports results using
+.Fa nmatch ,
+.Fa pmatch ,
+and the returned value.
+The RE must have been compiled by a previous invocation of
+.Fn regcomp .
+The compiled form is not altered during execution of
+.Fn regexec ,
+so a single compiled RE can be used simultaneously by multiple threads.
+.Pp
+By default,
+the NUL-terminated string pointed to by
+.Fa string
+is considered to be the text of an entire line, minus any terminating
+newline.
+The
+.Fa eflags
+argument is the bitwise OR of zero or more of the following flags:
+.Bl -tag -width REG_STARTEND
+.It Dv REG_NOTBOL
+The first character of
+the string
+is not the beginning of a line, so the
+.Ql ^\&
+anchor should not match before it.
+This does not affect the behavior of newlines under
+.Dv REG_NEWLINE .
+.It Dv REG_NOTEOL
+The NUL terminating
+the string
+does not end a line, so the
+.Ql $\&
+anchor should not match before it.
+This does not affect the behavior of newlines under
+.Dv REG_NEWLINE .
+.It Dv REG_STARTEND
+The string is considered to start at
+.Fa string
++
+.Fa pmatch Ns [0]. Ns Va rm_so
+and to have a terminating NUL located at
+.Fa string
++
+.Fa pmatch Ns [0]. Ns Va rm_eo
+(there need not actually be a NUL at that location),
+regardless of the value of
+.Fa nmatch .
+See below for the definition of
+.Fa pmatch
+and
+.Fa nmatch .
+This is an extension,
+compatible with but not specified by
+.St -p1003.2 ,
+and should be used with
+caution in software intended to be portable to other systems.
+Note that a non-zero
+.Va rm_so
+does not imply
+.Dv REG_NOTBOL ;
+.Dv REG_STARTEND
+affects only the location of the string,
+not how it is matched.
+.El
+.Pp
+See
+.Xr re_format 7
+for a discussion of what is matched in situations where an RE or a
+portion thereof could match any of several substrings of
+.Fa string .
+.Pp
+Normally,
+.Fn regexec
+returns 0 for success and the non-zero code
+.Dv REG_NOMATCH
+for failure.
+Other non-zero error codes may be returned in exceptional situations;
+see
+.Sx DIAGNOSTICS .
+.Pp
+If
+.Dv REG_NOSUB
+was specified in the compilation of the RE,
+or if
+.Fa nmatch
+is 0,
+.Fn regexec
+ignores the
+.Fa pmatch
+argument (but see below for the case where
+.Dv REG_STARTEND
+is specified).
+Otherwise,
+.Fa pmatch
+points to an array of
+.Fa nmatch
+structures of type
+.Ft regmatch_t .
+Such a structure has at least the members
+.Va rm_so
+and
+.Va rm_eo ,
+both of type
+.Ft regoff_t
+(a signed arithmetic type at least as large as an
+.Ft off_t
+and a
+.Ft ssize_t ) ,
+containing respectively the offset of the first character of a substring
+and the offset of the first character after the end of the substring.
+Offsets are measured from the beginning of the
+.Fa string
+argument given to
+.Fn regexec .
+An empty substring is denoted by equal offsets,
+both indicating the character following the empty substring.
+.Pp
+The 0th member of the
+.Fa pmatch
+array is filled in to indicate what substring of
+.Fa string
+was matched by the entire RE.
+Remaining members report what substring was matched by parenthesized
+subexpressions within the RE;
+member
+.Va i
+reports subexpression
+.Va i ,
+with subexpressions counted (starting at 1) by the order of their opening
+parentheses in the RE, left to right.
+Unused entries in the array (corresponding either to subexpressions that
+did not participate in the match at all, or to subexpressions that do not
+exist in the RE (that is,
+.Va i
+>
+.Fa preg Ns -> Ns Va re_nsub ) )
+have both
+.Va rm_so
+and
+.Va rm_eo
+set to -1.
+If a subexpression participated in the match several times,
+the reported substring is the last one it matched.
+(Note, as an example in particular, that when the RE
+.Ql "(b*)+"
+matches
+.Ql bbb ,
+the parenthesized subexpression matches each of the three
+.So Li b Sc Ns s
+and then
+an infinite number of empty strings following the last
+.Ql b ,
+so the reported substring is one of the empties.)
+.Pp
+If
+.Dv REG_STARTEND
+is specified,
+.Fa pmatch
+must point to at least one
+.Ft regmatch_t
+(even if
+.Fa nmatch
+is 0 or
+.Dv REG_NOSUB
+was specified),
+to hold the input offsets for
+.Dv REG_STARTEND .
+Use for output is still entirely controlled by
+.Fa nmatch ;
+if
+.Fa nmatch
+is 0 or
+.Dv REG_NOSUB
+was specified,
+the value of
+.Fa pmatch Ns [0]
+will not be changed by a successful
+.Fn regexec .
+.Pp
+The
+.Fn regerror
+function
+maps a non-zero
+.Fa errcode
+from either
+.Fn regcomp
+or
+.Fn regexec
+to a human-readable, printable message.
+If
+.Fa preg
+is
+.No non\- Ns Dv NULL ,
+the error code should have arisen from use of
+the
+.Ft regex_t
+pointed to by
+.Fa preg ,
+and if the error code came from
+.Fn regcomp ,
+it should have been the result from the most recent
+.Fn regcomp
+using that
+.Ft regex_t .
+The
+.Fn ( regerror
+may be able to supply a more detailed message using information
+from the
+.Ft regex_t . )
+The
+.Fn regerror
+function
+places the NUL-terminated message into the buffer pointed to by
+.Fa errbuf ,
+limiting the length (including the NUL) to at most
+.Fa errbuf_size
+bytes.
+If the whole message will not fit,
+as much of it as will fit before the terminating NUL is supplied.
+In any case,
+the returned value is the size of buffer needed to hold the whole
+message (including terminating NUL).
+If
+.Fa errbuf_size
+is 0,
+.Fa errbuf
+is ignored but the return value is still correct.
+.Pp
+If the
+.Fa errcode
+given to
+.Fn regerror
+is first ORed with
+.Dv REG_ITOA ,
+the
+.Dq message
+that results is the printable name of the error code,
+e.g.\&
+.Dq Dv REG_NOMATCH ,
+rather than an explanation thereof.
+If
+.Fa errcode
+is
+.Dv REG_ATOI ,
+then
+.Fa preg
+shall be
+.No non\- Ns Dv NULL
+and the
+.Va re_endp
+member of the structure it points to
+must point to the printable name of an error code;
+in this case, the result in
+.Fa errbuf
+is the decimal digits of
+the numeric value of the error code
+(0 if the name is not recognized).
+.Dv REG_ITOA
+and
+.Dv REG_ATOI
+are intended primarily as debugging facilities;
+they are extensions,
+compatible with but not specified by
+.St -p1003.2 ,
+and should be used with
+caution in software intended to be portable to other systems.
+Be warned also that they are considered experimental and changes are possible.
+.Pp
+The
+.Fn regfree
+function
+frees any dynamically-allocated storage associated with the compiled RE
+pointed to by
+.Fa preg .
+The remaining
+.Ft regex_t
+is no longer a valid compiled RE
+and the effect of supplying it to
+.Fn regexec
+or
+.Fn regerror
+is undefined.
+.Pp
+None of these functions references global variables except for tables
+of constants;
+all are safe for use from multiple threads if the arguments are safe.
+.Sh IMPLEMENTATION CHOICES
+There are a number of decisions that
+.St -p1003.2
+leaves up to the implementor,
+either by explicitly saying
+.Dq undefined
+or by virtue of them being
+forbidden by the RE grammar.
+This implementation treats them as follows.
+.Pp
+See
+.Xr re_format 7
+for a discussion of the definition of case-independent matching.
+.Pp
+There is no particular limit on the length of REs,
+except insofar as memory is limited.
+Memory usage is approximately linear in RE size, and largely insensitive
+to RE complexity, except for bounded repetitions.
+See
+.Sx BUGS
+for one short RE using them
+that will run almost any system out of memory.
+.Pp
+A backslashed character other than one specifically given a magic meaning
+by
+.St -p1003.2
+(such magic meanings occur only in obsolete
+.Bq Dq basic
+REs)
+is taken as an ordinary character.
+.Pp
+Any unmatched
+.Ql [\&
+is a
+.Dv REG_EBRACK
+error.
+.Pp
+Equivalence classes cannot begin or end bracket-expression ranges.
+The endpoint of one range cannot begin another.
+.Pp
+.Dv RE_DUP_MAX ,
+the limit on repetition counts in bounded repetitions, is 255.
+.Pp
+A repetition operator
+.Ql ( ?\& ,
+.Ql *\& ,
+.Ql +\& ,
+or bounds)
+cannot follow another
+repetition operator.
+A repetition operator cannot begin an expression or subexpression
+or follow
+.Ql ^\&
+or
+.Ql |\& .
+.Pp
+.Ql |\&
+cannot appear first or last in a (sub)expression or after another
+.Ql |\& ,
+i.e., an operand of
+.Ql |\&
+cannot be an empty subexpression.
+An empty parenthesized subexpression,
+.Ql "()" ,
+is legal and matches an
+empty (sub)string.
+An empty string is not a legal RE.
+.Pp
+A
+.Ql {\&
+followed by a digit is considered the beginning of bounds for a
+bounded repetition, which must then follow the syntax for bounds.
+A
+.Ql {\&
+.Em not
+followed by a digit is considered an ordinary character.
+.Pp
+.Ql ^\&
+and
+.Ql $\&
+beginning and ending subexpressions in obsolete
+.Pq Dq basic
+REs are anchors, not ordinary characters.
+.Sh DIAGNOSTICS
+Non-zero error codes from
+.Fn regcomp
+and
+.Fn regexec
+include the following:
+.Pp
+.Bl -tag -width REG_ECOLLATE -compact
+.It Dv REG_NOMATCH
+The
+.Fn regexec
+function
+failed to match
+.It Dv REG_BADPAT
+invalid regular expression
+.It Dv REG_ECOLLATE
+invalid collating element
+.It Dv REG_ECTYPE
+invalid character class
+.It Dv REG_EESCAPE
+.Ql \e
+applied to unescapable character
+.It Dv REG_ESUBREG
+invalid backreference number
+.It Dv REG_EBRACK
+brackets
+.Ql "[ ]"
+not balanced
+.It Dv REG_EPAREN
+parentheses
+.Ql "( )"
+not balanced
+.It Dv REG_EBRACE
+braces
+.Ql "{ }"
+not balanced
+.It Dv REG_BADBR
+invalid repetition count(s) in
+.Ql "{ }"
+.It Dv REG_ERANGE
+invalid character range in
+.Ql "[ ]"
+.It Dv REG_ESPACE
+ran out of memory
+.It Dv REG_BADRPT
+.Ql ?\& ,
+.Ql *\& ,
+or
+.Ql +\&
+operand invalid
+.It Dv REG_EMPTY
+empty (sub)expression
+.It Dv REG_ASSERT
+cannot happen - you found a bug
+.It Dv REG_INVARG
+invalid argument, e.g.\& negative-length string
+.It Dv REG_ILLSEQ
+illegal byte sequence (bad multibyte character)
+.El
+.Sh SEE ALSO
+.Xr grep 1 ,
+.Xr re_format 7
+.Pp
+.St -p1003.2 ,
+sections 2.8 (Regular Expression Notation)
+and
+B.5 (C Binding for Regular Expression Matching).
+.Sh HISTORY
+Originally written by
+.An Henry Spencer .
+Altered for inclusion in the
+.Bx 4.4
+distribution.
+.Sh BUGS
+This is an alpha release with known defects.
+Please report problems.
+.Pp
+The back-reference code is subtle and doubts linger about its correctness
+in complex cases.
+.Pp
+The
+.Fn regexec
+function
+performance is poor.
+This will improve with later releases.
+The
+.Fa nmatch
+argument
+exceeding 0 is expensive;
+.Fa nmatch
+exceeding 1 is worse.
+The
+.Fn regexec
+function
+is largely insensitive to RE complexity
+.Em except
+that back
+references are massively expensive.
+RE length does matter; in particular, there is a strong speed bonus
+for keeping RE length under about 30 characters,
+with most special characters counting roughly double.
+.Pp
+The
+.Fn regcomp
+function
+implements bounded repetitions by macro expansion,
+which is costly in time and space if counts are large
+or bounded repetitions are nested.
+An RE like, say,
+.Ql "((((a{1,100}){1,100}){1,100}){1,100}){1,100}"
+will (eventually) run almost any existing machine out of swap space.
+.Pp
+There are suspected problems with response to obscure error conditions.
+Notably,
+certain kinds of internal overflow,
+produced only by truly enormous REs or by multiply nested bounded repetitions,
+are probably not handled well.
+.Pp
+Due to a mistake in
+.St -p1003.2 ,
+things like
+.Ql "a)b"
+are legal REs because
+.Ql )\&
+is
+a special character only in the presence of a previous unmatched
+.Ql (\& .
+This cannot be fixed until the spec is fixed.
+.Pp
+The standard's definition of back references is vague.
+For example, does
+.Ql "a\e(\e(b\e)*\e2\e)*d"
+match
+.Ql "abbbd" ?
+Until the standard is clarified,
+behavior in such cases should not be relied on.
+.Pp
+The implementation of word-boundary matching is a bit of a kludge,
+and bugs may lurk in combinations of word-boundary matching and anchoring.
+.Pp
+Word-boundary matching does not work properly in multibyte locales.
diff --git a/lib/libc/regex/regex2.h b/lib/libc/regex/regex2.h
new file mode 100644
index 0000000..7aa717e
--- /dev/null
+++ b/lib/libc/regex/regex2.h
@@ -0,0 +1,192 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)regex2.h 8.4 (Berkeley) 3/20/94
+ * $FreeBSD$
+ */
+
+/*
+ * First, the stuff that ends up in the outside-world include file
+ = typedef off_t regoff_t;
+ = typedef struct {
+ = int re_magic;
+ = size_t re_nsub; // number of parenthesized subexpressions
+ = const char *re_endp; // end pointer for REG_PEND
+ = struct re_guts *re_g; // none of your business :-)
+ = } regex_t;
+ = typedef struct {
+ = regoff_t rm_so; // start of match
+ = regoff_t rm_eo; // end of match
+ = } regmatch_t;
+ */
+/*
+ * internals of regex_t
+ */
+#define MAGIC1 ((('r'^0200)<<8) | 'e')
+
+/*
+ * The internal representation is a *strip*, a sequence of
+ * operators ending with an endmarker. (Some terminology etc. is a
+ * historical relic of earlier versions which used multiple strips.)
+ * Certain oddities in the representation are there to permit running
+ * the machinery backwards; in particular, any deviation from sequential
+ * flow must be marked at both its source and its destination. Some
+ * fine points:
+ *
+ * - OPLUS_ and O_PLUS are *inside* the loop they create.
+ * - OQUEST_ and O_QUEST are *outside* the bypass they create.
+ * - OCH_ and O_CH are *outside* the multi-way branch they create, while
+ * OOR1 and OOR2 are respectively the end and the beginning of one of
+ * the branches. Note that there is an implicit OOR2 following OCH_
+ * and an implicit OOR1 preceding O_CH.
+ *
+ * In state representations, an operator's bit is on to signify a state
+ * immediately *preceding* "execution" of that operator.
+ */
+typedef unsigned long sop; /* strip operator */
+typedef long sopno;
+#define OPRMASK 0xf8000000L
+#define OPDMASK 0x07ffffffL
+#define OPSHIFT ((unsigned)27)
+#define OP(n) ((n)&OPRMASK)
+#define OPND(n) ((n)&OPDMASK)
+#define SOP(op, opnd) ((op)|(opnd))
+/* operators meaning operand */
+/* (back, fwd are offsets) */
+#define OEND (1L<<OPSHIFT) /* endmarker - */
+#define OCHAR (2L<<OPSHIFT) /* character wide character */
+#define OBOL (3L<<OPSHIFT) /* left anchor - */
+#define OEOL (4L<<OPSHIFT) /* right anchor - */
+#define OANY (5L<<OPSHIFT) /* . - */
+#define OANYOF (6L<<OPSHIFT) /* [...] set number */
+#define OBACK_ (7L<<OPSHIFT) /* begin \d paren number */
+#define O_BACK (8L<<OPSHIFT) /* end \d paren number */
+#define OPLUS_ (9L<<OPSHIFT) /* + prefix fwd to suffix */
+#define O_PLUS (10L<<OPSHIFT) /* + suffix back to prefix */
+#define OQUEST_ (11L<<OPSHIFT) /* ? prefix fwd to suffix */
+#define O_QUEST (12L<<OPSHIFT) /* ? suffix back to prefix */
+#define OLPAREN (13L<<OPSHIFT) /* ( fwd to ) */
+#define ORPAREN (14L<<OPSHIFT) /* ) back to ( */
+#define OCH_ (15L<<OPSHIFT) /* begin choice fwd to OOR2 */
+#define OOR1 (16L<<OPSHIFT) /* | pt. 1 back to OOR1 or OCH_ */
+#define OOR2 (17L<<OPSHIFT) /* | pt. 2 fwd to OOR2 or O_CH */
+#define O_CH (18L<<OPSHIFT) /* end choice back to OOR1 */
+#define OBOW (19L<<OPSHIFT) /* begin word - */
+#define OEOW (20L<<OPSHIFT) /* end word - */
+
+/*
+ * Structures for [] character-set representation.
+ */
+typedef struct {
+ wint_t min;
+ wint_t max;
+} crange;
+typedef struct {
+ unsigned char bmp[NC / 8];
+ wctype_t *types;
+ int ntypes;
+ wint_t *wides;
+ int nwides;
+ crange *ranges;
+ int nranges;
+ int invert;
+ int icase;
+} cset;
+
+static int
+CHIN1(cset *cs, wint_t ch)
+{
+ int i;
+
+ assert(ch >= 0);
+ if (ch < NC)
+ return (((cs->bmp[ch >> 3] & (1 << (ch & 7))) != 0) ^
+ cs->invert);
+ for (i = 0; i < cs->nwides; i++)
+ if (ch == cs->wides[i])
+ return (!cs->invert);
+ for (i = 0; i < cs->nranges; i++)
+ if (cs->ranges[i].min <= ch && ch <= cs->ranges[i].max)
+ return (!cs->invert);
+ for (i = 0; i < cs->ntypes; i++)
+ if (iswctype(ch, cs->types[i]))
+ return (!cs->invert);
+ return (cs->invert);
+}
+
+static __inline int
+CHIN(cset *cs, wint_t ch)
+{
+
+ assert(ch >= 0);
+ if (ch < NC)
+ return (((cs->bmp[ch >> 3] & (1 << (ch & 7))) != 0) ^
+ cs->invert);
+ else if (cs->icase)
+ return (CHIN1(cs, ch) || CHIN1(cs, towlower(ch)) ||
+ CHIN1(cs, towupper(ch)));
+ else
+ return (CHIN1(cs, ch));
+}
+
+/*
+ * main compiled-expression structure
+ */
+struct re_guts {
+ int magic;
+# define MAGIC2 ((('R'^0200)<<8)|'E')
+ sop *strip; /* malloced area for strip */
+ int ncsets; /* number of csets in use */
+ cset *sets; /* -> cset [ncsets] */
+ int cflags; /* copy of regcomp() cflags argument */
+ sopno nstates; /* = number of sops */
+ sopno firststate; /* the initial OEND (normally 0) */
+ sopno laststate; /* the final OEND */
+ int iflags; /* internal flags */
+# define USEBOL 01 /* used ^ */
+# define USEEOL 02 /* used $ */
+# define BAD 04 /* something wrong */
+ int nbol; /* number of ^ used */
+ int neol; /* number of $ used */
+ char *must; /* match must contain this string */
+ int moffset; /* latest point at which must may be located */
+ int *charjump; /* Boyer-Moore char jump table */
+ int *matchjump; /* Boyer-Moore match jump table */
+ int mlen; /* length of must */
+ size_t nsub; /* copy of re_nsub */
+ int backrefs; /* does it use back references? */
+ sopno nplus; /* how deep does it nest +s? */
+};
+
+/* misc utilities */
+#define OUT (CHAR_MIN - 1) /* a non-character value */
+#define ISWORD(c) (iswalnum((uch)(c)) || (c) == '_')
diff --git a/lib/libc/regex/regexec.c b/lib/libc/regex/regexec.c
new file mode 100644
index 0000000..1cf87b8
--- /dev/null
+++ b/lib/libc/regex/regexec.c
@@ -0,0 +1,233 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)regexec.c 8.3 (Berkeley) 3/20/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regexec.c 8.3 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * the outer shell of regexec()
+ *
+ * This file includes engine.c three times, after muchos fiddling with the
+ * macros that code uses. This lets the same code operate on two different
+ * representations for state sets and characters.
+ */
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <ctype.h>
+#include <regex.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "utils.h"
+#include "regex2.h"
+
+static int nope __unused = 0; /* for use in asserts; shuts lint up */
+
+static __inline size_t
+xmbrtowc(wint_t *wi, const char *s, size_t n, mbstate_t *mbs, wint_t dummy)
+{
+ size_t nr;
+ wchar_t wc;
+
+ nr = mbrtowc(&wc, s, n, mbs);
+ if (wi != NULL)
+ *wi = wc;
+ if (nr == 0)
+ return (1);
+ else if (nr == (size_t)-1 || nr == (size_t)-2) {
+ memset(mbs, 0, sizeof(*mbs));
+ if (wi != NULL)
+ *wi = dummy;
+ return (1);
+ } else
+ return (nr);
+}
+
+static __inline size_t
+xmbrtowc_dummy(wint_t *wi,
+ const char *s,
+ size_t n __unused,
+ mbstate_t *mbs __unused,
+ wint_t dummy __unused)
+{
+
+ if (wi != NULL)
+ *wi = (unsigned char)*s;
+ return (1);
+}
+
+/* macros for manipulating states, small version */
+#define states long
+#define states1 states /* for later use in regexec() decision */
+#define CLEAR(v) ((v) = 0)
+#define SET0(v, n) ((v) &= ~((unsigned long)1 << (n)))
+#define SET1(v, n) ((v) |= (unsigned long)1 << (n))
+#define ISSET(v, n) (((v) & ((unsigned long)1 << (n))) != 0)
+#define ASSIGN(d, s) ((d) = (s))
+#define EQ(a, b) ((a) == (b))
+#define STATEVARS long dummy /* dummy version */
+#define STATESETUP(m, n) /* nothing */
+#define STATETEARDOWN(m) /* nothing */
+#define SETUP(v) ((v) = 0)
+#define onestate long
+#define INIT(o, n) ((o) = (unsigned long)1 << (n))
+#define INC(o) ((o) <<= 1)
+#define ISSTATEIN(v, o) (((v) & (o)) != 0)
+/* some abbreviations; note that some of these know variable names! */
+/* do "if I'm here, I can also be there" etc without branches */
+#define FWD(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) << (n))
+#define BACK(dst, src, n) ((dst) |= ((unsigned long)(src)&(here)) >> (n))
+#define ISSETBACK(v, n) (((v) & ((unsigned long)here >> (n))) != 0)
+/* no multibyte support */
+#define XMBRTOWC xmbrtowc_dummy
+#define ZAPSTATE(mbs) ((void)(mbs))
+/* function names */
+#define SNAMES /* engine.c looks after details */
+
+#include "engine.c"
+
+/* now undo things */
+#undef states
+#undef CLEAR
+#undef SET0
+#undef SET1
+#undef ISSET
+#undef ASSIGN
+#undef EQ
+#undef STATEVARS
+#undef STATESETUP
+#undef STATETEARDOWN
+#undef SETUP
+#undef onestate
+#undef INIT
+#undef INC
+#undef ISSTATEIN
+#undef FWD
+#undef BACK
+#undef ISSETBACK
+#undef SNAMES
+#undef XMBRTOWC
+#undef ZAPSTATE
+
+/* macros for manipulating states, large version */
+#define states char *
+#define CLEAR(v) memset(v, 0, m->g->nstates)
+#define SET0(v, n) ((v)[n] = 0)
+#define SET1(v, n) ((v)[n] = 1)
+#define ISSET(v, n) ((v)[n])
+#define ASSIGN(d, s) memcpy(d, s, m->g->nstates)
+#define EQ(a, b) (memcmp(a, b, m->g->nstates) == 0)
+#define STATEVARS long vn; char *space
+#define STATESETUP(m, nv) { (m)->space = malloc((nv)*(m)->g->nstates); \
+ if ((m)->space == NULL) return(REG_ESPACE); \
+ (m)->vn = 0; }
+#define STATETEARDOWN(m) { free((m)->space); }
+#define SETUP(v) ((v) = &m->space[m->vn++ * m->g->nstates])
+#define onestate long
+#define INIT(o, n) ((o) = (n))
+#define INC(o) ((o)++)
+#define ISSTATEIN(v, o) ((v)[o])
+/* some abbreviations; note that some of these know variable names! */
+/* do "if I'm here, I can also be there" etc without branches */
+#define FWD(dst, src, n) ((dst)[here+(n)] |= (src)[here])
+#define BACK(dst, src, n) ((dst)[here-(n)] |= (src)[here])
+#define ISSETBACK(v, n) ((v)[here - (n)])
+/* no multibyte support */
+#define XMBRTOWC xmbrtowc_dummy
+#define ZAPSTATE(mbs) ((void)(mbs))
+/* function names */
+#define LNAMES /* flag */
+
+#include "engine.c"
+
+/* multibyte character & large states version */
+#undef LNAMES
+#undef XMBRTOWC
+#undef ZAPSTATE
+#define XMBRTOWC xmbrtowc
+#define ZAPSTATE(mbs) memset((mbs), 0, sizeof(*(mbs)))
+#define MNAMES
+
+#include "engine.c"
+
+/*
+ - regexec - interface for matching
+ = extern int regexec(const regex_t *, const char *, size_t, \
+ = regmatch_t [], int);
+ = #define REG_NOTBOL 00001
+ = #define REG_NOTEOL 00002
+ = #define REG_STARTEND 00004
+ = #define REG_TRACE 00400 // tracing of execution
+ = #define REG_LARGE 01000 // force large representation
+ = #define REG_BACKR 02000 // force use of backref code
+ *
+ * We put this here so we can exploit knowledge of the state representation
+ * when choosing which matcher to call. Also, by this point the matchers
+ * have been prototyped.
+ */
+int /* 0 success, REG_NOMATCH failure */
+regexec(const regex_t * __restrict preg,
+ const char * __restrict string,
+ size_t nmatch,
+ regmatch_t pmatch[__restrict],
+ int eflags)
+{
+ struct re_guts *g = preg->re_g;
+#ifdef REDEBUG
+# define GOODFLAGS(f) (f)
+#else
+# define GOODFLAGS(f) ((f)&(REG_NOTBOL|REG_NOTEOL|REG_STARTEND))
+#endif
+
+ if (preg->re_magic != MAGIC1 || g->magic != MAGIC2)
+ return(REG_BADPAT);
+ assert(!(g->iflags&BAD));
+ if (g->iflags&BAD) /* backstop for no-debug case */
+ return(REG_BADPAT);
+ eflags = GOODFLAGS(eflags);
+
+ if (MB_CUR_MAX > 1)
+ return(mmatcher(g, (char *)string, nmatch, pmatch, eflags));
+ else if (g->nstates <= CHAR_BIT*sizeof(states1) && !(eflags&REG_LARGE))
+ return(smatcher(g, (char *)string, nmatch, pmatch, eflags));
+ else
+ return(lmatcher(g, (char *)string, nmatch, pmatch, eflags));
+}
diff --git a/lib/libc/regex/regfree.c b/lib/libc/regex/regfree.c
new file mode 100644
index 0000000..c979bec
--- /dev/null
+++ b/lib/libc/regex/regfree.c
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)regfree.c 8.3 (Berkeley) 3/20/94
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)regfree.c 8.3 (Berkeley) 3/20/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <limits.h>
+#include <regex.h>
+#include <wchar.h>
+#include <wctype.h>
+
+#include "utils.h"
+#include "regex2.h"
+
+/*
+ - regfree - free everything
+ = extern void regfree(regex_t *);
+ */
+void
+regfree(regex_t *preg)
+{
+ struct re_guts *g;
+ int i;
+
+ if (preg->re_magic != MAGIC1) /* oops */
+ return; /* nice to complain, but hard */
+
+ g = preg->re_g;
+ if (g == NULL || g->magic != MAGIC2) /* oops again */
+ return;
+ preg->re_magic = 0; /* mark it invalid */
+ g->magic = 0; /* mark it invalid */
+
+ if (g->strip != NULL)
+ free((char *)g->strip);
+ if (g->sets != NULL) {
+ for (i = 0; i < g->ncsets; i++) {
+ free(g->sets[i].ranges);
+ free(g->sets[i].wides);
+ free(g->sets[i].types);
+ }
+ free((char *)g->sets);
+ }
+ if (g->must != NULL)
+ free(g->must);
+ if (g->charjump != NULL)
+ free(&g->charjump[CHAR_MIN]);
+ if (g->matchjump != NULL)
+ free(g->matchjump);
+ free((char *)g);
+}
diff --git a/lib/libc/regex/utils.h b/lib/libc/regex/utils.h
new file mode 100644
index 0000000..3531aed
--- /dev/null
+++ b/lib/libc/regex/utils.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1992, 1993, 1994 Henry Spencer.
+ * Copyright (c) 1992, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Henry Spencer.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)utils.h 8.3 (Berkeley) 3/20/94
+ * $FreeBSD$
+ */
+
+/* utility definitions */
+#define DUPMAX _POSIX2_RE_DUP_MAX /* xxx is this right? */
+#define INFINITY (DUPMAX + 1)
+#define NC (CHAR_MAX - CHAR_MIN + 1)
+typedef unsigned char uch;
+
+/* switch off assertions (if not already off) if no REDEBUG */
+#ifndef REDEBUG
+#ifndef NDEBUG
+#define NDEBUG /* no assertions please */
+#endif
+#endif
+#include <assert.h>
+
+/* for old systems with bcopy() but no memmove() */
+#ifdef USEBCOPY
+#define memmove(d, s, c) bcopy(s, d, c)
+#endif
diff --git a/lib/libc/resolv/Makefile.inc b/lib/libc/resolv/Makefile.inc
new file mode 100644
index 0000000..cd023cf
--- /dev/null
+++ b/lib/libc/resolv/Makefile.inc
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+# resolv sources
+.PATH: ${.CURDIR}/resolv
+
+SRCS+= herror.c h_errno.c mtctxres.c res_comp.c res_data.c res_debug.c \
+ res_findzonecut.c res_init.c res_mkquery.c res_mkupdate.c \
+ res_query.c res_send.c res_state.c res_update.c
+
+SYM_MAPS+= ${.CURDIR}/resolv/Symbol.map
diff --git a/lib/libc/resolv/Symbol.map b/lib/libc/resolv/Symbol.map
new file mode 100644
index 0000000..211f2c4
--- /dev/null
+++ b/lib/libc/resolv/Symbol.map
@@ -0,0 +1,107 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ /* h_nerr; */ /* Why is this not staticized in net/herror.c? */
+ h_errlist;
+ herror;
+ hstrerror;
+ __dn_expand;
+ __dn_comp;
+ __dn_skipname;
+ __res_hnok;
+ __res_ownok;
+ __res_mailok;
+ __res_dnok;
+ __putlong;
+ __putshort;
+ _getlong;
+ _getshort;
+ dn_comp;
+ dn_expand;
+ __fp_resstat;
+ __p_query;
+ __fp_query;
+ __fp_nquery;
+ __p_cdnname;
+ __p_cdname;
+ __p_fqnname;
+ __p_fqname;
+ __p_cert_syms;
+ __p_class_syms;
+ __p_key_syms;
+ __p_rcode_syms;
+ __p_type_syms;
+ __sym_ston;
+ __sym_ntos;
+ __sym_ntop;
+ __p_rcode;
+ __p_sockun;
+ __p_type;
+ __p_section;
+ __p_class;
+ __p_option;
+ __p_time;
+ __loc_aton;
+ __loc_ntoa;
+ __dn_count_labels;
+ __p_secstodate;
+ fp_resstat;
+ p_query;
+ p_fqnname;
+ sym_ston;
+ sym_ntos;
+ sym_ntop;
+ dn_count_labels;
+ p_secstodate;
+ __res_init;
+ __res_randomid;
+ __h_errno;
+ __h_errno_set;
+ h_errno;
+ res_init;
+ __res_findzonecut2;
+ __res_freeupdrec;
+ __res_mkquery;
+ res_mkquery;
+ __res_mkupdrec;
+ __res_mkupdate;
+ __res_opt;
+ __res_getservers;
+ __res_hostalias;
+ __res_nametoclass;
+ __res_nametotype;
+ __res_nclose;
+ __res_ndestroy;
+ __res_ninit;
+ __res_nmkquery;
+ __res_nmkupdate;
+ __res_nopt;
+ __res_nquery;
+ __res_nquerydomain;
+ __res_nsearch;
+ __res_nsend;
+ __res_nupdate;
+ __res_ourserver_p;
+ __res_pquery;
+ __res_query;
+ __res_search;
+ __res_querydomain;
+ __res_setservers;
+ _res;
+ __res_state;
+ __res_vinit;
+ __hostalias;
+ res_query;
+ res_search;
+ res_querydomain;
+ __res_isourserver;
+ __res_nameinquery;
+ __res_queriesmatch;
+ __res_send;
+ __res_close;
+ _res_close;
+ res_send;
+ __res_update;
+};
diff --git a/lib/libc/resolv/h_errno.c b/lib/libc/resolv/h_errno.c
new file mode 100644
index 0000000..88d15ae
--- /dev/null
+++ b/lib/libc/resolv/h_errno.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2006 The FreeBSD Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+
+#undef h_errno
+extern int h_errno;
+
+int *
+__h_errno(void)
+{
+ return (&__res_state()->res_h_errno);
+}
+
+void
+__h_errno_set(res_state res, int err)
+{
+ h_errno = res->res_h_errno = err;
+}
diff --git a/lib/libc/resolv/herror.c b/lib/libc/resolv/herror.c
new file mode 100644
index 0000000..cb9dd0e
--- /dev/null
+++ b/lib/libc/resolv/herror.c
@@ -0,0 +1,126 @@
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)herror.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: herror.c,v 1.3.18.1 2005/04/27 05:01:09 sra Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+
+#include <netdb.h>
+#include <resolv.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "port_after.h"
+
+const char *h_errlist[] = {
+ "Resolver Error 0 (no error)",
+ "Unknown host", /*%< 1 HOST_NOT_FOUND */
+ "Host name lookup failure", /*%< 2 TRY_AGAIN */
+ "Unknown server error", /*%< 3 NO_RECOVERY */
+ "No address associated with name", /*%< 4 NO_ADDRESS */
+};
+const int h_nerr = { sizeof h_errlist / sizeof h_errlist[0] };
+
+#undef h_errno
+int h_errno;
+
+/*%
+ * herror --
+ * print the error indicated by the h_errno value.
+ */
+void
+herror(const char *s) {
+ struct iovec iov[4], *v = iov;
+ char *t;
+
+ if (s != NULL && *s != '\0') {
+ DE_CONST(s, t);
+ v->iov_base = t;
+ v->iov_len = strlen(t);
+ v++;
+ DE_CONST(": ", t);
+ v->iov_base = t;
+ v->iov_len = 2;
+ v++;
+ }
+ DE_CONST(hstrerror(*__h_errno()), t);
+ v->iov_base = t;
+ v->iov_len = strlen(v->iov_base);
+ v++;
+ DE_CONST("\n", t);
+ v->iov_base = t;
+ v->iov_len = 1;
+ _writev(STDERR_FILENO, iov, (v - iov) + 1);
+}
+
+/*%
+ * hstrerror --
+ * return the string associated with a given "host" errno value.
+ */
+const char *
+hstrerror(int err) {
+ if (err < 0)
+ return ("Resolver internal error");
+ else if (err < h_nerr)
+ return (h_errlist[err]);
+ return ("Unknown resolver error");
+}
+
+/*! \file */
diff --git a/lib/libc/resolv/mtctxres.c b/lib/libc/resolv/mtctxres.c
new file mode 100644
index 0000000..f02a7f5
--- /dev/null
+++ b/lib/libc/resolv/mtctxres.c
@@ -0,0 +1,141 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <port_before.h>
+#ifdef DO_PTHREADS
+#include <pthread.h>
+#ifdef _LIBC
+#include <pthread_np.h>
+#endif
+#endif
+#include <errno.h>
+#include <netdb.h>
+#include <stdlib.h>
+#include <string.h>
+#include <resolv_mt.h>
+#include <port_after.h>
+
+#ifdef DO_PTHREADS
+static pthread_key_t key;
+static int mt_key_initialized = 0;
+
+static int __res_init_ctx(void);
+static void __res_destroy_ctx(void *);
+
+#if defined(sun) && !defined(__GNUC__)
+#pragma init (_mtctxres_init)
+#endif
+#endif
+
+static mtctxres_t sharedctx;
+
+#ifdef DO_PTHREADS
+/*
+ * Initialize the TSD key. By doing this at library load time, we're
+ * implicitly running without interference from other threads, so there's
+ * no need for locking.
+ */
+static void
+_mtctxres_init(void) {
+ int pthread_keycreate_ret;
+
+ pthread_keycreate_ret = pthread_key_create(&key, __res_destroy_ctx);
+ if (pthread_keycreate_ret == 0)
+ mt_key_initialized = 1;
+}
+#endif
+
+#ifndef _LIBC
+/*
+ * To support binaries that used the private MT-safe interface in
+ * Solaris 8, we still need to provide the __res_enable_mt()
+ * and __res_disable_mt() entry points. They're do-nothing routines.
+ */
+int
+__res_enable_mt(void) {
+ return (-1);
+}
+
+int
+__res_disable_mt(void) {
+ return (0);
+}
+#endif
+
+#ifdef DO_PTHREADS
+static int
+__res_init_ctx(void) {
+
+ mtctxres_t *mt;
+ int ret;
+
+
+ if (pthread_getspecific(key) != 0) {
+ /* Already exists */
+ return (0);
+ }
+
+ if ((mt = malloc(sizeof (mtctxres_t))) == 0) {
+ errno = ENOMEM;
+ return (-1);
+ }
+
+ memset(mt, 0, sizeof (mtctxres_t));
+
+ if ((ret = pthread_setspecific(key, mt)) != 0) {
+ free(mt);
+ errno = ret;
+ return (-1);
+ }
+
+ return (0);
+}
+
+static void
+__res_destroy_ctx(void *value) {
+
+ mtctxres_t *mt = (mtctxres_t *)value;
+
+ if (mt != 0)
+ free(mt);
+}
+#endif
+
+mtctxres_t *
+___mtctxres(void) {
+#ifdef DO_PTHREADS
+ mtctxres_t *mt;
+
+#ifdef _LIBC
+ if (pthread_main_np() != 0)
+ return (&sharedctx);
+#endif
+
+ /*
+ * This if clause should only be executed if we are linking
+ * statically. When linked dynamically _mtctxres_init() should
+ * be called at binding time due the #pragma above.
+ */
+ if (!mt_key_initialized) {
+ static pthread_mutex_t keylock = PTHREAD_MUTEX_INITIALIZER;
+ if (pthread_mutex_lock(&keylock) == 0) {
+ _mtctxres_init();
+ (void) pthread_mutex_unlock(&keylock);
+ }
+ }
+
+ /*
+ * If we have already been called in this thread return the existing
+ * context. Otherwise recreat a new context and return it. If
+ * that fails return a global context.
+ */
+ if (mt_key_initialized) {
+ if (((mt = pthread_getspecific(key)) != 0) ||
+ (__res_init_ctx() == 0 &&
+ (mt = pthread_getspecific(key)) != 0)) {
+ return (mt);
+ }
+ }
+#endif
+ return (&sharedctx);
+}
diff --git a/lib/libc/resolv/res_comp.c b/lib/libc/resolv/res_comp.c
new file mode 100644
index 0000000..81bce5e
--- /dev/null
+++ b/lib/libc/resolv/res_comp.c
@@ -0,0 +1,277 @@
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_comp.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_comp.c,v 1.3.18.2 2005/07/28 07:38:11 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "port_after.h"
+
+/*%
+ * Expand compressed domain name 'src' to full domain name.
+ *
+ * \li 'msg' is a pointer to the begining of the message,
+ * \li 'eom' points to the first location after the message,
+ * \li 'dst' is a pointer to a buffer of size 'dstsiz' for the result.
+ * \li Return size of compressed name or -1 if there was an error.
+ */
+int
+dn_expand(const u_char *msg, const u_char *eom, const u_char *src,
+ char *dst, int dstsiz)
+{
+ int n = ns_name_uncompress(msg, eom, src, dst, (size_t)dstsiz);
+
+ if (n > 0 && dst[0] == '.')
+ dst[0] = '\0';
+ return (n);
+}
+
+/*%
+ * Pack domain name 'exp_dn' in presentation form into 'comp_dn'.
+ *
+ * \li Return the size of the compressed name or -1.
+ * \li 'length' is the size of the array pointed to by 'comp_dn'.
+ */
+int
+dn_comp(const char *src, u_char *dst, int dstsiz,
+ u_char **dnptrs, u_char **lastdnptr)
+{
+ return (ns_name_compress(src, dst, (size_t)dstsiz,
+ (const u_char **)dnptrs,
+ (const u_char **)lastdnptr));
+}
+
+/*%
+ * Skip over a compressed domain name. Return the size or -1.
+ */
+int
+dn_skipname(const u_char *ptr, const u_char *eom) {
+ const u_char *saveptr = ptr;
+
+ if (ns_name_skip(&ptr, eom) == -1)
+ return (-1);
+ return (ptr - saveptr);
+}
+
+/*%
+ * Verify that a domain name uses an acceptable character set.
+ *
+ * Note the conspicuous absence of ctype macros in these definitions. On
+ * non-ASCII hosts, we can't depend on string literals or ctype macros to
+ * tell us anything about network-format data. The rest of the BIND system
+ * is not careful about this, but for some reason, we're doing it right here.
+ */
+#define PERIOD 0x2e
+#define hyphenchar(c) ((c) == 0x2d)
+#define bslashchar(c) ((c) == 0x5c)
+#define underscorechar(c) ((c) == 0x5f)
+#define periodchar(c) ((c) == PERIOD)
+#define asterchar(c) ((c) == 0x2a)
+#define alphachar(c) (((c) >= 0x41 && (c) <= 0x5a) \
+ || ((c) >= 0x61 && (c) <= 0x7a))
+#define digitchar(c) ((c) >= 0x30 && (c) <= 0x39)
+
+#define borderchar(c) (alphachar(c) || digitchar(c))
+#ifdef RES_ENFORCE_RFC1034
+#define middlechar(c) (borderchar(c) || hyphenchar(c))
+#else
+#define middlechar(c) (borderchar(c) || hyphenchar(c) || underscorechar(c))
+#endif
+#define domainchar(c) ((c) > 0x20 && (c) < 0x7f)
+
+int
+res_hnok(const char *dn) {
+ int pch = PERIOD, ch = *dn++;
+
+ while (ch != '\0') {
+ int nch = *dn++;
+
+ if (periodchar(ch)) {
+ (void)NULL;
+ } else if (periodchar(pch)) {
+ if (!borderchar(ch))
+ return (0);
+ } else if (periodchar(nch) || nch == '\0') {
+ if (!borderchar(ch))
+ return (0);
+ } else {
+ if (!middlechar(ch))
+ return (0);
+ }
+ pch = ch, ch = nch;
+ }
+ return (1);
+}
+
+/*%
+ * hostname-like (A, MX, WKS) owners can have "*" as their first label
+ * but must otherwise be as a host name.
+ */
+int
+res_ownok(const char *dn) {
+ if (asterchar(dn[0])) {
+ if (periodchar(dn[1]))
+ return (res_hnok(dn+2));
+ if (dn[1] == '\0')
+ return (1);
+ }
+ return (res_hnok(dn));
+}
+
+/*%
+ * SOA RNAMEs and RP RNAMEs can have any printable character in their first
+ * label, but the rest of the name has to look like a host name.
+ */
+int
+res_mailok(const char *dn) {
+ int ch, escaped = 0;
+
+ /* "." is a valid missing representation */
+ if (*dn == '\0')
+ return (1);
+
+ /* otherwise <label>.<hostname> */
+ while ((ch = *dn++) != '\0') {
+ if (!domainchar(ch))
+ return (0);
+ if (!escaped && periodchar(ch))
+ break;
+ if (escaped)
+ escaped = 0;
+ else if (bslashchar(ch))
+ escaped = 1;
+ }
+ if (periodchar(ch))
+ return (res_hnok(dn));
+ return (0);
+}
+
+/*%
+ * This function is quite liberal, since RFC1034's character sets are only
+ * recommendations.
+ */
+int
+res_dnok(const char *dn) {
+ int ch;
+
+ while ((ch = *dn++) != '\0')
+ if (!domainchar(ch))
+ return (0);
+ return (1);
+}
+
+#ifdef BIND_4_COMPAT
+/*%
+ * This module must export the following externally-visible symbols:
+ * ___putlong
+ * ___putshort
+ * __getlong
+ * __getshort
+ * Note that one _ comes from C and the others come from us.
+ */
+
+#ifdef SOLARIS2
+#ifdef __putlong
+#undef __putlong
+#endif
+#ifdef __putshort
+#undef __putshort
+#endif
+#pragma weak putlong = __putlong
+#pragma weak putshort = __putshort
+#endif /* SOLARIS2 */
+
+void __putlong(u_int32_t src, u_char *dst) { ns_put32(src, dst); }
+void __putshort(u_int16_t src, u_char *dst) { ns_put16(src, dst); }
+#ifndef __ultrix__
+u_int32_t _getlong(const u_char *src) { return (ns_get32(src)); }
+u_int16_t _getshort(const u_char *src) { return (ns_get16(src)); }
+#endif /*__ultrix__*/
+#endif /*BIND_4_COMPAT*/
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <resolv.h>.
+ */
+#undef dn_comp
+__weak_reference(__dn_comp, dn_comp);
+#undef dn_expand
+__weak_reference(__dn_expand, dn_expand);
+
+/*! \file */
diff --git a/lib/libc/resolv/res_data.c b/lib/libc/resolv/res_data.c
new file mode 100644
index 0000000..5a1a50c
--- /dev/null
+++ b/lib/libc/resolv/res_data.c
@@ -0,0 +1,320 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1995-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char rcsid[] = "$Id: res_data.c,v 1.3.18.2 2007/09/14 05:35:47 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <res_update.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "port_after.h"
+
+const char *_res_opcodes[] = {
+ "QUERY",
+ "IQUERY",
+ "CQUERYM",
+ "CQUERYU", /*%< experimental */
+ "NOTIFY", /*%< experimental */
+ "UPDATE",
+ "6",
+ "7",
+ "8",
+ "9",
+ "10",
+ "11",
+ "12",
+ "13",
+ "ZONEINIT",
+ "ZONEREF",
+};
+
+#ifdef BIND_UPDATE
+const char *_res_sectioncodes[] = {
+ "ZONE",
+ "PREREQUISITES",
+ "UPDATE",
+ "ADDITIONAL",
+};
+#endif
+
+#ifndef __BIND_NOSTATIC
+
+/* Proto. */
+
+int res_ourserver_p(const res_state, const struct sockaddr_in *);
+
+int
+res_init(void) {
+ extern int __res_vinit(res_state, int);
+
+ /*
+ * These three fields used to be statically initialized. This made
+ * it hard to use this code in a shared library. It is necessary,
+ * now that we're doing dynamic initialization here, that we preserve
+ * the old semantics: if an application modifies one of these three
+ * fields of _res before res_init() is called, res_init() will not
+ * alter them. Of course, if an application is setting them to
+ * _zero_ before calling res_init(), hoping to override what used
+ * to be the static default, we can't detect it and unexpected results
+ * will follow. Zero for any of these fields would make no sense,
+ * so one can safely assume that the applications were already getting
+ * unexpected results.
+ *
+ * _res.options is tricky since some apps were known to diddle the bits
+ * before res_init() was first called. We can't replicate that semantic
+ * with dynamic initialization (they may have turned bits off that are
+ * set in RES_DEFAULT). Our solution is to declare such applications
+ * "broken". They could fool us by setting RES_INIT but none do (yet).
+ */
+ if (!_res.retrans)
+ _res.retrans = RES_TIMEOUT;
+ if (!_res.retry)
+ _res.retry = RES_DFLRETRY;
+ if (!(_res.options & RES_INIT))
+ _res.options = RES_DEFAULT;
+
+ /*
+ * This one used to initialize implicitly to zero, so unless the app
+ * has set it to something in particular, we can randomize it now.
+ */
+ if (!_res.id)
+ _res.id = res_randomid();
+
+ return (__res_vinit(&_res, 1));
+}
+
+void
+p_query(const u_char *msg) {
+ fp_query(msg, stdout);
+}
+
+void
+fp_query(const u_char *msg, FILE *file) {
+ fp_nquery(msg, PACKETSZ, file);
+}
+
+void
+fp_nquery(const u_char *msg, int len, FILE *file) {
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1)
+ return;
+
+ res_pquery(&_res, msg, len, file);
+}
+
+int
+res_mkquery(int op, /*!< opcode of query */
+ const char *dname, /*!< domain name */
+ int class, int type, /*!< class and type of query */
+ const u_char *data, /*!< resource record data */
+ int datalen, /*!< length of data */
+ const u_char *newrr_in, /*!< new rr for modify or append */
+ u_char *buf, /*!< buffer to put query */
+ int buflen) /*!< size of buffer */
+{
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+ return (res_nmkquery(&_res, op, dname, class, type,
+ data, datalen,
+ newrr_in, buf, buflen));
+}
+
+int
+res_mkupdate(ns_updrec *rrecp_in, u_char *buf, int buflen) {
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nmkupdate(&_res, rrecp_in, buf, buflen));
+}
+
+int
+res_query(const char *name, /*!< domain name */
+ int class, int type, /*!< class and type of query */
+ u_char *answer, /*!< buffer to put answer */
+ int anslen) /*!< size of answer buffer */
+{
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+ return (res_nquery(&_res, name, class, type, answer, anslen));
+}
+
+#ifndef _LIBC
+void
+res_send_setqhook(res_send_qhook hook) {
+ _res.qhook = hook;
+}
+
+void
+res_send_setrhook(res_send_rhook hook) {
+ _res.rhook = hook;
+}
+#endif
+
+int
+res_isourserver(const struct sockaddr_in *inp) {
+ return (res_ourserver_p(&_res, inp));
+}
+
+int
+res_send(const u_char *buf, int buflen, u_char *ans, int anssiz) {
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ /* errno should have been set by res_init() in this case. */
+ return (-1);
+ }
+
+ return (res_nsend(&_res, buf, buflen, ans, anssiz));
+}
+
+#ifndef _LIBC
+int
+res_sendsigned(const u_char *buf, int buflen, ns_tsig_key *key,
+ u_char *ans, int anssiz)
+{
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ /* errno should have been set by res_init() in this case. */
+ return (-1);
+ }
+
+ return (res_nsendsigned(&_res, buf, buflen, key, ans, anssiz));
+}
+#endif
+
+void
+res_close(void) {
+ res_nclose(&_res);
+}
+
+int
+res_update(ns_updrec *rrecp_in) {
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nupdate(&_res, rrecp_in, NULL));
+}
+
+int
+res_search(const char *name, /*!< domain name */
+ int class, int type, /*!< class and type of query */
+ u_char *answer, /*!< buffer to put answer */
+ int anslen) /*!< size of answer */
+{
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nsearch(&_res, name, class, type, answer, anslen));
+}
+
+int
+res_querydomain(const char *name,
+ const char *domain,
+ int class, int type, /*!< class and type of query */
+ u_char *answer, /*!< buffer to put answer */
+ int anslen) /*!< size of answer */
+{
+ if ((_res.options & RES_INIT) == 0U && res_init() == -1) {
+ RES_SET_H_ERRNO(&_res, NETDB_INTERNAL);
+ return (-1);
+ }
+
+ return (res_nquerydomain(&_res, name, domain,
+ class, type,
+ answer, anslen));
+}
+
+int
+res_opt(int n0, u_char *buf, int buflen, int anslen)
+{
+ return (res_nopt(&_res, n0, buf, buflen, anslen));
+}
+
+const char *
+hostalias(const char *name) {
+ static char abuf[MAXDNAME];
+
+ return (res_hostalias(&_res, name, abuf, sizeof abuf));
+}
+
+#ifdef ultrix
+int
+local_hostname_length(const char *hostname) {
+ int len_host, len_domain;
+
+ if (!*_res.defdname)
+ res_init();
+ len_host = strlen(hostname);
+ len_domain = strlen(_res.defdname);
+ if (len_host > len_domain &&
+ !strcasecmp(hostname + len_host - len_domain, _res.defdname) &&
+ hostname[len_host - len_domain - 1] == '.')
+ return (len_host - len_domain - 1);
+ return (0);
+}
+#endif /*ultrix*/
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <resolv.h>.
+ */
+#undef res_init
+__weak_reference(__res_init, res_init);
+#undef p_query
+__weak_reference(__p_query, p_query);
+#undef res_mkquery
+__weak_reference(__res_mkquery, res_mkquery);
+#undef res_query
+__weak_reference(__res_query, res_query);
+#undef res_send
+__weak_reference(__res_send, res_send);
+#undef res_close
+__weak_reference(__res_close, _res_close);
+#undef res_search
+__weak_reference(__res_search, res_search);
+#undef res_querydomain
+__weak_reference(__res_querydomain, res_querydomain);
+
+#endif
+
+/*! \file */
diff --git a/lib/libc/resolv/res_debug.c b/lib/libc/resolv/res_debug.c
new file mode 100644
index 0000000..c2707bb
--- /dev/null
+++ b/lib/libc/resolv/res_debug.c
@@ -0,0 +1,1229 @@
+/*
+ * Copyright (c) 1985
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Portions Copyright (c) 1995 by International Business Machines, Inc.
+ *
+ * International Business Machines, Inc. (hereinafter called IBM) grants
+ * permission under its copyrights to use, copy, modify, and distribute this
+ * Software with or without fee, provided that the above copyright notice and
+ * all paragraphs of this notice appear in all copies, and that the name of IBM
+ * not be used in connection with the marketing of any product incorporating
+ * the Software or modifications thereof, without specific, written prior
+ * permission.
+ *
+ * To the extent it has a right to do so, IBM grants an immunity from suit
+ * under its patents, if any, for the use, sale or manufacture of products to
+ * the extent that such products are used for performing Domain Name System
+ * dynamic updates in TCP/IP networks by means of the Software. No immunity is
+ * granted for any product per se or for any other function of any product.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", AND IBM DISCLAIMS ALL WARRANTIES,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE. IN NO EVENT SHALL IBM BE LIABLE FOR ANY SPECIAL,
+ * DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER ARISING
+ * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE, EVEN
+ * IF IBM IS APPRISED OF THE POSSIBILITY OF SUCH DAMAGES.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_debug.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_debug.c,v 1.10.18.6 2008/04/03 23:15:15 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <math.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <resolv_mt.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+
+#include "port_after.h"
+
+#ifdef SPRINTF_CHAR
+# define SPRINTF(x) strlen(sprintf/**/x)
+#else
+# define SPRINTF(x) sprintf x
+#endif
+
+extern const char *_res_opcodes[];
+extern const char *_res_sectioncodes[];
+
+/*%
+ * Print the current options.
+ */
+void
+fp_resstat(const res_state statp, FILE *file) {
+ u_long mask;
+
+ fprintf(file, ";; res options:");
+ for (mask = 1; mask != 0U; mask <<= 1)
+ if (statp->options & mask)
+ fprintf(file, " %s", p_option(mask));
+ putc('\n', file);
+}
+
+static void
+do_section(const res_state statp,
+ ns_msg *handle, ns_sect section,
+ int pflag, FILE *file)
+{
+ int n, sflag, rrnum;
+ static int buflen = 2048;
+ char *buf;
+ ns_opcode opcode;
+ ns_rr rr;
+
+ /*
+ * Print answer records.
+ */
+ sflag = (statp->pfcode & pflag);
+ if (statp->pfcode && !sflag)
+ return;
+
+ buf = malloc(buflen);
+ if (buf == NULL) {
+ fprintf(file, ";; memory allocation failure\n");
+ return;
+ }
+
+ opcode = (ns_opcode) ns_msg_getflag(*handle, ns_f_opcode);
+ rrnum = 0;
+ for (;;) {
+ if (ns_parserr(handle, section, rrnum, &rr)) {
+ if (errno != ENODEV)
+ fprintf(file, ";; ns_parserr: %s\n",
+ strerror(errno));
+ else if (rrnum > 0 && sflag != 0 &&
+ (statp->pfcode & RES_PRF_HEAD1))
+ putc('\n', file);
+ goto cleanup;
+ }
+ if (rrnum == 0 && sflag != 0 && (statp->pfcode & RES_PRF_HEAD1))
+ fprintf(file, ";; %s SECTION:\n",
+ p_section(section, opcode));
+ if (section == ns_s_qd)
+ fprintf(file, ";;\t%s, type = %s, class = %s\n",
+ ns_rr_name(rr),
+ p_type(ns_rr_type(rr)),
+ p_class(ns_rr_class(rr)));
+ else if (section == ns_s_ar && ns_rr_type(rr) == ns_t_opt) {
+ u_int16_t optcode, optlen, rdatalen = ns_rr_rdlen(rr);
+ u_int32_t ttl = ns_rr_ttl(rr);
+
+ fprintf(file,
+ "; EDNS: version: %u, udp=%u, flags=%04x\n",
+ (ttl>>16)&0xff, ns_rr_class(rr), ttl&0xffff);
+
+ while (rdatalen >= 4) {
+ const u_char *cp = ns_rr_rdata(rr);
+ int i;
+
+ GETSHORT(optcode, cp);
+ GETSHORT(optlen, cp);
+
+ if (optcode == NS_OPT_NSID) {
+ fputs("; NSID: ", file);
+ if (optlen == 0) {
+ fputs("; NSID\n", file);
+ } else {
+ fputs("; NSID: ", file);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%02x ",
+ cp[i]);
+ fputs(" (",file);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%c",
+ isprint(cp[i])?
+ cp[i] : '.');
+ fputs(")\n", file);
+ }
+ } else {
+ if (optlen == 0) {
+ fprintf(file, "; OPT=%u\n",
+ optcode);
+ } else {
+ fprintf(file, "; OPT=%u: ",
+ optcode);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%02x ",
+ cp[i]);
+ fputs(" (",file);
+ for (i = 0; i < optlen; i++)
+ fprintf(file, "%c",
+ isprint(cp[i]) ?
+ cp[i] : '.');
+ fputs(")\n", file);
+ }
+ }
+ rdatalen -= 4 + optlen;
+ }
+ } else {
+ n = ns_sprintrr(handle, &rr, NULL, NULL,
+ buf, buflen);
+ if (n < 0) {
+ if (errno == ENOSPC) {
+ free(buf);
+ buf = NULL;
+ if (buflen < 131072)
+ buf = malloc(buflen += 1024);
+ if (buf == NULL) {
+ fprintf(file,
+ ";; memory allocation failure\n");
+ return;
+ }
+ continue;
+ }
+ fprintf(file, ";; ns_sprintrr: %s\n",
+ strerror(errno));
+ goto cleanup;
+ }
+ fputs(buf, file);
+ fputc('\n', file);
+ }
+ rrnum++;
+ }
+ cleanup:
+ if (buf != NULL)
+ free(buf);
+}
+
+/*%
+ * Print the contents of a query.
+ * This is intended to be primarily a debugging routine.
+ */
+void
+res_pquery(const res_state statp, const u_char *msg, int len, FILE *file) {
+ ns_msg handle;
+ int qdcount, ancount, nscount, arcount;
+ u_int opcode, rcode, id;
+
+ if (ns_initparse(msg, len, &handle) < 0) {
+ fprintf(file, ";; ns_initparse: %s\n", strerror(errno));
+ return;
+ }
+ opcode = ns_msg_getflag(handle, ns_f_opcode);
+ rcode = ns_msg_getflag(handle, ns_f_rcode);
+ id = ns_msg_id(handle);
+ qdcount = ns_msg_count(handle, ns_s_qd);
+ ancount = ns_msg_count(handle, ns_s_an);
+ nscount = ns_msg_count(handle, ns_s_ns);
+ arcount = ns_msg_count(handle, ns_s_ar);
+
+ /*
+ * Print header fields.
+ */
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX) || rcode)
+ fprintf(file,
+ ";; ->>HEADER<<- opcode: %s, status: %s, id: %d\n",
+ _res_opcodes[opcode], p_rcode(rcode), id);
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEADX))
+ putc(';', file);
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD2)) {
+ fprintf(file, "; flags:");
+ if (ns_msg_getflag(handle, ns_f_qr))
+ fprintf(file, " qr");
+ if (ns_msg_getflag(handle, ns_f_aa))
+ fprintf(file, " aa");
+ if (ns_msg_getflag(handle, ns_f_tc))
+ fprintf(file, " tc");
+ if (ns_msg_getflag(handle, ns_f_rd))
+ fprintf(file, " rd");
+ if (ns_msg_getflag(handle, ns_f_ra))
+ fprintf(file, " ra");
+ if (ns_msg_getflag(handle, ns_f_z))
+ fprintf(file, " ??");
+ if (ns_msg_getflag(handle, ns_f_ad))
+ fprintf(file, " ad");
+ if (ns_msg_getflag(handle, ns_f_cd))
+ fprintf(file, " cd");
+ }
+ if ((!statp->pfcode) || (statp->pfcode & RES_PRF_HEAD1)) {
+ fprintf(file, "; %s: %d",
+ p_section(ns_s_qd, opcode), qdcount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_an, opcode), ancount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_ns, opcode), nscount);
+ fprintf(file, ", %s: %d",
+ p_section(ns_s_ar, opcode), arcount);
+ }
+ if ((!statp->pfcode) || (statp->pfcode &
+ (RES_PRF_HEADX | RES_PRF_HEAD2 | RES_PRF_HEAD1))) {
+ putc('\n',file);
+ }
+ /*
+ * Print the various sections.
+ */
+ do_section(statp, &handle, ns_s_qd, RES_PRF_QUES, file);
+ do_section(statp, &handle, ns_s_an, RES_PRF_ANS, file);
+ do_section(statp, &handle, ns_s_ns, RES_PRF_AUTH, file);
+ do_section(statp, &handle, ns_s_ar, RES_PRF_ADD, file);
+ if (qdcount == 0 && ancount == 0 &&
+ nscount == 0 && arcount == 0)
+ putc('\n', file);
+}
+
+const u_char *
+p_cdnname(const u_char *cp, const u_char *msg, int len, FILE *file) {
+ char name[MAXDNAME];
+ int n;
+
+ if ((n = dn_expand(msg, msg + len, cp, name, sizeof name)) < 0)
+ return (NULL);
+ if (name[0] == '\0')
+ putc('.', file);
+ else
+ fputs(name, file);
+ return (cp + n);
+}
+
+const u_char *
+p_cdname(const u_char *cp, const u_char *msg, FILE *file) {
+ return (p_cdnname(cp, msg, PACKETSZ, file));
+}
+
+/*%
+ * Return a fully-qualified domain name from a compressed name (with
+ length supplied). */
+
+const u_char *
+p_fqnname(cp, msg, msglen, name, namelen)
+ const u_char *cp, *msg;
+ int msglen;
+ char *name;
+ int namelen;
+{
+ int n, newlen;
+
+ if ((n = dn_expand(msg, cp + msglen, cp, name, namelen)) < 0)
+ return (NULL);
+ newlen = strlen(name);
+ if (newlen == 0 || name[newlen - 1] != '.') {
+ if (newlen + 1 >= namelen) /*%< Lack space for final dot */
+ return (NULL);
+ else
+ strcpy(name + newlen, ".");
+ }
+ return (cp + n);
+}
+
+/* XXX: the rest of these functions need to become length-limited, too. */
+
+const u_char *
+p_fqname(const u_char *cp, const u_char *msg, FILE *file) {
+ char name[MAXDNAME];
+ const u_char *n;
+
+ n = p_fqnname(cp, msg, MAXCDNAME, name, sizeof name);
+ if (n == NULL)
+ return (NULL);
+ fputs(name, file);
+ return (n);
+}
+
+/*%
+ * Names of RR classes and qclasses. Classes and qclasses are the same, except
+ * that C_ANY is a qclass but not a class. (You can ask for records of class
+ * C_ANY, but you can't have any records of that class in the database.)
+ */
+const struct res_sym __p_class_syms[] = {
+ {C_IN, "IN", (char *)0},
+ {C_CHAOS, "CH", (char *)0},
+ {C_CHAOS, "CHAOS", (char *)0},
+ {C_HS, "HS", (char *)0},
+ {C_HS, "HESIOD", (char *)0},
+ {C_ANY, "ANY", (char *)0},
+ {C_NONE, "NONE", (char *)0},
+ {C_IN, (char *)0, (char *)0}
+};
+
+/*%
+ * Names of message sections.
+ */
+static const struct res_sym __p_default_section_syms[] = {
+ {ns_s_qd, "QUERY", (char *)0},
+ {ns_s_an, "ANSWER", (char *)0},
+ {ns_s_ns, "AUTHORITY", (char *)0},
+ {ns_s_ar, "ADDITIONAL", (char *)0},
+ {0, (char *)0, (char *)0}
+};
+
+static const struct res_sym __p_update_section_syms[] = {
+ {S_ZONE, "ZONE", (char *)0},
+ {S_PREREQ, "PREREQUISITE", (char *)0},
+ {S_UPDATE, "UPDATE", (char *)0},
+ {S_ADDT, "ADDITIONAL", (char *)0},
+ {0, (char *)0, (char *)0}
+};
+
+const struct res_sym __p_key_syms[] = {
+ {NS_ALG_MD5RSA, "RSA", "RSA KEY with MD5 hash"},
+ {NS_ALG_DH, "DH", "Diffie Hellman"},
+ {NS_ALG_DSA, "DSA", "Digital Signature Algorithm"},
+ {NS_ALG_EXPIRE_ONLY, "EXPIREONLY", "No algorithm"},
+ {NS_ALG_PRIVATE_OID, "PRIVATE", "Algorithm obtained from OID"},
+ {0, NULL, NULL}
+};
+
+const struct res_sym __p_cert_syms[] = {
+ {cert_t_pkix, "PKIX", "PKIX (X.509v3) Certificate"},
+ {cert_t_spki, "SPKI", "SPKI certificate"},
+ {cert_t_pgp, "PGP", "PGP certificate"},
+ {cert_t_url, "URL", "URL Private"},
+ {cert_t_oid, "OID", "OID Private"},
+ {0, NULL, NULL}
+};
+
+/*%
+ * Names of RR types and qtypes. Types and qtypes are the same, except
+ * that T_ANY is a qtype but not a type. (You can ask for records of type
+ * T_ANY, but you can't have any records of that type in the database.)
+ */
+const struct res_sym __p_type_syms[] = {
+ {ns_t_a, "A", "address"},
+ {ns_t_ns, "NS", "name server"},
+ {ns_t_md, "MD", "mail destination (deprecated)"},
+ {ns_t_mf, "MF", "mail forwarder (deprecated)"},
+ {ns_t_cname, "CNAME", "canonical name"},
+ {ns_t_soa, "SOA", "start of authority"},
+ {ns_t_mb, "MB", "mailbox"},
+ {ns_t_mg, "MG", "mail group member"},
+ {ns_t_mr, "MR", "mail rename"},
+ {ns_t_null, "NULL", "null"},
+ {ns_t_wks, "WKS", "well-known service (deprecated)"},
+ {ns_t_ptr, "PTR", "domain name pointer"},
+ {ns_t_hinfo, "HINFO", "host information"},
+ {ns_t_minfo, "MINFO", "mailbox information"},
+ {ns_t_mx, "MX", "mail exchanger"},
+ {ns_t_txt, "TXT", "text"},
+ {ns_t_rp, "RP", "responsible person"},
+ {ns_t_afsdb, "AFSDB", "DCE or AFS server"},
+ {ns_t_x25, "X25", "X25 address"},
+ {ns_t_isdn, "ISDN", "ISDN address"},
+ {ns_t_rt, "RT", "router"},
+ {ns_t_nsap, "NSAP", "nsap address"},
+ {ns_t_nsap_ptr, "NSAP_PTR", "domain name pointer"},
+ {ns_t_sig, "SIG", "signature"},
+ {ns_t_key, "KEY", "key"},
+ {ns_t_px, "PX", "mapping information"},
+ {ns_t_gpos, "GPOS", "geographical position (withdrawn)"},
+ {ns_t_aaaa, "AAAA", "IPv6 address"},
+ {ns_t_loc, "LOC", "location"},
+ {ns_t_nxt, "NXT", "next valid name (unimplemented)"},
+ {ns_t_eid, "EID", "endpoint identifier (unimplemented)"},
+ {ns_t_nimloc, "NIMLOC", "NIMROD locator (unimplemented)"},
+ {ns_t_srv, "SRV", "server selection"},
+ {ns_t_atma, "ATMA", "ATM address (unimplemented)"},
+ {ns_t_tkey, "TKEY", "tkey"},
+ {ns_t_tsig, "TSIG", "transaction signature"},
+ {ns_t_ixfr, "IXFR", "incremental zone transfer"},
+ {ns_t_axfr, "AXFR", "zone transfer"},
+ {ns_t_zxfr, "ZXFR", "compressed zone transfer"},
+ {ns_t_mailb, "MAILB", "mailbox-related data (deprecated)"},
+ {ns_t_maila, "MAILA", "mail agent (deprecated)"},
+ {ns_t_naptr, "NAPTR", "URN Naming Authority"},
+ {ns_t_kx, "KX", "Key Exchange"},
+ {ns_t_cert, "CERT", "Certificate"},
+ {ns_t_a6, "A6", "IPv6 Address"},
+ {ns_t_dname, "DNAME", "dname"},
+ {ns_t_sink, "SINK", "Kitchen Sink (experimental)"},
+ {ns_t_opt, "OPT", "EDNS Options"},
+ {ns_t_any, "ANY", "\"any\""},
+ {0, NULL, NULL}
+};
+
+/*%
+ * Names of DNS rcodes.
+ */
+const struct res_sym __p_rcode_syms[] = {
+ {ns_r_noerror, "NOERROR", "no error"},
+ {ns_r_formerr, "FORMERR", "format error"},
+ {ns_r_servfail, "SERVFAIL", "server failed"},
+ {ns_r_nxdomain, "NXDOMAIN", "no such domain name"},
+ {ns_r_notimpl, "NOTIMP", "not implemented"},
+ {ns_r_refused, "REFUSED", "refused"},
+ {ns_r_yxdomain, "YXDOMAIN", "domain name exists"},
+ {ns_r_yxrrset, "YXRRSET", "rrset exists"},
+ {ns_r_nxrrset, "NXRRSET", "rrset doesn't exist"},
+ {ns_r_notauth, "NOTAUTH", "not authoritative"},
+ {ns_r_notzone, "NOTZONE", "Not in zone"},
+ {ns_r_max, "", ""},
+ {ns_r_badsig, "BADSIG", "bad signature"},
+ {ns_r_badkey, "BADKEY", "bad key"},
+ {ns_r_badtime, "BADTIME", "bad time"},
+ {0, NULL, NULL}
+};
+
+int
+sym_ston(const struct res_sym *syms, const char *name, int *success) {
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (strcasecmp (name, syms->name) == 0) {
+ if (success)
+ *success = 1;
+ return (syms->number);
+ }
+ }
+ if (success)
+ *success = 0;
+ return (syms->number); /*%< The default value. */
+}
+
+const char *
+sym_ntos(const struct res_sym *syms, int number, int *success) {
+ char *unname = sym_ntos_unname;
+
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (number == syms->number) {
+ if (success)
+ *success = 1;
+ return (syms->name);
+ }
+ }
+
+ sprintf(unname, "%d", number); /*%< XXX nonreentrant */
+ if (success)
+ *success = 0;
+ return (unname);
+}
+
+const char *
+sym_ntop(const struct res_sym *syms, int number, int *success) {
+ char *unname = sym_ntop_unname;
+
+ for ((void)NULL; syms->name != 0; syms++) {
+ if (number == syms->number) {
+ if (success)
+ *success = 1;
+ return (syms->humanname);
+ }
+ }
+ sprintf(unname, "%d", number); /*%< XXX nonreentrant */
+ if (success)
+ *success = 0;
+ return (unname);
+}
+
+/*%
+ * Return a string for the type.
+ */
+const char *
+p_type(int type) {
+ int success;
+ const char *result;
+ static char typebuf[20];
+
+ result = sym_ntos(__p_type_syms, type, &success);
+ if (success)
+ return (result);
+ if (type < 0 || type > 0xffff)
+ return ("BADTYPE");
+ sprintf(typebuf, "TYPE%d", type);
+ return (typebuf);
+}
+
+/*%
+ * Return a string for the type.
+ */
+const char *
+p_section(int section, int opcode) {
+ const struct res_sym *symbols;
+
+ switch (opcode) {
+ case ns_o_update:
+ symbols = __p_update_section_syms;
+ break;
+ default:
+ symbols = __p_default_section_syms;
+ break;
+ }
+ return (sym_ntos(symbols, section, (int *)0));
+}
+
+/*%
+ * Return a mnemonic for class.
+ */
+const char *
+p_class(int class) {
+ int success;
+ const char *result;
+ static char classbuf[20];
+
+ result = sym_ntos(__p_class_syms, class, &success);
+ if (success)
+ return (result);
+ if (class < 0 || class > 0xffff)
+ return ("BADCLASS");
+ sprintf(classbuf, "CLASS%d", class);
+ return (classbuf);
+}
+
+/*%
+ * Return a mnemonic for an option
+ */
+const char *
+p_option(u_long option) {
+ char *nbuf = p_option_nbuf;
+
+ switch (option) {
+ case RES_INIT: return "init";
+ case RES_DEBUG: return "debug";
+ case RES_AAONLY: return "aaonly(unimpl)";
+ case RES_USEVC: return "usevc";
+ case RES_PRIMARY: return "primry(unimpl)";
+ case RES_IGNTC: return "igntc";
+ case RES_RECURSE: return "recurs";
+ case RES_DEFNAMES: return "defnam";
+ case RES_STAYOPEN: return "styopn";
+ case RES_DNSRCH: return "dnsrch";
+ case RES_INSECURE1: return "insecure1";
+ case RES_INSECURE2: return "insecure2";
+ case RES_NOALIASES: return "noaliases";
+ case RES_USE_INET6: return "inet6";
+#ifdef RES_USE_EDNS0 /*%< KAME extension */
+ case RES_USE_EDNS0: return "edns0";
+ case RES_NSID: return "nsid";
+#endif
+#ifdef RES_USE_DNAME
+ case RES_USE_DNAME: return "dname";
+#endif
+#ifdef RES_USE_DNSSEC
+ case RES_USE_DNSSEC: return "dnssec";
+#endif
+#ifdef RES_NOTLDQUERY
+ case RES_NOTLDQUERY: return "no-tld-query";
+#endif
+#ifdef RES_NO_NIBBLE2
+ case RES_NO_NIBBLE2: return "no-nibble2";
+#endif
+ /* XXX nonreentrant */
+ default: sprintf(nbuf, "?0x%lx?", (u_long)option);
+ return (nbuf);
+ }
+}
+
+/*%
+ * Return a mnemonic for a time to live.
+ */
+const char *
+p_time(u_int32_t value) {
+ char *nbuf = p_time_nbuf;
+
+ if (ns_format_ttl(value, nbuf, sizeof nbuf) < 0)
+ sprintf(nbuf, "%u", value);
+ return (nbuf);
+}
+
+/*%
+ * Return a string for the rcode.
+ */
+const char *
+p_rcode(int rcode) {
+ return (sym_ntos(__p_rcode_syms, rcode, (int *)0));
+}
+
+/*%
+ * Return a string for a res_sockaddr_union.
+ */
+const char *
+p_sockun(union res_sockaddr_union u, char *buf, size_t size) {
+ char ret[sizeof "ffff:ffff:ffff:ffff:ffff:ffff:123.123.123.123"];
+
+ switch (u.sin.sin_family) {
+ case AF_INET:
+ inet_ntop(AF_INET, &u.sin.sin_addr, ret, sizeof ret);
+ break;
+#ifdef HAS_INET6_STRUCTS
+ case AF_INET6:
+ inet_ntop(AF_INET6, &u.sin6.sin6_addr, ret, sizeof ret);
+ break;
+#endif
+ default:
+ sprintf(ret, "[af%d]", u.sin.sin_family);
+ break;
+ }
+ if (size > 0U) {
+ strncpy(buf, ret, size - 1);
+ buf[size - 1] = '0';
+ }
+ return (buf);
+}
+
+/*%
+ * routines to convert between on-the-wire RR format and zone file format.
+ * Does not contain conversion to/from decimal degrees; divide or multiply
+ * by 60*60*1000 for that.
+ */
+
+static unsigned int poweroften[10] = {1, 10, 100, 1000, 10000, 100000,
+ 1000000,10000000,100000000,1000000000};
+
+/*% takes an XeY precision/size value, returns a string representation. */
+static const char *
+precsize_ntoa(prec)
+ u_int8_t prec;
+{
+ char *retbuf = precsize_ntoa_retbuf;
+ unsigned long val;
+ int mantissa, exponent;
+
+ mantissa = (int)((prec >> 4) & 0x0f) % 10;
+ exponent = (int)((prec >> 0) & 0x0f) % 10;
+
+ val = mantissa * poweroften[exponent];
+
+ (void) sprintf(retbuf, "%lu.%.2lu", val/100, val%100);
+ return (retbuf);
+}
+
+/*% converts ascii size/precision X * 10**Y(cm) to 0xXY. moves pointer. */
+static u_int8_t
+precsize_aton(const char **strptr) {
+ unsigned int mval = 0, cmval = 0;
+ u_int8_t retval = 0;
+ const char *cp;
+ int exponent;
+ int mantissa;
+
+ cp = *strptr;
+
+ while (isdigit((unsigned char)*cp))
+ mval = mval * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /*%< centimeters */
+ cp++;
+ if (isdigit((unsigned char)*cp)) {
+ cmval = (*cp++ - '0') * 10;
+ if (isdigit((unsigned char)*cp)) {
+ cmval += (*cp++ - '0');
+ }
+ }
+ }
+ cmval = (mval * 100) + cmval;
+
+ for (exponent = 0; exponent < 9; exponent++)
+ if (cmval < poweroften[exponent+1])
+ break;
+
+ mantissa = cmval / poweroften[exponent];
+ if (mantissa > 9)
+ mantissa = 9;
+
+ retval = (mantissa << 4) | exponent;
+
+ *strptr = cp;
+
+ return (retval);
+}
+
+/*% converts ascii lat/lon to unsigned encoded 32-bit number. moves pointer. */
+static u_int32_t
+latlon2ul(const char **latlonstrptr, int *which) {
+ const char *cp;
+ u_int32_t retval;
+ int deg = 0, min = 0, secs = 0, secsfrac = 0;
+
+ cp = *latlonstrptr;
+
+ while (isdigit((unsigned char)*cp))
+ deg = deg * 10 + (*cp++ - '0');
+
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ if (!(isdigit((unsigned char)*cp)))
+ goto fndhemi;
+
+ while (isdigit((unsigned char)*cp))
+ min = min * 10 + (*cp++ - '0');
+
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ if (!(isdigit((unsigned char)*cp)))
+ goto fndhemi;
+
+ while (isdigit((unsigned char)*cp))
+ secs = secs * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /*%< decimal seconds */
+ cp++;
+ if (isdigit((unsigned char)*cp)) {
+ secsfrac = (*cp++ - '0') * 100;
+ if (isdigit((unsigned char)*cp)) {
+ secsfrac += (*cp++ - '0') * 10;
+ if (isdigit((unsigned char)*cp)) {
+ secsfrac += (*cp++ - '0');
+ }
+ }
+ }
+ }
+
+ while (!isspace((unsigned char)*cp)) /*%< if any trailing garbage */
+ cp++;
+
+ while (isspace((unsigned char)*cp))
+ cp++;
+
+ fndhemi:
+ switch (*cp) {
+ case 'N': case 'n':
+ case 'E': case 'e':
+ retval = ((unsigned)1<<31)
+ + (((((deg * 60) + min) * 60) + secs) * 1000)
+ + secsfrac;
+ break;
+ case 'S': case 's':
+ case 'W': case 'w':
+ retval = ((unsigned)1<<31)
+ - (((((deg * 60) + min) * 60) + secs) * 1000)
+ - secsfrac;
+ break;
+ default:
+ retval = 0; /*%< invalid value -- indicates error */
+ break;
+ }
+
+ switch (*cp) {
+ case 'N': case 'n':
+ case 'S': case 's':
+ *which = 1; /*%< latitude */
+ break;
+ case 'E': case 'e':
+ case 'W': case 'w':
+ *which = 2; /*%< longitude */
+ break;
+ default:
+ *which = 0; /*%< error */
+ break;
+ }
+
+ cp++; /*%< skip the hemisphere */
+ while (!isspace((unsigned char)*cp)) /*%< if any trailing garbage */
+ cp++;
+
+ while (isspace((unsigned char)*cp)) /*%< move to next field */
+ cp++;
+
+ *latlonstrptr = cp;
+
+ return (retval);
+}
+
+/*%
+ * converts a zone file representation in a string to an RDATA on-the-wire
+ * representation. */
+int
+loc_aton(ascii, binary)
+ const char *ascii;
+ u_char *binary;
+{
+ const char *cp, *maxcp;
+ u_char *bcp;
+
+ u_int32_t latit = 0, longit = 0, alt = 0;
+ u_int32_t lltemp1 = 0, lltemp2 = 0;
+ int altmeters = 0, altfrac = 0, altsign = 1;
+ u_int8_t hp = 0x16; /*%< default = 1e6 cm = 10000.00m = 10km */
+ u_int8_t vp = 0x13; /*%< default = 1e3 cm = 10.00m */
+ u_int8_t siz = 0x12; /*%< default = 1e2 cm = 1.00m */
+ int which1 = 0, which2 = 0;
+
+ cp = ascii;
+ maxcp = cp + strlen(ascii);
+
+ lltemp1 = latlon2ul(&cp, &which1);
+
+ lltemp2 = latlon2ul(&cp, &which2);
+
+ switch (which1 + which2) {
+ case 3: /*%< 1 + 2, the only valid combination */
+ if ((which1 == 1) && (which2 == 2)) { /*%< normal case */
+ latit = lltemp1;
+ longit = lltemp2;
+ } else if ((which1 == 2) && (which2 == 1)) { /*%< reversed */
+ longit = lltemp1;
+ latit = lltemp2;
+ } else { /*%< some kind of brokenness */
+ return (0);
+ }
+ break;
+ default: /*%< we didn't get one of each */
+ return (0);
+ }
+
+ /* altitude */
+ if (*cp == '-') {
+ altsign = -1;
+ cp++;
+ }
+
+ if (*cp == '+')
+ cp++;
+
+ while (isdigit((unsigned char)*cp))
+ altmeters = altmeters * 10 + (*cp++ - '0');
+
+ if (*cp == '.') { /*%< decimal meters */
+ cp++;
+ if (isdigit((unsigned char)*cp)) {
+ altfrac = (*cp++ - '0') * 10;
+ if (isdigit((unsigned char)*cp)) {
+ altfrac += (*cp++ - '0');
+ }
+ }
+ }
+
+ alt = (10000000 + (altsign * (altmeters * 100 + altfrac)));
+
+ while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */
+ cp++;
+
+ while (isspace((unsigned char)*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ siz = precsize_aton(&cp);
+
+ while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */
+ cp++;
+
+ while (isspace((unsigned char)*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ hp = precsize_aton(&cp);
+
+ while (!isspace((unsigned char)*cp) && (cp < maxcp)) /*%< if trailing garbage or m */
+ cp++;
+
+ while (isspace((unsigned char)*cp) && (cp < maxcp))
+ cp++;
+
+ if (cp >= maxcp)
+ goto defaults;
+
+ vp = precsize_aton(&cp);
+
+ defaults:
+
+ bcp = binary;
+ *bcp++ = (u_int8_t) 0; /*%< version byte */
+ *bcp++ = siz;
+ *bcp++ = hp;
+ *bcp++ = vp;
+ PUTLONG(latit,bcp);
+ PUTLONG(longit,bcp);
+ PUTLONG(alt,bcp);
+
+ return (16); /*%< size of RR in octets */
+}
+
+/*% takes an on-the-wire LOC RR and formats it in a human readable format. */
+const char *
+loc_ntoa(binary, ascii)
+ const u_char *binary;
+ char *ascii;
+{
+ static const char *error = "?";
+ static char tmpbuf[sizeof
+"1000 60 60.000 N 1000 60 60.000 W -12345678.00m 90000000.00m 90000000.00m 90000000.00m"];
+ const u_char *cp = binary;
+
+ int latdeg, latmin, latsec, latsecfrac;
+ int longdeg, longmin, longsec, longsecfrac;
+ char northsouth, eastwest;
+ const char *altsign;
+ int altmeters, altfrac;
+
+ const u_int32_t referencealt = 100000 * 100;
+
+ int32_t latval, longval, altval;
+ u_int32_t templ;
+ u_int8_t sizeval, hpval, vpval, versionval;
+
+ char *sizestr, *hpstr, *vpstr;
+
+ versionval = *cp++;
+
+ if (ascii == NULL)
+ ascii = tmpbuf;
+
+ if (versionval) {
+ (void) sprintf(ascii, "; error: unknown LOC RR version");
+ return (ascii);
+ }
+
+ sizeval = *cp++;
+
+ hpval = *cp++;
+ vpval = *cp++;
+
+ GETLONG(templ, cp);
+ latval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ, cp);
+ longval = (templ - ((unsigned)1<<31));
+
+ GETLONG(templ, cp);
+ if (templ < referencealt) { /*%< below WGS 84 spheroid */
+ altval = referencealt - templ;
+ altsign = "-";
+ } else {
+ altval = templ - referencealt;
+ altsign = "";
+ }
+
+ if (latval < 0) {
+ northsouth = 'S';
+ latval = -latval;
+ } else
+ northsouth = 'N';
+
+ latsecfrac = latval % 1000;
+ latval = latval / 1000;
+ latsec = latval % 60;
+ latval = latval / 60;
+ latmin = latval % 60;
+ latval = latval / 60;
+ latdeg = latval;
+
+ if (longval < 0) {
+ eastwest = 'W';
+ longval = -longval;
+ } else
+ eastwest = 'E';
+
+ longsecfrac = longval % 1000;
+ longval = longval / 1000;
+ longsec = longval % 60;
+ longval = longval / 60;
+ longmin = longval % 60;
+ longval = longval / 60;
+ longdeg = longval;
+
+ altfrac = altval % 100;
+ altmeters = (altval / 100);
+
+ sizestr = strdup(precsize_ntoa(sizeval));
+ hpstr = strdup(precsize_ntoa(hpval));
+ vpstr = strdup(precsize_ntoa(vpval));
+
+ sprintf(ascii,
+ "%d %.2d %.2d.%.3d %c %d %.2d %.2d.%.3d %c %s%d.%.2dm %sm %sm %sm",
+ latdeg, latmin, latsec, latsecfrac, northsouth,
+ longdeg, longmin, longsec, longsecfrac, eastwest,
+ altsign, altmeters, altfrac,
+ (sizestr != NULL) ? sizestr : error,
+ (hpstr != NULL) ? hpstr : error,
+ (vpstr != NULL) ? vpstr : error);
+
+ if (sizestr != NULL)
+ free(sizestr);
+ if (hpstr != NULL)
+ free(hpstr);
+ if (vpstr != NULL)
+ free(vpstr);
+
+ return (ascii);
+}
+
+
+/*% Return the number of DNS hierarchy levels in the name. */
+int
+dn_count_labels(const char *name) {
+ int i, len, count;
+
+ len = strlen(name);
+ for (i = 0, count = 0; i < len; i++) {
+ /* XXX need to check for \. or use named's nlabels(). */
+ if (name[i] == '.')
+ count++;
+ }
+
+ /* don't count initial wildcard */
+ if (name[0] == '*')
+ if (count)
+ count--;
+
+ /* don't count the null label for root. */
+ /* if terminating '.' not found, must adjust */
+ /* count to include last label */
+ if (len > 0 && name[len-1] != '.')
+ count++;
+ return (count);
+}
+
+/*%
+ * Make dates expressed in seconds-since-Jan-1-1970 easy to read.
+ * SIG records are required to be printed like this, by the Secure DNS RFC.
+ */
+char *
+p_secstodate (u_long secs) {
+ char *output = p_secstodate_output;
+ time_t clock = secs;
+ struct tm *time;
+#ifdef HAVE_TIME_R
+ struct tm res;
+
+ time = gmtime_r(&clock, &res);
+#else
+ time = gmtime(&clock);
+#endif
+ time->tm_year += 1900;
+ time->tm_mon += 1;
+ sprintf(output, "%04d%02d%02d%02d%02d%02d",
+ time->tm_year, time->tm_mon, time->tm_mday,
+ time->tm_hour, time->tm_min, time->tm_sec);
+ return (output);
+}
+
+u_int16_t
+res_nametoclass(const char *buf, int *successp) {
+ unsigned long result;
+ char *endptr;
+ int success;
+
+ result = sym_ston(__p_class_syms, buf, &success);
+ if (success)
+ goto done;
+
+ if (strncasecmp(buf, "CLASS", 5) != 0 ||
+ !isdigit((unsigned char)buf[5]))
+ goto done;
+ errno = 0;
+ result = strtoul(buf + 5, &endptr, 10);
+ if (errno == 0 && *endptr == '\0' && result <= 0xffffU)
+ success = 1;
+ done:
+ if (successp)
+ *successp = success;
+ return (result);
+}
+
+u_int16_t
+res_nametotype(const char *buf, int *successp) {
+ unsigned long result;
+ char *endptr;
+ int success;
+
+ result = sym_ston(__p_type_syms, buf, &success);
+ if (success)
+ goto done;
+
+ if (strncasecmp(buf, "type", 4) != 0 ||
+ !isdigit((unsigned char)buf[4]))
+ goto done;
+ errno = 0;
+ result = strtoul(buf + 4, &endptr, 10);
+ if (errno == 0 && *endptr == '\0' && result <= 0xffffU)
+ success = 1;
+ done:
+ if (successp)
+ *successp = success;
+ return (result);
+}
+
+/*
+ * Weak aliases for applications that use certain private entry points,
+ * and fail to include <resolv.h>.
+ */
+#undef fp_resstat
+__weak_reference(__fp_resstat, fp_resstat);
+#undef p_fqnname
+__weak_reference(__p_fqnname, p_fqnname);
+#undef sym_ston
+__weak_reference(__sym_ston, sym_ston);
+#undef sym_ntos
+__weak_reference(__sym_ntos, sym_ntos);
+#undef sym_ntop
+__weak_reference(__sym_ntop, sym_ntop);
+#undef dn_count_labels
+__weak_reference(__dn_count_labels, dn_count_labels);
+#undef p_secstodate
+__weak_reference(__p_secstodate, p_secstodate);
+
+/*! \file */
diff --git a/lib/libc/resolv/res_debug.h b/lib/libc/resolv/res_debug.h
new file mode 100644
index 0000000..c28171d
--- /dev/null
+++ b/lib/libc/resolv/res_debug.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#ifndef _RES_DEBUG_H_
+#define _RES_DEBUG_H_
+
+#ifndef DEBUG
+# define Dprint(cond, args) /*empty*/
+# define DprintQ(cond, args, query, size) /*empty*/
+# define Aerror(statp, file, string, error, address) /*empty*/
+# define Perror(statp, file, string, error) /*empty*/
+#else
+# define Dprint(cond, args) if (cond) {fprintf args;} else {}
+# define DprintQ(cond, args, query, size) if (cond) {\
+ fprintf args;\
+ res_pquery(statp, query, size, stdout);\
+ } else {}
+#endif
+
+#endif /* _RES_DEBUG_H_ */
+/*! \file */
diff --git a/lib/libc/resolv/res_findzonecut.c b/lib/libc/resolv/res_findzonecut.c
new file mode 100644
index 0000000..23c1af4
--- /dev/null
+++ b/lib/libc/resolv/res_findzonecut.c
@@ -0,0 +1,727 @@
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: res_findzonecut.c,v 1.7.18.3 2005/10/11 00:25:11 marka Exp $";
+#endif /* not lint */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/* Import. */
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/list.h>
+
+#include "port_after.h"
+
+#include <resolv.h>
+
+/* Data structures. */
+
+typedef struct rr_a {
+ LINK(struct rr_a) link;
+ union res_sockaddr_union addr;
+} rr_a;
+typedef LIST(rr_a) rrset_a;
+
+typedef struct rr_ns {
+ LINK(struct rr_ns) link;
+ const char * name;
+ unsigned int flags;
+ rrset_a addrs;
+} rr_ns;
+typedef LIST(rr_ns) rrset_ns;
+
+#define RR_NS_HAVE_V4 0x01
+#define RR_NS_HAVE_V6 0x02
+
+/* Forward. */
+
+static int satisfy(res_state, const char *, rrset_ns *,
+ union res_sockaddr_union *, int);
+static int add_addrs(res_state, rr_ns *,
+ union res_sockaddr_union *, int);
+static int get_soa(res_state, const char *, ns_class, int,
+ char *, size_t, char *, size_t,
+ rrset_ns *);
+static int get_ns(res_state, const char *, ns_class, int, rrset_ns *);
+static int get_glue(res_state, ns_class, int, rrset_ns *);
+static int save_ns(res_state, ns_msg *, ns_sect,
+ const char *, ns_class, int, rrset_ns *);
+static int save_a(res_state, ns_msg *, ns_sect,
+ const char *, ns_class, int, rr_ns *);
+static void free_nsrrset(rrset_ns *);
+static void free_nsrr(rrset_ns *, rr_ns *);
+static rr_ns * find_ns(rrset_ns *, const char *);
+static int do_query(res_state, const char *, ns_class, ns_type,
+ u_char *, ns_msg *);
+static void res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2);
+
+/* Macros. */
+
+#define DPRINTF(x) do {\
+ int save_errno = errno; \
+ if ((statp->options & RES_DEBUG) != 0U) res_dprintf x; \
+ errno = save_errno; \
+ } while (0)
+
+/* Public. */
+
+/*%
+ * find enclosing zone for a <dname,class>, and some server addresses
+ *
+ * parameters:
+ *\li res - resolver context to work within (is modified)
+ *\li dname - domain name whose enclosing zone is desired
+ *\li class - class of dname (and its enclosing zone)
+ *\li zname - found zone name
+ *\li zsize - allocated size of zname
+ *\li addrs - found server addresses
+ *\li naddrs - max number of addrs
+ *
+ * return values:
+ *\li < 0 - an error occurred (check errno)
+ *\li = 0 - zname is now valid, but addrs[] wasn't changed
+ *\li > 0 - zname is now valid, and return value is number of addrs[] found
+ *
+ * notes:
+ *\li this function calls res_nsend() which means it depends on correctly
+ * functioning recursive nameservers (usually defined in /etc/resolv.conf
+ * or its local equivilent).
+ *
+ *\li we start by asking for an SOA<dname,class>. if we get one as an
+ * answer, that just means <dname,class> is a zone top, which is fine.
+ * more than likely we'll be told to go pound sand, in the form of a
+ * negative answer.
+ *
+ *\li note that we are not prepared to deal with referrals since that would
+ * only come from authority servers and our correctly functioning local
+ * recursive server would have followed the referral and got us something
+ * more definite.
+ *
+ *\li if the authority section contains an SOA, this SOA should also be the
+ * closest enclosing zone, since any intermediary zone cuts would've been
+ * returned as referrals and dealt with by our correctly functioning local
+ * recursive name server. but an SOA in the authority section should NOT
+ * match our dname (since that would have been returned in the answer
+ * section). an authority section SOA has to be "above" our dname.
+ *
+ *\li however, since authority section SOA's were once optional, it's
+ * possible that we'll have to go hunting for the enclosing SOA by
+ * ripping labels off the front of our dname -- this is known as "doing
+ * it the hard way."
+ *
+ *\li ultimately we want some server addresses, which are ideally the ones
+ * pertaining to the SOA.MNAME, but only if there is a matching NS RR.
+ * so the second phase (after we find an SOA) is to go looking for the
+ * NS RRset for that SOA's zone.
+ *
+ *\li no answer section processed by this code is allowed to contain CNAME
+ * or DNAME RR's. for the SOA query this means we strip a label and
+ * keep going. for the NS and A queries this means we just give up.
+ */
+
+#ifndef _LIBC
+int
+res_findzonecut(res_state statp, const char *dname, ns_class class, int opts,
+ char *zname, size_t zsize, struct in_addr *addrs, int naddrs)
+{
+ int result, i;
+ union res_sockaddr_union *u;
+
+
+ opts |= RES_IPV4ONLY;
+ opts &= ~RES_IPV6ONLY;
+
+ u = calloc(naddrs, sizeof(*u));
+ if (u == NULL)
+ return(-1);
+
+ result = res_findzonecut2(statp, dname, class, opts, zname, zsize,
+ u, naddrs);
+
+ for (i = 0; i < result; i++) {
+ addrs[i] = u[i].sin.sin_addr;
+ }
+ free(u);
+ return (result);
+}
+#endif
+
+int
+res_findzonecut2(res_state statp, const char *dname, ns_class class, int opts,
+ char *zname, size_t zsize, union res_sockaddr_union *addrs,
+ int naddrs)
+{
+ char mname[NS_MAXDNAME];
+ u_long save_pfcode;
+ rrset_ns nsrrs;
+ int n;
+
+ DPRINTF(("START dname='%s' class=%s, zsize=%ld, naddrs=%d",
+ dname, p_class(class), (long)zsize, naddrs));
+ save_pfcode = statp->pfcode;
+ statp->pfcode |= RES_PRF_HEAD2 | RES_PRF_HEAD1 | RES_PRF_HEADX |
+ RES_PRF_QUES | RES_PRF_ANS |
+ RES_PRF_AUTH | RES_PRF_ADD;
+ INIT_LIST(nsrrs);
+
+ DPRINTF(("get the soa, and see if it has enough glue"));
+ if ((n = get_soa(statp, dname, class, opts, zname, zsize,
+ mname, sizeof mname, &nsrrs)) < 0 ||
+ ((opts & RES_EXHAUSTIVE) == 0 &&
+ (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0))
+ goto done;
+
+ DPRINTF(("get the ns rrset and see if it has enough glue"));
+ if ((n = get_ns(statp, zname, class, opts, &nsrrs)) < 0 ||
+ ((opts & RES_EXHAUSTIVE) == 0 &&
+ (n = satisfy(statp, mname, &nsrrs, addrs, naddrs)) > 0))
+ goto done;
+
+ DPRINTF(("get the missing glue and see if it's finally enough"));
+ if ((n = get_glue(statp, class, opts, &nsrrs)) >= 0)
+ n = satisfy(statp, mname, &nsrrs, addrs, naddrs);
+
+ done:
+ DPRINTF(("FINISH n=%d (%s)", n, (n < 0) ? strerror(errno) : "OK"));
+ free_nsrrset(&nsrrs);
+ statp->pfcode = save_pfcode;
+ return (n);
+}
+
+/* Private. */
+
+static int
+satisfy(res_state statp, const char *mname, rrset_ns *nsrrsp,
+ union res_sockaddr_union *addrs, int naddrs)
+{
+ rr_ns *nsrr;
+ int n, x;
+
+ n = 0;
+ nsrr = find_ns(nsrrsp, mname);
+ if (nsrr != NULL) {
+ x = add_addrs(statp, nsrr, addrs, naddrs);
+ addrs += x;
+ naddrs -= x;
+ n += x;
+ }
+ for (nsrr = HEAD(*nsrrsp);
+ nsrr != NULL && naddrs > 0;
+ nsrr = NEXT(nsrr, link))
+ if (ns_samename(nsrr->name, mname) != 1) {
+ x = add_addrs(statp, nsrr, addrs, naddrs);
+ addrs += x;
+ naddrs -= x;
+ n += x;
+ }
+ DPRINTF(("satisfy(%s): %d", mname, n));
+ return (n);
+}
+
+static int
+add_addrs(res_state statp, rr_ns *nsrr,
+ union res_sockaddr_union *addrs, int naddrs)
+{
+ rr_a *arr;
+ int n = 0;
+
+ for (arr = HEAD(nsrr->addrs); arr != NULL; arr = NEXT(arr, link)) {
+ if (naddrs <= 0)
+ return (0);
+ *addrs++ = arr->addr;
+ naddrs--;
+ n++;
+ }
+ DPRINTF(("add_addrs: %d", n));
+ return (n);
+}
+
+static int
+get_soa(res_state statp, const char *dname, ns_class class, int opts,
+ char *zname, size_t zsize, char *mname, size_t msize,
+ rrset_ns *nsrrsp)
+{
+ char tname[NS_MAXDNAME];
+ u_char *resp = NULL;
+ int n, i, ancount, nscount;
+ ns_sect sect;
+ ns_msg msg;
+ u_int rcode;
+
+ /*
+ * Find closest enclosing SOA, even if it's for the root zone.
+ */
+
+ /* First canonicalize dname (exactly one unescaped trailing "."). */
+ if (ns_makecanon(dname, tname, sizeof tname) < 0)
+ goto cleanup;
+ dname = tname;
+
+ resp = malloc(NS_MAXMSG);
+ if (resp == NULL)
+ goto cleanup;
+
+ /* Now grovel the subdomains, hunting for an SOA answer or auth. */
+ for (;;) {
+ /* Leading or inter-label '.' are skipped here. */
+ while (*dname == '.')
+ dname++;
+
+ /* Is there an SOA? */
+ n = do_query(statp, dname, class, ns_t_soa, resp, &msg);
+ if (n < 0) {
+ DPRINTF(("get_soa: do_query('%s', %s) failed (%d)",
+ dname, p_class(class), n));
+ goto cleanup;
+ }
+ if (n > 0) {
+ DPRINTF(("get_soa: CNAME or DNAME found"));
+ sect = ns_s_max, n = 0;
+ } else {
+ rcode = ns_msg_getflag(msg, ns_f_rcode);
+ ancount = ns_msg_count(msg, ns_s_an);
+ nscount = ns_msg_count(msg, ns_s_ns);
+ if (ancount > 0 && rcode == ns_r_noerror)
+ sect = ns_s_an, n = ancount;
+ else if (nscount > 0)
+ sect = ns_s_ns, n = nscount;
+ else
+ sect = ns_s_max, n = 0;
+ }
+ for (i = 0; i < n; i++) {
+ const char *t;
+ const u_char *rdata;
+ ns_rr rr;
+
+ if (ns_parserr(&msg, sect, i, &rr) < 0) {
+ DPRINTF(("get_soa: ns_parserr(%s, %d) failed",
+ p_section(sect, ns_o_query), i));
+ goto cleanup;
+ }
+ if (ns_rr_type(rr) == ns_t_cname ||
+ ns_rr_type(rr) == ns_t_dname)
+ break;
+ if (ns_rr_type(rr) != ns_t_soa ||
+ ns_rr_class(rr) != class)
+ continue;
+ t = ns_rr_name(rr);
+ switch (sect) {
+ case ns_s_an:
+ if (ns_samedomain(dname, t) == 0) {
+ DPRINTF(
+ ("get_soa: ns_samedomain('%s', '%s') == 0",
+ dname, t)
+ );
+ errno = EPROTOTYPE;
+ goto cleanup;
+ }
+ break;
+ case ns_s_ns:
+ if (ns_samename(dname, t) == 1 ||
+ ns_samedomain(dname, t) == 0) {
+ DPRINTF(
+ ("get_soa: ns_samename() || !ns_samedomain('%s', '%s')",
+ dname, t)
+ );
+ errno = EPROTOTYPE;
+ goto cleanup;
+ }
+ break;
+ default:
+ abort();
+ }
+ if (strlen(t) + 1 > zsize) {
+ DPRINTF(("get_soa: zname(%lu) too small (%lu)",
+ (unsigned long)zsize,
+ (unsigned long)strlen(t) + 1));
+ errno = EMSGSIZE;
+ goto cleanup;
+ }
+ strcpy(zname, t);
+ rdata = ns_rr_rdata(rr);
+ if (ns_name_uncompress(resp, ns_msg_end(msg), rdata,
+ mname, msize) < 0) {
+ DPRINTF(("get_soa: ns_name_uncompress failed")
+ );
+ goto cleanup;
+ }
+ if (save_ns(statp, &msg, ns_s_ns,
+ zname, class, opts, nsrrsp) < 0) {
+ DPRINTF(("get_soa: save_ns failed"));
+ goto cleanup;
+ }
+ free(resp);
+ return (0);
+ }
+
+ /* If we're out of labels, then not even "." has an SOA! */
+ if (*dname == '\0')
+ break;
+
+ /* Find label-terminating "."; top of loop will skip it. */
+ while (*dname != '.') {
+ if (*dname == '\\')
+ if (*++dname == '\0') {
+ errno = EMSGSIZE;
+ goto cleanup;
+ }
+ dname++;
+ }
+ }
+ DPRINTF(("get_soa: out of labels"));
+ errno = EDESTADDRREQ;
+ cleanup:
+ if (resp != NULL)
+ free(resp);
+ return (-1);
+}
+
+static int
+get_ns(res_state statp, const char *zname, ns_class class, int opts,
+ rrset_ns *nsrrsp)
+{
+ u_char *resp;
+ ns_msg msg;
+ int n;
+
+ resp = malloc(NS_MAXMSG);
+ if (resp == NULL)
+ return (-1);
+
+ /* Go and get the NS RRs for this zone. */
+ n = do_query(statp, zname, class, ns_t_ns, resp, &msg);
+ if (n != 0) {
+ DPRINTF(("get_ns: do_query('%s', %s) failed (%d)",
+ zname, p_class(class), n));
+ free(resp);
+ return (-1);
+ }
+
+ /* Remember the NS RRs and associated A RRs that came back. */
+ if (save_ns(statp, &msg, ns_s_an, zname, class, opts, nsrrsp) < 0) {
+ DPRINTF(("get_ns save_ns('%s', %s) failed",
+ zname, p_class(class)));
+ free(resp);
+ return (-1);
+ }
+
+ free(resp);
+ return (0);
+}
+
+static int
+get_glue(res_state statp, ns_class class, int opts, rrset_ns *nsrrsp) {
+ rr_ns *nsrr, *nsrr_n;
+ u_char *resp;
+
+ resp = malloc(NS_MAXMSG);
+ if (resp == NULL)
+ return(-1);
+
+ /* Go and get the A RRs for each empty NS RR on our list. */
+ for (nsrr = HEAD(*nsrrsp); nsrr != NULL; nsrr = nsrr_n) {
+ ns_msg msg;
+ int n;
+
+ nsrr_n = NEXT(nsrr, link);
+
+ if ((nsrr->flags & RR_NS_HAVE_V4) == 0) {
+ n = do_query(statp, nsrr->name, class, ns_t_a,
+ resp, &msg);
+ if (n < 0) {
+ DPRINTF(
+ ("get_glue: do_query('%s', %s') failed",
+ nsrr->name, p_class(class)));
+ goto cleanup;
+ }
+ if (n > 0) {
+ DPRINTF((
+ "get_glue: do_query('%s', %s') CNAME or DNAME found",
+ nsrr->name, p_class(class)));
+ }
+ if (save_a(statp, &msg, ns_s_an, nsrr->name, class,
+ opts, nsrr) < 0) {
+ DPRINTF(("get_glue: save_r('%s', %s) failed",
+ nsrr->name, p_class(class)));
+ goto cleanup;
+ }
+ }
+
+ if ((nsrr->flags & RR_NS_HAVE_V6) == 0) {
+ n = do_query(statp, nsrr->name, class, ns_t_aaaa,
+ resp, &msg);
+ if (n < 0) {
+ DPRINTF(
+ ("get_glue: do_query('%s', %s') failed",
+ nsrr->name, p_class(class)));
+ goto cleanup;
+ }
+ if (n > 0) {
+ DPRINTF((
+ "get_glue: do_query('%s', %s') CNAME or DNAME found",
+ nsrr->name, p_class(class)));
+ }
+ if (save_a(statp, &msg, ns_s_an, nsrr->name, class,
+ opts, nsrr) < 0) {
+ DPRINTF(("get_glue: save_r('%s', %s) failed",
+ nsrr->name, p_class(class)));
+ goto cleanup;
+ }
+ }
+
+ /* If it's still empty, it's just chaff. */
+ if (EMPTY(nsrr->addrs)) {
+ DPRINTF(("get_glue: removing empty '%s' NS",
+ nsrr->name));
+ free_nsrr(nsrrsp, nsrr);
+ }
+ }
+ free(resp);
+ return (0);
+
+ cleanup:
+ free(resp);
+ return (-1);
+}
+
+static int
+save_ns(res_state statp, ns_msg *msg, ns_sect sect,
+ const char *owner, ns_class class, int opts,
+ rrset_ns *nsrrsp)
+{
+ int i;
+
+ for (i = 0; i < ns_msg_count(*msg, sect); i++) {
+ char tname[MAXDNAME];
+ const u_char *rdata;
+ rr_ns *nsrr;
+ ns_rr rr;
+
+ if (ns_parserr(msg, sect, i, &rr) < 0) {
+ DPRINTF(("save_ns: ns_parserr(%s, %d) failed",
+ p_section(sect, ns_o_query), i));
+ return (-1);
+ }
+ if (ns_rr_type(rr) != ns_t_ns ||
+ ns_rr_class(rr) != class ||
+ ns_samename(ns_rr_name(rr), owner) != 1)
+ continue;
+ nsrr = find_ns(nsrrsp, ns_rr_name(rr));
+ if (nsrr == NULL) {
+ nsrr = malloc(sizeof *nsrr);
+ if (nsrr == NULL) {
+ DPRINTF(("save_ns: malloc failed"));
+ return (-1);
+ }
+ rdata = ns_rr_rdata(rr);
+ if (ns_name_uncompress(ns_msg_base(*msg),
+ ns_msg_end(*msg), rdata,
+ tname, sizeof tname) < 0) {
+ DPRINTF(("save_ns: ns_name_uncompress failed")
+ );
+ free(nsrr);
+ return (-1);
+ }
+ nsrr->name = strdup(tname);
+ if (nsrr->name == NULL) {
+ DPRINTF(("save_ns: strdup failed"));
+ free(nsrr);
+ return (-1);
+ }
+ INIT_LINK(nsrr, link);
+ INIT_LIST(nsrr->addrs);
+ nsrr->flags = 0;
+ APPEND(*nsrrsp, nsrr, link);
+ }
+ if (save_a(statp, msg, ns_s_ar,
+ nsrr->name, class, opts, nsrr) < 0) {
+ DPRINTF(("save_ns: save_r('%s', %s) failed",
+ nsrr->name, p_class(class)));
+ return (-1);
+ }
+ }
+ return (0);
+}
+
+static int
+save_a(res_state statp, ns_msg *msg, ns_sect sect,
+ const char *owner, ns_class class, int opts,
+ rr_ns *nsrr)
+{
+ int i;
+
+ for (i = 0; i < ns_msg_count(*msg, sect); i++) {
+ ns_rr rr;
+ rr_a *arr;
+
+ if (ns_parserr(msg, sect, i, &rr) < 0) {
+ DPRINTF(("save_a: ns_parserr(%s, %d) failed",
+ p_section(sect, ns_o_query), i));
+ return (-1);
+ }
+ if ((ns_rr_type(rr) != ns_t_a &&
+ ns_rr_type(rr) != ns_t_aaaa) ||
+ ns_rr_class(rr) != class ||
+ ns_samename(ns_rr_name(rr), owner) != 1 ||
+ ns_rr_rdlen(rr) != NS_INADDRSZ)
+ continue;
+ if ((opts & RES_IPV6ONLY) != 0 && ns_rr_type(rr) != ns_t_aaaa)
+ continue;
+ if ((opts & RES_IPV4ONLY) != 0 && ns_rr_type(rr) != ns_t_a)
+ continue;
+ arr = malloc(sizeof *arr);
+ if (arr == NULL) {
+ DPRINTF(("save_a: malloc failed"));
+ return (-1);
+ }
+ INIT_LINK(arr, link);
+ memset(&arr->addr, 0, sizeof(arr->addr));
+ switch (ns_rr_type(rr)) {
+ case ns_t_a:
+ arr->addr.sin.sin_family = AF_INET;
+#ifdef HAVE_SA_LEN
+ arr->addr.sin.sin_len = sizeof(arr->addr.sin);
+#endif
+ memcpy(&arr->addr.sin.sin_addr, ns_rr_rdata(rr),
+ NS_INADDRSZ);
+ arr->addr.sin.sin_port = htons(NAMESERVER_PORT);
+ nsrr->flags |= RR_NS_HAVE_V4;
+ break;
+ case ns_t_aaaa:
+ arr->addr.sin6.sin6_family = AF_INET6;
+#ifdef HAVE_SA_LEN
+ arr->addr.sin6.sin6_len = sizeof(arr->addr.sin6);
+#endif
+ memcpy(&arr->addr.sin6.sin6_addr, ns_rr_rdata(rr), 16);
+ arr->addr.sin.sin_port = htons(NAMESERVER_PORT);
+ nsrr->flags |= RR_NS_HAVE_V6;
+ break;
+ default:
+ abort();
+ }
+ APPEND(nsrr->addrs, arr, link);
+ }
+ return (0);
+}
+
+static void
+free_nsrrset(rrset_ns *nsrrsp) {
+ rr_ns *nsrr;
+
+ while ((nsrr = HEAD(*nsrrsp)) != NULL)
+ free_nsrr(nsrrsp, nsrr);
+}
+
+static void
+free_nsrr(rrset_ns *nsrrsp, rr_ns *nsrr) {
+ rr_a *arr;
+ char *tmp;
+
+ while ((arr = HEAD(nsrr->addrs)) != NULL) {
+ UNLINK(nsrr->addrs, arr, link);
+ free(arr);
+ }
+ DE_CONST(nsrr->name, tmp);
+ free(tmp);
+ UNLINK(*nsrrsp, nsrr, link);
+ free(nsrr);
+}
+
+static rr_ns *
+find_ns(rrset_ns *nsrrsp, const char *dname) {
+ rr_ns *nsrr;
+
+ for (nsrr = HEAD(*nsrrsp); nsrr != NULL; nsrr = NEXT(nsrr, link))
+ if (ns_samename(nsrr->name, dname) == 1)
+ return (nsrr);
+ return (NULL);
+}
+
+static int
+do_query(res_state statp, const char *dname, ns_class class, ns_type qtype,
+ u_char *resp, ns_msg *msg)
+{
+ u_char req[NS_PACKETSZ];
+ int i, n;
+
+ n = res_nmkquery(statp, ns_o_query, dname, class, qtype,
+ NULL, 0, NULL, req, NS_PACKETSZ);
+ if (n < 0) {
+ DPRINTF(("do_query: res_nmkquery failed"));
+ return (-1);
+ }
+ n = res_nsend(statp, req, n, resp, NS_MAXMSG);
+ if (n < 0) {
+ DPRINTF(("do_query: res_nsend failed"));
+ return (-1);
+ }
+ if (n == 0) {
+ DPRINTF(("do_query: res_nsend returned 0"));
+ errno = EMSGSIZE;
+ return (-1);
+ }
+ if (ns_initparse(resp, n, msg) < 0) {
+ DPRINTF(("do_query: ns_initparse failed"));
+ return (-1);
+ }
+ n = 0;
+ for (i = 0; i < ns_msg_count(*msg, ns_s_an); i++) {
+ ns_rr rr;
+
+ if (ns_parserr(msg, ns_s_an, i, &rr) < 0) {
+ DPRINTF(("do_query: ns_parserr failed"));
+ return (-1);
+ }
+ n += (ns_rr_class(rr) == class &&
+ (ns_rr_type(rr) == ns_t_cname ||
+ ns_rr_type(rr) == ns_t_dname));
+ }
+ return (n);
+}
+
+static void
+res_dprintf(const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ fputs(";; res_findzonecut: ", stderr);
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+}
+
+/*! \file */
diff --git a/lib/libc/resolv/res_init.c b/lib/libc/resolv/res_init.c
new file mode 100644
index 0000000..661e880
--- /dev/null
+++ b/lib/libc/resolv/res_init.c
@@ -0,0 +1,872 @@
+/*
+ * Copyright (c) 1985, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_init.c 8.1 (Berkeley) 6/7/93";
+static const char rcsid[] = "$Id: res_init.c,v 1.16.18.7 2007/07/09 01:52:58 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include "namespace.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <ctype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+
+#include "un-namespace.h"
+
+#include "port_after.h"
+
+/* ensure that sockaddr_in6 and IN6ADDR_ANY_INIT are declared / defined */
+#include <resolv.h>
+
+#include "res_private.h"
+
+/*% Options. Should all be left alone. */
+#define RESOLVSORT
+#define DEBUG
+
+#ifdef SOLARIS2
+#include <sys/systeminfo.h>
+#endif
+
+static void res_setoptions(res_state, const char *, const char *);
+
+#ifdef RESOLVSORT
+static const char sort_mask[] = "/&";
+#define ISSORTMASK(ch) (strchr(sort_mask, ch) != NULL)
+static u_int32_t net_mask(struct in_addr);
+#endif
+
+#if !defined(isascii) /*%< XXX - could be a function */
+# define isascii(c) (!(c & 0200))
+#endif
+
+/*
+ * Resolver state default settings.
+ */
+
+/*%
+ * Set up default settings. If the configuration file exist, the values
+ * there will have precedence. Otherwise, the server address is set to
+ * INADDR_ANY and the default domain name comes from the gethostname().
+ *
+ * An interrim version of this code (BIND 4.9, pre-4.4BSD) used 127.0.0.1
+ * rather than INADDR_ANY ("0.0.0.0") as the default name server address
+ * since it was noted that INADDR_ANY actually meant ``the first interface
+ * you "ifconfig"'d at boot time'' and if this was a SLIP or PPP interface,
+ * it had to be "up" in order for you to reach your own name server. It
+ * was later decided that since the recommended practice is to always
+ * install local static routes through 127.0.0.1 for all your network
+ * interfaces, that we could solve this problem without a code change.
+ *
+ * The configuration file should always be used, since it is the only way
+ * to specify a default domain. If you are running a server on your local
+ * machine, you should say "nameserver 0.0.0.0" or "nameserver 127.0.0.1"
+ * in the configuration file.
+ *
+ * Return 0 if completes successfully, -1 on error
+ */
+int
+res_ninit(res_state statp) {
+ extern int __res_vinit(res_state, int);
+
+ return (__res_vinit(statp, 0));
+}
+
+/*% This function has to be reachable by res_data.c but not publically. */
+int
+__res_vinit(res_state statp, int preinit) {
+ FILE *fp;
+ char *cp, **pp;
+ int n;
+ char buf[BUFSIZ];
+ int nserv = 0; /*%< number of nameserver records read from file */
+ int haveenv = 0;
+ int havesearch = 0;
+#ifdef RESOLVSORT
+ int nsort = 0;
+ char *net;
+#endif
+ int dots;
+ union res_sockaddr_union u[2];
+ int maxns = MAXNS;
+
+ RES_SET_H_ERRNO(statp, 0);
+ if (statp->_u._ext.ext != NULL)
+ res_ndestroy(statp);
+
+ if (!preinit) {
+ statp->retrans = RES_TIMEOUT;
+ statp->retry = RES_DFLRETRY;
+ statp->options = RES_DEFAULT;
+ statp->id = res_randomid();
+ }
+
+ memset(u, 0, sizeof(u));
+#ifdef USELOOPBACK
+ u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
+#else
+ u[nserv].sin.sin_addr.s_addr = INADDR_ANY;
+#endif
+ u[nserv].sin.sin_family = AF_INET;
+ u[nserv].sin.sin_port = htons(NAMESERVER_PORT);
+#ifdef HAVE_SA_LEN
+ u[nserv].sin.sin_len = sizeof(struct sockaddr_in);
+#endif
+ nserv++;
+#ifdef HAS_INET6_STRUCTS
+#ifdef USELOOPBACK
+ u[nserv].sin6.sin6_addr = in6addr_loopback;
+#else
+ u[nserv].sin6.sin6_addr = in6addr_any;
+#endif
+ u[nserv].sin6.sin6_family = AF_INET6;
+ u[nserv].sin6.sin6_port = htons(NAMESERVER_PORT);
+#ifdef HAVE_SA_LEN
+ u[nserv].sin6.sin6_len = sizeof(struct sockaddr_in6);
+#endif
+ nserv++;
+#endif
+ statp->nscount = 0;
+ statp->ndots = 1;
+ statp->pfcode = 0;
+ statp->_vcsock = -1;
+ statp->_flags = 0;
+ statp->qhook = NULL;
+ statp->rhook = NULL;
+ statp->_u._ext.nscount = 0;
+ statp->_u._ext.ext = malloc(sizeof(*statp->_u._ext.ext));
+ if (statp->_u._ext.ext != NULL) {
+ memset(statp->_u._ext.ext, 0, sizeof(*statp->_u._ext.ext));
+ statp->_u._ext.ext->nsaddrs[0].sin = statp->nsaddr;
+ strcpy(statp->_u._ext.ext->nsuffix, "ip6.arpa");
+ strcpy(statp->_u._ext.ext->nsuffix2, "ip6.int");
+ } else {
+ /*
+ * Historically res_init() rarely, if at all, failed.
+ * Examples and applications exist which do not check
+ * our return code. Furthermore several applications
+ * simply call us to get the systems domainname. So
+ * rather then immediately fail here we store the
+ * failure, which is returned later, in h_errno. And
+ * prevent the collection of 'nameserver' information
+ * by setting maxns to 0. Thus applications that fail
+ * to check our return code wont be able to make
+ * queries anyhow.
+ */
+ RES_SET_H_ERRNO(statp, NETDB_INTERNAL);
+ maxns = 0;
+ }
+#ifdef RESOLVSORT
+ statp->nsort = 0;
+#endif
+ res_setservers(statp, u, nserv);
+
+#ifdef SOLARIS2
+ /*
+ * The old libresolv derived the defaultdomain from NIS/NIS+.
+ * We want to keep this behaviour
+ */
+ {
+ char buf[sizeof(statp->defdname)], *cp;
+ int ret;
+
+ if ((ret = sysinfo(SI_SRPC_DOMAIN, buf, sizeof(buf))) > 0 &&
+ (unsigned int)ret <= sizeof(buf)) {
+ if (buf[0] == '+')
+ buf[0] = '.';
+ cp = strchr(buf, '.');
+ cp = (cp == NULL) ? buf : (cp + 1);
+ strncpy(statp->defdname, cp,
+ sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+ }
+ }
+#endif /* SOLARIS2 */
+
+ /* Allow user to override the local domain definition */
+ if (issetugid() == 0 && (cp = getenv("LOCALDOMAIN")) != NULL) {
+ (void)strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+ haveenv++;
+
+ /*
+ * Set search list to be blank-separated strings
+ * from rest of env value. Permits users of LOCALDOMAIN
+ * to still have a search list, and anyone to set the
+ * one that they want to use as an individual (even more
+ * important now that the rfc1535 stuff restricts searches)
+ */
+ cp = statp->defdname;
+ pp = statp->dnsrch;
+ *pp++ = cp;
+ for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
+ if (*cp == '\n') /*%< silly backwards compat */
+ break;
+ else if (*cp == ' ' || *cp == '\t') {
+ *cp = 0;
+ n = 1;
+ } else if (n) {
+ *pp++ = cp;
+ n = 0;
+ havesearch = 1;
+ }
+ }
+ /* null terminate last domain if there are excess */
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t' && *cp != '\n')
+ cp++;
+ *cp = '\0';
+ *pp++ = 0;
+ }
+
+#define MATCH(line, name) \
+ (!strncmp(line, name, sizeof(name) - 1) && \
+ (line[sizeof(name) - 1] == ' ' || \
+ line[sizeof(name) - 1] == '\t'))
+
+ nserv = 0;
+ if ((fp = fopen(_PATH_RESCONF, "r")) != NULL) {
+ /* read the config file */
+ while (fgets(buf, sizeof(buf), fp) != NULL) {
+ /* skip comments */
+ if (*buf == ';' || *buf == '#')
+ continue;
+ /* read default domain name */
+ if (MATCH(buf, "domain")) {
+ if (haveenv) /*%< skip if have from environ */
+ continue;
+ cp = buf + sizeof("domain") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+ if ((cp = strpbrk(statp->defdname, " \t\n")) != NULL)
+ *cp = '\0';
+ havesearch = 0;
+ continue;
+ }
+ /* set search list */
+ if (MATCH(buf, "search")) {
+ if (haveenv) /*%< skip if have from environ */
+ continue;
+ cp = buf + sizeof("search") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if ((*cp == '\0') || (*cp == '\n'))
+ continue;
+ strncpy(statp->defdname, cp, sizeof(statp->defdname) - 1);
+ statp->defdname[sizeof(statp->defdname) - 1] = '\0';
+ if ((cp = strchr(statp->defdname, '\n')) != NULL)
+ *cp = '\0';
+ /*
+ * Set search list to be blank-separated strings
+ * on rest of line.
+ */
+ cp = statp->defdname;
+ pp = statp->dnsrch;
+ *pp++ = cp;
+ for (n = 0; *cp && pp < statp->dnsrch + MAXDNSRCH; cp++) {
+ if (*cp == ' ' || *cp == '\t') {
+ *cp = 0;
+ n = 1;
+ } else if (n) {
+ *pp++ = cp;
+ n = 0;
+ }
+ }
+ /* null terminate last domain if there are excess */
+ while (*cp != '\0' && *cp != ' ' && *cp != '\t')
+ cp++;
+ *cp = '\0';
+ *pp++ = 0;
+ havesearch = 1;
+ continue;
+ }
+ /* read nameservers to query */
+ if (MATCH(buf, "nameserver") && nserv < maxns) {
+ struct addrinfo hints, *ai;
+ char sbuf[NI_MAXSERV];
+ const size_t minsiz =
+ sizeof(statp->_u._ext.ext->nsaddrs[0]);
+
+ cp = buf + sizeof("nameserver") - 1;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ cp[strcspn(cp, ";# \t\n")] = '\0';
+ if ((*cp != '\0') && (*cp != '\n')) {
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = PF_UNSPEC;
+ hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+ hints.ai_flags = AI_NUMERICHOST;
+ sprintf(sbuf, "%u", NAMESERVER_PORT);
+ if (getaddrinfo(cp, sbuf, &hints, &ai) == 0 &&
+ ai->ai_addrlen <= minsiz) {
+ if (statp->_u._ext.ext != NULL) {
+ memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
+ ai->ai_addr, ai->ai_addrlen);
+ }
+ if (ai->ai_addrlen <=
+ sizeof(statp->nsaddr_list[nserv])) {
+ memcpy(&statp->nsaddr_list[nserv],
+ ai->ai_addr, ai->ai_addrlen);
+ } else
+ statp->nsaddr_list[nserv].sin_family = 0;
+ freeaddrinfo(ai);
+ nserv++;
+ }
+ }
+ continue;
+ }
+#ifdef RESOLVSORT
+ if (MATCH(buf, "sortlist")) {
+ struct in_addr a;
+ struct in6_addr a6;
+ int m, i;
+ u_char *u;
+ struct __res_state_ext *ext = statp->_u._ext.ext;
+
+ cp = buf + sizeof("sortlist") - 1;
+ while (nsort < MAXRESOLVSORT) {
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if (*cp == '\0' || *cp == '\n' || *cp == ';')
+ break;
+ net = cp;
+ while (*cp && !ISSORTMASK(*cp) && *cp != ';' &&
+ isascii(*cp) && !isspace((unsigned char)*cp))
+ cp++;
+ n = *cp;
+ *cp = 0;
+ if (inet_aton(net, &a)) {
+ statp->sort_list[nsort].addr = a;
+ if (ISSORTMASK(n)) {
+ *cp++ = n;
+ net = cp;
+ while (*cp && *cp != ';' &&
+ isascii(*cp) &&
+ !isspace((unsigned char)*cp))
+ cp++;
+ n = *cp;
+ *cp = 0;
+ if (inet_aton(net, &a)) {
+ statp->sort_list[nsort].mask = a.s_addr;
+ } else {
+ statp->sort_list[nsort].mask =
+ net_mask(statp->sort_list[nsort].addr);
+ }
+ } else {
+ statp->sort_list[nsort].mask =
+ net_mask(statp->sort_list[nsort].addr);
+ }
+ ext->sort_list[nsort].af = AF_INET;
+ ext->sort_list[nsort].addr.ina =
+ statp->sort_list[nsort].addr;
+ ext->sort_list[nsort].mask.ina.s_addr =
+ statp->sort_list[nsort].mask;
+ nsort++;
+ }
+ else if (inet_pton(AF_INET6, net, &a6) == 1) {
+
+ ext->sort_list[nsort].af = AF_INET6;
+ ext->sort_list[nsort].addr.in6a = a6;
+ u = (u_char *)&ext->sort_list[nsort].mask.in6a;
+ *cp++ = n;
+ net = cp;
+ while (*cp && *cp != ';' &&
+ isascii(*cp) && !isspace(*cp))
+ cp++;
+ m = n;
+ n = *cp;
+ *cp = 0;
+ switch (m) {
+ case '/':
+ m = atoi(net);
+ break;
+ case '&':
+ if (inet_pton(AF_INET6, net, u) == 1) {
+ m = -1;
+ break;
+ }
+ /*FALLTHROUGH*/
+ default:
+ m = sizeof(struct in6_addr) * CHAR_BIT;
+ break;
+ }
+ if (m >= 0) {
+ for (i = 0; i < sizeof(struct in6_addr); i++) {
+ if (m <= 0) {
+ *u = 0;
+ } else {
+ m -= CHAR_BIT;
+ *u = (u_char)~0;
+ if (m < 0)
+ *u <<= -m;
+ }
+ u++;
+ }
+ }
+ statp->sort_list[nsort].addr.s_addr =
+ (u_int32_t)0xffffffff;
+ statp->sort_list[nsort].mask =
+ (u_int32_t)0xffffffff;
+ nsort++;
+ }
+ *cp = n;
+ }
+ continue;
+ }
+#endif
+ if (MATCH(buf, "options")) {
+ res_setoptions(statp, buf + sizeof("options") - 1, "conf");
+ continue;
+ }
+ }
+ if (nserv > 0)
+ statp->nscount = nserv;
+#ifdef RESOLVSORT
+ statp->nsort = nsort;
+#endif
+ (void) fclose(fp);
+ }
+/*
+ * Last chance to get a nameserver. This should not normally
+ * be necessary
+ */
+#ifdef NO_RESOLV_CONF
+ if(nserv == 0)
+ nserv = get_nameservers(statp);
+#endif
+
+ if (statp->defdname[0] == 0 &&
+ gethostname(buf, sizeof(statp->defdname) - 1) == 0 &&
+ (cp = strchr(buf, '.')) != NULL)
+ strcpy(statp->defdname, cp + 1);
+
+ /* find components of local domain that might be searched */
+ if (havesearch == 0) {
+ pp = statp->dnsrch;
+ *pp++ = statp->defdname;
+ *pp = NULL;
+
+ dots = 0;
+ for (cp = statp->defdname; *cp; cp++)
+ dots += (*cp == '.');
+
+ cp = statp->defdname;
+ while (pp < statp->dnsrch + MAXDFLSRCH) {
+ if (dots < LOCALDOMAINPARTS)
+ break;
+ cp = strchr(cp, '.') + 1; /*%< we know there is one */
+ *pp++ = cp;
+ dots--;
+ }
+ *pp = NULL;
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG) {
+ printf(";; res_init()... default dnsrch list:\n");
+ for (pp = statp->dnsrch; *pp; pp++)
+ printf(";;\t%s\n", *pp);
+ printf(";;\t..END..\n");
+ }
+#endif
+ }
+
+ if (issetugid())
+ statp->options |= RES_NOALIASES;
+ else if ((cp = getenv("RES_OPTIONS")) != NULL)
+ res_setoptions(statp, cp, "env");
+ statp->options |= RES_INIT;
+ return (statp->res_h_errno);
+}
+
+static void
+res_setoptions(res_state statp, const char *options, const char *source)
+{
+ const char *cp = options;
+ int i;
+#ifndef _LIBC
+ struct __res_state_ext *ext = statp->_u._ext.ext;
+#endif
+
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_setoptions(\"%s\", \"%s\")...\n",
+ options, source);
+#endif
+ while (*cp) {
+ /* skip leading and inner runs of spaces */
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ /* search for and process individual options */
+ if (!strncmp(cp, "ndots:", sizeof("ndots:") - 1)) {
+ i = atoi(cp + sizeof("ndots:") - 1);
+ if (i <= RES_MAXNDOTS)
+ statp->ndots = i;
+ else
+ statp->ndots = RES_MAXNDOTS;
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";;\tndots=%d\n", statp->ndots);
+#endif
+ } else if (!strncmp(cp, "timeout:", sizeof("timeout:") - 1)) {
+ i = atoi(cp + sizeof("timeout:") - 1);
+ if (i <= RES_MAXRETRANS)
+ statp->retrans = i;
+ else
+ statp->retrans = RES_MAXRETRANS;
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";;\ttimeout=%d\n", statp->retrans);
+#endif
+#ifdef SOLARIS2
+ } else if (!strncmp(cp, "retrans:", sizeof("retrans:") - 1)) {
+ /*
+ * For backward compatibility, 'retrans' is
+ * supported as an alias for 'timeout', though
+ * without an imposed maximum.
+ */
+ statp->retrans = atoi(cp + sizeof("retrans:") - 1);
+ } else if (!strncmp(cp, "retry:", sizeof("retry:") - 1)){
+ /*
+ * For backward compatibility, 'retry' is
+ * supported as an alias for 'attempts', though
+ * without an imposed maximum.
+ */
+ statp->retry = atoi(cp + sizeof("retry:") - 1);
+#endif /* SOLARIS2 */
+ } else if (!strncmp(cp, "attempts:", sizeof("attempts:") - 1)){
+ i = atoi(cp + sizeof("attempts:") - 1);
+ if (i <= RES_MAXRETRY)
+ statp->retry = i;
+ else
+ statp->retry = RES_MAXRETRY;
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";;\tattempts=%d\n", statp->retry);
+#endif
+ } else if (!strncmp(cp, "debug", sizeof("debug") - 1)) {
+#ifdef DEBUG
+ if (!(statp->options & RES_DEBUG)) {
+ printf(";; res_setoptions(\"%s\", \"%s\")..\n",
+ options, source);
+ statp->options |= RES_DEBUG;
+ }
+ printf(";;\tdebug\n");
+#endif
+ } else if (!strncmp(cp, "no_tld_query",
+ sizeof("no_tld_query") - 1) ||
+ !strncmp(cp, "no-tld-query",
+ sizeof("no-tld-query") - 1)) {
+ statp->options |= RES_NOTLDQUERY;
+ } else if (!strncmp(cp, "inet6", sizeof("inet6") - 1)) {
+ statp->options |= RES_USE_INET6;
+ } else if (!strncmp(cp, "insecure1", sizeof("insecure1") - 1)) {
+ statp->options |= RES_INSECURE1;
+ } else if (!strncmp(cp, "insecure2", sizeof("insecure2") - 1)) {
+ statp->options |= RES_INSECURE2;
+ } else if (!strncmp(cp, "rotate", sizeof("rotate") - 1)) {
+ statp->options |= RES_ROTATE;
+ } else if (!strncmp(cp, "no-check-names",
+ sizeof("no-check-names") - 1)) {
+ statp->options |= RES_NOCHECKNAME;
+ }
+#ifdef RES_USE_EDNS0
+ else if (!strncmp(cp, "edns0", sizeof("edns0") - 1)) {
+ statp->options |= RES_USE_EDNS0;
+ }
+#endif
+#ifndef _LIBC
+ else if (!strncmp(cp, "dname", sizeof("dname") - 1)) {
+ statp->options |= RES_USE_DNAME;
+ }
+ else if (!strncmp(cp, "nibble:", sizeof("nibble:") - 1)) {
+ if (ext == NULL)
+ goto skip;
+ cp += sizeof("nibble:") - 1;
+ i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix) - 1);
+ strncpy(ext->nsuffix, cp, i);
+ ext->nsuffix[i] = '\0';
+ }
+ else if (!strncmp(cp, "nibble2:", sizeof("nibble2:") - 1)) {
+ if (ext == NULL)
+ goto skip;
+ cp += sizeof("nibble2:") - 1;
+ i = MIN(strcspn(cp, " \t"), sizeof(ext->nsuffix2) - 1);
+ strncpy(ext->nsuffix2, cp, i);
+ ext->nsuffix2[i] = '\0';
+ }
+ else if (!strncmp(cp, "v6revmode:", sizeof("v6revmode:") - 1)) {
+ cp += sizeof("v6revmode:") - 1;
+ /* "nibble" and "bitstring" used to be valid */
+ if (!strncmp(cp, "single", sizeof("single") - 1)) {
+ statp->options |= RES_NO_NIBBLE2;
+ } else if (!strncmp(cp, "both", sizeof("both") - 1)) {
+ statp->options &=
+ ~RES_NO_NIBBLE2;
+ }
+ }
+#endif
+ else {
+ /* XXX - print a warning here? */
+ }
+#ifndef _LIBC
+ skip:
+#endif
+ /* skip to next run of spaces */
+ while (*cp && *cp != ' ' && *cp != '\t')
+ cp++;
+ }
+}
+
+#ifdef RESOLVSORT
+/* XXX - should really support CIDR which means explicit masks always. */
+static u_int32_t
+net_mask(in) /*!< XXX - should really use system's version of this */
+ struct in_addr in;
+{
+ u_int32_t i = ntohl(in.s_addr);
+
+ if (IN_CLASSA(i))
+ return (htonl(IN_CLASSA_NET));
+ else if (IN_CLASSB(i))
+ return (htonl(IN_CLASSB_NET));
+ return (htonl(IN_CLASSC_NET));
+}
+#endif
+
+u_int
+res_randomid(void) {
+ struct timeval now;
+
+ gettimeofday(&now, NULL);
+ return (0xffff & (now.tv_sec ^ now.tv_usec ^ getpid()));
+}
+
+/*%
+ * This routine is for closing the socket if a virtual circuit is used and
+ * the program wants to close it. This provides support for endhostent()
+ * which expects to close the socket.
+ *
+ * This routine is not expected to be user visible.
+ */
+void
+res_nclose(res_state statp) {
+ int ns;
+
+ if (statp->_vcsock >= 0) {
+ (void) _close(statp->_vcsock);
+ statp->_vcsock = -1;
+ statp->_flags &= ~(RES_F_VC | RES_F_CONN);
+ }
+ for (ns = 0; ns < statp->_u._ext.nscount; ns++) {
+ if (statp->_u._ext.nssocks[ns] != -1) {
+ (void) _close(statp->_u._ext.nssocks[ns]);
+ statp->_u._ext.nssocks[ns] = -1;
+ }
+ }
+}
+
+void
+res_ndestroy(res_state statp) {
+ res_nclose(statp);
+ if (statp->_u._ext.ext != NULL)
+ free(statp->_u._ext.ext);
+ statp->options &= ~RES_INIT;
+ statp->_u._ext.ext = NULL;
+}
+
+#ifndef _LIBC
+const char *
+res_get_nibblesuffix(res_state statp) {
+ if (statp->_u._ext.ext)
+ return (statp->_u._ext.ext->nsuffix);
+ return ("ip6.arpa");
+}
+
+const char *
+res_get_nibblesuffix2(res_state statp) {
+ if (statp->_u._ext.ext)
+ return (statp->_u._ext.ext->nsuffix2);
+ return ("ip6.int");
+}
+#endif
+
+void
+res_setservers(res_state statp, const union res_sockaddr_union *set, int cnt) {
+ int i, nserv;
+ size_t size;
+
+ /* close open servers */
+ res_nclose(statp);
+
+ /* cause rtt times to be forgotten */
+ statp->_u._ext.nscount = 0;
+
+ nserv = 0;
+ for (i = 0; i < cnt && nserv < MAXNS; i++) {
+ switch (set->sin.sin_family) {
+ case AF_INET:
+ size = sizeof(set->sin);
+ if (statp->_u._ext.ext)
+ memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
+ &set->sin, size);
+ if (size <= sizeof(statp->nsaddr_list[nserv]))
+ memcpy(&statp->nsaddr_list[nserv],
+ &set->sin, size);
+ else
+ statp->nsaddr_list[nserv].sin_family = 0;
+ nserv++;
+ break;
+
+#ifdef HAS_INET6_STRUCTS
+ case AF_INET6:
+ size = sizeof(set->sin6);
+ if (statp->_u._ext.ext)
+ memcpy(&statp->_u._ext.ext->nsaddrs[nserv],
+ &set->sin6, size);
+ if (size <= sizeof(statp->nsaddr_list[nserv]))
+ memcpy(&statp->nsaddr_list[nserv],
+ &set->sin6, size);
+ else
+ statp->nsaddr_list[nserv].sin_family = 0;
+ nserv++;
+ break;
+#endif
+
+ default:
+ break;
+ }
+ set++;
+ }
+ statp->nscount = nserv;
+
+}
+
+int
+res_getservers(res_state statp, union res_sockaddr_union *set, int cnt) {
+ int i;
+ size_t size;
+ u_int16_t family;
+
+ for (i = 0; i < statp->nscount && i < cnt; i++) {
+ if (statp->_u._ext.ext)
+ family = statp->_u._ext.ext->nsaddrs[i].sin.sin_family;
+ else
+ family = statp->nsaddr_list[i].sin_family;
+
+ switch (family) {
+ case AF_INET:
+ size = sizeof(set->sin);
+ if (statp->_u._ext.ext)
+ memcpy(&set->sin,
+ &statp->_u._ext.ext->nsaddrs[i],
+ size);
+ else
+ memcpy(&set->sin, &statp->nsaddr_list[i],
+ size);
+ break;
+
+#ifdef HAS_INET6_STRUCTS
+ case AF_INET6:
+ size = sizeof(set->sin6);
+ if (statp->_u._ext.ext)
+ memcpy(&set->sin6,
+ &statp->_u._ext.ext->nsaddrs[i],
+ size);
+ else
+ memcpy(&set->sin6, &statp->nsaddr_list[i],
+ size);
+ break;
+#endif
+
+ default:
+ set->sin.sin_family = 0;
+ break;
+ }
+ set++;
+ }
+ return (statp->nscount);
+}
+
+/*! \file */
diff --git a/lib/libc/resolv/res_mkquery.c b/lib/libc/resolv/res_mkquery.c
new file mode 100644
index 0000000..7bd9cda
--- /dev/null
+++ b/lib/libc/resolv/res_mkquery.c
@@ -0,0 +1,303 @@
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_mkquery.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_mkquery.c,v 1.5.18.2 2008/04/03 23:15:15 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <string.h>
+#include "port_after.h"
+
+/* Options. Leave them on. */
+#define DEBUG
+
+extern const char *_res_opcodes[];
+
+/*%
+ * Form all types of queries.
+ * Returns the size of the result or -1.
+ */
+int
+res_nmkquery(res_state statp,
+ int op, /*!< opcode of query */
+ const char *dname, /*!< domain name */
+ int class, int type, /*!< class and type of query */
+ const u_char *data, /*!< resource record data */
+ int datalen, /*!< length of data */
+ const u_char *newrr_in, /*!< new rr for modify or append */
+ u_char *buf, /*!< buffer to put query */
+ int buflen) /*!< size of buffer */
+{
+ HEADER *hp;
+ u_char *cp, *ep;
+ int n;
+ u_char *dnptrs[20], **dpp, **lastdnptr;
+
+ UNUSED(newrr_in);
+
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_nmkquery(%s, %s, %s, %s)\n",
+ _res_opcodes[op], dname, p_class(class), p_type(type));
+#endif
+ /*
+ * Initialize header fields.
+ */
+ if ((buf == NULL) || (buflen < HFIXEDSZ))
+ return (-1);
+ memset(buf, 0, HFIXEDSZ);
+ hp = (HEADER *) buf;
+ hp->id = htons(++statp->id);
+ hp->opcode = op;
+ hp->rd = (statp->options & RES_RECURSE) != 0U;
+ hp->rcode = NOERROR;
+ cp = buf + HFIXEDSZ;
+ ep = buf + buflen;
+ dpp = dnptrs;
+ *dpp++ = buf;
+ *dpp++ = NULL;
+ lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+ /*
+ * perform opcode specific processing
+ */
+ switch (op) {
+ case QUERY: /*FALLTHROUGH*/
+ case NS_NOTIFY_OP:
+ if (ep - cp < QFIXEDSZ)
+ return (-1);
+ if ((n = dn_comp(dname, cp, ep - cp - QFIXEDSZ, dnptrs,
+ lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ ns_put16(type, cp);
+ cp += INT16SZ;
+ ns_put16(class, cp);
+ cp += INT16SZ;
+ hp->qdcount = htons(1);
+ if (op == QUERY || data == NULL)
+ break;
+ /*
+ * Make an additional record for completion domain.
+ */
+ if ((ep - cp) < RRFIXEDSZ)
+ return (-1);
+ n = dn_comp((const char *)data, cp, ep - cp - RRFIXEDSZ,
+ dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ns_put16(T_NULL, cp);
+ cp += INT16SZ;
+ ns_put16(class, cp);
+ cp += INT16SZ;
+ ns_put32(0, cp);
+ cp += INT32SZ;
+ ns_put16(0, cp);
+ cp += INT16SZ;
+ hp->arcount = htons(1);
+ break;
+
+ case IQUERY:
+ /*
+ * Initialize answer section
+ */
+ if (ep - cp < 1 + RRFIXEDSZ + datalen)
+ return (-1);
+ *cp++ = '\0'; /*%< no domain name */
+ ns_put16(type, cp);
+ cp += INT16SZ;
+ ns_put16(class, cp);
+ cp += INT16SZ;
+ ns_put32(0, cp);
+ cp += INT32SZ;
+ ns_put16(datalen, cp);
+ cp += INT16SZ;
+ if (datalen) {
+ memcpy(cp, data, datalen);
+ cp += datalen;
+ }
+ hp->ancount = htons(1);
+ break;
+
+ default:
+ return (-1);
+ }
+ return (cp - buf);
+}
+
+#ifdef RES_USE_EDNS0
+/* attach OPT pseudo-RR, as documented in RFC2671 (EDNS0). */
+
+int
+res_nopt(res_state statp,
+ int n0, /*%< current offset in buffer */
+ u_char *buf, /*%< buffer to put query */
+ int buflen, /*%< size of buffer */
+ int anslen) /*%< UDP answer buffer size */
+{
+ HEADER *hp;
+ u_char *cp, *ep;
+ u_int16_t flags = 0;
+
+#ifdef DEBUG
+ if ((statp->options & RES_DEBUG) != 0U)
+ printf(";; res_nopt()\n");
+#endif
+
+ hp = (HEADER *) buf;
+ cp = buf + n0;
+ ep = buf + buflen;
+
+ if ((ep - cp) < 1 + RRFIXEDSZ)
+ return (-1);
+
+ *cp++ = 0; /*%< "." */
+ ns_put16(ns_t_opt, cp); /*%< TYPE */
+ cp += INT16SZ;
+ if (anslen > 0xffff)
+ anslen = 0xffff; /* limit to 16bit value */
+ ns_put16(anslen & 0xffff, cp); /*%< CLASS = UDP payload size */
+ cp += INT16SZ;
+ *cp++ = NOERROR; /*%< extended RCODE */
+ *cp++ = 0; /*%< EDNS version */
+
+ if (statp->options & RES_USE_DNSSEC) {
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_opt()... ENDS0 DNSSEC\n");
+#endif
+ flags |= NS_OPT_DNSSEC_OK;
+ }
+ ns_put16(flags, cp);
+ cp += INT16SZ;
+
+ ns_put16(0U, cp); /*%< RDLEN */
+ cp += INT16SZ;
+
+ hp->arcount = htons(ntohs(hp->arcount) + 1);
+
+ return (cp - buf);
+}
+
+/*
+ * Construct variable data (RDATA) block for OPT psuedo-RR, append it
+ * to the buffer, then update the RDLEN field (previously set to zero by
+ * res_nopt()) with the new RDATA length.
+ */
+int
+res_nopt_rdata(res_state statp,
+ int n0, /*%< current offset in buffer */
+ u_char *buf, /*%< buffer to put query */
+ int buflen, /*%< size of buffer */
+ u_char *rdata, /*%< ptr to start of opt rdata */
+ u_short code, /*%< OPTION-CODE */
+ u_short len, /*%< OPTION-LENGTH */
+ u_char *data) /*%< OPTION_DATA */
+{
+ register u_char *cp, *ep;
+
+#ifdef DEBUG
+ if ((statp->options & RES_DEBUG) != 0U)
+ printf(";; res_nopt_rdata()\n");
+#endif
+
+ cp = buf + n0;
+ ep = buf + buflen;
+
+ if ((ep - cp) < (4 + len))
+ return (-1);
+
+ if (rdata < (buf + 2) || rdata >= ep)
+ return (-1);
+
+ ns_put16(code, cp);
+ cp += INT16SZ;
+
+ ns_put16(len, cp);
+ cp += INT16SZ;
+
+ memcpy(cp, data, len);
+ cp += len;
+
+ len = cp - rdata;
+ ns_put16(len, rdata - 2); /* Update RDLEN field */
+
+ return (cp - buf);
+}
+#endif
+
+/*! \file */
diff --git a/lib/libc/resolv/res_mkupdate.c b/lib/libc/resolv/res_mkupdate.c
new file mode 100644
index 0000000..589c056
--- /dev/null
+++ b/lib/libc/resolv/res_mkupdate.c
@@ -0,0 +1,1196 @@
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*! \file
+ * \brief
+ * Based on the Dynamic DNS reference implementation by Viraj Bais
+ * &lt;viraj_bais@ccm.fm.intel.com>
+ */
+
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: res_mkupdate.c,v 1.4.18.4 2005/10/14 05:44:12 marka Exp $";
+#endif /* not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <res_update.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <ctype.h>
+
+#ifdef _LIBC
+#include <isc/list.h>
+#endif
+
+#include "port_after.h"
+
+/* Options. Leave them on. */
+#define DEBUG
+#define MAXPORT 1024
+
+static int getnum_str(u_char **, u_char *);
+static int gethexnum_str(u_char **, u_char *);
+static int getword_str(char *, int, u_char **, u_char *);
+static int getstr_str(char *, int, u_char **, u_char *);
+
+#define ShrinkBuffer(x) if ((buflen -= x) < 0) return (-2);
+
+/* Forward. */
+
+#ifdef _LIBC
+static
+#endif
+int res_protocolnumber(const char *);
+#ifdef _LIBC
+static
+#endif
+int res_servicenumber(const char *);
+
+/*%
+ * Form update packets.
+ * Returns the size of the resulting packet if no error
+ *
+ * On error,
+ * returns
+ *\li -1 if error in reading a word/number in rdata
+ * portion for update packets
+ *\li -2 if length of buffer passed is insufficient
+ *\li -3 if zone section is not the first section in
+ * the linked list, or section order has a problem
+ *\li -4 on a number overflow
+ *\li -5 unknown operation or no records
+ */
+int
+res_nmkupdate(res_state statp, ns_updrec *rrecp_in, u_char *buf, int buflen) {
+ ns_updrec *rrecp_start = rrecp_in;
+ HEADER *hp;
+ u_char *cp, *sp2, *startp, *endp;
+ int n, i, soanum, multiline;
+ ns_updrec *rrecp;
+ struct in_addr ina;
+ struct in6_addr in6a;
+ char buf2[MAXDNAME];
+ u_char buf3[MAXDNAME];
+ int section, numrrs = 0, counts[ns_s_max];
+ u_int16_t rtype, rclass;
+ u_int32_t n1, rttl;
+ u_char *dnptrs[20], **dpp, **lastdnptr;
+#ifndef _LIBC
+ int siglen;
+#endif
+ int keylen, certlen;
+
+ /*
+ * Initialize header fields.
+ */
+ if ((buf == NULL) || (buflen < HFIXEDSZ))
+ return (-1);
+ memset(buf, 0, HFIXEDSZ);
+ hp = (HEADER *) buf;
+ hp->id = htons(++statp->id);
+ hp->opcode = ns_o_update;
+ hp->rcode = NOERROR;
+ cp = buf + HFIXEDSZ;
+ buflen -= HFIXEDSZ;
+ dpp = dnptrs;
+ *dpp++ = buf;
+ *dpp++ = NULL;
+ lastdnptr = dnptrs + sizeof dnptrs / sizeof dnptrs[0];
+
+ if (rrecp_start == NULL)
+ return (-5);
+ else if (rrecp_start->r_section != S_ZONE)
+ return (-3);
+
+ memset(counts, 0, sizeof counts);
+ for (rrecp = rrecp_start; rrecp; rrecp = NEXT(rrecp, r_glink)) {
+ numrrs++;
+ section = rrecp->r_section;
+ if (section < 0 || section >= ns_s_max)
+ return (-1);
+ counts[section]++;
+ for (i = section + 1; i < ns_s_max; i++)
+ if (counts[i])
+ return (-3);
+ rtype = rrecp->r_type;
+ rclass = rrecp->r_class;
+ rttl = rrecp->r_ttl;
+ /* overload class and type */
+ if (section == S_PREREQ) {
+ rttl = 0;
+ switch (rrecp->r_opcode) {
+ case YXDOMAIN:
+ rclass = C_ANY;
+ rtype = T_ANY;
+ rrecp->r_size = 0;
+ break;
+ case NXDOMAIN:
+ rclass = C_NONE;
+ rtype = T_ANY;
+ rrecp->r_size = 0;
+ break;
+ case NXRRSET:
+ rclass = C_NONE;
+ rrecp->r_size = 0;
+ break;
+ case YXRRSET:
+ if (rrecp->r_size == 0)
+ rclass = C_ANY;
+ break;
+ default:
+ fprintf(stderr,
+ "res_mkupdate: incorrect opcode: %d\n",
+ rrecp->r_opcode);
+ fflush(stderr);
+ return (-1);
+ }
+ } else if (section == S_UPDATE) {
+ switch (rrecp->r_opcode) {
+ case DELETE:
+ rclass = rrecp->r_size == 0 ? C_ANY : C_NONE;
+ break;
+ case ADD:
+ break;
+ default:
+ fprintf(stderr,
+ "res_mkupdate: incorrect opcode: %d\n",
+ rrecp->r_opcode);
+ fflush(stderr);
+ return (-1);
+ }
+ }
+
+ /*
+ * XXX appending default domain to owner name is omitted,
+ * fqdn must be provided
+ */
+ if ((n = dn_comp(rrecp->r_dname, cp, buflen, dnptrs,
+ lastdnptr)) < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n + 2*INT16SZ);
+ PUTSHORT(rtype, cp);
+ PUTSHORT(rclass, cp);
+ if (section == S_ZONE) {
+ if (numrrs != 1 || rrecp->r_type != T_SOA)
+ return (-3);
+ continue;
+ }
+ ShrinkBuffer(INT32SZ + INT16SZ);
+ PUTLONG(rttl, cp);
+ sp2 = cp; /*%< save pointer to length byte */
+ cp += INT16SZ;
+ if (rrecp->r_size == 0) {
+ if (section == S_UPDATE && rclass != C_ANY)
+ return (-1);
+ else {
+ PUTSHORT(0, sp2);
+ continue;
+ }
+ }
+ startp = rrecp->r_data;
+ endp = startp + rrecp->r_size - 1;
+ /* XXX this should be done centrally. */
+ switch (rrecp->r_type) {
+ case T_A:
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if (!inet_aton(buf2, &ina))
+ return (-1);
+ n1 = ntohl(ina.s_addr);
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(n1, cp);
+ break;
+ case T_CNAME:
+ case T_MB:
+ case T_MG:
+ case T_MR:
+ case T_NS:
+ case T_PTR:
+ case ns_t_dname:
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ case T_MINFO:
+ case T_SOA:
+ case T_RP:
+ for (i = 0; i < 2; i++) {
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen,
+ dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ }
+ if (rrecp->r_type == T_SOA) {
+ ShrinkBuffer(5 * INT32SZ);
+ while (isspace(*startp) || !*startp)
+ startp++;
+ if (*startp == '(') {
+ multiline = 1;
+ startp++;
+ } else
+ multiline = 0;
+ /* serial, refresh, retry, expire, minimum */
+ for (i = 0; i < 5; i++) {
+ soanum = getnum_str(&startp, endp);
+ if (soanum < 0)
+ return (-1);
+ PUTLONG(soanum, cp);
+ }
+ if (multiline) {
+ while (isspace(*startp) || !*startp)
+ startp++;
+ if (*startp != ')')
+ return (-1);
+ }
+ }
+ break;
+ case T_MX:
+ case T_AFSDB:
+ case T_RT:
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ case T_SRV:
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, NULL, NULL);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ case T_PX:
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ PUTSHORT(n, cp);
+ ShrinkBuffer(INT16SZ);
+ for (i = 0; i < 2; i++) {
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs,
+ lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ }
+ break;
+ case T_WKS: {
+ char bm[MAXPORT/8];
+ unsigned int maxbm = 0;
+
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if (!inet_aton(buf2, &ina))
+ return (-1);
+ n1 = ntohl(ina.s_addr);
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(n1, cp);
+
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if ((i = res_protocolnumber(buf2)) < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = i & 0xff;
+
+ for (i = 0; i < MAXPORT/8 ; i++)
+ bm[i] = 0;
+
+ while (getword_str(buf2, sizeof buf2, &startp, endp)) {
+ if ((n = res_servicenumber(buf2)) <= 0)
+ return (-1);
+
+ if (n < MAXPORT) {
+ bm[n/8] |= (0x80>>(n%8));
+ if ((unsigned)n > maxbm)
+ maxbm = n;
+ } else
+ return (-1);
+ }
+ maxbm = maxbm/8 + 1;
+ ShrinkBuffer(maxbm);
+ memcpy(cp, bm, maxbm);
+ cp += maxbm;
+ break;
+ }
+ case T_HINFO:
+ for (i = 0; i < 2; i++) {
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ }
+ break;
+ case T_TXT:
+ for (;;) {
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0) {
+ if (cp != (sp2 + INT16SZ))
+ break;
+ return (-1);
+ }
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ }
+ break;
+ case T_X25:
+ /* RFC1183 */
+ if ((n = getstr_str(buf2, sizeof buf2, &startp,
+ endp)) < 0)
+ return (-1);
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ break;
+ case T_ISDN:
+ /* RFC1183 */
+ if ((n = getstr_str(buf2, sizeof buf2, &startp,
+ endp)) < 0)
+ return (-1);
+ if ((n > 255) || (n == 0))
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ if ((n = getstr_str(buf2, sizeof buf2, &startp,
+ endp)) < 0)
+ n = 0;
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ break;
+ case T_NSAP:
+ if ((n = inet_nsap_addr((char *)startp, (u_char *)buf2, sizeof(buf2))) != 0) {
+ ShrinkBuffer(n);
+ memcpy(cp, buf2, n);
+ cp += n;
+ } else {
+ return (-1);
+ }
+ break;
+ case T_LOC:
+ if ((n = loc_aton((char *)startp, (u_char *)buf2)) != 0) {
+ ShrinkBuffer(n);
+ memcpy(cp, buf2, n);
+ cp += n;
+ } else
+ return (-1);
+ break;
+ case ns_t_sig:
+#ifdef _LIBC
+ return (-1);
+#else
+ {
+ int sig_type, success, dateerror;
+ u_int32_t exptime, timesigned;
+
+ /* type */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ sig_type = sym_ston(__p_type_syms, buf2, &success);
+ if (!success || sig_type == ns_t_any)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(sig_type, cp);
+ /* alg */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* labels */
+ n = getnum_str(&startp, endp);
+ if (n <= 0 || n > 255)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* ottl & expire */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ exptime = ns_datetosecs(buf2, &dateerror);
+ if (!dateerror) {
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(rttl, cp);
+ }
+ else {
+ char *ulendp;
+ u_int32_t ottl;
+
+ errno = 0;
+ ottl = strtoul(buf2, &ulendp, 10);
+ if (errno != 0 ||
+ (ulendp != NULL && *ulendp != '\0'))
+ return (-1);
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(ottl, cp);
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ return (-1);
+ exptime = ns_datetosecs(buf2, &dateerror);
+ if (dateerror)
+ return (-1);
+ }
+ /* expire */
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(exptime, cp);
+ /* timesigned */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ timesigned = ns_datetosecs(buf2, &dateerror);
+ if (!dateerror) {
+ ShrinkBuffer(INT32SZ);
+ PUTLONG(timesigned, cp);
+ }
+ else
+ return (-1);
+ /* footprint */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* signer name */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, dnptrs, lastdnptr);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ /* sig */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ siglen = b64_pton(buf2, buf3, sizeof(buf3));
+ if (siglen < 0)
+ return (-1);
+ ShrinkBuffer(siglen);
+ memcpy(cp, buf3, siglen);
+ cp += siglen;
+ break;
+ }
+#endif
+ case ns_t_key:
+ /* flags */
+ n = gethexnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* proto */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* alg */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* key */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ keylen = b64_pton(buf2, buf3, sizeof(buf3));
+ if (keylen < 0)
+ return (-1);
+ ShrinkBuffer(keylen);
+ memcpy(cp, buf3, keylen);
+ cp += keylen;
+ break;
+ case ns_t_nxt:
+ {
+ int success, nxt_type;
+ u_char data[32];
+ int maxtype;
+
+ /* next name */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, NULL, NULL);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ maxtype = 0;
+ memset(data, 0, sizeof data);
+ for (;;) {
+ if (!getword_str(buf2, sizeof buf2, &startp,
+ endp))
+ break;
+ nxt_type = sym_ston(__p_type_syms, buf2,
+ &success);
+ if (!success || !ns_t_rr_p(nxt_type))
+ return (-1);
+ NS_NXT_BIT_SET(nxt_type, data);
+ if (nxt_type > maxtype)
+ maxtype = nxt_type;
+ }
+ n = maxtype/NS_NXT_BITS+1;
+ ShrinkBuffer(n);
+ memcpy(cp, data, n);
+ cp += n;
+ break;
+ }
+ case ns_t_cert:
+ /* type */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* key tag */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* alg */
+ n = getnum_str(&startp, endp);
+ if (n < 0)
+ return (-1);
+ ShrinkBuffer(1);
+ *cp++ = n;
+ /* cert */
+ if ((n = getword_str(buf2, sizeof buf2,
+ &startp, endp)) < 0)
+ return (-1);
+ certlen = b64_pton(buf2, buf3, sizeof(buf3));
+ if (certlen < 0)
+ return (-1);
+ ShrinkBuffer(certlen);
+ memcpy(cp, buf3, certlen);
+ cp += certlen;
+ break;
+ case ns_t_aaaa:
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ if (inet_pton(AF_INET6, buf2, &in6a) <= 0)
+ return (-1);
+ ShrinkBuffer(NS_IN6ADDRSZ);
+ memcpy(cp, &in6a, NS_IN6ADDRSZ);
+ cp += NS_IN6ADDRSZ;
+ break;
+ case ns_t_naptr:
+ /* Order Preference Flags Service Replacement Regexp */
+ /* Order */
+ n = getnum_str(&startp, endp);
+ if (n < 0 || n > 65535)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* Preference */
+ n = getnum_str(&startp, endp);
+ if (n < 0 || n > 65535)
+ return (-1);
+ ShrinkBuffer(INT16SZ);
+ PUTSHORT(n, cp);
+ /* Flags */
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0) {
+ return (-1);
+ }
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ /* Service Classes */
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0) {
+ return (-1);
+ }
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ /* Pattern */
+ if ((n = getstr_str(buf2, sizeof buf2,
+ &startp, endp)) < 0) {
+ return (-1);
+ }
+ if (n > 255)
+ return (-1);
+ ShrinkBuffer(n+1);
+ *cp++ = n;
+ memcpy(cp, buf2, n);
+ cp += n;
+ /* Replacement */
+ if (!getword_str(buf2, sizeof buf2, &startp, endp))
+ return (-1);
+ n = dn_comp(buf2, cp, buflen, NULL, NULL);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ ShrinkBuffer(n);
+ break;
+ default:
+ return (-1);
+ } /*switch*/
+ n = (u_int16_t)((cp - sp2) - INT16SZ);
+ PUTSHORT(n, sp2);
+ } /*for*/
+
+ hp->qdcount = htons(counts[0]);
+ hp->ancount = htons(counts[1]);
+ hp->nscount = htons(counts[2]);
+ hp->arcount = htons(counts[3]);
+ return (cp - buf);
+}
+
+/*%
+ * Get a whitespace delimited word from a string (not file)
+ * into buf. modify the start pointer to point after the
+ * word in the string.
+ */
+static int
+getword_str(char *buf, int size, u_char **startpp, u_char *endp) {
+ char *cp;
+ int c;
+
+ for (cp = buf; *startpp <= endp; ) {
+ c = **startpp;
+ if (isspace(c) || c == '\0') {
+ if (cp != buf) /*%< trailing whitespace */
+ break;
+ else { /*%< leading whitespace */
+ (*startpp)++;
+ continue;
+ }
+ }
+ (*startpp)++;
+ if (cp >= buf+size-1)
+ break;
+ *cp++ = (u_char)c;
+ }
+ *cp = '\0';
+ return (cp != buf);
+}
+
+/*%
+ * get a white spae delimited string from memory. Process quoted strings
+ * and \\DDD escapes. Return length or -1 on error. Returned string may
+ * contain nulls.
+ */
+static char digits[] = "0123456789";
+static int
+getstr_str(char *buf, int size, u_char **startpp, u_char *endp) {
+ char *cp;
+ int c, c1 = 0;
+ int inquote = 0;
+ int seen_quote = 0;
+ int escape = 0;
+ int dig = 0;
+
+ for (cp = buf; *startpp <= endp; ) {
+ if ((c = **startpp) == '\0')
+ break;
+ /* leading white space */
+ if ((cp == buf) && !seen_quote && isspace(c)) {
+ (*startpp)++;
+ continue;
+ }
+
+ switch (c) {
+ case '\\':
+ if (!escape) {
+ escape = 1;
+ dig = 0;
+ c1 = 0;
+ (*startpp)++;
+ continue;
+ }
+ goto do_escape;
+ case '"':
+ if (!escape) {
+ inquote = !inquote;
+ seen_quote = 1;
+ (*startpp)++;
+ continue;
+ }
+ /* fall through */
+ default:
+ do_escape:
+ if (escape) {
+ switch (c) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ c1 = c1 * 10 +
+ (strchr(digits, c) - digits);
+
+ if (++dig == 3) {
+ c = c1 &0xff;
+ break;
+ }
+ (*startpp)++;
+ continue;
+ }
+ escape = 0;
+ } else if (!inquote && isspace(c))
+ goto done;
+ if (cp >= buf+size-1)
+ goto done;
+ *cp++ = (u_char)c;
+ (*startpp)++;
+ }
+ }
+ done:
+ *cp = '\0';
+ return ((cp == buf)? (seen_quote? 0: -1): (cp - buf));
+}
+
+/*%
+ * Get a whitespace delimited base 16 number from a string (not file) into buf
+ * update the start pointer to point after the number in the string.
+ */
+static int
+gethexnum_str(u_char **startpp, u_char *endp) {
+ int c, n;
+ int seendigit = 0;
+ int m = 0;
+
+ if (*startpp + 2 >= endp || strncasecmp((char *)*startpp, "0x", 2) != 0)
+ return getnum_str(startpp, endp);
+ (*startpp)+=2;
+ for (n = 0; *startpp <= endp; ) {
+ c = **startpp;
+ if (isspace(c) || c == '\0') {
+ if (seendigit) /*%< trailing whitespace */
+ break;
+ else { /*%< leading whitespace */
+ (*startpp)++;
+ continue;
+ }
+ }
+ if (c == ';') {
+ while ((*startpp <= endp) &&
+ ((c = **startpp) != '\n'))
+ (*startpp)++;
+ if (seendigit)
+ break;
+ continue;
+ }
+ if (!isxdigit(c)) {
+ if (c == ')' && seendigit) {
+ (*startpp)--;
+ break;
+ }
+ return (-1);
+ }
+ (*startpp)++;
+ if (isdigit(c))
+ n = n * 16 + (c - '0');
+ else
+ n = n * 16 + (tolower(c) - 'a' + 10);
+ seendigit = 1;
+ }
+ return (n + m);
+}
+
+/*%
+ * Get a whitespace delimited base 10 number from a string (not file) into buf
+ * update the start pointer to point after the number in the string.
+ */
+static int
+getnum_str(u_char **startpp, u_char *endp) {
+ int c, n;
+ int seendigit = 0;
+ int m = 0;
+
+ for (n = 0; *startpp <= endp; ) {
+ c = **startpp;
+ if (isspace(c) || c == '\0') {
+ if (seendigit) /*%< trailing whitespace */
+ break;
+ else { /*%< leading whitespace */
+ (*startpp)++;
+ continue;
+ }
+ }
+ if (c == ';') {
+ while ((*startpp <= endp) &&
+ ((c = **startpp) != '\n'))
+ (*startpp)++;
+ if (seendigit)
+ break;
+ continue;
+ }
+ if (!isdigit(c)) {
+ if (c == ')' && seendigit) {
+ (*startpp)--;
+ break;
+ }
+ return (-1);
+ }
+ (*startpp)++;
+ n = n * 10 + (c - '0');
+ seendigit = 1;
+ }
+ return (n + m);
+}
+
+/*%
+ * Allocate a resource record buffer & save rr info.
+ */
+ns_updrec *
+res_mkupdrec(int section, const char *dname,
+ u_int class, u_int type, u_long ttl) {
+ ns_updrec *rrecp = (ns_updrec *)calloc(1, sizeof(ns_updrec));
+
+ if (!rrecp || !(rrecp->r_dname = strdup(dname))) {
+ if (rrecp)
+ free((char *)rrecp);
+ return (NULL);
+ }
+ INIT_LINK(rrecp, r_link);
+ INIT_LINK(rrecp, r_glink);
+ rrecp->r_class = (ns_class)class;
+ rrecp->r_type = (ns_type)type;
+ rrecp->r_ttl = ttl;
+ rrecp->r_section = (ns_sect)section;
+ return (rrecp);
+}
+
+/*%
+ * Free a resource record buffer created by res_mkupdrec.
+ */
+void
+res_freeupdrec(ns_updrec *rrecp) {
+ /* Note: freeing r_dp is the caller's responsibility. */
+ if (rrecp->r_dname != NULL)
+ free(rrecp->r_dname);
+ free(rrecp);
+}
+
+struct valuelist {
+ struct valuelist * next;
+ struct valuelist * prev;
+ char * name;
+ char * proto;
+ int port;
+};
+static struct valuelist *servicelist, *protolist;
+
+static void
+res_buildservicelist() {
+ struct servent *sp;
+ struct valuelist *slp;
+
+#ifdef MAYBE_HESIOD
+ setservent(0);
+#else
+ setservent(1);
+#endif
+ while ((sp = getservent()) != NULL) {
+ slp = (struct valuelist *)malloc(sizeof(struct valuelist));
+ if (!slp)
+ break;
+ slp->name = strdup(sp->s_name);
+ slp->proto = strdup(sp->s_proto);
+ if ((slp->name == NULL) || (slp->proto == NULL)) {
+ if (slp->name) free(slp->name);
+ if (slp->proto) free(slp->proto);
+ free(slp);
+ break;
+ }
+ slp->port = ntohs((u_int16_t)sp->s_port); /*%< host byt order */
+ slp->next = servicelist;
+ slp->prev = NULL;
+ if (servicelist)
+ servicelist->prev = slp;
+ servicelist = slp;
+ }
+ endservent();
+}
+
+#ifndef _LIBC
+void
+res_destroyservicelist() {
+ struct valuelist *slp, *slp_next;
+
+ for (slp = servicelist; slp != NULL; slp = slp_next) {
+ slp_next = slp->next;
+ free(slp->name);
+ free(slp->proto);
+ free(slp);
+ }
+ servicelist = (struct valuelist *)0;
+}
+#endif
+
+#ifdef _LIBC
+static
+#endif
+void
+res_buildprotolist(void) {
+ struct protoent *pp;
+ struct valuelist *slp;
+
+#ifdef MAYBE_HESIOD
+ setprotoent(0);
+#else
+ setprotoent(1);
+#endif
+ while ((pp = getprotoent()) != NULL) {
+ slp = (struct valuelist *)malloc(sizeof(struct valuelist));
+ if (!slp)
+ break;
+ slp->name = strdup(pp->p_name);
+ if (slp->name == NULL) {
+ free(slp);
+ break;
+ }
+ slp->port = pp->p_proto; /*%< host byte order */
+ slp->next = protolist;
+ slp->prev = NULL;
+ if (protolist)
+ protolist->prev = slp;
+ protolist = slp;
+ }
+ endprotoent();
+}
+
+#ifndef _LIBC
+void
+res_destroyprotolist(void) {
+ struct valuelist *plp, *plp_next;
+
+ for (plp = protolist; plp != NULL; plp = plp_next) {
+ plp_next = plp->next;
+ free(plp->name);
+ free(plp);
+ }
+ protolist = (struct valuelist *)0;
+}
+#endif
+
+static int
+findservice(const char *s, struct valuelist **list) {
+ struct valuelist *lp = *list;
+ int n;
+
+ for (; lp != NULL; lp = lp->next)
+ if (strcasecmp(lp->name, s) == 0) {
+ if (lp != *list) {
+ lp->prev->next = lp->next;
+ if (lp->next)
+ lp->next->prev = lp->prev;
+ (*list)->prev = lp;
+ lp->next = *list;
+ *list = lp;
+ }
+ return (lp->port); /*%< host byte order */
+ }
+ if (sscanf(s, "%d", &n) != 1 || n <= 0)
+ n = -1;
+ return (n);
+}
+
+/*%
+ * Convert service name or (ascii) number to int.
+ */
+#ifdef _LIBC
+static
+#endif
+int
+res_servicenumber(const char *p) {
+ if (servicelist == (struct valuelist *)0)
+ res_buildservicelist();
+ return (findservice(p, &servicelist));
+}
+
+/*%
+ * Convert protocol name or (ascii) number to int.
+ */
+#ifdef _LIBC
+static
+#endif
+int
+res_protocolnumber(const char *p) {
+ if (protolist == (struct valuelist *)0)
+ res_buildprotolist();
+ return (findservice(p, &protolist));
+}
+
+#ifndef _LIBC
+static struct servent *
+cgetservbyport(u_int16_t port, const char *proto) { /*%< Host byte order. */
+ struct valuelist **list = &servicelist;
+ struct valuelist *lp = *list;
+ static struct servent serv;
+
+ port = ntohs(port);
+ for (; lp != NULL; lp = lp->next) {
+ if (port != (u_int16_t)lp->port) /*%< Host byte order. */
+ continue;
+ if (strcasecmp(lp->proto, proto) == 0) {
+ if (lp != *list) {
+ lp->prev->next = lp->next;
+ if (lp->next)
+ lp->next->prev = lp->prev;
+ (*list)->prev = lp;
+ lp->next = *list;
+ *list = lp;
+ }
+ serv.s_name = lp->name;
+ serv.s_port = htons((u_int16_t)lp->port);
+ serv.s_proto = lp->proto;
+ return (&serv);
+ }
+ }
+ return (0);
+}
+
+static struct protoent *
+cgetprotobynumber(int proto) { /*%< Host byte order. */
+ struct valuelist **list = &protolist;
+ struct valuelist *lp = *list;
+ static struct protoent prot;
+
+ for (; lp != NULL; lp = lp->next)
+ if (lp->port == proto) { /*%< Host byte order. */
+ if (lp != *list) {
+ lp->prev->next = lp->next;
+ if (lp->next)
+ lp->next->prev = lp->prev;
+ (*list)->prev = lp;
+ lp->next = *list;
+ *list = lp;
+ }
+ prot.p_name = lp->name;
+ prot.p_proto = lp->port; /*%< Host byte order. */
+ return (&prot);
+ }
+ return (0);
+}
+
+const char *
+res_protocolname(int num) {
+ static char number[8];
+ struct protoent *pp;
+
+ if (protolist == (struct valuelist *)0)
+ res_buildprotolist();
+ pp = cgetprotobynumber(num);
+ if (pp == 0) {
+ (void) sprintf(number, "%d", num);
+ return (number);
+ }
+ return (pp->p_name);
+}
+
+const char *
+res_servicename(u_int16_t port, const char *proto) { /*%< Host byte order. */
+ static char number[8];
+ struct servent *ss;
+
+ if (servicelist == (struct valuelist *)0)
+ res_buildservicelist();
+ ss = cgetservbyport(htons(port), proto);
+ if (ss == 0) {
+ (void) sprintf(number, "%d", port);
+ return (number);
+ }
+ return (ss->s_name);
+}
+#endif
diff --git a/lib/libc/resolv/res_private.h b/lib/libc/resolv/res_private.h
new file mode 100644
index 0000000..4e98157
--- /dev/null
+++ b/lib/libc/resolv/res_private.h
@@ -0,0 +1,22 @@
+#ifndef res_private_h
+#define res_private_h
+
+struct __res_state_ext {
+ union res_sockaddr_union nsaddrs[MAXNS];
+ struct sort_list {
+ int af;
+ union {
+ struct in_addr ina;
+ struct in6_addr in6a;
+ } addr, mask;
+ } sort_list[MAXRESOLVSORT];
+ char nsuffix[64];
+ char nsuffix2[64];
+};
+
+extern int
+res_ourserver_p(const res_state statp, const struct sockaddr *sa);
+
+#endif
+
+/*! \file */
diff --git a/lib/libc/resolv/res_query.c b/lib/libc/resolv/res_query.c
new file mode 100644
index 0000000..746a2be
--- /dev/null
+++ b/lib/libc/resolv/res_query.c
@@ -0,0 +1,489 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_query.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_query.c,v 1.7.18.2 2008/04/03 23:15:15 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+#include <ctype.h>
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "port_after.h"
+
+/* Options. Leave them on. */
+#define DEBUG
+
+#if PACKETSZ > 1024
+#define MAXPACKET PACKETSZ
+#else
+#define MAXPACKET 1024
+#endif
+
+/*%
+ * Formulate a normal query, send, and await answer.
+ * Returned answer is placed in supplied buffer "answer".
+ * Perform preliminary check of answer, returning success only
+ * if no error is indicated and the answer count is nonzero.
+ * Return the size of the response on success, -1 on error.
+ * Error number is left in H_ERRNO.
+ *
+ * Caller must parse answer and determine whether it answers the question.
+ */
+int
+res_nquery(res_state statp,
+ const char *name, /*%< domain name */
+ int class, int type, /*%< class and type of query */
+ u_char *answer, /*%< buffer to put answer */
+ int anslen) /*%< size of answer buffer */
+{
+ u_char buf[MAXPACKET];
+ HEADER *hp = (HEADER *) answer;
+ u_int oflags;
+ u_char *rdata;
+ int n;
+
+ oflags = statp->_flags;
+
+again:
+ hp->rcode = NOERROR; /*%< default */
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_query(%s, %d, %d)\n", name, class, type);
+#endif
+
+ n = res_nmkquery(statp, QUERY, name, class, type, NULL, 0, NULL,
+ buf, sizeof(buf));
+#ifdef RES_USE_EDNS0
+ if (n > 0 && (statp->_flags & RES_F_EDNS0ERR) == 0 &&
+ (statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC|RES_NSID))) {
+ n = res_nopt(statp, n, buf, sizeof(buf), anslen);
+ rdata = &buf[n];
+ if (n > 0 && (statp->options & RES_NSID) != 0U) {
+ n = res_nopt_rdata(statp, n, buf, sizeof(buf), rdata,
+ NS_OPT_NSID, 0, NULL);
+ }
+ }
+#endif
+ if (n <= 0) {
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_query: mkquery failed\n");
+#endif
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (n);
+ }
+
+ n = res_nsend(statp, buf, n, answer, anslen);
+ if (n < 0) {
+#ifdef RES_USE_EDNS0
+ /* if the query choked with EDNS0, retry without EDNS0 */
+ if ((statp->options & (RES_USE_EDNS0|RES_USE_DNSSEC)) != 0U &&
+ ((oflags ^ statp->_flags) & RES_F_EDNS0ERR) != 0) {
+ statp->_flags |= RES_F_EDNS0ERR;
+ if (statp->options & RES_DEBUG)
+ printf(";; res_nquery: retry without EDNS0\n");
+ goto again;
+ }
+#endif
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_query: send error\n");
+#endif
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (n);
+ }
+
+ if (hp->rcode != NOERROR || ntohs(hp->ancount) == 0) {
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; rcode = (%s), counts = an:%d ns:%d ar:%d\n",
+ p_rcode(hp->rcode),
+ ntohs(hp->ancount),
+ ntohs(hp->nscount),
+ ntohs(hp->arcount));
+#endif
+ switch (hp->rcode) {
+ case NXDOMAIN:
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND);
+ break;
+ case SERVFAIL:
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ break;
+ case NOERROR:
+ RES_SET_H_ERRNO(statp, NO_DATA);
+ break;
+ case FORMERR:
+ case NOTIMP:
+ case REFUSED:
+ default:
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ break;
+ }
+ return (-1);
+ }
+ return (n);
+}
+
+/*%
+ * Formulate a normal query, send, and retrieve answer in supplied buffer.
+ * Return the size of the response on success, -1 on error.
+ * If enabled, implement search rules until answer or unrecoverable failure
+ * is detected. Error code, if any, is left in H_ERRNO.
+ */
+int
+res_nsearch(res_state statp,
+ const char *name, /*%< domain name */
+ int class, int type, /*%< class and type of query */
+ u_char *answer, /*%< buffer to put answer */
+ int anslen) /*%< size of answer */
+{
+ const char *cp, * const *domain;
+ HEADER *hp = (HEADER *) answer;
+ char tmp[NS_MAXDNAME];
+ u_int dots;
+ int trailing_dot, ret, saved_herrno;
+ int got_nodata = 0, got_servfail = 0, root_on_list = 0;
+ int tried_as_is = 0;
+ int searched = 0;
+
+ errno = 0;
+ RES_SET_H_ERRNO(statp, HOST_NOT_FOUND); /*%< True if we never query. */
+ dots = 0;
+ for (cp = name; *cp != '\0'; cp++)
+ dots += (*cp == '.');
+ trailing_dot = 0;
+ if (cp > name && *--cp == '.')
+ trailing_dot++;
+
+ /* If there aren't any dots, it could be a user-level alias. */
+ if (!dots && (cp = res_hostalias(statp, name, tmp, sizeof tmp))!= NULL)
+ return (res_nquery(statp, cp, class, type, answer, anslen));
+
+ /*
+ * If there are enough dots in the name, let's just give it a
+ * try 'as is'. The threshold can be set with the "ndots" option.
+ * Also, query 'as is', if there is a trailing dot in the name.
+ */
+ saved_herrno = -1;
+ if (dots >= statp->ndots || trailing_dot) {
+ ret = res_nquerydomain(statp, name, NULL, class, type,
+ answer, anslen);
+ if (ret > 0 || trailing_dot)
+ return (ret);
+ if (errno == ECONNREFUSED) {
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (-1);
+ }
+ switch (statp->res_h_errno) {
+ case NO_DATA:
+ case HOST_NOT_FOUND:
+ break;
+ case TRY_AGAIN:
+ if (hp->rcode == SERVFAIL)
+ break;
+ /* FALLTHROUGH */
+ default:
+ return (-1);
+ }
+ saved_herrno = statp->res_h_errno;
+ tried_as_is++;
+ }
+
+ /*
+ * We do at least one level of search if
+ * - there is no dot and RES_DEFNAME is set, or
+ * - there is at least one dot, there is no trailing dot,
+ * and RES_DNSRCH is set.
+ */
+ if ((!dots && (statp->options & RES_DEFNAMES) != 0U) ||
+ (dots && !trailing_dot && (statp->options & RES_DNSRCH) != 0U)) {
+ int done = 0;
+
+ for (domain = (const char * const *)statp->dnsrch;
+ *domain && !done;
+ domain++) {
+ searched = 1;
+
+ if (domain[0][0] == '\0' ||
+ (domain[0][0] == '.' && domain[0][1] == '\0'))
+ root_on_list++;
+
+ if (root_on_list && tried_as_is)
+ continue;
+
+ ret = res_nquerydomain(statp, name, *domain,
+ class, type,
+ answer, anslen);
+ if (ret > 0)
+ return (ret);
+
+ /*
+ * If no server present, give up.
+ * If name isn't found in this domain,
+ * keep trying higher domains in the search list
+ * (if that's enabled).
+ * On a NO_DATA error, keep trying, otherwise
+ * a wildcard entry of another type could keep us
+ * from finding this entry higher in the domain.
+ * If we get some other error (negative answer or
+ * server failure), then stop searching up,
+ * but try the input name below in case it's
+ * fully-qualified.
+ */
+ if (errno == ECONNREFUSED) {
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (-1);
+ }
+
+ switch (statp->res_h_errno) {
+ case NO_DATA:
+ got_nodata++;
+ /* FALLTHROUGH */
+ case HOST_NOT_FOUND:
+ /* keep trying */
+ break;
+ case TRY_AGAIN:
+ /*
+ * This can occur due to a server failure
+ * (that is, all listed servers have failed),
+ * or all listed servers have timed out.
+ * ((HEADER *)answer)->rcode may not be set
+ * to SERVFAIL in the case of a timeout.
+ *
+ * Either way we must return TRY_AGAIN in
+ * order to avoid non-deterministic
+ * return codes.
+ * For example, loaded name servers or races
+ * against network startup/validation (dhcp,
+ * ppp, etc) can cause the search to timeout
+ * on one search element, e.g. 'fu.bar.com',
+ * and return a definitive failure on the
+ * next search element, e.g. 'fu.'.
+ */
+ got_servfail++;
+ if (hp->rcode == SERVFAIL) {
+ /* try next search element, if any */
+ break;
+ }
+ /* FALLTHROUGH */
+ default:
+ /* anything else implies that we're done */
+ done++;
+ }
+
+ /* if we got here for some reason other than DNSRCH,
+ * we only wanted one iteration of the loop, so stop.
+ */
+ if ((statp->options & RES_DNSRCH) == 0U)
+ done++;
+ }
+ }
+
+ switch (statp->res_h_errno) {
+ case NO_DATA:
+ case HOST_NOT_FOUND:
+ break;
+ case TRY_AGAIN:
+ if (hp->rcode == SERVFAIL)
+ break;
+ /* FALLTHROUGH */
+ default:
+ goto giveup;
+ }
+
+ /*
+ * If the query has not already been tried as is then try it
+ * unless RES_NOTLDQUERY is set and there were no dots.
+ */
+ if ((dots || !searched || (statp->options & RES_NOTLDQUERY) == 0U) &&
+ !(tried_as_is || root_on_list)) {
+ ret = res_nquerydomain(statp, name, NULL, class, type,
+ answer, anslen);
+ if (ret > 0)
+ return (ret);
+ }
+
+ /* if we got here, we didn't satisfy the search.
+ * if we did an initial full query, return that query's H_ERRNO
+ * (note that we wouldn't be here if that query had succeeded).
+ * else if we ever got a nodata, send that back as the reason.
+ * else send back meaningless H_ERRNO, that being the one from
+ * the last DNSRCH we did.
+ */
+giveup:
+ if (saved_herrno != -1)
+ RES_SET_H_ERRNO(statp, saved_herrno);
+ else if (got_nodata)
+ RES_SET_H_ERRNO(statp, NO_DATA);
+ else if (got_servfail)
+ RES_SET_H_ERRNO(statp, TRY_AGAIN);
+ return (-1);
+}
+
+/*%
+ * Perform a call on res_query on the concatenation of name and domain,
+ * removing a trailing dot from name if domain is NULL.
+ */
+int
+res_nquerydomain(res_state statp,
+ const char *name,
+ const char *domain,
+ int class, int type, /*%< class and type of query */
+ u_char *answer, /*%< buffer to put answer */
+ int anslen) /*%< size of answer */
+{
+ char nbuf[MAXDNAME];
+ const char *longname = nbuf;
+ int n, d;
+
+#ifdef DEBUG
+ if (statp->options & RES_DEBUG)
+ printf(";; res_nquerydomain(%s, %s, %d, %d)\n",
+ name, domain?domain:"<Nil>", class, type);
+#endif
+ if (domain == NULL) {
+ /*
+ * Check for trailing '.';
+ * copy without '.' if present.
+ */
+ n = strlen(name);
+ if (n >= MAXDNAME) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ n--;
+ if (n >= 0 && name[n] == '.') {
+ strncpy(nbuf, name, n);
+ nbuf[n] = '\0';
+ } else
+ longname = name;
+ } else {
+ n = strlen(name);
+ d = strlen(domain);
+ if (n + d + 1 >= MAXDNAME) {
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ return (-1);
+ }
+ sprintf(nbuf, "%s.%s", name, domain);
+ }
+ return (res_nquery(statp, longname, class, type, answer, anslen));
+}
+
+const char *
+res_hostalias(const res_state statp, const char *name, char *dst, size_t siz) {
+ char *file, *cp1, *cp2;
+ char buf[BUFSIZ];
+ FILE *fp;
+
+ if (statp->options & RES_NOALIASES)
+ return (NULL);
+ if (issetugid())
+ return (NULL);
+ file = getenv("HOSTALIASES");
+ if (file == NULL || (fp = fopen(file, "r")) == NULL)
+ return (NULL);
+ setbuf(fp, NULL);
+ buf[sizeof(buf) - 1] = '\0';
+ while (fgets(buf, sizeof(buf), fp)) {
+ for (cp1 = buf; *cp1 && !isspace((unsigned char)*cp1); ++cp1)
+ ;
+ if (!*cp1)
+ break;
+ *cp1 = '\0';
+ if (ns_samename(buf, name) == 1) {
+ while (isspace((unsigned char)*++cp1))
+ ;
+ if (!*cp1)
+ break;
+ for (cp2 = cp1 + 1; *cp2 &&
+ !isspace((unsigned char)*cp2); ++cp2)
+ ;
+ *cp2 = '\0';
+ strncpy(dst, cp1, siz - 1);
+ dst[siz - 1] = '\0';
+ fclose(fp);
+ return (dst);
+ }
+ }
+ fclose(fp);
+ return (NULL);
+}
+
+/*! \file */
diff --git a/lib/libc/resolv/res_send.c b/lib/libc/resolv/res_send.c
new file mode 100644
index 0000000..716ae32
--- /dev/null
+++ b/lib/libc/resolv/res_send.c
@@ -0,0 +1,1179 @@
+/*
+ * Copyright (c) 1985, 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Portions Copyright (c) 1993 by Digital Equipment Corporation.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies, and that
+ * the name of Digital Equipment Corporation not be used in advertising or
+ * publicity pertaining to distribution of the document or software without
+ * specific, written prior permission.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND DIGITAL EQUIPMENT CORP. DISCLAIMS ALL
+ * WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL DIGITAL EQUIPMENT
+ * CORPORATION BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
+ * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
+ * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
+ * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+ * SOFTWARE.
+ */
+
+/*
+ * Copyright (c) 2005 by Internet Systems Consortium, Inc. ("ISC")
+ * Portions Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)res_send.c 8.1 (Berkeley) 6/4/93";
+static const char rcsid[] = "$Id: res_send.c,v 1.9.18.10 2008/01/27 02:06:26 marka Exp $";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*! \file
+ * \brief
+ * Send query to name server and wait for reply.
+ */
+
+#include "port_before.h"
+#ifndef USE_KQUEUE
+#include "fd_setsize.h"
+#endif
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/uio.h>
+
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <resolv.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <isc/eventlib.h>
+
+#include "port_after.h"
+
+#ifdef USE_KQUEUE
+#include <sys/event.h>
+#else
+#ifdef USE_POLL
+#ifdef HAVE_STROPTS_H
+#include <stropts.h>
+#endif
+#include <poll.h>
+#endif /* USE_POLL */
+#endif
+
+#include "un-namespace.h"
+
+/* Options. Leave them on. */
+#define DEBUG
+#include "res_debug.h"
+#include "res_private.h"
+
+#define EXT(res) ((res)->_u._ext)
+
+#if !defined(USE_POLL) && !defined(USE_KQUEUE)
+static const int highestFD = FD_SETSIZE - 1;
+#endif
+
+/* Forward. */
+
+static int get_salen(const struct sockaddr *);
+static struct sockaddr * get_nsaddr(res_state, size_t);
+static int send_vc(res_state, const u_char *, int,
+ u_char *, int, int *, int);
+static int send_dg(res_state,
+#ifdef USE_KQUEUE
+ int kq,
+#endif
+ const u_char *, int,
+ u_char *, int, int *, int, int,
+ int *, int *);
+static void Aerror(const res_state, FILE *, const char *, int,
+ const struct sockaddr *, int);
+static void Perror(const res_state, FILE *, const char *, int);
+static int sock_eq(struct sockaddr *, struct sockaddr *);
+#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE)
+static int pselect(int, void *, void *, void *,
+ struct timespec *,
+ const sigset_t *);
+#endif
+void res_pquery(const res_state, const u_char *, int, FILE *);
+
+static const int niflags = NI_NUMERICHOST | NI_NUMERICSERV;
+
+/* Public. */
+
+/*%
+ * looks up "ina" in _res.ns_addr_list[]
+ *
+ * returns:
+ *\li 0 : not found
+ *\li >0 : found
+ *
+ * author:
+ *\li paul vixie, 29may94
+ */
+int
+res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
+ const struct sockaddr_in *inp, *srv;
+ const struct sockaddr_in6 *in6p, *srv6;
+ int ns;
+
+ switch (sa->sa_family) {
+ case AF_INET:
+ inp = (const struct sockaddr_in *)sa;
+ for (ns = 0; ns < statp->nscount; ns++) {
+ srv = (struct sockaddr_in *)get_nsaddr(statp, ns);
+ if (srv->sin_family == inp->sin_family &&
+ srv->sin_port == inp->sin_port &&
+ (srv->sin_addr.s_addr == INADDR_ANY ||
+ srv->sin_addr.s_addr == inp->sin_addr.s_addr))
+ return (1);
+ }
+ break;
+ case AF_INET6:
+ if (EXT(statp).ext == NULL)
+ break;
+ in6p = (const struct sockaddr_in6 *)sa;
+ for (ns = 0; ns < statp->nscount; ns++) {
+ srv6 = (struct sockaddr_in6 *)get_nsaddr(statp, ns);
+ if (srv6->sin6_family == in6p->sin6_family &&
+ srv6->sin6_port == in6p->sin6_port &&
+#ifdef HAVE_SIN6_SCOPE_ID
+ (srv6->sin6_scope_id == 0 ||
+ srv6->sin6_scope_id == in6p->sin6_scope_id) &&
+#endif
+ (IN6_IS_ADDR_UNSPECIFIED(&srv6->sin6_addr) ||
+ IN6_ARE_ADDR_EQUAL(&srv6->sin6_addr, &in6p->sin6_addr)))
+ return (1);
+ }
+ break;
+ default:
+ break;
+ }
+ return (0);
+}
+
+/*%
+ * look for (name,type,class) in the query section of packet (buf,eom)
+ *
+ * requires:
+ *\li buf + HFIXEDSZ <= eom
+ *
+ * returns:
+ *\li -1 : format error
+ *\li 0 : not found
+ *\li >0 : found
+ *
+ * author:
+ *\li paul vixie, 29may94
+ */
+int
+res_nameinquery(const char *name, int type, int class,
+ const u_char *buf, const u_char *eom)
+{
+ const u_char *cp = buf + HFIXEDSZ;
+ int qdcount = ntohs(((const HEADER*)buf)->qdcount);
+
+ while (qdcount-- > 0) {
+ char tname[MAXDNAME+1];
+ int n, ttype, tclass;
+
+ n = dn_expand(buf, eom, cp, tname, sizeof tname);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ if (cp + 2 * INT16SZ > eom)
+ return (-1);
+ ttype = ns_get16(cp); cp += INT16SZ;
+ tclass = ns_get16(cp); cp += INT16SZ;
+ if (ttype == type && tclass == class &&
+ ns_samename(tname, name) == 1)
+ return (1);
+ }
+ return (0);
+}
+
+/*%
+ * is there a 1:1 mapping of (name,type,class)
+ * in (buf1,eom1) and (buf2,eom2)?
+ *
+ * returns:
+ *\li -1 : format error
+ *\li 0 : not a 1:1 mapping
+ *\li >0 : is a 1:1 mapping
+ *
+ * author:
+ *\li paul vixie, 29may94
+ */
+int
+res_queriesmatch(const u_char *buf1, const u_char *eom1,
+ const u_char *buf2, const u_char *eom2)
+{
+ const u_char *cp = buf1 + HFIXEDSZ;
+ int qdcount = ntohs(((const HEADER*)buf1)->qdcount);
+
+ if (buf1 + HFIXEDSZ > eom1 || buf2 + HFIXEDSZ > eom2)
+ return (-1);
+
+ /*
+ * Only header section present in replies to
+ * dynamic update packets.
+ */
+ if ((((const HEADER *)buf1)->opcode == ns_o_update) &&
+ (((const HEADER *)buf2)->opcode == ns_o_update))
+ return (1);
+
+ if (qdcount != ntohs(((const HEADER*)buf2)->qdcount))
+ return (0);
+ while (qdcount-- > 0) {
+ char tname[MAXDNAME+1];
+ int n, ttype, tclass;
+
+ n = dn_expand(buf1, eom1, cp, tname, sizeof tname);
+ if (n < 0)
+ return (-1);
+ cp += n;
+ if (cp + 2 * INT16SZ > eom1)
+ return (-1);
+ ttype = ns_get16(cp); cp += INT16SZ;
+ tclass = ns_get16(cp); cp += INT16SZ;
+ if (!res_nameinquery(tname, ttype, tclass, buf2, eom2))
+ return (0);
+ }
+ return (1);
+}
+
+int
+res_nsend(res_state statp,
+ const u_char *buf, int buflen, u_char *ans, int anssiz)
+{
+ int gotsomewhere, terrno, tries, v_circuit, resplen, ns, n;
+#ifdef USE_KQUEUE
+ int kq;
+#endif
+ char abuf[NI_MAXHOST];
+
+ /* No name servers or res_init() failure */
+ if (statp->nscount == 0 || EXT(statp).ext == NULL) {
+ errno = ESRCH;
+ return (-1);
+ }
+ if (anssiz < HFIXEDSZ) {
+ errno = EINVAL;
+ return (-1);
+ }
+ DprintQ((statp->options & RES_DEBUG) || (statp->pfcode & RES_PRF_QUERY),
+ (stdout, ";; res_send()\n"), buf, buflen);
+ v_circuit = (statp->options & RES_USEVC) || buflen > PACKETSZ;
+ gotsomewhere = 0;
+ terrno = ETIMEDOUT;
+
+#ifdef USE_KQUEUE
+ if ((kq = kqueue()) < 0) {
+ Perror(statp, stderr, "kqueue", errno);
+ return (-1);
+ }
+#endif
+
+ /*
+ * If the ns_addr_list in the resolver context has changed, then
+ * invalidate our cached copy and the associated timing data.
+ */
+ if (EXT(statp).nscount != 0) {
+ int needclose = 0;
+ struct sockaddr_storage peer;
+ ISC_SOCKLEN_T peerlen;
+
+ if (EXT(statp).nscount != statp->nscount)
+ needclose++;
+ else
+ for (ns = 0; ns < statp->nscount; ns++) {
+ if (statp->nsaddr_list[ns].sin_family &&
+ !sock_eq((struct sockaddr *)&statp->nsaddr_list[ns],
+ (struct sockaddr *)&EXT(statp).ext->nsaddrs[ns])) {
+ needclose++;
+ break;
+ }
+
+ if (EXT(statp).nssocks[ns] == -1)
+ continue;
+ peerlen = sizeof(peer);
+ if (_getsockname(EXT(statp).nssocks[ns],
+ (struct sockaddr *)&peer, &peerlen) < 0) {
+ needclose++;
+ break;
+ }
+ if (!sock_eq((struct sockaddr *)&peer,
+ get_nsaddr(statp, ns))) {
+ needclose++;
+ break;
+ }
+ }
+ if (needclose) {
+ res_nclose(statp);
+ EXT(statp).nscount = 0;
+ }
+ }
+
+ /*
+ * Maybe initialize our private copy of the ns_addr_list.
+ */
+ if (EXT(statp).nscount == 0) {
+ for (ns = 0; ns < statp->nscount; ns++) {
+ EXT(statp).nstimes[ns] = RES_MAXTIME;
+ EXT(statp).nssocks[ns] = -1;
+ if (!statp->nsaddr_list[ns].sin_family)
+ continue;
+ EXT(statp).ext->nsaddrs[ns].sin =
+ statp->nsaddr_list[ns];
+ }
+ EXT(statp).nscount = statp->nscount;
+ }
+
+ /*
+ * Some resolvers want to even out the load on their nameservers.
+ * Note that RES_BLAST overrides RES_ROTATE.
+ */
+ if ((statp->options & RES_ROTATE) != 0U &&
+ (statp->options & RES_BLAST) == 0U) {
+ union res_sockaddr_union inu;
+ struct sockaddr_in ina;
+ int lastns = statp->nscount - 1;
+ int fd;
+ u_int16_t nstime;
+
+ if (EXT(statp).ext != NULL)
+ inu = EXT(statp).ext->nsaddrs[0];
+ ina = statp->nsaddr_list[0];
+ fd = EXT(statp).nssocks[0];
+ nstime = EXT(statp).nstimes[0];
+ for (ns = 0; ns < lastns; ns++) {
+ if (EXT(statp).ext != NULL)
+ EXT(statp).ext->nsaddrs[ns] =
+ EXT(statp).ext->nsaddrs[ns + 1];
+ statp->nsaddr_list[ns] = statp->nsaddr_list[ns + 1];
+ EXT(statp).nssocks[ns] = EXT(statp).nssocks[ns + 1];
+ EXT(statp).nstimes[ns] = EXT(statp).nstimes[ns + 1];
+ }
+ if (EXT(statp).ext != NULL)
+ EXT(statp).ext->nsaddrs[lastns] = inu;
+ statp->nsaddr_list[lastns] = ina;
+ EXT(statp).nssocks[lastns] = fd;
+ EXT(statp).nstimes[lastns] = nstime;
+ }
+
+ /*
+ * Send request, RETRY times, or until successful.
+ */
+ for (tries = 0; tries < statp->retry; tries++) {
+ for (ns = 0; ns < statp->nscount; ns++) {
+ struct sockaddr *nsap;
+ int nsaplen;
+ nsap = get_nsaddr(statp, ns);
+ nsaplen = get_salen(nsap);
+ statp->_flags &= ~RES_F_LASTMASK;
+ statp->_flags |= (ns << RES_F_LASTSHIFT);
+ same_ns:
+ if (statp->qhook) {
+ int done = 0, loops = 0;
+
+ do {
+ res_sendhookact act;
+
+ act = (*statp->qhook)(&nsap, &buf, &buflen,
+ ans, anssiz, &resplen);
+ switch (act) {
+ case res_goahead:
+ done = 1;
+ break;
+ case res_nextns:
+ res_nclose(statp);
+ goto next_ns;
+ case res_done:
+#ifdef USE_KQUEUE
+ _close(kq);
+#endif
+ return (resplen);
+ case res_modified:
+ /* give the hook another try */
+ if (++loops < 42) /*doug adams*/
+ break;
+ /*FALLTHROUGH*/
+ case res_error:
+ /*FALLTHROUGH*/
+ default:
+ goto fail;
+ }
+ } while (!done);
+ }
+
+ Dprint(((statp->options & RES_DEBUG) &&
+ getnameinfo(nsap, nsaplen, abuf, sizeof(abuf),
+ NULL, 0, niflags) == 0),
+ (stdout, ";; Querying server (# %d) address = %s\n",
+ ns + 1, abuf));
+
+
+ if (v_circuit) {
+ /* Use VC; at most one attempt per server. */
+ tries = statp->retry;
+ n = send_vc(statp, buf, buflen, ans, anssiz, &terrno,
+ ns);
+ if (n < 0)
+ goto fail;
+ if (n == 0)
+ goto next_ns;
+ resplen = n;
+ } else {
+ /* Use datagrams. */
+ n = send_dg(statp,
+#ifdef USE_KQUEUE
+ kq,
+#endif
+ buf, buflen, ans, anssiz, &terrno,
+ ns, tries, &v_circuit, &gotsomewhere);
+ if (n < 0)
+ goto fail;
+ if (n == 0)
+ goto next_ns;
+ if (v_circuit)
+ goto same_ns;
+ resplen = n;
+ }
+
+ Dprint((statp->options & RES_DEBUG) ||
+ ((statp->pfcode & RES_PRF_REPLY) &&
+ (statp->pfcode & RES_PRF_HEAD1)),
+ (stdout, ";; got answer:\n"));
+
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, "%s", ""),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+
+ /*
+ * If we have temporarily opened a virtual circuit,
+ * or if we haven't been asked to keep a socket open,
+ * close the socket.
+ */
+ if ((v_circuit && (statp->options & RES_USEVC) == 0U) ||
+ (statp->options & RES_STAYOPEN) == 0U) {
+ res_nclose(statp);
+ }
+ if (statp->rhook) {
+ int done = 0, loops = 0;
+
+ do {
+ res_sendhookact act;
+
+ act = (*statp->rhook)(nsap, buf, buflen,
+ ans, anssiz, &resplen);
+ switch (act) {
+ case res_goahead:
+ case res_done:
+ done = 1;
+ break;
+ case res_nextns:
+ res_nclose(statp);
+ goto next_ns;
+ case res_modified:
+ /* give the hook another try */
+ if (++loops < 42) /*doug adams*/
+ break;
+ /*FALLTHROUGH*/
+ case res_error:
+ /*FALLTHROUGH*/
+ default:
+ goto fail;
+ }
+ } while (!done);
+
+ }
+#ifdef USE_KQUEUE
+ _close(kq);
+#endif
+ return (resplen);
+ next_ns: ;
+ } /*foreach ns*/
+ } /*foreach retry*/
+ res_nclose(statp);
+#ifdef USE_KQUEUE
+ _close(kq);
+#endif
+ if (!v_circuit) {
+ if (!gotsomewhere)
+ errno = ECONNREFUSED; /*%< no nameservers found */
+ else
+ errno = ETIMEDOUT; /*%< no answer obtained */
+ } else
+ errno = terrno;
+ return (-1);
+ fail:
+ res_nclose(statp);
+#ifdef USE_KQUEUE
+ _close(kq);
+#endif
+ return (-1);
+}
+
+/* Private */
+
+static int
+get_salen(sa)
+ const struct sockaddr *sa;
+{
+
+#ifdef HAVE_SA_LEN
+ /* There are people do not set sa_len. Be forgiving to them. */
+ if (sa->sa_len)
+ return (sa->sa_len);
+#endif
+
+ if (sa->sa_family == AF_INET)
+ return (sizeof(struct sockaddr_in));
+ else if (sa->sa_family == AF_INET6)
+ return (sizeof(struct sockaddr_in6));
+ else
+ return (0); /*%< unknown, die on connect */
+}
+
+/*%
+ * pick appropriate nsaddr_list for use. see res_init() for initialization.
+ */
+static struct sockaddr *
+get_nsaddr(statp, n)
+ res_state statp;
+ size_t n;
+{
+
+ if (!statp->nsaddr_list[n].sin_family && EXT(statp).ext) {
+ /*
+ * - EXT(statp).ext->nsaddrs[n] holds an address that is larger
+ * than struct sockaddr, and
+ * - user code did not update statp->nsaddr_list[n].
+ */
+ return (struct sockaddr *)(void *)&EXT(statp).ext->nsaddrs[n];
+ } else {
+ /*
+ * - user code updated statp->nsaddr_list[n], or
+ * - statp->nsaddr_list[n] has the same content as
+ * EXT(statp).ext->nsaddrs[n].
+ */
+ return (struct sockaddr *)(void *)&statp->nsaddr_list[n];
+ }
+}
+
+static int
+send_vc(res_state statp,
+ const u_char *buf, int buflen, u_char *ans, int anssiz,
+ int *terrno, int ns)
+{
+ const HEADER *hp = (const HEADER *) buf;
+ HEADER *anhp = (HEADER *) ans;
+ struct sockaddr *nsap;
+ int nsaplen;
+ int truncating, connreset, resplen, n;
+ struct iovec iov[2];
+ u_short len;
+ u_char *cp;
+ void *tmp;
+#ifdef SO_NOSIGPIPE
+ int on = 1;
+#endif
+
+ nsap = get_nsaddr(statp, ns);
+ nsaplen = get_salen(nsap);
+
+ connreset = 0;
+ same_ns:
+ truncating = 0;
+
+ /* Are we still talking to whom we want to talk to? */
+ if (statp->_vcsock >= 0 && (statp->_flags & RES_F_VC) != 0) {
+ struct sockaddr_storage peer;
+ ISC_SOCKLEN_T size = sizeof peer;
+
+ if (_getpeername(statp->_vcsock,
+ (struct sockaddr *)&peer, &size) < 0 ||
+ !sock_eq((struct sockaddr *)&peer, nsap)) {
+ res_nclose(statp);
+ statp->_flags &= ~RES_F_VC;
+ }
+ }
+
+ if (statp->_vcsock < 0 || (statp->_flags & RES_F_VC) == 0) {
+ if (statp->_vcsock >= 0)
+ res_nclose(statp);
+
+ statp->_vcsock = _socket(nsap->sa_family, SOCK_STREAM, 0);
+#if !defined(USE_POLL) && !defined(USE_KQUEUE)
+ if (statp->_vcsock > highestFD) {
+ res_nclose(statp);
+ errno = ENOTSOCK;
+ }
+#endif
+ if (statp->_vcsock < 0) {
+ switch (errno) {
+ case EPROTONOSUPPORT:
+#ifdef EPFNOSUPPORT
+ case EPFNOSUPPORT:
+#endif
+ case EAFNOSUPPORT:
+ Perror(statp, stderr, "socket(vc)", errno);
+ return (0);
+ default:
+ *terrno = errno;
+ Perror(statp, stderr, "socket(vc)", errno);
+ return (-1);
+ }
+ }
+#ifdef SO_NOSIGPIPE
+ /*
+ * Disable generation of SIGPIPE when writing to a closed
+ * socket. Write should return -1 and set errno to EPIPE
+ * instead.
+ *
+ * Push on even if setsockopt(SO_NOSIGPIPE) fails.
+ */
+ (void)_setsockopt(statp->_vcsock, SOL_SOCKET, SO_NOSIGPIPE, &on,
+ sizeof(on));
+#endif
+ errno = 0;
+ if (_connect(statp->_vcsock, nsap, nsaplen) < 0) {
+ *terrno = errno;
+ Aerror(statp, stderr, "connect/vc", errno, nsap,
+ nsaplen);
+ res_nclose(statp);
+ return (0);
+ }
+ statp->_flags |= RES_F_VC;
+ }
+
+ /*
+ * Send length & message
+ */
+ ns_put16((u_short)buflen, (u_char*)&len);
+ iov[0] = evConsIovec(&len, INT16SZ);
+ DE_CONST(buf, tmp);
+ iov[1] = evConsIovec(tmp, buflen);
+ if (_writev(statp->_vcsock, iov, 2) != (INT16SZ + buflen)) {
+ *terrno = errno;
+ Perror(statp, stderr, "write failed", errno);
+ res_nclose(statp);
+ return (0);
+ }
+ /*
+ * Receive length & response
+ */
+ read_len:
+ cp = ans;
+ len = INT16SZ;
+ while ((n = _read(statp->_vcsock, (char *)cp, (int)len)) > 0) {
+ cp += n;
+ if ((len -= n) == 0)
+ break;
+ }
+ if (n <= 0) {
+ *terrno = errno;
+ Perror(statp, stderr, "read failed", errno);
+ res_nclose(statp);
+ /*
+ * A long running process might get its TCP
+ * connection reset if the remote server was
+ * restarted. Requery the server instead of
+ * trying a new one. When there is only one
+ * server, this means that a query might work
+ * instead of failing. We only allow one reset
+ * per query to prevent looping.
+ */
+ if (*terrno == ECONNRESET && !connreset) {
+ connreset = 1;
+ res_nclose(statp);
+ goto same_ns;
+ }
+ res_nclose(statp);
+ return (0);
+ }
+ resplen = ns_get16(ans);
+ if (resplen > anssiz) {
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; response truncated\n")
+ );
+ truncating = 1;
+ len = anssiz;
+ } else
+ len = resplen;
+ if (len < HFIXEDSZ) {
+ /*
+ * Undersized message.
+ */
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; undersized: %d\n", len));
+ *terrno = EMSGSIZE;
+ res_nclose(statp);
+ return (0);
+ }
+ cp = ans;
+ while (len != 0 &&
+ (n = _read(statp->_vcsock, (char *)cp, (int)len)) > 0) {
+ cp += n;
+ len -= n;
+ }
+ if (n <= 0) {
+ *terrno = errno;
+ Perror(statp, stderr, "read(vc)", errno);
+ res_nclose(statp);
+ return (0);
+ }
+ if (truncating) {
+ /*
+ * Flush rest of answer so connection stays in synch.
+ */
+ anhp->tc = 1;
+ len = resplen - anssiz;
+ while (len != 0) {
+ char junk[PACKETSZ];
+
+ n = _read(statp->_vcsock, junk,
+ (len > sizeof junk) ? sizeof junk : len);
+ if (n > 0)
+ len -= n;
+ else
+ break;
+ }
+ }
+ /*
+ * If the calling applicating has bailed out of
+ * a previous call and failed to arrange to have
+ * the circuit closed or the server has got
+ * itself confused, then drop the packet and
+ * wait for the correct one.
+ */
+ if (hp->id != anhp->id) {
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; old answer (unexpected):\n"),
+ ans, (resplen > anssiz) ? anssiz: resplen);
+ goto read_len;
+ }
+
+ /*
+ * All is well, or the error is fatal. Signal that the
+ * next nameserver ought not be tried.
+ */
+ return (resplen);
+}
+
+static int
+send_dg(res_state statp,
+#ifdef USE_KQUEUE
+ int kq,
+#endif
+ const u_char *buf, int buflen, u_char *ans,
+ int anssiz, int *terrno, int ns, int tries, int *v_circuit,
+ int *gotsomewhere)
+{
+ const HEADER *hp = (const HEADER *) buf;
+ HEADER *anhp = (HEADER *) ans;
+ const struct sockaddr *nsap;
+ int nsaplen;
+ struct timespec now, timeout, finish;
+ struct sockaddr_storage from;
+ ISC_SOCKLEN_T fromlen;
+ int resplen, seconds, n, s;
+#ifdef USE_KQUEUE
+ struct kevent kv;
+#else
+#ifdef USE_POLL
+ int polltimeout;
+ struct pollfd pollfd;
+#else
+ fd_set dsmask;
+#endif
+#endif
+
+ nsap = get_nsaddr(statp, ns);
+ nsaplen = get_salen(nsap);
+ if (EXT(statp).nssocks[ns] == -1) {
+ EXT(statp).nssocks[ns] = _socket(nsap->sa_family,
+ SOCK_DGRAM, 0);
+#if !defined(USE_POLL) && !defined(USE_KQUEUE)
+ if (EXT(statp).nssocks[ns] > highestFD) {
+ res_nclose(statp);
+ errno = ENOTSOCK;
+ }
+#endif
+ if (EXT(statp).nssocks[ns] < 0) {
+ switch (errno) {
+ case EPROTONOSUPPORT:
+#ifdef EPFNOSUPPORT
+ case EPFNOSUPPORT:
+#endif
+ case EAFNOSUPPORT:
+ Perror(statp, stderr, "socket(dg)", errno);
+ return (0);
+ default:
+ *terrno = errno;
+ Perror(statp, stderr, "socket(dg)", errno);
+ return (-1);
+ }
+ }
+#ifndef CANNOT_CONNECT_DGRAM
+ /*
+ * On a 4.3BSD+ machine (client and server,
+ * actually), sending to a nameserver datagram
+ * port with no nameserver will cause an
+ * ICMP port unreachable message to be returned.
+ * If our datagram socket is "connected" to the
+ * server, we get an ECONNREFUSED error on the next
+ * socket operation, and select returns if the
+ * error message is received. We can thus detect
+ * the absence of a nameserver without timing out.
+ *
+ * When the option "insecure1" is specified, we'd
+ * rather expect to see responses from an "unknown"
+ * address. In order to let the kernel accept such
+ * responses, do not connect the socket here.
+ * XXX: or do we need an explicit option to disable
+ * connecting?
+ */
+ if (!(statp->options & RES_INSECURE1) &&
+ _connect(EXT(statp).nssocks[ns], nsap, nsaplen) < 0) {
+ Aerror(statp, stderr, "connect(dg)", errno, nsap,
+ nsaplen);
+ res_nclose(statp);
+ return (0);
+ }
+#endif /* !CANNOT_CONNECT_DGRAM */
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; new DG socket\n"))
+ }
+ s = EXT(statp).nssocks[ns];
+#ifndef CANNOT_CONNECT_DGRAM
+ if (statp->options & RES_INSECURE1) {
+ if (_sendto(s,
+ (const char*)buf, buflen, 0, nsap, nsaplen) != buflen) {
+ Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
+ res_nclose(statp);
+ return (0);
+ }
+ } else if (send(s, (const char*)buf, buflen, 0) != buflen) {
+ Perror(statp, stderr, "send", errno);
+ res_nclose(statp);
+ return (0);
+ }
+#else /* !CANNOT_CONNECT_DGRAM */
+ if (_sendto(s, (const char*)buf, buflen, 0, nsap, nsaplen) != buflen)
+ {
+ Aerror(statp, stderr, "sendto", errno, nsap, nsaplen);
+ res_nclose(statp);
+ return (0);
+ }
+#endif /* !CANNOT_CONNECT_DGRAM */
+
+ /*
+ * Wait for reply.
+ */
+ seconds = (statp->retrans << tries);
+ if (ns > 0)
+ seconds /= statp->nscount;
+ if (seconds <= 0)
+ seconds = 1;
+ now = evNowTime();
+ timeout = evConsTime(seconds, 0);
+ finish = evAddTime(now, timeout);
+ goto nonow;
+ wait:
+ now = evNowTime();
+ nonow:
+#ifndef USE_POLL
+ if (evCmpTime(finish, now) > 0)
+ timeout = evSubTime(finish, now);
+ else
+ timeout = evConsTime(0, 0);
+#ifdef USE_KQUEUE
+ EV_SET(&kv, s, EVFILT_READ, EV_ADD | EV_ONESHOT, 0, 0, 0);
+ n = _kevent(kq, &kv, 1, &kv, 1, &timeout);
+#else
+ FD_ZERO(&dsmask);
+ FD_SET(s, &dsmask);
+ n = pselect(s + 1, &dsmask, NULL, NULL, &timeout, NULL);
+#endif
+#else
+ timeout = evSubTime(finish, now);
+ if (timeout.tv_sec < 0)
+ timeout = evConsTime(0, 0);
+ polltimeout = 1000*timeout.tv_sec +
+ timeout.tv_nsec/1000000;
+ pollfd.fd = s;
+ pollfd.events = POLLRDNORM;
+ n = poll(&pollfd, 1, polltimeout);
+#endif /* USE_POLL */
+
+ if (n == 0) {
+ Dprint(statp->options & RES_DEBUG, (stdout, ";; timeout\n"));
+ *gotsomewhere = 1;
+ return (0);
+ }
+ if (n < 0) {
+ if (errno == EINTR)
+ goto wait;
+#ifdef USE_KQUEUE
+ Perror(statp, stderr, "kevent", errno);
+#else
+#ifndef USE_POLL
+ Perror(statp, stderr, "select", errno);
+#else
+ Perror(statp, stderr, "poll", errno);
+#endif /* USE_POLL */
+#endif
+ res_nclose(statp);
+ return (0);
+ }
+#ifdef USE_KQUEUE
+ if (kv.ident != s)
+ goto wait;
+#endif
+ errno = 0;
+ fromlen = sizeof(from);
+ resplen = _recvfrom(s, (char*)ans, anssiz,0,
+ (struct sockaddr *)&from, &fromlen);
+ if (resplen <= 0) {
+ Perror(statp, stderr, "recvfrom", errno);
+ res_nclose(statp);
+ return (0);
+ }
+ *gotsomewhere = 1;
+ if (resplen < HFIXEDSZ) {
+ /*
+ * Undersized message.
+ */
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; undersized: %d\n",
+ resplen));
+ *terrno = EMSGSIZE;
+ res_nclose(statp);
+ return (0);
+ }
+ if (hp->id != anhp->id) {
+ /*
+ * response from old query, ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; old answer:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ goto wait;
+ }
+ if (!(statp->options & RES_INSECURE1) &&
+ !res_ourserver_p(statp, (struct sockaddr *)&from)) {
+ /*
+ * response from wrong server? ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; not our server:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ goto wait;
+ }
+#ifdef RES_USE_EDNS0
+ if (anhp->rcode == FORMERR && (statp->options & RES_USE_EDNS0) != 0U) {
+ /*
+ * Do not retry if the server do not understand EDNS0.
+ * The case has to be captured here, as FORMERR packet do not
+ * carry query section, hence res_queriesmatch() returns 0.
+ */
+ DprintQ(statp->options & RES_DEBUG,
+ (stdout, "server rejected query with EDNS0:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ /* record the error */
+ statp->_flags |= RES_F_EDNS0ERR;
+ res_nclose(statp);
+ return (0);
+ }
+#endif
+ if (!(statp->options & RES_INSECURE2) &&
+ !res_queriesmatch(buf, buf + buflen,
+ ans, ans + anssiz)) {
+ /*
+ * response contains wrong query? ignore it.
+ * XXX - potential security hazard could
+ * be detected here.
+ */
+ DprintQ((statp->options & RES_DEBUG) ||
+ (statp->pfcode & RES_PRF_REPLY),
+ (stdout, ";; wrong query name:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ goto wait;
+ }
+ if (anhp->rcode == SERVFAIL ||
+ anhp->rcode == NOTIMP ||
+ anhp->rcode == REFUSED) {
+ DprintQ(statp->options & RES_DEBUG,
+ (stdout, "server rejected query:\n"),
+ ans, (resplen > anssiz) ? anssiz : resplen);
+ res_nclose(statp);
+ /* don't retry if called from dig */
+ if (!statp->pfcode)
+ return (0);
+ }
+ if (!(statp->options & RES_IGNTC) && anhp->tc) {
+ /*
+ * To get the rest of answer,
+ * use TCP with same server.
+ */
+ Dprint(statp->options & RES_DEBUG,
+ (stdout, ";; truncated answer\n"));
+ *v_circuit = 1;
+ res_nclose(statp);
+ return (1);
+ }
+ /*
+ * All is well, or the error is fatal. Signal that the
+ * next nameserver ought not be tried.
+ */
+ return (resplen);
+}
+
+static void
+Aerror(const res_state statp, FILE *file, const char *string, int error,
+ const struct sockaddr *address, int alen)
+{
+ int save = errno;
+ char hbuf[NI_MAXHOST];
+ char sbuf[NI_MAXSERV];
+
+ if ((statp->options & RES_DEBUG) != 0U) {
+ if (getnameinfo(address, alen, hbuf, sizeof(hbuf),
+ sbuf, sizeof(sbuf), niflags)) {
+ strncpy(hbuf, "?", sizeof(hbuf) - 1);
+ hbuf[sizeof(hbuf) - 1] = '\0';
+ strncpy(sbuf, "?", sizeof(sbuf) - 1);
+ sbuf[sizeof(sbuf) - 1] = '\0';
+ }
+ fprintf(file, "res_send: %s ([%s].%s): %s\n",
+ string, hbuf, sbuf, strerror(error));
+ }
+ errno = save;
+}
+
+static void
+Perror(const res_state statp, FILE *file, const char *string, int error) {
+ int save = errno;
+
+ if ((statp->options & RES_DEBUG) != 0U)
+ fprintf(file, "res_send: %s: %s\n",
+ string, strerror(error));
+ errno = save;
+}
+
+static int
+sock_eq(struct sockaddr *a, struct sockaddr *b) {
+ struct sockaddr_in *a4, *b4;
+ struct sockaddr_in6 *a6, *b6;
+
+ if (a->sa_family != b->sa_family)
+ return 0;
+ switch (a->sa_family) {
+ case AF_INET:
+ a4 = (struct sockaddr_in *)a;
+ b4 = (struct sockaddr_in *)b;
+ return a4->sin_port == b4->sin_port &&
+ a4->sin_addr.s_addr == b4->sin_addr.s_addr;
+ case AF_INET6:
+ a6 = (struct sockaddr_in6 *)a;
+ b6 = (struct sockaddr_in6 *)b;
+ return a6->sin6_port == b6->sin6_port &&
+#ifdef HAVE_SIN6_SCOPE_ID
+ a6->sin6_scope_id == b6->sin6_scope_id &&
+#endif
+ IN6_ARE_ADDR_EQUAL(&a6->sin6_addr, &b6->sin6_addr);
+ default:
+ return 0;
+ }
+}
+
+#if defined(NEED_PSELECT) && !defined(USE_POLL) && !defined(USE_KQUEUE)
+/* XXX needs to move to the porting library. */
+static int
+pselect(int nfds, void *rfds, void *wfds, void *efds,
+ struct timespec *tsp, const sigset_t *sigmask)
+{
+ struct timeval tv, *tvp;
+ sigset_t sigs;
+ int n;
+
+ if (tsp) {
+ tvp = &tv;
+ tv = evTimeVal(*tsp);
+ } else
+ tvp = NULL;
+ if (sigmask)
+ sigprocmask(SIG_SETMASK, sigmask, &sigs);
+ n = select(nfds, rfds, wfds, efds, tvp);
+ if (sigmask)
+ sigprocmask(SIG_SETMASK, &sigs, NULL);
+ if (tsp)
+ *tsp = evTimeSpec(tv);
+ return (n);
+}
+#endif
diff --git a/lib/libc/resolv/res_state.c b/lib/libc/resolv/res_state.c
new file mode 100644
index 0000000..59c9430
--- /dev/null
+++ b/lib/libc/resolv/res_state.c
@@ -0,0 +1,87 @@
+/*-
+ * Copyright (c) 2006 The FreeBSD Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <stdlib.h>
+
+#include "namespace.h"
+#include "reentrant.h"
+#include "un-namespace.h"
+
+#undef _res
+
+struct __res_state _res;
+
+static thread_key_t res_key;
+static once_t res_init_once = ONCE_INITIALIZER;
+static int res_thr_keycreated = 0;
+
+static void
+free_res(void *ptr)
+{
+ res_state statp = ptr;
+
+ if (statp->_u._ext.ext != NULL)
+ res_ndestroy(statp);
+ free(statp);
+}
+
+static void
+res_keycreate(void)
+{
+ res_thr_keycreated = thr_keycreate(&res_key, free_res) == 0;
+}
+
+res_state
+__res_state(void)
+{
+ res_state statp;
+
+ if (thr_main() != 0)
+ return (&_res);
+
+ if (thr_once(&res_init_once, res_keycreate) != 0 ||
+ !res_thr_keycreated)
+ return (&_res);
+
+ statp = thr_getspecific(res_key);
+ if (statp != NULL)
+ return (statp);
+ statp = calloc(1, sizeof(*statp));
+ if (statp == NULL)
+ return (&_res);
+#ifdef __BIND_RES_TEXT
+ statp->options = RES_TIMEOUT; /* Motorola, et al. */
+#endif
+ if (thr_setspecific(res_key, statp) == 0)
+ return (statp);
+ free(statp);
+ return (&_res);
+}
diff --git a/lib/libc/resolv/res_update.c b/lib/libc/resolv/res_update.c
new file mode 100644
index 0000000..a05e26d
--- /dev/null
+++ b/lib/libc/resolv/res_update.c
@@ -0,0 +1,222 @@
+#if !defined(lint) && !defined(SABER)
+static const char rcsid[] = "$Id: res_update.c,v 1.12.18.1 2005/04/27 05:01:12 sra Exp $";
+#endif /* not lint */
+
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996-1999 by Internet Software Consortium.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*! \file
+ * \brief
+ * Based on the Dynamic DNS reference implementation by Viraj Bais
+ * &lt;viraj_bais@ccm.fm.intel.com>
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "port_before.h"
+
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <arpa/nameser.h>
+
+#include <errno.h>
+#include <limits.h>
+#include <netdb.h>
+#include <res_update.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <isc/list.h>
+#include <resolv.h>
+
+#include "port_after.h"
+#include "res_private.h"
+
+/*%
+ * Separate a linked list of records into groups so that all records
+ * in a group will belong to a single zone on the nameserver.
+ * Create a dynamic update packet for each zone and send it to the
+ * nameservers for that zone, and await answer.
+ * Abort if error occurs in updating any zone.
+ * Return the number of zones updated on success, < 0 on error.
+ *
+ * On error, caller must deal with the unsynchronized zones
+ * eg. an A record might have been successfully added to the forward
+ * zone but the corresponding PTR record would be missing if error
+ * was encountered while updating the reverse zone.
+ */
+
+struct zonegrp {
+ char z_origin[MAXDNAME];
+ ns_class z_class;
+ union res_sockaddr_union z_nsaddrs[MAXNS];
+ int z_nscount;
+ int z_flags;
+ LIST(ns_updrec) z_rrlist;
+ LINK(struct zonegrp) z_link;
+};
+
+#define ZG_F_ZONESECTADDED 0x0001
+
+/* Forward. */
+
+static void res_dprintf(const char *, ...) ISC_FORMAT_PRINTF(1, 2);
+
+/* Macros. */
+
+#define DPRINTF(x) do {\
+ int save_errno = errno; \
+ if ((statp->options & RES_DEBUG) != 0U) res_dprintf x; \
+ errno = save_errno; \
+ } while (0)
+
+/* Public. */
+
+int
+res_nupdate(res_state statp, ns_updrec *rrecp_in, ns_tsig_key *key) {
+ ns_updrec *rrecp;
+ u_char answer[PACKETSZ];
+ u_char *packet;
+ struct zonegrp *zptr, tgrp;
+ LIST(struct zonegrp) zgrps;
+ int nzones = 0, nscount = 0, n;
+ union res_sockaddr_union nsaddrs[MAXNS];
+
+ packet = malloc(NS_MAXMSG);
+ if (packet == NULL) {
+ DPRINTF(("malloc failed"));
+ return (0);
+ }
+ /* Thread all of the updates onto a list of groups. */
+ INIT_LIST(zgrps);
+ memset(&tgrp, 0, sizeof (tgrp));
+ for (rrecp = rrecp_in; rrecp;
+ rrecp = LINKED(rrecp, r_link) ? NEXT(rrecp, r_link) : NULL) {
+ int nscnt;
+ /* Find the origin for it if there is one. */
+ tgrp.z_class = rrecp->r_class;
+ nscnt = res_findzonecut2(statp, rrecp->r_dname, tgrp.z_class,
+ RES_EXHAUSTIVE, tgrp.z_origin,
+ sizeof tgrp.z_origin,
+ tgrp.z_nsaddrs, MAXNS);
+ if (nscnt <= 0) {
+ DPRINTF(("res_findzonecut failed (%d)", nscnt));
+ goto done;
+ }
+ tgrp.z_nscount = nscnt;
+ /* Find the group for it if there is one. */
+ for (zptr = HEAD(zgrps); zptr != NULL; zptr = NEXT(zptr, z_link))
+ if (ns_samename(tgrp.z_origin, zptr->z_origin) == 1 &&
+ tgrp.z_class == zptr->z_class)
+ break;
+ /* Make a group for it if there isn't one. */
+ if (zptr == NULL) {
+ zptr = malloc(sizeof *zptr);
+ if (zptr == NULL) {
+ DPRINTF(("malloc failed"));
+ goto done;
+ }
+ *zptr = tgrp;
+ zptr->z_flags = 0;
+ INIT_LINK(zptr, z_link);
+ INIT_LIST(zptr->z_rrlist);
+ APPEND(zgrps, zptr, z_link);
+ }
+ /* Thread this rrecp onto the right group. */
+ APPEND(zptr->z_rrlist, rrecp, r_glink);
+ }
+
+ for (zptr = HEAD(zgrps); zptr != NULL; zptr = NEXT(zptr, z_link)) {
+ /* Construct zone section and prepend it. */
+ rrecp = res_mkupdrec(ns_s_zn, zptr->z_origin,
+ zptr->z_class, ns_t_soa, 0);
+ if (rrecp == NULL) {
+ DPRINTF(("res_mkupdrec failed"));
+ goto done;
+ }
+ PREPEND(zptr->z_rrlist, rrecp, r_glink);
+ zptr->z_flags |= ZG_F_ZONESECTADDED;
+
+ /* Marshall the update message. */
+ n = res_nmkupdate(statp, HEAD(zptr->z_rrlist),
+ packet, NS_MAXMSG);
+ DPRINTF(("res_mkupdate -> %d", n));
+ if (n < 0)
+ goto done;
+
+ /* Temporarily replace the resolver's nameserver set. */
+ nscount = res_getservers(statp, nsaddrs, MAXNS);
+ res_setservers(statp, zptr->z_nsaddrs, zptr->z_nscount);
+
+ /* Send the update and remember the result. */
+ if (key != NULL) {
+#ifdef _LIBC
+ DPRINTF(("TSIG is not supported\n"));
+ RES_SET_H_ERRNO(statp, NO_RECOVERY);
+ goto done;
+#else
+ n = res_nsendsigned(statp, packet, n, key,
+ answer, sizeof answer);
+#endif
+ } else
+ n = res_nsend(statp, packet, n, answer, sizeof answer);
+ if (n < 0) {
+ DPRINTF(("res_nsend: send error, n=%d (%s)\n",
+ n, strerror(errno)));
+ goto done;
+ }
+ if (((HEADER *)answer)->rcode == NOERROR)
+ nzones++;
+
+ /* Restore resolver's nameserver set. */
+ res_setservers(statp, nsaddrs, nscount);
+ nscount = 0;
+ }
+ done:
+ while (!EMPTY(zgrps)) {
+ zptr = HEAD(zgrps);
+ if ((zptr->z_flags & ZG_F_ZONESECTADDED) != 0)
+ res_freeupdrec(HEAD(zptr->z_rrlist));
+ UNLINK(zgrps, zptr, z_link);
+ free(zptr);
+ }
+ if (nscount != 0)
+ res_setservers(statp, nsaddrs, nscount);
+
+ free(packet);
+ return (nzones);
+}
+
+/* Private. */
+
+static void
+res_dprintf(const char *fmt, ...) {
+ va_list ap;
+
+ va_start(ap, fmt);
+ fputs(";; res_nupdate: ", stderr);
+ vfprintf(stderr, fmt, ap);
+ fputc('\n', stderr);
+ va_end(ap);
+}
diff --git a/lib/libc/rpc/DISCLAIMER b/lib/libc/rpc/DISCLAIMER
new file mode 100644
index 0000000..9a3a991
--- /dev/null
+++ b/lib/libc/rpc/DISCLAIMER
@@ -0,0 +1,31 @@
+/* $NetBSD: DISCLAIMER,v 1.2 1998/01/09 04:11:51 perry Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
diff --git a/lib/libc/rpc/LICENSE b/lib/libc/rpc/LICENSE
new file mode 100644
index 0000000..5f1205c
--- /dev/null
+++ b/lib/libc/rpc/LICENSE
@@ -0,0 +1,335 @@
+$FreeBSD$
+
+Sun Industry Standards Source License 1.0
+
+DEFINITIONS
+
+1.1. "Commercial Use" means distribution or otherwise
+making the Original Code available to a third party.
+
+1.2. "Contributor Version" means the combination of the
+Original Code, and the Modifications made by that particular
+Contributor.
+
+1.3. "Electronic Distribution Mechanism" means a mechanism
+generally accepted in the software development community for
+the electronic transfer of data.
+
+1.4. "Executable" means Original Code in any form other
+than Source Code.
+
+1.5. "Initial Developer" means the individual or entity
+identified as the Initial Developer in the Source Code
+notice required by 2 (Exhibit A)
+
+1.6. "Larger Work" means a work which combines Original
+Code or portions thereof with code not governed by the terms
+of this License.
+
+1.7. "License" means this document.
+
+1.8. "Licensable" means having the right to grant, to the
+maximum extent possible, whether at the time of the initial
+grant or subsequently acquired, any and all of the rights
+conveyed herein.
+
+1.9. "Modifications" means any addition to or deletion from
+the substance or structure of either the Original Code or
+any previous Modifications. A Modification is:
+
+A. Any addition to or deletion from the contents of a file
+containing Original Code or previous Modifications.
+
+B. Any new file that contains any part of the Original Code
+or previous Modifications. .
+
+1.10. "Original Code" means Source Code of computer
+software code which is described in the Source Code notice
+required by Exhibit A as Original Code.
+
+1.11. "Patent Claims" means any patent claims, now owned or
+hereafter acquired, including without limitation, method,
+process, and apparatus claims, in any patent Licensable by
+grantor.
+
+1.12. "Source Code" means the preferred form of the
+Original Code for making modifications to it, including all
+modules it contains, plus any associated interface
+definition files, or scripts used to control compilation and
+installation of an Executable.
+
+1.13. "Standards" means the standard identified in Exhibit
+B or a subsequent version of such standard.
+
+1.14. "You" or "Your" means an individual or a legal entity
+exercising rights under, and complying with all of the terms
+of, this License or a future version of this License issued
+under Section 6.1. For legal entities, "You" includes any
+entity which controls, is controlled by, or is under common
+control with You. For purposes of this definition,
+"control" means (a) the power, direct or indirect, to cause
+the direction or management of such entity, whether by
+contract or otherwise, or (b) ownership of more than fifty
+percent (50%) of the outstanding shares or beneficial
+ownership of such entity.
+
+2.0 SOURCE CODE LICENSE
+
+2.1 The Initial Developer Grant: The Initial Developer
+hereby grants You a world-wide, royalty-free, non-exclusive
+license, subject to third party intellectual property
+claims:
+
+a) under intellectual property rights (other than patent or
+trademark) Licensable by Initial Developer to use,
+reproduce, modify, display, perform, sub license and
+distribute the Original Code (or portions thereof )with or
+without Modifications, and/or as part of a Larger Work; and
+
+b) under Patents Claims infringed by the making, using or
+selling of Original Code, to make, have made, use, practice,
+sell, and offer for sale, and/or otherwise dispose of the
+Original Code (or portions thereof).
+
+c) the licenses granted in this Section 2.1(a ) and (b) are
+effective on the date Initial Developer first distributes
+Original Code under the terms of this License.
+
+d) Notwithstanding Section 2.1(b )above, no patent license
+is granted: 1) for code that You delete from the Original
+Code; 2) separate from the Original Code; or 3) for
+infringements caused by: i) the modification of the
+Original Code or
+
+ii) the combination of the Original Code with other software
+or devices, including but not limited to Modifications.
+
+3.0 DISTRIBUTION OBLIGATIONS
+
+3.1 Application of License. The Source Code version of
+Original Code may be distributed only under the terms of
+this License or a future version of this License released
+under Section 6.1, and You must include a copy of this
+License with every copy of the Source Code You distribute.
+You may not offer or impose any terms on any Source Code
+version that alters or restricts the applicable version of
+this License or the recipient's rights hereunder. Your
+license for shipment of the Contributor Version is
+conditioned upon your full compliance with this Section.
+The Modifications which you create must comply with all
+requirements set out by the Standards body in effect 120
+days before You ship the Contributor Version. In the event
+that the Modifications do not meet such requirements, You
+agree to publish (i) any deviation from the Standards
+protocol resulting from implementation of your Modifications
+and (ii) a reference implementation of Your Modifications,
+and to make any such deviation and reference implementation
+available to all third parties under the same terms as the
+license on a royalty free basis within thirty (30) days of
+Your first customer shipment of Your Modifications.
+
+3.2 Required Notices. You must duplicate the notice in
+Exhibit A in each file of the Source Code. If it is not
+possible to put such notice in a particular Source Code file
+due to its structure, then You must include such notice in a
+location (such as a relevant directory ) where a user would
+be likely to look for such a notice. If You created one or
+more Modifications ) You may add your name as a Contributor
+to the notice described in Exhibit A. You must also
+duplicate this License in any documentation for the Source
+Code where You describe recipients' rights or ownership
+rights relating to Initial Code. You may choose to offer,
+and to charge a fee for, warranty, support, indemnity or
+liability obligations to one or more recipients of Your
+version of the Code. However, You may do so only
+
+on Your own behalf, and not on behalf of the Initial
+Developer. You must make it absolutely clear than any such
+warranty, support, indemnity or liability obligation is
+offered by You alone, and You hereby agree to indemnify the
+Initial Developer for any liability incurred by the Initial
+Developer as a result of warranty, support, indemnity or
+liability terms You offer.
+
+3.3 Distribution of Executable Versions. You may distribute
+Original Code in Executable and Source form only if the
+requirements of Section 3.1 and 3.2 have been met for that
+Original Code, and if You include a notice stating that the
+Source Code version of the Original Code is available under
+the terms of this License. The notice must be conspicuously
+included in any notice in an Executable or Source versions,
+related documentation or collateral in which You describe
+recipients' rights relating to the Original Code. You may
+distribute the Executable and Source versions of Your
+version of the Code or ownership rights under a license of
+Your choice, which may contain terms different from this
+License, provided that You are in compliance with the terms
+of this License. If You distribute the Executable and
+Source versions under a different license You must make it
+absolutely clear that any terms which differ from this
+License are offered by You alone, not by the Initial
+Developer . You hereby agree to indemnify the Initial
+Developer for any liability incurred by the Initial
+Developer as a result of any such terms You offer .
+
+3.4 Larger Works. You may create a Larger Work by combining
+Original Code with other code not governed by the terms of
+this License and distribute the Larger Work as a single
+product. In such a case, You must make sure the
+requirements of this License are fulfilled for the Original
+Code.
+
+4.0 INABILITY TO COMPLY DUE TO STATUTE OR REGULATION
+
+If it is impossible for You to comply with any of the terms
+of this License with respect to some or all of the Original
+Code due to statute, judicial order, or regulation then You
+must:
+
+a) comply with the terms of this License to the maximum
+extent possible; and
+
+b) describe the limitations and the code they affect. Such
+description must be included in the LEGAL file described in
+Section 3.2 and must be included with all distributions of
+the Source Code. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently
+detailed for a recipient of ordinary skill to be able to
+understand it.
+
+5.0 APPLICATION OF THIS LICENSE This License applies to code
+to which the Initial Developer has attached the notice in
+Exhibit A and to related Modifications as set out in Section
+3.1.
+
+6.0 VERSIONS OF THE LICENSE
+
+6.1 New Versions. Sun Microsystems, Inc. Sun may publish
+revised and/or new versions of the License from time to
+time. Each version will be given a distinguishing version
+number .
+
+6.2 Effect of New Versions. Once Original Code has been
+published under a particular version of the License, You may
+always continue to use it under the terms of that version.
+You may also choose to use such Original Code under the
+terms of any subsequent version of the License published by
+Sun. No one other than Sun has the right to modify the
+terms applicable to Original Code.
+
+7. DISCLAIMER OF W ARRANTY. ORIGINAL CODE IS PROVIDED
+UNDER THIS LICENSE ON AN "AS IS" BASIS, WITHOUT WARRANTY OF
+ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT
+LIMITATION, WARRANTIES THAT THE ORIGINAL CODE IS FREE OF
+DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR PURPOSE OR
+NON-INFRINGING. THE ENTIRE RISK AS TO THE QUALITY AND
+PERFORMANCE OF THE ORIGINAL CODE IS WITH YOU. SHOULD ANY
+ORIGINAL CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
+INITIAL DEVELOPER )ASSUME THE COST OF ANY NECESSARY
+SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF
+WARRANTY CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO
+USE OF ANY ORIGINAL CODE IS AUTHORIZED HEREUNDER EXCEPT
+UNDER THIS DISCLAIMER.
+
+8.0 TERMINATION
+
+8.1 This License and the rights granted hereunder will
+terminate automatically if You fail to comply with terms
+herein and fail to cure such breach within 30 days of
+becoming aware of the breach. All sublicenses to the
+Original Code which are properly granted shall survive any
+termination of this License. Provisions which, by their
+nature, must remain in effect beyond the termination of this
+License shall survive.
+
+8.2 .In the event of termination under Section 8.1 above,
+all end user license agreements (excluding distributors and
+resellers) which have been validly granted by You or any
+distributor hereunder prior to termination shall survive
+termination.
+
+9.0 LIMIT OF LIABILITY UNDER NO CIRCUMSTANCES AND UNDER NO
+LEGAL THEORY, WHETHER TORT (INCLUDING NEGLIGENCE) ,CONTRACT,
+OR OTHER WISE, SHALL YOU, THE INITIAL DEVELOPER, ANY OTHER
+CONTRIBUTOR, OR ANY DISTRIBUTOR OF ORIGINAL CODE, OR ANY
+SUPPLIER OF ANY OF SUCH PARTIES, BE LIABLE TO ANY PERSON FOR
+ANY INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES
+OF ANY CHARACTER INCLUDING, WITHOUT LIMITATION, DAMAGES FOR
+LOSS OF GOOD WILL, WORK STOPPAGE, COMPUTER FAILURE OR
+MALFUNCTION, OR ANY AND ALL OTHER COMMERCIAL DAMAGES OR
+LOSSES, EVEN IF SUCH PARTY SHALL HAVE BEEN INFORMED OF THE
+POSSIBILITY OF SUCH DAMAGES. THIS LIMITATION OF LIABILITY
+SHALL NOT APPLY TO LIABILITY FOR DEATH OR PERSONAL INJURY
+RESULTING FROM SUCH PARTYS NEGLIGENCE TO THE EXTENT
+APPLICABLE LAW PROHIBITS SUCH LIMITATION. SOME
+JURISDICTIONS DO NOT ALLOW THE EXCLUSION OR LIMITATION OF
+INCIDENTAL OR CONSEQUENTIAL DAMAGES, SO THIS EXCLUSION AND
+LIMITATION MAY NOT APPLY TO YOU.
+
+10.0 U .S. GOVERNMENT END USERS U.S. Government: If this
+Software is being acquired by or on behalf of the U.S.
+Government or by a U.S. Government prime contractor or
+subcontractor (at any tier), then the Government's rights in
+the Software and accompanying documentation shall be only as
+set forth in this license; this is in accordance with 48 C.F
+.R. 227.7201 through 227.7202-4 (for Department of Defense
+(DoD) acquisitions )and with 48 C.F.R.2.101 and 12.212( for
+non-DoD acquisitions).
+
+11.0 MISCELLANEOUS This License represents the complete
+agreement concerning subject matter hereof. If any
+provision of this License is held to be unenforceable, such
+provision shall be reformed only to the extent necessary to
+make it enforceable. This License shall be governed by
+California law provisions (except to the extent applicable
+law, if any, provides otherwise), excluding its
+conflict-of-law provisions. With respect to disputes in
+which at least one party is a citizen of, or an entity
+chartered or registered to do business in the United States
+of America, any litigation relating to this License shall be
+subject to the jurisdiction of the Federal Courts of the
+Northern District of California, with venue lying in Santa
+Clara County, California, with the losing party responsible
+for costs, including without limitation, court costs and
+reasonable attorneys fees and expenses. The application of
+the United Nations Convention on Contracts for the
+International Sale of Goods is expressly excluded. Any law
+or regulation which provides that the language of a contract
+shall be construed against the drafter shall not apply to
+this License.
+
+EXHIBIT A - Sun Standards
+
+"The contents of this file are subject to the Sun Standards
+License Version 1.0 the (the "License";) You may not use
+this file except in compliance with the License. You may
+obtain a copy of the License at
+_______________________________.
+
+ Software distributed under the License is distributed on
+an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
+express or implied. See the License for the specific
+language governing rights and limitations under the License.
+
+The Original Code is Copyright 1998 by Sun Microsystems, Inc
+
+The Initial Developer of the Original Code is: Sun
+Microsystems, Inc.
+
+Portions created by _____________________________ are
+Copyright ______________________________.
+
+All Rights Reserved.
+
+Contributors: ______________________________________.
+
+EXHIBIT B - Sun Standards
+
+The Standard is defined as the following IETF RFCs:
+
+RFC1831: RPC: Remote Procedure Call Protocol Specification
+Version 2 RFC1832: XDR: External Data REpresentation
+Standard RFC1833: Binding Protocols for ONC RPC Version 2
+RFC2078: Generic Security Service Application Program
+Interface, Version 2 RFC2203: RPCSEC_GSS Protocol
+Specification RFC2695: Authentication Mechanisms for ONC RPC
diff --git a/lib/libc/rpc/Makefile.inc b/lib/libc/rpc/Makefile.inc
new file mode 100644
index 0000000..32e8f86
--- /dev/null
+++ b/lib/libc/rpc/Makefile.inc
@@ -0,0 +1,179 @@
+# @(#)Makefile 5.11 (Berkeley) 9/6/90
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/rpc ${.CURDIR}/.
+SRCS+= auth_none.c auth_unix.c authunix_prot.c bindresvport.c clnt_bcast.c \
+ clnt_dg.c clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c \
+ clnt_vc.c rpc_dtablesize.c getnetconfig.c getnetpath.c getrpcent.c \
+ getrpcport.c mt_misc.c pmap_clnt.c pmap_getmaps.c pmap_getport.c \
+ pmap_prot.c pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c \
+ rpc_callmsg.c rpc_generic.c rpc_soc.c rpcb_clnt.c rpcb_prot.c \
+ rpcb_st_xdr.c rpcsec_gss_stub.c svc.c svc_auth.c svc_dg.c \
+ svc_auth_unix.c svc_generic.c svc_raw.c svc_run.c svc_simple.c \
+ svc_vc.c
+
+# Secure-RPC
+SRCS+= auth_time.c auth_des.c authdes_prot.c des_crypt.c des_soft.c \
+ crypt_client.c key_call.c key_prot_xdr.c getpublickey.c \
+ svc_auth_des.c
+
+# Resolver stuff
+SRCS+= netname.c netnamer.c rpcdname.c
+
+# Misc Source
+SRCS+= rtime.c
+
+# generated sources
+SRCS+= crypt_clnt.c crypt_xdr.c crypt.h
+
+SYM_MAPS+=${.CURDIR}/rpc/Symbol.map
+
+CFLAGS+= -DBROKEN_DES -DPORTMAP -DDES_BUILTIN
+CFLAGS+= -I${.CURDIR}/rpc
+
+CLEANFILES+= crypt_clnt.c crypt_xdr.c crypt.h
+
+RPCDIR= ${DESTDIR}/usr/include/rpcsvc
+RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -C
+
+crypt_clnt.c: ${RPCDIR}/crypt.x crypt.h
+ ${RPCGEN} -l -o ${.TARGET} ${RPCDIR}/crypt.x
+
+crypt_xdr.c: ${RPCDIR}/crypt.x crypt.h
+ ${RPCGEN} -c -o ${.TARGET} ${RPCDIR}/crypt.x
+
+crypt.h: ${RPCDIR}/crypt.x
+ ${RPCGEN} -h -o ${.TARGET} ${RPCDIR}/crypt.x
+MAN+= bindresvport.3 des_crypt.3 getnetconfig.3 getnetpath.3 getrpcent.3 \
+ getrpcport.3 rpc.3 rpc_soc.3 rpc_clnt_auth.3 rpc_clnt_calls.3 \
+ rpc_clnt_create.3 rpc_svc_calls.3 rpc_svc_create.3 rpc_svc_err.3 \
+ rpc_svc_reg.3 rpc_xdr.3 rpcbind.3 publickey.3 rpc_secure.3 \
+ rtime.3
+MAN+= publickey.5 rpc.5 netconfig.5
+MLINKS+= bindresvport.3 bindresvport_sa.3 \
+ des_crypt.3 ecb_crypt.3 \
+ des_crypt.3 cbc_crypt.3 \
+ des_crypt.3 des_setparity.3 \
+ getnetconfig.3 setnetconfig.3 \
+ getnetconfig.3 getnetconfigent.3 \
+ getnetconfig.3 freenetconfigent.3 \
+ getnetconfig.3 endnetconfig.3 \
+ getnetconfig.3 nc_perror.3 \
+ getnetconfig.3 nc_sperror.3 \
+ getnetpath.3 setnetpath.3 \
+ getnetpath.3 endnetpath.3 \
+ getrpcent.3 getrpcbyname.3 \
+ getrpcent.3 getrpcbynumber.3 \
+ getrpcent.3 endrpcent.3 \
+ getrpcent.3 setrpcent.3 \
+ publickey.3 getpublickey.3 \
+ publickey.3 getsecretkey.3 \
+ rpc_clnt_auth.3 auth_destroy.3 \
+ rpc_clnt_auth.3 authnone_create.3 \
+ rpc_clnt_auth.3 authsys_create.3 \
+ rpc_clnt_auth.3 authsys_create_default.3 \
+ rpc_clnt_calls.3 clnt_call.3 \
+ rpc_clnt_calls.3 clnt_perrno.3 \
+ rpc_clnt_calls.3 clnt_perror.3 \
+ rpc_clnt_calls.3 clnt_sperrno.3 \
+ rpc_clnt_calls.3 clnt_sperror.3 \
+ rpc_clnt_calls.3 rpc_call.3 \
+ rpc_clnt_calls.3 rpc_broadcast.3 \
+ rpc_clnt_calls.3 rpc_broadcast_exp.3 \
+ rpc_clnt_calls.3 clnt_freeres.3 \
+ rpc_clnt_calls.3 clnt_geterr.3 \
+ rpc_clnt_create.3 clnt_control.3 \
+ rpc_clnt_create.3 clnt_create.3 \
+ rpc_clnt_create.3 clnt_create_timed.3 \
+ rpc_clnt_create.3 clnt_create_vers.3 \
+ rpc_clnt_create.3 clnt_create_vers_timed.3 \
+ rpc_clnt_create.3 clnt_destroy.3 \
+ rpc_clnt_create.3 clnt_pcreateerror.3 \
+ rpc_clnt_create.3 clnt_spcreateerror.3 \
+ rpc_clnt_create.3 clnt_dg_create.3 \
+ rpc_clnt_create.3 clnt_raw_create.3 \
+ rpc_clnt_create.3 clnt_tli_create.3 \
+ rpc_clnt_create.3 clnt_tp_create.3 \
+ rpc_clnt_create.3 clnt_tp_create_timed.3 \
+ rpc_clnt_create.3 clnt_vc_create.3 \
+ rpc_secure.3 authdes_create.3 \
+ rpc_secure.3 authdes_getucred.3 \
+ rpc_secure.3 getnetname.3 \
+ rpc_secure.3 host2netname.3 \
+ rpc_secure.3 key_decryptsession.3 \
+ rpc_secure.3 key_encryptsession.3 \
+ rpc_secure.3 key_gendes.3 \
+ rpc_secure.3 key_setsecret.3 \
+ rpc_secure.3 netname2host.3 \
+ rpc_secure.3 netname2user.3 \
+ rpc_secure.3 user2netname.3 \
+ rpc_svc_calls.3 svc_dg_enablecache.3 \
+ rpc_svc_calls.3 svc_exit.3 \
+ rpc_svc_calls.3 svc_freeargs.3 \
+ rpc_svc_calls.3 svc_getargs.3 \
+ rpc_svc_calls.3 svc_getreq_common.3 \
+ rpc_svc_calls.3 svc_getreq_poll.3 \
+ rpc_svc_calls.3 svc_getreqset.3 \
+ rpc_svc_calls.3 svc_getrpccaller.3 \
+ rpc_svc_calls.3 __svc_getcallercreds.3 \
+ rpc_svc_calls.3 svc_pollset.3 \
+ rpc_svc_calls.3 svc_run.3 \
+ rpc_svc_calls.3 svc_sendreply.3 \
+ rpc_svc_create.3 svc_control.3 \
+ rpc_svc_create.3 svc_create.3 \
+ rpc_svc_create.3 svc_dg_create.3 \
+ rpc_svc_create.3 svc_destroy.3 \
+ rpc_svc_create.3 svc_fd_create.3 \
+ rpc_svc_create.3 svc_raw_create.3 \
+ rpc_svc_create.3 svc_tli_create.3 \
+ rpc_svc_create.3 svc_tp_create.3 \
+ rpc_svc_create.3 svc_vc_create.3 \
+ rpc_svc_err.3 svcerr_auth.3 \
+ rpc_svc_err.3 svcerr_decode.3 \
+ rpc_svc_err.3 svcerr_noproc.3 \
+ rpc_svc_err.3 svcerr_noprog.3 \
+ rpc_svc_err.3 svcerr_progvers.3 \
+ rpc_svc_err.3 svcerr_systemerr.3 \
+ rpc_svc_err.3 svcerr_weakauth.3 \
+ rpc_svc_reg.3 rpc_reg.3 \
+ rpc_svc_reg.3 svc_reg.3 \
+ rpc_svc_reg.3 svc_unreg.3 \
+ rpc_svc_reg.3 svc_auth_reg.3 \
+ rpc_svc_reg.3 xprt_register.3 \
+ rpc_svc_reg.3 xprt_unregister.3 \
+ rpcbind.3 rpcb_getmaps.3 \
+ rpcbind.3 rpcb_getaddr.3 \
+ rpcbind.3 rpcb_gettime.3 \
+ rpcbind.3 rpcb_rmtcall.3 \
+ rpcbind.3 rpcb_set.3 \
+ rpcbind.3 rpcb_unset.3 \
+ rpc_soc.3 authunix_create.3 \
+ rpc_soc.3 authunix_create_default.3 \
+ rpc_soc.3 callrpc.3 \
+ rpc_soc.3 clnt_broadcast.3 \
+ rpc_soc.3 clntraw_create.3 \
+ rpc_soc.3 clnttcp_create.3 \
+ rpc_soc.3 clntunix_create.3 \
+ rpc_soc.3 clntudp_bufcreate.3 \
+ rpc_soc.3 clntudp_create.3 \
+ rpc_soc.3 get_myaddress.3 \
+ rpc_soc.3 pmap_getmaps.3 \
+ rpc_soc.3 pmap_getport.3 \
+ rpc_soc.3 pmap_rmtcall.3 \
+ rpc_soc.3 pmap_set.3 \
+ rpc_soc.3 pmap_unset.3 \
+ rpc_soc.3 registerrpc.3 \
+ rpc_soc.3 rpc_createerr.3 \
+ rpc_soc.3 svc_fds.3 \
+ rpc_soc.3 svc_fdset.3 \
+ rpc_soc.3 svc_getcaller.3 \
+ rpc_soc.3 svc_register.3 \
+ rpc_soc.3 svc_unregister.3 \
+ rpc_soc.3 svcfd_create.3 \
+ rpc_soc.3 svcunixfd_create.3 \
+ rpc_soc.3 svcraw_create.3 \
+ rpc_soc.3 svctcp_create.3 \
+ rpc_soc.3 svcudp_bufcreate.3 \
+ rpc_soc.3 svcunix_create.3 \
+ rpc_soc.3 xdr_pmap.3 \
+ rpc_soc.3 xdr_pmaplist.3
diff --git a/lib/libc/rpc/README b/lib/libc/rpc/README
new file mode 100644
index 0000000..c915fad
--- /dev/null
+++ b/lib/libc/rpc/README
@@ -0,0 +1,176 @@
+$FreeBSD$
+
+PLEASE READ THE DISCLAIMER FILE. DO NOT CALL THE SUN MICROSYSTEMS SUPPORT
+LINE WITH QUESTIONS ON THIS RELEASE. THEY CANNOT ANSWER QUESTIONS ABOUT THIS
+UNSUPPORTED SOURCE RELEASE.
+
+TIRPCSRC 2.3 29 Aug 1994
+
+This distribution contains SunSoft's implementation of transport-independent
+RPC (TI-RPC), External Data Representation (XDR), and various utilities and
+documentation. These libraries and programs form the base of Open Network
+Computing (ONC), and are derived directly from the Solaris 2.3 source.
+
+Previous releases of RPC Source based on SunOS 4.x were ported to 4.2BSD and
+used Sockets as the transport interface. These versions were
+transport-specific RPC (TS-RPC).
+
+TI-RPC is an enhanced version of TS-RPC that requires the UNIX System V
+Transport Layer Interface (TLI) or an equivalent X/Open Transport Interface
+(XTI). TI-RPC is on-the-wire compatible with the TS-RPC, which is supported
+by almost 70 vendors on all major operating systems. TS-RPC source code
+(RPCSRC 4.0) remains available from several internet sites.
+
+This release is a native source release, that is, it is compatible for
+building on Solaris 2.3. This release was built on Solaris 2.3 using SunPro
+SPARCompiler 2.0.1.
+
+Solaris 2.3 is based on System V, Release 4 (SVR4), and while this release
+should be mostly compatible with other SVR4 systems, some Solaris facilities
+that are assumed may not be available. In particular, this release uses the
+Makefile format supported by SparcCompiler 2.0.1. Second, the Secure RPC
+routines use the Solaris Name Service Switch to access public-key credential
+databases. This code will need to be ported if your system does not support
+the Name Service Switch. Finally, this release uses the synchronization
+interfaces of UI Threads to make certain interfaces thread-safe. These
+interfaces are found in libthread in Solaris 2.3 and later.
+
+Applications linked with this release's librpc must link with the United
+States domestic version of libcrypt in order to resolve the cbc_crypt() and
+ecb_crypt() functions. These routines are used with Secure RPC however all
+RPC programs that link with this release's librpc will need to link with the
+domestic libcrypt. Note that the Solaris 2.3 Encryption Kit is only available
+within the United States. (PLEASE NOTE: The RPC implementation found in
+Solaris 2.3's libnsl does *not* have this requirement; linking with libcrypt
+is only a requirement for the TIRPCSRC 2.3 version of librpc.)
+
+
+DOCUMENTATION NOTE
+
+The documentation found in the doc directory are derived from the Solaris 2.3
+Network Interfaces Programming Guide. A small number of compile examples are
+given, and these use libnsl to link in the RPC library. This release builds
+the RPC library as librpc. To use this release's librpc, use the link command
+"-lrpc -lnsl -lcrypt". This links the application with TIRPCSRC 2.3's librpc
+for RPC routines, Solaris's libnsl for other networking functions, and
+libcrypt for the cbc_crypt() and ecb_crypt functions.
+
+
+WHY IS THIS RELEASE BEING DONE?
+
+This release is being distributed to make the Sun implementation of the ONC
+technologies available for reference and porting to non-Solaris platforms.
+The current release is a native source distribution, and provides services
+that are already available on Solaris 2.3 (such as the RPC headers, the RPC
+library in libnsl, rpcbind, rpcinfo, etc.). It is not our intention to
+replace these services. See the DISCLAIMER for further information about the
+legal status of this release.
+
+
+WHAT'S NEW IN THIS RELEASE: TIRPCSRC 2.3
+
+The previous release was TIRPCSRC 2.0.
+
+1. This release is based on Solaris 2.3. The previous release was
+ based on Solaris 2.0. This release contains a siginificant number of
+ bug fixes and other enhancements over TIRPCSRC 2.0.
+
+2. The RPC library is thread safe for all client-side interfaces
+ (clnt_create, clnt_call, etc.). The server-side interfaces
+ (svc_create, svc_run, etc.) are not thread safe in this release. The
+ server-side interfaces will be made thread safe in the next release of
+ TIRPCSRC. Please see the manual pages for details about which
+ interfaces are thread safe.
+
+3. As part of the work to make the RPC library thread-safe, rpcgen has
+ been enhanced to generate thread-safe RPC stubs (the -M option). Note
+ that this modifies the call-signature for the stub functions; the
+ procedure calling the RPC stub must now pass to the stub a pointer to
+ an allocated structure where results will be placed by the stub. See
+ the rpcgen manual page and the rpcgen Programming Guide for details.
+
+4. The Remote Asynchronous Calls (RAC) library is now included. RAC was
+ first introduced in TIRPCSRC 1.0, and was bundled with librpc. It is
+ now a separate library. The asynchronous call model that RAC provides
+ can be achieved by using threads for making client-side RPC calls.
+ The ONC Technology group recommends using threads (where possible) to
+ achieve asynchrony rather than RAC. See the rpc_rac(3n) manual page
+ for details.
+
+
+ROADMAP
+
+The directory hierarchy is as follows:
+
+ cmd/ Utilities
+ cmd/rpcgen The RPC Language compiler (for .x files)
+ cmd/rpcbind The RPC bindery and portmapper
+ cmd/rpcinfo RPC bindery query utility
+ cmd/keyserv The Secure RPC keyserver
+ cmd/demo Some simple ONC demo services
+
+ doc/ Postscript versions of ONC documentation
+
+ head/ Header files
+ head/rpcsvc RPCL (.x) specifications for various ONC services, and
+ header files.
+
+ lib/ Libraries
+ lib/librpc The RPC and XDR library
+ lib/librac The Remote Asynchronous Calls (RAC) library
+
+ man/ Manual pages for the RPC library and utilities.
+
+ uts/common/rpc RPC header files
+
+
+
+BUILD INSTRUCTIONS
+
+Prior to building the release, you must define the SRC environment variable
+to be the path to the top-level Makefile. For example, if /usr/src/tirpcsrc
+is where to top-level Makefile is located, execute this command prior to
+building the release:
+
+ setenv SRC /usr/src/tirpcsrc (csh)
+or
+ SRC=/usr/src/tirpcsrc; export SRC (sh)
+
+The sources in the lib directory depend on header files installed from head
+and uts/common/rpc, and the programs in the cmd directory depend on libraries
+from lib. Therefore, you should do a "make install" to build the release.
+
+The top-level Makefile builds the release. The "ROOT" macro defines where the
+headers and libraries are installed. The default for ROOT is "/proto". You
+may change this by either modifiying Makefile.master, or issuing the build
+command with a new definition for ROOT:
+
+ make install ROOT=/opt/onc
+
+You will of course need write privileges for the destination directory.
+The headers, libraries and executables will be built and installed under the
+ROOT.
+
+
+The demonstration services in the demo directory are not built by the
+top-level "make install" command. To build these, cd to the cmd/demo
+directory and enter "make". The four services will be built.
+RPCGEN MUST BE INSTALLED in a path that make can find. To run the
+services, rpcbind must be running, then invoke the service
+(you probably will want to put it in the background). rpcinfo can be
+used to check that the service succeeded in getting registered with
+rpcbind, and to ping the service (see rpcinfo's man page). You can
+then use the corresponding client program to exercise the service.
+
+
+BUILDING ONC APPLICATIONS
+
+See the Makefiles in the demonstration services for examples of building
+ONC applications with this release. The $(ROOT)/usr/include directory
+must be included in the compiler header file search path (-I), and the
+$(ROOT)/usr/lib directory must be included in the linker library file search
+path (-L). Also, to run executables built dynamically, the shared library
+search path (LD_LIBRARY_PATH) must also include $(ROOT)/usr/lib. In addition
+to linking in this release's librpc (via -lrpc), you must also link with
+Solaris's libnsl (-lnsl) and the US domestic version of libcrypt (-lcrypt).
+
diff --git a/lib/libc/rpc/Symbol.map b/lib/libc/rpc/Symbol.map
new file mode 100644
index 0000000..4f356de
--- /dev/null
+++ b/lib/libc/rpc/Symbol.map
@@ -0,0 +1,247 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ /* From crypt_clnt.c (generated by rpcgen - include/rpcsvc/crypt.x) */
+ des_crypt_1;
+
+ /* From crypt_xdr.c (generated by rpcgen - include/rpcsvc/crypt.x) */
+ xdr_des_dir;
+ xdr_des_mode;
+ xdr_desargs;
+ xdr_desresp;
+
+ /* From yp_xdr.c (generated by rpcgen - include/rpcsvc/yp.x) */
+ xdr_domainname;
+ xdr_keydat;
+ xdr_mapname;
+ xdr_peername;
+ xdr_valdat;
+ xdr_ypbind_binding;
+ xdr_ypbind_resp;
+ xdr_ypbind_resptype;
+ xdr_ypbind_setdom;
+ xdr_ypmap_parms;
+ xdr_ypmaplist;
+ xdr_yppush_status;
+ xdr_yppushresp_xfr;
+ xdr_ypreq_key;
+ xdr_ypreq_nokey;
+ xdr_ypreq_xfr;
+ xdr_ypreqtype;
+ xdr_yprequest;
+ xdr_ypresp_all;
+ xdr_ypresp_key_val;
+ xdr_ypresp_maplist;
+ xdr_ypresp_master;
+ xdr_ypresp_order;
+ xdr_ypresp_val;
+ xdr_ypresp_xfr;
+ xdr_ypresponse;
+ xdr_ypresptype;
+ xdr_ypstat;
+ xdr_ypxfrstat;
+
+ authdes_seccreate;
+ authdes_pk_seccreate;
+ authnone_create;
+ authunix_create;
+ authunix_create_default;
+ xdr_authdes_cred;
+ xdr_authdes_verf;
+ xdr_authunix_parms;
+ bindresvport;
+ bindresvport_sa;
+ rpc_broadcast_exp;
+ rpc_broadcast;
+ clnt_dg_create;
+ clnt_create_vers;
+ clnt_create_vers_timed;
+ clnt_create;
+ clnt_create_timed;
+ clnt_tp_create;
+ clnt_tp_create_timed;
+ clnt_tli_create;
+ clnt_sperror;
+ clnt_perror;
+ clnt_sperrno;
+ clnt_perrno;
+ clnt_spcreateerror;
+ clnt_pcreateerror;
+ clnt_raw_create;
+ rpc_call;
+ clnt_vc_create;
+ cbc_crypt;
+ ecb_crypt;
+ des_setparity;
+ setnetconfig;
+ getnetconfig;
+ endnetconfig;
+ getnetconfigent;
+ freenetconfigent;
+ nc_sperror;
+ nc_perror;
+ setnetpath;
+ getnetpath;
+ endnetpath;
+ getpublicandprivatekey;
+ getpublickey;
+ getrpcbynumber;
+ getrpcbyname;
+ setrpcent;
+ endrpcent;
+ getrpcent;
+ getrpcport;
+ key_setsecret;
+ key_secretkey_is_set;
+ key_encryptsession_pk;
+ key_decryptsession_pk;
+ key_encryptsession;
+ key_decryptsession;
+ key_gendes;
+ key_setnet;
+ key_get_conv;
+ xdr_keystatus;
+ xdr_keybuf;
+ xdr_netnamestr;
+ xdr_cryptkeyarg;
+ xdr_cryptkeyarg2;
+ xdr_cryptkeyres;
+ xdr_unixcred;
+ xdr_getcredres;
+ xdr_key_netstarg;
+ xdr_key_netstres;
+ rpc_createerr;
+ __rpc_createerr;
+ getnetname;
+ user2netname;
+ host2netname;
+ netname2user;
+ netname2host;
+ pmap_set;
+ pmap_unset;
+ pmap_getmaps;
+ pmap_getport;
+ xdr_pmap;
+ xdr_pmaplist;
+ xdr_pmaplist_ptr;
+ pmap_rmtcall;
+ xdr_rmtcall_args;
+ xdr_rmtcallres;
+ xdr_callmsg;
+ _null_auth;
+ svc_fdset;
+ svc_maxfd;
+ _rpc_dtablesize;
+ __rpc_get_t_size;
+ __rpc_getconfip;
+ __rpc_setconf;
+ __rpc_getconf;
+ __rpc_endconf;
+ rpc_nullproc;
+ __rpc_fd2sockinfo;
+ __rpc_nconf2sockinfo;
+ __rpc_nconf2fd;
+ taddr2uaddr;
+ uaddr2taddr;
+ xdr_opaque_auth;
+ xdr_des_block;
+ xdr_accepted_reply;
+ xdr_rejected_reply;
+ xdr_replymsg;
+ xdr_callhdr;
+ _seterr_reply;
+ clntudp_bufcreate;
+ clntudp_create;
+ clnttcp_create;
+ clntraw_create;
+ svctcp_create;
+ svcudp_bufcreate;
+ svcfd_create;
+ svcudp_create;
+ svcraw_create;
+ get_myaddress;
+ callrpc;
+ registerrpc;
+ clnt_broadcast;
+ authdes_create;
+ clntunix_create;
+ svcunix_create;
+ svcunixfd_create;
+ rpcb_set;
+ rpcb_unset;
+ rpcb_getaddr;
+ rpcb_getmaps;
+ rpcb_rmtcall;
+ rpcb_gettime;
+ rpcb_taddr2uaddr;
+ rpcb_uaddr2taddr;
+ xdr_rpcb;
+ xdr_rpcblist_ptr;
+ xdr_rpcblist;
+ xdr_rpcb_entry;
+ xdr_rpcb_entry_list_ptr;
+ xdr_rpcb_rmtcallargs;
+ xdr_rpcb_rmtcallres;
+ xdr_netbuf;
+ xdr_rpcbs_addrlist;
+ xdr_rpcbs_rmtcalllist;
+ xdr_rpcbs_proc;
+ xdr_rpcbs_addrlist_ptr;
+ xdr_rpcbs_rmtcalllist_ptr;
+ xdr_rpcb_stat;
+ xdr_rpcb_stat_byvers;
+ rtime;
+ xprt_register;
+ xprt_unregister;
+ svc_reg;
+ svc_unreg;
+ svc_register;
+ svc_unregister;
+ svc_sendreply;
+ svcerr_noproc;
+ svcerr_decode;
+ svcerr_systemerr;
+ svcerr_auth;
+ svcerr_weakauth;
+ svcerr_noprog;
+ svcerr_progvers;
+ svc_getreq;
+ svc_getreqset;
+ svc_getreq_common;
+ svc_getreq_poll;
+ rpc_control;
+ _authenticate;
+ _svcauth_null;
+ svc_auth_reg;
+ _svcauth_des;
+ authdes_getucred;
+ _svcauth_unix;
+ _svcauth_short;
+ svc_dg_create;
+ svc_dg_enablecache;
+ svc_create;
+ svc_tp_create;
+ svc_tli_create;
+ __rpc_rawcombuf;
+ svc_raw_create;
+ svc_run;
+ svc_exit;
+ rpc_reg;
+ svc_vc_create;
+ svc_fd_create;
+ __rpc_get_local_uid;
+};
+
+FBSDprivate_1.0 {
+ __des_crypt_LOCAL;
+ __key_encryptsession_pk_LOCAL;
+ __key_decryptsession_pk_LOCAL;
+ __key_gendes_LOCAL;
+ __svc_clean_idle;
+ __rpc_gss_unwrap;
+ __rpc_gss_unwrap_stub;
+ __rpc_gss_wrap;
+ __rpc_gss_wrap_stub;
+};
diff --git a/lib/libc/rpc/auth_des.c b/lib/libc/rpc/auth_des.c
new file mode 100644
index 0000000..8f363e9
--- /dev/null
+++ b/lib/libc/rpc/auth_des.c
@@ -0,0 +1,498 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+ */
+/*
+ * auth_des.c, client-side implementation of DES authentication
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <err.h>
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/cdefs.h>
+#include <rpc/des_crypt.h>
+#include <syslog.h>
+#include <rpc/types.h>
+#include <rpc/auth.h>
+#include <rpc/auth_des.h>
+#include <rpc/clnt.h>
+#include <rpc/xdr.h>
+#include <sys/socket.h>
+#undef NIS
+#include <rpcsvc/nis.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)auth_des.c 2.2 88/07/29 4.0 RPCSRC; from 1.9 88/02/08 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define USEC_PER_SEC 1000000
+#define RTIME_TIMEOUT 5 /* seconds to wait for sync */
+
+#define AUTH_PRIVATE(auth) (struct ad_private *) auth->ah_private
+#define ALLOC(object_type) (object_type *) mem_alloc(sizeof(object_type))
+#define FREE(ptr, size) mem_free((char *)(ptr), (int) size)
+#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE)
+
+extern bool_t xdr_authdes_cred( XDR *, struct authdes_cred *);
+extern bool_t xdr_authdes_verf( XDR *, struct authdes_verf *);
+extern int key_encryptsession_pk();
+
+extern bool_t __rpc_get_time_offset(struct timeval *, nis_server *, char *,
+ char **, char **);
+
+/*
+ * DES authenticator operations vector
+ */
+static void authdes_nextverf(AUTH *);
+static bool_t authdes_marshal(AUTH *, XDR *);
+static bool_t authdes_validate(AUTH *, struct opaque_auth *);
+static bool_t authdes_refresh(AUTH *, void *);
+static void authdes_destroy(AUTH *);
+
+static struct auth_ops *authdes_ops(void);
+
+/*
+ * This struct is pointed to by the ah_private field of an "AUTH *"
+ */
+struct ad_private {
+ char *ad_fullname; /* client's full name */
+ u_int ad_fullnamelen; /* length of name, rounded up */
+ char *ad_servername; /* server's full name */
+ u_int ad_servernamelen; /* length of name, rounded up */
+ u_int ad_window; /* client specified window */
+ bool_t ad_dosync; /* synchronize? */
+ struct netbuf ad_syncaddr; /* remote host to synch with */
+ char *ad_timehost; /* remote host to synch with */
+ struct timeval ad_timediff; /* server's time - client's time */
+ u_int ad_nickname; /* server's nickname for client */
+ struct authdes_cred ad_cred; /* storage for credential */
+ struct authdes_verf ad_verf; /* storage for verifier */
+ struct timeval ad_timestamp; /* timestamp sent */
+ des_block ad_xkey; /* encrypted conversation key */
+ u_char ad_pkey[1024]; /* Server's actual public key */
+ char *ad_netid; /* Timehost netid */
+ char *ad_uaddr; /* Timehost uaddr */
+ nis_server *ad_nis_srvr; /* NIS+ server struct */
+};
+
+AUTH *authdes_pk_seccreate(const char *, netobj *, u_int, const char *,
+ const des_block *, nis_server *);
+
+/*
+ * documented version of authdes_seccreate
+ */
+/*
+ servername: network name of server
+ win: time to live
+ timehost: optional hostname to sync with
+ ckey: optional conversation key to use
+*/
+
+AUTH *
+authdes_seccreate(const char *servername, const u_int win,
+ const char *timehost, const des_block *ckey)
+{
+ u_char pkey_data[1024];
+ netobj pkey;
+ AUTH *dummy;
+
+ if (! getpublickey(servername, (char *) pkey_data)) {
+ syslog(LOG_ERR,
+ "authdes_seccreate: no public key found for %s",
+ servername);
+ return (NULL);
+ }
+
+ pkey.n_bytes = (char *) pkey_data;
+ pkey.n_len = (u_int)strlen((char *)pkey_data) + 1;
+ dummy = authdes_pk_seccreate(servername, &pkey, win, timehost,
+ ckey, NULL);
+ return (dummy);
+}
+
+/*
+ * Slightly modified version of authdessec_create which takes the public key
+ * of the server principal as an argument. This spares us a call to
+ * getpublickey() which in the nameserver context can cause a deadlock.
+ */
+AUTH *
+authdes_pk_seccreate(const char *servername, netobj *pkey, u_int window,
+ const char *timehost, const des_block *ckey, nis_server *srvr)
+{
+ AUTH *auth;
+ struct ad_private *ad;
+ char namebuf[MAXNETNAMELEN+1];
+
+ /*
+ * Allocate everything now
+ */
+ auth = ALLOC(AUTH);
+ if (auth == NULL) {
+ syslog(LOG_ERR, "authdes_pk_seccreate: out of memory");
+ return (NULL);
+ }
+ ad = ALLOC(struct ad_private);
+ if (ad == NULL) {
+ syslog(LOG_ERR, "authdes_pk_seccreate: out of memory");
+ goto failed;
+ }
+ ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */
+ ad->ad_timehost = NULL;
+ ad->ad_netid = NULL;
+ ad->ad_uaddr = NULL;
+ ad->ad_nis_srvr = NULL;
+ ad->ad_timediff.tv_sec = 0;
+ ad->ad_timediff.tv_usec = 0;
+ memcpy(ad->ad_pkey, pkey->n_bytes, pkey->n_len);
+ if (!getnetname(namebuf))
+ goto failed;
+ ad->ad_fullnamelen = RNDUP((u_int) strlen(namebuf));
+ ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1);
+ ad->ad_servernamelen = strlen(servername);
+ ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1);
+
+ if (ad->ad_fullname == NULL || ad->ad_servername == NULL) {
+ syslog(LOG_ERR, "authdes_seccreate: out of memory");
+ goto failed;
+ }
+ if (timehost != NULL) {
+ ad->ad_timehost = (char *)mem_alloc(strlen(timehost) + 1);
+ if (ad->ad_timehost == NULL) {
+ syslog(LOG_ERR, "authdes_seccreate: out of memory");
+ goto failed;
+ }
+ memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1);
+ ad->ad_dosync = TRUE;
+ } else if (srvr != NULL) {
+ ad->ad_nis_srvr = srvr; /* transient */
+ ad->ad_dosync = TRUE;
+ } else {
+ ad->ad_dosync = FALSE;
+ }
+ memcpy(ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1);
+ memcpy(ad->ad_servername, servername, ad->ad_servernamelen + 1);
+ ad->ad_window = window;
+ if (ckey == NULL) {
+ if (key_gendes(&auth->ah_key) < 0) {
+ syslog(LOG_ERR,
+ "authdes_seccreate: keyserv(1m) is unable to generate session key");
+ goto failed;
+ }
+ } else {
+ auth->ah_key = *ckey;
+ }
+
+ /*
+ * Set up auth handle
+ */
+ auth->ah_cred.oa_flavor = AUTH_DES;
+ auth->ah_verf.oa_flavor = AUTH_DES;
+ auth->ah_ops = authdes_ops();
+ auth->ah_private = (caddr_t)ad;
+
+ if (!authdes_refresh(auth, NULL)) {
+ goto failed;
+ }
+ ad->ad_nis_srvr = NULL; /* not needed any longer */
+ return (auth);
+
+failed:
+ if (auth)
+ FREE(auth, sizeof (AUTH));
+ if (ad) {
+ if (ad->ad_fullname)
+ FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
+ if (ad->ad_servername)
+ FREE(ad->ad_servername, ad->ad_servernamelen + 1);
+ if (ad->ad_timehost)
+ FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1);
+ if (ad->ad_netid)
+ FREE(ad->ad_netid, strlen(ad->ad_netid) + 1);
+ if (ad->ad_uaddr)
+ FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1);
+ FREE(ad, sizeof (struct ad_private));
+ }
+ return (NULL);
+}
+
+/*
+ * Implement the five authentication operations
+ */
+
+
+/*
+ * 1. Next Verifier
+ */
+/*ARGSUSED*/
+static void
+authdes_nextverf(AUTH *auth)
+{
+ /* what the heck am I supposed to do??? */
+}
+
+
+/*
+ * 2. Marshal
+ */
+static bool_t
+authdes_marshal(AUTH *auth, XDR *xdrs)
+{
+/* LINTED pointer alignment */
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+ struct authdes_cred *cred = &ad->ad_cred;
+ struct authdes_verf *verf = &ad->ad_verf;
+ des_block cryptbuf[2];
+ des_block ivec;
+ int status;
+ int len;
+ rpc_inline_t *ixdr;
+
+ /*
+ * Figure out the "time", accounting for any time difference
+ * with the server if necessary.
+ */
+ (void) gettimeofday(&ad->ad_timestamp, (struct timezone *)NULL);
+ ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec;
+ ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec;
+ while (ad->ad_timestamp.tv_usec >= USEC_PER_SEC) {
+ ad->ad_timestamp.tv_usec -= USEC_PER_SEC;
+ ad->ad_timestamp.tv_sec++;
+ }
+
+ /*
+ * XDR the timestamp and possibly some other things, then
+ * encrypt them.
+ */
+ ixdr = (rpc_inline_t *)cryptbuf;
+ IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_sec);
+ IXDR_PUT_INT32(ixdr, ad->ad_timestamp.tv_usec);
+ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
+ IXDR_PUT_U_INT32(ixdr, ad->ad_window);
+ IXDR_PUT_U_INT32(ixdr, ad->ad_window - 1);
+ ivec.key.high = ivec.key.low = 0;
+ status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf,
+ (u_int) 2 * sizeof (des_block),
+ DES_ENCRYPT | DES_HW, (char *)&ivec);
+ } else {
+ status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf,
+ (u_int) sizeof (des_block),
+ DES_ENCRYPT | DES_HW);
+ }
+ if (DES_FAILED(status)) {
+ syslog(LOG_ERR, "authdes_marshal: DES encryption failure");
+ return (FALSE);
+ }
+ ad->ad_verf.adv_xtimestamp = cryptbuf[0];
+ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
+ ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high;
+ ad->ad_verf.adv_winverf = cryptbuf[1].key.low;
+ } else {
+ ad->ad_cred.adc_nickname = ad->ad_nickname;
+ ad->ad_verf.adv_winverf = 0;
+ }
+
+ /*
+ * Serialize the credential and verifier into opaque
+ * authentication data.
+ */
+ if (ad->ad_cred.adc_namekind == ADN_FULLNAME) {
+ len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen);
+ } else {
+ len = (1 + 1)*BYTES_PER_XDR_UNIT;
+ }
+
+ if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
+ IXDR_PUT_INT32(ixdr, AUTH_DES);
+ IXDR_PUT_INT32(ixdr, len);
+ } else {
+ ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_cred.oa_flavor));
+ ATTEMPT(xdr_putint32(xdrs, &len));
+ }
+ ATTEMPT(xdr_authdes_cred(xdrs, cred));
+
+ len = (2 + 1)*BYTES_PER_XDR_UNIT;
+ if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) {
+ IXDR_PUT_INT32(ixdr, AUTH_DES);
+ IXDR_PUT_INT32(ixdr, len);
+ } else {
+ ATTEMPT(xdr_putint32(xdrs, (int *)&auth->ah_verf.oa_flavor));
+ ATTEMPT(xdr_putint32(xdrs, &len));
+ }
+ ATTEMPT(xdr_authdes_verf(xdrs, verf));
+ return (TRUE);
+}
+
+
+/*
+ * 3. Validate
+ */
+static bool_t
+authdes_validate(AUTH *auth, struct opaque_auth *rverf)
+{
+/* LINTED pointer alignment */
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+ struct authdes_verf verf;
+ int status;
+ uint32_t *ixdr;
+ des_block buf;
+
+ if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) {
+ return (FALSE);
+ }
+/* LINTED pointer alignment */
+ ixdr = (uint32_t *)rverf->oa_base;
+ buf.key.high = (uint32_t)*ixdr++;
+ buf.key.low = (uint32_t)*ixdr++;
+ verf.adv_int_u = (uint32_t)*ixdr++;
+
+ /*
+ * Decrypt the timestamp
+ */
+ status = ecb_crypt((char *)&auth->ah_key, (char *)&buf,
+ (u_int)sizeof (des_block), DES_DECRYPT | DES_HW);
+
+ if (DES_FAILED(status)) {
+ syslog(LOG_ERR, "authdes_validate: DES decryption failure");
+ return (FALSE);
+ }
+
+ /*
+ * xdr the decrypted timestamp
+ */
+/* LINTED pointer alignment */
+ ixdr = (uint32_t *)buf.c;
+ verf.adv_timestamp.tv_sec = IXDR_GET_INT32(ixdr) + 1;
+ verf.adv_timestamp.tv_usec = IXDR_GET_INT32(ixdr);
+
+ /*
+ * validate
+ */
+ if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp,
+ sizeof(struct timeval)) != 0) {
+ syslog(LOG_DEBUG, "authdes_validate: verifier mismatch");
+ return (FALSE);
+ }
+
+ /*
+ * We have a nickname now, let's use it
+ */
+ ad->ad_nickname = verf.adv_nickname;
+ ad->ad_cred.adc_namekind = ADN_NICKNAME;
+ return (TRUE);
+}
+
+/*
+ * 4. Refresh
+ */
+/*ARGSUSED*/
+static bool_t
+authdes_refresh(AUTH *auth, void *dummy)
+{
+/* LINTED pointer alignment */
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+ struct authdes_cred *cred = &ad->ad_cred;
+ int ok;
+ netobj pkey;
+
+ if (ad->ad_dosync) {
+ ok = __rpc_get_time_offset(&ad->ad_timediff, ad->ad_nis_srvr,
+ ad->ad_timehost, &(ad->ad_uaddr),
+ &(ad->ad_netid));
+ if (! ok) {
+ /*
+ * Hope the clocks are synced!
+ */
+ ad->ad_dosync = 0;
+ syslog(LOG_DEBUG,
+ "authdes_refresh: unable to synchronize clock");
+ }
+ }
+ ad->ad_xkey = auth->ah_key;
+ pkey.n_bytes = (char *)(ad->ad_pkey);
+ pkey.n_len = (u_int)strlen((char *)ad->ad_pkey) + 1;
+ if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) {
+ syslog(LOG_INFO,
+ "authdes_refresh: keyserv(1m) is unable to encrypt session key");
+ return (FALSE);
+ }
+ cred->adc_fullname.key = ad->ad_xkey;
+ cred->adc_namekind = ADN_FULLNAME;
+ cred->adc_fullname.name = ad->ad_fullname;
+ return (TRUE);
+}
+
+
+/*
+ * 5. Destroy
+ */
+static void
+authdes_destroy(AUTH *auth)
+{
+/* LINTED pointer alignment */
+ struct ad_private *ad = AUTH_PRIVATE(auth);
+
+ FREE(ad->ad_fullname, ad->ad_fullnamelen + 1);
+ FREE(ad->ad_servername, ad->ad_servernamelen + 1);
+ if (ad->ad_timehost)
+ FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1);
+ if (ad->ad_netid)
+ FREE(ad->ad_netid, strlen(ad->ad_netid) + 1);
+ if (ad->ad_uaddr)
+ FREE(ad->ad_uaddr, strlen(ad->ad_uaddr) + 1);
+ FREE(ad, sizeof (struct ad_private));
+ FREE(auth, sizeof(AUTH));
+}
+
+static struct auth_ops *
+authdes_ops(void)
+{
+ static struct auth_ops ops;
+
+ /* VARIABLES PROTECTED BY ops_lock: ops */
+
+ mutex_lock(&authdes_ops_lock);
+ if (ops.ah_nextverf == NULL) {
+ ops.ah_nextverf = authdes_nextverf;
+ ops.ah_marshal = authdes_marshal;
+ ops.ah_validate = authdes_validate;
+ ops.ah_refresh = authdes_refresh;
+ ops.ah_destroy = authdes_destroy;
+ }
+ mutex_unlock(&authdes_ops_lock);
+ return (&ops);
+}
diff --git a/lib/libc/rpc/auth_none.c b/lib/libc/rpc/auth_none.c
new file mode 100644
index 0000000..01ad701
--- /dev/null
+++ b/lib/libc/rpc/auth_none.c
@@ -0,0 +1,176 @@
+/* $NetBSD: auth_none.c,v 1.13 2000/01/22 22:19:17 mycroft Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)auth_none.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * auth_none.c
+ * Creates a client authentication handle for passing "null"
+ * credentials and verifiers to remote systems.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+#define MAX_MARSHAL_SIZE 20
+
+/*
+ * Authenticator operations routines
+ */
+
+static bool_t authnone_marshal (AUTH *, XDR *);
+static void authnone_verf (AUTH *);
+static bool_t authnone_validate (AUTH *, struct opaque_auth *);
+static bool_t authnone_refresh (AUTH *, void *);
+static void authnone_destroy (AUTH *);
+
+extern bool_t xdr_opaque_auth();
+
+static struct auth_ops *authnone_ops();
+
+static struct authnone_private {
+ AUTH no_client;
+ char marshalled_client[MAX_MARSHAL_SIZE];
+ u_int mcnt;
+} *authnone_private;
+
+AUTH *
+authnone_create()
+{
+ struct authnone_private *ap = authnone_private;
+ XDR xdr_stream;
+ XDR *xdrs;
+
+ mutex_lock(&authnone_lock);
+ if (ap == 0) {
+ ap = (struct authnone_private *)calloc(1, sizeof (*ap));
+ if (ap == 0) {
+ mutex_unlock(&authnone_lock);
+ return (0);
+ }
+ authnone_private = ap;
+ }
+ if (!ap->mcnt) {
+ ap->no_client.ah_cred = ap->no_client.ah_verf = _null_auth;
+ ap->no_client.ah_ops = authnone_ops();
+ xdrs = &xdr_stream;
+ xdrmem_create(xdrs, ap->marshalled_client,
+ (u_int)MAX_MARSHAL_SIZE, XDR_ENCODE);
+ (void)xdr_opaque_auth(xdrs, &ap->no_client.ah_cred);
+ (void)xdr_opaque_auth(xdrs, &ap->no_client.ah_verf);
+ ap->mcnt = XDR_GETPOS(xdrs);
+ XDR_DESTROY(xdrs);
+ }
+ mutex_unlock(&authnone_lock);
+ return (&ap->no_client);
+}
+
+/*ARGSUSED*/
+static bool_t
+authnone_marshal(AUTH *client, XDR *xdrs)
+{
+ struct authnone_private *ap;
+ bool_t dummy;
+
+ assert(xdrs != NULL);
+
+ ap = authnone_private;
+ if (ap == NULL) {
+ mutex_unlock(&authnone_lock);
+ return (FALSE);
+ }
+ dummy = (*xdrs->x_ops->x_putbytes)(xdrs,
+ ap->marshalled_client, ap->mcnt);
+ mutex_unlock(&authnone_lock);
+ return (dummy);
+}
+
+/* All these unused parameters are required to keep ANSI-C from grumbling */
+/*ARGSUSED*/
+static void
+authnone_verf(AUTH *client)
+{
+}
+
+/*ARGSUSED*/
+static bool_t
+authnone_validate(AUTH *client, struct opaque_auth *opaque)
+{
+
+ return (TRUE);
+}
+
+/*ARGSUSED*/
+static bool_t
+authnone_refresh(AUTH *client, void *dummy)
+{
+
+ return (FALSE);
+}
+
+/*ARGSUSED*/
+static void
+authnone_destroy(AUTH *client)
+{
+}
+
+static struct auth_ops *
+authnone_ops()
+{
+ static struct auth_ops ops;
+
+/* VARIABLES PROTECTED BY ops_lock: ops */
+
+ mutex_lock(&ops_lock);
+ if (ops.ah_nextverf == NULL) {
+ ops.ah_nextverf = authnone_verf;
+ ops.ah_marshal = authnone_marshal;
+ ops.ah_validate = authnone_validate;
+ ops.ah_refresh = authnone_refresh;
+ ops.ah_destroy = authnone_destroy;
+ }
+ mutex_unlock(&ops_lock);
+ return (&ops);
+}
diff --git a/lib/libc/rpc/auth_time.c b/lib/libc/rpc/auth_time.c
new file mode 100644
index 0000000..7aea232
--- /dev/null
+++ b/lib/libc/rpc/auth_time.c
@@ -0,0 +1,507 @@
+/* #pragma ident "@(#)auth_time.c 1.4 92/11/10 SMI" */
+
+/*
+ * auth_time.c
+ *
+ * This module contains the private function __rpc_get_time_offset()
+ * which will return the difference in seconds between the local system's
+ * notion of time and a remote server's notion of time. This must be
+ * possible without calling any functions that may invoke the name
+ * service. (netdir_getbyxxx, getXbyY, etc). The function is used in the
+ * synchronize call of the authdes code to synchronize clocks between
+ * NIS+ clients and their servers.
+ *
+ * Note to minimize the amount of duplicate code, portions of the
+ * synchronize() function were folded into this code, and the synchronize
+ * call becomes simply a wrapper around this function. Further, if this
+ * function is called with a timehost it *DOES* recurse to the name
+ * server so don't use it in that mode if you are doing name service code.
+ *
+ * Copyright (c) 1992 Sun Microsystems Inc.
+ * All rights reserved.
+ *
+ * Side effects :
+ * When called a client handle to a RPCBIND process is created
+ * and destroyed. Two strings "netid" and "uaddr" are malloc'd
+ * and returned. The SIGALRM processing is modified only if
+ * needed to deal with TCP connections.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <syslog.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/signal.h>
+#include <sys/errno.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include <rpc/rpc_com.h>
+#include <rpc/rpcb_prot.h>
+#undef NIS
+#include <rpcsvc/nis.h>
+#include "un-namespace.h"
+
+extern int _rpc_dtablesize( void );
+
+#ifdef TESTING
+#define msg(x) printf("ERROR: %s\n", x)
+/* #define msg(x) syslog(LOG_ERR, "%s", x) */
+#else
+#define msg(x)
+#endif
+
+static int saw_alarm = 0;
+
+static void
+alarm_hndler(s)
+ int s;
+{
+ saw_alarm = 1;
+ return;
+}
+
+/*
+ * The internet time server defines the epoch to be Jan 1, 1900
+ * whereas UNIX defines it to be Jan 1, 1970. To adjust the result
+ * from internet time-service time, into UNIX time we subtract the
+ * following offset :
+ */
+#define NYEARS (1970 - 1900)
+#define TOFFSET ((u_long)60*60*24*(365*NYEARS + (NYEARS/4)))
+
+
+/*
+ * Stolen from rpc.nisd:
+ * Turn a 'universal address' into a struct sockaddr_in.
+ * Bletch.
+ */
+static int uaddr_to_sockaddr(uaddr, sin)
+#ifdef foo
+ endpoint *endpt;
+#endif
+ char *uaddr;
+ struct sockaddr_in *sin;
+{
+ unsigned char p_bytes[2];
+ int i;
+ unsigned long a[6];
+
+ i = sscanf(uaddr, "%lu.%lu.%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2],
+ &a[3], &a[4], &a[5]);
+
+ if (i < 6)
+ return(1);
+
+ for (i = 0; i < 4; i++)
+ sin->sin_addr.s_addr |= (a[i] & 0x000000FF) << (8 * i);
+
+ p_bytes[0] = (unsigned char)a[4] & 0x000000FF;
+ p_bytes[1] = (unsigned char)a[5] & 0x000000FF;
+
+ sin->sin_family = AF_INET; /* always */
+ bcopy((char *)&p_bytes, (char *)&sin->sin_port, 2);
+
+ return (0);
+}
+
+/*
+ * free_eps()
+ *
+ * Free the strings that were strduped into the eps structure.
+ */
+static void
+free_eps(eps, num)
+ endpoint eps[];
+ int num;
+{
+ int i;
+
+ for (i = 0; i < num; i++) {
+ free(eps[i].uaddr);
+ free(eps[i].proto);
+ free(eps[i].family);
+ }
+ return;
+}
+
+/*
+ * get_server()
+ *
+ * This function constructs a nis_server structure description for the
+ * indicated hostname.
+ *
+ * NOTE: There is a chance we may end up recursing here due to the
+ * fact that gethostbyname() could do an NIS search. Ideally, the
+ * NIS+ server will call __rpc_get_time_offset() with the nis_server
+ * structure already populated.
+ */
+static nis_server *
+get_server(sin, host, srv, eps, maxep)
+ struct sockaddr_in *sin;
+ char *host; /* name of the time host */
+ nis_server *srv; /* nis_server struct to use. */
+ endpoint eps[]; /* array of endpoints */
+ int maxep; /* max array size */
+{
+ char hname[256];
+ int num_ep = 0, i;
+ struct hostent *he;
+ struct hostent dummy;
+ char *ptr[2];
+ endpoint *ep;
+
+ if (host == NULL && sin == NULL)
+ return (NULL);
+
+ if (sin == NULL) {
+ he = gethostbyname(host);
+ if (he == NULL)
+ return(NULL);
+ } else {
+ he = &dummy;
+ ptr[0] = (char *)&sin->sin_addr.s_addr;
+ ptr[1] = NULL;
+ dummy.h_addr_list = ptr;
+ }
+
+ /*
+ * This is lame. We go around once for TCP, then again
+ * for UDP.
+ */
+ for (i = 0, ep = eps; (he->h_addr_list[i] != NULL) && (num_ep < maxep);
+ i++, ep++, num_ep++) {
+ struct in_addr *a;
+
+ a = (struct in_addr *)he->h_addr_list[i];
+ snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a));
+ ep->uaddr = strdup(hname);
+ ep->family = strdup("inet");
+ ep->proto = strdup("tcp");
+ if (ep->uaddr == NULL || ep->family == NULL || ep->proto == NULL) {
+ free_eps(eps, num_ep + 1);
+ return (NULL);
+ }
+ }
+
+ for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep);
+ i++, ep++, num_ep++) {
+ struct in_addr *a;
+
+ a = (struct in_addr *)he->h_addr_list[i];
+ snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a));
+ ep->uaddr = strdup(hname);
+ ep->family = strdup("inet");
+ ep->proto = strdup("udp");
+ if (ep->uaddr == NULL || ep->family == NULL || ep->proto == NULL) {
+ free_eps(eps, num_ep + 1);
+ return (NULL);
+ }
+ }
+
+ srv->name = (nis_name) host;
+ srv->ep.ep_len = num_ep;
+ srv->ep.ep_val = eps;
+ srv->key_type = NIS_PK_NONE;
+ srv->pkey.n_bytes = NULL;
+ srv->pkey.n_len = 0;
+ return (srv);
+}
+
+/*
+ * __rpc_get_time_offset()
+ *
+ * This function uses a nis_server structure to contact the a remote
+ * machine (as named in that structure) and returns the offset in time
+ * between that machine and this one. This offset is returned in seconds
+ * and may be positive or negative.
+ *
+ * The first time through, a lot of fiddling is done with the netconfig
+ * stuff to find a suitable transport. The function is very aggressive
+ * about choosing UDP or at worst TCP if it can. This is because
+ * those transports support both the RCPBIND call and the internet
+ * time service.
+ *
+ * Once through, *uaddr is set to the universal address of
+ * the machine and *netid is set to the local netid for the transport
+ * that uaddr goes with. On the second call, the netconfig stuff
+ * is skipped and the uaddr/netid pair are used to fetch the netconfig
+ * structure and to then contact the machine for the time.
+ *
+ * td = "server" - "client"
+ */
+int
+__rpc_get_time_offset(td, srv, thost, uaddr, netid)
+ struct timeval *td; /* Time difference */
+ nis_server *srv; /* NIS Server description */
+ char *thost; /* if no server, this is the timehost */
+ char **uaddr; /* known universal address */
+ struct sockaddr_in *netid; /* known network identifier */
+{
+ CLIENT *clnt; /* Client handle */
+ endpoint *ep, /* useful endpoints */
+ *useep = NULL; /* endpoint of xp */
+ char *useua = NULL; /* uaddr of selected xp */
+ int epl, i; /* counters */
+ enum clnt_stat status; /* result of clnt_call */
+ u_long thetime, delta;
+ int needfree = 0;
+ struct timeval tv;
+ int time_valid;
+ int udp_ep = -1, tcp_ep = -1;
+ int a1, a2, a3, a4;
+ char ut[64], ipuaddr[64];
+ endpoint teps[32];
+ nis_server tsrv;
+ void (*oldsig)() = NULL; /* old alarm handler */
+ struct sockaddr_in sin;
+ socklen_t len;
+ int s = RPC_ANYSOCK;
+ int type = 0;
+
+ td->tv_sec = 0;
+ td->tv_usec = 0;
+
+ /*
+ * First check to see if we need to find and address for this
+ * server.
+ */
+ if (*uaddr == NULL) {
+ if ((srv != NULL) && (thost != NULL)) {
+ msg("both timehost and srv pointer used!");
+ return (0);
+ }
+ if (! srv) {
+ srv = get_server(netid, thost, &tsrv, teps, 32);
+ if (srv == NULL) {
+ msg("unable to contruct server data.");
+ return (0);
+ }
+ needfree = 1; /* need to free data in endpoints */
+ }
+
+ ep = srv->ep.ep_val;
+ epl = srv->ep.ep_len;
+
+ /* Identify the TCP and UDP endpoints */
+ for (i = 0;
+ (i < epl) && ((udp_ep == -1) || (tcp_ep == -1)); i++) {
+ if (strcasecmp(ep[i].proto, "udp") == 0)
+ udp_ep = i;
+ if (strcasecmp(ep[i].proto, "tcp") == 0)
+ tcp_ep = i;
+ }
+
+ /* Check to see if it is UDP or TCP */
+ if (tcp_ep > -1) {
+ useep = &ep[tcp_ep];
+ useua = ep[tcp_ep].uaddr;
+ type = SOCK_STREAM;
+ } else if (udp_ep > -1) {
+ useep = &ep[udp_ep];
+ useua = ep[udp_ep].uaddr;
+ type = SOCK_DGRAM;
+ }
+
+ if (useep == NULL) {
+ msg("no acceptable transport endpoints.");
+ if (needfree)
+ free_eps(teps, tsrv.ep.ep_len);
+ return (0);
+ }
+ }
+
+ /*
+ * Create a sockaddr from the uaddr.
+ */
+ if (*uaddr != NULL)
+ useua = *uaddr;
+
+ /* Fixup test for NIS+ */
+ sscanf(useua, "%d.%d.%d.%d.", &a1, &a2, &a3, &a4);
+ sprintf(ipuaddr, "%d.%d.%d.%d.0.111", a1, a2, a3, a4);
+ useua = &ipuaddr[0];
+
+ bzero((char *)&sin, sizeof(sin));
+ if (uaddr_to_sockaddr(useua, &sin)) {
+ msg("unable to translate uaddr to sockaddr.");
+ if (needfree)
+ free_eps(teps, tsrv.ep.ep_len);
+ return (0);
+ }
+
+ /*
+ * Create the client handle to rpcbind. Note we always try
+ * version 3 since that is the earliest version that supports
+ * the RPCB_GETTIME call. Also it is the version that comes
+ * standard with SVR4. Since most everyone supports TCP/IP
+ * we could consider trying the rtime call first.
+ */
+ clnt = clnttcp_create(&sin, RPCBPROG, RPCBVERS, &s, 0, 0);
+ if (clnt == NULL) {
+ msg("unable to create client handle to rpcbind.");
+ if (needfree)
+ free_eps(teps, tsrv.ep.ep_len);
+ return (0);
+ }
+
+ tv.tv_sec = 5;
+ tv.tv_usec = 0;
+ time_valid = 0;
+ status = clnt_call(clnt, RPCBPROC_GETTIME, (xdrproc_t)xdr_void, NULL,
+ (xdrproc_t)xdr_u_long, &thetime, tv);
+ /*
+ * The only error we check for is anything but success. In
+ * fact we could have seen PROGMISMATCH if talking to a 4.1
+ * machine (pmap v2) or TIMEDOUT if the net was busy.
+ */
+ if (status == RPC_SUCCESS)
+ time_valid = 1;
+ else {
+ int save;
+
+ /* Blow away possible stale CLNT handle. */
+ if (clnt != NULL) {
+ clnt_destroy(clnt);
+ clnt = NULL;
+ }
+
+ /*
+ * Convert PMAP address into timeservice address
+ * We take advantage of the fact that we "know" what
+ * the universal address looks like for inet transports.
+ *
+ * We also know that the internet timeservice is always
+ * listening on port 37.
+ */
+ sscanf(useua, "%d.%d.%d.%d.", &a1, &a2, &a3, &a4);
+ sprintf(ut, "%d.%d.%d.%d.0.37", a1, a2, a3, a4);
+
+ if (uaddr_to_sockaddr(ut, &sin)) {
+ msg("cannot convert timeservice uaddr to sockaddr.");
+ goto error;
+ }
+
+ s = _socket(AF_INET, type, 0);
+ if (s == -1) {
+ msg("unable to open fd to network.");
+ goto error;
+ }
+
+ /*
+ * Now depending on whether or not we're talking to
+ * UDP we set a timeout or not.
+ */
+ if (type == SOCK_DGRAM) {
+ struct timeval timeout = { 20, 0 };
+ struct sockaddr_in from;
+ fd_set readfds;
+ int res;
+
+ if (_sendto(s, &thetime, sizeof(thetime), 0,
+ (struct sockaddr *)&sin, sizeof(sin)) == -1) {
+ msg("udp : sendto failed.");
+ goto error;
+ }
+ do {
+ FD_ZERO(&readfds);
+ FD_SET(s, &readfds);
+ res = _select(_rpc_dtablesize(), &readfds,
+ (fd_set *)NULL, (fd_set *)NULL, &timeout);
+ } while (res < 0 && errno == EINTR);
+ if (res <= 0)
+ goto error;
+ len = sizeof(from);
+ res = _recvfrom(s, (char *)&thetime, sizeof(thetime), 0,
+ (struct sockaddr *)&from, &len);
+ if (res == -1) {
+ msg("recvfrom failed on udp transport.");
+ goto error;
+ }
+ time_valid = 1;
+ } else {
+ int res;
+
+ oldsig = (void (*)())signal(SIGALRM, alarm_hndler);
+ saw_alarm = 0; /* global tracking the alarm */
+ alarm(20); /* only wait 20 seconds */
+ res = _connect(s, (struct sockaddr *)&sin, sizeof(sin));
+ if (res == -1) {
+ msg("failed to connect to tcp endpoint.");
+ goto error;
+ }
+ if (saw_alarm) {
+ msg("alarm caught it, must be unreachable.");
+ goto error;
+ }
+ res = _read(s, (char *)&thetime, sizeof(thetime));
+ if (res != sizeof(thetime)) {
+ if (saw_alarm)
+ msg("timed out TCP call.");
+ else
+ msg("wrong size of results returned");
+
+ goto error;
+ }
+ time_valid = 1;
+ }
+ save = errno;
+ (void)_close(s);
+ errno = save;
+ s = RPC_ANYSOCK;
+
+ if (time_valid) {
+ thetime = ntohl(thetime);
+ thetime = thetime - TOFFSET; /* adjust to UNIX time */
+ } else
+ thetime = 0;
+ }
+
+ gettimeofday(&tv, 0);
+
+error:
+ /*
+ * clean up our allocated data structures.
+ */
+
+ if (s != RPC_ANYSOCK)
+ (void)_close(s);
+
+ if (clnt != NULL)
+ clnt_destroy(clnt);
+
+ alarm(0); /* reset that alarm if its outstanding */
+ if (oldsig) {
+ signal(SIGALRM, oldsig);
+ }
+
+ /*
+ * note, don't free uaddr strings until after we've made a
+ * copy of them.
+ */
+ if (time_valid) {
+ if (*uaddr == NULL)
+ *uaddr = strdup(useua);
+
+ /* Round to the nearest second */
+ tv.tv_sec += (tv.tv_sec > 500000) ? 1 : 0;
+ delta = (thetime > tv.tv_sec) ? thetime - tv.tv_sec :
+ tv.tv_sec - thetime;
+ td->tv_sec = (thetime < tv.tv_sec) ? - delta : delta;
+ td->tv_usec = 0;
+ } else {
+ msg("unable to get the server's time.");
+ }
+
+ if (needfree)
+ free_eps(teps, tsrv.ep.ep_len);
+
+ return (time_valid);
+}
diff --git a/lib/libc/rpc/auth_unix.c b/lib/libc/rpc/auth_unix.c
new file mode 100644
index 0000000..ff3ca7b
--- /dev/null
+++ b/lib/libc/rpc/auth_unix.c
@@ -0,0 +1,381 @@
+/* $NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * auth_unix.c, Implements UNIX style authentication parameters.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * The system is very weak. The client uses no encryption for it's
+ * credentials and only sends null verifiers. The server sends backs
+ * null verifiers or optionally a verifier that suggests a new short hand
+ * for the credentials.
+ *
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/param.h>
+
+#include <assert.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+/* auth_unix.c */
+static void authunix_nextverf (AUTH *);
+static bool_t authunix_marshal (AUTH *, XDR *);
+static bool_t authunix_validate (AUTH *, struct opaque_auth *);
+static bool_t authunix_refresh (AUTH *, void *);
+static void authunix_destroy (AUTH *);
+static void marshal_new_auth (AUTH *);
+static struct auth_ops *authunix_ops (void);
+
+/*
+ * This struct is pointed to by the ah_private field of an auth_handle.
+ */
+struct audata {
+ struct opaque_auth au_origcred; /* original credentials */
+ struct opaque_auth au_shcred; /* short hand cred */
+ u_long au_shfaults; /* short hand cache faults */
+ char au_marshed[MAX_AUTH_BYTES];
+ u_int au_mpos; /* xdr pos at end of marshed */
+};
+#define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
+
+/*
+ * Create a unix style authenticator.
+ * Returns an auth handle with the given stuff in it.
+ */
+AUTH *
+authunix_create(machname, uid, gid, len, aup_gids)
+ char *machname;
+ int uid;
+ int gid;
+ int len;
+ int *aup_gids;
+{
+ struct authunix_parms aup;
+ char mymem[MAX_AUTH_BYTES];
+ struct timeval now;
+ XDR xdrs;
+ AUTH *auth;
+ struct audata *au;
+
+ /*
+ * Allocate and set up auth handle
+ */
+ au = NULL;
+ auth = mem_alloc(sizeof(*auth));
+#ifndef _KERNEL
+ if (auth == NULL) {
+ warnx("authunix_create: out of memory");
+ goto cleanup_authunix_create;
+ }
+#endif
+ au = mem_alloc(sizeof(*au));
+#ifndef _KERNEL
+ if (au == NULL) {
+ warnx("authunix_create: out of memory");
+ goto cleanup_authunix_create;
+ }
+#endif
+ auth->ah_ops = authunix_ops();
+ auth->ah_private = (caddr_t)au;
+ auth->ah_verf = au->au_shcred = _null_auth;
+ au->au_shfaults = 0;
+ au->au_origcred.oa_base = NULL;
+
+ /*
+ * fill in param struct from the given params
+ */
+ (void)gettimeofday(&now, NULL);
+ aup.aup_time = now.tv_sec;
+ aup.aup_machname = machname;
+ aup.aup_uid = uid;
+ aup.aup_gid = gid;
+ aup.aup_len = (u_int)len;
+ aup.aup_gids = aup_gids;
+
+ /*
+ * Serialize the parameters into origcred
+ */
+ xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE);
+ if (! xdr_authunix_parms(&xdrs, &aup))
+ abort();
+ au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);
+ au->au_origcred.oa_flavor = AUTH_UNIX;
+#ifdef _KERNEL
+ au->au_origcred.oa_base = mem_alloc((u_int) len);
+#else
+ if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) {
+ warnx("authunix_create: out of memory");
+ goto cleanup_authunix_create;
+ }
+#endif
+ memmove(au->au_origcred.oa_base, mymem, (size_t)len);
+
+ /*
+ * set auth handle to reflect new cred.
+ */
+ auth->ah_cred = au->au_origcred;
+ marshal_new_auth(auth);
+ return (auth);
+#ifndef _KERNEL
+ cleanup_authunix_create:
+ if (auth)
+ mem_free(auth, sizeof(*auth));
+ if (au) {
+ if (au->au_origcred.oa_base)
+ mem_free(au->au_origcred.oa_base, (u_int)len);
+ mem_free(au, sizeof(*au));
+ }
+ return (NULL);
+#endif
+}
+
+/*
+ * Returns an auth handle with parameters determined by doing lots of
+ * syscalls.
+ */
+AUTH *
+authunix_create_default()
+{
+ int ngids;
+ long ngids_max;
+ char machname[MAXHOSTNAMELEN + 1];
+ uid_t uid;
+ gid_t gid;
+ gid_t *gids;
+
+ ngids_max = sysconf(_SC_NGROUPS_MAX) + 1;
+ gids = malloc(sizeof(gid_t) * ngids_max);
+ if (gids == NULL)
+ return (NULL);
+
+ if (gethostname(machname, sizeof machname) == -1)
+ abort();
+ machname[sizeof(machname) - 1] = 0;
+ uid = geteuid();
+ gid = getegid();
+ if ((ngids = getgroups(ngids_max, gids)) < 0)
+ abort();
+ if (ngids > NGRPS)
+ ngids = NGRPS;
+ /* XXX: interface problem; those should all have been unsigned */
+ return (authunix_create(machname, (int)uid, (int)gid, ngids,
+ (int *)gids));
+}
+
+/*
+ * authunix operations
+ */
+
+/* ARGSUSED */
+static void
+authunix_nextverf(auth)
+ AUTH *auth;
+{
+ /* no action necessary */
+}
+
+static bool_t
+authunix_marshal(auth, xdrs)
+ AUTH *auth;
+ XDR *xdrs;
+{
+ struct audata *au;
+
+ assert(auth != NULL);
+ assert(xdrs != NULL);
+
+ au = AUTH_PRIVATE(auth);
+ return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos));
+}
+
+static bool_t
+authunix_validate(auth, verf)
+ AUTH *auth;
+ struct opaque_auth *verf;
+{
+ struct audata *au;
+ XDR xdrs;
+
+ assert(auth != NULL);
+ assert(verf != NULL);
+
+ if (verf->oa_flavor == AUTH_SHORT) {
+ au = AUTH_PRIVATE(auth);
+ xdrmem_create(&xdrs, verf->oa_base, verf->oa_length,
+ XDR_DECODE);
+
+ if (au->au_shcred.oa_base != NULL) {
+ mem_free(au->au_shcred.oa_base,
+ au->au_shcred.oa_length);
+ au->au_shcred.oa_base = NULL;
+ }
+ if (xdr_opaque_auth(&xdrs, &au->au_shcred)) {
+ auth->ah_cred = au->au_shcred;
+ } else {
+ xdrs.x_op = XDR_FREE;
+ (void)xdr_opaque_auth(&xdrs, &au->au_shcred);
+ au->au_shcred.oa_base = NULL;
+ auth->ah_cred = au->au_origcred;
+ }
+ marshal_new_auth(auth);
+ }
+ return (TRUE);
+}
+
+static bool_t
+authunix_refresh(AUTH *auth, void *dummy)
+{
+ struct audata *au = AUTH_PRIVATE(auth);
+ struct authunix_parms aup;
+ struct timeval now;
+ XDR xdrs;
+ int stat;
+
+ assert(auth != NULL);
+
+ if (auth->ah_cred.oa_base == au->au_origcred.oa_base) {
+ /* there is no hope. Punt */
+ return (FALSE);
+ }
+ au->au_shfaults ++;
+
+ /* first deserialize the creds back into a struct authunix_parms */
+ aup.aup_machname = NULL;
+ aup.aup_gids = NULL;
+ xdrmem_create(&xdrs, au->au_origcred.oa_base,
+ au->au_origcred.oa_length, XDR_DECODE);
+ stat = xdr_authunix_parms(&xdrs, &aup);
+ if (! stat)
+ goto done;
+
+ /* update the time and serialize in place */
+ (void)gettimeofday(&now, NULL);
+ aup.aup_time = now.tv_sec;
+ xdrs.x_op = XDR_ENCODE;
+ XDR_SETPOS(&xdrs, 0);
+ stat = xdr_authunix_parms(&xdrs, &aup);
+ if (! stat)
+ goto done;
+ auth->ah_cred = au->au_origcred;
+ marshal_new_auth(auth);
+done:
+ /* free the struct authunix_parms created by deserializing */
+ xdrs.x_op = XDR_FREE;
+ (void)xdr_authunix_parms(&xdrs, &aup);
+ XDR_DESTROY(&xdrs);
+ return (stat);
+}
+
+static void
+authunix_destroy(auth)
+ AUTH *auth;
+{
+ struct audata *au;
+
+ assert(auth != NULL);
+
+ au = AUTH_PRIVATE(auth);
+ mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length);
+
+ if (au->au_shcred.oa_base != NULL)
+ mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length);
+
+ mem_free(auth->ah_private, sizeof(struct audata));
+
+ if (auth->ah_verf.oa_base != NULL)
+ mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length);
+
+ mem_free(auth, sizeof(*auth));
+}
+
+/*
+ * Marshals (pre-serializes) an auth struct.
+ * sets private data, au_marshed and au_mpos
+ */
+static void
+marshal_new_auth(auth)
+ AUTH *auth;
+{
+ XDR xdr_stream;
+ XDR *xdrs = &xdr_stream;
+ struct audata *au;
+
+ assert(auth != NULL);
+
+ au = AUTH_PRIVATE(auth);
+ xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE);
+ if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) ||
+ (! xdr_opaque_auth(xdrs, &(auth->ah_verf))))
+ warnx("auth_none.c - Fatal marshalling problem");
+ else
+ au->au_mpos = XDR_GETPOS(xdrs);
+ XDR_DESTROY(xdrs);
+}
+
+static struct auth_ops *
+authunix_ops()
+{
+ static struct auth_ops ops;
+
+ /* VARIABLES PROTECTED BY ops_lock: ops */
+
+ mutex_lock(&ops_lock);
+ if (ops.ah_nextverf == NULL) {
+ ops.ah_nextverf = authunix_nextverf;
+ ops.ah_marshal = authunix_marshal;
+ ops.ah_validate = authunix_validate;
+ ops.ah_refresh = authunix_refresh;
+ ops.ah_destroy = authunix_destroy;
+ }
+ mutex_unlock(&ops_lock);
+ return (&ops);
+}
diff --git a/lib/libc/rpc/authdes_prot.c b/lib/libc/rpc/authdes_prot.c
new file mode 100644
index 0000000..5be1f12
--- /dev/null
+++ b/lib/libc/rpc/authdes_prot.c
@@ -0,0 +1,94 @@
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)authdes_prot.c 2.1 88/07/29 4.0 RPCSRC; from 1.6 88/02/08 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/*
+ * authdes_prot.c, XDR routines for DES authentication
+ */
+
+#include "namespace.h"
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_des.h>
+#include "un-namespace.h"
+
+#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE)
+
+bool_t
+xdr_authdes_cred(xdrs, cred)
+ XDR *xdrs;
+ struct authdes_cred *cred;
+{
+ enum authdes_namekind *padc_namekind = &cred->adc_namekind;
+ /*
+ * Unrolled xdr
+ */
+ ATTEMPT(xdr_enum(xdrs, (enum_t *) padc_namekind));
+ switch (cred->adc_namekind) {
+ case ADN_FULLNAME:
+ ATTEMPT(xdr_string(xdrs, &cred->adc_fullname.name,
+ MAXNETNAMELEN));
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.key,
+ sizeof(des_block)));
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.window,
+ sizeof(cred->adc_fullname.window)));
+ return (TRUE);
+ case ADN_NICKNAME:
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_nickname,
+ sizeof(cred->adc_nickname)));
+ return (TRUE);
+ default:
+ return (FALSE);
+ }
+}
+
+
+bool_t
+xdr_authdes_verf(xdrs, verf)
+ XDR *xdrs;
+ struct authdes_verf *verf;
+{
+ /*
+ * Unrolled xdr
+ */
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_xtimestamp,
+ sizeof(des_block)));
+ ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_int_u,
+ sizeof(verf->adv_int_u)));
+ return (TRUE);
+}
diff --git a/lib/libc/rpc/authunix_prot.c b/lib/libc/rpc/authunix_prot.c
new file mode 100644
index 0000000..7699e28
--- /dev/null
+++ b/lib/libc/rpc/authunix_prot.c
@@ -0,0 +1,79 @@
+/* $NetBSD: authunix_prot.c,v 1.12 2000/01/22 22:19:17 mycroft Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)authunix_prot.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * authunix_prot.c
+ * XDR for UNIX style authentication parameters for RPC
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <assert.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+#include "un-namespace.h"
+
+/*
+ * XDR for unix authentication parameters.
+ */
+bool_t
+xdr_authunix_parms(xdrs, p)
+ XDR *xdrs;
+ struct authunix_parms *p;
+{
+ int **paup_gids;
+
+ assert(xdrs != NULL);
+ assert(p != NULL);
+
+ paup_gids = &p->aup_gids;
+
+ if (xdr_u_long(xdrs, &(p->aup_time))
+ && xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME)
+ && xdr_int(xdrs, &(p->aup_uid))
+ && xdr_int(xdrs, &(p->aup_gid))
+ && xdr_array(xdrs, (char **) paup_gids,
+ &(p->aup_len), NGRPS, sizeof(int), (xdrproc_t)xdr_int) ) {
+ return (TRUE);
+ }
+ return (FALSE);
+}
diff --git a/lib/libc/rpc/bindresvport.3 b/lib/libc/rpc/bindresvport.3
new file mode 100644
index 0000000..28e86e5
--- /dev/null
+++ b/lib/libc/rpc/bindresvport.3
@@ -0,0 +1,103 @@
+.\" @(#)bindresvport.3n 2.2 88/08/02 4.0 RPCSRC; from 1.7 88/03/14 SMI
+.\" $NetBSD: bindresvport.3,v 1.8 2000/07/05 15:45:33 msaitoh Exp $
+.\" $FreeBSD$
+.\"
+.Dd November 22, 1987
+.Dt BINDRESVPORT 3
+.Os
+.Sh NAME
+.Nm bindresvport ,
+.Nm bindresvport_sa
+.Nd bind a socket to a privileged IP port
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In rpc/rpc.h
+.Ft int
+.Fn bindresvport "int sd" "struct sockaddr_in *sin"
+.Ft int
+.Fn bindresvport_sa "int sd" "struct sockaddr *sa"
+.Sh DESCRIPTION
+The
+.Fn bindresvport
+and
+.Fn bindresvport_sa
+functions
+are used to bind a socket descriptor to a privileged
+.Tn IP
+port, that is, a
+port number in the range 0-1023.
+.Pp
+If
+.Fa sin
+is a pointer to a
+.Ft "struct sockaddr_in"
+then the appropriate fields in the structure should be defined.
+Note that
+.Fa sin->sin_family
+must be initialized to the address family of the socket, passed by
+.Fa sd .
+If
+.Fa sin->sin_port
+is
+.Sq 0
+then an anonymous port (in the range 600-1023) will be
+chosen, and if
+.Xr bind 2
+is successful, the
+.Fa sin->sin_port
+will be updated to contain the allocated port.
+.Pp
+If
+.Fa sin
+is the
+.Dv NULL
+pointer,
+an anonymous port will be allocated (as above).
+However, there is no way for
+.Fn bindresvport
+to return the allocated port in this case.
+.Pp
+Only root can bind to a privileged port; this call will fail for any
+other users.
+.Pp
+Function prototype of
+.Fn bindresvport
+is biased to
+.Dv AF_INET
+socket.
+The
+.Fn bindresvport_sa
+function
+acts exactly the same, with more neutral function prototype.
+Note that both functions behave exactly the same, and
+both support
+.Dv AF_INET6
+sockets as well as
+.Dv AF_INET
+sockets.
+.Sh RETURN VALUES
+.Rv -std bindresvport
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EPFNOSUPPORT
+If second argument was supplied,
+and address family did not match between arguments.
+.El
+.Pp
+The
+.Fn bindresvport
+function
+may also fail and set
+.Va errno
+for any of the errors specified for the calls
+.Xr bind 2 ,
+.Xr getsockopt 2 ,
+or
+.Xr setsockopt 2 .
+.Sh SEE ALSO
+.Xr bind 2 ,
+.Xr getsockopt 2 ,
+.Xr setsockopt 2 ,
+.Xr ip 4
diff --git a/lib/libc/rpc/bindresvport.c b/lib/libc/rpc/bindresvport.c
new file mode 100644
index 0000000..75a1c8f
--- /dev/null
+++ b/lib/libc/rpc/bindresvport.c
@@ -0,0 +1,161 @@
+/* $NetBSD: bindresvport.c,v 1.19 2000/07/06 03:03:59 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "from: @(#)bindresvport.c 1.8 88/02/08 SMI";
+static char *sccsid = "from: @(#)bindresvport.c 2.2 88/07/29 4.0 RPCSRC";
+#endif
+/* from: $OpenBSD: bindresvport.c,v 1.7 1996/07/30 16:25:47 downsj Exp $ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Copyright (c) 1987 by Sun Microsystems, Inc.
+ *
+ * Portions Copyright(C) 1996, Jason Downs. All rights reserved.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <netinet/in.h>
+
+#include <errno.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+
+#include <string.h>
+#include "un-namespace.h"
+
+/*
+ * Bind a socket to a privileged IP port
+ */
+int
+bindresvport(sd, sin)
+ int sd;
+ struct sockaddr_in *sin;
+{
+ return bindresvport_sa(sd, (struct sockaddr *)sin);
+}
+
+/*
+ * Bind a socket to a privileged IP port
+ */
+int
+bindresvport_sa(sd, sa)
+ int sd;
+ struct sockaddr *sa;
+{
+ int old, error, af;
+ struct sockaddr_storage myaddr;
+ struct sockaddr_in *sin;
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+#endif
+ int proto, portrange, portlow;
+ u_int16_t *portp;
+ socklen_t salen;
+
+ if (sa == NULL) {
+ salen = sizeof(myaddr);
+ sa = (struct sockaddr *)&myaddr;
+
+ if (_getsockname(sd, sa, &salen) == -1)
+ return -1; /* errno is correctly set */
+
+ af = sa->sa_family;
+ memset(sa, 0, salen);
+ } else
+ af = sa->sa_family;
+
+ switch (af) {
+ case AF_INET:
+ proto = IPPROTO_IP;
+ portrange = IP_PORTRANGE;
+ portlow = IP_PORTRANGE_LOW;
+ sin = (struct sockaddr_in *)sa;
+ salen = sizeof(struct sockaddr_in);
+ portp = &sin->sin_port;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ proto = IPPROTO_IPV6;
+ portrange = IPV6_PORTRANGE;
+ portlow = IPV6_PORTRANGE_LOW;
+ sin6 = (struct sockaddr_in6 *)sa;
+ salen = sizeof(struct sockaddr_in6);
+ portp = &sin6->sin6_port;
+ break;
+#endif
+ default:
+ errno = EPFNOSUPPORT;
+ return (-1);
+ }
+ sa->sa_family = af;
+ sa->sa_len = salen;
+
+ if (*portp == 0) {
+ socklen_t oldlen = sizeof(old);
+
+ error = _getsockopt(sd, proto, portrange, &old, &oldlen);
+ if (error < 0)
+ return (error);
+
+ error = _setsockopt(sd, proto, portrange, &portlow,
+ sizeof(portlow));
+ if (error < 0)
+ return (error);
+ }
+
+ error = _bind(sd, sa, salen);
+
+ if (*portp == 0) {
+ int saved_errno = errno;
+
+ if (error < 0) {
+ if (_setsockopt(sd, proto, portrange, &old,
+ sizeof(old)) < 0)
+ errno = saved_errno;
+ return (error);
+ }
+
+ if (sa != (struct sockaddr *)&myaddr) {
+ /* Hmm, what did the kernel assign? */
+ if (_getsockname(sd, sa, &salen) < 0)
+ errno = saved_errno;
+ return (error);
+ }
+ }
+ return (error);
+}
diff --git a/lib/libc/rpc/clnt_bcast.c b/lib/libc/rpc/clnt_bcast.c
new file mode 100644
index 0000000..612007e
--- /dev/null
+++ b/lib/libc/rpc/clnt_bcast.c
@@ -0,0 +1,673 @@
+/* $NetBSD: clnt_bcast.c,v 1.3 2000/07/06 03:05:20 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#ident "@(#)clnt_bcast.c 1.18 94/05/03 SMI"
+static char sccsid[] = "@(#)clnt_bcast.c 1.15 89/04/21 Copyr 1988 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+
+/*
+ * clnt_bcast.c
+ * Client interface to broadcast service.
+ *
+ * Copyright (C) 1988, Sun Microsystems, Inc.
+ *
+ * The following is kludged-up support for simple rpc broadcasts.
+ * Someday a large, complicated system will replace these routines.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <net/if.h>
+#include <netinet/in.h>
+#include <ifaddrs.h>
+#include <sys/poll.h>
+#include <rpc/rpc.h>
+#ifdef PORTMAP
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_rmt.h>
+#endif /* PORTMAP */
+#include <rpc/nettype.h>
+#include <arpa/inet.h>
+#ifdef RPC_DEBUG
+#include <stdio.h>
+#endif
+#include <errno.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <err.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+
+#define MAXBCAST 20 /* Max no of broadcasting transports */
+#define INITTIME 4000 /* Time to wait initially */
+#define WAITTIME 8000 /* Maximum time to wait */
+
+/*
+ * If nettype is NULL, it broadcasts on all the available
+ * datagram_n transports. May potentially lead to broadacst storms
+ * and hence should be used with caution, care and courage.
+ *
+ * The current parameter xdr packet size is limited by the max tsdu
+ * size of the transport. If the max tsdu size of any transport is
+ * smaller than the parameter xdr packet, then broadcast is not
+ * sent on that transport.
+ *
+ * Also, the packet size should be less the packet size of
+ * the data link layer (for ethernet it is 1400 bytes). There is
+ * no easy way to find out the max size of the data link layer and
+ * we are assuming that the args would be smaller than that.
+ *
+ * The result size has to be smaller than the transport tsdu size.
+ *
+ * If PORTMAP has been defined, we send two packets for UDP, one for
+ * rpcbind and one for portmap. For those machines which support
+ * both rpcbind and portmap, it will cause them to reply twice, and
+ * also here it will get two responses ... inefficient and clumsy.
+ */
+
+struct broadif {
+ int index;
+ struct sockaddr_storage broadaddr;
+ TAILQ_ENTRY(broadif) link;
+};
+
+typedef TAILQ_HEAD(, broadif) broadlist_t;
+
+int __rpc_getbroadifs(int, int, int, broadlist_t *);
+void __rpc_freebroadifs(broadlist_t *);
+int __rpc_broadenable(int, int, struct broadif *);
+
+int __rpc_lowvers = 0;
+
+int
+__rpc_getbroadifs(int af, int proto, int socktype, broadlist_t *list)
+{
+ int count = 0;
+ struct broadif *bip;
+ struct ifaddrs *ifap, *ifp;
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+#endif
+ struct sockaddr_in *sin;
+ struct addrinfo hints, *res;
+
+ if (getifaddrs(&ifp) < 0)
+ return 0;
+
+ memset(&hints, 0, sizeof hints);
+
+ hints.ai_family = af;
+ hints.ai_protocol = proto;
+ hints.ai_socktype = socktype;
+
+ if (getaddrinfo(NULL, "sunrpc", &hints, &res) != 0) {
+ freeifaddrs(ifp);
+ return 0;
+ }
+
+ for (ifap = ifp; ifap != NULL; ifap = ifap->ifa_next) {
+ if (ifap->ifa_addr->sa_family != af ||
+ !(ifap->ifa_flags & IFF_UP))
+ continue;
+ bip = (struct broadif *)malloc(sizeof *bip);
+ if (bip == NULL)
+ break;
+ bip->index = if_nametoindex(ifap->ifa_name);
+ if (
+#ifdef INET6
+ af != AF_INET6 &&
+#endif
+ (ifap->ifa_flags & IFF_BROADCAST) &&
+ ifap->ifa_broadaddr) {
+ memcpy(&bip->broadaddr, ifap->ifa_broadaddr,
+ (size_t)ifap->ifa_broadaddr->sa_len);
+ sin = (struct sockaddr_in *)(void *)&bip->broadaddr;
+ sin->sin_port =
+ ((struct sockaddr_in *)
+ (void *)res->ai_addr)->sin_port;
+ } else
+#ifdef INET6
+ if (af == AF_INET6 && (ifap->ifa_flags & IFF_MULTICAST)) {
+ sin6 = (struct sockaddr_in6 *)(void *)&bip->broadaddr;
+ inet_pton(af, RPCB_MULTICAST_ADDR, &sin6->sin6_addr);
+ sin6->sin6_family = af;
+ sin6->sin6_len = sizeof *sin6;
+ sin6->sin6_port =
+ ((struct sockaddr_in6 *)
+ (void *)res->ai_addr)->sin6_port;
+ sin6->sin6_scope_id = bip->index;
+ } else
+#endif
+ {
+ free(bip);
+ continue;
+ }
+ TAILQ_INSERT_TAIL(list, bip, link);
+ count++;
+ }
+ freeifaddrs(ifp);
+ freeaddrinfo(res);
+
+ return count;
+}
+
+void
+__rpc_freebroadifs(broadlist_t *list)
+{
+ struct broadif *bip, *next;
+
+ bip = TAILQ_FIRST(list);
+
+ while (bip != NULL) {
+ next = TAILQ_NEXT(bip, link);
+ free(bip);
+ bip = next;
+ }
+}
+
+int
+/*ARGSUSED*/
+__rpc_broadenable(int af, int s, struct broadif *bip)
+{
+ int o = 1;
+
+#if 0
+ if (af == AF_INET6) {
+ fprintf(stderr, "set v6 multicast if to %d\n", bip->index);
+ if (_setsockopt(s, IPPROTO_IPV6, IPV6_MULTICAST_IF, &bip->index,
+ sizeof bip->index) < 0)
+ return -1;
+ } else
+#endif
+ if (_setsockopt(s, SOL_SOCKET, SO_BROADCAST, &o, sizeof o) < 0)
+ return -1;
+
+ return 0;
+}
+
+
+enum clnt_stat
+rpc_broadcast_exp(prog, vers, proc, xargs, argsp, xresults, resultsp,
+ eachresult, inittime, waittime, nettype)
+ rpcprog_t prog; /* program number */
+ rpcvers_t vers; /* version number */
+ rpcproc_t proc; /* procedure number */
+ xdrproc_t xargs; /* xdr routine for args */
+ caddr_t argsp; /* pointer to args */
+ xdrproc_t xresults; /* xdr routine for results */
+ caddr_t resultsp; /* pointer to results */
+ resultproc_t eachresult; /* call with each result obtained */
+ int inittime; /* how long to wait initially */
+ int waittime; /* maximum time to wait */
+ const char *nettype; /* transport type */
+{
+ enum clnt_stat stat = RPC_SUCCESS; /* Return status */
+ XDR xdr_stream; /* XDR stream */
+ XDR *xdrs = &xdr_stream;
+ struct rpc_msg msg; /* RPC message */
+ struct timeval t;
+ char *outbuf = NULL; /* Broadcast msg buffer */
+ char *inbuf = NULL; /* Reply buf */
+ int inlen;
+ u_int maxbufsize = 0;
+ AUTH *sys_auth = authunix_create_default();
+ int i;
+ void *handle;
+ char uaddress[1024]; /* A self imposed limit */
+ char *uaddrp = uaddress;
+ int pmap_reply_flag; /* reply recvd from PORTMAP */
+ /* An array of all the suitable broadcast transports */
+ struct {
+ int fd; /* File descriptor */
+ int af;
+ int proto;
+ struct netconfig *nconf; /* Netconfig structure */
+ u_int asize; /* Size of the addr buf */
+ u_int dsize; /* Size of the data buf */
+ struct sockaddr_storage raddr; /* Remote address */
+ broadlist_t nal;
+ } fdlist[MAXBCAST];
+ struct pollfd pfd[MAXBCAST];
+ size_t fdlistno = 0;
+ struct r_rpcb_rmtcallargs barg; /* Remote arguments */
+ struct r_rpcb_rmtcallres bres; /* Remote results */
+ size_t outlen;
+ struct netconfig *nconf;
+ int msec;
+ int pollretval;
+ int fds_found;
+
+#ifdef PORTMAP
+ size_t outlen_pmap = 0;
+ u_long port; /* Remote port number */
+ int pmap_flag = 0; /* UDP exists ? */
+ char *outbuf_pmap = NULL;
+ struct rmtcallargs barg_pmap; /* Remote arguments */
+ struct rmtcallres bres_pmap; /* Remote results */
+ u_int udpbufsz = 0;
+#endif /* PORTMAP */
+
+ if (sys_auth == NULL) {
+ return (RPC_SYSTEMERROR);
+ }
+ /*
+ * initialization: create a fd, a broadcast address, and send the
+ * request on the broadcast transport.
+ * Listen on all of them and on replies, call the user supplied
+ * function.
+ */
+
+ if (nettype == NULL)
+ nettype = "datagram_n";
+ if ((handle = __rpc_setconf(nettype)) == NULL) {
+ AUTH_DESTROY(sys_auth);
+ return (RPC_UNKNOWNPROTO);
+ }
+ while ((nconf = __rpc_getconf(handle)) != NULL) {
+ int fd;
+ struct __rpc_sockinfo si;
+
+ if (nconf->nc_semantics != NC_TPI_CLTS)
+ continue;
+ if (fdlistno >= MAXBCAST)
+ break; /* No more slots available */
+ if (!__rpc_nconf2sockinfo(nconf, &si))
+ continue;
+
+ TAILQ_INIT(&fdlist[fdlistno].nal);
+ if (__rpc_getbroadifs(si.si_af, si.si_proto, si.si_socktype,
+ &fdlist[fdlistno].nal) == 0)
+ continue;
+
+ fd = _socket(si.si_af, si.si_socktype, si.si_proto);
+ if (fd < 0) {
+ stat = RPC_CANTSEND;
+ continue;
+ }
+ fdlist[fdlistno].af = si.si_af;
+ fdlist[fdlistno].proto = si.si_proto;
+ fdlist[fdlistno].fd = fd;
+ fdlist[fdlistno].nconf = nconf;
+ fdlist[fdlistno].asize = __rpc_get_a_size(si.si_af);
+ pfd[fdlistno].events = POLLIN | POLLPRI |
+ POLLRDNORM | POLLRDBAND;
+ pfd[fdlistno].fd = fdlist[fdlistno].fd = fd;
+ fdlist[fdlistno].dsize = __rpc_get_t_size(si.si_af, si.si_proto,
+ 0);
+
+ if (maxbufsize <= fdlist[fdlistno].dsize)
+ maxbufsize = fdlist[fdlistno].dsize;
+
+#ifdef PORTMAP
+ if (si.si_af == AF_INET && si.si_proto == IPPROTO_UDP) {
+ udpbufsz = fdlist[fdlistno].dsize;
+ if ((outbuf_pmap = malloc(udpbufsz)) == NULL) {
+ _close(fd);
+ stat = RPC_SYSTEMERROR;
+ goto done_broad;
+ }
+ pmap_flag = 1;
+ }
+#endif /* PORTMAP */
+ fdlistno++;
+ }
+
+ if (fdlistno == 0) {
+ if (stat == RPC_SUCCESS)
+ stat = RPC_UNKNOWNPROTO;
+ goto done_broad;
+ }
+ if (maxbufsize == 0) {
+ if (stat == RPC_SUCCESS)
+ stat = RPC_CANTSEND;
+ goto done_broad;
+ }
+ inbuf = malloc(maxbufsize);
+ outbuf = malloc(maxbufsize);
+ if ((inbuf == NULL) || (outbuf == NULL)) {
+ stat = RPC_SYSTEMERROR;
+ goto done_broad;
+ }
+
+ /* Serialize all the arguments which have to be sent */
+ (void) gettimeofday(&t, NULL);
+ msg.rm_xid = __RPC_GETXID(&t);
+ msg.rm_direction = CALL;
+ msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ msg.rm_call.cb_prog = RPCBPROG;
+ msg.rm_call.cb_vers = RPCBVERS;
+ msg.rm_call.cb_proc = RPCBPROC_CALLIT;
+ barg.prog = prog;
+ barg.vers = vers;
+ barg.proc = proc;
+ barg.args.args_val = argsp;
+ barg.xdr_args = xargs;
+ bres.addr = uaddrp;
+ bres.results.results_val = resultsp;
+ bres.xdr_res = xresults;
+ msg.rm_call.cb_cred = sys_auth->ah_cred;
+ msg.rm_call.cb_verf = sys_auth->ah_verf;
+ xdrmem_create(xdrs, outbuf, maxbufsize, XDR_ENCODE);
+ if ((!xdr_callmsg(xdrs, &msg)) ||
+ (!xdr_rpcb_rmtcallargs(xdrs,
+ (struct rpcb_rmtcallargs *)(void *)&barg))) {
+ stat = RPC_CANTENCODEARGS;
+ goto done_broad;
+ }
+ outlen = xdr_getpos(xdrs);
+ xdr_destroy(xdrs);
+
+#ifdef PORTMAP
+ /* Prepare the packet for version 2 PORTMAP */
+ if (pmap_flag) {
+ msg.rm_xid++; /* One way to distinguish */
+ msg.rm_call.cb_prog = PMAPPROG;
+ msg.rm_call.cb_vers = PMAPVERS;
+ msg.rm_call.cb_proc = PMAPPROC_CALLIT;
+ barg_pmap.prog = prog;
+ barg_pmap.vers = vers;
+ barg_pmap.proc = proc;
+ barg_pmap.args_ptr = argsp;
+ barg_pmap.xdr_args = xargs;
+ bres_pmap.port_ptr = &port;
+ bres_pmap.xdr_results = xresults;
+ bres_pmap.results_ptr = resultsp;
+ xdrmem_create(xdrs, outbuf_pmap, udpbufsz, XDR_ENCODE);
+ if ((! xdr_callmsg(xdrs, &msg)) ||
+ (! xdr_rmtcall_args(xdrs, &barg_pmap))) {
+ stat = RPC_CANTENCODEARGS;
+ goto done_broad;
+ }
+ outlen_pmap = xdr_getpos(xdrs);
+ xdr_destroy(xdrs);
+ }
+#endif /* PORTMAP */
+
+ /*
+ * Basic loop: broadcast the packets to transports which
+ * support data packets of size such that one can encode
+ * all the arguments.
+ * Wait a while for response(s).
+ * The response timeout grows larger per iteration.
+ */
+ for (msec = inittime; msec <= waittime; msec += msec) {
+ struct broadif *bip;
+
+ /* Broadcast all the packets now */
+ for (i = 0; i < fdlistno; i++) {
+ if (fdlist[i].dsize < outlen) {
+ stat = RPC_CANTSEND;
+ continue;
+ }
+ for (bip = TAILQ_FIRST(&fdlist[i].nal); bip != NULL;
+ bip = TAILQ_NEXT(bip, link)) {
+ void *addr;
+
+ addr = &bip->broadaddr;
+
+ __rpc_broadenable(fdlist[i].af, fdlist[i].fd,
+ bip);
+
+ /*
+ * Only use version 3 if lowvers is not set
+ */
+
+ if (!__rpc_lowvers)
+ if (_sendto(fdlist[i].fd, outbuf,
+ outlen, 0, (struct sockaddr*)addr,
+ (size_t)fdlist[i].asize) !=
+ outlen) {
+#ifdef RPC_DEBUG
+ perror("sendto");
+#endif
+ warnx("clnt_bcast: cannot send "
+ "broadcast packet");
+ stat = RPC_CANTSEND;
+ continue;
+ };
+#ifdef RPC_DEBUG
+ if (!__rpc_lowvers)
+ fprintf(stderr, "Broadcast packet sent "
+ "for %s\n",
+ fdlist[i].nconf->nc_netid);
+#endif
+#ifdef PORTMAP
+ /*
+ * Send the version 2 packet also
+ * for UDP/IP
+ */
+ if (pmap_flag &&
+ fdlist[i].proto == IPPROTO_UDP) {
+ if (_sendto(fdlist[i].fd, outbuf_pmap,
+ outlen_pmap, 0, addr,
+ (size_t)fdlist[i].asize) !=
+ outlen_pmap) {
+ warnx("clnt_bcast: "
+ "Cannot send broadcast packet");
+ stat = RPC_CANTSEND;
+ continue;
+ }
+ }
+#ifdef RPC_DEBUG
+ fprintf(stderr, "PMAP Broadcast packet "
+ "sent for %s\n",
+ fdlist[i].nconf->nc_netid);
+#endif
+#endif /* PORTMAP */
+ }
+ /* End for sending all packets on this transport */
+ } /* End for sending on all transports */
+
+ if (eachresult == NULL) {
+ stat = RPC_SUCCESS;
+ goto done_broad;
+ }
+
+ /*
+ * Get all the replies from these broadcast requests
+ */
+ recv_again:
+
+ switch (pollretval = _poll(pfd, fdlistno, msec)) {
+ case 0: /* timed out */
+ stat = RPC_TIMEDOUT;
+ continue;
+ case -1: /* some kind of error - we ignore it */
+ goto recv_again;
+ } /* end of poll results switch */
+
+ for (i = fds_found = 0;
+ i < fdlistno && fds_found < pollretval; i++) {
+ bool_t done = FALSE;
+
+ if (pfd[i].revents == 0)
+ continue;
+ else if (pfd[i].revents & POLLNVAL) {
+ /*
+ * Something bad has happened to this descri-
+ * ptor. We can cause _poll() to ignore
+ * it simply by using a negative fd. We do that
+ * rather than compacting the pfd[] and fdlist[]
+ * arrays.
+ */
+ pfd[i].fd = -1;
+ fds_found++;
+ continue;
+ } else
+ fds_found++;
+#ifdef RPC_DEBUG
+ fprintf(stderr, "response for %s\n",
+ fdlist[i].nconf->nc_netid);
+#endif
+ try_again:
+ inlen = _recvfrom(fdlist[i].fd, inbuf, fdlist[i].dsize,
+ 0, (struct sockaddr *)(void *)&fdlist[i].raddr,
+ &fdlist[i].asize);
+ if (inlen < 0) {
+ if (errno == EINTR)
+ goto try_again;
+ warnx("clnt_bcast: Cannot receive reply to "
+ "broadcast");
+ stat = RPC_CANTRECV;
+ continue;
+ }
+ if (inlen < sizeof (u_int32_t))
+ continue; /* Drop that and go ahead */
+ /*
+ * see if reply transaction id matches sent id.
+ * If so, decode the results. If return id is xid + 1
+ * it was a PORTMAP reply
+ */
+ if (*((u_int32_t *)(void *)(inbuf)) ==
+ *((u_int32_t *)(void *)(outbuf))) {
+ pmap_reply_flag = 0;
+ msg.acpted_rply.ar_verf = _null_auth;
+ msg.acpted_rply.ar_results.where =
+ (caddr_t)(void *)&bres;
+ msg.acpted_rply.ar_results.proc =
+ (xdrproc_t)xdr_rpcb_rmtcallres;
+#ifdef PORTMAP
+ } else if (pmap_flag &&
+ *((u_int32_t *)(void *)(inbuf)) ==
+ *((u_int32_t *)(void *)(outbuf_pmap))) {
+ pmap_reply_flag = 1;
+ msg.acpted_rply.ar_verf = _null_auth;
+ msg.acpted_rply.ar_results.where =
+ (caddr_t)(void *)&bres_pmap;
+ msg.acpted_rply.ar_results.proc =
+ (xdrproc_t)xdr_rmtcallres;
+#endif /* PORTMAP */
+ } else
+ continue;
+ xdrmem_create(xdrs, inbuf, (u_int)inlen, XDR_DECODE);
+ if (xdr_replymsg(xdrs, &msg)) {
+ if ((msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+ (msg.acpted_rply.ar_stat == SUCCESS)) {
+ struct netbuf taddr, *np;
+ struct sockaddr_in *sin;
+
+#ifdef PORTMAP
+ if (pmap_flag && pmap_reply_flag) {
+ sin = (struct sockaddr_in *)
+ (void *)&fdlist[i].raddr;
+ sin->sin_port =
+ htons((u_short)port);
+ taddr.len = taddr.maxlen =
+ fdlist[i].raddr.ss_len;
+ taddr.buf = &fdlist[i].raddr;
+ done = (*eachresult)(resultsp,
+ &taddr, fdlist[i].nconf);
+ } else {
+#endif /* PORTMAP */
+#ifdef RPC_DEBUG
+ fprintf(stderr, "uaddr %s\n",
+ uaddrp);
+#endif
+ np = uaddr2taddr(
+ fdlist[i].nconf, uaddrp);
+ done = (*eachresult)(resultsp,
+ np, fdlist[i].nconf);
+ free(np);
+#ifdef PORTMAP
+ }
+#endif /* PORTMAP */
+ }
+ /* otherwise, we just ignore the errors ... */
+ }
+ /* else some kind of deserialization problem ... */
+
+ xdrs->x_op = XDR_FREE;
+ msg.acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
+ (void) xdr_replymsg(xdrs, &msg);
+ (void) (*xresults)(xdrs, resultsp);
+ XDR_DESTROY(xdrs);
+ if (done) {
+ stat = RPC_SUCCESS;
+ goto done_broad;
+ } else {
+ goto recv_again;
+ }
+ } /* The recv for loop */
+ } /* The giant for loop */
+
+done_broad:
+ if (inbuf)
+ (void) free(inbuf);
+ if (outbuf)
+ (void) free(outbuf);
+#ifdef PORTMAP
+ if (outbuf_pmap)
+ (void) free(outbuf_pmap);
+#endif /* PORTMAP */
+ for (i = 0; i < fdlistno; i++) {
+ (void)_close(fdlist[i].fd);
+ __rpc_freebroadifs(&fdlist[i].nal);
+ }
+ AUTH_DESTROY(sys_auth);
+ (void) __rpc_endconf(handle);
+
+ return (stat);
+}
+
+
+enum clnt_stat
+rpc_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp,
+ eachresult, nettype)
+ rpcprog_t prog; /* program number */
+ rpcvers_t vers; /* version number */
+ rpcproc_t proc; /* procedure number */
+ xdrproc_t xargs; /* xdr routine for args */
+ caddr_t argsp; /* pointer to args */
+ xdrproc_t xresults; /* xdr routine for results */
+ caddr_t resultsp; /* pointer to results */
+ resultproc_t eachresult; /* call with each result obtained */
+ const char *nettype; /* transport type */
+{
+ enum clnt_stat dummy;
+
+ dummy = rpc_broadcast_exp(prog, vers, proc, xargs, argsp,
+ xresults, resultsp, eachresult,
+ INITTIME, WAITTIME, nettype);
+ return (dummy);
+}
diff --git a/lib/libc/rpc/clnt_dg.c b/lib/libc/rpc/clnt_dg.c
new file mode 100644
index 0000000..9c52e1e
--- /dev/null
+++ b/lib/libc/rpc/clnt_dg.c
@@ -0,0 +1,859 @@
+/* $NetBSD: clnt_dg.c,v 1.4 2000/07/14 08:40:41 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#ident "@(#)clnt_dg.c 1.23 94/04/22 SMI"
+static char sccsid[] = "@(#)clnt_dg.c 1.19 89/03/16 Copyr 1988 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Implements a connectionless client side RPC.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/event.h>
+#include <sys/time.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcsec_gss.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <err.h>
+#include "un-namespace.h"
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+
+#ifdef _FREEFALL_CONFIG
+/*
+ * Disable RPC exponential back-off for FreeBSD.org systems.
+ */
+#define RPC_MAX_BACKOFF 1 /* second */
+#else
+#define RPC_MAX_BACKOFF 30 /* seconds */
+#endif
+
+
+static struct clnt_ops *clnt_dg_ops(void);
+static bool_t time_not_ok(struct timeval *);
+static enum clnt_stat clnt_dg_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
+ xdrproc_t, void *, struct timeval);
+static void clnt_dg_geterr(CLIENT *, struct rpc_err *);
+static bool_t clnt_dg_freeres(CLIENT *, xdrproc_t, void *);
+static void clnt_dg_abort(CLIENT *);
+static bool_t clnt_dg_control(CLIENT *, u_int, void *);
+static void clnt_dg_destroy(CLIENT *);
+
+
+
+
+/*
+ * This machinery implements per-fd locks for MT-safety. It is not
+ * sufficient to do per-CLIENT handle locks for MT-safety because a
+ * user may create more than one CLIENT handle with the same fd behind
+ * it. Therfore, we allocate an array of flags (dg_fd_locks), protected
+ * by the clnt_fd_lock mutex, and an array (dg_cv) of condition variables
+ * similarly protected. Dg_fd_lock[fd] == 1 => a call is activte on some
+ * CLIENT handle created for that fd.
+ * The current implementation holds locks across the entire RPC and reply,
+ * including retransmissions. Yes, this is silly, and as soon as this
+ * code is proven to work, this should be the first thing fixed. One step
+ * at a time.
+ */
+static int *dg_fd_locks;
+static cond_t *dg_cv;
+#define release_fd_lock(fd, mask) { \
+ mutex_lock(&clnt_fd_lock); \
+ dg_fd_locks[fd] = 0; \
+ mutex_unlock(&clnt_fd_lock); \
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL); \
+ cond_signal(&dg_cv[fd]); \
+}
+
+static const char mem_err_clnt_dg[] = "clnt_dg_create: out of memory";
+
+/* VARIABLES PROTECTED BY clnt_fd_lock: dg_fd_locks, dg_cv */
+
+#define MCALL_MSG_SIZE 24
+
+/*
+ * Private data kept per client handle
+ */
+struct cu_data {
+ int cu_fd; /* connections fd */
+ bool_t cu_closeit; /* opened by library */
+ struct sockaddr_storage cu_raddr; /* remote address */
+ int cu_rlen;
+ struct timeval cu_wait; /* retransmit interval */
+ struct timeval cu_total; /* total time for the call */
+ struct rpc_err cu_error;
+ XDR cu_outxdrs;
+ u_int cu_xdrpos;
+ u_int cu_sendsz; /* send size */
+ char cu_outhdr[MCALL_MSG_SIZE];
+ char *cu_outbuf;
+ u_int cu_recvsz; /* recv size */
+ int cu_async;
+ int cu_connect; /* Use connect(). */
+ int cu_connected; /* Have done connect(). */
+ struct kevent cu_kin;
+ int cu_kq;
+ char cu_inbuf[1];
+};
+
+/*
+ * Connection less client creation returns with client handle parameters.
+ * Default options are set, which the user can change using clnt_control().
+ * fd should be open and bound.
+ * NB: The rpch->cl_auth is initialized to null authentication.
+ * Caller may wish to set this something more useful.
+ *
+ * sendsz and recvsz are the maximum allowable packet sizes that can be
+ * sent and received. Normally they are the same, but they can be
+ * changed to improve the program efficiency and buffer allocation.
+ * If they are 0, use the transport default.
+ *
+ * If svcaddr is NULL, returns NULL.
+ */
+CLIENT *
+clnt_dg_create(fd, svcaddr, program, version, sendsz, recvsz)
+ int fd; /* open file descriptor */
+ const struct netbuf *svcaddr; /* servers address */
+ rpcprog_t program; /* program number */
+ rpcvers_t version; /* version number */
+ u_int sendsz; /* buffer recv size */
+ u_int recvsz; /* buffer send size */
+{
+ CLIENT *cl = NULL; /* client handle */
+ struct cu_data *cu = NULL; /* private data */
+ struct timeval now;
+ struct rpc_msg call_msg;
+ sigset_t mask;
+ sigset_t newmask;
+ struct __rpc_sockinfo si;
+ int one = 1;
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ if (dg_fd_locks == (int *) NULL) {
+ int cv_allocsz;
+ size_t fd_allocsz;
+ int dtbsize = __rpc_dtbsize();
+
+ fd_allocsz = dtbsize * sizeof (int);
+ dg_fd_locks = (int *) mem_alloc(fd_allocsz);
+ if (dg_fd_locks == (int *) NULL) {
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ goto err1;
+ } else
+ memset(dg_fd_locks, '\0', fd_allocsz);
+
+ cv_allocsz = dtbsize * sizeof (cond_t);
+ dg_cv = (cond_t *) mem_alloc(cv_allocsz);
+ if (dg_cv == (cond_t *) NULL) {
+ mem_free(dg_fd_locks, fd_allocsz);
+ dg_fd_locks = (int *) NULL;
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ goto err1;
+ } else {
+ int i;
+
+ for (i = 0; i < dtbsize; i++)
+ cond_init(&dg_cv[i], 0, (void *) 0);
+ }
+ }
+
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+
+ if (svcaddr == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+ return (NULL);
+ }
+
+ if (!__rpc_fd2sockinfo(fd, &si)) {
+ rpc_createerr.cf_stat = RPC_TLIERROR;
+ rpc_createerr.cf_error.re_errno = 0;
+ return (NULL);
+ }
+ /*
+ * Find the receive and the send size
+ */
+ sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
+ recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
+ if ((sendsz == 0) || (recvsz == 0)) {
+ rpc_createerr.cf_stat = RPC_TLIERROR; /* XXX */
+ rpc_createerr.cf_error.re_errno = 0;
+ return (NULL);
+ }
+
+ if ((cl = mem_alloc(sizeof (CLIENT))) == NULL)
+ goto err1;
+ /*
+ * Should be multiple of 4 for XDR.
+ */
+ sendsz = ((sendsz + 3) / 4) * 4;
+ recvsz = ((recvsz + 3) / 4) * 4;
+ cu = mem_alloc(sizeof (*cu) + sendsz + recvsz);
+ if (cu == NULL)
+ goto err1;
+ (void) memcpy(&cu->cu_raddr, svcaddr->buf, (size_t)svcaddr->len);
+ cu->cu_rlen = svcaddr->len;
+ cu->cu_outbuf = &cu->cu_inbuf[recvsz];
+ /* Other values can also be set through clnt_control() */
+ cu->cu_wait.tv_sec = 15; /* heuristically chosen */
+ cu->cu_wait.tv_usec = 0;
+ cu->cu_total.tv_sec = -1;
+ cu->cu_total.tv_usec = -1;
+ cu->cu_sendsz = sendsz;
+ cu->cu_recvsz = recvsz;
+ cu->cu_async = FALSE;
+ cu->cu_connect = FALSE;
+ cu->cu_connected = FALSE;
+ (void) gettimeofday(&now, NULL);
+ call_msg.rm_xid = __RPC_GETXID(&now);
+ call_msg.rm_call.cb_prog = program;
+ call_msg.rm_call.cb_vers = version;
+ xdrmem_create(&(cu->cu_outxdrs), cu->cu_outhdr, MCALL_MSG_SIZE,
+ XDR_ENCODE);
+ if (! xdr_callhdr(&cu->cu_outxdrs, &call_msg)) {
+ rpc_createerr.cf_stat = RPC_CANTENCODEARGS; /* XXX */
+ rpc_createerr.cf_error.re_errno = 0;
+ goto err2;
+ }
+ cu->cu_xdrpos = XDR_GETPOS(&(cu->cu_outxdrs));
+ XDR_DESTROY(&cu->cu_outxdrs);
+ xdrmem_create(&cu->cu_outxdrs, cu->cu_outbuf, sendsz, XDR_ENCODE);
+
+ /* XXX fvdl - do we still want this? */
+#if 0
+ (void)bindresvport_sa(fd, (struct sockaddr *)svcaddr->buf);
+#endif
+ _ioctl(fd, FIONBIO, (char *)(void *)&one);
+
+ /*
+ * By default, closeit is always FALSE. It is users responsibility
+ * to do a close on it, else the user may use clnt_control
+ * to let clnt_destroy do it for him/her.
+ */
+ cu->cu_closeit = FALSE;
+ cu->cu_fd = fd;
+ cl->cl_ops = clnt_dg_ops();
+ cl->cl_private = (caddr_t)(void *)cu;
+ cl->cl_auth = authnone_create();
+ cl->cl_tp = NULL;
+ cl->cl_netid = NULL;
+ cu->cu_kq = -1;
+ EV_SET(&cu->cu_kin, cu->cu_fd, EVFILT_READ, EV_ADD, 0, 0, 0);
+ return (cl);
+err1:
+ warnx(mem_err_clnt_dg);
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+err2:
+ if (cl) {
+ mem_free(cl, sizeof (CLIENT));
+ if (cu)
+ mem_free(cu, sizeof (*cu) + sendsz + recvsz);
+ }
+ return (NULL);
+}
+
+static enum clnt_stat
+clnt_dg_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)
+ CLIENT *cl; /* client handle */
+ rpcproc_t proc; /* procedure number */
+ xdrproc_t xargs; /* xdr routine for args */
+ void *argsp; /* pointer to args */
+ xdrproc_t xresults; /* xdr routine for results */
+ void *resultsp; /* pointer to results */
+ struct timeval utimeout; /* seconds to wait before giving up */
+{
+ struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ XDR *xdrs;
+ size_t outlen = 0;
+ struct rpc_msg reply_msg;
+ XDR reply_xdrs;
+ bool_t ok;
+ int nrefreshes = 2; /* number of times to refresh cred */
+ int nretries = 0; /* number of times we retransmitted */
+ struct timeval timeout;
+ struct timeval retransmit_time;
+ struct timeval next_sendtime, starttime, time_waited, tv;
+ struct timespec ts;
+ struct kevent kv;
+ struct sockaddr *sa;
+ sigset_t mask;
+ sigset_t newmask;
+ socklen_t inlen, salen;
+ ssize_t recvlen = 0;
+ int kin_len, n, rpc_lock_value;
+ u_int32_t xid;
+
+ outlen = 0;
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (dg_fd_locks[cu->cu_fd])
+ cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
+ if (__isthreaded)
+ rpc_lock_value = 1;
+ else
+ rpc_lock_value = 0;
+ dg_fd_locks[cu->cu_fd] = rpc_lock_value;
+ mutex_unlock(&clnt_fd_lock);
+ if (cu->cu_total.tv_usec == -1) {
+ timeout = utimeout; /* use supplied timeout */
+ } else {
+ timeout = cu->cu_total; /* use default timeout */
+ }
+
+ if (cu->cu_connect && !cu->cu_connected) {
+ if (_connect(cu->cu_fd, (struct sockaddr *)&cu->cu_raddr,
+ cu->cu_rlen) < 0) {
+ cu->cu_error.re_errno = errno;
+ cu->cu_error.re_status = RPC_CANTSEND;
+ goto out;
+ }
+ cu->cu_connected = 1;
+ }
+ if (cu->cu_connected) {
+ sa = NULL;
+ salen = 0;
+ } else {
+ sa = (struct sockaddr *)&cu->cu_raddr;
+ salen = cu->cu_rlen;
+ }
+ time_waited.tv_sec = 0;
+ time_waited.tv_usec = 0;
+ retransmit_time = next_sendtime = cu->cu_wait;
+ gettimeofday(&starttime, NULL);
+
+ /* Clean up in case the last call ended in a longjmp(3) call. */
+ if (cu->cu_kq >= 0)
+ _close(cu->cu_kq);
+ if ((cu->cu_kq = kqueue()) < 0) {
+ cu->cu_error.re_errno = errno;
+ cu->cu_error.re_status = RPC_CANTSEND;
+ goto out;
+ }
+ kin_len = 1;
+
+call_again:
+ if (cu->cu_async == TRUE && xargs == NULL)
+ goto get_reply;
+ /*
+ * the transaction is the first thing in the out buffer
+ * XXX Yes, and it's in network byte order, so we should to
+ * be careful when we increment it, shouldn't we.
+ */
+ xid = ntohl(*(u_int32_t *)(void *)(cu->cu_outhdr));
+ xid++;
+ *(u_int32_t *)(void *)(cu->cu_outhdr) = htonl(xid);
+call_again_same_xid:
+ xdrs = &(cu->cu_outxdrs);
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, 0);
+
+ if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) {
+ if ((! XDR_PUTBYTES(xdrs, cu->cu_outhdr, cu->cu_xdrpos)) ||
+ (! XDR_PUTINT32(xdrs, &proc)) ||
+ (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+ (! (*xargs)(xdrs, argsp))) {
+ cu->cu_error.re_status = RPC_CANTENCODEARGS;
+ goto out;
+ }
+ } else {
+ *(uint32_t *) &cu->cu_outhdr[cu->cu_xdrpos] = htonl(proc);
+ if (!__rpc_gss_wrap(cl->cl_auth, cu->cu_outhdr,
+ cu->cu_xdrpos + sizeof(uint32_t),
+ xdrs, xargs, argsp)) {
+ cu->cu_error.re_status = RPC_CANTENCODEARGS;
+ goto out;
+ }
+ }
+ outlen = (size_t)XDR_GETPOS(xdrs);
+
+send_again:
+ if (_sendto(cu->cu_fd, cu->cu_outbuf, outlen, 0, sa, salen) != outlen) {
+ cu->cu_error.re_errno = errno;
+ cu->cu_error.re_status = RPC_CANTSEND;
+ goto out;
+ }
+
+ /*
+ * Hack to provide rpc-based message passing
+ */
+ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+ cu->cu_error.re_status = RPC_TIMEDOUT;
+ goto out;
+ }
+
+get_reply:
+
+ /*
+ * sub-optimal code appears here because we have
+ * some clock time to spare while the packets are in flight.
+ * (We assume that this is actually only executed once.)
+ */
+ reply_msg.acpted_rply.ar_verf = _null_auth;
+ if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) {
+ reply_msg.acpted_rply.ar_results.where = resultsp;
+ reply_msg.acpted_rply.ar_results.proc = xresults;
+ } else {
+ reply_msg.acpted_rply.ar_results.where = NULL;
+ reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
+ }
+
+ for (;;) {
+ /* Decide how long to wait. */
+ if (timercmp(&next_sendtime, &timeout, <))
+ timersub(&next_sendtime, &time_waited, &tv);
+ else
+ timersub(&timeout, &time_waited, &tv);
+ if (tv.tv_sec < 0 || tv.tv_usec < 0)
+ tv.tv_sec = tv.tv_usec = 0;
+ TIMEVAL_TO_TIMESPEC(&tv, &ts);
+
+ n = _kevent(cu->cu_kq, &cu->cu_kin, kin_len, &kv, 1, &ts);
+ /* We don't need to register the event again. */
+ kin_len = 0;
+
+ if (n == 1) {
+ if (kv.flags & EV_ERROR) {
+ cu->cu_error.re_errno = kv.data;
+ cu->cu_error.re_status = RPC_CANTRECV;
+ goto out;
+ }
+ /* We have some data now */
+ do {
+ recvlen = _recvfrom(cu->cu_fd, cu->cu_inbuf,
+ cu->cu_recvsz, 0, NULL, NULL);
+ } while (recvlen < 0 && errno == EINTR);
+ if (recvlen < 0 && errno != EWOULDBLOCK) {
+ cu->cu_error.re_errno = errno;
+ cu->cu_error.re_status = RPC_CANTRECV;
+ goto out;
+ }
+ if (recvlen >= sizeof(u_int32_t) &&
+ (cu->cu_async == TRUE ||
+ *((u_int32_t *)(void *)(cu->cu_inbuf)) ==
+ *((u_int32_t *)(void *)(cu->cu_outbuf)))) {
+ /* We now assume we have the proper reply. */
+ break;
+ }
+ }
+ if (n == -1 && errno != EINTR) {
+ cu->cu_error.re_errno = errno;
+ cu->cu_error.re_status = RPC_CANTRECV;
+ goto out;
+ }
+ gettimeofday(&tv, NULL);
+ timersub(&tv, &starttime, &time_waited);
+
+ /* Check for timeout. */
+ if (timercmp(&time_waited, &timeout, >)) {
+ cu->cu_error.re_status = RPC_TIMEDOUT;
+ goto out;
+ }
+
+ /* Retransmit if necessary. */
+ if (timercmp(&time_waited, &next_sendtime, >)) {
+ /* update retransmit_time */
+ if (retransmit_time.tv_sec < RPC_MAX_BACKOFF)
+ timeradd(&retransmit_time, &retransmit_time,
+ &retransmit_time);
+ timeradd(&next_sendtime, &retransmit_time,
+ &next_sendtime);
+ nretries++;
+
+ /*
+ * When retransmitting a RPCSEC_GSS message,
+ * we must use a new sequence number (handled
+ * by __rpc_gss_wrap above).
+ */
+ if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS)
+ goto send_again;
+ else
+ goto call_again_same_xid;
+ }
+ }
+ inlen = (socklen_t)recvlen;
+
+ /*
+ * now decode and validate the response
+ */
+
+ xdrmem_create(&reply_xdrs, cu->cu_inbuf, (u_int)recvlen, XDR_DECODE);
+ ok = xdr_replymsg(&reply_xdrs, &reply_msg);
+ /* XDR_DESTROY(&reply_xdrs); save a few cycles on noop destroy */
+ if (ok) {
+ if ((reply_msg.rm_reply.rp_stat == MSG_ACCEPTED) &&
+ (reply_msg.acpted_rply.ar_stat == SUCCESS))
+ cu->cu_error.re_status = RPC_SUCCESS;
+ else
+ _seterr_reply(&reply_msg, &(cu->cu_error));
+
+ if (cu->cu_error.re_status == RPC_SUCCESS) {
+ if (! AUTH_VALIDATE(cl->cl_auth,
+ &reply_msg.acpted_rply.ar_verf)) {
+ if (nretries &&
+ cl->cl_auth->ah_cred.oa_flavor
+ == RPCSEC_GSS)
+ /*
+ * If we retransmitted, its
+ * possible that we will
+ * receive a reply for one of
+ * the earlier transmissions
+ * (which will use an older
+ * RPCSEC_GSS sequence
+ * number). In this case, just
+ * go back and listen for a
+ * new reply. We could keep a
+ * record of all the seq
+ * numbers we have transmitted
+ * so far so that we could
+ * accept a reply for any of
+ * them here.
+ */
+ goto get_reply;
+ cu->cu_error.re_status = RPC_AUTHERROR;
+ cu->cu_error.re_why = AUTH_INVALIDRESP;
+ } else {
+ if (cl->cl_auth->ah_cred.oa_flavor
+ == RPCSEC_GSS) {
+ if (!__rpc_gss_unwrap(cl->cl_auth,
+ &reply_xdrs, xresults,
+ resultsp))
+ cu->cu_error.re_status =
+ RPC_CANTDECODERES;
+ }
+ }
+ if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
+ xdrs->x_op = XDR_FREE;
+ (void) xdr_opaque_auth(xdrs,
+ &(reply_msg.acpted_rply.ar_verf));
+ }
+ } /* end successful completion */
+ /*
+ * If unsuccesful AND error is an authentication error
+ * then refresh credentials and try again, else break
+ */
+ else if (cu->cu_error.re_status == RPC_AUTHERROR)
+ /* maybe our credentials need to be refreshed ... */
+ if (nrefreshes > 0 &&
+ AUTH_REFRESH(cl->cl_auth, &reply_msg)) {
+ nrefreshes--;
+ goto call_again;
+ }
+ /* end of unsuccessful completion */
+ } /* end of valid reply message */
+ else {
+ cu->cu_error.re_status = RPC_CANTDECODERES;
+
+ }
+out:
+ if (cu->cu_kq >= 0)
+ _close(cu->cu_kq);
+ cu->cu_kq = -1;
+ release_fd_lock(cu->cu_fd, mask);
+ return (cu->cu_error.re_status);
+}
+
+static void
+clnt_dg_geterr(cl, errp)
+ CLIENT *cl;
+ struct rpc_err *errp;
+{
+ struct cu_data *cu = (struct cu_data *)cl->cl_private;
+
+ *errp = cu->cu_error;
+}
+
+static bool_t
+clnt_dg_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ void *res_ptr;
+{
+ struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ XDR *xdrs = &(cu->cu_outxdrs);
+ bool_t dummy;
+ sigset_t mask;
+ sigset_t newmask;
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (dg_fd_locks[cu->cu_fd])
+ cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
+ xdrs->x_op = XDR_FREE;
+ dummy = (*xdr_res)(xdrs, res_ptr);
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &mask, NULL);
+ cond_signal(&dg_cv[cu->cu_fd]);
+ return (dummy);
+}
+
+/*ARGSUSED*/
+static void
+clnt_dg_abort(h)
+ CLIENT *h;
+{
+}
+
+static bool_t
+clnt_dg_control(cl, request, info)
+ CLIENT *cl;
+ u_int request;
+ void *info;
+{
+ struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ struct netbuf *addr;
+ sigset_t mask;
+ sigset_t newmask;
+ int rpc_lock_value;
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (dg_fd_locks[cu->cu_fd])
+ cond_wait(&dg_cv[cu->cu_fd], &clnt_fd_lock);
+ if (__isthreaded)
+ rpc_lock_value = 1;
+ else
+ rpc_lock_value = 0;
+ dg_fd_locks[cu->cu_fd] = rpc_lock_value;
+ mutex_unlock(&clnt_fd_lock);
+ switch (request) {
+ case CLSET_FD_CLOSE:
+ cu->cu_closeit = TRUE;
+ release_fd_lock(cu->cu_fd, mask);
+ return (TRUE);
+ case CLSET_FD_NCLOSE:
+ cu->cu_closeit = FALSE;
+ release_fd_lock(cu->cu_fd, mask);
+ return (TRUE);
+ }
+
+ /* for other requests which use info */
+ if (info == NULL) {
+ release_fd_lock(cu->cu_fd, mask);
+ return (FALSE);
+ }
+ switch (request) {
+ case CLSET_TIMEOUT:
+ if (time_not_ok((struct timeval *)info)) {
+ release_fd_lock(cu->cu_fd, mask);
+ return (FALSE);
+ }
+ cu->cu_total = *(struct timeval *)info;
+ break;
+ case CLGET_TIMEOUT:
+ *(struct timeval *)info = cu->cu_total;
+ break;
+ case CLGET_SERVER_ADDR: /* Give him the fd address */
+ /* Now obsolete. Only for backward compatibility */
+ (void) memcpy(info, &cu->cu_raddr, (size_t)cu->cu_rlen);
+ break;
+ case CLSET_RETRY_TIMEOUT:
+ if (time_not_ok((struct timeval *)info)) {
+ release_fd_lock(cu->cu_fd, mask);
+ return (FALSE);
+ }
+ cu->cu_wait = *(struct timeval *)info;
+ break;
+ case CLGET_RETRY_TIMEOUT:
+ *(struct timeval *)info = cu->cu_wait;
+ break;
+ case CLGET_FD:
+ *(int *)info = cu->cu_fd;
+ break;
+ case CLGET_SVC_ADDR:
+ addr = (struct netbuf *)info;
+ addr->buf = &cu->cu_raddr;
+ addr->len = cu->cu_rlen;
+ addr->maxlen = sizeof cu->cu_raddr;
+ break;
+ case CLSET_SVC_ADDR: /* set to new address */
+ addr = (struct netbuf *)info;
+ if (addr->len < sizeof cu->cu_raddr) {
+ release_fd_lock(cu->cu_fd, mask);
+ return (FALSE);
+ }
+ (void) memcpy(&cu->cu_raddr, addr->buf, addr->len);
+ cu->cu_rlen = addr->len;
+ break;
+ case CLGET_XID:
+ /*
+ * use the knowledge that xid is the
+ * first element in the call structure *.
+ * This will get the xid of the PREVIOUS call
+ */
+ *(u_int32_t *)info =
+ ntohl(*(u_int32_t *)(void *)cu->cu_outhdr);
+ break;
+
+ case CLSET_XID:
+ /* This will set the xid of the NEXT call */
+ *(u_int32_t *)(void *)cu->cu_outhdr =
+ htonl(*(u_int32_t *)info - 1);
+ /* decrement by 1 as clnt_dg_call() increments once */
+ break;
+
+ case CLGET_VERS:
+ /*
+ * This RELIES on the information that, in the call body,
+ * the version number field is the fifth field from the
+ * begining of the RPC header. MUST be changed if the
+ * call_struct is changed
+ */
+ *(u_int32_t *)info =
+ ntohl(*(u_int32_t *)(void *)(cu->cu_outhdr +
+ 4 * BYTES_PER_XDR_UNIT));
+ break;
+
+ case CLSET_VERS:
+ *(u_int32_t *)(void *)(cu->cu_outhdr + 4 * BYTES_PER_XDR_UNIT)
+ = htonl(*(u_int32_t *)info);
+ break;
+
+ case CLGET_PROG:
+ /*
+ * This RELIES on the information that, in the call body,
+ * the program number field is the fourth field from the
+ * begining of the RPC header. MUST be changed if the
+ * call_struct is changed
+ */
+ *(u_int32_t *)info =
+ ntohl(*(u_int32_t *)(void *)(cu->cu_outhdr +
+ 3 * BYTES_PER_XDR_UNIT));
+ break;
+
+ case CLSET_PROG:
+ *(u_int32_t *)(void *)(cu->cu_outhdr + 3 * BYTES_PER_XDR_UNIT)
+ = htonl(*(u_int32_t *)info);
+ break;
+ case CLSET_ASYNC:
+ cu->cu_async = *(int *)info;
+ break;
+ case CLSET_CONNECT:
+ cu->cu_connect = *(int *)info;
+ break;
+ default:
+ release_fd_lock(cu->cu_fd, mask);
+ return (FALSE);
+ }
+ release_fd_lock(cu->cu_fd, mask);
+ return (TRUE);
+}
+
+static void
+clnt_dg_destroy(cl)
+ CLIENT *cl;
+{
+ struct cu_data *cu = (struct cu_data *)cl->cl_private;
+ int cu_fd = cu->cu_fd;
+ sigset_t mask;
+ sigset_t newmask;
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (dg_fd_locks[cu_fd])
+ cond_wait(&dg_cv[cu_fd], &clnt_fd_lock);
+ if (cu->cu_closeit)
+ (void)_close(cu_fd);
+ if (cu->cu_kq >= 0)
+ _close(cu->cu_kq);
+ XDR_DESTROY(&(cu->cu_outxdrs));
+ mem_free(cu, (sizeof (*cu) + cu->cu_sendsz + cu->cu_recvsz));
+ if (cl->cl_netid && cl->cl_netid[0])
+ mem_free(cl->cl_netid, strlen(cl->cl_netid) +1);
+ if (cl->cl_tp && cl->cl_tp[0])
+ mem_free(cl->cl_tp, strlen(cl->cl_tp) +1);
+ mem_free(cl, sizeof (CLIENT));
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &mask, NULL);
+ cond_signal(&dg_cv[cu_fd]);
+}
+
+static struct clnt_ops *
+clnt_dg_ops()
+{
+ static struct clnt_ops ops;
+ sigset_t mask;
+ sigset_t newmask;
+
+/* VARIABLES PROTECTED BY ops_lock: ops */
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&ops_lock);
+ if (ops.cl_call == NULL) {
+ ops.cl_call = clnt_dg_call;
+ ops.cl_abort = clnt_dg_abort;
+ ops.cl_geterr = clnt_dg_geterr;
+ ops.cl_freeres = clnt_dg_freeres;
+ ops.cl_destroy = clnt_dg_destroy;
+ ops.cl_control = clnt_dg_control;
+ }
+ mutex_unlock(&ops_lock);
+ thr_sigsetmask(SIG_SETMASK, &mask, NULL);
+ return (&ops);
+}
+
+/*
+ * Make sure that the time is not garbage. -1 value is allowed.
+ */
+static bool_t
+time_not_ok(t)
+ struct timeval *t;
+{
+ return (t->tv_sec < -1 || t->tv_sec > 100000000 ||
+ t->tv_usec < -1 || t->tv_usec > 1000000);
+}
+
diff --git a/lib/libc/rpc/clnt_generic.c b/lib/libc/rpc/clnt_generic.c
new file mode 100644
index 0000000..302a30e
--- /dev/null
+++ b/lib/libc/rpc/clnt_generic.c
@@ -0,0 +1,466 @@
+/* $NetBSD: clnt_generic.c,v 1.18 2000/07/06 03:10:34 christos Exp $ */
+
+/*
+ * The contents of this file are subject to the Sun Standards
+ * License Version 1.0 the (the "License";) You may not use
+ * this file except in compliance with the License. You may
+ * obtain a copy of the License at lib/libc/rpc/LICENSE
+ *
+ * Software distributed under the License is distributed on
+ * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the License for the specific
+ * language governing rights and limitations under the License.
+ *
+ * The Original Code is Copyright 1998 by Sun Microsystems, Inc
+ *
+ * The Initial Developer of the Original Code is: Sun
+ * Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/* #ident "@(#)clnt_generic.c 1.40 99/04/21 SMI" */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "from: @(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";
+static char *sccsid = "from: @(#)clnt_generic.c 2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Copyright (c) 1986-1996,1998 by Sun Microsystems, Inc.
+ * All rights reserved.
+ */
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/fcntl.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <stdio.h>
+#include <errno.h>
+#include <netdb.h>
+#include <syslog.h>
+#include <rpc/rpc.h>
+#include <rpc/nettype.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "rpc_com.h"
+
+extern bool_t __rpc_is_local_host(const char *);
+int __rpc_raise_fd(int);
+
+#ifndef NETIDLEN
+#define NETIDLEN 32
+#endif
+
+
+/*
+ * Generic client creation with version checking the value of
+ * vers_out is set to the highest server supported value
+ * vers_low <= vers_out <= vers_high AND an error results
+ * if this can not be done.
+ *
+ * It calls clnt_create_vers_timed() with a NULL value for the timeout
+ * pointer, which indicates that the default timeout should be used.
+ */
+CLIENT *
+clnt_create_vers(const char *hostname, rpcprog_t prog, rpcvers_t *vers_out,
+ rpcvers_t vers_low, rpcvers_t vers_high, const char *nettype)
+{
+
+ return (clnt_create_vers_timed(hostname, prog, vers_out, vers_low,
+ vers_high, nettype, NULL));
+}
+
+/*
+ * This the routine has the same definition as clnt_create_vers(),
+ * except it takes an additional timeout parameter - a pointer to
+ * a timeval structure. A NULL value for the pointer indicates
+ * that the default timeout value should be used.
+ */
+CLIENT *
+clnt_create_vers_timed(const char *hostname, rpcprog_t prog,
+ rpcvers_t *vers_out, rpcvers_t vers_low, rpcvers_t vers_high,
+ const char *nettype, const struct timeval *tp)
+{
+ CLIENT *clnt;
+ struct timeval to;
+ enum clnt_stat rpc_stat;
+ struct rpc_err rpcerr;
+
+ clnt = clnt_create_timed(hostname, prog, vers_high, nettype, tp);
+ if (clnt == NULL) {
+ return (NULL);
+ }
+ to.tv_sec = 10;
+ to.tv_usec = 0;
+ rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void,
+ (char *)NULL, (xdrproc_t)xdr_void, (char *)NULL, to);
+ if (rpc_stat == RPC_SUCCESS) {
+ *vers_out = vers_high;
+ return (clnt);
+ }
+ while (rpc_stat == RPC_PROGVERSMISMATCH && vers_high > vers_low) {
+ unsigned int minvers, maxvers;
+
+ clnt_geterr(clnt, &rpcerr);
+ minvers = rpcerr.re_vers.low;
+ maxvers = rpcerr.re_vers.high;
+ if (maxvers < vers_high)
+ vers_high = maxvers;
+ else
+ vers_high--;
+ if (minvers > vers_low)
+ vers_low = minvers;
+ if (vers_low > vers_high) {
+ goto error;
+ }
+ CLNT_CONTROL(clnt, CLSET_VERS, (char *)&vers_high);
+ rpc_stat = clnt_call(clnt, NULLPROC, (xdrproc_t)xdr_void,
+ (char *)NULL, (xdrproc_t)xdr_void,
+ (char *)NULL, to);
+ if (rpc_stat == RPC_SUCCESS) {
+ *vers_out = vers_high;
+ return (clnt);
+ }
+ }
+ clnt_geterr(clnt, &rpcerr);
+
+error:
+ rpc_createerr.cf_stat = rpc_stat;
+ rpc_createerr.cf_error = rpcerr;
+ clnt_destroy(clnt);
+ return (NULL);
+}
+
+/*
+ * Top level client creation routine.
+ * Generic client creation: takes (servers name, program-number, nettype) and
+ * returns client handle. Default options are set, which the user can
+ * change using the rpc equivalent of _ioctl()'s.
+ *
+ * It tries for all the netids in that particular class of netid until
+ * it succeeds.
+ * XXX The error message in the case of failure will be the one
+ * pertaining to the last create error.
+ *
+ * It calls clnt_create_timed() with the default timeout.
+ */
+CLIENT *
+clnt_create(const char *hostname, rpcprog_t prog, rpcvers_t vers,
+ const char *nettype)
+{
+
+ return (clnt_create_timed(hostname, prog, vers, nettype, NULL));
+}
+
+/*
+ * This the routine has the same definition as clnt_create(),
+ * except it takes an additional timeout parameter - a pointer to
+ * a timeval structure. A NULL value for the pointer indicates
+ * that the default timeout value should be used.
+ *
+ * This function calls clnt_tp_create_timed().
+ */
+CLIENT *
+clnt_create_timed(const char *hostname, rpcprog_t prog, rpcvers_t vers,
+ const char *netclass, const struct timeval *tp)
+{
+ struct netconfig *nconf;
+ CLIENT *clnt = NULL;
+ void *handle;
+ enum clnt_stat save_cf_stat = RPC_SUCCESS;
+ struct rpc_err save_cf_error;
+ char nettype_array[NETIDLEN];
+ char *nettype = &nettype_array[0];
+
+ if (netclass == NULL)
+ nettype = NULL;
+ else {
+ size_t len = strlen(netclass);
+ if (len >= sizeof (nettype_array)) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+ strcpy(nettype, netclass);
+ }
+
+ if ((handle = __rpc_setconf((char *)nettype)) == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+ rpc_createerr.cf_stat = RPC_SUCCESS;
+ while (clnt == NULL) {
+ if ((nconf = __rpc_getconf(handle)) == NULL) {
+ if (rpc_createerr.cf_stat == RPC_SUCCESS)
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ break;
+ }
+#ifdef CLNT_DEBUG
+ printf("trying netid %s\n", nconf->nc_netid);
+#endif
+ clnt = clnt_tp_create_timed(hostname, prog, vers, nconf, tp);
+ if (clnt)
+ break;
+ else
+ /*
+ * Since we didn't get a name-to-address
+ * translation failure here, we remember
+ * this particular error. The object of
+ * this is to enable us to return to the
+ * caller a more-specific error than the
+ * unhelpful ``Name to address translation
+ * failed'' which might well occur if we
+ * merely returned the last error (because
+ * the local loopbacks are typically the
+ * last ones in /etc/netconfig and the most
+ * likely to be unable to translate a host
+ * name). We also check for a more
+ * meaningful error than ``unknown host
+ * name'' for the same reasons.
+ */
+ if (rpc_createerr.cf_stat != RPC_N2AXLATEFAILURE &&
+ rpc_createerr.cf_stat != RPC_UNKNOWNHOST) {
+ save_cf_stat = rpc_createerr.cf_stat;
+ save_cf_error = rpc_createerr.cf_error;
+ }
+ }
+
+ /*
+ * Attempt to return an error more specific than ``Name to address
+ * translation failed'' or ``unknown host name''
+ */
+ if ((rpc_createerr.cf_stat == RPC_N2AXLATEFAILURE ||
+ rpc_createerr.cf_stat == RPC_UNKNOWNHOST) &&
+ (save_cf_stat != RPC_SUCCESS)) {
+ rpc_createerr.cf_stat = save_cf_stat;
+ rpc_createerr.cf_error = save_cf_error;
+ }
+ __rpc_endconf(handle);
+ return (clnt);
+}
+
+/*
+ * Generic client creation: takes (servers name, program-number, netconf) and
+ * returns client handle. Default options are set, which the user can
+ * change using the rpc equivalent of _ioctl()'s : clnt_control()
+ * It finds out the server address from rpcbind and calls clnt_tli_create().
+ *
+ * It calls clnt_tp_create_timed() with the default timeout.
+ */
+CLIENT *
+clnt_tp_create(const char *hostname, rpcprog_t prog, rpcvers_t vers,
+ const struct netconfig *nconf)
+{
+
+ return (clnt_tp_create_timed(hostname, prog, vers, nconf, NULL));
+}
+
+/*
+ * This has the same definition as clnt_tp_create(), except it
+ * takes an additional parameter - a pointer to a timeval structure.
+ * A NULL value for the timeout pointer indicates that the default
+ * value for the timeout should be used.
+ */
+CLIENT *
+clnt_tp_create_timed(const char *hostname, rpcprog_t prog, rpcvers_t vers,
+ const struct netconfig *nconf, const struct timeval *tp)
+{
+ struct netbuf *svcaddr; /* servers address */
+ CLIENT *cl = NULL; /* client handle */
+
+ if (nconf == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+
+ /*
+ * Get the address of the server
+ */
+ if ((svcaddr = __rpcb_findaddr_timed(prog, vers,
+ (struct netconfig *)nconf, (char *)hostname,
+ &cl, (struct timeval *)tp)) == NULL) {
+ /* appropriate error number is set by rpcbind libraries */
+ return (NULL);
+ }
+ if (cl == NULL) {
+ cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr,
+ prog, vers, 0, 0);
+ } else {
+ /* Reuse the CLIENT handle and change the appropriate fields */
+ if (CLNT_CONTROL(cl, CLSET_SVC_ADDR, (void *)svcaddr) == TRUE) {
+ if (cl->cl_netid == NULL)
+ cl->cl_netid = strdup(nconf->nc_netid);
+ if (cl->cl_tp == NULL)
+ cl->cl_tp = strdup(nconf->nc_device);
+ (void) CLNT_CONTROL(cl, CLSET_PROG, (void *)&prog);
+ (void) CLNT_CONTROL(cl, CLSET_VERS, (void *)&vers);
+ } else {
+ CLNT_DESTROY(cl);
+ cl = clnt_tli_create(RPC_ANYFD, nconf, svcaddr,
+ prog, vers, 0, 0);
+ }
+ }
+ free(svcaddr->buf);
+ free(svcaddr);
+ return (cl);
+}
+
+/*
+ * Generic client creation: returns client handle.
+ * Default options are set, which the user can
+ * change using the rpc equivalent of _ioctl()'s : clnt_control().
+ * If fd is RPC_ANYFD, it will be opened using nconf.
+ * It will be bound if not so.
+ * If sizes are 0; appropriate defaults will be chosen.
+ */
+CLIENT *
+clnt_tli_create(int fd, const struct netconfig *nconf,
+ struct netbuf *svcaddr, rpcprog_t prog, rpcvers_t vers,
+ uint sendsz, uint recvsz)
+{
+ CLIENT *cl; /* client handle */
+ bool_t madefd = FALSE; /* whether fd opened here */
+ long servtype;
+ int one = 1;
+ struct __rpc_sockinfo si;
+ extern int __rpc_minfd;
+
+ if (fd == RPC_ANYFD) {
+ if (nconf == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+
+ fd = __rpc_nconf2fd(nconf);
+
+ if (fd == -1)
+ goto err;
+ if (fd < __rpc_minfd)
+ fd = __rpc_raise_fd(fd);
+ madefd = TRUE;
+ servtype = nconf->nc_semantics;
+ if (!__rpc_fd2sockinfo(fd, &si))
+ goto err;
+ bindresvport(fd, NULL);
+ } else {
+ if (!__rpc_fd2sockinfo(fd, &si))
+ goto err;
+ servtype = __rpc_socktype2seman(si.si_socktype);
+ if (servtype == -1) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+ }
+
+ if (si.si_af != ((struct sockaddr *)svcaddr->buf)->sa_family) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNHOST; /* XXX */
+ goto err1;
+ }
+
+ switch (servtype) {
+ case NC_TPI_COTS:
+ cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz);
+ break;
+ case NC_TPI_COTS_ORD:
+ if (nconf && ((strcmp(nconf->nc_protofmly, "inet") == 0))) {
+ _setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one,
+ sizeof (one));
+ }
+ cl = clnt_vc_create(fd, svcaddr, prog, vers, sendsz, recvsz);
+ break;
+ case NC_TPI_CLTS:
+ cl = clnt_dg_create(fd, svcaddr, prog, vers, sendsz, recvsz);
+ break;
+ default:
+ goto err;
+ }
+
+ if (cl == NULL)
+ goto err1; /* borrow errors from clnt_dg/vc creates */
+ if (nconf) {
+ cl->cl_netid = strdup(nconf->nc_netid);
+ cl->cl_tp = strdup(nconf->nc_device);
+ } else {
+ cl->cl_netid = "";
+ cl->cl_tp = "";
+ }
+ if (madefd) {
+ (void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
+/* (void) CLNT_CONTROL(cl, CLSET_POP_TIMOD, NULL); */
+ };
+
+ return (cl);
+
+err:
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+err1: if (madefd)
+ (void)_close(fd);
+ return (NULL);
+}
+
+/*
+ * To avoid conflicts with the "magic" file descriptors (0, 1, and 2),
+ * we try to not use them. The __rpc_raise_fd() routine will dup
+ * a descriptor to a higher value. If we fail to do it, we continue
+ * to use the old one (and hope for the best).
+ */
+int __rpc_minfd = 3;
+
+int
+__rpc_raise_fd(int fd)
+{
+ int nfd;
+
+ if (fd >= __rpc_minfd)
+ return (fd);
+
+ if ((nfd = _fcntl(fd, F_DUPFD, __rpc_minfd)) == -1)
+ return (fd);
+
+ if (_fsync(nfd) == -1) {
+ _close(nfd);
+ return (fd);
+ }
+
+ if (_close(fd) == -1) {
+ /* this is okay, we will syslog an error, then use the new fd */
+ (void) syslog(LOG_ERR,
+ "could not close() fd %d; mem & fd leak", fd);
+ }
+
+ return (nfd);
+}
diff --git a/lib/libc/rpc/clnt_perror.c b/lib/libc/rpc/clnt_perror.c
new file mode 100644
index 0000000..efe9043
--- /dev/null
+++ b/lib/libc/rpc/clnt_perror.c
@@ -0,0 +1,333 @@
+/* $NetBSD: clnt_perror.c,v 1.24 2000/06/02 23:11:07 fvdl Exp $ */
+
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)clnt_perror.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * clnt_perror.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+#include "namespace.h"
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rpc/rpc.h>
+#include <rpc/types.h>
+#include <rpc/auth.h>
+#include <rpc/clnt.h>
+#include "un-namespace.h"
+
+static char *buf;
+
+static char *_buf(void);
+static char *auth_errmsg(enum auth_stat);
+#define CLNT_PERROR_BUFLEN 256
+
+static char *
+_buf()
+{
+
+ if (buf == 0)
+ buf = (char *)malloc(CLNT_PERROR_BUFLEN);
+ return (buf);
+}
+
+/*
+ * Print reply error info
+ */
+char *
+clnt_sperror(rpch, s)
+ CLIENT *rpch;
+ const char *s;
+{
+ struct rpc_err e;
+ char *err;
+ char *str;
+ char *strstart;
+ size_t len, i;
+
+ assert(rpch != NULL);
+ assert(s != NULL);
+
+ str = _buf(); /* side effect: sets CLNT_PERROR_BUFLEN */
+ if (str == 0)
+ return (0);
+ len = CLNT_PERROR_BUFLEN;
+ strstart = str;
+ CLNT_GETERR(rpch, &e);
+
+ if ((i = snprintf(str, len, "%s: ", s)) > 0) {
+ str += i;
+ len -= i;
+ }
+
+ (void)strncpy(str, clnt_sperrno(e.re_status), len - 1);
+ i = strlen(str);
+ str += i;
+ len -= i;
+
+ switch (e.re_status) {
+ case RPC_SUCCESS:
+ case RPC_CANTENCODEARGS:
+ case RPC_CANTDECODERES:
+ case RPC_TIMEDOUT:
+ case RPC_PROGUNAVAIL:
+ case RPC_PROCUNAVAIL:
+ case RPC_CANTDECODEARGS:
+ case RPC_SYSTEMERROR:
+ case RPC_UNKNOWNHOST:
+ case RPC_UNKNOWNPROTO:
+ case RPC_PMAPFAILURE:
+ case RPC_PROGNOTREGISTERED:
+ case RPC_FAILED:
+ break;
+
+ case RPC_CANTSEND:
+ case RPC_CANTRECV:
+ i = snprintf(str, len, "; errno = %s", strerror(e.re_errno));
+ if (i > 0) {
+ str += i;
+ len -= i;
+ }
+ break;
+
+ case RPC_VERSMISMATCH:
+ i = snprintf(str, len, "; low version = %u, high version = %u",
+ e.re_vers.low, e.re_vers.high);
+ if (i > 0) {
+ str += i;
+ len -= i;
+ }
+ break;
+
+ case RPC_AUTHERROR:
+ err = auth_errmsg(e.re_why);
+ i = snprintf(str, len, "; why = ");
+ if (i > 0) {
+ str += i;
+ len -= i;
+ }
+ if (err != NULL) {
+ i = snprintf(str, len, "%s",err);
+ } else {
+ i = snprintf(str, len,
+ "(unknown authentication error - %d)",
+ (int) e.re_why);
+ }
+ if (i > 0) {
+ str += i;
+ len -= i;
+ }
+ break;
+
+ case RPC_PROGVERSMISMATCH:
+ i = snprintf(str, len, "; low version = %u, high version = %u",
+ e.re_vers.low, e.re_vers.high);
+ if (i > 0) {
+ str += i;
+ len -= i;
+ }
+ break;
+
+ default: /* unknown */
+ i = snprintf(str, len, "; s1 = %u, s2 = %u",
+ e.re_lb.s1, e.re_lb.s2);
+ if (i > 0) {
+ str += i;
+ len -= i;
+ }
+ break;
+ }
+ strstart[CLNT_PERROR_BUFLEN-1] = '\0';
+ return(strstart) ;
+}
+
+void
+clnt_perror(rpch, s)
+ CLIENT *rpch;
+ const char *s;
+{
+
+ assert(rpch != NULL);
+ assert(s != NULL);
+
+ (void) fprintf(stderr, "%s\n", clnt_sperror(rpch,s));
+}
+
+static const char *const rpc_errlist[] = {
+ "RPC: Success", /* 0 - RPC_SUCCESS */
+ "RPC: Can't encode arguments", /* 1 - RPC_CANTENCODEARGS */
+ "RPC: Can't decode result", /* 2 - RPC_CANTDECODERES */
+ "RPC: Unable to send", /* 3 - RPC_CANTSEND */
+ "RPC: Unable to receive", /* 4 - RPC_CANTRECV */
+ "RPC: Timed out", /* 5 - RPC_TIMEDOUT */
+ "RPC: Incompatible versions of RPC", /* 6 - RPC_VERSMISMATCH */
+ "RPC: Authentication error", /* 7 - RPC_AUTHERROR */
+ "RPC: Program unavailable", /* 8 - RPC_PROGUNAVAIL */
+ "RPC: Program/version mismatch", /* 9 - RPC_PROGVERSMISMATCH */
+ "RPC: Procedure unavailable", /* 10 - RPC_PROCUNAVAIL */
+ "RPC: Server can't decode arguments", /* 11 - RPC_CANTDECODEARGS */
+ "RPC: Remote system error", /* 12 - RPC_SYSTEMERROR */
+ "RPC: Unknown host", /* 13 - RPC_UNKNOWNHOST */
+ "RPC: Port mapper failure", /* 14 - RPC_PMAPFAILURE */
+ "RPC: Program not registered", /* 15 - RPC_PROGNOTREGISTERED */
+ "RPC: Failed (unspecified error)", /* 16 - RPC_FAILED */
+ "RPC: Unknown protocol" /* 17 - RPC_UNKNOWNPROTO */
+};
+
+
+/*
+ * This interface for use by clntrpc
+ */
+char *
+clnt_sperrno(stat)
+ enum clnt_stat stat;
+{
+ unsigned int errnum = stat;
+
+ if (errnum < (sizeof(rpc_errlist)/sizeof(rpc_errlist[0])))
+ /* LINTED interface problem */
+ return (char *)rpc_errlist[errnum];
+
+ return ("RPC: (unknown error code)");
+}
+
+void
+clnt_perrno(num)
+ enum clnt_stat num;
+{
+ (void) fprintf(stderr, "%s\n", clnt_sperrno(num));
+}
+
+
+char *
+clnt_spcreateerror(s)
+ const char *s;
+{
+ char *str;
+ size_t len, i;
+
+ assert(s != NULL);
+
+ str = _buf(); /* side effect: sets CLNT_PERROR_BUFLEN */
+ if (str == 0)
+ return(0);
+ len = CLNT_PERROR_BUFLEN;
+ i = snprintf(str, len, "%s: ", s);
+ if (i > 0)
+ len -= i;
+ (void)strncat(str, clnt_sperrno(rpc_createerr.cf_stat), len - 1);
+ switch (rpc_createerr.cf_stat) {
+ case RPC_PMAPFAILURE:
+ (void) strncat(str, " - ", len - 1);
+ (void) strncat(str,
+ clnt_sperrno(rpc_createerr.cf_error.re_status), len - 4);
+ break;
+
+ case RPC_SYSTEMERROR:
+ (void)strncat(str, " - ", len - 1);
+ (void)strncat(str, strerror(rpc_createerr.cf_error.re_errno),
+ len - 4);
+ break;
+
+ case RPC_CANTSEND:
+ case RPC_CANTDECODERES:
+ case RPC_CANTENCODEARGS:
+ case RPC_SUCCESS:
+ case RPC_UNKNOWNPROTO:
+ case RPC_PROGNOTREGISTERED:
+ case RPC_FAILED:
+ case RPC_UNKNOWNHOST:
+ case RPC_CANTDECODEARGS:
+ case RPC_PROCUNAVAIL:
+ case RPC_PROGVERSMISMATCH:
+ case RPC_PROGUNAVAIL:
+ case RPC_AUTHERROR:
+ case RPC_VERSMISMATCH:
+ case RPC_TIMEDOUT:
+ case RPC_CANTRECV:
+ default:
+ break;
+ }
+ str[CLNT_PERROR_BUFLEN-1] = '\0';
+ return (str);
+}
+
+void
+clnt_pcreateerror(s)
+ const char *s;
+{
+
+ assert(s != NULL);
+
+ (void) fprintf(stderr, "%s\n", clnt_spcreateerror(s));
+}
+
+static const char *const auth_errlist[] = {
+ "Authentication OK", /* 0 - AUTH_OK */
+ "Invalid client credential", /* 1 - AUTH_BADCRED */
+ "Server rejected credential", /* 2 - AUTH_REJECTEDCRED */
+ "Invalid client verifier", /* 3 - AUTH_BADVERF */
+ "Server rejected verifier", /* 4 - AUTH_REJECTEDVERF */
+ "Client credential too weak", /* 5 - AUTH_TOOWEAK */
+ "Invalid server verifier", /* 6 - AUTH_INVALIDRESP */
+ "Failed (unspecified error)", /* 7 - AUTH_FAILED */
+ "Kerberos generic error", /* 8 - AUTH_KERB_GENERIC*/
+ "Kerberos credential expired", /* 9 - AUTH_TIMEEXPIRE */
+ "Bad kerberos ticket file", /* 10 - AUTH_TKT_FILE */
+ "Can't decode kerberos authenticator", /* 11 - AUTH_DECODE */
+ "Address wrong in kerberos ticket", /* 12 - AUTH_NET_ADDR */
+ "GSS-API crediential problem", /* 13 - RPCSEC_GSS_CREDPROBLEM */
+ "GSS-API context problem" /* 14 - RPCSEC_GSS_CTXPROBLEM */
+};
+
+static char *
+auth_errmsg(stat)
+ enum auth_stat stat;
+{
+ unsigned int errnum = stat;
+
+ if (errnum < (sizeof(auth_errlist)/sizeof(auth_errlist[0])))
+ /* LINTED interface problem */
+ return (char *)auth_errlist[errnum];
+
+ return(NULL);
+}
diff --git a/lib/libc/rpc/clnt_raw.c b/lib/libc/rpc/clnt_raw.c
new file mode 100644
index 0000000..cd3a384
--- /dev/null
+++ b/lib/libc/rpc/clnt_raw.c
@@ -0,0 +1,315 @@
+/* $NetBSD: clnt_raw.c,v 1.20 2000/12/10 04:12:03 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)clnt_raw.c 2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * clnt_raw.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * Memory based rpc for simple testing and timing.
+ * Interface to create an rpc client and server in the same process.
+ * This lets us similate rpc and get round trip overhead, without
+ * any interference from the kernel.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <assert.h>
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <rpc/rpc.h>
+#include <rpc/raw.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+#define MCALL_MSG_SIZE 24
+
+/*
+ * This is the "network" we will be moving stuff over.
+ */
+static struct clntraw_private {
+ CLIENT client_object;
+ XDR xdr_stream;
+ char *_raw_buf;
+ union {
+ struct rpc_msg mashl_rpcmsg;
+ char mashl_callmsg[MCALL_MSG_SIZE];
+ } u;
+ u_int mcnt;
+} *clntraw_private;
+
+static enum clnt_stat clnt_raw_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
+ xdrproc_t, void *, struct timeval);
+static void clnt_raw_geterr(CLIENT *, struct rpc_err *);
+static bool_t clnt_raw_freeres(CLIENT *, xdrproc_t, void *);
+static void clnt_raw_abort(CLIENT *);
+static bool_t clnt_raw_control(CLIENT *, u_int, void *);
+static void clnt_raw_destroy(CLIENT *);
+static struct clnt_ops *clnt_raw_ops(void);
+
+/*
+ * Create a client handle for memory based rpc.
+ */
+CLIENT *
+clnt_raw_create(prog, vers)
+ rpcprog_t prog;
+ rpcvers_t vers;
+{
+ struct clntraw_private *clp;
+ struct rpc_msg call_msg;
+ XDR *xdrs;
+ CLIENT *client;
+
+ mutex_lock(&clntraw_lock);
+ if ((clp = clntraw_private) == NULL) {
+ clp = (struct clntraw_private *)calloc(1, sizeof (*clp));
+ if (clp == NULL) {
+ mutex_unlock(&clntraw_lock);
+ return NULL;
+ }
+ if (__rpc_rawcombuf == NULL)
+ __rpc_rawcombuf =
+ (char *)calloc(UDPMSGSIZE, sizeof (char));
+ clp->_raw_buf = __rpc_rawcombuf;
+ clntraw_private = clp;
+ }
+ xdrs = &clp->xdr_stream;
+ client = &clp->client_object;
+
+ /*
+ * pre-serialize the static part of the call msg and stash it away
+ */
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ /* XXX: prog and vers have been long historically :-( */
+ call_msg.rm_call.cb_prog = (u_int32_t)prog;
+ call_msg.rm_call.cb_vers = (u_int32_t)vers;
+ xdrmem_create(xdrs, clp->u.mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);
+ if (! xdr_callhdr(xdrs, &call_msg))
+ warnx("clntraw_create - Fatal header serialization error.");
+ clp->mcnt = XDR_GETPOS(xdrs);
+ XDR_DESTROY(xdrs);
+
+ /*
+ * Set xdrmem for client/server shared buffer
+ */
+ xdrmem_create(xdrs, clp->_raw_buf, UDPMSGSIZE, XDR_FREE);
+
+ /*
+ * create client handle
+ */
+ client->cl_ops = clnt_raw_ops();
+ client->cl_auth = authnone_create();
+ mutex_unlock(&clntraw_lock);
+ return (client);
+}
+
+/* ARGSUSED */
+static enum clnt_stat
+clnt_raw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)
+ CLIENT *h;
+ rpcproc_t proc;
+ xdrproc_t xargs;
+ void *argsp;
+ xdrproc_t xresults;
+ void *resultsp;
+ struct timeval timeout;
+{
+ struct clntraw_private *clp = clntraw_private;
+ XDR *xdrs = &clp->xdr_stream;
+ struct rpc_msg msg;
+ enum clnt_stat status;
+ struct rpc_err error;
+
+ assert(h != NULL);
+
+ mutex_lock(&clntraw_lock);
+ if (clp == NULL) {
+ mutex_unlock(&clntraw_lock);
+ return (RPC_FAILED);
+ }
+ mutex_unlock(&clntraw_lock);
+
+call_again:
+ /*
+ * send request
+ */
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, 0);
+ clp->u.mashl_rpcmsg.rm_xid ++ ;
+ if ((! XDR_PUTBYTES(xdrs, clp->u.mashl_callmsg, clp->mcnt)) ||
+ (! XDR_PUTINT32(xdrs, &proc)) ||
+ (! AUTH_MARSHALL(h->cl_auth, xdrs)) ||
+ (! (*xargs)(xdrs, argsp))) {
+ return (RPC_CANTENCODEARGS);
+ }
+ (void)XDR_GETPOS(xdrs); /* called just to cause overhead */
+
+ /*
+ * We have to call server input routine here because this is
+ * all going on in one process. Yuk.
+ */
+ svc_getreq_common(FD_SETSIZE);
+
+ /*
+ * get results
+ */
+ xdrs->x_op = XDR_DECODE;
+ XDR_SETPOS(xdrs, 0);
+ msg.acpted_rply.ar_verf = _null_auth;
+ msg.acpted_rply.ar_results.where = resultsp;
+ msg.acpted_rply.ar_results.proc = xresults;
+ if (! xdr_replymsg(xdrs, &msg)) {
+ /*
+ * It's possible for xdr_replymsg() to fail partway
+ * through its attempt to decode the result from the
+ * server. If this happens, it will leave the reply
+ * structure partially populated with dynamically
+ * allocated memory. (This can happen if someone uses
+ * clntudp_bufcreate() to create a CLIENT handle and
+ * specifies a receive buffer size that is too small.)
+ * This memory must be free()ed to avoid a leak.
+ */
+ int op = xdrs->x_op;
+ xdrs->x_op = XDR_FREE;
+ xdr_replymsg(xdrs, &msg);
+ xdrs->x_op = op;
+ return (RPC_CANTDECODERES);
+ }
+ _seterr_reply(&msg, &error);
+ status = error.re_status;
+
+ if (status == RPC_SUCCESS) {
+ if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
+ status = RPC_AUTHERROR;
+ }
+ } /* end successful completion */
+ else {
+ if (AUTH_REFRESH(h->cl_auth, &msg))
+ goto call_again;
+ } /* end of unsuccessful completion */
+
+ if (status == RPC_SUCCESS) {
+ if (! AUTH_VALIDATE(h->cl_auth, &msg.acpted_rply.ar_verf)) {
+ status = RPC_AUTHERROR;
+ }
+ if (msg.acpted_rply.ar_verf.oa_base != NULL) {
+ xdrs->x_op = XDR_FREE;
+ (void)xdr_opaque_auth(xdrs, &(msg.acpted_rply.ar_verf));
+ }
+ }
+
+ return (status);
+}
+
+/*ARGSUSED*/
+static void
+clnt_raw_geterr(cl, err)
+ CLIENT *cl;
+ struct rpc_err *err;
+{
+}
+
+
+/* ARGSUSED */
+static bool_t
+clnt_raw_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ void *res_ptr;
+{
+ struct clntraw_private *clp = clntraw_private;
+ XDR *xdrs = &clp->xdr_stream;
+ bool_t rval;
+
+ mutex_lock(&clntraw_lock);
+ if (clp == NULL) {
+ rval = (bool_t) RPC_FAILED;
+ mutex_unlock(&clntraw_lock);
+ return (rval);
+ }
+ mutex_unlock(&clntraw_lock);
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_res)(xdrs, res_ptr));
+}
+
+/*ARGSUSED*/
+static void
+clnt_raw_abort(cl)
+ CLIENT *cl;
+{
+}
+
+/*ARGSUSED*/
+static bool_t
+clnt_raw_control(cl, ui, str)
+ CLIENT *cl;
+ u_int ui;
+ void *str;
+{
+ return (FALSE);
+}
+
+/*ARGSUSED*/
+static void
+clnt_raw_destroy(cl)
+ CLIENT *cl;
+{
+}
+
+static struct clnt_ops *
+clnt_raw_ops()
+{
+ static struct clnt_ops ops;
+
+ /* VARIABLES PROTECTED BY ops_lock: ops */
+
+ mutex_lock(&ops_lock);
+ if (ops.cl_call == NULL) {
+ ops.cl_call = clnt_raw_call;
+ ops.cl_abort = clnt_raw_abort;
+ ops.cl_geterr = clnt_raw_geterr;
+ ops.cl_freeres = clnt_raw_freeres;
+ ops.cl_destroy = clnt_raw_destroy;
+ ops.cl_control = clnt_raw_control;
+ }
+ mutex_unlock(&ops_lock);
+ return (&ops);
+}
diff --git a/lib/libc/rpc/clnt_simple.c b/lib/libc/rpc/clnt_simple.c
new file mode 100644
index 0000000..ba21d2d
--- /dev/null
+++ b/lib/libc/rpc/clnt_simple.c
@@ -0,0 +1,206 @@
+/* $NetBSD: clnt_simple.c,v 1.21 2000/07/06 03:10:34 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "from: @(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "from: @(#)clnt_simple.c 2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * clnt_simple.c
+ * Simplified front end to client rpc.
+ *
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/param.h>
+#include <stdio.h>
+#include <errno.h>
+#include <rpc/rpc.h>
+#include <string.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 64
+#endif
+
+#ifndef NETIDLEN
+#define NETIDLEN 32
+#endif
+
+struct rpc_call_private {
+ int valid; /* Is this entry valid ? */
+ CLIENT *client; /* Client handle */
+ pid_t pid; /* process-id at moment of creation */
+ rpcprog_t prognum; /* Program */
+ rpcvers_t versnum; /* Version */
+ char host[MAXHOSTNAMELEN]; /* Servers host */
+ char nettype[NETIDLEN]; /* Network type */
+};
+static struct rpc_call_private *rpc_call_private_main;
+static thread_key_t rpc_call_key;
+static once_t rpc_call_once = ONCE_INITIALIZER;
+static int rpc_call_key_error;
+
+static void rpc_call_key_init(void);
+static void rpc_call_destroy(void *);
+
+static void
+rpc_call_destroy(void *vp)
+{
+ struct rpc_call_private *rcp = (struct rpc_call_private *)vp;
+
+ if (rcp) {
+ if (rcp->client)
+ CLNT_DESTROY(rcp->client);
+ free(rcp);
+ }
+}
+
+static void
+rpc_call_key_init(void)
+{
+
+ rpc_call_key_error = thr_keycreate(&rpc_call_key, rpc_call_destroy);
+}
+
+/*
+ * This is the simplified interface to the client rpc layer.
+ * The client handle is not destroyed here and is reused for
+ * the future calls to same prog, vers, host and nettype combination.
+ *
+ * The total time available is 25 seconds.
+ */
+enum clnt_stat
+rpc_call(host, prognum, versnum, procnum, inproc, in, outproc, out, nettype)
+ const char *host; /* host name */
+ rpcprog_t prognum; /* program number */
+ rpcvers_t versnum; /* version number */
+ rpcproc_t procnum; /* procedure number */
+ xdrproc_t inproc, outproc; /* in/out XDR procedures */
+ const char *in;
+ char *out; /* recv/send data */
+ const char *nettype; /* nettype */
+{
+ struct rpc_call_private *rcp = (struct rpc_call_private *) 0;
+ enum clnt_stat clnt_stat;
+ struct timeval timeout, tottimeout;
+ int main_thread = 1;
+
+ if ((main_thread = thr_main())) {
+ rcp = rpc_call_private_main;
+ } else {
+ if (thr_once(&rpc_call_once, rpc_call_key_init) != 0 ||
+ rpc_call_key_error != 0) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = rpc_call_key_error;
+ return (rpc_createerr.cf_stat);
+ }
+ rcp = (struct rpc_call_private *)thr_getspecific(rpc_call_key);
+ }
+ if (rcp == NULL) {
+ rcp = malloc(sizeof (*rcp));
+ if (rcp == NULL) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ return (rpc_createerr.cf_stat);
+ }
+ if (main_thread)
+ rpc_call_private_main = rcp;
+ else
+ thr_setspecific(rpc_call_key, (void *) rcp);
+ rcp->valid = 0;
+ rcp->client = NULL;
+ }
+ if ((nettype == NULL) || (nettype[0] == 0))
+ nettype = "netpath";
+ if (!(rcp->valid && rcp->pid == getpid() &&
+ (rcp->prognum == prognum) &&
+ (rcp->versnum == versnum) &&
+ (!strcmp(rcp->host, host)) &&
+ (!strcmp(rcp->nettype, nettype)))) {
+ int fd;
+
+ rcp->valid = 0;
+ if (rcp->client)
+ CLNT_DESTROY(rcp->client);
+ /*
+ * Using the first successful transport for that type
+ */
+ rcp->client = clnt_create(host, prognum, versnum, nettype);
+ rcp->pid = getpid();
+ if (rcp->client == NULL) {
+ return (rpc_createerr.cf_stat);
+ }
+ /*
+ * Set time outs for connectionless case. Do it
+ * unconditionally. Faster than doing a t_getinfo()
+ * and then doing the right thing.
+ */
+ timeout.tv_usec = 0;
+ timeout.tv_sec = 5;
+ (void) CLNT_CONTROL(rcp->client,
+ CLSET_RETRY_TIMEOUT, (char *)(void *)&timeout);
+ if (CLNT_CONTROL(rcp->client, CLGET_FD, (char *)(void *)&fd))
+ _fcntl(fd, F_SETFD, 1); /* make it "close on exec" */
+ rcp->prognum = prognum;
+ rcp->versnum = versnum;
+ if ((strlen(host) < (size_t)MAXHOSTNAMELEN) &&
+ (strlen(nettype) < (size_t)NETIDLEN)) {
+ (void) strcpy(rcp->host, host);
+ (void) strcpy(rcp->nettype, nettype);
+ rcp->valid = 1;
+ } else {
+ rcp->valid = 0;
+ }
+ } /* else reuse old client */
+ tottimeout.tv_sec = 25;
+ tottimeout.tv_usec = 0;
+ /*LINTED const castaway*/
+ clnt_stat = CLNT_CALL(rcp->client, procnum, inproc, (char *) in,
+ outproc, out, tottimeout);
+ /*
+ * if call failed, empty cache
+ */
+ if (clnt_stat != RPC_SUCCESS)
+ rcp->valid = 0;
+ return (clnt_stat);
+}
diff --git a/lib/libc/rpc/clnt_vc.c b/lib/libc/rpc/clnt_vc.c
new file mode 100644
index 0000000..07eff46
--- /dev/null
+++ b/lib/libc/rpc/clnt_vc.c
@@ -0,0 +1,871 @@
+/* $NetBSD: clnt_vc.c,v 1.4 2000/07/14 08:40:42 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)clnt_tcp.c 2.2 88/08/01 4.0 RPCSRC";
+static char sccsid3[] = "@(#)clnt_vc.c 1.19 89/03/16 Copyr 1988 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * clnt_tcp.c, Implements a TCP/IP based, client side RPC.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * TCP based RPC supports 'batched calls'.
+ * A sequence of calls may be batched-up in a send buffer. The rpc call
+ * return immediately to the client even though the call was not necessarily
+ * sent. The batching occurs if the results' xdr routine is NULL (0) AND
+ * the rpc timeout value is zero (see clnt.h, rpc).
+ *
+ * Clients should NOT casually batch calls that in fact return results; that is,
+ * the server side should be aware that a call is batched and not produce any
+ * return message. Batched calls that produce many result messages can
+ * deadlock (netlock) the client and the server....
+ *
+ * Now go hang yourself.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <sys/syslog.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/uio.h>
+
+#include <arpa/inet.h>
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <rpc/rpc.h>
+#include <rpc/rpcsec_gss.h>
+#include "un-namespace.h"
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+#define MCALL_MSG_SIZE 24
+
+struct cmessage {
+ struct cmsghdr cmsg;
+ struct cmsgcred cmcred;
+};
+
+static enum clnt_stat clnt_vc_call(CLIENT *, rpcproc_t, xdrproc_t, void *,
+ xdrproc_t, void *, struct timeval);
+static void clnt_vc_geterr(CLIENT *, struct rpc_err *);
+static bool_t clnt_vc_freeres(CLIENT *, xdrproc_t, void *);
+static void clnt_vc_abort(CLIENT *);
+static bool_t clnt_vc_control(CLIENT *, u_int, void *);
+static void clnt_vc_destroy(CLIENT *);
+static struct clnt_ops *clnt_vc_ops(void);
+static bool_t time_not_ok(struct timeval *);
+static int read_vc(void *, void *, int);
+static int write_vc(void *, void *, int);
+static int __msgwrite(int, void *, size_t);
+static int __msgread(int, void *, size_t);
+
+struct ct_data {
+ int ct_fd; /* connection's fd */
+ bool_t ct_closeit; /* close it on destroy */
+ struct timeval ct_wait; /* wait interval in milliseconds */
+ bool_t ct_waitset; /* wait set by clnt_control? */
+ struct netbuf ct_addr; /* remote addr */
+ struct rpc_err ct_error;
+ union {
+ char ct_mcallc[MCALL_MSG_SIZE]; /* marshalled callmsg */
+ u_int32_t ct_mcalli;
+ } ct_u;
+ u_int ct_mpos; /* pos after marshal */
+ XDR ct_xdrs; /* XDR stream */
+};
+
+/*
+ * This machinery implements per-fd locks for MT-safety. It is not
+ * sufficient to do per-CLIENT handle locks for MT-safety because a
+ * user may create more than one CLIENT handle with the same fd behind
+ * it. Therfore, we allocate an array of flags (vc_fd_locks), protected
+ * by the clnt_fd_lock mutex, and an array (vc_cv) of condition variables
+ * similarly protected. Vc_fd_lock[fd] == 1 => a call is activte on some
+ * CLIENT handle created for that fd.
+ * The current implementation holds locks across the entire RPC and reply.
+ * Yes, this is silly, and as soon as this code is proven to work, this
+ * should be the first thing fixed. One step at a time.
+ */
+static int *vc_fd_locks;
+static cond_t *vc_cv;
+#define release_fd_lock(fd, mask) { \
+ mutex_lock(&clnt_fd_lock); \
+ vc_fd_locks[fd] = 0; \
+ mutex_unlock(&clnt_fd_lock); \
+ thr_sigsetmask(SIG_SETMASK, &(mask), (sigset_t *) NULL); \
+ cond_signal(&vc_cv[fd]); \
+}
+
+static const char clnt_vc_errstr[] = "%s : %s";
+static const char clnt_vc_str[] = "clnt_vc_create";
+static const char clnt_read_vc_str[] = "read_vc";
+static const char __no_mem_str[] = "out of memory";
+
+/*
+ * Create a client handle for a connection.
+ * Default options are set, which the user can change using clnt_control()'s.
+ * The rpc/vc package does buffering similar to stdio, so the client
+ * must pick send and receive buffer sizes, 0 => use the default.
+ * NB: fd is copied into a private area.
+ * NB: The rpch->cl_auth is set null authentication. Caller may wish to
+ * set this something more useful.
+ *
+ * fd should be an open socket
+ */
+CLIENT *
+clnt_vc_create(fd, raddr, prog, vers, sendsz, recvsz)
+ int fd; /* open file descriptor */
+ const struct netbuf *raddr; /* servers address */
+ const rpcprog_t prog; /* program number */
+ const rpcvers_t vers; /* version number */
+ u_int sendsz; /* buffer recv size */
+ u_int recvsz; /* buffer send size */
+{
+ CLIENT *cl; /* client handle */
+ struct ct_data *ct = NULL; /* client handle */
+ struct timeval now;
+ struct rpc_msg call_msg;
+ static u_int32_t disrupt;
+ sigset_t mask;
+ sigset_t newmask;
+ struct sockaddr_storage ss;
+ socklen_t slen;
+ struct __rpc_sockinfo si;
+
+ if (disrupt == 0)
+ disrupt = (u_int32_t)(long)raddr;
+
+ cl = (CLIENT *)mem_alloc(sizeof (*cl));
+ ct = (struct ct_data *)mem_alloc(sizeof (*ct));
+ if ((cl == (CLIENT *)NULL) || (ct == (struct ct_data *)NULL)) {
+ (void) syslog(LOG_ERR, clnt_vc_errstr,
+ clnt_vc_str, __no_mem_str);
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ goto err;
+ }
+ ct->ct_addr.buf = NULL;
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ if (vc_fd_locks == (int *) NULL) {
+ int cv_allocsz, fd_allocsz;
+ int dtbsize = __rpc_dtbsize();
+
+ fd_allocsz = dtbsize * sizeof (int);
+ vc_fd_locks = (int *) mem_alloc(fd_allocsz);
+ if (vc_fd_locks == (int *) NULL) {
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ goto err;
+ } else
+ memset(vc_fd_locks, '\0', fd_allocsz);
+
+ assert(vc_cv == (cond_t *) NULL);
+ cv_allocsz = dtbsize * sizeof (cond_t);
+ vc_cv = (cond_t *) mem_alloc(cv_allocsz);
+ if (vc_cv == (cond_t *) NULL) {
+ mem_free(vc_fd_locks, fd_allocsz);
+ vc_fd_locks = (int *) NULL;
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ goto err;
+ } else {
+ int i;
+
+ for (i = 0; i < dtbsize; i++)
+ cond_init(&vc_cv[i], 0, (void *) 0);
+ }
+ } else
+ assert(vc_cv != (cond_t *) NULL);
+
+ /*
+ * XXX - fvdl connecting while holding a mutex?
+ */
+ slen = sizeof ss;
+ if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
+ if (errno != ENOTCONN) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ goto err;
+ }
+ if (_connect(fd, (struct sockaddr *)raddr->buf, raddr->len) < 0){
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ goto err;
+ }
+ }
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ if (!__rpc_fd2sockinfo(fd, &si))
+ goto err;
+
+ ct->ct_closeit = FALSE;
+
+ /*
+ * Set up private data struct
+ */
+ ct->ct_fd = fd;
+ ct->ct_wait.tv_usec = 0;
+ ct->ct_waitset = FALSE;
+ ct->ct_addr.buf = malloc(raddr->maxlen);
+ if (ct->ct_addr.buf == NULL)
+ goto err;
+ memcpy(ct->ct_addr.buf, raddr->buf, raddr->len);
+ ct->ct_addr.len = raddr->maxlen;
+ ct->ct_addr.maxlen = raddr->maxlen;
+
+ /*
+ * Initialize call message
+ */
+ (void)gettimeofday(&now, NULL);
+ call_msg.rm_xid = ((u_int32_t)++disrupt) ^ __RPC_GETXID(&now);
+ call_msg.rm_direction = CALL;
+ call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ call_msg.rm_call.cb_prog = (u_int32_t)prog;
+ call_msg.rm_call.cb_vers = (u_int32_t)vers;
+
+ /*
+ * pre-serialize the static part of the call msg and stash it away
+ */
+ xdrmem_create(&(ct->ct_xdrs), ct->ct_u.ct_mcallc, MCALL_MSG_SIZE,
+ XDR_ENCODE);
+ if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) {
+ if (ct->ct_closeit) {
+ (void)_close(fd);
+ }
+ goto err;
+ }
+ ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs));
+ XDR_DESTROY(&(ct->ct_xdrs));
+ assert(ct->ct_mpos + sizeof(uint32_t) <= MCALL_MSG_SIZE);
+
+ /*
+ * Create a client handle which uses xdrrec for serialization
+ * and authnone for authentication.
+ */
+ cl->cl_ops = clnt_vc_ops();
+ cl->cl_private = ct;
+ cl->cl_auth = authnone_create();
+ sendsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsz);
+ recvsz = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsz);
+ xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz,
+ cl->cl_private, read_vc, write_vc);
+ return (cl);
+
+err:
+ if (cl) {
+ if (ct) {
+ if (ct->ct_addr.len)
+ mem_free(ct->ct_addr.buf, ct->ct_addr.len);
+ mem_free(ct, sizeof (struct ct_data));
+ }
+ if (cl)
+ mem_free(cl, sizeof (CLIENT));
+ }
+ return ((CLIENT *)NULL);
+}
+
+static enum clnt_stat
+clnt_vc_call(cl, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)
+ CLIENT *cl;
+ rpcproc_t proc;
+ xdrproc_t xdr_args;
+ void *args_ptr;
+ xdrproc_t xdr_results;
+ void *results_ptr;
+ struct timeval timeout;
+{
+ struct ct_data *ct = (struct ct_data *) cl->cl_private;
+ XDR *xdrs = &(ct->ct_xdrs);
+ struct rpc_msg reply_msg;
+ u_int32_t x_id;
+ u_int32_t *msg_x_id = &ct->ct_u.ct_mcalli; /* yuk */
+ bool_t shipnow;
+ int refreshes = 2;
+ sigset_t mask, newmask;
+ int rpc_lock_value;
+ bool_t reply_stat;
+
+ assert(cl != NULL);
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (vc_fd_locks[ct->ct_fd])
+ cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock);
+ if (__isthreaded)
+ rpc_lock_value = 1;
+ else
+ rpc_lock_value = 0;
+ vc_fd_locks[ct->ct_fd] = rpc_lock_value;
+ mutex_unlock(&clnt_fd_lock);
+ if (!ct->ct_waitset) {
+ /* If time is not within limits, we ignore it. */
+ if (time_not_ok(&timeout) == FALSE)
+ ct->ct_wait = timeout;
+ }
+
+ shipnow =
+ (xdr_results == NULL && timeout.tv_sec == 0
+ && timeout.tv_usec == 0) ? FALSE : TRUE;
+
+call_again:
+ xdrs->x_op = XDR_ENCODE;
+ ct->ct_error.re_status = RPC_SUCCESS;
+ x_id = ntohl(--(*msg_x_id));
+
+ if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) {
+ if ((! XDR_PUTBYTES(xdrs, ct->ct_u.ct_mcallc, ct->ct_mpos)) ||
+ (! XDR_PUTINT32(xdrs, &proc)) ||
+ (! AUTH_MARSHALL(cl->cl_auth, xdrs)) ||
+ (! (*xdr_args)(xdrs, args_ptr))) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ ct->ct_error.re_status = RPC_CANTENCODEARGS;
+ (void)xdrrec_endofrecord(xdrs, TRUE);
+ release_fd_lock(ct->ct_fd, mask);
+ return (ct->ct_error.re_status);
+ }
+ } else {
+ *(uint32_t *) &ct->ct_u.ct_mcallc[ct->ct_mpos] = htonl(proc);
+ if (! __rpc_gss_wrap(cl->cl_auth, ct->ct_u.ct_mcallc,
+ ct->ct_mpos + sizeof(uint32_t),
+ xdrs, xdr_args, args_ptr)) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ ct->ct_error.re_status = RPC_CANTENCODEARGS;
+ (void)xdrrec_endofrecord(xdrs, TRUE);
+ release_fd_lock(ct->ct_fd, mask);
+ return (ct->ct_error.re_status);
+ }
+ }
+ if (! xdrrec_endofrecord(xdrs, shipnow)) {
+ release_fd_lock(ct->ct_fd, mask);
+ return (ct->ct_error.re_status = RPC_CANTSEND);
+ }
+ if (! shipnow) {
+ release_fd_lock(ct->ct_fd, mask);
+ return (RPC_SUCCESS);
+ }
+ /*
+ * Hack to provide rpc-based message passing
+ */
+ if (timeout.tv_sec == 0 && timeout.tv_usec == 0) {
+ release_fd_lock(ct->ct_fd, mask);
+ return(ct->ct_error.re_status = RPC_TIMEDOUT);
+ }
+
+
+ /*
+ * Keep receiving until we get a valid transaction id
+ */
+ xdrs->x_op = XDR_DECODE;
+ while (TRUE) {
+ reply_msg.acpted_rply.ar_verf = _null_auth;
+ reply_msg.acpted_rply.ar_results.where = NULL;
+ reply_msg.acpted_rply.ar_results.proc = (xdrproc_t)xdr_void;
+ if (! xdrrec_skiprecord(xdrs)) {
+ release_fd_lock(ct->ct_fd, mask);
+ return (ct->ct_error.re_status);
+ }
+ /* now decode and validate the response header */
+ if (! xdr_replymsg(xdrs, &reply_msg)) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ continue;
+ release_fd_lock(ct->ct_fd, mask);
+ return (ct->ct_error.re_status);
+ }
+ if (reply_msg.rm_xid == x_id)
+ break;
+ }
+
+ /*
+ * process header
+ */
+ _seterr_reply(&reply_msg, &(ct->ct_error));
+ if (ct->ct_error.re_status == RPC_SUCCESS) {
+ if (! AUTH_VALIDATE(cl->cl_auth,
+ &reply_msg.acpted_rply.ar_verf)) {
+ ct->ct_error.re_status = RPC_AUTHERROR;
+ ct->ct_error.re_why = AUTH_INVALIDRESP;
+ } else {
+ if (cl->cl_auth->ah_cred.oa_flavor != RPCSEC_GSS) {
+ reply_stat = (*xdr_results)(xdrs, results_ptr);
+ } else {
+ reply_stat = __rpc_gss_unwrap(cl->cl_auth,
+ xdrs, xdr_results, results_ptr);
+ }
+ if (! reply_stat) {
+ if (ct->ct_error.re_status == RPC_SUCCESS)
+ ct->ct_error.re_status =
+ RPC_CANTDECODERES;
+ }
+ }
+ /* free verifier ... */
+ if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) {
+ xdrs->x_op = XDR_FREE;
+ (void)xdr_opaque_auth(xdrs,
+ &(reply_msg.acpted_rply.ar_verf));
+ }
+ } /* end successful completion */
+ else {
+ /* maybe our credentials need to be refreshed ... */
+ if (refreshes-- && AUTH_REFRESH(cl->cl_auth, &reply_msg))
+ goto call_again;
+ } /* end of unsuccessful completion */
+ release_fd_lock(ct->ct_fd, mask);
+ return (ct->ct_error.re_status);
+}
+
+static void
+clnt_vc_geterr(cl, errp)
+ CLIENT *cl;
+ struct rpc_err *errp;
+{
+ struct ct_data *ct;
+
+ assert(cl != NULL);
+ assert(errp != NULL);
+
+ ct = (struct ct_data *) cl->cl_private;
+ *errp = ct->ct_error;
+}
+
+static bool_t
+clnt_vc_freeres(cl, xdr_res, res_ptr)
+ CLIENT *cl;
+ xdrproc_t xdr_res;
+ void *res_ptr;
+{
+ struct ct_data *ct;
+ XDR *xdrs;
+ bool_t dummy;
+ sigset_t mask;
+ sigset_t newmask;
+
+ assert(cl != NULL);
+
+ ct = (struct ct_data *)cl->cl_private;
+ xdrs = &(ct->ct_xdrs);
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (vc_fd_locks[ct->ct_fd])
+ cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock);
+ xdrs->x_op = XDR_FREE;
+ dummy = (*xdr_res)(xdrs, res_ptr);
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ cond_signal(&vc_cv[ct->ct_fd]);
+
+ return dummy;
+}
+
+/*ARGSUSED*/
+static void
+clnt_vc_abort(cl)
+ CLIENT *cl;
+{
+}
+
+static bool_t
+clnt_vc_control(cl, request, info)
+ CLIENT *cl;
+ u_int request;
+ void *info;
+{
+ struct ct_data *ct;
+ void *infop = info;
+ sigset_t mask;
+ sigset_t newmask;
+ int rpc_lock_value;
+
+ assert(cl != NULL);
+
+ ct = (struct ct_data *)cl->cl_private;
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (vc_fd_locks[ct->ct_fd])
+ cond_wait(&vc_cv[ct->ct_fd], &clnt_fd_lock);
+ if (__isthreaded)
+ rpc_lock_value = 1;
+ else
+ rpc_lock_value = 0;
+ vc_fd_locks[ct->ct_fd] = rpc_lock_value;
+ mutex_unlock(&clnt_fd_lock);
+
+ switch (request) {
+ case CLSET_FD_CLOSE:
+ ct->ct_closeit = TRUE;
+ release_fd_lock(ct->ct_fd, mask);
+ return (TRUE);
+ case CLSET_FD_NCLOSE:
+ ct->ct_closeit = FALSE;
+ release_fd_lock(ct->ct_fd, mask);
+ return (TRUE);
+ default:
+ break;
+ }
+
+ /* for other requests which use info */
+ if (info == NULL) {
+ release_fd_lock(ct->ct_fd, mask);
+ return (FALSE);
+ }
+ switch (request) {
+ case CLSET_TIMEOUT:
+ if (time_not_ok((struct timeval *)info)) {
+ release_fd_lock(ct->ct_fd, mask);
+ return (FALSE);
+ }
+ ct->ct_wait = *(struct timeval *)infop;
+ ct->ct_waitset = TRUE;
+ break;
+ case CLGET_TIMEOUT:
+ *(struct timeval *)infop = ct->ct_wait;
+ break;
+ case CLGET_SERVER_ADDR:
+ (void) memcpy(info, ct->ct_addr.buf, (size_t)ct->ct_addr.len);
+ break;
+ case CLGET_FD:
+ *(int *)info = ct->ct_fd;
+ break;
+ case CLGET_SVC_ADDR:
+ /* The caller should not free this memory area */
+ *(struct netbuf *)info = ct->ct_addr;
+ break;
+ case CLSET_SVC_ADDR: /* set to new address */
+ release_fd_lock(ct->ct_fd, mask);
+ return (FALSE);
+ case CLGET_XID:
+ /*
+ * use the knowledge that xid is the
+ * first element in the call structure
+ * This will get the xid of the PREVIOUS call
+ */
+ *(u_int32_t *)info =
+ ntohl(*(u_int32_t *)(void *)&ct->ct_u.ct_mcalli);
+ break;
+ case CLSET_XID:
+ /* This will set the xid of the NEXT call */
+ *(u_int32_t *)(void *)&ct->ct_u.ct_mcalli =
+ htonl(*((u_int32_t *)info) + 1);
+ /* increment by 1 as clnt_vc_call() decrements once */
+ break;
+ case CLGET_VERS:
+ /*
+ * This RELIES on the information that, in the call body,
+ * the version number field is the fifth field from the
+ * begining of the RPC header. MUST be changed if the
+ * call_struct is changed
+ */
+ *(u_int32_t *)info =
+ ntohl(*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
+ 4 * BYTES_PER_XDR_UNIT));
+ break;
+
+ case CLSET_VERS:
+ *(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
+ 4 * BYTES_PER_XDR_UNIT) =
+ htonl(*(u_int32_t *)info);
+ break;
+
+ case CLGET_PROG:
+ /*
+ * This RELIES on the information that, in the call body,
+ * the program number field is the fourth field from the
+ * begining of the RPC header. MUST be changed if the
+ * call_struct is changed
+ */
+ *(u_int32_t *)info =
+ ntohl(*(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
+ 3 * BYTES_PER_XDR_UNIT));
+ break;
+
+ case CLSET_PROG:
+ *(u_int32_t *)(void *)(ct->ct_u.ct_mcallc +
+ 3 * BYTES_PER_XDR_UNIT) =
+ htonl(*(u_int32_t *)info);
+ break;
+
+ default:
+ release_fd_lock(ct->ct_fd, mask);
+ return (FALSE);
+ }
+ release_fd_lock(ct->ct_fd, mask);
+ return (TRUE);
+}
+
+
+static void
+clnt_vc_destroy(cl)
+ CLIENT *cl;
+{
+ struct ct_data *ct = (struct ct_data *) cl->cl_private;
+ int ct_fd = ct->ct_fd;
+ sigset_t mask;
+ sigset_t newmask;
+
+ assert(cl != NULL);
+
+ ct = (struct ct_data *) cl->cl_private;
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&clnt_fd_lock);
+ while (vc_fd_locks[ct_fd])
+ cond_wait(&vc_cv[ct_fd], &clnt_fd_lock);
+ if (ct->ct_closeit && ct->ct_fd != -1) {
+ (void)_close(ct->ct_fd);
+ }
+ XDR_DESTROY(&(ct->ct_xdrs));
+ if (ct->ct_addr.buf)
+ free(ct->ct_addr.buf);
+ mem_free(ct, sizeof(struct ct_data));
+ mem_free(cl, sizeof(CLIENT));
+ mutex_unlock(&clnt_fd_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ cond_signal(&vc_cv[ct_fd]);
+}
+
+/*
+ * Interface between xdr serializer and tcp connection.
+ * Behaves like the system calls, read & write, but keeps some error state
+ * around for the rpc level.
+ */
+static int
+read_vc(ctp, buf, len)
+ void *ctp;
+ void *buf;
+ int len;
+{
+ struct sockaddr sa;
+ socklen_t sal;
+ struct ct_data *ct = (struct ct_data *)ctp;
+ struct pollfd fd;
+ int milliseconds = (int)((ct->ct_wait.tv_sec * 1000) +
+ (ct->ct_wait.tv_usec / 1000));
+
+ if (len == 0)
+ return (0);
+ fd.fd = ct->ct_fd;
+ fd.events = POLLIN;
+ for (;;) {
+ switch (_poll(&fd, 1, milliseconds)) {
+ case 0:
+ ct->ct_error.re_status = RPC_TIMEDOUT;
+ return (-1);
+
+ case -1:
+ if (errno == EINTR)
+ continue;
+ ct->ct_error.re_status = RPC_CANTRECV;
+ ct->ct_error.re_errno = errno;
+ return (-1);
+ }
+ break;
+ }
+
+ sal = sizeof(sa);
+ if ((_getpeername(ct->ct_fd, &sa, &sal) == 0) &&
+ (sa.sa_family == AF_LOCAL)) {
+ len = __msgread(ct->ct_fd, buf, (size_t)len);
+ } else {
+ len = _read(ct->ct_fd, buf, (size_t)len);
+ }
+
+ switch (len) {
+ case 0:
+ /* premature eof */
+ ct->ct_error.re_errno = ECONNRESET;
+ ct->ct_error.re_status = RPC_CANTRECV;
+ len = -1; /* it's really an error */
+ break;
+
+ case -1:
+ ct->ct_error.re_errno = errno;
+ ct->ct_error.re_status = RPC_CANTRECV;
+ break;
+ }
+ return (len);
+}
+
+static int
+write_vc(ctp, buf, len)
+ void *ctp;
+ void *buf;
+ int len;
+{
+ struct sockaddr sa;
+ socklen_t sal;
+ struct ct_data *ct = (struct ct_data *)ctp;
+ int i, cnt;
+
+ sal = sizeof(sa);
+ if ((_getpeername(ct->ct_fd, &sa, &sal) == 0) &&
+ (sa.sa_family == AF_LOCAL)) {
+ for (cnt = len; cnt > 0; cnt -= i, buf = (char *)buf + i) {
+ if ((i = __msgwrite(ct->ct_fd, buf,
+ (size_t)cnt)) == -1) {
+ ct->ct_error.re_errno = errno;
+ ct->ct_error.re_status = RPC_CANTSEND;
+ return (-1);
+ }
+ }
+ } else {
+ for (cnt = len; cnt > 0; cnt -= i, buf = (char *)buf + i) {
+ if ((i = _write(ct->ct_fd, buf, (size_t)cnt)) == -1) {
+ ct->ct_error.re_errno = errno;
+ ct->ct_error.re_status = RPC_CANTSEND;
+ return (-1);
+ }
+ }
+ }
+ return (len);
+}
+
+static struct clnt_ops *
+clnt_vc_ops()
+{
+ static struct clnt_ops ops;
+ sigset_t mask, newmask;
+
+ /* VARIABLES PROTECTED BY ops_lock: ops */
+
+ sigfillset(&newmask);
+ thr_sigsetmask(SIG_SETMASK, &newmask, &mask);
+ mutex_lock(&ops_lock);
+ if (ops.cl_call == NULL) {
+ ops.cl_call = clnt_vc_call;
+ ops.cl_abort = clnt_vc_abort;
+ ops.cl_geterr = clnt_vc_geterr;
+ ops.cl_freeres = clnt_vc_freeres;
+ ops.cl_destroy = clnt_vc_destroy;
+ ops.cl_control = clnt_vc_control;
+ }
+ mutex_unlock(&ops_lock);
+ thr_sigsetmask(SIG_SETMASK, &(mask), NULL);
+ return (&ops);
+}
+
+/*
+ * Make sure that the time is not garbage. -1 value is disallowed.
+ * Note this is different from time_not_ok in clnt_dg.c
+ */
+static bool_t
+time_not_ok(t)
+ struct timeval *t;
+{
+ return (t->tv_sec <= -1 || t->tv_sec > 100000000 ||
+ t->tv_usec <= -1 || t->tv_usec > 1000000);
+}
+
+static int
+__msgread(sock, buf, cnt)
+ int sock;
+ void *buf;
+ size_t cnt;
+{
+ struct iovec iov[1];
+ struct msghdr msg;
+ union {
+ struct cmsghdr cmsg;
+ char control[CMSG_SPACE(sizeof(struct cmsgcred))];
+ } cm;
+
+ bzero((char *)&cm, sizeof(cm));
+ iov[0].iov_base = buf;
+ iov[0].iov_len = cnt;
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_control = (caddr_t)&cm;
+ msg.msg_controllen = CMSG_SPACE(sizeof(struct cmsgcred));
+ msg.msg_flags = 0;
+
+ return(_recvmsg(sock, &msg, 0));
+}
+
+static int
+__msgwrite(sock, buf, cnt)
+ int sock;
+ void *buf;
+ size_t cnt;
+{
+ struct iovec iov[1];
+ struct msghdr msg;
+ union {
+ struct cmsghdr cmsg;
+ char control[CMSG_SPACE(sizeof(struct cmsgcred))];
+ } cm;
+
+ bzero((char *)&cm, sizeof(cm));
+ iov[0].iov_base = buf;
+ iov[0].iov_len = cnt;
+
+ cm.cmsg.cmsg_type = SCM_CREDS;
+ cm.cmsg.cmsg_level = SOL_SOCKET;
+ cm.cmsg.cmsg_len = CMSG_LEN(sizeof(struct cmsgcred));
+
+ msg.msg_iov = iov;
+ msg.msg_iovlen = 1;
+ msg.msg_name = NULL;
+ msg.msg_namelen = 0;
+ msg.msg_control = (caddr_t)&cm;
+ msg.msg_controllen = CMSG_SPACE(sizeof(struct cmsgcred));
+ msg.msg_flags = 0;
+
+ return(_sendmsg(sock, &msg, 0));
+}
diff --git a/lib/libc/rpc/crypt_client.c b/lib/libc/rpc/crypt_client.c
new file mode 100644
index 0000000..4e5c793
--- /dev/null
+++ b/lib/libc/rpc/crypt_client.c
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 1996
+ * Bill Paul <wpaul@ctr.columbia.edu>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Bill Paul.
+ * 4. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <err.h>
+#include <sys/types.h>
+#include <rpc/des_crypt.h>
+#include <rpc/des.h>
+#include <string.h>
+#include <rpcsvc/crypt.h>
+#include "un-namespace.h"
+
+int
+_des_crypt_call(buf, len, dparms)
+ char *buf;
+ int len;
+ struct desparams *dparms;
+{
+ CLIENT *clnt;
+ desresp *result_1;
+ desargs des_crypt_1_arg;
+ struct netconfig *nconf;
+ void *localhandle;
+ int stat;
+
+ nconf = NULL;
+ localhandle = setnetconfig();
+ while ((nconf = getnetconfig(localhandle)) != NULL) {
+ if (nconf->nc_protofmly != NULL &&
+ strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
+ break;
+ }
+ if (nconf == NULL) {
+ warnx("getnetconfig: %s", nc_sperror());
+ return(DESERR_HWERROR);
+ }
+ clnt = clnt_tp_create(NULL, CRYPT_PROG, CRYPT_VERS, nconf);
+ if (clnt == (CLIENT *) NULL) {
+ endnetconfig(localhandle);
+ return(DESERR_HWERROR);
+ }
+ endnetconfig(localhandle);
+
+ des_crypt_1_arg.desbuf.desbuf_len = len;
+ des_crypt_1_arg.desbuf.desbuf_val = buf;
+ des_crypt_1_arg.des_dir = (dparms->des_dir == ENCRYPT) ? ENCRYPT_DES : DECRYPT_DES;
+ des_crypt_1_arg.des_mode = (dparms->des_mode == CBC) ? CBC_DES : ECB_DES;
+ bcopy(dparms->des_ivec, des_crypt_1_arg.des_ivec, 8);
+ bcopy(dparms->des_key, des_crypt_1_arg.des_key, 8);
+
+ result_1 = des_crypt_1(&des_crypt_1_arg, clnt);
+ if (result_1 == (desresp *) NULL) {
+ clnt_destroy(clnt);
+ return(DESERR_HWERROR);
+ }
+
+ stat = result_1->stat;
+
+ if (result_1->stat == DESERR_NONE ||
+ result_1->stat == DESERR_NOHWDEVICE) {
+ bcopy(result_1->desbuf.desbuf_val, buf, len);
+ bcopy(result_1->des_ivec, dparms->des_ivec, 8);
+ }
+
+ clnt_freeres(clnt, (xdrproc_t)xdr_desresp, result_1);
+ clnt_destroy(clnt);
+
+ return(stat);
+}
diff --git a/lib/libc/rpc/des_crypt.3 b/lib/libc/rpc/des_crypt.3
new file mode 100644
index 0000000..b40a62c
--- /dev/null
+++ b/lib/libc/rpc/des_crypt.3
@@ -0,0 +1,130 @@
+.\" @(#)des_crypt.3 2.1 88/08/11 4.0 RPCSRC; from 1.16 88/03/02 SMI;
+.\" $FreeBSD$
+.\"
+.Dd October 6, 1987
+.Dt DES_CRYPT 3
+.Os
+.Sh NAME
+.Nm des_crypt , ecb_crypt , cbc_crypt , des_setparity
+.Nd "fast DES encryption"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In rpc/des_crypt.h
+.Ft int
+.Fn ecb_crypt "char *key" "char *data" "unsigned datalen" "unsigned mode"
+.Ft int
+.Fn cbc_crypt "char *key" "char *data" "unsigned datalen" "unsigned mode" "char *ivec"
+.Ft void
+.Fn des_setparity "char *key"
+.Sh DESCRIPTION
+The
+.Fn ecb_crypt
+and
+.Fn cbc_crypt
+functions
+implement the
+.Tn NBS
+.Tn DES
+(Data Encryption Standard).
+These routines are faster and more general purpose than
+.Xr crypt 3 .
+They also are able to utilize
+.Tn DES
+hardware if it is available.
+The
+.Fn ecb_crypt
+function
+encrypts in
+.Tn ECB
+(Electronic Code Book)
+mode, which encrypts blocks of data independently.
+The
+.Fn cbc_crypt
+function
+encrypts in
+.Tn CBC
+(Cipher Block Chaining)
+mode, which chains together
+successive blocks.
+.Tn CBC
+mode protects against insertions, deletions and
+substitutions of blocks.
+Also, regularities in the clear text will
+not appear in the cipher text.
+.Pp
+Here is how to use these routines.
+The first argument,
+.Fa key ,
+is the 8-byte encryption key with parity.
+To set the key's parity, which for
+.Tn DES
+is in the low bit of each byte, use
+.Fn des_setparity .
+The second argument,
+.Fa data ,
+contains the data to be encrypted or decrypted.
+The
+third argument,
+.Fa datalen ,
+is the length in bytes of
+.Fa data ,
+which must be a multiple of 8.
+The fourth argument,
+.Fa mode ,
+is formed by
+.Em OR Ns 'ing
+together some things.
+For the encryption direction
+.Em OR
+in either
+.Dv DES_ENCRYPT
+or
+.Dv DES_DECRYPT .
+For software versus hardware
+encryption,
+.Em OR
+in either
+.Dv DES_HW
+or
+.Dv DES_SW .
+If
+.Dv DES_HW
+is specified, and there is no hardware, then the encryption is performed
+in software and the routine returns
+.Er DESERR_NOHWDEVICE .
+For
+.Fn cbc_crypt ,
+the
+.Fa ivec
+argument
+is the 8-byte initialization
+vector for the chaining.
+It is updated to the next initialization
+vector upon return.
+.Sh ERRORS
+.Bl -tag -width [DESERR_NOHWDEVICE] -compact
+.It Bq Er DESERR_NONE
+No error.
+.It Bq Er DESERR_NOHWDEVICE
+Encryption succeeded, but done in software instead of the requested hardware.
+.It Bq Er DESERR_HWERR
+An error occurred in the hardware or driver.
+.It Bq Er DESERR_BADPARAM
+Bad argument to routine.
+.El
+.Pp
+Given a result status
+.Va stat ,
+the macro
+.Fn DES_FAILED stat
+is false only for the first two statuses.
+.Sh SEE ALSO
+.\" .Xr des 1 ,
+.Xr crypt 3
+.Sh RESTRICTIONS
+These routines are not available in RPCSRC 4.0.
+This information is provided to describe the
+.Tn DES
+interface expected by
+Secure RPC.
diff --git a/lib/libc/rpc/des_crypt.c b/lib/libc/rpc/des_crypt.c
new file mode 100644
index 0000000..238d55a
--- /dev/null
+++ b/lib/libc/rpc/des_crypt.c
@@ -0,0 +1,154 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * des_crypt.c, DES encryption library routines
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+#include <sys/types.h>
+#include <rpc/des_crypt.h>
+#include <rpc/des.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)des_crypt.c 2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+static int common_crypt( char *, char *, unsigned, unsigned, struct desparams * );
+int (*__des_crypt_LOCAL)() = 0;
+extern int _des_crypt_call(char *, int, struct desparams *);
+/*
+ * Copy 8 bytes
+ */
+#define COPY8(src, dst) { \
+ char *a = (char *) dst; \
+ char *b = (char *) src; \
+ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+}
+
+/*
+ * Copy multiple of 8 bytes
+ */
+#define DESCOPY(src, dst, len) { \
+ char *a = (char *) dst; \
+ char *b = (char *) src; \
+ int i; \
+ for (i = (int) len; i > 0; i -= 8) { \
+ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+ *a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \
+ } \
+}
+
+/*
+ * CBC mode encryption
+ */
+int
+cbc_crypt(key, buf, len, mode, ivec)
+ char *key;
+ char *buf;
+ unsigned len;
+ unsigned mode;
+ char *ivec;
+{
+ int err;
+ struct desparams dp;
+
+#ifdef BROKEN_DES
+ dp.UDES.UDES_buf = buf;
+ dp.des_mode = ECB;
+#else
+ dp.des_mode = CBC;
+#endif
+ COPY8(ivec, dp.des_ivec);
+ err = common_crypt(key, buf, len, mode, &dp);
+ COPY8(dp.des_ivec, ivec);
+ return(err);
+}
+
+
+/*
+ * ECB mode encryption
+ */
+int
+ecb_crypt(key, buf, len, mode)
+ char *key;
+ char *buf;
+ unsigned len;
+ unsigned mode;
+{
+ struct desparams dp;
+
+#ifdef BROKEN_DES
+ dp.UDES.UDES_buf = buf;
+ dp.des_mode = CBC;
+#else
+ dp.des_mode = ECB;
+#endif
+ return(common_crypt(key, buf, len, mode, &dp));
+}
+
+
+
+/*
+ * Common code to cbc_crypt() & ecb_crypt()
+ */
+static int
+common_crypt(key, buf, len, mode, desp)
+ char *key;
+ char *buf;
+ unsigned len;
+ unsigned mode;
+ struct desparams *desp;
+{
+ int desdev;
+
+ if ((len % 8) != 0 || len > DES_MAXDATA) {
+ return(DESERR_BADPARAM);
+ }
+ desp->des_dir =
+ ((mode & DES_DIRMASK) == DES_ENCRYPT) ? ENCRYPT : DECRYPT;
+
+ desdev = mode & DES_DEVMASK;
+ COPY8(key, desp->des_key);
+ /*
+ * software
+ */
+ if (__des_crypt_LOCAL != NULL) {
+ if (!__des_crypt_LOCAL(buf, len, desp)) {
+ return (DESERR_HWERROR);
+ }
+ } else {
+ if (!_des_crypt_call(buf, len, desp)) {
+ return (DESERR_HWERROR);
+ }
+ }
+ return(desdev == DES_SW ? DESERR_NONE : DESERR_NOHWDEVICE);
+}
diff --git a/lib/libc/rpc/des_soft.c b/lib/libc/rpc/des_soft.c
new file mode 100644
index 0000000..daed265
--- /dev/null
+++ b/lib/libc/rpc/des_soft.c
@@ -0,0 +1,71 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)des_soft.c 2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Table giving odd parity in the low bit for ASCII characters
+ */
+static char partab[128] = {
+ 0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07,
+ 0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e,
+ 0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16,
+ 0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f,
+ 0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26,
+ 0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f,
+ 0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37,
+ 0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e,
+ 0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46,
+ 0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f,
+ 0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57,
+ 0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e,
+ 0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67,
+ 0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e,
+ 0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76,
+ 0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f,
+};
+
+/*
+ * Add odd parity to low bit of 8 byte key
+ */
+void
+des_setparity(p)
+ char *p;
+{
+ int i;
+
+ for (i = 0; i < 8; i++) {
+ *p = partab[*p & 0x7f];
+ p++;
+ }
+}
diff --git a/lib/libc/rpc/getnetconfig.3 b/lib/libc/rpc/getnetconfig.3
new file mode 100644
index 0000000..e67b9bb
--- /dev/null
+++ b/lib/libc/rpc/getnetconfig.3
@@ -0,0 +1,222 @@
+.\" @(#)getnetconfig.3n 1.28 93/06/02 SMI; from SVr4
+.\" $NetBSD: getnetconfig.3,v 1.1 2000/06/02 23:11:11 fvdl Exp $
+.\" $FreeBSD$
+.\" Copyright 1989 AT&T
+.Dd April 22, 2000
+.Dt GETNETCONFIG 3
+.Os
+.Sh NAME
+.Nm getnetconfig ,
+.Nm setnetconfig ,
+.Nm endnetconfig ,
+.Nm getnetconfigent ,
+.Nm freenetconfigent ,
+.Nm nc_perror ,
+.Nm nc_sperror
+.Nd get network configuration database entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In netconfig.h
+.Ft "struct netconfig *"
+.Fn getnetconfig "void *handlep"
+.Ft "void *"
+.Fn setnetconfig "void"
+.Ft int
+.Fn endnetconfig "void *handlep"
+.Ft "struct netconfig *"
+.Fn getnetconfigent "const char *netid"
+.Ft void
+.Fn freenetconfigent "struct netconfig *netconfigp"
+.Ft void
+.Fn nc_perror "const char *msg"
+.Ft "char *"
+.Fn nc_sperror "void"
+.Sh DESCRIPTION
+The library routines described on this page
+provide the application access to
+the system network configuration database,
+.Pa /etc/netconfig .
+The
+.Fn getnetconfig
+function
+returns a pointer to the
+current entry in the
+netconfig
+database, formatted as a
+.Ft "struct netconfig" .
+Successive calls will return successive netconfig
+entries in the netconfig database.
+The
+.Fn getnetconfig
+function
+can be used to search the entire netconfig
+file.
+The
+.Fn getnetconfig
+function
+returns
+.Dv NULL
+at the end of the file.
+The
+.Fa handlep
+argument
+is the handle obtained through
+.Fn setnetconfig .
+.Pp
+A call to
+.Fn setnetconfig
+has the effect of
+.Dq binding
+to or
+.Dq rewinding
+the netconfig database.
+The
+.Fn setnetconfig
+function
+must be called before the first call to
+.Fn getnetconfig
+and may be called at any other time.
+The
+.Fn setnetconfig
+function
+need not be called before a call to
+.Fn getnetconfigent .
+The
+.Fn setnetconfig
+function
+returns a unique handle to be used by
+.Fn getnetconfig .
+.Pp
+The
+.Fn endnetconfig
+function
+should be called when processing is complete to release resources for reuse.
+The
+.Fa handlep
+argument
+is the handle obtained through
+.Fn setnetconfig .
+Programmers should be aware, however, that the last call to
+.Fn endnetconfig
+frees all memory allocated by
+.Fn getnetconfig
+for the
+.Ft "struct netconfig"
+data structure.
+The
+.Fn endnetconfig
+function
+may not be called before
+.Fn setnetconfig .
+.Pp
+The
+.Fn getnetconfigent
+function
+returns a pointer
+to the netconfig structure corresponding
+to
+.Fa netid .
+It returns
+.Dv NULL
+if
+.Fa netid
+is invalid
+(that is, does not name an entry in the netconfig database).
+.Pp
+The
+.Fn freenetconfigent
+function
+frees the netconfig structure pointed to by
+.Fa netconfigp
+(previously returned by
+.Fn getnetconfigent ) .
+.Pp
+The
+.Fn nc_perror
+function
+prints a message to the standard error indicating why any of the
+above routines failed.
+The message is prepended with the string
+.Fa msg
+and a colon.
+A newline character is appended at the end of the message.
+.Pp
+The
+.Fn nc_sperror
+function
+is similar to
+.Fn nc_perror
+but instead of sending the message
+to the standard error, will return a pointer to a string that
+contains the error message.
+.Pp
+The
+.Fn nc_perror
+and
+.Fn nc_sperror
+functions
+can also be used with the
+.Ev NETPATH
+access routines defined in
+.Xr getnetpath 3 .
+.Sh RETURN VALUES
+The
+.Fn setnetconfig
+function
+returns a unique handle to be used by
+.Fn getnetconfig .
+In the case of an error,
+.Fn setnetconfig
+returns
+.Dv NULL
+and
+.Fn nc_perror
+or
+.Fn nc_sperror
+can be used to print the reason for failure.
+.Pp
+The
+.Fn getnetconfig
+function
+returns a pointer to the current entry in the netconfig
+database, formatted as a
+.Ft "struct netconfig" .
+The
+.Fn getnetconfig
+function
+returns
+.Dv NULL
+at the end of the file, or upon failure.
+.Pp
+The
+.Fn endnetconfig
+function
+returns 0 on success and \-1 on failure
+(for example, if
+.Fn setnetconfig
+was not called previously).
+.Pp
+On success,
+.Fn getnetconfigent
+returns a pointer to the
+.Ft "struct netconfig"
+structure corresponding to
+.Fa netid ;
+otherwise it returns
+.Dv NULL .
+.Pp
+The
+.Fn nc_sperror
+function
+returns a pointer to a buffer which contains the error message string.
+This buffer is overwritten on each call.
+In multithreaded applications, this buffer is
+implemented as thread-specific data.
+.Sh FILES
+.Bl -tag -width /etc/netconfig -compact
+.It Pa /etc/netconfig
+.El
+.Sh SEE ALSO
+.Xr getnetpath 3 ,
+.Xr netconfig 5
diff --git a/lib/libc/rpc/getnetconfig.c b/lib/libc/rpc/getnetconfig.c
new file mode 100644
index 0000000..1310e36
--- /dev/null
+++ b/lib/libc/rpc/getnetconfig.c
@@ -0,0 +1,742 @@
+/* $NetBSD: getnetconfig.c,v 1.3 2000/07/06 03:10:34 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetconfig.c 1.12 91/12/19 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Copyright (c) 1989 by Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <stdio.h>
+#include <errno.h>
+#include <netconfig.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <rpc/rpc.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "rpc_com.h"
+
+/*
+ * The five library routines in this file provide application access to the
+ * system network configuration database, /etc/netconfig. In addition to the
+ * netconfig database and the routines for accessing it, the environment
+ * variable NETPATH and its corresponding routines in getnetpath.c may also be
+ * used to specify the network transport to be used.
+ */
+
+
+/*
+ * netconfig errors
+ */
+
+#define NC_NONETCONFIG ENOENT
+#define NC_NOMEM ENOMEM
+#define NC_NOTINIT EINVAL /* setnetconfig was not called first */
+#define NC_BADFILE EBADF /* format for netconfig file is bad */
+#define NC_NOTFOUND ENOPROTOOPT /* specified netid was not found */
+
+/*
+ * semantics as strings (should be in netconfig.h)
+ */
+#define NC_TPI_CLTS_S "tpi_clts"
+#define NC_TPI_COTS_S "tpi_cots"
+#define NC_TPI_COTS_ORD_S "tpi_cots_ord"
+#define NC_TPI_RAW_S "tpi_raw"
+
+/*
+ * flags as characters (also should be in netconfig.h)
+ */
+#define NC_NOFLAG_C '-'
+#define NC_VISIBLE_C 'v'
+#define NC_BROADCAST_C 'b'
+
+/*
+ * Character used to indicate there is no name-to-address lookup library
+ */
+#define NC_NOLOOKUP "-"
+
+static const char * const _nc_errors[] = {
+ "Netconfig database not found",
+ "Not enough memory",
+ "Not initialized",
+ "Netconfig database has invalid format",
+ "Netid not found in netconfig database"
+};
+
+struct netconfig_info {
+ int eof; /* all entries has been read */
+ int ref; /* # of times setnetconfig() has been called */
+ struct netconfig_list *head; /* head of the list */
+ struct netconfig_list *tail; /* last of the list */
+};
+
+struct netconfig_list {
+ char *linep; /* hold line read from netconfig */
+ struct netconfig *ncp;
+ struct netconfig_list *next;
+};
+
+struct netconfig_vars {
+ int valid; /* token that indicates a valid netconfig_vars */
+ int flag; /* first time flag */
+ struct netconfig_list *nc_configs; /* pointer to the current netconfig entry */
+};
+
+#define NC_VALID 0xfeed
+#define NC_STORAGE 0xf00d
+#define NC_INVALID 0
+
+
+static int *__nc_error(void);
+static int parse_ncp(char *, struct netconfig *);
+static struct netconfig *dup_ncp(struct netconfig *);
+
+
+static FILE *nc_file; /* for netconfig db */
+static mutex_t nc_file_lock = MUTEX_INITIALIZER;
+
+static struct netconfig_info ni = { 0, 0, NULL, NULL};
+static mutex_t ni_lock = MUTEX_INITIALIZER;
+
+static thread_key_t nc_key;
+static once_t nc_once = ONCE_INITIALIZER;
+static int nc_key_error;
+
+static void
+nc_key_init(void)
+{
+
+ nc_key_error = thr_keycreate(&nc_key, free);
+}
+
+#define MAXNETCONFIGLINE 1000
+
+static int *
+__nc_error()
+{
+ static int nc_error = 0;
+ int *nc_addr;
+
+ /*
+ * Use the static `nc_error' if we are the main thread
+ * (including non-threaded programs), or if an allocation
+ * fails.
+ */
+ if (thr_main())
+ return (&nc_error);
+ if (thr_once(&nc_once, nc_key_init) != 0 || nc_key_error != 0)
+ return (&nc_error);
+ if ((nc_addr = (int *)thr_getspecific(nc_key)) == NULL) {
+ nc_addr = (int *)malloc(sizeof (int));
+ if (thr_setspecific(nc_key, (void *) nc_addr) != 0) {
+ if (nc_addr)
+ free(nc_addr);
+ return (&nc_error);
+ }
+ *nc_addr = 0;
+ }
+ return (nc_addr);
+}
+
+#define nc_error (*(__nc_error()))
+/*
+ * A call to setnetconfig() establishes a /etc/netconfig "session". A session
+ * "handle" is returned on a successful call. At the start of a session (after
+ * a call to setnetconfig()) searches through the /etc/netconfig database will
+ * proceed from the start of the file. The session handle must be passed to
+ * getnetconfig() to parse the file. Each call to getnetconfig() using the
+ * current handle will process one subsequent entry in /etc/netconfig.
+ * setnetconfig() must be called before the first call to getnetconfig().
+ * (Handles are used to allow for nested calls to setnetpath()).
+ *
+ * A new session is established with each call to setnetconfig(), with a new
+ * handle being returned on each call. Previously established sessions remain
+ * active until endnetconfig() is called with that session's handle as an
+ * argument.
+ *
+ * setnetconfig() need *not* be called before a call to getnetconfigent().
+ * setnetconfig() returns a NULL pointer on failure (for example, if
+ * the netconfig database is not present).
+ */
+void *
+setnetconfig()
+{
+ struct netconfig_vars *nc_vars;
+
+ if ((nc_vars = (struct netconfig_vars *)malloc(sizeof
+ (struct netconfig_vars))) == NULL) {
+ return(NULL);
+ }
+
+ /*
+ * For multiple calls, i.e. nc_file is not NULL, we just return the
+ * handle without reopening the netconfig db.
+ */
+ mutex_lock(&ni_lock);
+ ni.ref++;
+ mutex_unlock(&ni_lock);
+
+ mutex_lock(&nc_file_lock);
+ if ((nc_file != NULL) || (nc_file = fopen(NETCONFIG, "r")) != NULL) {
+ nc_vars->valid = NC_VALID;
+ nc_vars->flag = 0;
+ nc_vars->nc_configs = ni.head;
+ mutex_unlock(&nc_file_lock);
+ return ((void *)nc_vars);
+ }
+ mutex_unlock(&nc_file_lock);
+
+ mutex_lock(&ni_lock);
+ ni.ref--;
+ mutex_unlock(&ni_lock);
+
+ nc_error = NC_NONETCONFIG;
+ free(nc_vars);
+ return (NULL);
+}
+
+
+/*
+ * When first called, getnetconfig() returns a pointer to the first entry in
+ * the netconfig database, formatted as a struct netconfig. On each subsequent
+ * call, getnetconfig() returns a pointer to the next entry in the database.
+ * getnetconfig() can thus be used to search the entire netconfig file.
+ * getnetconfig() returns NULL at end of file.
+ */
+
+struct netconfig *
+getnetconfig(handlep)
+void *handlep;
+{
+ struct netconfig_vars *ncp = (struct netconfig_vars *)handlep;
+ char *stringp; /* tmp string pointer */
+ struct netconfig_list *list;
+ struct netconfig *np;
+ struct netconfig *result;
+
+ /*
+ * Verify that handle is valid
+ */
+ mutex_lock(&nc_file_lock);
+ if (ncp == NULL || nc_file == NULL) {
+ nc_error = NC_NOTINIT;
+ mutex_unlock(&nc_file_lock);
+ return (NULL);
+ }
+ mutex_unlock(&nc_file_lock);
+
+ switch (ncp->valid) {
+ case NC_VALID:
+ /*
+ * If entry has already been read into the list,
+ * we return the entry in the linked list.
+ * If this is the first time call, check if there are any entries in
+ * linked list. If no entries, we need to read the netconfig db.
+ * If we have been here and the next entry is there, we just return
+ * it.
+ */
+ if (ncp->flag == 0) { /* first time */
+ ncp->flag = 1;
+ mutex_lock(&ni_lock);
+ ncp->nc_configs = ni.head;
+ mutex_unlock(&ni_lock);
+ if (ncp->nc_configs != NULL) /* entry already exist */
+ return(ncp->nc_configs->ncp);
+ }
+ else if (ncp->nc_configs != NULL && ncp->nc_configs->next != NULL) {
+ ncp->nc_configs = ncp->nc_configs->next;
+ return(ncp->nc_configs->ncp);
+ }
+
+ /*
+ * If we cannot find the entry in the list and is end of file,
+ * we give up.
+ */
+ mutex_lock(&ni_lock);
+ if (ni.eof == 1) {
+ mutex_unlock(&ni_lock);
+ return(NULL);
+ }
+ mutex_unlock(&ni_lock);
+
+ break;
+ default:
+ nc_error = NC_NOTINIT;
+ return (NULL);
+ }
+
+ stringp = (char *) malloc(MAXNETCONFIGLINE);
+ if (stringp == NULL)
+ return (NULL);
+
+#ifdef MEM_CHK
+ if (malloc_verify() == 0) {
+ fprintf(stderr, "memory heap corrupted in getnetconfig\n");
+ exit(1);
+ }
+#endif
+
+ /*
+ * Read a line from netconfig file.
+ */
+ mutex_lock(&nc_file_lock);
+ do {
+ if (fgets(stringp, MAXNETCONFIGLINE, nc_file) == NULL) {
+ free(stringp);
+ mutex_lock(&ni_lock);
+ ni.eof = 1;
+ mutex_unlock(&ni_lock);
+ mutex_unlock(&nc_file_lock);
+ return (NULL);
+ }
+ } while (*stringp == '#');
+ mutex_unlock(&nc_file_lock);
+
+ list = (struct netconfig_list *) malloc(sizeof (struct netconfig_list));
+ if (list == NULL) {
+ free(stringp);
+ return(NULL);
+ }
+ np = (struct netconfig *) malloc(sizeof (struct netconfig));
+ if (np == NULL) {
+ free(stringp);
+ free(list);
+ return(NULL);
+ }
+ list->ncp = np;
+ list->next = NULL;
+ list->ncp->nc_lookups = NULL;
+ list->linep = stringp;
+ if (parse_ncp(stringp, list->ncp) == -1) {
+ free(stringp);
+ free(np);
+ free(list);
+ return (NULL);
+ }
+ else {
+ /*
+ * If this is the first entry that's been read, it is the head of
+ * the list. If not, put the entry at the end of the list.
+ * Reposition the current pointer of the handle to the last entry
+ * in the list.
+ */
+ mutex_lock(&ni_lock);
+ if (ni.head == NULL) { /* first entry */
+ ni.head = ni.tail = list;
+ }
+ else {
+ ni.tail->next = list;
+ ni.tail = ni.tail->next;
+ }
+ ncp->nc_configs = ni.tail;
+ result = ni.tail->ncp;
+ mutex_unlock(&ni_lock);
+ return(result);
+ }
+}
+
+/*
+ * endnetconfig() may be called to "unbind" or "close" the netconfig database
+ * when processing is complete, releasing resources for reuse. endnetconfig()
+ * may not be called before setnetconfig(). endnetconfig() returns 0 on
+ * success and -1 on failure (for example, if setnetconfig() was not called
+ * previously).
+ */
+int
+endnetconfig(handlep)
+void *handlep;
+{
+ struct netconfig_vars *nc_handlep = (struct netconfig_vars *)handlep;
+
+ struct netconfig_list *q, *p;
+
+ /*
+ * Verify that handle is valid
+ */
+ if (nc_handlep == NULL || (nc_handlep->valid != NC_VALID &&
+ nc_handlep->valid != NC_STORAGE)) {
+ nc_error = NC_NOTINIT;
+ return (-1);
+ }
+
+ /*
+ * Return 0 if anyone still needs it.
+ */
+ nc_handlep->valid = NC_INVALID;
+ nc_handlep->flag = 0;
+ nc_handlep->nc_configs = NULL;
+ mutex_lock(&ni_lock);
+ if (--ni.ref > 0) {
+ mutex_unlock(&ni_lock);
+ free(nc_handlep);
+ return(0);
+ }
+
+ /*
+ * Noone needs these entries anymore, then frees them.
+ * Make sure all info in netconfig_info structure has been reinitialized.
+ */
+ q = ni.head;
+ ni.eof = ni.ref = 0;
+ ni.head = NULL;
+ ni.tail = NULL;
+ mutex_unlock(&ni_lock);
+
+ while (q != NULL) {
+ p = q->next;
+ if (q->ncp->nc_lookups != NULL) free(q->ncp->nc_lookups);
+ free(q->ncp);
+ free(q->linep);
+ free(q);
+ q = p;
+ }
+ free(nc_handlep);
+
+ mutex_lock(&nc_file_lock);
+ fclose(nc_file);
+ nc_file = NULL;
+ mutex_unlock(&nc_file_lock);
+
+ return (0);
+}
+
+/*
+ * getnetconfigent(netid) returns a pointer to the struct netconfig structure
+ * corresponding to netid. It returns NULL if netid is invalid (that is, does
+ * not name an entry in the netconfig database). It returns NULL and sets
+ * errno in case of failure (for example, if the netconfig database cannot be
+ * opened).
+ */
+
+struct netconfig *
+getnetconfigent(netid)
+ const char *netid;
+{
+ FILE *file; /* NETCONFIG db's file pointer */
+ char *linep; /* holds current netconfig line */
+ char *stringp; /* temporary string pointer */
+ struct netconfig *ncp = NULL; /* returned value */
+ struct netconfig_list *list; /* pointer to cache list */
+
+ nc_error = NC_NOTFOUND; /* default error. */
+ if (netid == NULL || strlen(netid) == 0) {
+ return (NULL);
+ }
+
+ /*
+ * Look up table if the entries have already been read and parsed in
+ * getnetconfig(), then copy this entry into a buffer and return it.
+ * If we cannot find the entry in the current list and there are more
+ * entries in the netconfig db that has not been read, we then read the
+ * db and try find the match netid.
+ * If all the netconfig db has been read and placed into the list and
+ * there is no match for the netid, return NULL.
+ */
+ mutex_lock(&ni_lock);
+ if (ni.head != NULL) {
+ for (list = ni.head; list; list = list->next) {
+ if (strcmp(list->ncp->nc_netid, netid) == 0) {
+ mutex_unlock(&ni_lock);
+ return(dup_ncp(list->ncp));
+ }
+ }
+ if (ni.eof == 1) { /* that's all the entries */
+ mutex_unlock(&ni_lock);
+ return(NULL);
+ }
+ }
+ mutex_unlock(&ni_lock);
+
+
+ if ((file = fopen(NETCONFIG, "r")) == NULL) {
+ nc_error = NC_NONETCONFIG;
+ return (NULL);
+ }
+
+ if ((linep = malloc(MAXNETCONFIGLINE)) == NULL) {
+ fclose(file);
+ nc_error = NC_NOMEM;
+ return (NULL);
+ }
+ do {
+ ptrdiff_t len;
+ char *tmpp; /* tmp string pointer */
+
+ do {
+ if ((stringp = fgets(linep, MAXNETCONFIGLINE, file)) == NULL) {
+ break;
+ }
+ } while (*stringp == '#');
+ if (stringp == NULL) { /* eof */
+ break;
+ }
+ if ((tmpp = strpbrk(stringp, "\t ")) == NULL) { /* can't parse file */
+ nc_error = NC_BADFILE;
+ break;
+ }
+ if (strlen(netid) == (size_t) (len = tmpp - stringp) && /* a match */
+ strncmp(stringp, netid, (size_t)len) == 0) {
+ if ((ncp = (struct netconfig *)
+ malloc(sizeof (struct netconfig))) == NULL) {
+ break;
+ }
+ ncp->nc_lookups = NULL;
+ if (parse_ncp(linep, ncp) == -1) {
+ free(ncp);
+ ncp = NULL;
+ }
+ break;
+ }
+ } while (stringp != NULL);
+ if (ncp == NULL) {
+ free(linep);
+ }
+ fclose(file);
+ return(ncp);
+}
+
+/*
+ * freenetconfigent(netconfigp) frees the netconfig structure pointed to by
+ * netconfigp (previously returned by getnetconfigent()).
+ */
+
+void
+freenetconfigent(netconfigp)
+ struct netconfig *netconfigp;
+{
+ if (netconfigp != NULL) {
+ free(netconfigp->nc_netid); /* holds all netconfigp's strings */
+ if (netconfigp->nc_lookups != NULL)
+ free(netconfigp->nc_lookups);
+ free(netconfigp);
+ }
+ return;
+}
+
+/*
+ * Parse line and stuff it in a struct netconfig
+ * Typical line might look like:
+ * udp tpi_cots vb inet udp /dev/udp /usr/lib/ip.so,/usr/local/ip.so
+ *
+ * We return -1 if any of the tokens don't parse, or malloc fails.
+ *
+ * Note that we modify stringp (putting NULLs after tokens) and
+ * we set the ncp's string field pointers to point to these tokens within
+ * stringp.
+ */
+
+static int
+parse_ncp(stringp, ncp)
+char *stringp; /* string to parse */
+struct netconfig *ncp; /* where to put results */
+{
+ char *tokenp; /* for processing tokens */
+ char *lasts;
+ char **nc_lookups;
+
+ nc_error = NC_BADFILE; /* nearly anything that breaks is for this reason */
+ stringp[strlen(stringp)-1] = '\0'; /* get rid of newline */
+ /* netid */
+ if ((ncp->nc_netid = strtok_r(stringp, "\t ", &lasts)) == NULL) {
+ return (-1);
+ }
+
+ /* semantics */
+ if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
+ return (-1);
+ }
+ if (strcmp(tokenp, NC_TPI_COTS_ORD_S) == 0)
+ ncp->nc_semantics = NC_TPI_COTS_ORD;
+ else if (strcmp(tokenp, NC_TPI_COTS_S) == 0)
+ ncp->nc_semantics = NC_TPI_COTS;
+ else if (strcmp(tokenp, NC_TPI_CLTS_S) == 0)
+ ncp->nc_semantics = NC_TPI_CLTS;
+ else if (strcmp(tokenp, NC_TPI_RAW_S) == 0)
+ ncp->nc_semantics = NC_TPI_RAW;
+ else
+ return (-1);
+
+ /* flags */
+ if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
+ return (-1);
+ }
+ for (ncp->nc_flag = NC_NOFLAG; *tokenp != '\0';
+ tokenp++) {
+ switch (*tokenp) {
+ case NC_NOFLAG_C:
+ break;
+ case NC_VISIBLE_C:
+ ncp->nc_flag |= NC_VISIBLE;
+ break;
+ case NC_BROADCAST_C:
+ ncp->nc_flag |= NC_BROADCAST;
+ break;
+ default:
+ return (-1);
+ }
+ }
+ /* protocol family */
+ if ((ncp->nc_protofmly = strtok_r(NULL, "\t ", &lasts)) == NULL) {
+ return (-1);
+ }
+ /* protocol name */
+ if ((ncp->nc_proto = strtok_r(NULL, "\t ", &lasts)) == NULL) {
+ return (-1);
+ }
+ /* network device */
+ if ((ncp->nc_device = strtok_r(NULL, "\t ", &lasts)) == NULL) {
+ return (-1);
+ }
+ if ((tokenp = strtok_r(NULL, "\t ", &lasts)) == NULL) {
+ return (-1);
+ }
+ if (strcmp(tokenp, NC_NOLOOKUP) == 0) {
+ ncp->nc_nlookups = 0;
+ ncp->nc_lookups = NULL;
+ } else {
+ char *cp; /* tmp string */
+
+ if (ncp->nc_lookups != NULL) /* from last visit */
+ free(ncp->nc_lookups);
+ ncp->nc_lookups = NULL;
+ ncp->nc_nlookups = 0;
+ while ((cp = tokenp) != NULL) {
+ if ((nc_lookups = realloc(ncp->nc_lookups,
+ (ncp->nc_nlookups + 1) * sizeof *ncp->nc_lookups)) == NULL) {
+ free(ncp->nc_lookups);
+ ncp->nc_lookups = NULL;
+ return (-1);
+ }
+ tokenp = _get_next_token(cp, ',');
+ ncp->nc_lookups = nc_lookups;
+ ncp->nc_lookups[ncp->nc_nlookups++] = cp;
+ }
+ }
+ return (0);
+}
+
+
+/*
+ * Returns a string describing the reason for failure.
+ */
+char *
+nc_sperror()
+{
+ const char *message;
+
+ switch(nc_error) {
+ case NC_NONETCONFIG:
+ message = _nc_errors[0];
+ break;
+ case NC_NOMEM:
+ message = _nc_errors[1];
+ break;
+ case NC_NOTINIT:
+ message = _nc_errors[2];
+ break;
+ case NC_BADFILE:
+ message = _nc_errors[3];
+ break;
+ case NC_NOTFOUND:
+ message = _nc_errors[4];
+ break;
+ default:
+ message = "Unknown network selection error";
+ }
+ /* LINTED const castaway */
+ return ((char *)message);
+}
+
+/*
+ * Prints a message onto standard error describing the reason for failure.
+ */
+void
+nc_perror(s)
+ const char *s;
+{
+ fprintf(stderr, "%s: %s\n", s, nc_sperror());
+}
+
+/*
+ * Duplicates the matched netconfig buffer.
+ */
+static struct netconfig *
+dup_ncp(ncp)
+struct netconfig *ncp;
+{
+ struct netconfig *p;
+ char *tmp;
+ u_int i;
+
+ if ((tmp=malloc(MAXNETCONFIGLINE)) == NULL)
+ return(NULL);
+ if ((p=(struct netconfig *)malloc(sizeof(struct netconfig))) == NULL) {
+ free(tmp);
+ return(NULL);
+ }
+ /*
+ * First we dup all the data from matched netconfig buffer. Then we
+ * adjust some of the member pointer to a pre-allocated buffer where
+ * contains part of the data.
+ * To follow the convention used in parse_ncp(), we store all the
+ * necessary information in the pre-allocated buffer and let each
+ * of the netconfig char pointer member point to the right address
+ * in the buffer.
+ */
+ *p = *ncp;
+ p->nc_netid = (char *)strcpy(tmp,ncp->nc_netid);
+ tmp = strchr(tmp, '\0') + 1;
+ p->nc_protofmly = (char *)strcpy(tmp,ncp->nc_protofmly);
+ tmp = strchr(tmp, '\0') + 1;
+ p->nc_proto = (char *)strcpy(tmp,ncp->nc_proto);
+ tmp = strchr(tmp, '\0') + 1;
+ p->nc_device = (char *)strcpy(tmp,ncp->nc_device);
+ p->nc_lookups = (char **)malloc((size_t)(p->nc_nlookups+1) * sizeof(char *));
+ if (p->nc_lookups == NULL) {
+ free(p->nc_netid);
+ free(p);
+ return(NULL);
+ }
+ for (i=0; i < p->nc_nlookups; i++) {
+ tmp = strchr(tmp, '\0') + 1;
+ p->nc_lookups[i] = (char *)strcpy(tmp,ncp->nc_lookups[i]);
+ }
+ return(p);
+}
diff --git a/lib/libc/rpc/getnetpath.3 b/lib/libc/rpc/getnetpath.3
new file mode 100644
index 0000000..5dfe68a
--- /dev/null
+++ b/lib/libc/rpc/getnetpath.3
@@ -0,0 +1,170 @@
+.\" @(#)getnetpath.3n 1.26 93/05/07 SMI; from SVr4
+.\" $NetBSD: getnetpath.3,v 1.1 2000/06/02 23:11:11 fvdl Exp $
+.\" $FreeBSD$
+.\" Copyright 1989 AT&T
+.Dd April 22, 2000
+.Dt GETNETPATH 3
+.Os
+.Sh NAME
+.Nm getnetpath ,
+.Nm setnetpath ,
+.Nm endnetpath
+.Nd get
+.Pa /etc/netconfig
+entry corresponding to
+.Ev NETPATH
+component
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In netconfig.h
+.Ft "struct netconfig *"
+.Fn getnetpath "void *handlep"
+.Ft "void *"
+.Fn setnetpath "void"
+.Ft int
+.Fn endnetpath "void *handlep"
+.Sh DESCRIPTION
+The routines described in this page provide the application access to the system
+network configuration database,
+.Pa /etc/netconfig ,
+as it is
+.Dq filtered
+by the
+.Ev NETPATH
+environment variable (see
+.Xr environ 7 ) .
+See
+.Xr getnetconfig 3
+for other routines that also access the
+network configuration database directly.
+The
+.Ev NETPATH
+variable is a list of colon-separated network identifiers.
+.Pp
+The
+.Fn getnetpath
+function
+returns a pointer to the
+netconfig database entry corresponding to the first valid
+.Ev NETPATH
+component.
+The netconfig entry is formatted as a
+.Ft "struct netconfig" .
+On each subsequent call,
+.Fn getnetpath
+returns a pointer to the netconfig entry that corresponds to the next
+valid
+.Ev NETPATH
+component.
+The
+.Fn getnetpath
+function
+can thus be used to search the netconfig database for all networks
+included in the
+.Ev NETPATH
+variable.
+When
+.Ev NETPATH
+has been exhausted,
+.Fn getnetpath
+returns
+.Dv NULL .
+.Pp
+A call to
+.Fn setnetpath
+.Dq binds
+to or
+.Dq rewinds
+.Ev NETPATH .
+The
+.Fn setnetpath
+function
+must be called before the first call to
+.Fn getnetpath
+and may be called at any other time.
+It returns a handle that is used by
+.Fn getnetpath .
+.Pp
+The
+.Fn getnetpath
+function
+silently ignores invalid
+.Ev NETPATH
+components.
+A
+.Ev NETPATH
+component is invalid if there is no corresponding
+entry in the netconfig database.
+.Pp
+If the
+.Ev NETPATH
+variable is unset,
+.Fn getnetpath
+behaves as if
+.Ev NETPATH
+were set to the sequence of
+.Dq default
+or
+.Dq visible
+networks in the netconfig database, in the
+order in which they are listed.
+.\"This proviso holds also for this
+.\"whole manpage.
+.Pp
+The
+.Fn endnetpath
+function
+may be called to
+.Dq unbind
+from
+.Ev NETPATH
+when processing is complete, releasing resources for reuse.
+Programmers should be aware, however, that
+.Fn endnetpath
+frees all memory allocated by
+.Fn getnetpath
+for the struct netconfig data structure.
+.Sh RETURN VALUES
+The
+.Fn setnetpath
+function
+returns a handle that is used by
+.Fn getnetpath .
+In case of an error,
+.Fn setnetpath
+returns
+.Dv NULL .
+.Pp
+The
+.Fn endnetpath
+function
+returns 0 on success and \-1 on failure
+(for example, if
+.Fn setnetpath
+was not called previously).
+The
+.Fn nc_perror
+or
+.Fn nc_sperror
+function
+can be used to print out the reason for failure.
+See
+.Xr getnetconfig 3 .
+.Pp
+When first called,
+.Fn getnetpath
+returns a pointer to the netconfig database entry corresponding to the first
+valid
+.Ev NETPATH
+component.
+When
+.Ev NETPATH
+has been exhausted,
+.Fn getnetpath
+returns
+.Dv NULL .
+.Sh SEE ALSO
+.Xr getnetconfig 3 ,
+.Xr netconfig 5 ,
+.Xr environ 7
diff --git a/lib/libc/rpc/getnetpath.c b/lib/libc/rpc/getnetpath.c
new file mode 100644
index 0000000..d1ea554
--- /dev/null
+++ b/lib/libc/rpc/getnetpath.c
@@ -0,0 +1,276 @@
+/* $NetBSD: getnetpath.c,v 1.3 2000/07/06 03:10:34 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getnetpath.c 1.11 91/12/19 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Copyright (c) 1989 by Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <stdio.h>
+#include <errno.h>
+#include <netconfig.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+/*
+ * internal structure to keep track of a netpath "session"
+ */
+struct netpath_chain {
+ struct netconfig *ncp; /* an nconf entry */
+ struct netpath_chain *nchain_next; /* next nconf entry allocated */
+};
+
+
+struct netpath_vars {
+ int valid; /* token that indicates a valid netpath_vars */
+ void *nc_handlep; /* handle for current netconfig "session" */
+ char *netpath; /* pointer to current view-point in NETPATH */
+ char *netpath_start; /* pointer to start of our copy of NETPATH */
+ struct netpath_chain *ncp_list; /* list of nconfs allocated this session*/
+};
+
+#define NP_VALID 0xf00d
+#define NP_INVALID 0
+
+char *_get_next_token(char *, int);
+
+
+/*
+ * A call to setnetpath() establishes a NETPATH "session". setnetpath()
+ * must be called before the first call to getnetpath(). A "handle" is
+ * returned to distinguish the session; this handle should be passed
+ * subsequently to getnetpath(). (Handles are used to allow for nested calls
+ * to setnetpath()).
+ * If setnetpath() is unable to establish a session (due to lack of memory
+ * resources, or the absence of the /etc/netconfig file), a NULL pointer is
+ * returned.
+ */
+
+void *
+setnetpath()
+{
+
+ struct netpath_vars *np_sessionp; /* this session's variables */
+ char *npp; /* NETPATH env variable */
+
+#ifdef MEM_CHK
+ malloc_debug(1);
+#endif
+
+ if ((np_sessionp =
+ (struct netpath_vars *)malloc(sizeof (struct netpath_vars))) == NULL) {
+ return (NULL);
+ }
+ if ((np_sessionp->nc_handlep = setnetconfig()) == NULL) {
+ free(np_sessionp);
+ syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
+ return (NULL);
+ }
+ np_sessionp->valid = NP_VALID;
+ np_sessionp->ncp_list = NULL;
+ if ((npp = getenv(NETPATH)) == NULL) {
+ np_sessionp->netpath = NULL;
+ } else {
+ (void) endnetconfig(np_sessionp->nc_handlep);/* won't need nc session*/
+ np_sessionp->nc_handlep = NULL;
+ if ((np_sessionp->netpath = malloc(strlen(npp)+1)) == NULL)
+ goto failed;
+ else {
+ (void) strcpy(np_sessionp->netpath, npp);
+ }
+ }
+ np_sessionp->netpath_start = np_sessionp->netpath;
+ return ((void *)np_sessionp);
+
+failed:
+ free(np_sessionp);
+ return (NULL);
+}
+
+/*
+ * When first called, getnetpath() returns a pointer to the netconfig
+ * database entry corresponding to the first valid NETPATH component. The
+ * netconfig entry is formatted as a struct netconfig.
+ * On each subsequent call, getnetpath returns a pointer to the netconfig
+ * entry that corresponds to the next valid NETPATH component. getnetpath
+ * can thus be used to search the netconfig database for all networks
+ * included in the NETPATH variable.
+ * When NETPATH has been exhausted, getnetpath() returns NULL. It returns
+ * NULL and sets errno in case of an error (e.g., setnetpath was not called
+ * previously).
+ * getnetpath() silently ignores invalid NETPATH components. A NETPATH
+ * compnent is invalid if there is no corresponding entry in the netconfig
+ * database.
+ * If the NETPATH variable is unset, getnetpath() behaves as if NETPATH
+ * were set to the sequence of default or visible networks in the netconfig
+ * database, in the order in which they are listed.
+ */
+
+struct netconfig *
+getnetpath(handlep)
+ void *handlep;
+{
+ struct netpath_vars *np_sessionp = (struct netpath_vars *)handlep;
+ struct netconfig *ncp = NULL; /* temp. holds a netconfig session */
+ struct netpath_chain *chainp; /* holds chain of ncp's we alloc */
+ char *npp; /* holds current NETPATH */
+
+ if (np_sessionp == NULL || np_sessionp->valid != NP_VALID) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ if (np_sessionp->netpath_start == NULL) { /* NETPATH was not set */
+ do { /* select next visible network */
+ if (np_sessionp->nc_handlep == NULL) {
+ np_sessionp->nc_handlep = setnetconfig();
+ if (np_sessionp->nc_handlep == NULL)
+ syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
+ }
+ if ((ncp = getnetconfig(np_sessionp->nc_handlep)) == NULL) {
+ return(NULL);
+ }
+ } while ((ncp->nc_flag & NC_VISIBLE) == 0);
+ return (ncp);
+ }
+ /*
+ * Find first valid network ID in netpath.
+ */
+ while ((npp = np_sessionp->netpath) != NULL && strlen(npp) != 0) {
+ np_sessionp->netpath = _get_next_token(npp, ':');
+ /*
+ * npp is a network identifier.
+ */
+ if ((ncp = getnetconfigent(npp)) != NULL) {
+ chainp = (struct netpath_chain *) /* cobble alloc chain entry */
+ malloc(sizeof (struct netpath_chain));
+ chainp->ncp = ncp;
+ chainp->nchain_next = NULL;
+ if (np_sessionp->ncp_list == NULL) {
+ np_sessionp->ncp_list = chainp;
+ } else {
+ np_sessionp->ncp_list->nchain_next = chainp;
+ }
+ return (ncp);
+ }
+ /* couldn't find this token in the database; go to next one. */
+ }
+ return (NULL);
+}
+
+/*
+ * endnetpath() may be called to unbind NETPATH when processing is complete,
+ * releasing resources for reuse. It returns 0 on success and -1 on failure
+ * (e.g. if setnetpath() was not called previously.
+ */
+int
+endnetpath(handlep)
+ void *handlep;
+{
+ struct netpath_vars *np_sessionp = (struct netpath_vars *)handlep;
+ struct netpath_chain *chainp, *lastp;
+
+ if (np_sessionp == NULL || np_sessionp->valid != NP_VALID) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (np_sessionp->nc_handlep != NULL)
+ endnetconfig(np_sessionp->nc_handlep);
+ if (np_sessionp->netpath_start != NULL)
+ free(np_sessionp->netpath_start);
+ for (chainp = np_sessionp->ncp_list; chainp != NULL;
+ lastp=chainp, chainp=chainp->nchain_next, free(lastp)) {
+ freenetconfigent(chainp->ncp);
+ }
+ free(np_sessionp);
+#ifdef MEM_CHK
+ if (malloc_verify() == 0) {
+ fprintf(stderr, "memory heap corrupted in endnetpath\n");
+ exit(1);
+ }
+#endif
+ return (0);
+}
+
+
+
+/*
+ * Returns pointer to the rest-of-the-string after the current token.
+ * The token itself starts at arg, and we null terminate it. We return NULL
+ * if either the arg is empty, or if this is the last token.
+ */
+
+char *
+_get_next_token(npp, token)
+char *npp; /* string */
+int token; /* char to parse string for */
+{
+ char *cp; /* char pointer */
+ char *np; /* netpath pointer */
+ char *ep; /* escape pointer */
+
+ if ((cp = strchr(npp, token)) == NULL) {
+ return (NULL);
+ }
+ /*
+ * did find a token, but it might be escaped.
+ */
+ if ((cp > npp) && (cp[-1] == '\\')) {
+ /* if slash was also escaped, carry on, otherwise find next token */
+ if ((cp > npp + 1) && (cp[-2] != '\\')) {
+ /* shift r-o-s onto the escaped token */
+ strcpy(&cp[-1], cp); /* XXX: overlapping string copy */
+ /*
+ * Do a recursive call.
+ * We don't know how many escaped tokens there might be.
+ */
+ return (_get_next_token(cp, token));
+ }
+ }
+
+ *cp++ = '\0'; /* null-terminate token */
+ /* get rid of any backslash escapes */
+ ep = npp;
+ while ((np = strchr(ep, '\\')) != 0) {
+ if (np[1] == '\\')
+ np++;
+ strcpy(np, (ep = &np[1])); /* XXX: overlapping string copy */
+ }
+ return (cp); /* return ptr to r-o-s */
+}
diff --git a/lib/libc/rpc/getpublickey.c b/lib/libc/rpc/getpublickey.c
new file mode 100644
index 0000000..3c95338
--- /dev/null
+++ b/lib/libc/rpc/getpublickey.c
@@ -0,0 +1,179 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)publickey.c 1.10 91/03/11 Copyr 1986 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * publickey.c
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ */
+
+/*
+ * Public key lookup routines
+ */
+#include "namespace.h"
+#include <stdio.h>
+#include <pwd.h>
+#include <rpc/rpc.h>
+#include <rpc/key_prot.h>
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#include <string.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+
+#define PKFILE "/etc/publickey"
+
+/*
+ * Hack to let ypserv/rpc.nisd use AUTH_DES.
+ */
+int (*__getpublickey_LOCAL)() = 0;
+
+/*
+ * Get somebody's public key
+ */
+static int
+__getpublickey_real(netname, publickey)
+ const char *netname;
+ char *publickey;
+{
+ char lookup[3 * HEXKEYBYTES];
+ char *p;
+
+ if (publickey == NULL)
+ return (0);
+ if (!getpublicandprivatekey(netname, lookup))
+ return (0);
+ p = strchr(lookup, ':');
+ if (p == NULL) {
+ return (0);
+ }
+ *p = '\0';
+ (void) strncpy(publickey, lookup, HEXKEYBYTES);
+ publickey[HEXKEYBYTES] = '\0';
+ return (1);
+}
+
+/*
+ * reads the file /etc/publickey looking for a + to optionally go to the
+ * yellow pages
+ */
+
+int
+getpublicandprivatekey(key, ret)
+ const char *key;
+ char *ret;
+{
+ char buf[1024]; /* big enough */
+ char *res;
+ FILE *fd;
+ char *mkey;
+ char *mval;
+
+ fd = fopen(PKFILE, "r");
+ if (fd == NULL)
+ return (0);
+ for (;;) {
+ res = fgets(buf, sizeof(buf), fd);
+ if (res == NULL) {
+ fclose(fd);
+ return (0);
+ }
+ if (res[0] == '#')
+ continue;
+ else if (res[0] == '+') {
+#ifdef YP
+ char *PKMAP = "publickey.byname";
+ char *lookup;
+ char *domain;
+ int err;
+ int len;
+
+ err = yp_get_default_domain(&domain);
+ if (err) {
+ continue;
+ }
+ lookup = NULL;
+ err = yp_match(domain, PKMAP, key, strlen(key), &lookup, &len);
+ if (err) {
+#ifdef DEBUG
+ fprintf(stderr, "match failed error %d\n", err);
+#endif
+ continue;
+ }
+ lookup[len] = 0;
+ strcpy(ret, lookup);
+ fclose(fd);
+ free(lookup);
+ return (2);
+#else /* YP */
+#ifdef DEBUG
+ fprintf(stderr,
+"Bad record in %s '+' -- NIS not supported in this library copy\n", PKFILE);
+#endif /* DEBUG */
+ continue;
+#endif /* YP */
+ } else {
+ mkey = strsep(&res, "\t ");
+ if (mkey == NULL) {
+ fprintf(stderr,
+ "Bad record in %s -- %s", PKFILE, buf);
+ continue;
+ }
+ do {
+ mval = strsep(&res, " \t#\n");
+ } while (mval != NULL && !*mval);
+ if (mval == NULL) {
+ fprintf(stderr,
+ "Bad record in %s val problem - %s", PKFILE, buf);
+ continue;
+ }
+ if (strcmp(mkey, key) == 0) {
+ strcpy(ret, mval);
+ fclose(fd);
+ return (1);
+ }
+ }
+ }
+}
+
+int getpublickey(netname, publickey)
+ const char *netname;
+ char *publickey;
+{
+ if (__getpublickey_LOCAL != NULL)
+ return(__getpublickey_LOCAL(netname, publickey));
+ else
+ return(__getpublickey_real(netname, publickey));
+}
diff --git a/lib/libc/rpc/getrpcent.3 b/lib/libc/rpc/getrpcent.3
new file mode 100644
index 0000000..1a999eb
--- /dev/null
+++ b/lib/libc/rpc/getrpcent.3
@@ -0,0 +1,109 @@
+.\" @(#)getrpcent.3n 2.2 88/08/02 4.0 RPCSRC; from 1.11 88/03/14 SMI
+.\" $NetBSD: getrpcent.3,v 1.6 1998/02/05 18:49:06 perry Exp $
+.\" $FreeBSD$
+.\"
+.Dd December 14, 1987
+.Dt GETRPCENT 3
+.Os
+.Sh NAME
+.Nm getrpcent ,
+.Nm getrpcbyname ,
+.Nm getrpcbynumber ,
+.Nm endrpcent ,
+.Nm setrpcent
+.Nd get RPC entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In rpc/rpc.h
+.Ft struct rpcent *
+.Fn getrpcent void
+.Ft struct rpcent *
+.Fn getrpcbyname "char *name"
+.Ft struct rpcent *
+.Fn getrpcbynumber "int number"
+.Ft void
+.Fn setrpcent "int stayopen"
+.Ft void
+.Fn endrpcent void
+.Sh DESCRIPTION
+The
+.Fn getrpcent ,
+.Fn getrpcbyname ,
+and
+.Fn getrpcbynumber
+functions
+each return a pointer to an object with the
+following structure
+containing the broken-out
+fields of a line in the rpc program number data base,
+.Pa /etc/rpc :
+.Bd -literal
+struct rpcent {
+ char *r_name; /* name of server for this rpc program */
+ char **r_aliases; /* alias list */
+ long r_number; /* rpc program number */
+};
+.Ed
+.Pp
+The members of this structure are:
+.Bl -tag -width r_aliases -offset indent
+.It Va r_name
+The name of the server for this rpc program.
+.It Va r_aliases
+A zero terminated list of alternate names for the rpc program.
+.It Va r_number
+The rpc program number for this service.
+.El
+.Pp
+The
+.Fn getrpcent
+function
+reads the next line of the file, opening the file if necessary.
+.Pp
+The
+.Fn setrpcent
+function
+opens and rewinds the file.
+If the
+.Fa stayopen
+flag is non-zero,
+the net data base will not be closed after each call to
+.Fn getrpcent
+(either directly, or indirectly through one of
+the other
+.Dq getrpc
+calls).
+.Pp
+The
+.Fn endrpcent
+function
+closes the file.
+.Pp
+The
+.Fn getrpcbyname
+and
+.Fn getrpcbynumber
+functions
+sequentially search from the beginning
+of the file until a matching rpc program name or
+program number is found, or until end-of-file is encountered.
+.Sh FILES
+.Bl -tag -width /etc/rpc -compact
+.It Pa /etc/rpc
+.El
+.Sh DIAGNOSTICS
+A
+.Dv NULL
+pointer is returned on
+.Dv EOF
+or error.
+.Sh SEE ALSO
+.Xr rpc 5 ,
+.Xr rpcinfo 8 ,
+.Xr ypserv 8
+.Sh BUGS
+All information
+is contained in a static area
+so it must be copied if it is
+to be saved.
diff --git a/lib/libc/rpc/getrpcent.c b/lib/libc/rpc/getrpcent.c
new file mode 100644
index 0000000..1f198fa
--- /dev/null
+++ b/lib/libc/rpc/getrpcent.c
@@ -0,0 +1,1048 @@
+/* $NetBSD: getrpcent.c,v 1.17 2000/01/22 22:19:17 mycroft Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid = "@(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Copyright (c) 1984 by Sun Microsystems, Inc.
+ */
+
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <arpa/inet.h>
+#include <assert.h>
+#include <errno.h>
+#include <nsswitch.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <rpc/rpc.h>
+#ifdef YP
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <unistd.h>
+#include "namespace.h"
+#include "reentrant.h"
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "nss_tls.h"
+#ifdef NS_CACHING
+#include "nscache.h"
+#endif
+
+#define RPCDB "/etc/rpc"
+
+/* nsswitch declarations */
+enum constants
+{
+ SETRPCENT = 1,
+ ENDRPCENT = 2,
+ RPCENT_STORAGE_INITIAL = 1 << 10, /* 1 KByte */
+ RPCENT_STORAGE_MAX = 1 << 20, /* 1 MByte */
+};
+
+static const ns_src defaultsrc[] = {
+ { NSSRC_FILES, NS_SUCCESS },
+#ifdef YP
+ { NSSRC_NIS, NS_SUCCESS },
+#endif
+ { NULL, 0 }
+};
+
+/* files backend declarations */
+struct files_state {
+ FILE *fp;
+ int stayopen;
+};
+
+static int files_rpcent(void *, void *, va_list);
+static int files_setrpcent(void *, void *, va_list);
+
+static void files_endstate(void *);
+NSS_TLS_HANDLING(files);
+
+/* nis backend declarations */
+#ifdef YP
+struct nis_state {
+ char domain[MAXHOSTNAMELEN];
+ char *current;
+ int currentlen;
+ int stepping;
+ int no_name_map;
+};
+
+static int nis_rpcent(void *, void *, va_list);
+static int nis_setrpcent(void *, void *, va_list);
+
+static void nis_endstate(void *);
+NSS_TLS_HANDLING(nis);
+#endif
+
+/* get** wrappers for get**_r functions declarations */
+struct rpcent_state {
+ struct rpcent rpc;
+ char *buffer;
+ size_t bufsize;
+};
+static void rpcent_endstate(void *);
+NSS_TLS_HANDLING(rpcent);
+
+union key {
+ const char *name;
+ int number;
+};
+
+static int wrap_getrpcbyname_r(union key, struct rpcent *, char *,
+ size_t, struct rpcent **);
+static int wrap_getrpcbynumber_r(union key, struct rpcent *, char *,
+ size_t, struct rpcent **);
+static int wrap_getrpcent_r(union key, struct rpcent *, char *,
+ size_t, struct rpcent **);
+static struct rpcent *getrpc(int (*fn)(union key, struct rpcent *, char *,
+ size_t, struct rpcent **), union key);
+
+#ifdef NS_CACHING
+static int rpc_id_func(char *, size_t *, va_list, void *);
+static int rpc_marshal_func(char *, size_t *, void *, va_list, void *);
+static int rpc_unmarshal_func(char *, size_t, void *, va_list, void *);
+#endif
+
+static int
+rpcent_unpack(char *p, struct rpcent *rpc, char **r_aliases,
+ size_t aliases_size, int *errnop)
+{
+ char *cp, **q;
+
+ assert(p != NULL);
+
+ if (*p == '#')
+ return (-1);
+ cp = strpbrk(p, "#\n");
+ if (cp == NULL)
+ return (-1);
+ *cp = '\0';
+ cp = strpbrk(p, " \t");
+ if (cp == NULL)
+ return (-1);
+ *cp++ = '\0';
+ /* THIS STUFF IS INTERNET SPECIFIC */
+ rpc->r_name = p;
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ rpc->r_number = atoi(cp);
+ q = rpc->r_aliases = r_aliases;
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ while (cp && *cp) {
+ if (*cp == ' ' || *cp == '\t') {
+ cp++;
+ continue;
+ }
+ if (q < &(r_aliases[aliases_size - 1]))
+ *q++ = cp;
+ else {
+ *errnop = ERANGE;
+ return -1;
+ }
+
+ cp = strpbrk(cp, " \t");
+ if (cp != NULL)
+ *cp++ = '\0';
+ }
+ *q = NULL;
+ return 0;
+}
+
+/* files backend implementation */
+static void
+files_endstate(void *p)
+{
+ FILE * f;
+
+ if (p == NULL)
+ return;
+
+ f = ((struct files_state *)p)->fp;
+ if (f != NULL)
+ fclose(f);
+
+ free(p);
+}
+
+static int
+files_rpcent(void *retval, void *mdata, va_list ap)
+{
+ char *name;
+ int number;
+ struct rpcent *rpc;
+ char *buffer;
+ size_t bufsize;
+ int *errnop;
+
+ char *line;
+ size_t linesize;
+ char **aliases;
+ int aliases_size;
+ char **rp;
+
+ struct files_state *st;
+ int rv;
+ int stayopen;
+ enum nss_lookup_type how;
+
+ how = (enum nss_lookup_type)mdata;
+ switch (how)
+ {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ number = va_arg(ap, int);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ return (NS_NOTFOUND);
+ }
+
+ rpc = va_arg(ap, struct rpcent *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+
+ *errnop = files_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+
+ if (st->fp == NULL && (st->fp = fopen(RPCDB, "r")) == NULL) {
+ *errnop = errno;
+ return (NS_UNAVAIL);
+ }
+
+ if (how == nss_lt_all)
+ stayopen = 1;
+ else {
+ rewind(st->fp);
+ stayopen = st->stayopen;
+ }
+
+ do {
+ if ((line = fgetln(st->fp, &linesize)) == NULL) {
+ *errnop = errno;
+ rv = NS_RETURN;
+ break;
+ }
+
+ if (bufsize <= linesize + _ALIGNBYTES + sizeof(char *)) {
+ *errnop = ERANGE;
+ rv = NS_RETURN;
+ break;
+ }
+
+ aliases = (char **)_ALIGN(&buffer[linesize+1]);
+ aliases_size = (buffer + bufsize -
+ (char *)aliases)/sizeof(char *);
+ if (aliases_size < 1) {
+ *errnop = ERANGE;
+ rv = NS_RETURN;
+ break;
+ }
+
+ memcpy(buffer, line, linesize);
+ buffer[linesize] = '\0';
+
+ rv = rpcent_unpack(buffer, rpc, aliases, aliases_size, errnop);
+ if (rv != 0) {
+ if (*errnop == 0) {
+ rv = NS_NOTFOUND;
+ continue;
+ }
+ else {
+ rv = NS_RETURN;
+ break;
+ }
+ }
+
+ switch (how)
+ {
+ case nss_lt_name:
+ if (strcmp(rpc->r_name, name) == 0)
+ goto done;
+ for (rp = rpc->r_aliases; *rp != NULL; rp++) {
+ if (strcmp(*rp, name) == 0)
+ goto done;
+ }
+ rv = NS_NOTFOUND;
+ continue;
+done:
+ rv = NS_SUCCESS;
+ break;
+ case nss_lt_id:
+ rv = (rpc->r_number == number) ? NS_SUCCESS :
+ NS_NOTFOUND;
+ break;
+ case nss_lt_all:
+ rv = NS_SUCCESS;
+ break;
+ }
+
+ } while (!(rv & NS_TERMINATE));
+
+ if (!stayopen && st->fp!=NULL) {
+ fclose(st->fp);
+ st->fp = NULL;
+ }
+
+ if ((rv == NS_SUCCESS) && (retval != NULL))
+ *((struct rpcent **)retval) = rpc;
+
+ return (rv);
+}
+
+static int
+files_setrpcent(void *retval, void *mdata, va_list ap)
+{
+ struct files_state *st;
+ int rv;
+ int f;
+
+ rv = files_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+
+ switch ((enum constants)mdata)
+ {
+ case SETRPCENT:
+ f = va_arg(ap,int);
+ if (st->fp == NULL)
+ st->fp = fopen(RPCDB, "r");
+ else
+ rewind(st->fp);
+ st->stayopen |= f;
+ break;
+ case ENDRPCENT:
+ if (st->fp != NULL) {
+ fclose(st->fp);
+ st->fp = NULL;
+ }
+ st->stayopen = 0;
+ break;
+ default:
+ break;
+ }
+
+ return (NS_UNAVAIL);
+}
+
+/* nis backend implementation */
+#ifdef YP
+static void
+nis_endstate(void *p)
+{
+ if (p == NULL)
+ return;
+
+ free(((struct nis_state *)p)->current);
+ free(p);
+}
+
+static int
+nis_rpcent(void *retval, void *mdata, va_list ap)
+{
+ char *name;
+ int number;
+ struct rpcent *rpc;
+ char *buffer;
+ size_t bufsize;
+ int *errnop;
+
+ char **rp;
+ char **aliases;
+ int aliases_size;
+
+ char *lastkey;
+ char *resultbuf;
+ int resultbuflen;
+ char buf[YPMAXRECORD + 2];
+
+ struct nis_state *st;
+ int rv;
+ enum nss_lookup_type how;
+ int no_name_active;
+
+ how = (enum nss_lookup_type)mdata;
+ switch (how)
+ {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ number = va_arg(ap, int);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ return (NS_NOTFOUND);
+ }
+
+ rpc = va_arg(ap, struct rpcent *);
+ buffer = va_arg(ap, char *);
+ bufsize = va_arg(ap, size_t);
+ errnop = va_arg(ap, int *);
+
+ *errnop = nis_getstate(&st);
+ if (*errnop != 0)
+ return (NS_UNAVAIL);
+
+ if (st->domain[0] == '\0') {
+ if (getdomainname(st->domain, sizeof(st->domain)) != 0) {
+ *errnop = errno;
+ return (NS_UNAVAIL);
+ }
+ }
+
+ no_name_active = 0;
+ do {
+ switch (how)
+ {
+ case nss_lt_name:
+ if (!st->no_name_map)
+ {
+ snprintf(buf, sizeof buf, "%s", name);
+ rv = yp_match(st->domain, "rpc.byname", buf,
+ strlen(buf), &resultbuf, &resultbuflen);
+
+ switch (rv) {
+ case 0:
+ break;
+ case YPERR_MAP:
+ st->stepping = 0;
+ no_name_active = 1;
+ how = nss_lt_all;
+
+ rv = NS_NOTFOUND;
+ continue;
+ default:
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ } else {
+ st->stepping = 0;
+ no_name_active = 1;
+ how = nss_lt_all;
+
+ rv = NS_NOTFOUND;
+ continue;
+ }
+ break;
+ case nss_lt_id:
+ snprintf(buf, sizeof buf, "%d", number);
+ if (yp_match(st->domain, "rpc.bynumber", buf,
+ strlen(buf), &resultbuf, &resultbuflen)) {
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ break;
+ case nss_lt_all:
+ if (!st->stepping) {
+ rv = yp_first(st->domain, "rpc.bynumber",
+ &st->current,
+ &st->currentlen, &resultbuf,
+ &resultbuflen);
+ if (rv) {
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ st->stepping = 1;
+ } else {
+ lastkey = st->current;
+ rv = yp_next(st->domain, "rpc.bynumber",
+ st->current,
+ st->currentlen, &st->current,
+ &st->currentlen,
+ &resultbuf, &resultbuflen);
+ free(lastkey);
+ if (rv) {
+ st->stepping = 0;
+ rv = NS_NOTFOUND;
+ goto fin;
+ }
+ }
+ break;
+ }
+
+ /* we need a room for additional \n symbol */
+ if (bufsize <= resultbuflen + 1 + _ALIGNBYTES +
+ sizeof(char *)) {
+ *errnop = ERANGE;
+ rv = NS_RETURN;
+ break;
+ }
+
+ aliases=(char **)_ALIGN(&buffer[resultbuflen+2]);
+ aliases_size = (buffer + bufsize - (char *)aliases) /
+ sizeof(char *);
+ if (aliases_size < 1) {
+ *errnop = ERANGE;
+ rv = NS_RETURN;
+ break;
+ }
+
+ /*
+ * rpcent_unpack expects lines terminated with \n -- make it happy
+ */
+ memcpy(buffer, resultbuf, resultbuflen);
+ buffer[resultbuflen] = '\n';
+ buffer[resultbuflen+1] = '\0';
+ free(resultbuf);
+
+ if (rpcent_unpack(buffer, rpc, aliases, aliases_size,
+ errnop) != 0) {
+ if (*errnop == 0)
+ rv = NS_NOTFOUND;
+ else
+ rv = NS_RETURN;
+ } else {
+ if ((how == nss_lt_all) && (no_name_active != 0)) {
+ if (strcmp(rpc->r_name, name) == 0)
+ goto done;
+ for (rp = rpc->r_aliases; *rp != NULL; rp++) {
+ if (strcmp(*rp, name) == 0)
+ goto done;
+ }
+ rv = NS_NOTFOUND;
+ continue;
+done:
+ rv = NS_SUCCESS;
+ } else
+ rv = NS_SUCCESS;
+ }
+
+ } while (!(rv & NS_TERMINATE) && (how == nss_lt_all));
+
+fin:
+ if ((rv == NS_SUCCESS) && (retval != NULL))
+ *((struct rpcent **)retval) = rpc;
+
+ return (rv);
+}
+
+static int
+nis_setrpcent(void *retval, void *mdata, va_list ap)
+{
+ struct nis_state *st;
+ int rv;
+
+ rv = nis_getstate(&st);
+ if (rv != 0)
+ return (NS_UNAVAIL);
+
+ switch ((enum constants)mdata)
+ {
+ case SETRPCENT:
+ case ENDRPCENT:
+ free(st->current);
+ st->current = NULL;
+ st->stepping = 0;
+ break;
+ default:
+ break;
+ }
+
+ return (NS_UNAVAIL);
+}
+#endif
+
+#ifdef NS_CACHING
+static int
+rpc_id_func(char *buffer, size_t *buffer_size, va_list ap, void *cache_mdata)
+{
+ char *name;
+ int rpc;
+
+ size_t desired_size, size;
+ enum nss_lookup_type lookup_type;
+ int res = NS_UNAVAIL;
+
+ lookup_type = (enum nss_lookup_type)cache_mdata;
+ switch (lookup_type) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+
+ size = strlen(name);
+ desired_size = sizeof(enum nss_lookup_type) + size + 1;
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), name, size + 1);
+
+ res = NS_SUCCESS;
+ break;
+ case nss_lt_id:
+ rpc = va_arg(ap, int);
+
+ desired_size = sizeof(enum nss_lookup_type) + sizeof(int);
+ if (desired_size > *buffer_size) {
+ res = NS_RETURN;
+ goto fin;
+ }
+
+ memcpy(buffer, &lookup_type, sizeof(enum nss_lookup_type));
+ memcpy(buffer + sizeof(enum nss_lookup_type), &rpc,
+ sizeof(int));
+
+ res = NS_SUCCESS;
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+fin:
+ *buffer_size = desired_size;
+ return (res);
+}
+
+static int
+rpc_marshal_func(char *buffer, size_t *buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ int num;
+ struct rpcent *rpc;
+ char *orig_buf;
+ size_t orig_buf_size;
+
+ struct rpcent new_rpc;
+ size_t desired_size, size, aliases_size;
+ char *p;
+ char **alias;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ num = va_arg(ap, int);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ rpc = va_arg(ap, struct rpcent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+
+ desired_size = _ALIGNBYTES + sizeof(struct rpcent) + sizeof(char *);
+ if (rpc->r_name != NULL)
+ desired_size += strlen(rpc->r_name) + 1;
+
+ if (rpc->r_aliases != NULL) {
+ aliases_size = 0;
+ for (alias = rpc->r_aliases; *alias; ++alias) {
+ desired_size += strlen(*alias) + 1;
+ ++aliases_size;
+ }
+
+ desired_size += _ALIGNBYTES + (aliases_size + 1) *
+ sizeof(char *);
+ }
+
+ if (*buffer_size < desired_size) {
+ /* this assignment is here for future use */
+ *buffer_size = desired_size;
+ return (NS_RETURN);
+ }
+
+ new_rpc = *rpc;
+
+ *buffer_size = desired_size;
+ memset(buffer, 0, desired_size);
+ p = buffer + sizeof(struct rpcent) + sizeof(char *);
+ memcpy(buffer + sizeof(struct rpcent), &p, sizeof(char *));
+ p = (char *)_ALIGN(p);
+
+ if (new_rpc.r_name != NULL) {
+ size = strlen(new_rpc.r_name);
+ memcpy(p, new_rpc.r_name, size);
+ new_rpc.r_name = p;
+ p += size + 1;
+ }
+
+ if (new_rpc.r_aliases != NULL) {
+ p = (char *)_ALIGN(p);
+ memcpy(p, new_rpc.r_aliases, sizeof(char *) * aliases_size);
+ new_rpc.r_aliases = (char **)p;
+ p += sizeof(char *) * (aliases_size + 1);
+
+ for (alias = new_rpc.r_aliases; *alias; ++alias) {
+ size = strlen(*alias);
+ memcpy(p, *alias, size);
+ *alias = p;
+ p += size + 1;
+ }
+ }
+
+ memcpy(buffer, &new_rpc, sizeof(struct rpcent));
+ return (NS_SUCCESS);
+}
+
+static int
+rpc_unmarshal_func(char *buffer, size_t buffer_size, void *retval, va_list ap,
+ void *cache_mdata)
+{
+ char *name;
+ int num;
+ struct rpcent *rpc;
+ char *orig_buf;
+ size_t orig_buf_size;
+ int *ret_errno;
+
+ char *p;
+ char **alias;
+
+ switch ((enum nss_lookup_type)cache_mdata) {
+ case nss_lt_name:
+ name = va_arg(ap, char *);
+ break;
+ case nss_lt_id:
+ num = va_arg(ap, int);
+ break;
+ case nss_lt_all:
+ break;
+ default:
+ /* should be unreachable */
+ return (NS_UNAVAIL);
+ }
+
+ rpc = va_arg(ap, struct rpcent *);
+ orig_buf = va_arg(ap, char *);
+ orig_buf_size = va_arg(ap, size_t);
+ ret_errno = va_arg(ap, int *);
+
+ if (orig_buf_size <
+ buffer_size - sizeof(struct rpcent) - sizeof(char *)) {
+ *ret_errno = ERANGE;
+ return (NS_RETURN);
+ }
+
+ memcpy(rpc, buffer, sizeof(struct rpcent));
+ memcpy(&p, buffer + sizeof(struct rpcent), sizeof(char *));
+
+ orig_buf = (char *)_ALIGN(orig_buf);
+ memcpy(orig_buf, buffer + sizeof(struct rpcent) + sizeof(char *) +
+ _ALIGN(p) - (size_t)p,
+ buffer_size - sizeof(struct rpcent) - sizeof(char *) -
+ _ALIGN(p) + (size_t)p);
+ p = (char *)_ALIGN(p);
+
+ NS_APPLY_OFFSET(rpc->r_name, orig_buf, p, char *);
+ if (rpc->r_aliases != NULL) {
+ NS_APPLY_OFFSET(rpc->r_aliases, orig_buf, p, char **);
+
+ for (alias = rpc->r_aliases ; *alias; ++alias)
+ NS_APPLY_OFFSET(*alias, orig_buf, p, char *);
+ }
+
+ if (retval != NULL)
+ *((struct rpcent **)retval) = rpc;
+
+ return (NS_SUCCESS);
+}
+
+NSS_MP_CACHE_HANDLING(rpc);
+#endif /* NS_CACHING */
+
+
+/* get**_r functions implementation */
+static int
+getrpcbyname_r(const char *name, struct rpcent *rpc, char *buffer,
+ size_t bufsize, struct rpcent **result)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ rpc, (void *)nss_lt_name,
+ rpc_id_func, rpc_marshal_func, rpc_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_rpcent, (void *)nss_lt_name },
+#ifdef YP
+ { NSSRC_NIS, nis_rpcent, (void *)nss_lt_name },
+#endif
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcbyname_r", defaultsrc,
+ name, rpc, buffer, bufsize, &ret_errno);
+
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+static int
+getrpcbynumber_r(int number, struct rpcent *rpc, char *buffer,
+ size_t bufsize, struct rpcent **result)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info =
+ NS_COMMON_CACHE_INFO_INITIALIZER(
+ rpc, (void *)nss_lt_id,
+ rpc_id_func, rpc_marshal_func, rpc_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_rpcent, (void *)nss_lt_id },
+#ifdef YP
+ { NSSRC_NIS, nis_rpcent, (void *)nss_lt_id },
+#endif
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcbynumber_r", defaultsrc,
+ number, rpc, buffer, bufsize, &ret_errno);
+
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+static int
+getrpcent_r(struct rpcent *rpc, char *buffer, size_t bufsize,
+ struct rpcent **result)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ rpc, (void *)nss_lt_all,
+ rpc_marshal_func, rpc_unmarshal_func);
+#endif
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_rpcent, (void *)nss_lt_all },
+#ifdef YP
+ { NSSRC_NIS, nis_rpcent, (void *)nss_lt_all },
+#endif
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+ int rv, ret_errno;
+
+ ret_errno = 0;
+ *result = NULL;
+ rv = nsdispatch(result, dtab, NSDB_RPC, "getrpcent_r", defaultsrc,
+ rpc, buffer, bufsize, &ret_errno);
+
+ if (rv == NS_SUCCESS)
+ return (0);
+ else
+ return (ret_errno);
+}
+
+/* get** wrappers for get**_r functions implementation */
+static void
+rpcent_endstate(void *p)
+{
+ if (p == NULL)
+ return;
+
+ free(((struct rpcent_state *)p)->buffer);
+ free(p);
+}
+
+static int
+wrap_getrpcbyname_r(union key key, struct rpcent *rpc, char *buffer,
+ size_t bufsize, struct rpcent **res)
+{
+ return (getrpcbyname_r(key.name, rpc, buffer, bufsize, res));
+}
+
+static int
+wrap_getrpcbynumber_r(union key key, struct rpcent *rpc, char *buffer,
+ size_t bufsize, struct rpcent **res)
+{
+ return (getrpcbynumber_r(key.number, rpc, buffer, bufsize, res));
+}
+
+static int
+wrap_getrpcent_r(union key key __unused, struct rpcent *rpc, char *buffer,
+ size_t bufsize, struct rpcent **res)
+{
+ return (getrpcent_r(rpc, buffer, bufsize, res));
+}
+
+static struct rpcent *
+getrpc(int (*fn)(union key, struct rpcent *, char *, size_t, struct rpcent **),
+ union key key)
+{
+ int rv;
+ struct rpcent *res;
+ struct rpcent_state * st;
+
+ rv=rpcent_getstate(&st);
+ if (rv != 0) {
+ errno = rv;
+ return NULL;
+ }
+
+ if (st->buffer == NULL) {
+ st->buffer = malloc(RPCENT_STORAGE_INITIAL);
+ if (st->buffer == NULL)
+ return (NULL);
+ st->bufsize = RPCENT_STORAGE_INITIAL;
+ }
+ do {
+ rv = fn(key, &st->rpc, st->buffer, st->bufsize, &res);
+ if (res == NULL && rv == ERANGE) {
+ free(st->buffer);
+ if ((st->bufsize << 1) > RPCENT_STORAGE_MAX) {
+ st->buffer = NULL;
+ errno = ERANGE;
+ return (NULL);
+ }
+ st->bufsize <<= 1;
+ st->buffer = malloc(st->bufsize);
+ if (st->buffer == NULL)
+ return (NULL);
+ }
+ } while (res == NULL && rv == ERANGE);
+ if (rv != 0)
+ errno = rv;
+
+ return (res);
+}
+
+struct rpcent *
+getrpcbyname(char *name)
+{
+ union key key;
+
+ key.name = name;
+
+ return (getrpc(wrap_getrpcbyname_r, key));
+}
+
+struct rpcent *
+getrpcbynumber(int number)
+{
+ union key key;
+
+ key.number = number;
+
+ return (getrpc(wrap_getrpcbynumber_r, key));
+}
+
+struct rpcent *
+getrpcent()
+{
+ union key key;
+
+ key.number = 0; /* not used */
+
+ return (getrpc(wrap_getrpcent_r, key));
+}
+
+void
+setrpcent(int stayopen)
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ rpc, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_setrpcent, (void *)SETRPCENT },
+#ifdef YP
+ { NSSRC_NIS, nis_setrpcent, (void *)SETRPCENT },
+#endif
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+
+ (void)nsdispatch(NULL, dtab, NSDB_RPC, "setrpcent", defaultsrc,
+ stayopen);
+}
+
+void
+endrpcent()
+{
+#ifdef NS_CACHING
+ static const nss_cache_info cache_info = NS_MP_CACHE_INFO_INITIALIZER(
+ rpc, (void *)nss_lt_all,
+ NULL, NULL);
+#endif
+
+ static const ns_dtab dtab[] = {
+ { NSSRC_FILES, files_setrpcent, (void *)ENDRPCENT },
+#ifdef YP
+ { NSSRC_NIS, nis_setrpcent, (void *)ENDRPCENT },
+#endif
+#ifdef NS_CACHING
+ NS_CACHE_CB(&cache_info)
+#endif
+ { NULL, NULL, NULL }
+ };
+
+ (void)nsdispatch(NULL, dtab, NSDB_RPC, "endrpcent", defaultsrc);
+}
diff --git a/lib/libc/rpc/getrpcport.3 b/lib/libc/rpc/getrpcport.3
new file mode 100644
index 0000000..6e1f199
--- /dev/null
+++ b/lib/libc/rpc/getrpcport.3
@@ -0,0 +1,36 @@
+.\" @(#)getrpcport.3r 2.2 88/08/02 4.0 RPCSRC; from 1.12 88/02/26 SMI
+.\" $FreeBSD$
+.\"
+.Dd October 6, 1987
+.Dt GETRPCPORT 3
+.Os
+.Sh NAME
+.Nm getrpcport
+.Nd get RPC port number
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Ft int
+.Fn getrpcport "char *host" "int prognum" "int versnum" "int proto"
+.Sh DESCRIPTION
+The
+.Fn getrpcport
+function
+returns the port number for version
+.Fa versnum
+of the RPC program
+.Fa prognum
+running on
+.Fa host
+and using protocol
+.Fa proto .
+It returns 0 if it cannot contact the portmapper, or if
+.Fa prognum
+is not registered.
+If
+.Fa prognum
+is registered but not with version
+.Fa versnum ,
+it will still return a port number (for some version of the program)
+indicating that the program is indeed registered.
+The version mismatch will be detected upon the first call to the service.
diff --git a/lib/libc/rpc/getrpcport.c b/lib/libc/rpc/getrpcport.c
new file mode 100644
index 0000000..676a1f5
--- /dev/null
+++ b/lib/libc/rpc/getrpcport.c
@@ -0,0 +1,78 @@
+/* $NetBSD: getrpcport.c,v 1.16 2000/01/22 22:19:18 mycroft Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)getrpcport.c 1.3 87/08/11 SMI";
+static char *sccsid = "@(#)getrpcport.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Copyright (c) 1985 by Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <assert.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include "un-namespace.h"
+
+int
+getrpcport(host, prognum, versnum, proto)
+ char *host;
+ int prognum, versnum, proto;
+{
+ struct sockaddr_in addr;
+ struct hostent *hp;
+
+ assert(host != NULL);
+
+ if ((hp = gethostbyname(host)) == NULL)
+ return (0);
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_len = sizeof(struct sockaddr_in);
+ addr.sin_family = AF_INET;
+ addr.sin_port = 0;
+ if (hp->h_length > addr.sin_len)
+ hp->h_length = addr.sin_len;
+ memcpy(&addr.sin_addr.s_addr, hp->h_addr, (size_t)hp->h_length);
+ /* Inconsistent interfaces need casts! :-( */
+ return (pmap_getport(&addr, (u_long)prognum, (u_long)versnum,
+ (u_int)proto));
+}
diff --git a/lib/libc/rpc/key_call.c b/lib/libc/rpc/key_call.c
new file mode 100644
index 0000000..afb11c8
--- /dev/null
+++ b/lib/libc/rpc/key_call.c
@@ -0,0 +1,480 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+#ident "@(#)key_call.c 1.25 94/04/24 SMI"
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * key_call.c, Interface to keyserver
+ *
+ * setsecretkey(key) - set your secret key
+ * encryptsessionkey(agent, deskey) - encrypt a session key to talk to agent
+ * decryptsessionkey(agent, deskey) - decrypt ditto
+ * gendeskey(deskey) - generate a secure des key
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <errno.h>
+#include <rpc/rpc.h>
+#include <rpc/auth.h>
+#include <rpc/auth_unix.h>
+#include <rpc/key_prot.h>
+#include <string.h>
+#include <netconfig.h>
+#include <sys/utsname.h>
+#include <stdlib.h>
+#include <signal.h>
+#include <sys/wait.h>
+#include <sys/fcntl.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+
+#define KEY_TIMEOUT 5 /* per-try timeout in seconds */
+#define KEY_NRETRY 12 /* number of retries */
+
+#ifdef DEBUG
+#define debug(msg) (void) fprintf(stderr, "%s\n", msg);
+#else
+#define debug(msg)
+#endif /* DEBUG */
+
+/*
+ * Hack to allow the keyserver to use AUTH_DES (for authenticated
+ * NIS+ calls, for example). The only functions that get called
+ * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes.
+ *
+ * The approach is to have the keyserver fill in pointers to local
+ * implementations of these functions, and to call those in key_call().
+ */
+
+cryptkeyres *(*__key_encryptsession_pk_LOCAL)() = 0;
+cryptkeyres *(*__key_decryptsession_pk_LOCAL)() = 0;
+des_block *(*__key_gendes_LOCAL)() = 0;
+
+static int key_call( u_long, xdrproc_t, void *, xdrproc_t, void *);
+
+int
+key_setsecret(secretkey)
+ const char *secretkey;
+{
+ keystatus status;
+
+ if (!key_call((u_long) KEY_SET, (xdrproc_t)xdr_keybuf,
+ (void *)secretkey,
+ (xdrproc_t)xdr_keystatus, &status)) {
+ return (-1);
+ }
+ if (status != KEY_SUCCESS) {
+ debug("set status is nonzero");
+ return (-1);
+ }
+ return (0);
+}
+
+
+/* key_secretkey_is_set() returns 1 if the keyserver has a secret key
+ * stored for the caller's effective uid; it returns 0 otherwise
+ *
+ * N.B.: The KEY_NET_GET key call is undocumented. Applications shouldn't
+ * be using it, because it allows them to get the user's secret key.
+ */
+
+int
+key_secretkey_is_set(void)
+{
+ struct key_netstres kres;
+
+ memset((void*)&kres, 0, sizeof (kres));
+ if (key_call((u_long) KEY_NET_GET, (xdrproc_t)xdr_void, NULL,
+ (xdrproc_t)xdr_key_netstres, &kres) &&
+ (kres.status == KEY_SUCCESS) &&
+ (kres.key_netstres_u.knet.st_priv_key[0] != 0)) {
+ /* avoid leaving secret key in memory */
+ memset(kres.key_netstres_u.knet.st_priv_key, 0, HEXKEYBYTES);
+ return (1);
+ }
+ return (0);
+}
+
+int
+key_encryptsession_pk(remotename, remotekey, deskey)
+ char *remotename;
+ netobj *remotekey;
+ des_block *deskey;
+{
+ cryptkeyarg2 arg;
+ cryptkeyres res;
+
+ arg.remotename = remotename;
+ arg.remotekey = *remotekey;
+ arg.deskey = *deskey;
+ if (!key_call((u_long)KEY_ENCRYPT_PK, (xdrproc_t)xdr_cryptkeyarg2, &arg,
+ (xdrproc_t)xdr_cryptkeyres, &res)) {
+ return (-1);
+ }
+ if (res.status != KEY_SUCCESS) {
+ debug("encrypt status is nonzero");
+ return (-1);
+ }
+ *deskey = res.cryptkeyres_u.deskey;
+ return (0);
+}
+
+int
+key_decryptsession_pk(remotename, remotekey, deskey)
+ char *remotename;
+ netobj *remotekey;
+ des_block *deskey;
+{
+ cryptkeyarg2 arg;
+ cryptkeyres res;
+
+ arg.remotename = remotename;
+ arg.remotekey = *remotekey;
+ arg.deskey = *deskey;
+ if (!key_call((u_long)KEY_DECRYPT_PK, (xdrproc_t)xdr_cryptkeyarg2, &arg,
+ (xdrproc_t)xdr_cryptkeyres, &res)) {
+ return (-1);
+ }
+ if (res.status != KEY_SUCCESS) {
+ debug("decrypt status is nonzero");
+ return (-1);
+ }
+ *deskey = res.cryptkeyres_u.deskey;
+ return (0);
+}
+
+int
+key_encryptsession(remotename, deskey)
+ const char *remotename;
+ des_block *deskey;
+{
+ cryptkeyarg arg;
+ cryptkeyres res;
+
+ arg.remotename = (char *) remotename;
+ arg.deskey = *deskey;
+ if (!key_call((u_long)KEY_ENCRYPT, (xdrproc_t)xdr_cryptkeyarg, &arg,
+ (xdrproc_t)xdr_cryptkeyres, &res)) {
+ return (-1);
+ }
+ if (res.status != KEY_SUCCESS) {
+ debug("encrypt status is nonzero");
+ return (-1);
+ }
+ *deskey = res.cryptkeyres_u.deskey;
+ return (0);
+}
+
+int
+key_decryptsession(remotename, deskey)
+ const char *remotename;
+ des_block *deskey;
+{
+ cryptkeyarg arg;
+ cryptkeyres res;
+
+ arg.remotename = (char *) remotename;
+ arg.deskey = *deskey;
+ if (!key_call((u_long)KEY_DECRYPT, (xdrproc_t)xdr_cryptkeyarg, &arg,
+ (xdrproc_t)xdr_cryptkeyres, &res)) {
+ return (-1);
+ }
+ if (res.status != KEY_SUCCESS) {
+ debug("decrypt status is nonzero");
+ return (-1);
+ }
+ *deskey = res.cryptkeyres_u.deskey;
+ return (0);
+}
+
+int
+key_gendes(key)
+ des_block *key;
+{
+ if (!key_call((u_long)KEY_GEN, (xdrproc_t)xdr_void, NULL,
+ (xdrproc_t)xdr_des_block, key)) {
+ return (-1);
+ }
+ return (0);
+}
+
+int
+key_setnet(arg)
+struct key_netstarg *arg;
+{
+ keystatus status;
+
+
+ if (!key_call((u_long) KEY_NET_PUT, (xdrproc_t)xdr_key_netstarg, arg,
+ (xdrproc_t)xdr_keystatus, &status)){
+ return (-1);
+ }
+
+ if (status != KEY_SUCCESS) {
+ debug("key_setnet status is nonzero");
+ return (-1);
+ }
+ return (1);
+}
+
+
+int
+key_get_conv(pkey, deskey)
+ char *pkey;
+ des_block *deskey;
+{
+ cryptkeyres res;
+
+ if (!key_call((u_long) KEY_GET_CONV, (xdrproc_t)xdr_keybuf, pkey,
+ (xdrproc_t)xdr_cryptkeyres, &res)) {
+ return (-1);
+ }
+ if (res.status != KEY_SUCCESS) {
+ debug("get_conv status is nonzero");
+ return (-1);
+ }
+ *deskey = res.cryptkeyres_u.deskey;
+ return (0);
+}
+
+struct key_call_private {
+ CLIENT *client; /* Client handle */
+ pid_t pid; /* process-id at moment of creation */
+ uid_t uid; /* user-id at last authorization */
+};
+static struct key_call_private *key_call_private_main = NULL;
+static thread_key_t key_call_key;
+static once_t key_call_once = ONCE_INITIALIZER;
+static int key_call_key_error;
+
+static void
+key_call_destroy(void *vp)
+{
+ struct key_call_private *kcp = (struct key_call_private *)vp;
+
+ if (kcp) {
+ if (kcp->client)
+ clnt_destroy(kcp->client);
+ free(kcp);
+ }
+}
+
+static void
+key_call_init(void)
+{
+
+ key_call_key_error = thr_keycreate(&key_call_key, key_call_destroy);
+}
+
+/*
+ * Keep the handle cached. This call may be made quite often.
+ */
+static CLIENT *
+getkeyserv_handle(vers)
+int vers;
+{
+ void *localhandle;
+ struct netconfig *nconf;
+ struct netconfig *tpconf;
+ struct key_call_private *kcp;
+ struct timeval wait_time;
+ struct utsname u;
+ int main_thread;
+ int fd;
+
+#define TOTAL_TIMEOUT 30 /* total timeout talking to keyserver */
+#define TOTAL_TRIES 5 /* Number of tries */
+
+ if ((main_thread = thr_main())) {
+ kcp = key_call_private_main;
+ } else {
+ if (thr_once(&key_call_once, key_call_init) != 0 ||
+ key_call_key_error != 0)
+ return ((CLIENT *) NULL);
+ kcp = (struct key_call_private *)thr_getspecific(key_call_key);
+ }
+ if (kcp == (struct key_call_private *)NULL) {
+ kcp = (struct key_call_private *)malloc(sizeof (*kcp));
+ if (kcp == (struct key_call_private *)NULL) {
+ return ((CLIENT *) NULL);
+ }
+ if (main_thread)
+ key_call_private_main = kcp;
+ else
+ thr_setspecific(key_call_key, (void *) kcp);
+ kcp->client = NULL;
+ }
+
+ /* if pid has changed, destroy client and rebuild */
+ if (kcp->client != NULL && kcp->pid != getpid()) {
+ clnt_destroy(kcp->client);
+ kcp->client = NULL;
+ }
+
+ if (kcp->client != NULL) {
+ /* if uid has changed, build client handle again */
+ if (kcp->uid != geteuid()) {
+ kcp->uid = geteuid();
+ auth_destroy(kcp->client->cl_auth);
+ kcp->client->cl_auth =
+ authsys_create("", kcp->uid, 0, 0, NULL);
+ if (kcp->client->cl_auth == NULL) {
+ clnt_destroy(kcp->client);
+ kcp->client = NULL;
+ return ((CLIENT *) NULL);
+ }
+ }
+ /* Change the version number to the new one */
+ clnt_control(kcp->client, CLSET_VERS, (void *)&vers);
+ return (kcp->client);
+ }
+ if (!(localhandle = setnetconfig())) {
+ return ((CLIENT *) NULL);
+ }
+ tpconf = NULL;
+#if defined(__FreeBSD__)
+ if (uname(&u) == -1)
+#else
+#if defined(i386)
+ if (_nuname(&u) == -1)
+#elif defined(sparc)
+ if (_uname(&u) == -1)
+#else
+#error Unknown architecture!
+#endif
+#endif
+ {
+ endnetconfig(localhandle);
+ return ((CLIENT *) NULL);
+ }
+ while ((nconf = getnetconfig(localhandle)) != NULL) {
+ if (strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
+ /*
+ * We use COTS_ORD here so that the caller can
+ * find out immediately if the server is dead.
+ */
+ if (nconf->nc_semantics == NC_TPI_COTS_ORD) {
+ kcp->client = clnt_tp_create(u.nodename,
+ KEY_PROG, vers, nconf);
+ if (kcp->client)
+ break;
+ } else {
+ tpconf = nconf;
+ }
+ }
+ }
+ if ((kcp->client == (CLIENT *) NULL) && (tpconf))
+ /* Now, try the CLTS or COTS loopback transport */
+ kcp->client = clnt_tp_create(u.nodename,
+ KEY_PROG, vers, tpconf);
+ endnetconfig(localhandle);
+
+ if (kcp->client == (CLIENT *) NULL) {
+ return ((CLIENT *) NULL);
+ }
+ kcp->uid = geteuid();
+ kcp->pid = getpid();
+ kcp->client->cl_auth = authsys_create("", kcp->uid, 0, 0, NULL);
+ if (kcp->client->cl_auth == NULL) {
+ clnt_destroy(kcp->client);
+ kcp->client = NULL;
+ return ((CLIENT *) NULL);
+ }
+
+ wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES;
+ wait_time.tv_usec = 0;
+ (void) clnt_control(kcp->client, CLSET_RETRY_TIMEOUT,
+ (char *)&wait_time);
+ if (clnt_control(kcp->client, CLGET_FD, (char *)&fd))
+ _fcntl(fd, F_SETFD, 1); /* make it "close on exec" */
+
+ return (kcp->client);
+}
+
+/* returns 0 on failure, 1 on success */
+
+static int
+key_call(proc, xdr_arg, arg, xdr_rslt, rslt)
+ u_long proc;
+ xdrproc_t xdr_arg;
+ void *arg;
+ xdrproc_t xdr_rslt;
+ void *rslt;
+{
+ CLIENT *clnt;
+ struct timeval wait_time;
+
+ if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) {
+ cryptkeyres *res;
+ res = (*__key_encryptsession_pk_LOCAL)(geteuid(), arg);
+ *(cryptkeyres*)rslt = *res;
+ return (1);
+ } else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) {
+ cryptkeyres *res;
+ res = (*__key_decryptsession_pk_LOCAL)(geteuid(), arg);
+ *(cryptkeyres*)rslt = *res;
+ return (1);
+ } else if (proc == KEY_GEN && __key_gendes_LOCAL) {
+ des_block *res;
+ res = (*__key_gendes_LOCAL)(geteuid(), 0);
+ *(des_block*)rslt = *res;
+ return (1);
+ }
+
+ if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) ||
+ (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) ||
+ (proc == KEY_GET_CONV))
+ clnt = getkeyserv_handle(2); /* talk to version 2 */
+ else
+ clnt = getkeyserv_handle(1); /* talk to version 1 */
+
+ if (clnt == NULL) {
+ return (0);
+ }
+
+ wait_time.tv_sec = TOTAL_TIMEOUT;
+ wait_time.tv_usec = 0;
+
+ if (clnt_call(clnt, proc, xdr_arg, arg, xdr_rslt, rslt,
+ wait_time) == RPC_SUCCESS) {
+ return (1);
+ } else {
+ return (0);
+ }
+}
diff --git a/lib/libc/rpc/key_prot_xdr.c b/lib/libc/rpc/key_prot_xdr.c
new file mode 100644
index 0000000..bcead6a
--- /dev/null
+++ b/lib/libc/rpc/key_prot_xdr.c
@@ -0,0 +1,178 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "namespace.h"
+#include <rpc/key_prot.h>
+#include "un-namespace.h"
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/* Copyright (c) 1990, 1991 Sun Microsystems, Inc. */
+
+/* #pragma ident "@(#)key_prot.x 1.7 94/04/29 SMI" */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Compiled from key_prot.x using rpcgen.
+ * DO NOT EDIT THIS FILE!
+ * This is NOT source code!
+ */
+
+bool_t
+xdr_keystatus(register XDR *xdrs, keystatus *objp)
+{
+
+ if (!xdr_enum(xdrs, (enum_t *)objp))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_keybuf(register XDR *xdrs, keybuf objp)
+{
+
+ if (!xdr_opaque(xdrs, objp, HEXKEYBYTES))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_netnamestr(register XDR *xdrs, netnamestr *objp)
+{
+
+ if (!xdr_string(xdrs, objp, MAXNETNAMELEN))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_cryptkeyarg(register XDR *xdrs, cryptkeyarg *objp)
+{
+
+ if (!xdr_netnamestr(xdrs, &objp->remotename))
+ return (FALSE);
+ if (!xdr_des_block(xdrs, &objp->deskey))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_cryptkeyarg2(register XDR *xdrs, cryptkeyarg2 *objp)
+{
+
+ if (!xdr_netnamestr(xdrs, &objp->remotename))
+ return (FALSE);
+ if (!xdr_netobj(xdrs, &objp->remotekey))
+ return (FALSE);
+ if (!xdr_des_block(xdrs, &objp->deskey))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_cryptkeyres(register XDR *xdrs, cryptkeyres *objp)
+{
+
+ if (!xdr_keystatus(xdrs, &objp->status))
+ return (FALSE);
+ switch (objp->status) {
+ case KEY_SUCCESS:
+ if (!xdr_des_block(xdrs, &objp->cryptkeyres_u.deskey))
+ return (FALSE);
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_unixcred(register XDR *xdrs, unixcred *objp)
+{
+ u_int **pgids_val;
+
+ if (!xdr_u_int(xdrs, &objp->uid))
+ return (FALSE);
+ if (!xdr_u_int(xdrs, &objp->gid))
+ return (FALSE);
+ pgids_val = &objp->gids.gids_val;
+ if (!xdr_array(xdrs, (char **) pgids_val, (u_int *) &objp->gids.gids_len, MAXGIDS,
+ sizeof (u_int), (xdrproc_t) xdr_u_int))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_getcredres(register XDR *xdrs, getcredres *objp)
+{
+
+ if (!xdr_keystatus(xdrs, &objp->status))
+ return (FALSE);
+ switch (objp->status) {
+ case KEY_SUCCESS:
+ if (!xdr_unixcred(xdrs, &objp->getcredres_u.cred))
+ return (FALSE);
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_key_netstarg(register XDR *xdrs, key_netstarg *objp)
+{
+
+ if (!xdr_keybuf(xdrs, objp->st_priv_key))
+ return (FALSE);
+ if (!xdr_keybuf(xdrs, objp->st_pub_key))
+ return (FALSE);
+ if (!xdr_netnamestr(xdrs, &objp->st_netname))
+ return (FALSE);
+ return (TRUE);
+}
+
+bool_t
+xdr_key_netstres(register XDR *xdrs, key_netstres *objp)
+{
+
+ if (!xdr_keystatus(xdrs, &objp->status))
+ return (FALSE);
+ switch (objp->status) {
+ case KEY_SUCCESS:
+ if (!xdr_key_netstarg(xdrs, &objp->key_netstres_u.knet))
+ return (FALSE);
+ break;
+ default:
+ break;
+ }
+ return (TRUE);
+}
diff --git a/lib/libc/rpc/mt_misc.c b/lib/libc/rpc/mt_misc.c
new file mode 100644
index 0000000..7abcaed
--- /dev/null
+++ b/lib/libc/rpc/mt_misc.c
@@ -0,0 +1,117 @@
+/* $NetBSD: mt_misc.c,v 1.1 2000/06/02 23:11:11 fvdl Exp $ */
+
+/* #pragma ident "@(#)mt_misc.c 1.24 93/04/29 SMI" */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <rpc/rpc.h>
+#include <sys/time.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+/* Take these objects out of the application namespace. */
+#define svc_lock __svc_lock
+#define svc_fd_lock __svc_fd_lock
+#define rpcbaddr_cache_lock __rpcbaddr_cache_lock
+#define authdes_ops_lock __authdes_ops_lock
+#define authnone_lock __authnone_lock
+#define authsvc_lock __authsvc_lock
+#define clnt_fd_lock __clnt_fd_lock
+#define clntraw_lock __clntraw_lock
+#define dupreq_lock __dupreq_lock
+#define loopnconf_lock __loopnconf_lock
+#define ops_lock __ops_lock
+#define proglst_lock __proglst_lock
+#define rpcsoc_lock __rpcsoc_lock
+#define svcraw_lock __svcraw_lock
+#define xprtlist_lock __xprtlist_lock
+
+/* protects the services list (svc.c) */
+pthread_rwlock_t svc_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/* protects svc_fdset and the xports[] array */
+pthread_rwlock_t svc_fd_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/* protects the RPCBIND address cache */
+pthread_rwlock_t rpcbaddr_cache_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+/* serializes authdes ops initializations */
+pthread_mutex_t authdes_ops_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects des stats list */
+pthread_mutex_t svcauthdesstats_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* auth_none.c serialization */
+pthread_mutex_t authnone_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects the Auths list (svc_auth.c) */
+pthread_mutex_t authsvc_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects client-side fd lock array */
+pthread_mutex_t clnt_fd_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* clnt_raw.c serialization */
+pthread_mutex_t clntraw_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* dupreq variables (svc_dg.c) */
+pthread_mutex_t dupreq_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* loopnconf (rpcb_clnt.c) */
+pthread_mutex_t loopnconf_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* serializes ops initializations */
+pthread_mutex_t ops_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* protects proglst list (svc_simple.c) */
+pthread_mutex_t proglst_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* serializes clnt_com_create() (rpc_soc.c) */
+pthread_mutex_t rpcsoc_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* svc_raw.c serialization */
+pthread_mutex_t svcraw_lock = PTHREAD_MUTEX_INITIALIZER;
+
+/* xprtlist (svc_generic.c) */
+pthread_mutex_t xprtlist_lock = PTHREAD_MUTEX_INITIALIZER;
+
+#undef rpc_createerr
+
+struct rpc_createerr rpc_createerr;
+static thread_key_t rce_key;
+static once_t rce_once = ONCE_INITIALIZER;
+static int rce_key_error;
+
+static void
+rce_key_init(void)
+{
+
+ rce_key_error = thr_keycreate(&rce_key, free);
+}
+
+struct rpc_createerr *
+__rpc_createerr()
+{
+ struct rpc_createerr *rce_addr = 0;
+
+ if (thr_main())
+ return (&rpc_createerr);
+ if (thr_once(&rce_once, rce_key_init) != 0 || rce_key_error != 0)
+ return (&rpc_createerr);
+ rce_addr = (struct rpc_createerr *)thr_getspecific(rce_key);
+ if (!rce_addr) {
+ rce_addr = (struct rpc_createerr *)
+ malloc(sizeof (struct rpc_createerr));
+ if (thr_setspecific(rce_key, (void *) rce_addr) != 0) {
+ if (rce_addr)
+ free(rce_addr);
+ return (&rpc_createerr);
+ }
+ memset(rce_addr, 0, sizeof (struct rpc_createerr));
+ return (rce_addr);
+ }
+ return (rce_addr);
+}
diff --git a/lib/libc/rpc/mt_misc.h b/lib/libc/rpc/mt_misc.h
new file mode 100644
index 0000000..9cc2349
--- /dev/null
+++ b/lib/libc/rpc/mt_misc.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2006 The FreeBSD Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#ifndef _MT_MISC_H
+#define _MT_MISC_H
+
+/* Take these locks out of the application namespace. */
+#define svc_lock __svc_lock
+#define svc_fd_lock __svc_fd_lock
+#define rpcbaddr_cache_lock __rpcbaddr_cache_lock
+#define authdes_ops_lock __authdes_ops_lock
+#define authnone_lock __authnone_lock
+#define authsvc_lock __authsvc_lock
+#define clnt_fd_lock __clnt_fd_lock
+#define clntraw_lock __clntraw_lock
+#define dupreq_lock __dupreq_lock
+#define loopnconf_lock __loopnconf_lock
+#define ops_lock __ops_lock
+#define proglst_lock __proglst_lock
+#define rpcsoc_lock __rpcsoc_lock
+#define svcraw_lock __svcraw_lock
+#define xprtlist_lock __xprtlist_lock
+
+extern pthread_rwlock_t svc_lock;
+extern pthread_rwlock_t svc_fd_lock;
+extern pthread_rwlock_t rpcbaddr_cache_lock;
+extern pthread_mutex_t authdes_ops_lock;
+extern pthread_mutex_t svcauthdesstats_lock;
+extern pthread_mutex_t authnone_lock;
+extern pthread_mutex_t authsvc_lock;
+extern pthread_mutex_t clnt_fd_lock;
+extern pthread_mutex_t clntraw_lock;
+extern pthread_mutex_t dupreq_lock;
+extern pthread_mutex_t loopnconf_lock;
+extern pthread_mutex_t ops_lock;
+extern pthread_mutex_t proglst_lock;
+extern pthread_mutex_t rpcsoc_lock;
+extern pthread_mutex_t svcraw_lock;
+extern pthread_mutex_t tsd_lock;
+extern pthread_mutex_t xprtlist_lock;
+
+#endif
diff --git a/lib/libc/rpc/netconfig.5 b/lib/libc/rpc/netconfig.5
new file mode 100644
index 0000000..edd2f63
--- /dev/null
+++ b/lib/libc/rpc/netconfig.5
@@ -0,0 +1,132 @@
+.\" $NetBSD: netconfig.5,v 1.2 2000/11/08 13:18:28 lukem Exp $
+.\" $NetBSD: netconfig.5,v 1.2 2000/11/08 13:18:28 lukem Exp $
+.\" $FreeBSD$
+.Dd November 17, 2000
+.Dt NETCONFIG 5
+.Os
+.Sh NAME
+.Nm netconfig
+.Nd network configuration data base
+.Sh SYNOPSIS
+.Pa /etc/netconfig
+.Sh DESCRIPTION
+The
+.Nm
+file defines a list of
+.Dq transport names ,
+describing their semantics and protocol.
+In
+.Fx ,
+this file is only used by the RPC library code.
+.Pp
+Entries have the following format:
+.Pp
+.Ar network_id semantics flags family protoname device libraries
+.Pp
+Entries consist of the following fields:
+.Bl -tag -width network_id
+.It Ar network_id
+The name of the transport described.
+.It Ar semantics
+Describes the semantics of the transport.
+This can be one of:
+.Bl -tag -width tpi_cots_ord -offset indent
+.It Sy tpi_clts
+Connectionless transport.
+.It Sy tpi_cots
+Connection-oriented transport
+.It Sy tpi_cots_ord
+Connection-oriented, ordered transport.
+.It Sy tpi_raw
+A raw connection.
+.El
+.It Ar flags
+This field is either blank (specified by
+.Dq Li - ) ,
+or contains one or more of the following characters:
+.Bl -tag -width b -offset indent
+.It Sy b
+The network represented by this entry is broadcast capable.
+This flag is meaningless in
+.Fx .
+.It Sy v
+The entry may be returned by the
+.Xr getnetpath 3
+function.
+.El
+.It Ar family
+The protocol family of the transport.
+This is currently one of:
+.Bl -tag -width loopback -offset indent
+.It Sy inet6
+The IPv6
+.Pq Dv PF_INET6
+family of protocols.
+.It Sy inet
+The IPv4
+.Pq Dv PF_INET
+family of protocols.
+.It Sy loopback
+The
+.Dv PF_LOCAL
+protocol family.
+.El
+.It Ar protoname
+The name of the protocol used for this transport.
+Can currently be either
+.Sy udp ,
+.Sy tcp
+or empty.
+.It Ar device
+This field is always empty in
+.Fx .
+.It Ar libraries
+This field is always empty in
+.Fx .
+.El
+.Pp
+The order of entries in this file will determine which transport will
+be preferred by the RPC library code, given a match on a specified
+network type.
+For example, if a sample network config file would look like this:
+.Bd -literal -offset indent
+udp6 tpi_clts v inet6 udp - -
+tcp6 tpi_cots_ord v inet6 tcp - -
+udp tpi_clts v inet udp - -
+tcp tpi_cots_ord v inet tcp - -
+rawip tpi_raw - inet - - -
+local tpi_cots_ord - loopback - - -
+.Ed
+.Pp
+then using the network type
+.Sy udp
+in calls to the RPC library function (see
+.Xr rpc 3 )
+will make the code first try
+.Sy udp6 ,
+and then
+.Sy udp .
+.Pp
+.Xr getnetconfig 3
+and associated functions will parse this file and return structures of
+the following format:
+.Bd -literal
+struct netconfig {
+ char *nc_netid; /* Network ID */
+ unsigned long nc_semantics; /* Semantics */
+ unsigned long nc_flag; /* Flags */
+ char *nc_protofmly; /* Protocol family */
+ char *nc_proto; /* Protocol name */
+ char *nc_device; /* Network device pathname (unused) */
+ unsigned long nc_nlookups; /* Number of lookup libs (unused) */
+ char **nc_lookups; /* Names of the libraries (unused) */
+ unsigned long nc_unused[9]; /* reserved */
+};
+.Ed
+.Sh FILES
+.Bl -tag -width /etc/netconfig -compact
+.It Pa /etc/netconfig
+.El
+.Sh SEE ALSO
+.Xr getnetconfig 3 ,
+.Xr getnetpath 3
diff --git a/lib/libc/rpc/netname.c b/lib/libc/rpc/netname.c
new file mode 100644
index 0000000..72361ba
--- /dev/null
+++ b/lib/libc/rpc/netname.c
@@ -0,0 +1,150 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)netname.c 1.8 91/03/11 Copyr 1986 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * netname utility routines
+ * convert from unix names to network names and vice-versa
+ * This module is operating system dependent!
+ * What we define here will work with any unix system that has adopted
+ * the sun NIS domain architecture.
+ */
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <rpc/rpc.h>
+#include <rpc/rpc_com.h>
+#ifdef YP
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <ctype.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#ifndef MAXHOSTNAMELEN
+#define MAXHOSTNAMELEN 256
+#endif
+
+#define TYPE_BIT(type) (sizeof (type) * CHAR_BIT)
+
+#define TYPE_SIGNED(type) (((type) -1) < 0)
+
+/*
+** 302 / 1000 is log10(2.0) rounded up.
+** Subtract one for the sign bit if the type is signed;
+** add one for integer division truncation;
+** add one more for a minus sign if the type is signed.
+*/
+#define INT_STRLEN_MAXIMUM(type) \
+ ((TYPE_BIT(type) - TYPE_SIGNED(type)) * 302 / 1000 + 1 + TYPE_SIGNED(type))
+
+static char *OPSYS = "unix";
+
+/*
+ * Figure out my fully qualified network name
+ */
+int
+getnetname(name)
+ char name[MAXNETNAMELEN+1];
+{
+ uid_t uid;
+
+ uid = geteuid();
+ if (uid == 0) {
+ return (host2netname(name, (char *) NULL, (char *) NULL));
+ } else {
+ return (user2netname(name, uid, (char *) NULL));
+ }
+}
+
+
+/*
+ * Convert unix cred to network-name
+ */
+int
+user2netname(netname, uid, domain)
+ char netname[MAXNETNAMELEN + 1];
+ const uid_t uid;
+ const char *domain;
+{
+ char *dfltdom;
+
+ if (domain == NULL) {
+ if (__rpc_get_default_domain(&dfltdom) != 0) {
+ return (0);
+ }
+ domain = dfltdom;
+ }
+ if (strlen(domain) + 1 + INT_STRLEN_MAXIMUM(u_long) + 1 + strlen(OPSYS) > MAXNETNAMELEN) {
+ return (0);
+ }
+ (void) sprintf(netname, "%s.%ld@%s", OPSYS, (u_long)uid, domain);
+ return (1);
+}
+
+
+/*
+ * Convert host to network-name
+ */
+int
+host2netname(netname, host, domain)
+ char netname[MAXNETNAMELEN + 1];
+ const char *host;
+ const char *domain;
+{
+ char *dfltdom;
+ char hostname[MAXHOSTNAMELEN+1];
+
+ if (domain == NULL) {
+ if (__rpc_get_default_domain(&dfltdom) != 0) {
+ return (0);
+ }
+ domain = dfltdom;
+ }
+ if (host == NULL) {
+ (void) gethostname(hostname, sizeof(hostname));
+ host = hostname;
+ }
+ if (strlen(domain) + 1 + strlen(host) + 1 + strlen(OPSYS) > MAXNETNAMELEN) {
+ return (0);
+ }
+ (void) sprintf(netname, "%s.%s@%s", OPSYS, host, domain);
+ return (1);
+}
diff --git a/lib/libc/rpc/netnamer.c b/lib/libc/rpc/netnamer.c
new file mode 100644
index 0000000..772160a
--- /dev/null
+++ b/lib/libc/rpc/netnamer.c
@@ -0,0 +1,331 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)netnamer.c 1.13 91/03/11 Copyr 1986 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * netname utility routines convert from unix names to network names and
+ * vice-versa This module is operating system dependent! What we define here
+ * will work with any unix system that has adopted the sun NIS domain
+ * architecture.
+ */
+#include "namespace.h"
+#include <sys/param.h>
+#include <rpc/rpc.h>
+#include <rpc/rpc_com.h>
+#ifdef YP
+#include <rpcsvc/yp_prot.h>
+#include <rpcsvc/ypclnt.h>
+#endif
+#include <ctype.h>
+#include <stdio.h>
+#include <grp.h>
+#include <pwd.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+static char *OPSYS = "unix";
+#ifdef YP
+static char *NETID = "netid.byname";
+#endif
+static char *NETIDFILE = "/etc/netid";
+
+static int getnetid( char *, char * );
+static int _getgroups( char *, gid_t * );
+
+/*
+ * Convert network-name into unix credential
+ */
+int
+netname2user(netname, uidp, gidp, gidlenp, gidlist)
+ char netname[MAXNETNAMELEN + 1];
+ uid_t *uidp;
+ gid_t *gidp;
+ int *gidlenp;
+ gid_t *gidlist;
+{
+ char *p;
+ int gidlen;
+ uid_t uid;
+ long luid;
+ struct passwd *pwd;
+ char val[1024];
+ char *val1, *val2;
+ char *domain;
+ int vallen;
+ int err;
+
+ if (getnetid(netname, val)) {
+ char *res = val;
+
+ p = strsep(&res, ":");
+ if (p == NULL)
+ return (0);
+ *uidp = (uid_t) atol(p);
+ p = strsep(&res, "\n,");
+ if (p == NULL) {
+ return (0);
+ }
+ *gidp = (gid_t) atol(p);
+ for (gidlen = 0; gidlen < NGRPS; gidlen++) {
+ p = strsep(&res, "\n,");
+ if (p == NULL)
+ break;
+ gidlist[gidlen] = (gid_t) atol(p);
+ }
+ *gidlenp = gidlen;
+
+ return (1);
+ }
+ val1 = strchr(netname, '.');
+ if (val1 == NULL)
+ return (0);
+ if (strncmp(netname, OPSYS, (val1-netname)))
+ return (0);
+ val1++;
+ val2 = strchr(val1, '@');
+ if (val2 == NULL)
+ return (0);
+ vallen = val2 - val1;
+ if (vallen > (1024 - 1))
+ vallen = 1024 - 1;
+ (void) strncpy(val, val1, 1024);
+ val[vallen] = 0;
+
+ err = __rpc_get_default_domain(&domain); /* change to rpc */
+ if (err)
+ return (0);
+
+ if (strcmp(val2 + 1, domain))
+ return (0); /* wrong domain */
+
+ if (sscanf(val, "%ld", &luid) != 1)
+ return (0);
+ uid = luid;
+
+ /* use initgroups method */
+ pwd = getpwuid(uid);
+ if (pwd == NULL)
+ return (0);
+ *uidp = pwd->pw_uid;
+ *gidp = pwd->pw_gid;
+ *gidlenp = _getgroups(pwd->pw_name, gidlist);
+ return (1);
+}
+
+/*
+ * initgroups
+ */
+
+static int
+_getgroups(uname, groups)
+ char *uname;
+ gid_t groups[NGRPS];
+{
+ gid_t ngroups = 0;
+ struct group *grp;
+ int i;
+ int j;
+ int filter;
+
+ setgrent();
+ while ((grp = getgrent())) {
+ for (i = 0; grp->gr_mem[i]; i++)
+ if (!strcmp(grp->gr_mem[i], uname)) {
+ if (ngroups == NGRPS) {
+#ifdef DEBUG
+ fprintf(stderr,
+ "initgroups: %s is in too many groups\n", uname);
+#endif
+ goto toomany;
+ }
+ /* filter out duplicate group entries */
+ filter = 0;
+ for (j = 0; j < ngroups; j++)
+ if (groups[j] == grp->gr_gid) {
+ filter++;
+ break;
+ }
+ if (!filter)
+ groups[ngroups++] = grp->gr_gid;
+ }
+ }
+toomany:
+ endgrent();
+ return (ngroups);
+}
+
+/*
+ * Convert network-name to hostname
+ */
+int
+netname2host(netname, hostname, hostlen)
+ char netname[MAXNETNAMELEN + 1];
+ char *hostname;
+ int hostlen;
+{
+ int err;
+ char valbuf[1024];
+ char *val;
+ char *val2;
+ int vallen;
+ char *domain;
+
+ if (getnetid(netname, valbuf)) {
+ val = valbuf;
+ if ((*val == '0') && (val[1] == ':')) {
+ (void) strncpy(hostname, val + 2, hostlen);
+ return (1);
+ }
+ }
+ val = strchr(netname, '.');
+ if (val == NULL)
+ return (0);
+ if (strncmp(netname, OPSYS, (val - netname)))
+ return (0);
+ val++;
+ val2 = strchr(val, '@');
+ if (val2 == NULL)
+ return (0);
+ vallen = val2 - val;
+ if (vallen > (hostlen - 1))
+ vallen = hostlen - 1;
+ (void) strncpy(hostname, val, vallen);
+ hostname[vallen] = 0;
+
+ err = __rpc_get_default_domain(&domain); /* change to rpc */
+ if (err)
+ return (0);
+
+ if (strcmp(val2 + 1, domain))
+ return (0); /* wrong domain */
+ else
+ return (1);
+}
+
+/*
+ * reads the file /etc/netid looking for a + to optionally go to the
+ * network information service.
+ */
+int
+getnetid(key, ret)
+ char *key, *ret;
+{
+ char buf[1024]; /* big enough */
+ char *res;
+ char *mkey;
+ char *mval;
+ FILE *fd;
+#ifdef YP
+ char *domain;
+ int err;
+ char *lookup;
+ int len;
+#endif
+
+ fd = fopen(NETIDFILE, "r");
+ if (fd == NULL) {
+#ifdef YP
+ res = "+";
+ goto getnetidyp;
+#else
+ return (0);
+#endif
+ }
+ for (;;) {
+ if (fd == NULL)
+ return (0); /* getnetidyp brings us here */
+ res = fgets(buf, sizeof(buf), fd);
+ if (res == NULL) {
+ fclose(fd);
+ return (0);
+ }
+ if (res[0] == '#')
+ continue;
+ else if (res[0] == '+') {
+#ifdef YP
+ getnetidyp:
+ err = yp_get_default_domain(&domain);
+ if (err) {
+ continue;
+ }
+ lookup = NULL;
+ err = yp_match(domain, NETID, key,
+ strlen(key), &lookup, &len);
+ if (err) {
+#ifdef DEBUG
+ fprintf(stderr, "match failed error %d\n", err);
+#endif
+ continue;
+ }
+ lookup[len] = 0;
+ strcpy(ret, lookup);
+ free(lookup);
+ if (fd != NULL)
+ fclose(fd);
+ return (2);
+#else /* YP */
+#ifdef DEBUG
+ fprintf(stderr,
+"Bad record in %s '+' -- NIS not supported in this library copy\n",
+ NETIDFILE);
+#endif
+ continue;
+#endif /* YP */
+ } else {
+ mkey = strsep(&res, "\t ");
+ if (mkey == NULL) {
+ fprintf(stderr,
+ "Bad record in %s -- %s", NETIDFILE, buf);
+ continue;
+ }
+ do {
+ mval = strsep(&res, " \t#\n");
+ } while (mval != NULL && !*mval);
+ if (mval == NULL) {
+ fprintf(stderr,
+ "Bad record in %s val problem - %s", NETIDFILE, buf);
+ continue;
+ }
+ if (strcmp(mkey, key) == 0) {
+ strcpy(ret, mval);
+ fclose(fd);
+ return (1);
+
+ }
+ }
+ }
+}
diff --git a/lib/libc/rpc/pmap_clnt.c b/lib/libc/rpc/pmap_clnt.c
new file mode 100644
index 0000000..a0db013
--- /dev/null
+++ b/lib/libc/rpc/pmap_clnt.c
@@ -0,0 +1,120 @@
+/* $NetBSD: pmap_clnt.c,v 1.16 2000/07/06 03:10:34 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)pmap_clnt.c 2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * pmap_clnt.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/nettype.h>
+#include <netinet/in.h>
+#include "un-namespace.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "rpc_com.h"
+
+bool_t
+pmap_set(u_long program, u_long version, int protocol, int port)
+{
+ bool_t rslt;
+ struct netbuf *na;
+ struct netconfig *nconf;
+ char buf[32];
+
+ if ((protocol != IPPROTO_UDP) && (protocol != IPPROTO_TCP)) {
+ return (FALSE);
+ }
+ nconf = __rpc_getconfip(protocol == IPPROTO_UDP ? "udp" : "tcp");
+ if (nconf == NULL) {
+ return (FALSE);
+ }
+ snprintf(buf, sizeof buf, "0.0.0.0.%d.%d",
+ (((u_int32_t)port) >> 8) & 0xff, port & 0xff);
+ na = uaddr2taddr(nconf, buf);
+ if (na == NULL) {
+ freenetconfigent(nconf);
+ return (FALSE);
+ }
+ rslt = rpcb_set((rpcprog_t)program, (rpcvers_t)version, nconf, na);
+ free(na);
+ freenetconfigent(nconf);
+ return (rslt);
+}
+
+/*
+ * Remove the mapping between program, version and port.
+ * Calls the pmap service remotely to do the un-mapping.
+ */
+bool_t
+pmap_unset(u_long program, u_long version)
+{
+ struct netconfig *nconf;
+ bool_t udp_rslt = FALSE;
+ bool_t tcp_rslt = FALSE;
+
+ nconf = __rpc_getconfip("udp");
+ if (nconf != NULL) {
+ udp_rslt = rpcb_unset((rpcprog_t)program, (rpcvers_t)version,
+ nconf);
+ freenetconfigent(nconf);
+ }
+ nconf = __rpc_getconfip("tcp");
+ if (nconf != NULL) {
+ tcp_rslt = rpcb_unset((rpcprog_t)program, (rpcvers_t)version,
+ nconf);
+ freenetconfigent(nconf);
+ }
+ /*
+ * XXX: The call may still succeed even if only one of the
+ * calls succeeded. This was the best that could be
+ * done for backward compatibility.
+ */
+ return (tcp_rslt || udp_rslt);
+}
diff --git a/lib/libc/rpc/pmap_getmaps.c b/lib/libc/rpc/pmap_getmaps.c
new file mode 100644
index 0000000..42d3720
--- /dev/null
+++ b/lib/libc/rpc/pmap_getmaps.c
@@ -0,0 +1,100 @@
+/* $NetBSD: pmap_getmaps.c,v 1.16 2000/07/06 03:10:34 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)pmap_getmaps.c 2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * pmap_getmap.c
+ * Client interface to pmap rpc service.
+ * contains pmap_getmaps, which is only tcp service involved
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include <assert.h>
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include "un-namespace.h"
+
+#define NAMELEN 255
+#define MAX_BROADCAST_SIZE 1400
+
+/*
+ * Get a copy of the current port maps.
+ * Calls the pmap service remotely to do get the maps.
+ */
+struct pmaplist *
+pmap_getmaps(address)
+ struct sockaddr_in *address;
+{
+ struct pmaplist *head = NULL;
+ int sock = -1;
+ struct timeval minutetimeout;
+ CLIENT *client;
+
+ assert(address != NULL);
+
+ minutetimeout.tv_sec = 60;
+ minutetimeout.tv_usec = 0;
+ address->sin_port = htons(PMAPPORT);
+ client = clnttcp_create(address, PMAPPROG,
+ PMAPVERS, &sock, 50, 500);
+ if (client != NULL) {
+ if (CLNT_CALL(client, (rpcproc_t)PMAPPROC_DUMP,
+ (xdrproc_t)xdr_void, NULL,
+ (xdrproc_t)xdr_pmaplist, &head, minutetimeout) !=
+ RPC_SUCCESS) {
+ clnt_perror(client, "pmap_getmaps rpc problem");
+ }
+ CLNT_DESTROY(client);
+ }
+ address->sin_port = 0;
+ return (head);
+}
diff --git a/lib/libc/rpc/pmap_getport.c b/lib/libc/rpc/pmap_getport.c
new file mode 100644
index 0000000..ca0aafd
--- /dev/null
+++ b/lib/libc/rpc/pmap_getport.c
@@ -0,0 +1,104 @@
+/* $NetBSD: pmap_getport.c,v 1.16 2000/07/06 03:10:34 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "from: @(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "from: @(#)pmap_getport.c 2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * pmap_getport.c
+ * Client interface to pmap rpc service.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+
+#include <arpa/inet.h>
+#include <net/if.h>
+
+#include <assert.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include "un-namespace.h"
+
+static const struct timeval timeout = { 5, 0 };
+static const struct timeval tottimeout = { 60, 0 };
+
+/*
+ * Find the mapped port for program,version.
+ * Calls the pmap service remotely to do the lookup.
+ * Returns 0 if no map exists.
+ */
+u_short
+pmap_getport(address, program, version, protocol)
+ struct sockaddr_in *address;
+ u_long program;
+ u_long version;
+ u_int protocol;
+{
+ u_short port = 0;
+ int sock = -1;
+ CLIENT *client;
+ struct pmap parms;
+
+ assert(address != NULL);
+
+ address->sin_port = htons(PMAPPORT);
+ client = clntudp_bufcreate(address, PMAPPROG,
+ PMAPVERS, timeout, &sock, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);
+ if (client != NULL) {
+ parms.pm_prog = program;
+ parms.pm_vers = version;
+ parms.pm_prot = protocol;
+ parms.pm_port = 0; /* not needed or used */
+ if (CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT,
+ (xdrproc_t)xdr_pmap,
+ &parms, (xdrproc_t)xdr_u_short, &port, tottimeout) !=
+ RPC_SUCCESS){
+ rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+ } else if (port == 0) {
+ rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+ }
+ CLNT_DESTROY(client);
+ }
+ address->sin_port = 0;
+ return (port);
+}
diff --git a/lib/libc/rpc/pmap_prot.c b/lib/libc/rpc/pmap_prot.c
new file mode 100644
index 0000000..2c01311
--- /dev/null
+++ b/lib/libc/rpc/pmap_prot.c
@@ -0,0 +1,69 @@
+/* $NetBSD: pmap_prot.c,v 1.10 2000/01/22 22:19:18 mycroft Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)pmap_prot.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * pmap_prot.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <assert.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_prot.h>
+#include "un-namespace.h"
+
+
+bool_t
+xdr_pmap(xdrs, regs)
+ XDR *xdrs;
+ struct pmap *regs;
+{
+
+ assert(xdrs != NULL);
+ assert(regs != NULL);
+
+ if (xdr_u_long(xdrs, &regs->pm_prog) &&
+ xdr_u_long(xdrs, &regs->pm_vers) &&
+ xdr_u_long(xdrs, &regs->pm_prot))
+ return (xdr_u_long(xdrs, &regs->pm_port));
+ return (FALSE);
+}
diff --git a/lib/libc/rpc/pmap_prot2.c b/lib/libc/rpc/pmap_prot2.c
new file mode 100644
index 0000000..ae7c7c6
--- /dev/null
+++ b/lib/libc/rpc/pmap_prot2.c
@@ -0,0 +1,143 @@
+/* $NetBSD: pmap_prot2.c,v 1.14 2000/07/06 03:10:34 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)pmap_prot2.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * pmap_prot2.c
+ * Protocol for the local binder service, or pmap.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <assert.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/pmap_prot.h>
+#include "un-namespace.h"
+
+
+/*
+ * What is going on with linked lists? (!)
+ * First recall the link list declaration from pmap_prot.h:
+ *
+ * struct pmaplist {
+ * struct pmap pml_map;
+ * struct pmaplist *pml_map;
+ * };
+ *
+ * Compare that declaration with a corresponding xdr declaration that
+ * is (a) pointer-less, and (b) recursive:
+ *
+ * typedef union switch (bool_t) {
+ *
+ * case TRUE: struct {
+ * struct pmap;
+ * pmaplist_t foo;
+ * };
+ *
+ * case FALSE: struct {};
+ * } pmaplist_t;
+ *
+ * Notice that the xdr declaration has no nxt pointer while
+ * the C declaration has no bool_t variable. The bool_t can be
+ * interpreted as ``more data follows me''; if FALSE then nothing
+ * follows this bool_t; if TRUE then the bool_t is followed by
+ * an actual struct pmap, and then (recursively) by the
+ * xdr union, pamplist_t.
+ *
+ * This could be implemented via the xdr_union primitive, though this
+ * would cause a one recursive call per element in the list. Rather than do
+ * that we can ``unwind'' the recursion
+ * into a while loop and do the union arms in-place.
+ *
+ * The head of the list is what the C programmer wishes to past around
+ * the net, yet is the data that the pointer points to which is interesting;
+ * this sounds like a job for xdr_reference!
+ */
+bool_t
+xdr_pmaplist(xdrs, rp)
+ XDR *xdrs;
+ struct pmaplist **rp;
+{
+ /*
+ * more_elements is pre-computed in case the direction is
+ * XDR_ENCODE or XDR_FREE. more_elements is overwritten by
+ * xdr_bool when the direction is XDR_DECODE.
+ */
+ bool_t more_elements;
+ int freeing;
+ struct pmaplist **next = NULL; /* pacify gcc */
+
+ assert(xdrs != NULL);
+ assert(rp != NULL);
+
+ freeing = (xdrs->x_op == XDR_FREE);
+
+ for (;;) {
+ more_elements = (bool_t)(*rp != NULL);
+ if (! xdr_bool(xdrs, &more_elements))
+ return (FALSE);
+ if (! more_elements)
+ return (TRUE); /* we are done */
+ /*
+ * the unfortunate side effect of non-recursion is that in
+ * the case of freeing we must remember the next object
+ * before we free the current object ...
+ */
+ if (freeing)
+ next = &((*rp)->pml_next);
+ if (! xdr_reference(xdrs, (caddr_t *)rp,
+ (u_int)sizeof(struct pmaplist), (xdrproc_t)xdr_pmap))
+ return (FALSE);
+ rp = (freeing) ? next : &((*rp)->pml_next);
+ }
+}
+
+
+/*
+ * xdr_pmaplist_ptr() is specified to take a PMAPLIST *, but is identical in
+ * functionality to xdr_pmaplist().
+ */
+bool_t
+xdr_pmaplist_ptr(xdrs, rp)
+ XDR *xdrs;
+ struct pmaplist *rp;
+{
+ return xdr_pmaplist(xdrs, (struct pmaplist **)(void *)rp);
+}
diff --git a/lib/libc/rpc/pmap_rmt.c b/lib/libc/rpc/pmap_rmt.c
new file mode 100644
index 0000000..ddcde2e
--- /dev/null
+++ b/lib/libc/rpc/pmap_rmt.c
@@ -0,0 +1,176 @@
+/* $NetBSD: pmap_rmt.c,v 1.29 2000/07/06 03:10:34 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)pmap_rmt.c 2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * pmap_rmt.c
+ * Client interface to pmap rpc service.
+ * remote call and broadcast service
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+
+#include <net/if.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_rmt.h>
+#include "un-namespace.h"
+
+static const struct timeval timeout = { 3, 0 };
+
+/*
+ * pmapper remote-call-service interface.
+ * This routine is used to call the pmapper remote call service
+ * which will look up a service program in the port maps, and then
+ * remotely call that routine with the given parameters. This allows
+ * programs to do a lookup and call in one step.
+*/
+enum clnt_stat
+pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout,
+ port_ptr)
+ struct sockaddr_in *addr;
+ u_long prog, vers, proc;
+ xdrproc_t xdrargs, xdrres;
+ caddr_t argsp, resp;
+ struct timeval tout;
+ u_long *port_ptr;
+{
+ int sock = -1;
+ CLIENT *client;
+ struct rmtcallargs a;
+ struct rmtcallres r;
+ enum clnt_stat stat;
+
+ assert(addr != NULL);
+ assert(port_ptr != NULL);
+
+ addr->sin_port = htons(PMAPPORT);
+ client = clntudp_create(addr, PMAPPROG, PMAPVERS, timeout, &sock);
+ if (client != NULL) {
+ a.prog = prog;
+ a.vers = vers;
+ a.proc = proc;
+ a.args_ptr = argsp;
+ a.xdr_args = xdrargs;
+ r.port_ptr = port_ptr;
+ r.results_ptr = resp;
+ r.xdr_results = xdrres;
+ stat = CLNT_CALL(client, (rpcproc_t)PMAPPROC_CALLIT,
+ (xdrproc_t)xdr_rmtcall_args, &a, (xdrproc_t)xdr_rmtcallres,
+ &r, tout);
+ CLNT_DESTROY(client);
+ } else {
+ stat = RPC_FAILED;
+ }
+ addr->sin_port = 0;
+ return (stat);
+}
+
+
+/*
+ * XDR remote call arguments
+ * written for XDR_ENCODE direction only
+ */
+bool_t
+xdr_rmtcall_args(xdrs, cap)
+ XDR *xdrs;
+ struct rmtcallargs *cap;
+{
+ u_int lenposition, argposition, position;
+
+ assert(xdrs != NULL);
+ assert(cap != NULL);
+
+ if (xdr_u_long(xdrs, &(cap->prog)) &&
+ xdr_u_long(xdrs, &(cap->vers)) &&
+ xdr_u_long(xdrs, &(cap->proc))) {
+ lenposition = XDR_GETPOS(xdrs);
+ if (! xdr_u_long(xdrs, &(cap->arglen)))
+ return (FALSE);
+ argposition = XDR_GETPOS(xdrs);
+ if (! (*(cap->xdr_args))(xdrs, cap->args_ptr))
+ return (FALSE);
+ position = XDR_GETPOS(xdrs);
+ cap->arglen = (u_long)position - (u_long)argposition;
+ XDR_SETPOS(xdrs, lenposition);
+ if (! xdr_u_long(xdrs, &(cap->arglen)))
+ return (FALSE);
+ XDR_SETPOS(xdrs, position);
+ return (TRUE);
+ }
+ return (FALSE);
+}
+
+/*
+ * XDR remote call results
+ * written for XDR_DECODE direction only
+ */
+bool_t
+xdr_rmtcallres(xdrs, crp)
+ XDR *xdrs;
+ struct rmtcallres *crp;
+{
+ caddr_t port_ptr;
+
+ assert(xdrs != NULL);
+ assert(crp != NULL);
+
+ port_ptr = (caddr_t)(void *)crp->port_ptr;
+ if (xdr_reference(xdrs, &port_ptr, sizeof (u_long),
+ (xdrproc_t)xdr_u_long) && xdr_u_long(xdrs, &crp->resultslen)) {
+ crp->port_ptr = (u_long *)(void *)port_ptr;
+ return ((*(crp->xdr_results))(xdrs, crp->results_ptr));
+ }
+ return (FALSE);
+}
diff --git a/lib/libc/rpc/publickey.3 b/lib/libc/rpc/publickey.3
new file mode 100644
index 0000000..d0ad6cc
--- /dev/null
+++ b/lib/libc/rpc/publickey.3
@@ -0,0 +1,53 @@
+.\" @(#)publickey.3r 2.1 88/08/07 4.0 RPCSRC
+.\" $FreeBSD$
+.\"
+.Dd October 6, 1987
+.Dt PUBLICKEY 3
+.Os
+.Sh NAME
+.Nm publickey , getpublickey , getsecretkey
+.Nd "get public or secret key"
+.Sh LIBRARY
+.Lb librpcsvc
+.Sh SYNOPSIS
+.In rpc/rpc.h
+.In rpc/key_prot.h
+.Ft int
+.Fo getpublickey
+.Fa "const char netname[MAXNETNAMELEN+1]"
+.Fa "char publickey[HEXKEYBYTES+1]"
+.Fc
+.Ft int
+.Fo getsecretkey
+.Fa "char netname[MAXNETNAMELEN+1]"
+.Fa "char secretkey[HEXKEYBYTES+1]"
+.Fa "char *passwd"
+.Fc
+.Sh DESCRIPTION
+These routines are used to get public and secret keys from the
+.Tn YP
+database.
+The
+.Fn getsecretkey
+function
+has an extra argument,
+.Fa passwd ,
+which is used to decrypt the encrypted secret key stored in the database.
+Both routines return 1 if they are successful in finding the key, 0 otherwise.
+The keys are returned as
+.Dv NULL Ns \-terminated ,
+hexadecimal strings.
+If the password supplied to
+.Fn getsecretkey
+fails to decrypt the secret key, the routine will return 1 but the
+.Fa secretkey
+argument will be a
+.Dv NULL
+string
+.Pq Dq .
+.Sh SEE ALSO
+.Xr publickey 5
+.Pp
+.%T "RPC Programmer's Manual"
+in
+.Pa /usr/share/doc/psd/23.rpc .
diff --git a/lib/libc/rpc/publickey.5 b/lib/libc/rpc/publickey.5
new file mode 100644
index 0000000..71f4ef6
--- /dev/null
+++ b/lib/libc/rpc/publickey.5
@@ -0,0 +1,42 @@
+.\" $FreeBSD$
+.\" @(#)publickey.5 2.1 88/08/07 4.0 RPCSRC; from 1.6 88/02/29 SMI;
+.Dd October 19, 1987
+.Dt PUBLICKEY 5
+.Os
+.Sh NAME
+.Nm publickey
+.Nd "public key database"
+.Sh SYNOPSIS
+.Pa /etc/publickey
+.Sh DESCRIPTION
+.Pa /etc/publickey
+is the public key database used for secure
+RPC (Remote Procedure Calls).
+Each entry in
+the database consists of a network user
+name (which may either refer to
+a user or a hostname), followed by the user's
+public key (in hex
+notation), a colon, and then the user's
+secret key encrypted with
+its login password (also in hex notation).
+.Pp
+This file is altered either by the user through the
+.Xr chkey 1
+command or by the system administrator through the
+.Xr newkey 8
+command.
+The file
+.Pa /etc/publickey
+should only contain data on the
+.Tn NIS
+master machine, where it
+is converted into the
+.Tn NIS
+database
+.Pa publickey.byname .
+.Sh SEE ALSO
+.Xr chkey 1 ,
+.Xr publickey 3 ,
+.Xr newkey 8 ,
+.Xr ypupdated 8
diff --git a/lib/libc/rpc/rpc.3 b/lib/libc/rpc/rpc.3
new file mode 100644
index 0000000..4fa3e2c
--- /dev/null
+++ b/lib/libc/rpc/rpc.3
@@ -0,0 +1,517 @@
+.\" @(#)rpc.3n 1.31 93/08/31 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" $NetBSD: rpc.3,v 1.10 2000/06/02 23:11:12 fvdl Exp $
+.\" $FreeBSD$
+.Dd May 7, 1993
+.Dt RPC 3
+.Os
+.Sh NAME
+.Nm rpc
+.Nd library routines for remote procedure calls
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In rpc/rpc.h
+.In netconfig.h
+.Sh DESCRIPTION
+These
+routines allow C language programs to make procedure
+calls on other machines across a network.
+First, the client sends a request to the server.
+On receipt of the request, the server calls a dispatch routine
+to perform the requested service, and then sends back a reply.
+.Pp
+All
+RPC routines require the header
+.In rpc/rpc.h .
+Routines that take a
+.Vt "struct netconfig"
+also require that
+.In netconfig.h
+be included.
+.Sh Nettype
+Some of the high-level
+RPC interface routines take a
+.Fa nettype
+string as one of the arguments
+(for example,
+.Fn clnt_create ,
+.Fn svc_create ,
+.Fn rpc_reg ,
+.Fn rpc_call ) .
+This string defines a class of transports which can be used
+for a particular application.
+.Pp
+The
+.Fa nettype
+argument
+can be one of the following:
+.Bl -tag -width datagram_v
+.It netpath
+Choose from the transports which have been
+indicated by their token names in the
+.Ev NETPATH
+environment variable.
+.Ev NETPATH
+is unset or
+.Dv NULL ,
+it defaults to
+.Qq visible .
+.Qq netpath
+is the default
+.Fa nettype .
+.It visible
+Choose the transports which have the visible flag (v)
+set in the
+.Pa /etc/netconfig
+file.
+.It circuit_v
+This is same as
+.Qq visible
+except that it chooses only the connection oriented transports
+(semantics
+.Qq tpi_cots
+or
+.Qq tpi_cots_ord )
+from the entries in the
+.Pa /etc/netconfig
+file.
+.It datagram_v
+This is same as
+.Qq visible
+except that it chooses only the connectionless datagram transports
+(semantics
+.Qq tpi_clts )
+from the entries in the
+.Pa /etc/netconfig
+file.
+.It circuit_n
+This is same as
+.Qq netpath
+except that it chooses only the connection oriented datagram transports
+(semantics
+.Qq tpi_cots
+or
+.Qq tpi_cots_ord ) .
+.It datagram_n
+This is same as
+.Qq netpath
+except that it chooses only the connectionless datagram transports
+(semantics
+.Qq tpi_clts ) .
+.It udp
+This refers to Internet UDP, both version 4 and 6.
+.It tcp
+This refers to Internet TCP, both version 4 and 6.
+.El
+.Pp
+If
+.Fa nettype
+is
+.Dv NULL ,
+it defaults to
+.Qq netpath .
+The transports are tried in left to right order in the
+.Ev NETPATH
+variable or in top to down order in the
+.Pa /etc/netconfig
+file.
+.Sh Derived Types
+The derived types used in the RPC interfaces are defined as follows:
+.Bd -literal
+ typedef uint32_t rpcprog_t;
+ typedef uint32_t rpcvers_t;
+ typedef uint32_t rpcproc_t;
+ typedef uint32_t rpcprot_t;
+ typedef uint32_t rpcport_t;
+ typedef int32_t rpc_inline_t;
+.Ed
+.Sh "Data Structures"
+Some of the data structures used by the
+RPC package are shown below.
+.Sh "The AUTH Structure"
+.Bd -literal
+/*
+ * Authentication info. Opaque to client.
+ */
+struct opaque_auth {
+ enum_t oa_flavor; /* flavor of auth */
+ caddr_t oa_base; /* address of more auth stuff */
+ u_int oa_length; /* not to exceed MAX_AUTH_BYTES */
+};
+
+/*
+ * Auth handle, interface to client side authenticators.
+ */
+typedef struct {
+ struct opaque_auth ah_cred;
+ struct opaque_auth ah_verf;
+ struct auth_ops {
+ void (*ah_nextverf)(\|);
+ int (*ah_marshal)(\|); /* nextverf & serialize */
+ int (*ah_validate)(\|); /* validate verifier */
+ int (*ah_refresh)(\|); /* refresh credentials */
+ void (*ah_destroy)(\|); /* destroy this structure */
+ } *ah_ops;
+ caddr_t ah_private;
+} AUTH;
+.Ed
+.Sh "The CLIENT Structure"
+.Bd -literal
+/*
+ * Client rpc handle.
+ * Created by individual implementations.
+ * Client is responsible for initializing auth.
+ */
+
+typedef struct {
+ AUTH *cl_auth; /* authenticator */
+ struct clnt_ops {
+ enum clnt_stat (*cl_call)(); /* call remote procedure */
+ void (*cl_abort)(); /* abort a call */
+ void (*cl_geterr)(); /* get specific error code */
+ bool_t (*cl_freeres)(); /* frees results */
+ void (*cl_destroy)(); /* destroy this structure */
+ bool_t (*cl_control)(); /* the ioctl() of rpc */
+ } *cl_ops;
+ caddr_t cl_private; /* private stuff */
+ char *cl_netid; /* network identifier */
+ char *cl_tp; /* device name */
+} CLIENT;
+.Ed
+.Sh "The SVCXPRT structure"
+.Bd -literal
+enum xprt_stat {
+ XPRT_DIED,
+ XPRT_MOREREQS,
+ XPRT_IDLE
+};
+
+/*
+ * Server side transport handle
+ */
+typedef struct {
+ int xp_fd; /* file descriptor for the server handle */
+ u_short xp_port; /* obsolete */
+ const struct xp_ops {
+ bool_t (*xp_recv)(); /* receive incoming requests */
+ enum xprt_stat (*xp_stat)(); /* get transport status */
+ bool_t (*xp_getargs)(); /* get arguments */
+ bool_t (*xp_reply)(); /* send reply */
+ bool_t (*xp_freeargs)(); /* free mem allocated for args */
+ void (*xp_destroy)(); /* destroy this struct */
+ } *xp_ops;
+ int xp_addrlen; /* length of remote addr. Obsolete */
+ struct sockaddr_in xp_raddr; /* Obsolete */
+ const struct xp_ops2 {
+ bool_t (*xp_control)(); /* catch-all function */
+ } *xp_ops2;
+ char *xp_tp; /* transport provider device name */
+ char *xp_netid; /* network identifier */
+ struct netbuf xp_ltaddr; /* local transport address */
+ struct netbuf xp_rtaddr; /* remote transport address */
+ struct opaque_auth xp_verf; /* raw response verifier */
+ caddr_t xp_p1; /* private: for use by svc ops */
+ caddr_t xp_p2; /* private: for use by svc ops */
+ caddr_t xp_p3; /* private: for use by svc lib */
+ int xp_type /* transport type */
+} SVCXPRT;
+.Ed
+.Sh "The svc_reg structure"
+.Bd -literal
+struct svc_req {
+ rpcprog_t rq_prog; /* service program number */
+ rpcvers_t rq_vers; /* service protocol version */
+ rpcproc_t rq_proc; /* the desired procedure */
+ struct opaque_auth rq_cred; /* raw creds from the wire */
+ caddr_t rq_clntcred; /* read only cooked cred */
+ SVCXPRT *rq_xprt; /* associated transport */
+};
+.Ed
+.Sh "The XDR structure"
+.Bd -literal
+/*
+ * XDR operations.
+ * XDR_ENCODE causes the type to be encoded into the stream.
+ * XDR_DECODE causes the type to be extracted from the stream.
+ * XDR_FREE can be used to release the space allocated by an XDR_DECODE
+ * request.
+ */
+enum xdr_op {
+ XDR_ENCODE=0,
+ XDR_DECODE=1,
+ XDR_FREE=2
+};
+/*
+ * This is the number of bytes per unit of external data.
+ */
+#define BYTES_PER_XDR_UNIT (4)
+#define RNDUP(x) ((((x) + BYTES_PER_XDR_UNIT - 1) /
+ BYTES_PER_XDR_UNIT) \e * BYTES_PER_XDR_UNIT)
+
+/*
+ * A xdrproc_t exists for each data type which is to be encoded or
+ * decoded. The second argument to the xdrproc_t is a pointer to
+ * an opaque pointer. The opaque pointer generally points to a
+ * structure of the data type to be decoded. If this points to 0,
+ * then the type routines should allocate dynamic storage of the
+ * appropriate size and return it.
+ * bool_t (*xdrproc_t)(XDR *, caddr_t *);
+ */
+typedef bool_t (*xdrproc_t)();
+
+/*
+ * The XDR handle.
+ * Contains operation which is being applied to the stream,
+ * an operations vector for the particular implementation
+ */
+typedef struct {
+ enum xdr_op x_op; /* operation; fast additional param */
+ struct xdr_ops {
+ bool_t (*x_getlong)(); /* get a long from underlying stream */
+ bool_t (*x_putlong)(); /* put a long to underlying stream */
+ bool_t (*x_getbytes)(); /* get bytes from underlying stream */
+ bool_t (*x_putbytes)(); /* put bytes to underlying stream */
+ u_int (*x_getpostn)(); /* returns bytes off from beginning */
+ bool_t (*x_setpostn)(); /* lets you reposition the stream */
+ long * (*x_inline)(); /* buf quick ptr to buffered data */
+ void (*x_destroy)(); /* free privates of this xdr_stream */
+ } *x_ops;
+ caddr_t x_public; /* users' data */
+ caddr_t x_private; /* pointer to private data */
+ caddr_t x_base; /* private used for position info */
+ u_int x_handy; /* extra private word */
+} XDR;
+
+/*
+ * The netbuf structure. This structure is defined in <xti.h> on SysV
+ * systems, but NetBSD / FreeBSD do not use XTI.
+ *
+ * Usually, buf will point to a struct sockaddr, and len and maxlen
+ * will contain the length and maximum length of that socket address,
+ * respectively.
+ */
+struct netbuf {
+ unsigned int maxlen;
+ unsigned int len;
+ void *buf;
+};
+
+/*
+ * The format of the address and options arguments of the XTI t_bind call.
+ * Only provided for compatibility, it should not be used other than
+ * as an argument to svc_tli_create().
+ */
+
+struct t_bind {
+ struct netbuf addr;
+ unsigned int qlen;
+};
+.Ed
+.Sh "Index to Routines"
+The following table lists RPC routines and the manual reference
+pages on which they are described:
+.Pp
+.Bl -tag -width "authunix_create_default()" -compact
+.It Em "RPC Routine"
+.Em "Manual Reference Page"
+.Pp
+.It Fn auth_destroy
+.Xr rpc_clnt_auth 3
+.It Fn authdes_create
+.Xr rpc_soc 3
+.It Fn authnone_create
+.Xr rpc_clnt_auth 3
+.It Fn authsys_create
+.Xr rpc_clnt_auth 3
+.It Fn authsys_create_default
+.Xr rpc_clnt_auth 3
+.It Fn authunix_create
+.Xr rpc_soc 3
+.It Fn authunix_create_default
+.Xr rpc_soc 3
+.It Fn callrpc
+.Xr rpc_soc 3
+.It Fn clnt_broadcast
+.Xr rpc_soc 3
+.It Fn clnt_call
+.Xr rpc_clnt_calls 3
+.It Fn clnt_control
+.Xr rpc_clnt_create 3
+.It Fn clnt_create
+.Xr rpc_clnt_create 3
+.It Fn clnt_create_timed
+.Xr rpc_clnt_create 3
+.It Fn clnt_create_vers
+.Xr rpc_clnt_create 3
+.It Fn clnt_create_vers_timed
+.Xr rpc_clnt_create 3
+.It Fn clnt_destroy
+.Xr rpc_clnt_create 3
+.It Fn clnt_dg_create
+.Xr rpc_clnt_create 3
+.It Fn clnt_freeres
+.Xr rpc_clnt_calls 3
+.It Fn clnt_geterr
+.Xr rpc_clnt_calls 3
+.It Fn clnt_pcreateerror
+.Xr rpc_clnt_create 3
+.It Fn clnt_perrno
+.Xr rpc_clnt_calls 3
+.It Fn clnt_perror
+.Xr rpc_clnt_calls 3
+.It Fn clnt_raw_create
+.Xr rpc_clnt_create 3
+.It Fn clnt_spcreateerror
+.Xr rpc_clnt_create 3
+.It Fn clnt_sperrno
+.Xr rpc_clnt_calls 3
+.It Fn clnt_sperror
+.Xr rpc_clnt_calls 3
+.It Fn clnt_tli_create
+.Xr rpc_clnt_create 3
+.It Fn clnt_tp_create
+.Xr rpc_clnt_create 3
+.It Fn clnt_tp_create_timed
+.Xr rpc_clnt_create 3
+.It Fn clnt_udpcreate
+.Xr rpc_soc 3
+.It Fn clnt_vc_create
+.Xr rpc_clnt_create 3
+.It Fn clntraw_create
+.Xr rpc_soc 3
+.It Fn clnttcp_create
+.Xr rpc_soc 3
+.It Fn clntudp_bufcreate
+.Xr rpc_soc 3
+.It Fn get_myaddress
+.Xr rpc_soc 3
+.It Fn pmap_getmaps
+.Xr rpc_soc 3
+.It Fn pmap_getport
+.Xr rpc_soc 3
+.It Fn pmap_rmtcall
+.Xr rpc_soc 3
+.It Fn pmap_set
+.Xr rpc_soc 3
+.It Fn pmap_unset
+.Xr rpc_soc 3
+.It Fn registerrpc
+.Xr rpc_soc 3
+.It Fn rpc_broadcast
+.Xr rpc_clnt_calls 3
+.It Fn rpc_broadcast_exp
+.Xr rpc_clnt_calls 3
+.It Fn rpc_call
+.Xr rpc_clnt_calls 3
+.It Fn rpc_reg
+.Xr rpc_svc_calls 3
+.It Fn svc_create
+.Xr rpc_svc_create 3
+.It Fn svc_destroy
+.Xr rpc_svc_create 3
+.It Fn svc_dg_create
+.Xr rpc_svc_create 3
+.It Fn svc_dg_enablecache
+.Xr rpc_svc_calls 3
+.It Fn svc_fd_create
+.Xr rpc_svc_create 3
+.It Fn svc_fds
+.Xr rpc_soc 3
+.It Fn svc_freeargs
+.Xr rpc_svc_reg 3
+.It Fn svc_getargs
+.Xr rpc_svc_reg 3
+.It Fn svc_getcaller
+.Xr rpc_soc 3
+.It Fn svc_getreq
+.Xr rpc_soc 3
+.It Fn svc_getreqset
+.Xr rpc_svc_calls 3
+.It Fn svc_getrpccaller
+.Xr rpc_svc_calls 3
+.It Fn svc_kerb_reg
+.Xr kerberos_rpc 3
+.It Fn svc_raw_create
+.Xr rpc_svc_create 3
+.It Fn svc_reg
+.Xr rpc_svc_calls 3
+.It Fn svc_register
+.Xr rpc_soc 3
+.It Fn svc_run
+.Xr rpc_svc_reg 3
+.It Fn svc_sendreply
+.Xr rpc_svc_reg 3
+.It Fn svc_tli_create
+.Xr rpc_svc_create 3
+.It Fn svc_tp_create
+.Xr rpc_svc_create 3
+.It Fn svc_unreg
+.Xr rpc_svc_calls 3
+.It Fn svc_unregister
+.Xr rpc_soc 3
+.It Fn svc_vc_create
+.Xr rpc_svc_create 3
+.It Fn svcerr_auth
+.Xr rpc_svc_err 3
+.It Fn svcerr_decode
+.Xr rpc_svc_err 3
+.It Fn svcerr_noproc
+.Xr rpc_svc_err 3
+.It Fn svcerr_noprog
+.Xr rpc_svc_err 3
+.It Fn svcerr_progvers
+.Xr rpc_svc_err 3
+.It Fn svcerr_systemerr
+.Xr rpc_svc_err 3
+.It Fn svcerr_weakauth
+.Xr rpc_svc_err 3
+.It Fn svcfd_create
+.Xr rpc_soc 3
+.It Fn svcraw_create
+.Xr rpc_soc 3
+.It Fn svctcp_create
+.Xr rpc_soc 3
+.It Fn svcudp_bufcreate
+.Xr rpc_soc 3
+.It Fn svcudp_create
+.Xr rpc_soc 3
+.It Fn xdr_accepted_reply
+.Xr rpc_xdr 3
+.It Fn xdr_authsys_parms
+.Xr rpc_xdr 3
+.It Fn xdr_authunix_parms
+.Xr rpc_soc 3
+.It Fn xdr_callhdr
+.Xr rpc_xdr 3
+.It Fn xdr_callmsg
+.Xr rpc_xdr 3
+.It Fn xdr_opaque_auth
+.Xr rpc_xdr 3
+.It Fn xdr_rejected_reply
+.Xr rpc_xdr 3
+.It Fn xdr_replymsg
+.Xr rpc_xdr 3
+.It Fn xprt_register
+.Xr rpc_svc_calls 3
+.It Fn xprt_unregister
+.Xr rpc_svc_calls 3
+.El
+.Sh FILES
+.Bl -tag -width /etc/netconfig
+.It Pa /etc/netconfig
+.El
+.Sh SEE ALSO
+.Xr getnetconfig 3 ,
+.Xr getnetpath 3 ,
+.Xr rpcbind 3 ,
+.Xr rpc_clnt_auth 3 ,
+.Xr rpc_clnt_calls 3 ,
+.Xr rpc_clnt_create 3 ,
+.Xr rpc_svc_calls 3 ,
+.Xr rpc_svc_create 3 ,
+.Xr rpc_svc_err 3 ,
+.Xr rpc_svc_reg 3 ,
+.Xr rpc_xdr 3 ,
+.Xr xdr 3 ,
+.Xr netconfig 5
diff --git a/lib/libc/rpc/rpc.5 b/lib/libc/rpc/rpc.5
new file mode 100644
index 0000000..398d9aa
--- /dev/null
+++ b/lib/libc/rpc/rpc.5
@@ -0,0 +1,59 @@
+.\" $NetBSD: rpc.5,v 1.3 2000/06/15 20:05:54 fvdl Exp $
+.\" $FreeBSD$
+.\" @(#)rpc.4 1.17 93/08/30 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.Dd December 10, 1991
+.Dt RPC 5
+.Os
+.Sh NAME
+.Nm rpc
+.Nd rpc program number data base
+.Sh SYNOPSIS
+.Pa /etc/rpc
+.Sh DESCRIPTION
+The
+.Nm
+file contains user readable names that
+can be used in place of RPC program numbers.
+For each RPC program a single line should be present
+with the following information:
+.Pp
+.Bl -enum -compact
+.It
+name of the RPC program
+.It
+RPC program number
+.It
+aliases
+.El
+.Pp
+Items are separated by any number of blanks and/or
+tab characters.
+A hash
+.Pq Dq Li #
+indicates the beginning of a comment; characters up to the end of
+the line are not interpreted by routines which search the file.
+.Sh FILES
+.Bl -tag -width /etc/nsswitch.conf -compact
+.It Pa /etc/nsswitch.conf
+.El
+.Sh EXAMPLES
+Below is an example of an RPC database:
+.Bd -literal
+#
+# rpc
+#
+rpcbind 100000 portmap sunrpc portmapper
+rusersd 100002 rusers
+nfs 100003 nfsprog
+mountd 100005 mount showmount
+walld 100008 rwall shutdown
+sprayd 100012 spray
+llockmgr 100020
+nlockmgr 100021
+status 100024
+bootparam 100026
+keyserv 100029 keyserver
+.Ed
+.Sh SEE ALSO
+.Xr getrpcent 3
diff --git a/lib/libc/rpc/rpc_callmsg.c b/lib/libc/rpc/rpc_callmsg.c
new file mode 100644
index 0000000..ad1bdb3
--- /dev/null
+++ b/lib/libc/rpc/rpc_callmsg.c
@@ -0,0 +1,207 @@
+/* $NetBSD: rpc_callmsg.c,v 1.16 2000/07/14 08:40:42 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)rpc_callmsg.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * rpc_callmsg.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ */
+
+#include "namespace.h"
+#include <assert.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rpc/rpc.h>
+#include "un-namespace.h"
+
+/*
+ * XDR a call message
+ */
+bool_t
+xdr_callmsg(xdrs, cmsg)
+ XDR *xdrs;
+ struct rpc_msg *cmsg;
+{
+ enum msg_type *prm_direction;
+ int32_t *buf;
+ struct opaque_auth *oa;
+
+ assert(xdrs != NULL);
+ assert(cmsg != NULL);
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (cmsg->rm_call.cb_cred.oa_length > MAX_AUTH_BYTES) {
+ return (FALSE);
+ }
+ if (cmsg->rm_call.cb_verf.oa_length > MAX_AUTH_BYTES) {
+ return (FALSE);
+ }
+ buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT
+ + RNDUP(cmsg->rm_call.cb_cred.oa_length)
+ + 2 * BYTES_PER_XDR_UNIT
+ + RNDUP(cmsg->rm_call.cb_verf.oa_length));
+ if (buf != NULL) {
+ IXDR_PUT_INT32(buf, cmsg->rm_xid);
+ IXDR_PUT_ENUM(buf, cmsg->rm_direction);
+ if (cmsg->rm_direction != CALL) {
+ return (FALSE);
+ }
+ IXDR_PUT_INT32(buf, cmsg->rm_call.cb_rpcvers);
+ if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
+ return (FALSE);
+ }
+ IXDR_PUT_INT32(buf, cmsg->rm_call.cb_prog);
+ IXDR_PUT_INT32(buf, cmsg->rm_call.cb_vers);
+ IXDR_PUT_INT32(buf, cmsg->rm_call.cb_proc);
+ oa = &cmsg->rm_call.cb_cred;
+ IXDR_PUT_ENUM(buf, oa->oa_flavor);
+ IXDR_PUT_INT32(buf, oa->oa_length);
+ if (oa->oa_length) {
+ memmove(buf, oa->oa_base, oa->oa_length);
+ buf += RNDUP(oa->oa_length) / sizeof (int32_t);
+ }
+ oa = &cmsg->rm_call.cb_verf;
+ IXDR_PUT_ENUM(buf, oa->oa_flavor);
+ IXDR_PUT_INT32(buf, oa->oa_length);
+ if (oa->oa_length) {
+ memmove(buf, oa->oa_base, oa->oa_length);
+ /* no real need....
+ buf += RNDUP(oa->oa_length) / sizeof (int32_t);
+ */
+ }
+ return (TRUE);
+ }
+ }
+ if (xdrs->x_op == XDR_DECODE) {
+ buf = XDR_INLINE(xdrs, 8 * BYTES_PER_XDR_UNIT);
+ if (buf != NULL) {
+ cmsg->rm_xid = IXDR_GET_U_INT32(buf);
+ cmsg->rm_direction = IXDR_GET_ENUM(buf, enum msg_type);
+ if (cmsg->rm_direction != CALL) {
+ return (FALSE);
+ }
+ cmsg->rm_call.cb_rpcvers = IXDR_GET_U_INT32(buf);
+ if (cmsg->rm_call.cb_rpcvers != RPC_MSG_VERSION) {
+ return (FALSE);
+ }
+ cmsg->rm_call.cb_prog = IXDR_GET_U_INT32(buf);
+ cmsg->rm_call.cb_vers = IXDR_GET_U_INT32(buf);
+ cmsg->rm_call.cb_proc = IXDR_GET_U_INT32(buf);
+ oa = &cmsg->rm_call.cb_cred;
+ oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+ oa->oa_length = (u_int)IXDR_GET_U_INT32(buf);
+ if (oa->oa_length) {
+ if (oa->oa_length > MAX_AUTH_BYTES) {
+ return (FALSE);
+ }
+ if (oa->oa_base == NULL) {
+ oa->oa_base = (caddr_t)
+ mem_alloc(oa->oa_length);
+ if (oa->oa_base == NULL)
+ return (FALSE);
+ }
+ buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
+ if (buf == NULL) {
+ if (xdr_opaque(xdrs, oa->oa_base,
+ oa->oa_length) == FALSE) {
+ return (FALSE);
+ }
+ } else {
+ memmove(oa->oa_base, buf,
+ oa->oa_length);
+ /* no real need....
+ buf += RNDUP(oa->oa_length) /
+ sizeof (int32_t);
+ */
+ }
+ }
+ oa = &cmsg->rm_call.cb_verf;
+ buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (xdr_enum(xdrs, &oa->oa_flavor) == FALSE ||
+ xdr_u_int(xdrs, &oa->oa_length) == FALSE) {
+ return (FALSE);
+ }
+ } else {
+ oa->oa_flavor = IXDR_GET_ENUM(buf, enum_t);
+ oa->oa_length = (u_int)IXDR_GET_U_INT32(buf);
+ }
+ if (oa->oa_length) {
+ if (oa->oa_length > MAX_AUTH_BYTES) {
+ return (FALSE);
+ }
+ if (oa->oa_base == NULL) {
+ oa->oa_base = (caddr_t)
+ mem_alloc(oa->oa_length);
+ if (oa->oa_base == NULL)
+ return (FALSE);
+ }
+ buf = XDR_INLINE(xdrs, RNDUP(oa->oa_length));
+ if (buf == NULL) {
+ if (xdr_opaque(xdrs, oa->oa_base,
+ oa->oa_length) == FALSE) {
+ return (FALSE);
+ }
+ } else {
+ memmove(oa->oa_base, buf,
+ oa->oa_length);
+ /* no real need...
+ buf += RNDUP(oa->oa_length) /
+ sizeof (int32_t);
+ */
+ }
+ }
+ return (TRUE);
+ }
+ }
+ prm_direction = &cmsg->rm_direction;
+ if (
+ xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
+ xdr_enum(xdrs, (enum_t *) prm_direction) &&
+ (cmsg->rm_direction == CALL) &&
+ xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+ (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) &&
+ xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) &&
+ xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)) &&
+ xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_proc)) &&
+ xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) )
+ return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf)));
+ return (FALSE);
+}
diff --git a/lib/libc/rpc/rpc_clnt_auth.3 b/lib/libc/rpc/rpc_clnt_auth.3
new file mode 100644
index 0000000..863707e
--- /dev/null
+++ b/lib/libc/rpc/rpc_clnt_auth.3
@@ -0,0 +1,96 @@
+.\" @(#)rpc_clnt_auth.3n 1.21 93/05/07 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" @(#)rpc_clnt_auth 1.4 89/07/20 SMI;
+.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
+.\" $NetBSD: rpc_clnt_auth.3,v 1.1 2000/06/03 09:29:50 fvdl Exp $
+.\" $FreeBSD$
+.Dd May 7, 1993
+.Dt RPC_CLNT_AUTH 3
+.Os
+.Sh NAME
+.Nm auth_destroy ,
+.Nm authnone_create ,
+.Nm authsys_create ,
+.Nm authsys_create_default
+.Nd library routines for client side remote procedure call authentication
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In rpc/rpc.h
+.Ft "void"
+.Fn auth_destroy "AUTH *auth"
+.Ft "AUTH *"
+.Fn authnone_create "void"
+.Ft "AUTH *"
+.Fn authsys_create "const char *host" "const uid_t uid" "const gid_t gid" "const int len" "const gid_t *aup_gids"
+.Ft "AUTH *"
+.Fn authsys_create_default "void"
+.Sh DESCRIPTION
+These routines are part of the
+RPC library that allows C language programs to make procedure
+calls on other machines across the network,
+with desired authentication.
+.Pp
+These routines are normally called after creating the
+.Vt CLIENT
+handle.
+The
+.Va cl_auth
+field of the
+.Vt CLIENT
+structure should be initialized by the
+.Vt AUTH
+structure returned by some of the following routines.
+The client's authentication information
+is passed to the server when the
+RPC
+call is made.
+.Pp
+Only the
+.Dv NULL
+and the
+.Dv SYS
+style of authentication is discussed here.
+.Sh Routines
+.Bl -tag -width authsys_create_default()
+.It Fn auth_destroy
+A function macro that destroys the authentication
+information associated with
+.Fa auth .
+Destruction usually involves deallocation
+of private data structures.
+The use of
+.Fa auth
+is undefined after calling
+.Fn auth_destroy .
+.It Fn authnone_create
+Create and return an RPC
+authentication handle that passes nonusable
+authentication information with each remote procedure call.
+This is the default authentication used by RPC.
+.It Fn authsys_create
+Create and return an RPC authentication handle that contains
+.Dv AUTH_SYS
+authentication information.
+The
+.Fa host
+argument
+is the name of the machine on which the information was
+created;
+.Fa uid
+is the user's user ID;
+.Fa gid
+is the user's current group ID;
+.Fa len
+and
+.Fa aup_gids
+refer to a counted array of groups to which the user belongs.
+.It Fn authsys_create_default
+Call
+.Fn authsys_create
+with the appropriate arguments.
+.El
+.Sh SEE ALSO
+.Xr rpc 3 ,
+.Xr rpc_clnt_calls 3 ,
+.Xr rpc_clnt_create 3
diff --git a/lib/libc/rpc/rpc_clnt_calls.3 b/lib/libc/rpc/rpc_clnt_calls.3
new file mode 100644
index 0000000..213a7d1
--- /dev/null
+++ b/lib/libc/rpc/rpc_clnt_calls.3
@@ -0,0 +1,316 @@
+.\" @(#)rpc_clnt_calls.3n 1.30 93/08/31 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" @(#)rpc_clnt_calls 1.4 89/07/20 SMI;
+.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
+.\" $FreeBSD$
+.Dd May 7, 1993
+.Dt RPC_CLNT_CALLS 3
+.Os
+.Sh NAME
+.Nm rpc_clnt_calls ,
+.Nm clnt_call ,
+.Nm clnt_freeres ,
+.Nm clnt_geterr ,
+.Nm clnt_perrno ,
+.Nm clnt_perror ,
+.Nm clnt_sperrno ,
+.Nm clnt_sperror ,
+.Nm rpc_broadcast ,
+.Nm rpc_broadcast_exp ,
+.Nm rpc_call
+.Nd library routines for client side calls
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In rpc/rpc.h
+.Ft "enum clnt_stat"
+.Fn clnt_call "CLIENT *clnt" "const rpcproc_t procnum" "const xdrproc_t inproc" "const caddr_t in" "const xdrproc_t outproc" "caddr_t out" "const struct timeval tout"
+.Ft bool_t
+.Fn clnt_freeres "CLIENT *clnt" "const xdrproc_t outproc" "caddr_t out"
+.Ft void
+.Fn clnt_geterr "const CLIENT * clnt" "struct rpc_err * errp"
+.Ft void
+.Fn clnt_perrno "const enum clnt_stat stat"
+.Ft void
+.Fn clnt_perror "CLIENT *clnt" "const char *s"
+.Ft "char *"
+.Fn clnt_sperrno "const enum clnt_stat stat"
+.Ft "char *"
+.Fn clnt_sperror "CLIENT *clnt" "const char * s"
+.Ft "enum clnt_stat"
+.Fo rpc_broadcast
+.Fa "const rpcprog_t prognum" "const rpcvers_t versnum"
+.Fa "const rpcproc_t procnum" "const xdrproc_t inproc"
+.Fa "const caddr_t in" "const xdrproc_t outproc" "caddr_t out"
+.Fa "const resultproc_t eachresult" "const char *nettype"
+.Fc
+.Ft "enum clnt_stat"
+.Fo rpc_broadcast_exp
+.Fa "const rpcprog_t prognum" "const rpcvers_t versnum"
+.Fa "const rpcproc_t procnum" "const xdrproc_t xargs"
+.Fa "caddr_t argsp" "const xdrproc_t xresults"
+.Fa "caddr_t resultsp" "const resultproc_t eachresult"
+.Fa "const int inittime" "const int waittime"
+.Fa "const char * nettype"
+.Fc
+.Ft "enum clnt_stat"
+.Fo rpc_call
+.Fa "const char *host" "const rpcprog_t prognum"
+.Fa "const rpcvers_t versnum" "const rpcproc_t procnum"
+.Fa "const xdrproc_t inproc" "const char *in"
+.Fa "const xdrproc_t outproc" "char *out" "const char *nettype"
+.Fc
+.Sh DESCRIPTION
+RPC library routines allow C language programs to make procedure
+calls on other machines across the network.
+First, the client calls a procedure to send a request to the server.
+Upon receipt of the request, the server calls a dispatch routine
+to perform the requested service, and then sends back a reply.
+.Pp
+The
+.Fn clnt_call ,
+.Fn rpc_call ,
+and
+.Fn rpc_broadcast
+routines handle the client side of the procedure call.
+The remaining routines deal with error handling in the case of errors.
+.Pp
+Some of the routines take a
+.Vt CLIENT
+handle as one of the arguments.
+A
+.Vt CLIENT
+handle can be created by an RPC creation routine such as
+.Fn clnt_create
+(see
+.Xr rpc_clnt_create 3 ) .
+.Pp
+These routines are safe for use in multithreaded applications.
+.Vt CLIENT
+handles can be shared between threads, however in this implementation
+requests by different threads are serialized (that is, the first request will
+receive its results before the second request is sent).
+.Sh Routines
+See
+.Xr rpc 3
+for the definition of the
+.Vt CLIENT
+data structure.
+.Bl -tag -width XXXXX
+.It Fn clnt_call
+A function macro that calls the remote procedure
+.Fa procnum
+associated with the client handle,
+.Fa clnt ,
+which is obtained with an RPC
+client creation routine such as
+.Fn clnt_create
+(see
+.Xr rpc_clnt_create 3 ) .
+The
+.Fa inproc
+argument
+is the XDR function used to encode the procedure's arguments, and
+.Fa outproc
+is the XDR function used to decode the procedure's results;
+.Fa in
+is the address of the procedure's argument(s), and
+.Fa out
+is the address of where to place the result(s).
+The
+.Fa tout
+argument
+is the time allowed for results to be returned, which is overridden by
+a time-out set explicitly through
+.Fn clnt_control ,
+see
+.Xr rpc_clnt_create 3 .
+If the remote call succeeds, the status returned is
+.Dv RPC_SUCCESS ,
+otherwise an appropriate status is returned.
+.It Fn clnt_freeres
+A function macro that frees any data allocated by the
+RPC/XDR system when it decoded the results of an RPC call.
+The
+.Fa out
+argument
+is the address of the results, and
+.Fa outproc
+is the XDR routine describing the results.
+This routine returns 1 if the results were successfully freed,
+and 0 otherwise.
+.It Fn clnt_geterr
+A function macro that copies the error structure out of the client
+handle to the structure at address
+.Fa errp .
+.It Fn clnt_perrno
+Print a message to standard error corresponding
+to the condition indicated by
+.Fa stat .
+A newline is appended.
+Normally used after a procedure call fails for a routine
+for which a client handle is not needed, for instance
+.Fn rpc_call .
+.It Fn clnt_perror
+Print a message to the standard error indicating why an
+RPC call failed;
+.Fa clnt
+is the handle used to do the call.
+The message is prepended with string
+.Fa s
+and a colon.
+A newline is appended.
+Normally used after a remote procedure call fails
+for a routine which requires a client handle,
+for instance
+.Fn clnt_call .
+.It Fn clnt_sperrno
+Take the same arguments as
+.Fn clnt_perrno ,
+but instead of sending a message to the standard error
+indicating why an RPC
+call failed, return a pointer to a string which contains the message.
+The
+.Fn clnt_sperrno
+function
+is normally used instead of
+.Fn clnt_perrno
+when the program does not have a standard error (as a program
+running as a server quite likely does not), or if the programmer
+does not want the message to be output with
+.Fn printf
+(see
+.Xr printf 3 ) ,
+or if a message format different than that supported by
+.Fn clnt_perrno
+is to be used.
+Note:
+unlike
+.Fn clnt_sperror
+and
+.Fn clnt_spcreateerror
+(see
+.Xr rpc_clnt_create 3 ) ,
+.Fn clnt_sperrno
+does not return pointer to static data so the
+result will not get overwritten on each call.
+.It Fn clnt_sperror
+Like
+.Fn clnt_perror ,
+except that (like
+.Fn clnt_sperrno )
+it returns a string instead of printing to standard error.
+However,
+.Fn clnt_sperror
+does not append a newline at the end of the message.
+Warning:
+returns pointer to a buffer that is overwritten
+on each call.
+.It Fn rpc_broadcast
+Like
+.Fn rpc_call ,
+except the call message is broadcast to
+all the connectionless transports specified by
+.Fa nettype .
+If
+.Fa nettype
+is
+.Dv NULL ,
+it defaults to
+.Qq netpath .
+Each time it receives a response,
+this routine calls
+.Fn eachresult ,
+whose form is:
+.Ft bool_t
+.Fn eachresult "caddr_t out" "const struct netbuf * addr" "const struct netconfig * netconf"
+where
+.Fa out
+is the same as
+.Fa out
+passed to
+.Fn rpc_broadcast ,
+except that the remote procedure's output is decoded there;
+.Fa addr
+points to the address of the machine that sent the results, and
+.Fa netconf
+is the netconfig structure of the transport on which the remote
+server responded.
+If
+.Fn eachresult
+returns 0,
+.Fn rpc_broadcast
+waits for more replies;
+otherwise it returns with appropriate status.
+Warning:
+broadcast file descriptors are limited in size to the
+maximum transfer size of that transport.
+For Ethernet, this value is 1500 bytes.
+The
+.Fn rpc_broadcast
+function
+uses
+.Dv AUTH_SYS
+credentials by default (see
+.Xr rpc_clnt_auth 3 ) .
+.It Fn rpc_broadcast_exp
+Like
+.Fn rpc_broadcast ,
+except that the initial timeout,
+.Fa inittime
+and the maximum timeout,
+.Fa waittime
+are specified in milliseconds.
+The
+.Fa inittime
+argument
+is the initial time that
+.Fn rpc_broadcast_exp
+waits before resending the request.
+After the first resend, the re-transmission interval
+increases exponentially until it exceeds
+.Fa waittime .
+.It Fn rpc_call
+Call the remote procedure associated with
+.Fa prognum ,
+.Fa versnum ,
+and
+.Fa procnum
+on the machine,
+.Fa host .
+The
+.Fa inproc
+argument
+is used to encode the procedure's arguments, and
+.Fa outproc
+is used to decode the procedure's results;
+.Fa in
+is the address of the procedure's argument(s), and
+.Fa out
+is the address of where to place the result(s).
+The
+.Fa nettype
+argument
+can be any of the values listed on
+.Xr rpc 3 .
+This routine returns
+.Dv RPC_SUCCESS
+if it succeeds,
+or an appropriate status is returned.
+Use the
+.Fn clnt_perrno
+routine to translate failure status into error messages.
+Warning:
+.Fn rpc_call
+uses the first available transport belonging
+to the class
+.Fa nettype ,
+on which it can create a connection.
+You do not have control of timeouts or authentication
+using this routine.
+.El
+.Sh SEE ALSO
+.Xr printf 3 ,
+.Xr rpc 3 ,
+.Xr rpc_clnt_auth 3 ,
+.Xr rpc_clnt_create 3
diff --git a/lib/libc/rpc/rpc_clnt_create.3 b/lib/libc/rpc/rpc_clnt_create.3
new file mode 100644
index 0000000..079c9eb
--- /dev/null
+++ b/lib/libc/rpc/rpc_clnt_create.3
@@ -0,0 +1,514 @@
+.\" @(#)rpc_clnt_create.3n 1.36 93/08/31 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" @(#)rpc_clnt_create 1.5 89/07/24 SMI;
+.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
+.\" $NetBSD: rpc_clnt_create.3,v 1.2 2000/06/20 00:53:08 fvdl Exp $
+.\" $FreeBSD$
+.Dd May 7, 1993
+.Dt RPC_CLNT_CREATE 3
+.Os
+.Sh NAME
+.Nm rpc_clnt_create ,
+.Nm clnt_control ,
+.Nm clnt_create ,
+.Nm clnt_create_timed ,
+.Nm clnt_create_vers ,
+.Nm clnt_create_vers_timed ,
+.Nm clnt_destroy ,
+.Nm clnt_dg_create ,
+.Nm clnt_pcreateerror ,
+.Nm clnt_raw_create ,
+.Nm clnt_spcreateerror ,
+.Nm clnt_tli_create ,
+.Nm clnt_tp_create ,
+.Nm clnt_tp_create_timed ,
+.Nm clnt_vc_create ,
+.Nm rpc_createerr
+.Nd "library routines for dealing with creation and manipulation of"
+.Vt CLIENT
+handles
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In rpc/rpc.h
+.Ft bool_t
+.Fn clnt_control "CLIENT *clnt" "const u_int req" "char *info"
+.Ft "CLIENT *"
+.Fn clnt_create "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const char *nettype"
+.Ft "CLIENT *"
+.Fn clnt_create_timed "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const char *nettype" "const struct timeval *timeout"
+.Ft "CLIENT *"
+.Fn clnt_create_vers "const char * host" "const rpcprog_t prognum" "rpcvers_t *vers_outp" "const rpcvers_t vers_low" "const rpcvers_t vers_high" "const char *nettype"
+.Ft "CLIENT *"
+.Fn clnt_create_vers_timed "const char * host" "const rpcprog_t prognum" "rpcvers_t *vers_outp" "const rpcvers_t vers_low" "const rpcvers_t vers_high" "const char *nettype" "const struct timeval *timeout"
+.Ft void
+.Fn clnt_destroy "CLIENT *clnt"
+.Ft "CLIENT *"
+.Fn clnt_dg_create "const int fildes" "const struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "const u_int sendsz" "const u_int recvsz"
+.Ft void
+.Fn clnt_pcreateerror "const char *s"
+.Ft "char *"
+.Fn clnt_spcreateerror "const char *s"
+.Ft "CLIENT *"
+.Fn clnt_raw_create "const rpcprog_t prognum" "const rpcvers_t versnum"
+.Ft "CLIENT *"
+.Fn clnt_tli_create "const int fildes" "const struct netconfig *netconf" "struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "const u_int sendsz" "const u_int recvsz"
+.Ft "CLIENT *"
+.Fn clnt_tp_create "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf"
+.Ft "CLIENT *"
+.Fn clnt_tp_create_timed "const char * host" "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" "const struct timeval *timeout"
+.Ft "CLIENT *"
+.Fn clnt_vc_create "const int fildes" "const struct netbuf *svcaddr" "const rpcprog_t prognum" "const rpcvers_t versnum" "u_int sendsz" "u_int recvsz"
+.Sh DESCRIPTION
+RPC library routines allow C language programs to make procedure
+calls on other machines across the network.
+First a
+.Vt CLIENT
+handle is created and then the client calls a procedure to send a
+request to the server.
+On receipt of the request, the server calls a dispatch routine
+to perform the requested service, and then sends a reply.
+.Sh Routines
+.Bl -tag -width YYYYYYY
+.It Fn clnt_control
+A function macro to change or retrieve various information
+about a client object.
+The
+.Fa req
+argument
+indicates the type of operation, and
+.Fa info
+is a pointer to the information.
+For both connectionless and connection-oriented transports,
+the supported values of
+.Fa req
+and their argument types and what they do are:
+.Bl -column "CLSET_FD_NCLOSE" "struct timeval *" "set total timeout"
+.It Dv CLSET_TIMEOUT Ta "struct timeval *" Ta "set total timeout"
+.It Dv CLGET_TIMEOUT Ta "struct timeval *" Ta "get total timeout"
+.El
+.Pp
+Note:
+if you set the timeout using
+.Fn clnt_control ,
+the timeout argument passed by
+.Fn clnt_call
+is ignored in all subsequent calls.
+.Pp
+Note:
+If you set the timeout value to 0,
+.Fn clnt_control
+immediately returns an error
+.Pq Dv RPC_TIMEDOUT .
+Set the timeout argument to 0 for batching calls.
+.Bl -column CLSET_FD_NCLOSE "struct timeval *"
+.It Dv CLGET_SVC_ADDR Ta "struct netbuf *" Ta "get servers address"
+.It Dv CLGET_FD Ta "int *" Ta "get fd from handle"
+.It Dv CLSET_FD_CLOSE Ta "void" Ta "close fd on destroy"
+.It Dv CLSET_FD_NCLOSE Ta void Ta "do not close fd on destroy"
+.It Dv CLGET_VERS Ta "uint32_t *" Ta "get RPC program version"
+.It Dv CLSET_VERS Ta "uint32_t *" Ta "set RPC program version"
+.It Dv CLGET_XID Ta "uint32_t *" Ta "get XID of previous call"
+.It Dv CLSET_XID Ta "uint32_t *" Ta "set XID of next call"
+.El
+.Pp
+The following operations are valid for connectionless transports only:
+.Bl -column CLSET_RETRY_TIMEOUT "struct timeval *" "set total timeout"
+.It Dv CLSET_RETRY_TIMEOUT Ta "struct timeval *" Ta "set the retry timeout"
+.It Dv CLGET_RETRY_TIMEOUT Ta "struct timeval *" Ta "get the retry timeout"
+.It Dv CLSET_CONNECT Ta Vt "int *" Ta use Xr connect 2
+.El
+.Pp
+The retry timeout is the time that RPC
+waits for the server to reply before retransmitting the request.
+The
+.Fn clnt_control
+function
+returns
+.Dv TRUE
+on success and
+.Dv FALSE
+on failure.
+.It Fn clnt_create
+Generic client creation routine for program
+.Fa prognum
+and version
+.Fa versnum .
+The
+.Fa host
+argument
+identifies the name of the remote host where the server
+is located.
+The
+.Fa nettype
+argument
+indicates the class of transport protocol to use.
+The transports are tried in left to right order in
+.Ev NETPATH
+environment variable or in top to bottom order in
+the netconfig database.
+The
+.Fn clnt_create
+function
+tries all the transports of the
+.Fa nettype
+class available from the
+.Ev NETPATH
+environment variable and the netconfig database,
+and chooses the first successful one.
+A default timeout is set and can be modified using
+.Fn clnt_control .
+This routine returns
+.Dv NULL
+if it fails.
+The
+.Fn clnt_pcreateerror
+routine can be used to print the reason for failure.
+.Pp
+Note:
+.Fn clnt_create
+returns a valid client handle even
+if the particular version number supplied to
+.Fn clnt_create
+is not registered with the
+.Xr rpcbind 8
+service.
+This mismatch will be discovered by a
+.Fn clnt_call
+later (see
+.Xr rpc_clnt_calls 3 ) .
+.It Fn clnt_create_timed
+Generic client creation routine which is similar to
+.Fn clnt_create
+but which also has the additional argument
+.Fa timeout
+that specifies the maximum amount of time allowed for
+each transport class tried.
+In all other respects, the
+.Fn clnt_create_timed
+call behaves exactly like the
+.Fn clnt_create
+call.
+.It Fn clnt_create_vers
+Generic client creation routine which is similar to
+.Fn clnt_create
+but which also checks for the
+version availability.
+The
+.Fa host
+argument
+identifies the name of the remote host where the server
+is located.
+The
+.Fa nettype
+argument
+indicates the class transport protocols to be used.
+If the routine is successful it returns a client handle created for
+the highest version between
+.Fa vers_low
+and
+.Fa vers_high
+that is supported by the server.
+The
+.Fa vers_outp
+argument
+is set to this value.
+That is, after a successful return
+.Fa vers_low
+<=
+.Fa *vers_outp
+<=
+.Fa vers_high .
+If no version between
+.Fa vers_low
+and
+.Fa vers_high
+is supported by the server then the routine fails and returns
+.Dv NULL .
+A default timeout is set and can be modified using
+.Fn clnt_control .
+This routine returns
+.Dv NULL
+if it fails.
+The
+.Fn clnt_pcreateerror
+routine can be used to print the reason for failure.
+Note:
+.Fn clnt_create
+returns a valid client handle even
+if the particular version number supplied to
+.Fn clnt_create
+is not registered with the
+.Xr rpcbind 8
+service.
+This mismatch will be discovered by a
+.Fn clnt_call
+later (see
+.Xr rpc_clnt_calls 3 ) .
+However,
+.Fn clnt_create_vers
+does this for you and returns a valid handle
+only if a version within
+the range supplied is supported by the server.
+.It Fn clnt_create_vers_timed
+Generic client creation routine which is similar to
+.Fn clnt_create_vers
+but which also has the additional argument
+.Fa timeout
+that specifies the maximum amount of time allowed for
+each transport class tried.
+In all other respects, the
+.Fn clnt_create_vers_timed
+call behaves exactly like the
+.Fn clnt_create_vers
+call.
+.It Fn clnt_destroy
+A function macro that destroys the client's RPC handle.
+Destruction usually involves deallocation
+of private data structures, including
+.Fa clnt
+itself.
+Use of
+.Fa clnt
+is undefined after calling
+.Fn clnt_destroy .
+If the RPC library opened the associated file descriptor, or
+.Dv CLSET_FD_CLOSE
+was set using
+.Fn clnt_control ,
+the file descriptor will be closed.
+The caller should call
+.Fn auth_destroy "clnt->cl_auth"
+(before calling
+.Fn clnt_destroy )
+to destroy the associated
+.Vt AUTH
+structure (see
+.Xr rpc_clnt_auth 3 ) .
+.It Fn clnt_dg_create
+This routine creates an RPC client for the remote program
+.Fa prognum
+and version
+.Fa versnum ;
+the client uses a connectionless transport.
+The remote program is located at address
+.Fa svcaddr .
+The
+.Fa fildes
+argument
+is an open and bound file descriptor.
+This routine will resend the call message in intervals of
+15 seconds until a response is received or until the
+call times out.
+The total time for the call to time out is specified by
+.Fn clnt_call
+(see
+.Fn clnt_call
+in
+.Xr rpc_clnt_calls 3 ) .
+The retry time out and the total time out periods can
+be changed using
+.Fn clnt_control .
+The user may set the size of the send and receive
+buffers with the
+.Fa sendsz
+and
+.Fa recvsz
+arguments;
+values of 0 choose suitable defaults.
+This routine returns
+.Dv NULL
+if it fails.
+.It Fn clnt_pcreateerror
+Print a message to standard error indicating
+why a client RPC handle could not be created.
+The message is prepended with the string
+.Fa s
+and a colon, and appended with a newline.
+.It Fn clnt_spcreateerror
+Like
+.Fn clnt_pcreateerror ,
+except that it returns a string
+instead of printing to the standard error.
+A newline is not appended to the message in this case.
+Warning:
+returns a pointer to a buffer that is overwritten
+on each call.
+.It Fn clnt_raw_create
+This routine creates an RPC
+client handle for the remote program
+.Fa prognum
+and version
+.Fa versnum .
+The transport used to pass messages to the service is
+a buffer within the process's address space,
+so the corresponding RPC
+server should live in the same address space;
+(see
+.Fn svc_raw_create
+in
+.Xr rpc_svc_create 3 ) .
+This allows simulation of RPC and measurement of
+RPC overheads, such as round trip times,
+without any kernel or networking interference.
+This routine returns
+.Dv NULL
+if it fails.
+The
+.Fn clnt_raw_create
+function
+should be called after
+.Fn svc_raw_create .
+.It Fn clnt_tli_create
+This routine creates an RPC
+client handle for the remote program
+.Fa prognum
+and version
+.Fa versnum .
+The remote program is located at address
+.Fa svcaddr .
+If
+.Fa svcaddr
+is
+.Dv NULL
+and it is connection-oriented, it is assumed that the file descriptor
+is connected.
+For connectionless transports, if
+.Fa svcaddr
+is
+.Dv NULL ,
+.Dv RPC_UNKNOWNADDR
+error is set.
+The
+.Fa fildes
+argument
+is a file descriptor which may be open, bound and connected.
+If it is
+.Dv RPC_ANYFD ,
+it opens a file descriptor on the transport specified by
+.Fa netconf .
+If
+.Fa fildes
+is
+.Dv RPC_ANYFD
+and
+.Fa netconf
+is
+.Dv NULL ,
+a
+.Dv RPC_UNKNOWNPROTO
+error is set.
+If
+.Fa fildes
+is unbound, then it will attempt to bind the descriptor.
+The user may specify the size of the buffers with the
+.Fa sendsz
+and
+.Fa recvsz
+arguments;
+values of 0 choose suitable defaults.
+Depending upon the type of the transport (connection-oriented
+or connectionless),
+.Fn clnt_tli_create
+calls appropriate client creation routines.
+This routine returns
+.Dv NULL
+if it fails.
+The
+.Fn clnt_pcreateerror
+routine can be used to print the reason for failure.
+The remote rpcbind
+service (see
+.Xr rpcbind 8 )
+is not consulted for the address of the remote
+service.
+.It Fn clnt_tp_create
+Like
+.Fn clnt_create
+except
+.Fn clnt_tp_create
+tries only one transport specified through
+.Fa netconf .
+The
+.Fn clnt_tp_create
+function
+creates a client handle for the program
+.Fa prognum ,
+the version
+.Fa versnum ,
+and for the transport specified by
+.Fa netconf .
+Default options are set,
+which can be changed using
+.Fn clnt_control
+calls.
+The remote rpcbind service on the host
+.Fa host
+is consulted for the address of the remote service.
+This routine returns
+.Dv NULL
+if it fails.
+The
+.Fn clnt_pcreateerror
+routine can be used to print the reason for failure.
+.It Fn clnt_tp_create_timed
+Like
+.Fn clnt_tp_create
+except
+.Fn clnt_tp_create_timed
+has the extra argument
+.Fa timeout
+which specifies the maximum time allowed for
+the creation attempt to succeed.
+In all other respects, the
+.Fn clnt_tp_create_timed
+call behaves exactly like the
+.Fn clnt_tp_create
+call.
+.It Fn clnt_vc_create
+This routine creates an RPC
+client for the remote program
+.Fa prognum
+and version
+.Fa versnum ;
+the client uses a connection-oriented transport.
+The remote program is located at address
+.Fa svcaddr .
+The
+.Fa fildes
+argument
+is an open and bound file descriptor.
+The user may specify the size of the send and receive buffers
+with the
+.Fa sendsz
+and
+.Fa recvsz
+arguments;
+values of 0 choose suitable defaults.
+This routine returns
+.Dv NULL
+if it fails.
+The address
+.Fa svcaddr
+should not be
+.Dv NULL
+and should point to the actual address of the remote program.
+The
+.Fn clnt_vc_create
+function
+does not consult the remote rpcbind service for this information.
+.It Xo
+.Vt "struct rpc_createerr" Va rpc_createerr ;
+.Xc
+A global variable whose value is set by any RPC
+client handle creation routine
+that fails.
+It is used by the routine
+.Fn clnt_pcreateerror
+to print the reason for the failure.
+.El
+.Sh SEE ALSO
+.Xr rpc 3 ,
+.Xr rpc_clnt_auth 3 ,
+.Xr rpc_clnt_calls 3 ,
+.Xr rpcbind 8
diff --git a/lib/libc/rpc/rpc_com.h b/lib/libc/rpc/rpc_com.h
new file mode 100644
index 0000000..f2bf11f
--- /dev/null
+++ b/lib/libc/rpc/rpc_com.h
@@ -0,0 +1,95 @@
+/* $NetBSD: rpc_com.h,v 1.3 2000/12/10 04:10:08 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ *
+ * $FreeBSD$
+ */
+/*
+ * Copyright (c) 1986 - 1991 by Sun Microsystems, Inc.
+ */
+
+/*
+ * rpc_com.h, Common definitions for both the server and client side.
+ * All for the topmost layer of rpc
+ *
+ * In Sun's tirpc distribution, this was installed as <rpc/rpc_com.h>,
+ * but as it contains only non-exported interfaces, it was moved here.
+ */
+
+#ifndef _RPC_RPCCOM_H
+#define _RPC_RPCCOM_H
+
+#include <sys/cdefs.h>
+
+/* #pragma ident "@(#)rpc_com.h 1.11 93/07/05 SMI" */
+
+/*
+ * The max size of the transport, if the size cannot be determined
+ * by other means.
+ */
+#define RPC_MAXDATASIZE 9000
+#define RPC_MAXADDRSIZE 1024
+
+#define __RPC_GETXID(now) ((u_int32_t)getpid() ^ (u_int32_t)(now)->tv_sec ^ \
+ (u_int32_t)(now)->tv_usec)
+
+__BEGIN_DECLS
+extern u_int __rpc_get_a_size(int);
+extern int __rpc_dtbsize(void);
+extern struct netconfig * __rpcgettp(int);
+extern int __rpc_get_default_domain(char **);
+
+char *__rpc_taddr2uaddr_af(int, const struct netbuf *);
+struct netbuf *__rpc_uaddr2taddr_af(int, const char *);
+int __rpc_fixup_addr(struct netbuf *, const struct netbuf *);
+int __rpc_sockinfo2netid(struct __rpc_sockinfo *, const char **);
+int __rpc_seman2socktype(int);
+int __rpc_socktype2seman(int);
+void *rpc_nullproc(CLIENT *);
+int __rpc_sockisbound(int);
+
+struct netbuf *__rpcb_findaddr_timed(rpcprog_t, rpcvers_t,
+ const struct netconfig *, const char *host, CLIENT **clpp,
+ struct timeval *tp);
+
+bool_t __rpc_control(int,void *);
+
+char *_get_next_token(char *, int);
+
+bool_t __svc_clean_idle(fd_set *, int, bool_t);
+bool_t __xdrrec_setnonblock(XDR *, int);
+bool_t __xdrrec_getrec(XDR *, enum xprt_stat *, bool_t);
+void __xprt_unregister_unlocked(SVCXPRT *);
+
+SVCXPRT **__svc_xports;
+int __svc_maxrec;
+
+__END_DECLS
+
+#endif /* _RPC_RPCCOM_H */
diff --git a/lib/libc/rpc/rpc_commondata.c b/lib/libc/rpc/rpc_commondata.c
new file mode 100644
index 0000000..679233a
--- /dev/null
+++ b/lib/libc/rpc/rpc_commondata.c
@@ -0,0 +1,48 @@
+/* $NetBSD: rpc_commondata.c,v 1.7 2000/06/02 23:11:13 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid = "@(#)rpc_commondata.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <rpc/rpc.h>
+#include "un-namespace.h"
+
+/*
+ * This file should only contain common data (global data) that is exported
+ * by public interfaces
+ */
+struct opaque_auth _null_auth;
+fd_set svc_fdset;
+int svc_maxfd = -1;
diff --git a/lib/libc/rpc/rpc_dtablesize.c b/lib/libc/rpc/rpc_dtablesize.c
new file mode 100644
index 0000000..5e50ba8
--- /dev/null
+++ b/lib/libc/rpc/rpc_dtablesize.c
@@ -0,0 +1,67 @@
+/* $NetBSD: rpc_dtablesize.c,v 1.14 1998/11/15 17:32:43 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";
+static char *sccsid = "@(#)rpc_dtablesize.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <unistd.h>
+#include "un-namespace.h"
+
+int _rpc_dtablesize(void); /* XXX */
+
+/*
+ * Cache the result of getdtablesize(), so we don't have to do an
+ * expensive system call every time.
+ */
+/*
+ * XXX In FreeBSD 2.x, you can have the maximum number of open file
+ * descriptors be greater than FD_SETSIZE (which us 256 by default).
+ *
+ * Since old programs tend to use this call to determine the first arg
+ * for _select(), having this return > FD_SETSIZE is a Bad Idea(TM)!
+ */
+int
+_rpc_dtablesize(void)
+{
+ static int size;
+
+ if (size == 0) {
+ size = getdtablesize();
+ if (size > FD_SETSIZE)
+ size = FD_SETSIZE;
+ }
+ return (size);
+}
diff --git a/lib/libc/rpc/rpc_generic.c b/lib/libc/rpc/rpc_generic.c
new file mode 100644
index 0000000..ab259d5
--- /dev/null
+++ b/lib/libc/rpc/rpc_generic.c
@@ -0,0 +1,845 @@
+/* $NetBSD: rpc_generic.c,v 1.4 2000/09/28 09:07:04 kleink Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/* #pragma ident "@(#)rpc_generic.c 1.17 94/04/24 SMI" */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * rpc_generic.c, Miscl routines for RPC.
+ *
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/un.h>
+#include <sys/resource.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <rpc/rpc.h>
+#include <ctype.h>
+#include <stddef.h>
+#include <stdio.h>
+#include <netdb.h>
+#include <netconfig.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syslog.h>
+#include <rpc/nettype.h>
+#include "un-namespace.h"
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+struct handle {
+ NCONF_HANDLE *nhandle;
+ int nflag; /* Whether NETPATH or NETCONFIG */
+ int nettype;
+};
+
+static const struct _rpcnettype {
+ const char *name;
+ const int type;
+} _rpctypelist[] = {
+ { "netpath", _RPC_NETPATH },
+ { "visible", _RPC_VISIBLE },
+ { "circuit_v", _RPC_CIRCUIT_V },
+ { "datagram_v", _RPC_DATAGRAM_V },
+ { "circuit_n", _RPC_CIRCUIT_N },
+ { "datagram_n", _RPC_DATAGRAM_N },
+ { "tcp", _RPC_TCP },
+ { "udp", _RPC_UDP },
+ { 0, _RPC_NONE }
+};
+
+struct netid_af {
+ const char *netid;
+ int af;
+ int protocol;
+};
+
+static const struct netid_af na_cvt[] = {
+ { "udp", AF_INET, IPPROTO_UDP },
+ { "tcp", AF_INET, IPPROTO_TCP },
+#ifdef INET6
+ { "udp6", AF_INET6, IPPROTO_UDP },
+ { "tcp6", AF_INET6, IPPROTO_TCP },
+#endif
+ { "local", AF_LOCAL, 0 }
+};
+
+#if 0
+static char *strlocase(char *);
+#endif
+static int getnettype(const char *);
+
+/*
+ * Cache the result of getrlimit(), so we don't have to do an
+ * expensive call every time.
+ */
+int
+__rpc_dtbsize()
+{
+ static int tbsize;
+ struct rlimit rl;
+
+ if (tbsize) {
+ return (tbsize);
+ }
+ if (getrlimit(RLIMIT_NOFILE, &rl) == 0) {
+ return (tbsize = (int)rl.rlim_max);
+ }
+ /*
+ * Something wrong. I'll try to save face by returning a
+ * pessimistic number.
+ */
+ return (32);
+}
+
+
+/*
+ * Find the appropriate buffer size
+ */
+u_int
+/*ARGSUSED*/
+__rpc_get_t_size(af, proto, size)
+ int af, proto;
+ int size; /* Size requested */
+{
+ int maxsize, defsize;
+
+ maxsize = 256 * 1024; /* XXX */
+ switch (proto) {
+ case IPPROTO_TCP:
+ defsize = 64 * 1024; /* XXX */
+ break;
+ case IPPROTO_UDP:
+ defsize = UDPMSGSIZE;
+ break;
+ default:
+ defsize = RPC_MAXDATASIZE;
+ break;
+ }
+ if (size == 0)
+ return defsize;
+
+ /* Check whether the value is within the upper max limit */
+ return (size > maxsize ? (u_int)maxsize : (u_int)size);
+}
+
+/*
+ * Find the appropriate address buffer size
+ */
+u_int
+__rpc_get_a_size(af)
+ int af;
+{
+ switch (af) {
+ case AF_INET:
+ return sizeof (struct sockaddr_in);
+#ifdef INET6
+ case AF_INET6:
+ return sizeof (struct sockaddr_in6);
+#endif
+ case AF_LOCAL:
+ return sizeof (struct sockaddr_un);
+ default:
+ break;
+ }
+ return ((u_int)RPC_MAXADDRSIZE);
+}
+
+#if 0
+static char *
+strlocase(p)
+ char *p;
+{
+ char *t = p;
+
+ for (; *p; p++)
+ if (isupper(*p))
+ *p = tolower(*p);
+ return (t);
+}
+#endif
+
+/*
+ * Returns the type of the network as defined in <rpc/nettype.h>
+ * If nettype is NULL, it defaults to NETPATH.
+ */
+static int
+getnettype(nettype)
+ const char *nettype;
+{
+ int i;
+
+ if ((nettype == NULL) || (nettype[0] == 0)) {
+ return (_RPC_NETPATH); /* Default */
+ }
+
+#if 0
+ nettype = strlocase(nettype);
+#endif
+ for (i = 0; _rpctypelist[i].name; i++)
+ if (strcasecmp(nettype, _rpctypelist[i].name) == 0) {
+ return (_rpctypelist[i].type);
+ }
+ return (_rpctypelist[i].type);
+}
+
+static thread_key_t tcp_key, udp_key;
+static once_t keys_once = ONCE_INITIALIZER;
+static int tcp_key_error, udp_key_error;
+
+static void
+keys_init(void)
+{
+
+ tcp_key_error = thr_keycreate(&tcp_key, free);
+ udp_key_error = thr_keycreate(&udp_key, free);
+}
+
+/*
+ * For the given nettype (tcp or udp only), return the first structure found.
+ * This should be freed by calling freenetconfigent()
+ */
+struct netconfig *
+__rpc_getconfip(nettype)
+ const char *nettype;
+{
+ char *netid;
+ char *netid_tcp = (char *) NULL;
+ char *netid_udp = (char *) NULL;
+ static char *netid_tcp_main;
+ static char *netid_udp_main;
+ struct netconfig *dummy;
+ int main_thread;
+
+ if ((main_thread = thr_main())) {
+ netid_udp = netid_udp_main;
+ netid_tcp = netid_tcp_main;
+ } else {
+ if (thr_once(&keys_once, keys_init) != 0 ||
+ tcp_key_error != 0 || udp_key_error != 0)
+ return (NULL);
+ netid_tcp = (char *)thr_getspecific(tcp_key);
+ netid_udp = (char *)thr_getspecific(udp_key);
+ }
+ if (!netid_udp && !netid_tcp) {
+ struct netconfig *nconf;
+ void *confighandle;
+
+ if (!(confighandle = setnetconfig())) {
+ syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
+ return (NULL);
+ }
+ while ((nconf = getnetconfig(confighandle)) != NULL) {
+ if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
+ if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
+ netid_tcp = strdup(nconf->nc_netid);
+ if (main_thread)
+ netid_tcp_main = netid_tcp;
+ else
+ thr_setspecific(tcp_key,
+ (void *) netid_tcp);
+ } else
+ if (strcmp(nconf->nc_proto, NC_UDP) == 0) {
+ netid_udp = strdup(nconf->nc_netid);
+ if (main_thread)
+ netid_udp_main = netid_udp;
+ else
+ thr_setspecific(udp_key,
+ (void *) netid_udp);
+ }
+ }
+ }
+ endnetconfig(confighandle);
+ }
+ if (strcmp(nettype, "udp") == 0)
+ netid = netid_udp;
+ else if (strcmp(nettype, "tcp") == 0)
+ netid = netid_tcp;
+ else {
+ return (NULL);
+ }
+ if ((netid == NULL) || (netid[0] == 0)) {
+ return (NULL);
+ }
+ dummy = getnetconfigent(netid);
+ return (dummy);
+}
+
+/*
+ * Returns the type of the nettype, which should then be used with
+ * __rpc_getconf().
+ */
+void *
+__rpc_setconf(nettype)
+ const char *nettype;
+{
+ struct handle *handle;
+
+ handle = (struct handle *) malloc(sizeof (struct handle));
+ if (handle == NULL) {
+ return (NULL);
+ }
+ switch (handle->nettype = getnettype(nettype)) {
+ case _RPC_NETPATH:
+ case _RPC_CIRCUIT_N:
+ case _RPC_DATAGRAM_N:
+ if (!(handle->nhandle = setnetpath()))
+ goto failed;
+ handle->nflag = TRUE;
+ break;
+ case _RPC_VISIBLE:
+ case _RPC_CIRCUIT_V:
+ case _RPC_DATAGRAM_V:
+ case _RPC_TCP:
+ case _RPC_UDP:
+ if (!(handle->nhandle = setnetconfig())) {
+ syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
+ goto failed;
+ }
+ handle->nflag = FALSE;
+ break;
+ default:
+ goto failed;
+ }
+
+ return (handle);
+
+failed:
+ free(handle);
+ return (NULL);
+}
+
+/*
+ * Returns the next netconfig struct for the given "net" type.
+ * __rpc_setconf() should have been called previously.
+ */
+struct netconfig *
+__rpc_getconf(vhandle)
+ void *vhandle;
+{
+ struct handle *handle;
+ struct netconfig *nconf;
+
+ handle = (struct handle *)vhandle;
+ if (handle == NULL) {
+ return (NULL);
+ }
+ for (;;) {
+ if (handle->nflag)
+ nconf = getnetpath(handle->nhandle);
+ else
+ nconf = getnetconfig(handle->nhandle);
+ if (nconf == NULL)
+ break;
+ if ((nconf->nc_semantics != NC_TPI_CLTS) &&
+ (nconf->nc_semantics != NC_TPI_COTS) &&
+ (nconf->nc_semantics != NC_TPI_COTS_ORD))
+ continue;
+ switch (handle->nettype) {
+ case _RPC_VISIBLE:
+ if (!(nconf->nc_flag & NC_VISIBLE))
+ continue;
+ /* FALLTHROUGH */
+ case _RPC_NETPATH: /* Be happy */
+ break;
+ case _RPC_CIRCUIT_V:
+ if (!(nconf->nc_flag & NC_VISIBLE))
+ continue;
+ /* FALLTHROUGH */
+ case _RPC_CIRCUIT_N:
+ if ((nconf->nc_semantics != NC_TPI_COTS) &&
+ (nconf->nc_semantics != NC_TPI_COTS_ORD))
+ continue;
+ break;
+ case _RPC_DATAGRAM_V:
+ if (!(nconf->nc_flag & NC_VISIBLE))
+ continue;
+ /* FALLTHROUGH */
+ case _RPC_DATAGRAM_N:
+ if (nconf->nc_semantics != NC_TPI_CLTS)
+ continue;
+ break;
+ case _RPC_TCP:
+ if (((nconf->nc_semantics != NC_TPI_COTS) &&
+ (nconf->nc_semantics != NC_TPI_COTS_ORD)) ||
+ (strcmp(nconf->nc_protofmly, NC_INET)
+#ifdef INET6
+ && strcmp(nconf->nc_protofmly, NC_INET6))
+#else
+ )
+#endif
+ ||
+ strcmp(nconf->nc_proto, NC_TCP))
+ continue;
+ break;
+ case _RPC_UDP:
+ if ((nconf->nc_semantics != NC_TPI_CLTS) ||
+ (strcmp(nconf->nc_protofmly, NC_INET)
+#ifdef INET6
+ && strcmp(nconf->nc_protofmly, NC_INET6))
+#else
+ )
+#endif
+ ||
+ strcmp(nconf->nc_proto, NC_UDP))
+ continue;
+ break;
+ }
+ break;
+ }
+ return (nconf);
+}
+
+void
+__rpc_endconf(vhandle)
+ void * vhandle;
+{
+ struct handle *handle;
+
+ handle = (struct handle *) vhandle;
+ if (handle == NULL) {
+ return;
+ }
+ if (handle->nflag) {
+ endnetpath(handle->nhandle);
+ } else {
+ endnetconfig(handle->nhandle);
+ }
+ free(handle);
+}
+
+/*
+ * Used to ping the NULL procedure for clnt handle.
+ * Returns NULL if fails, else a non-NULL pointer.
+ */
+void *
+rpc_nullproc(clnt)
+ CLIENT *clnt;
+{
+ struct timeval TIMEOUT = {25, 0};
+
+ if (clnt_call(clnt, NULLPROC, (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_void, NULL, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((void *) clnt);
+}
+
+/*
+ * Try all possible transports until
+ * one succeeds in finding the netconf for the given fd.
+ */
+struct netconfig *
+__rpcgettp(fd)
+ int fd;
+{
+ const char *netid;
+ struct __rpc_sockinfo si;
+
+ if (!__rpc_fd2sockinfo(fd, &si))
+ return NULL;
+
+ if (!__rpc_sockinfo2netid(&si, &netid))
+ return NULL;
+
+ /*LINTED const castaway*/
+ return getnetconfigent((char *)netid);
+}
+
+int
+__rpc_fd2sockinfo(int fd, struct __rpc_sockinfo *sip)
+{
+ socklen_t len;
+ int type, proto;
+ struct sockaddr_storage ss;
+
+ len = sizeof ss;
+ if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &len) < 0)
+ return 0;
+ sip->si_alen = len;
+
+ len = sizeof type;
+ if (_getsockopt(fd, SOL_SOCKET, SO_TYPE, &type, &len) < 0)
+ return 0;
+
+ /* XXX */
+ if (ss.ss_family != AF_LOCAL) {
+ if (type == SOCK_STREAM)
+ proto = IPPROTO_TCP;
+ else if (type == SOCK_DGRAM)
+ proto = IPPROTO_UDP;
+ else
+ return 0;
+ } else
+ proto = 0;
+
+ sip->si_af = ss.ss_family;
+ sip->si_proto = proto;
+ sip->si_socktype = type;
+
+ return 1;
+}
+
+/*
+ * Linear search, but the number of entries is small.
+ */
+int
+__rpc_nconf2sockinfo(const struct netconfig *nconf, struct __rpc_sockinfo *sip)
+{
+ int i;
+
+ for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++)
+ if (strcmp(na_cvt[i].netid, nconf->nc_netid) == 0 || (
+ strcmp(nconf->nc_netid, "unix") == 0 &&
+ strcmp(na_cvt[i].netid, "local") == 0)) {
+ sip->si_af = na_cvt[i].af;
+ sip->si_proto = na_cvt[i].protocol;
+ sip->si_socktype =
+ __rpc_seman2socktype((int)nconf->nc_semantics);
+ if (sip->si_socktype == -1)
+ return 0;
+ sip->si_alen = __rpc_get_a_size(sip->si_af);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+__rpc_nconf2fd(const struct netconfig *nconf)
+{
+ struct __rpc_sockinfo si;
+
+ if (!__rpc_nconf2sockinfo(nconf, &si))
+ return 0;
+
+ return _socket(si.si_af, si.si_socktype, si.si_proto);
+}
+
+int
+__rpc_sockinfo2netid(struct __rpc_sockinfo *sip, const char **netid)
+{
+ int i;
+ struct netconfig *nconf;
+
+ nconf = getnetconfigent("local");
+
+ for (i = 0; i < (sizeof na_cvt) / (sizeof (struct netid_af)); i++) {
+ if (na_cvt[i].af == sip->si_af &&
+ na_cvt[i].protocol == sip->si_proto) {
+ if (strcmp(na_cvt[i].netid, "local") == 0 && nconf == NULL) {
+ if (netid)
+ *netid = "unix";
+ } else {
+ if (netid)
+ *netid = na_cvt[i].netid;
+ }
+ if (nconf != NULL)
+ freenetconfigent(nconf);
+ return 1;
+ }
+ }
+ if (nconf != NULL)
+ freenetconfigent(nconf);
+
+ return 0;
+}
+
+char *
+taddr2uaddr(const struct netconfig *nconf, const struct netbuf *nbuf)
+{
+ struct __rpc_sockinfo si;
+
+ if (!__rpc_nconf2sockinfo(nconf, &si))
+ return NULL;
+ return __rpc_taddr2uaddr_af(si.si_af, nbuf);
+}
+
+struct netbuf *
+uaddr2taddr(const struct netconfig *nconf, const char *uaddr)
+{
+ struct __rpc_sockinfo si;
+
+ if (!__rpc_nconf2sockinfo(nconf, &si))
+ return NULL;
+ return __rpc_uaddr2taddr_af(si.si_af, uaddr);
+}
+
+char *
+__rpc_taddr2uaddr_af(int af, const struct netbuf *nbuf)
+{
+ char *ret;
+ struct sockaddr_in *sin;
+ struct sockaddr_un *sun;
+ char namebuf[INET_ADDRSTRLEN];
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+ char namebuf6[INET6_ADDRSTRLEN];
+#endif
+ u_int16_t port;
+
+ switch (af) {
+ case AF_INET:
+ sin = nbuf->buf;
+ if (inet_ntop(af, &sin->sin_addr, namebuf, sizeof namebuf)
+ == NULL)
+ return NULL;
+ port = ntohs(sin->sin_port);
+ if (asprintf(&ret, "%s.%u.%u", namebuf, ((u_int32_t)port) >> 8,
+ port & 0xff) < 0)
+ return NULL;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ sin6 = nbuf->buf;
+ if (inet_ntop(af, &sin6->sin6_addr, namebuf6, sizeof namebuf6)
+ == NULL)
+ return NULL;
+ port = ntohs(sin6->sin6_port);
+ if (asprintf(&ret, "%s.%u.%u", namebuf6, ((u_int32_t)port) >> 8,
+ port & 0xff) < 0)
+ return NULL;
+ break;
+#endif
+ case AF_LOCAL:
+ sun = nbuf->buf;
+ if (asprintf(&ret, "%.*s", (int)(sun->sun_len -
+ offsetof(struct sockaddr_un, sun_path)),
+ sun->sun_path) < 0)
+ return (NULL);
+ break;
+ default:
+ return NULL;
+ }
+
+ return ret;
+}
+
+struct netbuf *
+__rpc_uaddr2taddr_af(int af, const char *uaddr)
+{
+ struct netbuf *ret = NULL;
+ char *addrstr, *p;
+ unsigned port, portlo, porthi;
+ struct sockaddr_in *sin;
+#ifdef INET6
+ struct sockaddr_in6 *sin6;
+#endif
+ struct sockaddr_un *sun;
+
+ port = 0;
+ sin = NULL;
+ addrstr = strdup(uaddr);
+ if (addrstr == NULL)
+ return NULL;
+
+ /*
+ * AF_LOCAL addresses are expected to be absolute
+ * pathnames, anything else will be AF_INET or AF_INET6.
+ */
+ if (*addrstr != '/') {
+ p = strrchr(addrstr, '.');
+ if (p == NULL)
+ goto out;
+ portlo = (unsigned)atoi(p + 1);
+ *p = '\0';
+
+ p = strrchr(addrstr, '.');
+ if (p == NULL)
+ goto out;
+ porthi = (unsigned)atoi(p + 1);
+ *p = '\0';
+ port = (porthi << 8) | portlo;
+ }
+
+ ret = (struct netbuf *)malloc(sizeof *ret);
+ if (ret == NULL)
+ goto out;
+
+ switch (af) {
+ case AF_INET:
+ sin = (struct sockaddr_in *)malloc(sizeof *sin);
+ if (sin == NULL)
+ goto out;
+ memset(sin, 0, sizeof *sin);
+ sin->sin_family = AF_INET;
+ sin->sin_port = htons(port);
+ if (inet_pton(AF_INET, addrstr, &sin->sin_addr) <= 0) {
+ free(sin);
+ free(ret);
+ ret = NULL;
+ goto out;
+ }
+ sin->sin_len = ret->maxlen = ret->len = sizeof *sin;
+ ret->buf = sin;
+ break;
+#ifdef INET6
+ case AF_INET6:
+ sin6 = (struct sockaddr_in6 *)malloc(sizeof *sin6);
+ if (sin6 == NULL)
+ goto out;
+ memset(sin6, 0, sizeof *sin6);
+ sin6->sin6_family = AF_INET6;
+ sin6->sin6_port = htons(port);
+ if (inet_pton(AF_INET6, addrstr, &sin6->sin6_addr) <= 0) {
+ free(sin6);
+ free(ret);
+ ret = NULL;
+ goto out;
+ }
+ sin6->sin6_len = ret->maxlen = ret->len = sizeof *sin6;
+ ret->buf = sin6;
+ break;
+#endif
+ case AF_LOCAL:
+ sun = (struct sockaddr_un *)malloc(sizeof *sun);
+ if (sun == NULL)
+ goto out;
+ memset(sun, 0, sizeof *sun);
+ sun->sun_family = AF_LOCAL;
+ strncpy(sun->sun_path, addrstr, sizeof(sun->sun_path) - 1);
+ ret->len = ret->maxlen = sun->sun_len = SUN_LEN(sun);
+ ret->buf = sun;
+ break;
+ default:
+ break;
+ }
+out:
+ free(addrstr);
+ return ret;
+}
+
+int
+__rpc_seman2socktype(int semantics)
+{
+ switch (semantics) {
+ case NC_TPI_CLTS:
+ return SOCK_DGRAM;
+ case NC_TPI_COTS_ORD:
+ return SOCK_STREAM;
+ case NC_TPI_RAW:
+ return SOCK_RAW;
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+int
+__rpc_socktype2seman(int socktype)
+{
+ switch (socktype) {
+ case SOCK_DGRAM:
+ return NC_TPI_CLTS;
+ case SOCK_STREAM:
+ return NC_TPI_COTS_ORD;
+ case SOCK_RAW:
+ return NC_TPI_RAW;
+ default:
+ break;
+ }
+
+ return -1;
+}
+
+/*
+ * XXXX - IPv6 scope IDs can't be handled in universal addresses.
+ * Here, we compare the original server address to that of the RPC
+ * service we just received back from a call to rpcbind on the remote
+ * machine. If they are both "link local" or "site local", copy
+ * the scope id of the server address over to the service address.
+ */
+int
+__rpc_fixup_addr(struct netbuf *new, const struct netbuf *svc)
+{
+#ifdef INET6
+ struct sockaddr *sa_new, *sa_svc;
+ struct sockaddr_in6 *sin6_new, *sin6_svc;
+
+ sa_svc = (struct sockaddr *)svc->buf;
+ sa_new = (struct sockaddr *)new->buf;
+
+ if (sa_new->sa_family == sa_svc->sa_family &&
+ sa_new->sa_family == AF_INET6) {
+ sin6_new = (struct sockaddr_in6 *)new->buf;
+ sin6_svc = (struct sockaddr_in6 *)svc->buf;
+
+ if ((IN6_IS_ADDR_LINKLOCAL(&sin6_new->sin6_addr) &&
+ IN6_IS_ADDR_LINKLOCAL(&sin6_svc->sin6_addr)) ||
+ (IN6_IS_ADDR_SITELOCAL(&sin6_new->sin6_addr) &&
+ IN6_IS_ADDR_SITELOCAL(&sin6_svc->sin6_addr))) {
+ sin6_new->sin6_scope_id = sin6_svc->sin6_scope_id;
+ }
+ }
+#endif
+ return 1;
+}
+
+int
+__rpc_sockisbound(int fd)
+{
+ struct sockaddr_storage ss;
+ socklen_t slen;
+
+ slen = sizeof (struct sockaddr_storage);
+ if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0)
+ return 0;
+
+ switch (ss.ss_family) {
+ case AF_INET:
+ return (((struct sockaddr_in *)
+ (void *)&ss)->sin_port != 0);
+#ifdef INET6
+ case AF_INET6:
+ return (((struct sockaddr_in6 *)
+ (void *)&ss)->sin6_port != 0);
+#endif
+ case AF_LOCAL:
+ /* XXX check this */
+ return (((struct sockaddr_un *)
+ (void *)&ss)->sun_path[0] != '\0');
+ default:
+ break;
+ }
+
+ return 0;
+}
diff --git a/lib/libc/rpc/rpc_prot.c b/lib/libc/rpc/rpc_prot.c
new file mode 100644
index 0000000..2a4b575
--- /dev/null
+++ b/lib/libc/rpc/rpc_prot.c
@@ -0,0 +1,372 @@
+/* $NetBSD: rpc_prot.c,v 1.16 2000/06/02 23:11:13 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)rpc_prot.c 2.3 88/08/07 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * rpc_prot.c
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * This set of routines implements the rpc message definition,
+ * its serializer and some common rpc utility routines.
+ * The routines are meant for various implementations of rpc -
+ * they are NOT for the rpc client or rpc service implementations!
+ * Because authentication stuff is easy and is part of rpc, the opaque
+ * routines are also in this program.
+ */
+
+#include "namespace.h"
+#include <sys/param.h>
+
+#include <assert.h>
+
+#include <rpc/rpc.h>
+#include "un-namespace.h"
+
+static void accepted(enum accept_stat, struct rpc_err *);
+static void rejected(enum reject_stat, struct rpc_err *);
+
+/* * * * * * * * * * * * * * XDR Authentication * * * * * * * * * * * */
+
+extern struct opaque_auth _null_auth;
+
+/*
+ * XDR an opaque authentication struct
+ * (see auth.h)
+ */
+bool_t
+xdr_opaque_auth(xdrs, ap)
+ XDR *xdrs;
+ struct opaque_auth *ap;
+{
+
+ assert(xdrs != NULL);
+ assert(ap != NULL);
+
+ if (xdr_enum(xdrs, &(ap->oa_flavor)))
+ return (xdr_bytes(xdrs, &ap->oa_base,
+ &ap->oa_length, MAX_AUTH_BYTES));
+ return (FALSE);
+}
+
+/*
+ * XDR a DES block
+ */
+bool_t
+xdr_des_block(xdrs, blkp)
+ XDR *xdrs;
+ des_block *blkp;
+{
+
+ assert(xdrs != NULL);
+ assert(blkp != NULL);
+
+ return (xdr_opaque(xdrs, (caddr_t)(void *)blkp, sizeof(des_block)));
+}
+
+/* * * * * * * * * * * * * * XDR RPC MESSAGE * * * * * * * * * * * * * * * */
+
+/*
+ * XDR the MSG_ACCEPTED part of a reply message union
+ */
+bool_t
+xdr_accepted_reply(xdrs, ar)
+ XDR *xdrs;
+ struct accepted_reply *ar;
+{
+ enum accept_stat *par_stat;
+
+ assert(xdrs != NULL);
+ assert(ar != NULL);
+
+ par_stat = &ar->ar_stat;
+
+ /* personalized union, rather than calling xdr_union */
+ if (! xdr_opaque_auth(xdrs, &(ar->ar_verf)))
+ return (FALSE);
+ if (! xdr_enum(xdrs, (enum_t *) par_stat))
+ return (FALSE);
+ switch (ar->ar_stat) {
+
+ case SUCCESS:
+ return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));
+
+ case PROG_MISMATCH:
+ if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low)))
+ return (FALSE);
+ return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high)));
+
+ case GARBAGE_ARGS:
+ case SYSTEM_ERR:
+ case PROC_UNAVAIL:
+ case PROG_UNAVAIL:
+ break;
+ }
+ return (TRUE); /* TRUE => open ended set of problems */
+}
+
+/*
+ * XDR the MSG_DENIED part of a reply message union
+ */
+bool_t
+xdr_rejected_reply(xdrs, rr)
+ XDR *xdrs;
+ struct rejected_reply *rr;
+{
+ enum reject_stat *prj_stat;
+ enum auth_stat *prj_why;
+
+ assert(xdrs != NULL);
+ assert(rr != NULL);
+
+ prj_stat = &rr->rj_stat;
+
+ /* personalized union, rather than calling xdr_union */
+ if (! xdr_enum(xdrs, (enum_t *) prj_stat))
+ return (FALSE);
+ switch (rr->rj_stat) {
+
+ case RPC_MISMATCH:
+ if (! xdr_u_int32_t(xdrs, &(rr->rj_vers.low)))
+ return (FALSE);
+ return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high)));
+
+ case AUTH_ERROR:
+ prj_why = &rr->rj_why;
+ return (xdr_enum(xdrs, (enum_t *) prj_why));
+ }
+ /* NOTREACHED */
+ assert(0);
+ return (FALSE);
+}
+
+static const struct xdr_discrim reply_dscrm[3] = {
+ { (int)MSG_ACCEPTED, (xdrproc_t)xdr_accepted_reply },
+ { (int)MSG_DENIED, (xdrproc_t)xdr_rejected_reply },
+ { __dontcare__, NULL_xdrproc_t } };
+
+/*
+ * XDR a reply message
+ */
+bool_t
+xdr_replymsg(xdrs, rmsg)
+ XDR *xdrs;
+ struct rpc_msg *rmsg;
+{
+ enum msg_type *prm_direction;
+ enum reply_stat *prp_stat;
+
+ assert(xdrs != NULL);
+ assert(rmsg != NULL);
+
+ prm_direction = &rmsg->rm_direction;
+ prp_stat = &rmsg->rm_reply.rp_stat;
+
+ if (
+ xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&
+ xdr_enum(xdrs, (enum_t *) prm_direction) &&
+ (rmsg->rm_direction == REPLY) )
+ return (xdr_union(xdrs, (enum_t *) prp_stat,
+ (caddr_t)(void *)&(rmsg->rm_reply.ru), reply_dscrm,
+ NULL_xdrproc_t));
+ return (FALSE);
+}
+
+
+/*
+ * Serializes the "static part" of a call message header.
+ * The fields include: rm_xid, rm_direction, rpcvers, prog, and vers.
+ * The rm_xid is not really static, but the user can easily munge on the fly.
+ */
+bool_t
+xdr_callhdr(xdrs, cmsg)
+ XDR *xdrs;
+ struct rpc_msg *cmsg;
+{
+ enum msg_type *prm_direction;
+
+ assert(xdrs != NULL);
+ assert(cmsg != NULL);
+
+ prm_direction = &cmsg->rm_direction;
+
+ cmsg->rm_direction = CALL;
+ cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;
+ if (
+ (xdrs->x_op == XDR_ENCODE) &&
+ xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&
+ xdr_enum(xdrs, (enum_t *) prm_direction) &&
+ xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&
+ xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) )
+ return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)));
+ return (FALSE);
+}
+
+/* ************************** Client utility routine ************* */
+
+static void
+accepted(acpt_stat, error)
+ enum accept_stat acpt_stat;
+ struct rpc_err *error;
+{
+
+ assert(error != NULL);
+
+ switch (acpt_stat) {
+
+ case PROG_UNAVAIL:
+ error->re_status = RPC_PROGUNAVAIL;
+ return;
+
+ case PROG_MISMATCH:
+ error->re_status = RPC_PROGVERSMISMATCH;
+ return;
+
+ case PROC_UNAVAIL:
+ error->re_status = RPC_PROCUNAVAIL;
+ return;
+
+ case GARBAGE_ARGS:
+ error->re_status = RPC_CANTDECODEARGS;
+ return;
+
+ case SYSTEM_ERR:
+ error->re_status = RPC_SYSTEMERROR;
+ return;
+
+ case SUCCESS:
+ error->re_status = RPC_SUCCESS;
+ return;
+ }
+ /* NOTREACHED */
+ /* something's wrong, but we don't know what ... */
+ error->re_status = RPC_FAILED;
+ error->re_lb.s1 = (int32_t)MSG_ACCEPTED;
+ error->re_lb.s2 = (int32_t)acpt_stat;
+}
+
+static void
+rejected(rjct_stat, error)
+ enum reject_stat rjct_stat;
+ struct rpc_err *error;
+{
+
+ assert(error != NULL);
+
+ switch (rjct_stat) {
+ case RPC_MISMATCH:
+ error->re_status = RPC_VERSMISMATCH;
+ return;
+
+ case AUTH_ERROR:
+ error->re_status = RPC_AUTHERROR;
+ return;
+ }
+ /* something's wrong, but we don't know what ... */
+ /* NOTREACHED */
+ error->re_status = RPC_FAILED;
+ error->re_lb.s1 = (int32_t)MSG_DENIED;
+ error->re_lb.s2 = (int32_t)rjct_stat;
+}
+
+/*
+ * given a reply message, fills in the error
+ */
+void
+_seterr_reply(msg, error)
+ struct rpc_msg *msg;
+ struct rpc_err *error;
+{
+
+ assert(msg != NULL);
+ assert(error != NULL);
+
+ /* optimized for normal, SUCCESSful case */
+ switch (msg->rm_reply.rp_stat) {
+
+ case MSG_ACCEPTED:
+ if (msg->acpted_rply.ar_stat == SUCCESS) {
+ error->re_status = RPC_SUCCESS;
+ return;
+ }
+ accepted(msg->acpted_rply.ar_stat, error);
+ break;
+
+ case MSG_DENIED:
+ rejected(msg->rjcted_rply.rj_stat, error);
+ break;
+
+ default:
+ error->re_status = RPC_FAILED;
+ error->re_lb.s1 = (int32_t)(msg->rm_reply.rp_stat);
+ break;
+ }
+ switch (error->re_status) {
+
+ case RPC_VERSMISMATCH:
+ error->re_vers.low = msg->rjcted_rply.rj_vers.low;
+ error->re_vers.high = msg->rjcted_rply.rj_vers.high;
+ break;
+
+ case RPC_AUTHERROR:
+ error->re_why = msg->rjcted_rply.rj_why;
+ break;
+
+ case RPC_PROGVERSMISMATCH:
+ error->re_vers.low = msg->acpted_rply.ar_vers.low;
+ error->re_vers.high = msg->acpted_rply.ar_vers.high;
+ break;
+
+ case RPC_FAILED:
+ case RPC_SUCCESS:
+ case RPC_PROGNOTREGISTERED:
+ case RPC_PMAPFAILURE:
+ case RPC_UNKNOWNPROTO:
+ case RPC_UNKNOWNHOST:
+ case RPC_SYSTEMERROR:
+ case RPC_CANTDECODEARGS:
+ case RPC_PROCUNAVAIL:
+ case RPC_PROGUNAVAIL:
+ case RPC_TIMEDOUT:
+ case RPC_CANTRECV:
+ case RPC_CANTSEND:
+ case RPC_CANTDECODERES:
+ case RPC_CANTENCODEARGS:
+ default:
+ break;
+ }
+}
diff --git a/lib/libc/rpc/rpc_secure.3 b/lib/libc/rpc/rpc_secure.3
new file mode 100644
index 0000000..07c6314
--- /dev/null
+++ b/lib/libc/rpc/rpc_secure.3
@@ -0,0 +1,287 @@
+.\" @(#)rpc_secure.3n 2.1 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI
+.\" $FreeBSD$
+.\"
+.Dd February 16, 1988
+.Dt RPC 3
+.Os
+.Sh NAME
+.Nm rpc_secure
+.Nd library routines for secure remote procedure calls
+.Sh SYNOPSIS
+.In rpc/rpc.h
+.Ft AUTH *
+.Fo authdes_create
+.Fa "char *name"
+.Fa "unsigned window"
+.Fa "struct sockaddr *addr"
+.Fa "des_block *ckey"
+.Fc
+.Ft int
+.Fn authdes_getucred "struct authdes_cred *adc" "uid_t *uid" "gid_t *gid" "int *grouplen" "gid_t *groups"
+.Ft int
+.Fn getnetname "char *name"
+.Ft int
+.Fn host2netname "char *name" "const char *host" "const char *domain"
+.Ft int
+.Fn key_decryptsession "const char *remotename" "des_block *deskey"
+.Ft int
+.Fn key_encryptsession "const char *remotename" "des_block *deskey"
+.Ft int
+.Fn key_gendes "des_block *deskey"
+.Ft int
+.Fn key_setsecret "const char *key"
+.Ft int
+.Fn netname2host "char *name" "char *host" "int hostlen"
+.Ft int
+.Fn netname2user "char *name" "uid_t *uidp" "gid_t *gidp" "int *gidlenp" "gid_t *gidlist"
+.Ft int
+.Fn user2netname "char *name" "const uid_t uid" "const char *domain"
+.Sh DESCRIPTION
+These routines are part of the
+.Tn RPC
+library.
+They implement
+.Tn DES
+Authentication.
+See
+.Xr rpc 3
+for further details about
+.Tn RPC .
+.Pp
+The
+.Fn authdes_create
+is the first of two routines which interface to the
+.Tn RPC
+secure authentication system, known as
+.Tn DES
+authentication.
+The second is
+.Fn authdes_getucred ,
+below.
+.Pp
+Note: the keyserver daemon
+.Xr keyserv 8
+must be running for the
+.Tn DES
+authentication system to work.
+.Pp
+The
+.Fn authdes_create
+function,
+used on the client side, returns an authentication handle that
+will enable the use of the secure authentication system.
+The first argument
+.Fa name
+is the network name, or
+.Fa netname ,
+of the owner of the server process.
+This field usually
+represents a
+.Fa hostname
+derived from the utility routine
+.Fn host2netname ,
+but could also represent a user name using
+.Fn user2netname .
+The second field is window on the validity of
+the client credential, given in seconds.
+A small
+window is more secure than a large one, but choosing
+too small of a window will increase the frequency of
+resynchronizations because of clock drift.
+The third
+argument
+.Fa addr
+is optional.
+If it is
+.Dv NULL ,
+then the authentication system will assume
+that the local clock is always in sync with the server's
+clock, and will not attempt resynchronizations.
+If an address
+is supplied, however, then the system will use the address
+for consulting the remote time service whenever
+resynchronization
+is required.
+This argument is usually the
+address of the
+.Tn RPC
+server itself.
+The final argument
+.Fa ckey
+is also optional.
+If it is
+.Dv NULL ,
+then the authentication system will
+generate a random
+.Tn DES
+key to be used for the encryption of credentials.
+If it is supplied, however, then it will be used instead.
+.Pp
+The
+.Fn authdes_getucred
+function,
+the second of the two
+.Tn DES
+authentication routines,
+is used on the server side for converting a
+.Tn DES
+credential, which is
+operating system independent, into a
+.Ux
+credential.
+This routine differs from utility routine
+.Fn netname2user
+in that
+.Fn authdes_getucred
+pulls its information from a cache, and does not have to do a
+Yellow Pages lookup every time it is called to get its information.
+.Pp
+The
+.Fn getnetname
+function
+installs the unique, operating-system independent netname of
+the
+caller in the fixed-length array
+.Fa name .
+Returns
+.Dv TRUE
+if it succeeds and
+.Dv FALSE
+if it fails.
+.Pp
+The
+.Fn host2netname
+function
+converts from a domain-specific hostname to an
+operating-system independent netname.
+Returns
+.Dv TRUE
+if it succeeds and
+.Dv FALSE
+if it fails.
+Inverse of
+.Fn netname2host .
+.Pp
+The
+.Fn key_decryptsession
+function
+is an interface to the keyserver daemon, which is associated
+with
+.Tn RPC Ns 's
+secure authentication system
+.Tn ( DES
+authentication).
+User programs rarely need to call it, or its associated routines
+.Fn key_encryptsession ,
+.Fn key_gendes
+and
+.Fn key_setsecret .
+System commands such as
+.Xr login 1
+and the
+.Tn RPC
+library are the main clients of these four routines.
+.Pp
+The
+.Fn key_decryptsession
+function
+takes a server netname and a
+.Tn DES
+key, and decrypts the key by
+using the public key of the server and the secret key
+associated with the effective uid of the calling process.
+It
+is the inverse of
+.Fn key_encryptsession .
+.Pp
+The
+.Fn key_encryptsession
+function
+is a keyserver interface routine.
+It
+takes a server netname and a des key, and encrypts
+it using the public key of the server and the secret key
+associated with the effective uid of the calling process.
+It
+is the inverse of
+.Fn key_decryptsession .
+.Pp
+The
+.Fn key_gendes
+function
+is a keyserver interface routine.
+It
+is used to ask the keyserver for a secure conversation key.
+Choosing one
+.Qq random
+is usually not good enough,
+because
+the common ways of choosing random numbers, such as using the
+current time, are very easy to guess.
+.Pp
+The
+.Fn key_setsecret
+function
+is a keyserver interface routine.
+It is used to set the key for
+the effective
+.Fa uid
+of the calling process.
+.Pp
+The
+.Fn netname2host
+function
+converts from an operating-system independent netname to a
+domain-specific hostname.
+Returns
+.Dv TRUE
+if it succeeds and
+.Dv FALSE
+if it fails.
+Inverse of
+.Fn host2netname .
+.Pp
+The
+.Fn netname2user
+function
+converts from an operating-system independent netname to a
+domain-specific user ID.
+Returns
+.Dv TRUE
+if it succeeds and
+.Dv FALSE
+if it fails.
+Inverse of
+.Fn user2netname .
+.Pp
+The
+.Fn user2netname
+function
+converts from a domain-specific username to an operating-system
+independent netname.
+Returns
+.Dv TRUE
+if it succeeds and
+.Dv FALSE
+if it fails.
+Inverse of
+.Fn netname2user .
+.Sh SEE ALSO
+.Xr rpc 3 ,
+.Xr xdr 3 ,
+.Xr keyserv 8
+.Pp
+The following manuals:
+.Rs
+.%B Remote Procedure Calls: Protocol Specification
+.Re
+.Rs
+.%B Remote Procedure Call Programming Guide
+.Re
+.Rs
+.%B Rpcgen Programming Guide
+.Re
+.Rs
+.%B RPC: Remote Procedure Call Protocol Specification
+.%O RFC1050, Sun Microsystems Inc., USC-ISI
+.Re
diff --git a/lib/libc/rpc/rpc_soc.3 b/lib/libc/rpc/rpc_soc.3
new file mode 100644
index 0000000..8dedaa8
--- /dev/null
+++ b/lib/libc/rpc/rpc_soc.3
@@ -0,0 +1,1721 @@
+.\" @(#)rpc.3n 2.4 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI
+.\" $NetBSD: rpc_soc.3,v 1.2 2000/06/07 13:39:43 simonb Exp $
+.\" $FreeBSD$
+.\"
+.Dd February 16, 1988
+.Dt RPC_SOC 3
+.Os
+.Sh NAME
+.Nm rpc_soc ,
+.Nm auth_destroy ,
+.Nm authnone_create ,
+.Nm authunix_create ,
+.Nm authunix_create_default ,
+.Nm callrpc ,
+.Nm clnt_broadcast ,
+.Nm clnt_call ,
+.Nm clnt_control ,
+.Nm clnt_create ,
+.Nm clnt_destroy ,
+.Nm clnt_freeres ,
+.Nm clnt_geterr ,
+.Nm clnt_pcreateerror ,
+.Nm clnt_perrno ,
+.Nm clnt_perror ,
+.Nm clnt_spcreateerror ,
+.Nm clnt_sperrno ,
+.Nm clnt_sperror ,
+.Nm clntraw_create ,
+.Nm clnttcp_create ,
+.Nm clntudp_bufcreate ,
+.Nm clntudp_create ,
+.Nm clntunix_create ,
+.Nm get_myaddress ,
+.Nm pmap_getmaps ,
+.Nm pmap_getport ,
+.Nm pmap_rmtcall ,
+.Nm pmap_set ,
+.Nm pmap_unset ,
+.Nm registerrpc ,
+.Nm rpc_createerr ,
+.Nm svc_destroy ,
+.Nm svc_fds ,
+.Nm svc_fdset ,
+.Nm svc_getargs ,
+.Nm svc_getcaller ,
+.Nm svc_getreq ,
+.Nm svc_getreqset ,
+.Nm svc_register ,
+.Nm svc_run ,
+.Nm svc_sendreply ,
+.Nm svc_unregister ,
+.Nm svcerr_auth ,
+.Nm svcerr_decode ,
+.Nm svcerr_noproc ,
+.Nm svcerr_noprog ,
+.Nm svcerr_progvers ,
+.Nm svcerr_systemerr ,
+.Nm svcerr_weakauth ,
+.Nm svcfd_create ,
+.Nm svcunixfd_create ,
+.Nm svcraw_create ,
+.Nm svcunix_create ,
+.Nm xdr_accepted_reply ,
+.Nm xdr_authunix_parms ,
+.Nm xdr_callhdr ,
+.Nm xdr_callmsg ,
+.Nm xdr_opaque_auth ,
+.Nm xdr_pmap ,
+.Nm xdr_pmaplist ,
+.Nm xdr_rejected_reply ,
+.Nm xdr_replymsg ,
+.Nm xprt_register ,
+.Nm xprt_unregister
+.Nd "library routines for remote procedure calls"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In rpc/rpc.h
+.Pp
+See
+.Sx DESCRIPTION
+for function declarations.
+.Sh DESCRIPTION
+.Bf -symbolic
+The
+.Fn svc_*
+and
+.Fn clnt_*
+functions described in this page are the old, TS-RPC
+interface to the XDR and RPC library, and exist for backward compatibility.
+The new interface is described in the pages
+referenced from
+.Xr rpc 3 .
+.Ef
+.Pp
+These routines allow C programs to make procedure
+calls on other machines across the network.
+First, the client calls a procedure to send a
+data packet to the server.
+Upon receipt of the packet, the server calls a dispatch routine
+to perform the requested service, and then sends back a
+reply.
+Finally, the procedure call returns to the client.
+.Pp
+Routines that are used for Secure
+.Tn RPC ( DES
+authentication) are described in
+.Xr rpc_secure 3 .
+Secure
+.Tn RPC
+can be used only if
+.Tn DES
+encryption is available.
+.Pp
+.Bl -tag -width indent -compact
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn auth_destroy "AUTH *auth"
+.Xc
+.Pp
+A macro that destroys the authentication information associated with
+.Fa auth .
+Destruction usually involves deallocation of private data
+structures.
+The use of
+.Fa auth
+is undefined after calling
+.Fn auth_destroy .
+.Pp
+.It Xo
+.Ft "AUTH *"
+.Xc
+.It Xo
+.Fn authnone_create
+.Xc
+.Pp
+Create and return an
+.Tn RPC
+authentication handle that passes nonusable authentication
+information with each remote procedure call.
+This is the
+default authentication used by
+.Tn RPC .
+.Pp
+.It Xo
+.Ft "AUTH *"
+.Xc
+.It Xo
+.Fn authunix_create "char *host" "int uid" "int gid" "int len" "int *aup_gids"
+.Xc
+.Pp
+Create and return an
+.Tn RPC
+authentication handle that contains
+.Ux
+authentication information.
+The
+.Fa host
+argument
+is the name of the machine on which the information was
+created;
+.Fa uid
+is the user's user ID;
+.Fa gid
+is the user's current group ID;
+.Fa len
+and
+.Fa aup_gids
+refer to a counted array of groups to which the user belongs.
+It is easy to impersonate a user.
+.Pp
+.It Xo
+.Ft "AUTH *"
+.Xc
+.It Xo
+.Fn authunix_create_default
+.Xc
+.Pp
+Calls
+.Fn authunix_create
+with the appropriate arguments.
+.Pp
+.It Xo
+.Ft int
+.Fo callrpc
+.Fa "char *host"
+.Fa "u_long prognum"
+.Fa "u_long versnum"
+.Fa "u_long procnum"
+.Fa "xdrproc_t inproc"
+.Fa "void *in"
+.Fa "xdrproc_t outproc"
+.Fa "void *out"
+.Fc
+.Xc
+.Pp
+Call the remote procedure associated with
+.Fa prognum ,
+.Fa versnum ,
+and
+.Fa procnum
+on the machine
+.Fa host .
+The
+.Fa in
+argument
+is the address of the procedure's argument(s), and
+.Fa out
+is the address of where to place the result(s);
+.Fa inproc
+is used to encode the procedure's arguments, and
+.Fa outproc
+is used to decode the procedure's results.
+This routine returns zero if it succeeds, or the value of
+.Vt "enum clnt_stat"
+cast to an integer if it fails.
+The routine
+.Fn clnt_perrno
+is handy for translating failure statuses into messages.
+.Pp
+Warning: calling remote procedures with this routine
+uses
+.Tn UDP/IP
+as a transport; see
+.Fn clntudp_create
+for restrictions.
+You do not have control of timeouts or authentication using
+this routine.
+.Pp
+.It Xo
+.Ft "enum clnt_stat"
+.Xc
+.It Xo
+.Fo clnt_broadcast
+.Fa "u_long prognum"
+.Fa "u_long versnum"
+.Fa "u_long procnum"
+.Fa "xdrproc_t inproc"
+.Fa "char *in"
+.Fa "xdrproc_t outproc"
+.Fa "char *out"
+.Fa "bool_t (*eachresult)(caddr_t, struct sockaddr_in *)"
+.Fc
+.Xc
+.Pp
+Like
+.Fn callrpc ,
+except the call message is broadcast to all locally
+connected broadcast nets.
+Each time it receives a
+response, this routine calls
+.Fn eachresult ,
+whose form is:
+.Bd -ragged -offset indent
+.Ft bool_t
+.Fn eachresult "caddr_t out" "struct sockaddr_in *addr"
+.Ed
+.Pp
+where
+.Fa out
+is the same as
+.Fa out
+passed to
+.Fn clnt_broadcast ,
+except that the remote procedure's output is decoded there;
+.Fa addr
+points to the address of the machine that sent the results.
+If
+.Fn eachresult
+returns zero,
+.Fn clnt_broadcast
+waits for more replies; otherwise it returns with appropriate
+status.
+.Pp
+Warning: broadcast sockets are limited in size to the
+maximum transfer unit of the data link.
+For ethernet,
+this value is 1500 bytes.
+.Pp
+.It Xo
+.Ft "enum clnt_stat"
+.Xc
+.It Xo
+.Fo clnt_call
+.Fa "CLIENT *clnt"
+.Fa "u_long procnum"
+.Fa "xdrproc_t inproc"
+.Fa "char *in"
+.Fa "xdrproc_t outproc"
+.Fa "char *out"
+.Fa "struct timeval tout"
+.Fc
+.Xc
+.Pp
+A macro that calls the remote procedure
+.Fa procnum
+associated with the client handle,
+.Fa clnt ,
+which is obtained with an
+.Tn RPC
+client creation routine such as
+.Fn clnt_create .
+The
+.Fa in
+argument
+is the address of the procedure's argument(s), and
+.Fa out
+is the address of where to place the result(s);
+.Fa inproc
+is used to encode the procedure's arguments, and
+.Fa outproc
+is used to decode the procedure's results;
+.Fa tout
+is the time allowed for results to come back.
+.Pp
+.It Xo
+.Ft void
+.Fn clnt_destroy "CLIENT *clnt"
+.Xc
+.Pp
+A macro that destroys the client's
+.Tn RPC
+handle.
+Destruction usually involves deallocation
+of private data structures, including
+.Fa clnt
+itself.
+Use of
+.Fa clnt
+is undefined after calling
+.Fn clnt_destroy .
+If the
+.Tn RPC
+library opened the associated socket, it will close it also.
+Otherwise, the socket remains open.
+.Pp
+.It Xo
+.Ft CLIENT *
+.Xc
+.It Xo
+.Fn clnt_create "char *host" "u_long prog" "u_long vers" "char *proto"
+.Xc
+.Pp
+Generic client creation routine.
+The
+.Fa host
+argument
+identifies the name of the remote host where the server
+is located.
+The
+.Fa proto
+argument
+indicates which kind of transport protocol to use.
+The
+currently supported values for this field are
+.Qq Li udp
+and
+.Qq Li tcp .
+Default timeouts are set, but can be modified using
+.Fn clnt_control .
+.Pp
+Warning: Using
+.Tn UDP
+has its shortcomings.
+Since
+.Tn UDP Ns \-based
+.Tn RPC
+messages can only hold up to 8 Kbytes of encoded data,
+this transport cannot be used for procedures that take
+large arguments or return huge results.
+.Pp
+.It Xo
+.Ft bool_t
+.Xc
+.It Xo
+.Fn clnt_control "CLIENT *cl" "u_int req" "char *info"
+.Xc
+.Pp
+A macro used to change or retrieve various information
+about a client object.
+The
+.Fa req
+argument
+indicates the type of operation, and
+.Fa info
+is a pointer to the information.
+For both
+.Tn UDP
+and
+.Tn TCP ,
+the supported values of
+.Fa req
+and their argument types and what they do are:
+.Bl -column "CLSET_RETRY_TIMEOUT" "struct sockaddr_in"
+.It Dv CLSET_TIMEOUT Ta
+.Vt "struct timeval" Ta "set total timeout"
+.It Dv CLGET_TIMEOUT Ta
+.Vt "struct timeval" Ta "get total timeout"
+.El
+.Pp
+Note: if you set the timeout using
+.Fn clnt_control ,
+the timeout argument passed to
+.Fn clnt_call
+will be ignored in all future calls.
+.Bl -column "CLSET_RETRY_TIMEOUT" "struct sockaddr_in"
+.It Dv CLGET_SERVER_ADDR Ta
+.Vt "struct sockaddr_in" Ta "get server's address"
+.El
+.Pp
+The following operations are valid for
+.Tn UDP
+only:
+.Bl -column "CLSET_RETRY_TIMEOUT" "struct sockaddr_in"
+.It Dv CLSET_RETRY_TIMEOUT Ta
+.Vt "struct timeval" Ta "set the retry timeout"
+.It Dv CLGET_RETRY_TIMEOUT Ta
+.Vt "struct timeval" Ta "get the retry timeout"
+.El
+.Pp
+The retry timeout is the time that
+.Tn "UDP RPC"
+waits for the server to reply before
+retransmitting the request.
+.Pp
+.It Xo
+.Ft bool_t
+.Fn clnt_freeres "CLIENT *clnt" "xdrproc_t outproc" "char *out"
+.Xc
+.Pp
+A macro that frees any data allocated by the
+.Tn RPC/XDR
+system when it decoded the results of an
+.Tn RPC
+call.
+The
+.Fa out
+argument
+is the address of the results, and
+.Fa outproc
+is the
+.Tn XDR
+routine describing the results.
+This routine returns one if the results were successfully
+freed,
+and zero otherwise.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn clnt_geterr "CLIENT *clnt" "struct rpc_err *errp"
+.Xc
+.Pp
+A macro that copies the error structure out of the client
+handle
+to the structure at address
+.Fa errp .
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn clnt_pcreateerror "char *s"
+.Xc
+.Pp
+prints a message to standard error indicating
+why a client
+.Tn RPC
+handle could not be created.
+The message is prepended with string
+.Fa s
+and a colon.
+A newline is appended at the end of the message.
+Used when a
+.Fn clnt_create ,
+.Fn clntraw_create ,
+.Fn clnttcp_create ,
+or
+.Fn clntudp_create
+call fails.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn clnt_perrno "enum clnt_stat stat"
+.Xc
+.Pp
+Print a message to standard error corresponding
+to the condition indicated by
+.Fa stat .
+A newline is appended at the end of the message.
+Used after
+.Fn callrpc .
+.Pp
+.It Xo
+.Ft void
+.Fn clnt_perror "CLIENT *clnt" "char *s"
+.Xc
+.Pp
+Print a message to standard error indicating why an
+.Tn RPC
+call failed;
+.Fa clnt
+is the handle used to do the call.
+The message is prepended with string
+.Fa s
+and a colon.
+A newline is appended at the end of the message.
+Used after
+.Fn clnt_call .
+.Pp
+.It Xo
+.Ft "char *"
+.Xc
+.It Xo
+.Fn clnt_spcreateerror "char *s"
+.Xc
+.Pp
+Like
+.Fn clnt_pcreateerror ,
+except that it returns a string
+instead of printing to the standard error.
+.Pp
+Bugs: returns pointer to static data that is overwritten
+on each call.
+.Pp
+.It Xo
+.Ft "char *"
+.Xc
+.It Xo
+.Fn clnt_sperrno "enum clnt_stat stat"
+.Xc
+.Pp
+Take the same arguments as
+.Fn clnt_perrno ,
+but instead of sending a message to the standard error
+indicating why an
+.Tn RPC
+call failed, return a pointer to a string which contains
+the message.
+.Pp
+The
+.Fn clnt_sperrno
+function
+is used instead of
+.Fn clnt_perrno
+if the program does not have a standard error (as a program
+running as a server quite likely does not), or if the
+programmer
+does not want the message to be output with
+.Fn printf ,
+or if a message format different from that supported by
+.Fn clnt_perrno
+is to be used.
+.Pp
+Note: unlike
+.Fn clnt_sperror
+and
+.Fn clnt_spcreateerror ,
+.Fn clnt_sperrno
+returns pointer to static data, but the
+result will not get overwritten on each call.
+.Pp
+.It Xo
+.Ft "char *"
+.Xc
+.It Xo
+.Fn clnt_sperror "CLIENT *rpch" "char *s"
+.Xc
+.Pp
+Like
+.Fn clnt_perror ,
+except that (like
+.Fn clnt_sperrno )
+it returns a string instead of printing to standard error.
+.Pp
+Bugs: returns pointer to static data that is overwritten
+on each call.
+.Pp
+.It Xo
+.Ft "CLIENT *"
+.Xc
+.It Xo
+.Fn clntraw_create "u_long prognum" "u_long versnum"
+.Xc
+.Pp
+This routine creates a toy
+.Tn RPC
+client for the remote program
+.Fa prognum ,
+version
+.Fa versnum .
+The transport used to pass messages to the service is
+actually a buffer within the process's address space, so the
+corresponding
+.Tn RPC
+server should live in the same address space; see
+.Fn svcraw_create .
+This allows simulation of
+.Tn RPC
+and acquisition of
+.Tn RPC
+overheads, such as round trip times, without any
+kernel interference.
+This routine returns
+.Dv NULL
+if it fails.
+.Pp
+.It Xo
+.Ft "CLIENT *"
+.Xc
+.It Xo
+.Fo clnttcp_create
+.Fa "struct sockaddr_in *addr"
+.Fa "u_long prognum"
+.Fa "u_long versnum"
+.Fa "int *sockp"
+.Fa "u_int sendsz"
+.Fa "u_int recvsz"
+.Fc
+.Xc
+.Pp
+This routine creates an
+.Tn RPC
+client for the remote program
+.Fa prognum ,
+version
+.Fa versnum ;
+the client uses
+.Tn TCP/IP
+as a transport.
+The remote program is located at Internet
+address
+.Fa addr .
+If
+.Fa addr\->sin_port
+is zero, then it is set to the actual port that the remote
+program is listening on (the remote
+.Xr rpcbind 8
+service is consulted for this information).
+The
+.Fa sockp
+argument
+is a socket; if it is
+.Dv RPC_ANYSOCK ,
+then this routine opens a new one and sets
+.Fa sockp .
+Since
+.Tn TCP Ns \-based
+.Tn RPC
+uses buffered
+.Tn I/O ,
+the user may specify the size of the send and receive buffers
+with the
+.Fa sendsz
+and
+.Fa recvsz
+arguments;
+values of zero choose suitable defaults.
+This routine returns
+.Dv NULL
+if it fails.
+.Pp
+.It Xo
+.Ft "CLIENT *"
+.Xc
+.It Xo
+.Fo clntudp_create
+.Fa "struct sockaddr_in *addr"
+.Fa "u_long prognum"
+.Fa "u_long versnum"
+.Fa "struct timeval wait"
+.Fa "int *sockp"
+.Fc
+.Xc
+.Pp
+This routine creates an
+.Tn RPC
+client for the remote program
+.Fa prognum ,
+version
+.Fa versnum ;
+the client uses
+.Tn UDP/IP
+as a transport.
+The remote program is located at Internet
+address
+.Fa addr .
+If
+.Fa addr\->sin_port
+is zero, then it is set to actual port that the remote
+program is listening on (the remote
+.Xr rpcbind 8
+service is consulted for this information).
+The
+.Fa sockp
+argument
+is a socket; if it is
+.Dv RPC_ANYSOCK ,
+then this routine opens a new one and sets
+.Fa sockp .
+The
+.Tn UDP
+transport resends the call message in intervals of
+.Fa wait
+time until a response is received or until the call times
+out.
+The total time for the call to time out is specified by
+.Fn clnt_call .
+.Pp
+Warning: since
+.Tn UDP Ns \-based
+.Tn RPC
+messages can only hold up to 8 Kbytes
+of encoded data, this transport cannot be used for procedures
+that take large arguments or return huge results.
+.Pp
+.It Xo
+.Ft "CLIENT *"
+.Xc
+.It Xo
+.Fo clntudp_bufcreate
+.Fa "struct sockaddr_in *addr"
+.Fa "u_long prognum"
+.Fa "u_long versnum"
+.Fa "struct timeval wait"
+.Fa "int *sockp"
+.Fa "unsigned int sendsize"
+.Fa "unsigned int recosize"
+.Fc
+.Xc
+.Pp
+This routine creates an
+.Tn RPC
+client for the remote program
+.Fa prognum ,
+on
+.Fa versnum ;
+the client uses
+.Tn UDP/IP
+as a transport.
+The remote program is located at Internet
+address
+.Fa addr .
+If
+.Fa addr\->sin_port
+is zero, then it is set to actual port that the remote
+program is listening on (the remote
+.Xr rpcbind 8
+service is consulted for this information).
+The
+.Fa sockp
+argument
+is a socket; if it is
+.Dv RPC_ANYSOCK ,
+then this routine opens a new one and sets
+.Fa sockp .
+The
+.Tn UDP
+transport resends the call message in intervals of
+.Fa wait
+time until a response is received or until the call times
+out.
+The total time for the call to time out is specified by
+.Fn clnt_call .
+.Pp
+This allows the user to specify the maximum packet size
+for sending and receiving
+.Tn UDP Ns \-based
+.Tn RPC
+messages.
+.Pp
+.It Xo
+.Ft "CLIENT *"
+.Xc
+.It Xo
+.Fo clntunix_create
+.Fa "struct sockaddr_un *raddr"
+.Fa "u_long prognum"
+.Fa "u_long versnum"
+.Fa "int *sockp"
+.Fa "u_int sendsz"
+.Fa "u_int recvsz"
+.Fc
+.Xc
+.Pp
+This routine creates an
+.Tn RPC
+client for the local
+program
+.Fa prognum ,
+version
+.Fa versnum ;
+the client uses
+.Ux Ns -domain
+sockets as a transport.
+The local program is located at the
+.Fa *raddr .
+The
+.Fa sockp
+argument
+is a socket; if it is
+.Dv RPC_ANYSOCK ,
+then this routine opens a new one and sets
+.Fa sockp .
+Since
+.Ux Ns -based
+.Tn RPC
+uses buffered
+.Tn I/O ,
+the user may specify the size of the send and receive buffers
+with the
+.Fa sendsz
+and
+.Fa recvsz
+arguments;
+values of zero choose suitable defaults.
+This routine returns
+.Dv NULL
+if it fails.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn get_myaddress "struct sockaddr_in *addr"
+.Xc
+.Pp
+Stuff the machine's
+.Tn IP
+address into
+.Fa addr ,
+without consulting the library routines that deal with
+.Pa /etc/hosts .
+The port number is always set to
+.Fn htons PMAPPORT .
+Returns zero on success, non-zero on failure.
+.Pp
+.It Xo
+.Ft "struct pmaplist *"
+.Xc
+.It Xo
+.Fn pmap_getmaps "struct sockaddr_in *addr"
+.Xc
+.Pp
+A user interface to the
+.Xr rpcbind 8
+service, which returns a list of the current
+.Tn RPC
+program\-to\-port mappings
+on the host located at
+.Tn IP
+address
+.Fa addr .
+This routine can return
+.Dv NULL .
+The command
+.Dq Nm rpcinfo Fl p
+uses this routine.
+.Pp
+.It Xo
+.Ft u_short
+.Xc
+.It Xo
+.Fo pmap_getport
+.Fa "struct sockaddr_in *addr"
+.Fa "u_long prognum"
+.Fa "u_long versnum"
+.Fa "u_long protocol"
+.Fc
+.Xc
+.Pp
+A user interface to the
+.Xr rpcbind 8
+service, which returns the port number
+on which waits a service that supports program number
+.Fa prognum ,
+version
+.Fa versnum ,
+and speaks the transport protocol associated with
+.Fa protocol .
+The value of
+.Fa protocol
+is most likely
+.Dv IPPROTO_UDP
+or
+.Dv IPPROTO_TCP .
+A return value of zero means that the mapping does not exist
+or that
+the
+.Tn RPC
+system failed to contact the remote
+.Xr rpcbind 8
+service.
+In the latter case, the global variable
+.Va rpc_createerr
+contains the
+.Tn RPC
+status.
+.Pp
+.It Xo
+.Ft "enum clnt_stat"
+.Xc
+.It Xo
+.Fo pmap_rmtcall
+.Fa "struct sockaddr_in *addr"
+.Fa "u_long prognum"
+.Fa "u_long versnum"
+.Fa "u_long procnum"
+.Fa "xdrproc_t inproc"
+.Fa "char *in"
+.Fa "xdrproc_t outproc"
+.Fa "char *out"
+.Fa "struct timeval tout"
+.Fa "u_long *portp"
+.Fc
+.Xc
+.Pp
+A user interface to the
+.Xr rpcbind 8
+service, which instructs
+.Xr rpcbind 8
+on the host at
+.Tn IP
+address
+.Fa addr
+to make an
+.Tn RPC
+call on your behalf to a procedure on that host.
+The
+.Fa portp
+argument
+will be modified to the program's port number if the
+procedure
+succeeds.
+The definitions of other arguments are discussed
+in
+.Fn callrpc
+and
+.Fn clnt_call .
+This procedure should be used for a
+.Dq ping
+and nothing
+else.
+See also
+.Fn clnt_broadcast .
+.Pp
+.It Xo
+.Ft bool_t
+.Fn pmap_set "u_long prognum" "u_long versnum" "u_long protocol" "u_short port"
+.Xc
+.Pp
+A user interface to the
+.Xr rpcbind 8
+service, which establishes a mapping between the triple
+.Pq Fa prognum , versnum , protocol
+and
+.Fa port
+on the machine's
+.Xr rpcbind 8
+service.
+The value of
+.Fa protocol
+is most likely
+.Dv IPPROTO_UDP
+or
+.Dv IPPROTO_TCP .
+This routine returns one if it succeeds, zero otherwise.
+Automatically done by
+.Fn svc_register .
+.Pp
+.It Xo
+.Ft bool_t
+.Fn pmap_unset "u_long prognum" "u_long versnum"
+.Xc
+.Pp
+A user interface to the
+.Xr rpcbind 8
+service, which destroys all mapping between the triple
+.Pq Fa prognum , versnum , *
+and
+.Fa ports
+on the machine's
+.Xr rpcbind 8
+service.
+This routine returns one if it succeeds, zero
+otherwise.
+.Pp
+.It Xo
+.Ft bool_t
+.Fo registerrpc
+.Fa "u_long prognum"
+.Fa "u_long versnum"
+.Fa "u_long procnum"
+.Fa "char *(*procname)(void)"
+.Fa "xdrproc_t inproc"
+.Fa "xdrproc_t outproc"
+.Fc
+.Xc
+.Pp
+Register procedure
+.Fa procname
+with the
+.Tn RPC
+service package.
+If a request arrives for program
+.Fa prognum ,
+version
+.Fa versnum ,
+and procedure
+.Fa procnum ,
+.Fa procname
+is called with a pointer to its argument(s);
+.Fa progname
+should return a pointer to its static result(s);
+.Fa inproc
+is used to decode the arguments while
+.Fa outproc
+is used to encode the results.
+This routine returns zero if the registration succeeded, \-1
+otherwise.
+.Pp
+Warning: remote procedures registered in this form
+are accessed using the
+.Tn UDP/IP
+transport; see
+.Fn svcudp_create
+for restrictions.
+.Pp
+.It Xo
+.Vt "struct rpc_createerr" rpc_createerr ;
+.Xc
+.Pp
+A global variable whose value is set by any
+.Tn RPC
+client creation routine
+that does not succeed.
+Use the routine
+.Fn clnt_pcreateerror
+to print the reason why.
+.Pp
+.It Xo
+.Ft bool_t
+.Fn svc_destroy "SVCXPRT * xprt"
+.Xc
+.Pp
+A macro that destroys the
+.Tn RPC
+service transport handle,
+.Fa xprt .
+Destruction usually involves deallocation
+of private data structures, including
+.Fa xprt
+itself.
+Use of
+.Fa xprt
+is undefined after calling this routine.
+.Pp
+.It Xo
+.Vt fd_set svc_fdset ;
+.Xc
+.Pp
+A global variable reflecting the
+.Tn RPC
+service side's
+read file descriptor bit mask; it is suitable as a template argument
+to the
+.Xr select 2
+system call.
+This is only of interest
+if a service implementor does not call
+.Fn svc_run ,
+but rather does his own asynchronous event processing.
+This variable is read\-only (do not pass its address to
+.Xr select 2 ! ) ,
+yet it may change after calls to
+.Fn svc_getreqset
+or any creation routines.
+As well, note that if the process has descriptor limits
+which are extended beyond
+.Dv FD_SETSIZE ,
+this variable will only be usable for the first
+.Dv FD_SETSIZE
+descriptors.
+.Pp
+.It Xo
+.Vt int svc_fds ;
+.Xc
+.Pp
+Similar to
+.Va svc_fdset ,
+but limited to 32 descriptors.
+This
+interface is obsoleted by
+.Va svc_fdset .
+.Pp
+.It Xo
+.Ft bool_t
+.Fn svc_freeargs "SVCXPRT *xprt" "xdrproc_t inproc" "char *in"
+.Xc
+.Pp
+A macro that frees any data allocated by the
+.Tn RPC/XDR
+system when it decoded the arguments to a service procedure
+using
+.Fn svc_getargs .
+This routine returns 1 if the results were successfully
+freed,
+and zero otherwise.
+.Pp
+.It Xo
+.Ft bool_t
+.Fn svc_getargs "SVCXPRT *xprt" "xdrproc_t inproc" "char *in"
+.Xc
+.Pp
+A macro that decodes the arguments of an
+.Tn RPC
+request
+associated with the
+.Tn RPC
+service transport handle,
+.Fa xprt .
+The
+.Fa in
+argument
+is the address where the arguments will be placed;
+.Fa inproc
+is the
+.Tn XDR
+routine used to decode the arguments.
+This routine returns one if decoding succeeds, and zero
+otherwise.
+.Pp
+.It Xo
+.Ft "struct sockaddr_in *"
+.Xc
+.It Xo
+.Fn svc_getcaller "SVCXPRT *xprt"
+.Xc
+.Pp
+The approved way of getting the network address of the caller
+of a procedure associated with the
+.Tn RPC
+service transport handle,
+.Fa xprt .
+.Pp
+.It Xo
+.Ft void
+.Fn svc_getreqset "fd_set *rdfds"
+.Xc
+.Pp
+This routine is only of interest if a service implementor
+does not call
+.Fn svc_run ,
+but instead implements custom asynchronous event processing.
+It is called when the
+.Xr select 2
+system call has determined that an
+.Tn RPC
+request has arrived on some
+.Tn RPC
+socket(s);
+.Fa rdfds
+is the resultant read file descriptor bit mask.
+The routine returns when all sockets associated with the
+value of
+.Fa rdfds
+have been serviced.
+.Pp
+.It Xo
+.Ft void
+.Fn svc_getreq "int rdfds"
+.Xc
+.Pp
+Similar to
+.Fn svc_getreqset ,
+but limited to 32 descriptors.
+This interface is obsoleted by
+.Fn svc_getreqset .
+.Pp
+.It Xo
+.Ft bool_t
+.Fo svc_register
+.Fa "SVCXPRT *xprt"
+.Fa "u_long prognum"
+.Fa "u_long versnum"
+.Fa "void (*dispatch)(struct svc_req *, SVCXPRT *)"
+.Fa "int protocol"
+.Fc
+.Xc
+.Pp
+Associates
+.Fa prognum
+and
+.Fa versnum
+with the service dispatch procedure,
+.Fn dispatch .
+If
+.Fa protocol
+is zero, the service is not registered with the
+.Xr rpcbind 8
+service.
+If
+.Fa protocol
+is non-zero, then a mapping of the triple
+.Pq Fa prognum , versnum , protocol
+to
+.Fa xprt\->xp_port
+is established with the local
+.Xr rpcbind 8
+service (generally
+.Fa protocol
+is zero,
+.Dv IPPROTO_UDP
+or
+.Dv IPPROTO_TCP ) .
+The procedure
+.Fn dispatch
+has the following form:
+.Bd -ragged -offset indent
+.Ft bool_t
+.Fn dispatch "struct svc_req *request" "SVCXPRT *xprt"
+.Ed
+.Pp
+The
+.Fn svc_register
+routine returns one if it succeeds, and zero otherwise.
+.Pp
+.It Xo
+.Fn svc_run
+.Xc
+.Pp
+This routine never returns.
+It waits for
+.Tn RPC
+requests to arrive, and calls the appropriate service
+procedure using
+.Fn svc_getreq
+when one arrives.
+This procedure is usually waiting for a
+.Xr select 2
+system call to return.
+.Pp
+.It Xo
+.Ft bool_t
+.Fn svc_sendreply "SVCXPRT *xprt" "xdrproc_t outproc" "char *out"
+.Xc
+.Pp
+Called by an
+.Tn RPC
+service's dispatch routine to send the results of a
+remote procedure call.
+The
+.Fa xprt
+argument
+is the request's associated transport handle;
+.Fa outproc
+is the
+.Tn XDR
+routine which is used to encode the results; and
+.Fa out
+is the address of the results.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn svc_unregister "u_long prognum" "u_long versnum"
+.Xc
+.Pp
+Remove all mapping of the double
+.Pq Fa prognum , versnum
+to dispatch routines, and of the triple
+.Pq Fa prognum , versnum , *
+to port number.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn svcerr_auth "SVCXPRT *xprt" "enum auth_stat why"
+.Xc
+.Pp
+Called by a service dispatch routine that refuses to perform
+a remote procedure call due to an authentication error.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn svcerr_decode "SVCXPRT *xprt"
+.Xc
+.Pp
+Called by a service dispatch routine that cannot successfully
+decode its arguments.
+See also
+.Fn svc_getargs .
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn svcerr_noproc "SVCXPRT *xprt"
+.Xc
+.Pp
+Called by a service dispatch routine that does not implement
+the procedure number that the caller requests.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn svcerr_noprog "SVCXPRT *xprt"
+.Xc
+.Pp
+Called when the desired program is not registered with the
+.Tn RPC
+package.
+Service implementors usually do not need this routine.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn svcerr_progvers "SVCXPRT *xprt" "u_long low_vers" "u_long high_vers"
+.Xc
+.Pp
+Called when the desired version of a program is not registered
+with the
+.Tn RPC
+package.
+Service implementors usually do not need this routine.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn svcerr_systemerr "SVCXPRT *xprt"
+.Xc
+.Pp
+Called by a service dispatch routine when it detects a system
+error
+not covered by any particular protocol.
+For example, if a service can no longer allocate storage,
+it may call this routine.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn svcerr_weakauth "SVCXPRT *xprt"
+.Xc
+.Pp
+Called by a service dispatch routine that refuses to perform
+a remote procedure call due to insufficient
+authentication arguments.
+The routine calls
+.Fn svcerr_auth xprt AUTH_TOOWEAK .
+.Pp
+.It Xo
+.Ft "SVCXPRT *"
+.Xc
+.It Xo
+.Fn svcraw_create void
+.Xc
+.Pp
+This routine creates a toy
+.Tn RPC
+service transport, to which it returns a pointer.
+The transport
+is really a buffer within the process's address space,
+so the corresponding
+.Tn RPC
+client should live in the same
+address space;
+see
+.Fn clntraw_create .
+This routine allows simulation of
+.Tn RPC
+and acquisition of
+.Tn RPC
+overheads (such as round trip times), without any kernel
+interference.
+This routine returns
+.Dv NULL
+if it fails.
+.Pp
+.It Xo
+.Ft "SVCXPRT *"
+.Xc
+.It Xo
+.Fn svctcp_create "int sock" "u_int send_buf_size" "u_int recv_buf_size"
+.Xc
+.Pp
+This routine creates a
+.Tn TCP/IP Ns \-based
+.Tn RPC
+service transport, to which it returns a pointer.
+The transport is associated with the socket
+.Fa sock ,
+which may be
+.Dv RPC_ANYSOCK ,
+in which case a new socket is created.
+If the socket is not bound to a local
+.Tn TCP
+port, then this routine binds it to an arbitrary port.
+Upon completion,
+.Fa xprt\->xp_fd
+is the transport's socket descriptor, and
+.Fa xprt\->xp_port
+is the transport's port number.
+This routine returns
+.Dv NULL
+if it fails.
+Since
+.Tn TCP Ns \-based
+.Tn RPC
+uses buffered
+.Tn I/O ,
+users may specify the size of buffers; values of zero
+choose suitable defaults.
+.Pp
+.It Xo
+.Ft "SVCXPRT *"
+.Xc
+.It Xo
+.Fn svcunix_create "int sock" "u_int send_buf_size" "u_int recv_buf_size" "char *path"
+.Xc
+.Pp
+This routine creates a
+.Ux Ns -based
+.Tn RPC
+service transport, to which it returns a pointer.
+The transport is associated with the socket
+.Fa sock ,
+which may be
+.Dv RPC_ANYSOCK ,
+in which case a new socket is created.
+The
+.Fa *path
+argument
+is a variable-length file system pathname of
+at most 104 characters.
+This file is
+.Em not
+removed when the socket is closed.
+The
+.Xr unlink 2
+system call must be used to remove the file.
+Upon completion,
+.Fa xprt\->xp_fd
+is the transport's socket descriptor.
+This routine returns
+.Dv NULL
+if it fails.
+Since
+.Ux Ns -based
+.Tn RPC
+uses buffered
+.Tn I/O ,
+users may specify the size of buffers; values of zero
+choose suitable defaults.
+.Pp
+.It Xo
+.Ft "SVCXPRT *"
+.Xc
+.It Xo
+.Fn svcunixfd_create "int fd" "u_int sendsize" "u_int recvsize"
+.Xc
+.Pp
+Create a service on top of any open descriptor.
+The
+.Fa sendsize
+and
+.Fa recvsize
+arguments
+indicate sizes for the send and receive buffers.
+If they are
+zero, a reasonable default is chosen.
+.Pp
+.It Xo
+.Ft "SVCXPRT *"
+.Xc
+.It Xo
+.Fn svcfd_create "int fd" "u_int sendsize" "u_int recvsize"
+.Xc
+.Pp
+Create a service on top of any open descriptor.
+Typically,
+this
+descriptor is a connected socket for a stream protocol such
+as
+.Tn TCP .
+The
+.Fa sendsize
+and
+.Fa recvsize
+arguments
+indicate sizes for the send and receive buffers.
+If they are
+zero, a reasonable default is chosen.
+.Pp
+.It Xo
+.Ft "SVCXPRT *"
+.Xc
+.It Xo
+.Fn svcudp_bufcreate "int sock" "u_int sendsize" "u_int recvsize"
+.Xc
+.Pp
+This routine creates a
+.Tn UDP/IP Ns \-based
+.Tn RPC
+service transport, to which it returns a pointer.
+The transport is associated with the socket
+.Fa sock ,
+which may be
+.Dv RPC_ANYSOCK ,
+in which case a new socket is created.
+If the socket is not bound to a local
+.Tn UDP
+port, then this routine binds it to an arbitrary port.
+Upon
+completion,
+.Fa xprt\->xp_fd
+is the transport's socket descriptor, and
+.Fa xprt\->xp_port
+is the transport's port number.
+This routine returns
+.Dv NULL
+if it fails.
+.Pp
+This allows the user to specify the maximum packet size for sending and
+receiving
+.Tn UDP Ns \-based
+.Tn RPC
+messages.
+.Pp
+.It Xo
+.Ft bool_t
+.Fn xdr_accepted_reply "XDR *xdrs" "struct accepted_reply *ar"
+.Xc
+.Pp
+Used for encoding
+.Tn RPC
+reply messages.
+This routine is useful for users who
+wish to generate
+.Tn RPC Ns \-style
+messages without using the
+.Tn RPC
+package.
+.Pp
+.It Xo
+.Ft bool_t
+.Fn xdr_authunix_parms "XDR *xdrs" "struct authunix_parms *aupp"
+.Xc
+.Pp
+Used for describing
+.Ux
+credentials.
+This routine is useful for users
+who wish to generate these credentials without using the
+.Tn RPC
+authentication package.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Ft bool_t
+.Fn xdr_callhdr "XDR *xdrs" "struct rpc_msg *chdr"
+.Xc
+.Pp
+Used for describing
+.Tn RPC
+call header messages.
+This routine is useful for users who wish to generate
+.Tn RPC Ns \-style
+messages without using the
+.Tn RPC
+package.
+.Pp
+.It Xo
+.Ft bool_t
+.Fn xdr_callmsg "XDR *xdrs" "struct rpc_msg *cmsg"
+.Xc
+.Pp
+Used for describing
+.Tn RPC
+call messages.
+This routine is useful for users who wish to generate
+.Tn RPC Ns \-style
+messages without using the
+.Tn RPC
+package.
+.Pp
+.It Xo
+.Ft bool_t
+.Fn xdr_opaque_auth "XDR *xdrs" "struct opaque_auth *ap"
+.Xc
+.Pp
+Used for describing
+.Tn RPC
+authentication information messages.
+This routine is useful for users who wish to generate
+.Tn RPC Ns \-style
+messages without using the
+.Tn RPC
+package.
+.Pp
+.It Xo
+.Vt struct pmap ;
+.Xc
+.It Xo
+.Ft bool_t
+.Fn xdr_pmap "XDR *xdrs" "struct pmap *regs"
+.Xc
+.Pp
+Used for describing arguments to various
+.Xr rpcbind 8
+procedures, externally.
+This routine is useful for users who wish to generate
+these arguments without using the
+.Fn pmap_*
+interface.
+.Pp
+.It Xo
+.Ft bool_t
+.Fn xdr_pmaplist "XDR *xdrs" "struct pmaplist **rp"
+.Xc
+.Pp
+Used for describing a list of port mappings, externally.
+This routine is useful for users who wish to generate
+these arguments without using the
+.Fn pmap_*
+interface.
+.Pp
+.It Xo
+.Ft bool_t
+.Fn xdr_rejected_reply "XDR *xdrs" "struct rejected_reply *rr"
+.Xc
+.Pp
+Used for describing
+.Tn RPC
+reply messages.
+This routine is useful for users who wish to generate
+.Tn RPC Ns \-style
+messages without using the
+.Tn RPC
+package.
+.Pp
+.It Xo
+.Ft bool_t
+.Fn xdr_replymsg "XDR *xdrs" "struct rpc_msg *rmsg"
+.Xc
+.Pp
+Used for describing
+.Tn RPC
+reply messages.
+This routine is useful for users who wish to generate
+.Tn RPC
+style messages without using the
+.Tn RPC
+package.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn xprt_register "SVCXPRT *xprt"
+.Xc
+.Pp
+After
+.Tn RPC
+service transport handles are created,
+they should register themselves with the
+.Tn RPC
+service package.
+This routine modifies the global variable
+.Va svc_fds .
+Service implementors usually do not need this routine.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn xprt_unregister "SVCXPRT *xprt"
+.Xc
+.Pp
+Before an
+.Tn RPC
+service transport handle is destroyed,
+it should unregister itself with the
+.Tn RPC
+service package.
+This routine modifies the global variable
+.Va svc_fds .
+Service implementors usually do not need this routine.
+.El
+.Sh SEE ALSO
+.Xr rpc_secure 3 ,
+.Xr xdr 3
+.Rs
+.%T "Remote Procedure Calls: Protocol Specification"
+.Re
+.Rs
+.%T "Remote Procedure Call Programming Guide"
+.Re
+.Rs
+.%T "rpcgen Programming Guide"
+.Re
+.Rs
+.%T "RPC: Remote Procedure Call Protocol Specification"
+.%O RFC1050
+.%Q "Sun Microsystems, Inc., USC-ISI"
+.Re
diff --git a/lib/libc/rpc/rpc_soc.c b/lib/libc/rpc/rpc_soc.c
new file mode 100644
index 0000000..2568d43
--- /dev/null
+++ b/lib/libc/rpc/rpc_soc.c
@@ -0,0 +1,582 @@
+/* $NetBSD: rpc_soc.c,v 1.6 2000/07/06 03:10:35 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/* #ident "@(#)rpc_soc.c 1.17 94/04/24 SMI" */
+
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ * In addition, portions of such source code were derived from Berkeley
+ * 4.3 BSD under license from the Regents of the University of
+ * California.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rpc_soc.c 1.41 89/05/02 Copyr 1988 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef PORTMAP
+/*
+ * rpc_soc.c
+ *
+ * The backward compatibility routines for the earlier implementation
+ * of RPC, where the only transports supported were tcp/ip and udp/ip.
+ * Based on berkeley socket abstraction, now implemented on the top
+ * of TLI/Streams
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <stdio.h>
+#include <rpc/rpc.h>
+#include <rpc/pmap_clnt.h>
+#include <rpc/pmap_prot.h>
+#include <rpc/nettype.h>
+#include <syslog.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <errno.h>
+#include <syslog.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+static CLIENT *clnt_com_create(struct sockaddr_in *, rpcprog_t, rpcvers_t,
+ int *, u_int, u_int, char *);
+static SVCXPRT *svc_com_create(int, u_int, u_int, char *);
+static bool_t rpc_wrap_bcast(char *, struct netbuf *, struct netconfig *);
+
+/* XXX */
+#define IN4_LOCALHOST_STRING "127.0.0.1"
+#define IN6_LOCALHOST_STRING "::1"
+
+/*
+ * A common clnt create routine
+ */
+static CLIENT *
+clnt_com_create(raddr, prog, vers, sockp, sendsz, recvsz, tp)
+ struct sockaddr_in *raddr;
+ rpcprog_t prog;
+ rpcvers_t vers;
+ int *sockp;
+ u_int sendsz;
+ u_int recvsz;
+ char *tp;
+{
+ CLIENT *cl;
+ int madefd = FALSE;
+ int fd = *sockp;
+ struct netconfig *nconf;
+ struct netbuf bindaddr;
+
+ mutex_lock(&rpcsoc_lock);
+ if ((nconf = __rpc_getconfip(tp)) == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ mutex_unlock(&rpcsoc_lock);
+ return (NULL);
+ }
+ if (fd == RPC_ANYSOCK) {
+ fd = __rpc_nconf2fd(nconf);
+ if (fd == -1)
+ goto syserror;
+ madefd = TRUE;
+ }
+
+ if (raddr->sin_port == 0) {
+ u_int proto;
+ u_short sport;
+
+ mutex_unlock(&rpcsoc_lock); /* pmap_getport is recursive */
+ proto = strcmp(tp, "udp") == 0 ? IPPROTO_UDP : IPPROTO_TCP;
+ sport = pmap_getport(raddr, (u_long)prog, (u_long)vers,
+ proto);
+ if (sport == 0) {
+ goto err;
+ }
+ raddr->sin_port = htons(sport);
+ mutex_lock(&rpcsoc_lock); /* pmap_getport is recursive */
+ }
+
+ /* Transform sockaddr_in to netbuf */
+ bindaddr.maxlen = bindaddr.len = sizeof (struct sockaddr_in);
+ bindaddr.buf = raddr;
+
+ bindresvport(fd, NULL);
+ cl = clnt_tli_create(fd, nconf, &bindaddr, prog, vers,
+ sendsz, recvsz);
+ if (cl) {
+ if (madefd == TRUE) {
+ /*
+ * The fd should be closed while destroying the handle.
+ */
+ (void) CLNT_CONTROL(cl, CLSET_FD_CLOSE, NULL);
+ *sockp = fd;
+ }
+ (void) freenetconfigent(nconf);
+ mutex_unlock(&rpcsoc_lock);
+ return (cl);
+ }
+ goto err;
+
+syserror:
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+
+err: if (madefd == TRUE)
+ (void)_close(fd);
+ (void) freenetconfigent(nconf);
+ mutex_unlock(&rpcsoc_lock);
+ return (NULL);
+}
+
+CLIENT *
+clntudp_bufcreate(raddr, prog, vers, wait, sockp, sendsz, recvsz)
+ struct sockaddr_in *raddr;
+ u_long prog;
+ u_long vers;
+ struct timeval wait;
+ int *sockp;
+ u_int sendsz;
+ u_int recvsz;
+{
+ CLIENT *cl;
+
+ cl = clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
+ sendsz, recvsz, "udp");
+ if (cl == NULL) {
+ return (NULL);
+ }
+ (void) CLNT_CONTROL(cl, CLSET_RETRY_TIMEOUT, &wait);
+ return (cl);
+}
+
+CLIENT *
+clntudp_create(raddr, program, version, wait, sockp)
+ struct sockaddr_in *raddr;
+ u_long program;
+ u_long version;
+ struct timeval wait;
+ int *sockp;
+{
+
+ return clntudp_bufcreate(raddr, program, version, wait, sockp,
+ UDPMSGSIZE, UDPMSGSIZE);
+}
+
+CLIENT *
+clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ struct sockaddr_in *raddr;
+ u_long prog;
+ u_long vers;
+ int *sockp;
+ u_int sendsz;
+ u_int recvsz;
+{
+
+ return clnt_com_create(raddr, (rpcprog_t)prog, (rpcvers_t)vers, sockp,
+ sendsz, recvsz, "tcp");
+}
+
+CLIENT *
+clntraw_create(prog, vers)
+ u_long prog;
+ u_long vers;
+{
+
+ return clnt_raw_create((rpcprog_t)prog, (rpcvers_t)vers);
+}
+
+/*
+ * A common server create routine
+ */
+static SVCXPRT *
+svc_com_create(fd, sendsize, recvsize, netid)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+ char *netid;
+{
+ struct netconfig *nconf;
+ SVCXPRT *svc;
+ int madefd = FALSE;
+ int port;
+ struct sockaddr_in sin;
+
+ if ((nconf = __rpc_getconfip(netid)) == NULL) {
+ (void) syslog(LOG_ERR, "Could not get %s transport", netid);
+ return (NULL);
+ }
+ if (fd == RPC_ANYSOCK) {
+ fd = __rpc_nconf2fd(nconf);
+ if (fd == -1) {
+ (void) freenetconfigent(nconf);
+ (void) syslog(LOG_ERR,
+ "svc%s_create: could not open connection", netid);
+ return (NULL);
+ }
+ madefd = TRUE;
+ }
+
+ memset(&sin, 0, sizeof sin);
+ sin.sin_family = AF_INET;
+ bindresvport(fd, &sin);
+ _listen(fd, SOMAXCONN);
+ svc = svc_tli_create(fd, nconf, NULL, sendsize, recvsize);
+ (void) freenetconfigent(nconf);
+ if (svc == NULL) {
+ if (madefd)
+ (void)_close(fd);
+ return (NULL);
+ }
+ port = (((struct sockaddr_in *)svc->xp_ltaddr.buf)->sin_port);
+ svc->xp_port = ntohs(port);
+ return (svc);
+}
+
+SVCXPRT *
+svctcp_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+
+ return svc_com_create(fd, sendsize, recvsize, "tcp");
+}
+
+SVCXPRT *
+svcudp_bufcreate(fd, sendsz, recvsz)
+ int fd;
+ u_int sendsz, recvsz;
+{
+
+ return svc_com_create(fd, sendsz, recvsz, "udp");
+}
+
+SVCXPRT *
+svcfd_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+
+ return svc_fd_create(fd, sendsize, recvsize);
+}
+
+
+SVCXPRT *
+svcudp_create(fd)
+ int fd;
+{
+
+ return svc_com_create(fd, UDPMSGSIZE, UDPMSGSIZE, "udp");
+}
+
+SVCXPRT *
+svcraw_create()
+{
+
+ return svc_raw_create();
+}
+
+int
+get_myaddress(addr)
+ struct sockaddr_in *addr;
+{
+
+ memset((void *) addr, 0, sizeof(*addr));
+ addr->sin_family = AF_INET;
+ addr->sin_port = htons(PMAPPORT);
+ addr->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+ return (0);
+}
+
+/*
+ * For connectionless "udp" transport. Obsoleted by rpc_call().
+ */
+int
+callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)
+ const char *host;
+ int prognum, versnum, procnum;
+ xdrproc_t inproc, outproc;
+ void *in, *out;
+{
+
+ return (int)rpc_call(host, (rpcprog_t)prognum, (rpcvers_t)versnum,
+ (rpcproc_t)procnum, inproc, in, outproc, out, "udp");
+}
+
+/*
+ * For connectionless kind of transport. Obsoleted by rpc_reg()
+ */
+int
+registerrpc(prognum, versnum, procnum, progname, inproc, outproc)
+ int prognum, versnum, procnum;
+ char *(*progname)(char [UDPMSGSIZE]);
+ xdrproc_t inproc, outproc;
+{
+
+ return rpc_reg((rpcprog_t)prognum, (rpcvers_t)versnum,
+ (rpcproc_t)procnum, progname, inproc, outproc, "udp");
+}
+
+/*
+ * All the following clnt_broadcast stuff is convulated; it supports
+ * the earlier calling style of the callback function
+ */
+static thread_key_t clnt_broadcast_key;
+static resultproc_t clnt_broadcast_result_main;
+static once_t clnt_broadcast_once = ONCE_INITIALIZER;
+
+static void
+clnt_broadcast_key_init(void)
+{
+
+ thr_keycreate(&clnt_broadcast_key, free);
+}
+
+/*
+ * Need to translate the netbuf address into sockaddr_in address.
+ * Dont care about netid here.
+ */
+/* ARGSUSED */
+static bool_t
+rpc_wrap_bcast(resultp, addr, nconf)
+ char *resultp; /* results of the call */
+ struct netbuf *addr; /* address of the guy who responded */
+ struct netconfig *nconf; /* Netconf of the transport */
+{
+ resultproc_t clnt_broadcast_result;
+
+ if (strcmp(nconf->nc_netid, "udp"))
+ return (FALSE);
+ if (thr_main())
+ clnt_broadcast_result = clnt_broadcast_result_main;
+ else
+ clnt_broadcast_result = (resultproc_t)thr_getspecific(clnt_broadcast_key);
+ return (*clnt_broadcast_result)(resultp,
+ (struct sockaddr_in *)addr->buf);
+}
+
+/*
+ * Broadcasts on UDP transport. Obsoleted by rpc_broadcast().
+ */
+enum clnt_stat
+clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)
+ u_long prog; /* program number */
+ u_long vers; /* version number */
+ u_long proc; /* procedure number */
+ xdrproc_t xargs; /* xdr routine for args */
+ void *argsp; /* pointer to args */
+ xdrproc_t xresults; /* xdr routine for results */
+ void *resultsp; /* pointer to results */
+ resultproc_t eachresult; /* call with each result obtained */
+{
+
+ if (thr_main())
+ clnt_broadcast_result_main = eachresult;
+ else {
+ thr_once(&clnt_broadcast_once, clnt_broadcast_key_init);
+ thr_setspecific(clnt_broadcast_key, (void *) eachresult);
+ }
+ return rpc_broadcast((rpcprog_t)prog, (rpcvers_t)vers,
+ (rpcproc_t)proc, xargs, argsp, xresults, resultsp,
+ (resultproc_t) rpc_wrap_bcast, "udp");
+}
+
+/*
+ * Create the client des authentication object. Obsoleted by
+ * authdes_seccreate().
+ */
+AUTH *
+authdes_create(servername, window, syncaddr, ckey)
+ char *servername; /* network name of server */
+ u_int window; /* time to live */
+ struct sockaddr *syncaddr; /* optional hostaddr to sync with */
+ des_block *ckey; /* optional conversation key to use */
+{
+ AUTH *dummy;
+ AUTH *nauth;
+ char hostname[NI_MAXHOST];
+
+ if (syncaddr) {
+ /*
+ * Change addr to hostname, because that is the way
+ * new interface takes it.
+ */
+ if (getnameinfo(syncaddr, syncaddr->sa_len, hostname,
+ sizeof hostname, NULL, 0, 0) != 0)
+ goto fallback;
+
+ nauth = authdes_seccreate(servername, window, hostname, ckey);
+ return (nauth);
+ }
+fallback:
+ dummy = authdes_seccreate(servername, window, NULL, ckey);
+ return (dummy);
+}
+
+/*
+ * Create a client handle for a unix connection. Obsoleted by clnt_vc_create()
+ */
+CLIENT *
+clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz)
+ struct sockaddr_un *raddr;
+ u_long prog;
+ u_long vers;
+ int *sockp;
+ u_int sendsz;
+ u_int recvsz;
+{
+ struct netbuf *svcaddr;
+ struct netconfig *nconf;
+ CLIENT *cl;
+ int len;
+
+ cl = NULL;
+ nconf = NULL;
+ svcaddr = NULL;
+ if ((raddr->sun_len == 0) ||
+ ((svcaddr = malloc(sizeof(struct netbuf))) == NULL ) ||
+ ((svcaddr->buf = malloc(sizeof(struct sockaddr_un))) == NULL)) {
+ if (svcaddr != NULL)
+ free(svcaddr);
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ return(cl);
+ }
+ if (*sockp < 0) {
+ *sockp = _socket(AF_LOCAL, SOCK_STREAM, 0);
+ len = raddr->sun_len = SUN_LEN(raddr);
+ if ((*sockp < 0) || (_connect(*sockp,
+ (struct sockaddr *)raddr, len) < 0)) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ rpc_createerr.cf_error.re_errno = errno;
+ if (*sockp != -1)
+ (void)_close(*sockp);
+ goto done;
+ }
+ }
+ svcaddr->buf = raddr;
+ svcaddr->len = raddr->sun_len;
+ svcaddr->maxlen = sizeof (struct sockaddr_un);
+ cl = clnt_vc_create(*sockp, svcaddr, prog,
+ vers, sendsz, recvsz);
+done:
+ free(svcaddr->buf);
+ free(svcaddr);
+ return(cl);
+}
+
+/*
+ * Creates, registers, and returns a (rpc) unix based transporter.
+ * Obsoleted by svc_vc_create().
+ */
+SVCXPRT *
+svcunix_create(sock, sendsize, recvsize, path)
+ int sock;
+ u_int sendsize;
+ u_int recvsize;
+ char *path;
+{
+ struct netconfig *nconf;
+ void *localhandle;
+ struct sockaddr_un sun;
+ struct sockaddr *sa;
+ struct t_bind taddr;
+ SVCXPRT *xprt;
+ int addrlen;
+
+ xprt = (SVCXPRT *)NULL;
+ localhandle = setnetconfig();
+ while ((nconf = getnetconfig(localhandle)) != NULL) {
+ if (nconf->nc_protofmly != NULL &&
+ strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
+ break;
+ }
+ if (nconf == NULL)
+ return(xprt);
+
+ if ((sock = __rpc_nconf2fd(nconf)) < 0)
+ goto done;
+
+ memset(&sun, 0, sizeof sun);
+ sun.sun_family = AF_LOCAL;
+ if (strlcpy(sun.sun_path, path, sizeof(sun.sun_path)) >=
+ sizeof(sun.sun_path))
+ goto done;
+ sun.sun_len = SUN_LEN(&sun);
+ addrlen = sizeof (struct sockaddr_un);
+ sa = (struct sockaddr *)&sun;
+
+ if (_bind(sock, sa, addrlen) < 0)
+ goto done;
+
+ taddr.addr.len = taddr.addr.maxlen = addrlen;
+ taddr.addr.buf = malloc(addrlen);
+ if (taddr.addr.buf == NULL)
+ goto done;
+ memcpy(taddr.addr.buf, sa, addrlen);
+
+ if (nconf->nc_semantics != NC_TPI_CLTS) {
+ if (_listen(sock, SOMAXCONN) < 0) {
+ free(taddr.addr.buf);
+ goto done;
+ }
+ }
+
+ xprt = (SVCXPRT *)svc_tli_create(sock, nconf, &taddr, sendsize, recvsize);
+
+done:
+ endnetconfig(localhandle);
+ return(xprt);
+}
+
+/*
+ * Like svunix_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input. Obsoleted by svc_fd_create();
+ */
+SVCXPRT *
+svcunixfd_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+ return (svc_fd_create(fd, sendsize, recvsize));
+}
+
+#endif /* PORTMAP */
diff --git a/lib/libc/rpc/rpc_svc_calls.3 b/lib/libc/rpc/rpc_svc_calls.3
new file mode 100644
index 0000000..8732962
--- /dev/null
+++ b/lib/libc/rpc/rpc_svc_calls.3
@@ -0,0 +1,267 @@
+.\" @(#)rpc_svc_calls.3n 1.28 93/05/10 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" @(#)rpc_svc_calls 1.5 89/07/25 SMI;
+.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
+.\" $NetBSD: rpc_svc_calls.3,v 1.1 2000/06/02 23:11:13 fvdl Exp $
+.\" $FreeBSD$
+.Dd May 3, 1993
+.Dt RPC_SVC_CALLS 3
+.Os
+.Sh NAME
+.Nm svc_dg_enablecache ,
+.Nm svc_exit ,
+.Nm svc_fdset ,
+.Nm svc_freeargs ,
+.Nm svc_getargs ,
+.Nm svc_getreq_common ,
+.Nm svc_getreq_poll ,
+.Nm svc_getreqset ,
+.Nm svc_getrpccaller ,
+.Nm svc_pollset ,
+.Nm svc_run ,
+.Nm svc_sendreply
+.Nd library routines for RPC servers
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In rpc/rpc.h
+.Ft int
+.Fn svc_dg_enablecache "SVCXPRT *xprt" "const unsigned cache_size"
+.Ft void
+.Fn svc_exit "void"
+.Ft bool_t
+.Fn svc_freeargs "const SVCXPRT *xprt" "const xdrproc_t inproc" "caddr_t in"
+.Ft bool_t
+.Fn svc_getargs "const SVCXPRT *xprt" "const xdrproc_t inproc" "caddr_t in"
+.Ft void
+.Fn svc_getreq_common "const int fd"
+.Ft void
+.Fn svc_getreq_poll "struct pollfd *pfdp" "const int pollretval"
+.Ft void
+.Fn svc_getreqset "fd_set * rdfds"
+.Ft "struct netbuf *"
+.Fn svc_getrpccaller "const SVCXPRT *xprt"
+.Ft "struct cmsgcred *"
+.Fn __svc_getcallercreds "const SVCXPRT *xprt"
+.Vt struct pollfd svc_pollset[FD_SETSIZE];
+.Ft void
+.Fn svc_run "void"
+.Ft bool_t
+.Fn svc_sendreply "SVCXPRT *xprt" "xdrproc_t outproc" "void *out"
+.Sh DESCRIPTION
+These routines are part of the
+RPC
+library which allows C language programs to make procedure
+calls on other machines across the network.
+.Pp
+These routines are associated with the server side of the
+RPC mechanism.
+Some of them are called by the server side dispatch function,
+while others
+(such as
+.Fn svc_run )
+are called when the server is initiated.
+.\" .Pp
+.\" In the current implementation, the service transport handle,
+.\" .Dv SVCXPRT ,
+.\" contains a single data area for decoding arguments and encoding results.
+.\" Therefore, this structure cannot be freely shared between threads that call
+.\" functions that do this.
+.\" Routines on this page that are affected by this
+.\" restriction are marked as unsafe for MT applications.
+.Sh Routines
+See
+.Xr rpc 3
+for the definition of the
+.Vt SVCXPRT
+data structure.
+.Bl -tag -width __svc_getcallercreds()
+.It Fn svc_dg_enablecache
+This function allocates a duplicate request cache for the
+service endpoint
+.Fa xprt ,
+large enough to hold
+.Fa cache_size
+entries.
+Once enabled, there is no way to disable caching.
+This routine returns 0 if space necessary for a cache of the given size
+was successfully allocated, and 1 otherwise.
+.It Fn svc_exit
+This function, when called by any of the RPC server procedure or
+otherwise, causes
+.Fn svc_run
+to return.
+.Pp
+As currently implemented,
+.Fn svc_exit
+zeroes the
+.Va svc_fdset
+global variable.
+If RPC server activity is to be resumed,
+services must be reregistered with the RPC library
+either through one of the
+.Xr rpc_svc_create 3
+functions, or using
+.Fn xprt_register .
+The
+.Fn svc_exit
+function
+has global scope and ends all RPC server activity.
+.It Xo
+.Vt fd_set Va svc_fdset
+.Xc
+A global variable reflecting the
+RPC server's read file descriptor bit mask; it is suitable as an argument
+to the
+.Xr select 2
+system call.
+This is only of interest
+if service implementors do not call
+.Fn svc_run ,
+but rather do their own asynchronous event processing.
+This variable is read-only (do not pass its address to
+.Xr select 2 ! ) ,
+yet it may change after calls to
+.Fn svc_getreqset
+or any creation routines.
+.It Fn svc_freeargs
+A function macro that frees any data allocated by the
+RPC/XDR system when it decoded the arguments to a service procedure
+using
+.Fn svc_getargs .
+This routine returns
+.Dv TRUE
+if the results were successfully
+freed, and
+.Dv FALSE
+otherwise.
+.It Fn svc_getargs
+A function macro that decodes the arguments of an
+RPC request associated with the RPC
+service transport handle
+.Fa xprt .
+The
+.Fa in
+argument
+is the address where the arguments will be placed;
+.Fa inproc
+is the XDR
+routine used to decode the arguments.
+This routine returns
+.Dv TRUE
+if decoding succeeds, and
+.Dv FALSE
+otherwise.
+.It Fn svc_getreq_common
+This routine is called to handle a request on the given
+file descriptor.
+.It Fn svc_getreq_poll
+This routine is only of interest if a service implementor
+does not call
+.Fn svc_run ,
+but instead implements custom asynchronous event processing.
+It is called when
+.Xr poll 2
+has determined that an RPC request has arrived on some RPC
+file descriptors;
+.Fa pollretval
+is the return value from
+.Xr poll 2
+and
+.Fa pfdp
+is the array of
+.Vt pollfd
+structures on which the
+.Xr poll 2
+was done.
+It is assumed to be an array large enough to
+contain the maximal number of descriptors allowed.
+.It Fn svc_getreqset
+This routine is only of interest if a service implementor
+does not call
+.Fn svc_run ,
+but instead implements custom asynchronous event processing.
+It is called when
+.Xr poll 2
+has determined that an RPC
+request has arrived on some RPC file descriptors;
+.Fa rdfds
+is the resultant read file descriptor bit mask.
+The routine returns when all file descriptors
+associated with the value of
+.Fa rdfds
+have been serviced.
+.It Fn svc_getrpccaller
+The approved way of getting the network address of the caller
+of a procedure associated with the
+RPC service transport handle
+.Fa xprt .
+.It Fn __svc_getcallercreds
+.Em Warning :
+this macro is specific to
+.Fx
+and thus not portable.
+This macro returns a pointer to a
+.Vt cmsgcred
+structure, defined in
+.In sys/socket.h ,
+identifying the calling client.
+This only works if the client is
+calling the server over an
+.Dv AF_LOCAL
+socket.
+.It Xo
+.Vt struct pollfd Va svc_pollset[FD_SETSIZE] ;
+.Xc
+.Va svc_pollset
+is an array of
+.Vt pollfd
+structures derived from
+.Va svc_fdset[] .
+It is suitable as an argument to the
+.Xr poll 2
+system call.
+The derivation of
+.Va svc_pollset
+from
+.Va svc_fdset
+is made in the current implementation in
+.Fn svc_run .
+Service implementors who do not call
+.Fn svc_run
+and who wish to use this array must perform this derivation themselves.
+.It Fn svc_run
+This routine never returns.
+It waits for RPC
+requests to arrive, and calls the appropriate service
+procedure using
+.Fn svc_getreq_poll
+when one arrives.
+This procedure is usually waiting for the
+.Xr poll 2
+system call to return.
+.It Fn svc_sendreply
+Called by an RPC service's dispatch routine to send the results of a
+remote procedure call.
+The
+.Fa xprt
+argument
+is the request's associated transport handle;
+.Fa outproc
+is the XDR
+routine which is used to encode the results; and
+.Fa out
+is the address of the results.
+This routine returns
+.Dv TRUE
+if it succeeds,
+.Dv FALSE
+otherwise.
+.El
+.Sh SEE ALSO
+.Xr poll 2 ,
+.Xr select 2 ,
+.Xr rpc 3 ,
+.Xr rpc_svc_create 3 ,
+.Xr rpc_svc_err 3 ,
+.Xr rpc_svc_reg 3
diff --git a/lib/libc/rpc/rpc_svc_create.3 b/lib/libc/rpc/rpc_svc_create.3
new file mode 100644
index 0000000..4016a6c
--- /dev/null
+++ b/lib/libc/rpc/rpc_svc_create.3
@@ -0,0 +1,337 @@
+.\" @(#)rpc_svc_create.3n 1.26 93/08/26 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" @(#)rpc_svc_create 1.3 89/06/28 SMI;
+.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
+.\" $FreeBSD$
+.Dd May 3, 1993
+.Dt RPC_SVC_CREATE 3
+.Os
+.Sh NAME
+.Nm rpc_svc_create ,
+.Nm svc_control ,
+.Nm svc_create ,
+.Nm svc_destroy ,
+.Nm svc_dg_create ,
+.Nm svc_fd_create ,
+.Nm svc_raw_create ,
+.Nm svc_tli_create ,
+.Nm svc_tp_create ,
+.Nm svc_vc_create
+.Nd library routines for the creation of server handles
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In rpc/rpc.h
+.Ft bool_t
+.Fn svc_control "SVCXPRT *svc" "const u_int req" "void *info"
+.Ft int
+.Fn svc_create "void (*dispatch)(struct svc_req *, SVCXPRT *)" "const rpcprog_t prognum" "const rpcvers_t versnum" "const char *nettype"
+.Ft SVCXPRT *
+.Fn svc_dg_create "const int fildes" "const u_int sendsz" "const u_int recvsz"
+.Ft void
+.Fn svc_destroy "SVCXPRT *xprt"
+.Ft "SVCXPRT *"
+.Fn svc_fd_create "const int fildes" "const u_int sendsz" "const u_int recvsz"
+.Ft "SVCXPRT *"
+.Fn svc_raw_create "void"
+.Ft "SVCXPRT *"
+.Fn svc_tli_create "const int fildes" "const struct netconfig *netconf" "const struct t_bind *bindaddr" "const u_int sendsz" "const u_int recvsz"
+.Ft "SVCXPRT *"
+.Fn svc_tp_create "void (*dispatch)(struct svc_req *, SVCXPRT *)" "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf"
+.Ft "SVCXPRT *"
+.Fn svc_vc_create "const int fildes" "const u_int sendsz" "const u_int recvsz"
+.Sh DESCRIPTION
+These routines are part of the RPC
+library which allows C language programs to make procedure
+calls on servers across the network.
+These routines deal with the creation of service handles.
+Once the handle is created, the server can be invoked by calling
+.Fn svc_run .
+.Sh Routines
+See
+.Xr rpc 3
+for the definition of the
+.Vt SVCXPRT
+data structure.
+.Bl -tag -width XXXXX
+.It Fn svc_control
+A function to change or retrieve various information
+about a service object.
+The
+.Fa req
+argument
+indicates the type of operation and
+.Fa info
+is a pointer to the information.
+The supported values of
+.Fa req ,
+their argument types, and what they do are:
+.Bl -tag -width SVCGET_XID
+.It Dv SVCGET_VERSQUIET
+If a request is received for a program number
+served by this server but the version number
+is outside the range registered with the server,
+an
+.Dv RPC_PROGVERSMISMATCH
+error will normally
+be returned.
+The
+.Fa info
+argument
+should be a pointer to an
+integer.
+Upon successful completion of the
+.Dv SVCGET_VERSQUIET
+request,
+.Fa *info
+contains an
+integer which describes the server's current
+behavior: 0 indicates normal server behavior
+(that is, an
+.Dv RPC_PROGVERSMISMATCH
+error
+will be returned); 1 indicates that the out of
+range request will be silently ignored.
+.It Dv SVCSET_VERSQUIET
+If a request is received for a program number
+served by this server but the version number
+is outside the range registered with the server,
+an
+.Dv RPC_PROGVERSMISMATCH
+error will normally
+be returned.
+It is sometimes desirable to
+change this behavior.
+The
+.Fa info
+argument
+should be a
+pointer to an integer which is either 0
+(indicating normal server behavior - an
+.Dv RPC_PROGVERSMISMATCH
+error will be returned),
+or 1 (indicating that the out of range request
+should be silently ignored).
+.El
+.It Fn svc_create
+The
+.Fn svc_create
+function
+creates server handles for all the transports
+belonging to the class
+.Fa nettype .
+The
+.Fa nettype
+argument
+defines a class of transports which can be used
+for a particular application.
+The transports are tried in left to right order in
+.Ev NETPATH
+variable or in top to bottom order in the netconfig database.
+If
+.Fa nettype
+is
+.Dv NULL ,
+it defaults to
+.Qq netpath .
+.Pp
+The
+.Fn svc_create
+function
+registers itself with the rpcbind
+service (see
+.Xr rpcbind 8 ) .
+The
+.Fa dispatch
+function
+is called when there is a remote procedure call for the given
+.Fa prognum
+and
+.Fa versnum ;
+this requires calling
+.Fn svc_run
+(see
+.Fn svc_run
+in
+.Xr rpc_svc_reg 3 ) .
+If
+.Fn svc_create
+succeeds, it returns the number of server
+handles it created,
+otherwise it returns 0 and an error message is logged.
+.It Fn svc_destroy
+A function macro that destroys the RPC
+service handle
+.Fa xprt .
+Destruction usually involves deallocation
+of private data structures,
+including
+.Fa xprt
+itself.
+Use of
+.Fa xprt
+is undefined after calling this routine.
+.It Fn svc_dg_create
+This routine creates a connectionless RPC
+service handle, and returns a pointer to it.
+This routine returns
+.Dv NULL
+if it fails, and an error message is logged.
+The
+.Fa sendsz
+and
+.Fa recvsz
+arguments
+are arguments used to specify the size of the buffers.
+If they are 0, suitable defaults are chosen.
+The file descriptor
+.Fa fildes
+should be open and bound.
+The server is not registered with
+.Xr rpcbind 8 .
+.Pp
+Warning:
+since connectionless-based RPC
+messages can only hold limited amount of encoded data,
+this transport cannot be used for procedures
+that take large arguments or return huge results.
+.It Fn svc_fd_create
+This routine creates a service on top of an open and bound file descriptor,
+and returns the handle to it.
+Typically, this descriptor is a connected file descriptor for a
+connection-oriented transport.
+The
+.Fa sendsz
+and
+.Fa recvsz
+arguments
+indicate sizes for the send and receive buffers.
+If they are 0, reasonable defaults are chosen.
+This routine returns
+.Dv NULL
+if it fails, and an error message is logged.
+.It Fn svc_raw_create
+This routine creates an RPC
+service handle and returns a pointer to it.
+The transport is really a buffer within the process's
+address space, so the corresponding RPC
+client should live in the same address space;
+(see
+.Fn clnt_raw_create
+in
+.Xr rpc_clnt_create 3 ) .
+This routine allows simulation of RPC and acquisition of
+RPC overheads (such as round trip times),
+without any kernel and networking interference.
+This routine returns
+.Dv NULL
+if it fails, and an error message is logged.
+.Pp
+Note:
+.Fn svc_run
+should not be called when the raw interface is being used.
+.It Fn svc_tli_create
+This routine creates an RPC
+server handle, and returns a pointer to it.
+The
+.Fa fildes
+argument
+is the file descriptor on which the service is listening.
+If
+.Fa fildes
+is
+.Dv RPC_ANYFD ,
+it opens a file descriptor on the transport specified by
+.Fa netconf .
+If the file descriptor is unbound and
+.Fa bindaddr
+is not
+.Dv NULL ,
+.Fa fildes
+is bound to the address specified by
+.Fa bindaddr ,
+otherwise
+.Fa fildes
+is bound to a default address chosen by the transport.
+.Pp
+Note: the
+.Vt t_bind
+structure comes from the TLI/XTI SysV interface, which
+.Nx
+does not use.
+The structure is defined in
+.In rpc/types.h
+for compatibility as:
+.Bd -literal
+struct t_bind {
+ struct netbuf addr; /* network address, see rpc(3) */
+ unsigned int qlen; /* queue length (for listen(2)) */
+};
+.Ed
+.Pp
+In the case where the default address is chosen,
+the number of outstanding connect requests is set to 8
+for connection-oriented transports.
+The user may specify the size of the send and receive buffers
+with the arguments
+.Fa sendsz
+and
+.Fa recvsz ;
+values of 0 choose suitable defaults.
+This routine returns
+.Dv NULL
+if it fails,
+and an error message is logged.
+The server is not registered with the
+.Xr rpcbind 8
+service.
+.It Fn svc_tp_create
+The
+.Fn svc_tp_create
+function
+creates a server handle for the network
+specified by
+.Fa netconf ,
+and registers itself with the rpcbind service.
+The
+.Fa dispatch
+function
+is called when there is a remote procedure call
+for the given
+.Fa prognum
+and
+.Fa versnum ;
+this requires calling
+.Fn svc_run .
+The
+.Fn svc_tp_create
+function
+returns the service handle if it succeeds,
+otherwise a
+.Dv NULL
+is returned and an error message is logged.
+.It Fn svc_vc_create
+This routine creates a connection-oriented RPC
+service and returns a pointer to it.
+This routine returns
+.Dv NULL
+if it fails, and an error message is logged.
+The users may specify the size of the send and receive buffers
+with the arguments
+.Fa sendsz
+and
+.Fa recvsz ;
+values of 0 choose suitable defaults.
+The file descriptor
+.Fa fildes
+should be open and bound.
+The server is not registered with the
+.Xr rpcbind 8
+service.
+.El
+.Sh SEE ALSO
+.Xr rpc 3 ,
+.Xr rpc_svc_calls 3 ,
+.Xr rpc_svc_err 3 ,
+.Xr rpc_svc_reg 3 ,
+.Xr rpcbind 8
diff --git a/lib/libc/rpc/rpc_svc_err.3 b/lib/libc/rpc/rpc_svc_err.3
new file mode 100644
index 0000000..7a6b1f1
--- /dev/null
+++ b/lib/libc/rpc/rpc_svc_err.3
@@ -0,0 +1,97 @@
+.\" @(#)rpc_svc_err.3n 1.23 93/08/31 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" @(#)rpc_svc_err 1.4 89/06/28 SMI;
+.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
+.\" $NetBSD: rpc_svc_err.3,v 1.1 2000/06/02 23:11:14 fvdl Exp $
+.\" $FreeBSD$
+.Dd May 3, 1993
+.Dt RPC_SVC_ERR 3
+.Os
+.Sh NAME
+.Nm rpc_svc_err ,
+.Nm svcerr_auth ,
+.Nm svcerr_decode ,
+.Nm svcerr_noproc ,
+.Nm svcerr_noprog ,
+.Nm svcerr_progvers ,
+.Nm svcerr_systemerr ,
+.Nm svcerr_weakauth
+.Nd library routines for server side remote procedure call errors
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In rpc/rpc.h
+.Ft void
+.Fn svcerr_auth "SVCXPRT *xprt" "enum auth_stat why"
+.Ft void
+.Fn svcerr_decode "SVCXPRT *xprt"
+.Ft void
+.Fn svcerr_noproc "SVCXPRT *xprt"
+.Ft void
+.Fn svcerr_noprog "SVCXPRT *xprt"
+.Ft void
+.Fn svcerr_progvers "SVCXPRT *xprt" "rpcvers_t low_vers" "rpcvers_t high_vers"
+.Ft void
+.Fn svcerr_systemerr "SVCXPRT *xprt"
+.Ft void
+.Fn svcerr_weakauth "SVCXPRT *xprt"
+.Sh DESCRIPTION
+These routines are part of the RPC
+library which allows C language programs to make procedure
+calls on other machines across the network.
+.Pp
+These routines can be called by the server side
+dispatch function if there is any error in the
+transaction with the client.
+.Sh Routines
+See
+.Xr rpc 3
+for the definition of the
+.Vt SVCXPRT
+data structure.
+.Bl -tag -width XXXXX
+.It Fn svcerr_auth
+Called by a service dispatch routine that refuses to perform
+a remote procedure call due to an authentication error.
+.It Fn svcerr_decode
+Called by a service dispatch routine that cannot successfully
+decode the remote arguments
+(see
+.Fn svc_getargs
+in
+.Xr rpc_svc_reg 3 ) .
+.It Fn svcerr_noproc
+Called by a service dispatch routine that does not implement
+the procedure number that the caller requests.
+.It Fn svcerr_noprog
+Called when the desired program is not registered with the
+RPC package.
+Service implementors usually do not need this routine.
+.It Fn svcerr_progvers
+Called when the desired version of a program is not registered with the
+RPC package.
+The
+.Fa low_vers
+argument
+is the lowest version number,
+and
+.Fa high_vers
+is the highest version number.
+Service implementors usually do not need this routine.
+.It Fn svcerr_systemerr
+Called by a service dispatch routine when it detects a system
+error not covered by any particular protocol.
+For example, if a service can no longer allocate storage,
+it may call this routine.
+.It Fn svcerr_weakauth
+Called by a service dispatch routine that refuses to perform
+a remote procedure call due to insufficient (but correct)
+authentication arguments.
+The routine calls
+.Fn svcerr_auth "xprt" "AUTH_TOOWEAK" .
+.El
+.Sh SEE ALSO
+.Xr rpc 3 ,
+.Xr rpc_svc_calls 3 ,
+.Xr rpc_svc_create 3 ,
+.Xr rpc_svc_reg 3
diff --git a/lib/libc/rpc/rpc_svc_reg.3 b/lib/libc/rpc/rpc_svc_reg.3
new file mode 100644
index 0000000..aed2ba1
--- /dev/null
+++ b/lib/libc/rpc/rpc_svc_reg.3
@@ -0,0 +1,183 @@
+.\" @(#)rpc_svc_reg.3n 1.32 93/08/31 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" @(#)rpc_svc_call 1.6 89/07/20 SMI;
+.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
+.\" $NetBSD: rpc_svc_reg.3,v 1.1 2000/06/02 23:11:14 fvdl Exp $
+.\" $FreeBSD$
+.Dd May 3, 1993
+.Dt RPC_SVC_REG 3
+.Os
+.Sh NAME
+.Nm rpc_svc_reg ,
+.Nm rpc_reg ,
+.Nm svc_reg ,
+.Nm svc_unreg ,
+.Nm svc_auth_reg ,
+.Nm xprt_register ,
+.Nm xprt_unregister
+.Nd library routines for registering servers
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In rpc/rpc.h
+.Ft int
+.Fn rpc_reg "rpcprog_t prognum" "rpcvers_t versnum" "rpcproc_t procnum" "char *(*procname)()" "xdrproc_t inproc" "xdrproc_t outproc" "char *nettype"
+.Ft bool_t
+.Fn svc_reg "SVCXPRT *xprt" "const rpcprog_t prognum" "const rpcvers_t versnum" "void (*dispatch)(struct svc_req *, SVCXPRT *)" "const struct netconfig *netconf"
+.Ft void
+.Fn svc_unreg "const rpcprog_t prognum" "const rpcvers_t versnum"
+.Ft int
+.Fn svc_auth_reg "int cred_flavor" "enum auth_stat (*handler)(struct svc_req *, struct rpc_msg *)"
+.Ft void
+.Fn xprt_register "SVCXPRT *xprt"
+.Ft void
+.Fn xprt_unregister "SVCXPRT *xprt"
+.Sh DESCRIPTION
+These routines are a part of the RPC
+library which allows the RPC
+servers to register themselves with rpcbind
+(see
+.Xr rpcbind 8 ) ,
+and associate the given program and version
+number with the dispatch function.
+When the RPC server receives a RPC request, the library invokes the
+dispatch routine with the appropriate arguments.
+.Sh Routines
+See
+.Xr rpc 3
+for the definition of the
+.Vt SVCXPRT
+data structure.
+.Bl -tag -width XXXXX
+.It Fn rpc_reg
+Register program
+.Fa prognum ,
+procedure
+.Fa procname ,
+and version
+.Fa versnum
+with the RPC
+service package.
+If a request arrives for program
+.Fa prognum ,
+version
+.Fa versnum ,
+and procedure
+.Fa procnum ,
+.Fa procname
+is called with a pointer to its argument(s);
+.Fa procname
+should return a pointer to its static result(s);
+.Fa inproc
+is the XDR function used to decode the arguments while
+.Fa outproc
+is the XDR function used to encode the results.
+Procedures are registered on all available transports of the class
+.Fa nettype .
+See
+.Xr rpc 3 .
+This routine returns 0 if the registration succeeded,
+\-1 otherwise.
+.It Fn svc_reg
+Associates
+.Fa prognum
+and
+.Fa versnum
+with the service dispatch procedure,
+.Fa dispatch .
+If
+.Fa netconf
+is
+.Dv NULL ,
+the service is not registered with the
+.Xr rpcbind 8
+service.
+If
+.Fa netconf
+is non-zero,
+then a mapping of the triple
+.Bq Fa prognum , versnum , netconf->nc_netid
+to
+.Fa xprt->xp_ltaddr
+is established with the local rpcbind
+service.
+.Pp
+The
+.Fn svc_reg
+routine returns 1 if it succeeds,
+and 0 otherwise.
+.It Fn svc_unreg
+Remove from the rpcbind
+service, all mappings of the triple
+.Bq Fa prognum , versnum , No all-transports
+to network address
+and all mappings within the RPC service package
+of the double
+.Bq Fa prognum , versnum
+to dispatch routines.
+.It Fn svc_auth_reg
+Registers the service authentication routine
+.Fa handler
+with the dispatch mechanism so that it can be
+invoked to authenticate RPC requests received
+with authentication type
+.Fa cred_flavor .
+This interface allows developers to add new authentication
+types to their RPC applications without needing to modify
+the libraries.
+Service implementors usually do not need this routine.
+.Pp
+Typical service application would call
+.Fn svc_auth_reg
+after registering the service and prior to calling
+.Fn svc_run .
+When needed to process an RPC credential of type
+.Fa cred_flavor ,
+the
+.Fa handler
+procedure will be called with two arguments,
+.Fa "struct svc_req *rqst"
+and
+.Fa "struct rpc_msg *msg" ,
+and is expected to return a valid
+.Vt "enum auth_stat"
+value.
+There is no provision to change or delete an authentication handler
+once registered.
+.Pp
+The
+.Fn svc_auth_reg
+routine returns 0 if the registration is successful,
+1 if
+.Fa cred_flavor
+already has an authentication handler registered for it,
+and \-1 otherwise.
+.It Fn xprt_register
+After RPC service transport handle
+.Fa xprt
+is created, it is registered with the RPC
+service package.
+This routine modifies the global variable
+.Va svc_fdset
+(see
+.Xr rpc_svc_calls 3 ) .
+Service implementors usually do not need this routine.
+.It Fn xprt_unregister
+Before an RPC service transport handle
+.Fa xprt
+is destroyed, it unregisters itself with the
+RPC service package.
+This routine modifies the global variable
+.Va svc_fdset
+(see
+.Xr rpc_svc_calls 3 ) .
+Service implementors usually do not need this routine.
+.El
+.Sh SEE ALSO
+.Xr select 2 ,
+.Xr rpc 3 ,
+.Xr rpcbind 3 ,
+.Xr rpc_svc_calls 3 ,
+.Xr rpc_svc_create 3 ,
+.Xr rpc_svc_err 3 ,
+.Xr rpcbind 8
diff --git a/lib/libc/rpc/rpc_xdr.3 b/lib/libc/rpc/rpc_xdr.3
new file mode 100644
index 0000000..62754fe
--- /dev/null
+++ b/lib/libc/rpc/rpc_xdr.3
@@ -0,0 +1,101 @@
+.\" @(#)rpc_xdr.3n 1.24 93/08/31 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" @(#)rpc_xdr.new 1.1 89/04/06 SMI;
+.\" Copyright (c) 1988 Sun Microsystems, Inc. - All Rights Reserved.
+.\" $FreeBSD$
+.Dd May 3, 1993
+.Dt RPC_XDR 3
+.Os
+.Sh NAME
+.Nm xdr_accepted_reply ,
+.Nm xdr_authsys_parms ,
+.Nm xdr_callhdr ,
+.Nm xdr_callmsg ,
+.Nm xdr_opaque_auth ,
+.Nm xdr_rejected_reply ,
+.Nm xdr_replymsg
+.Nd XDR library routines for remote procedure calls
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In rpc/rpc.h
+.Ft bool_t
+.Fn xdr_accepted_reply "XDR *xdrs" "struct accepted_reply *ar"
+.Ft bool_t
+.Fn xdr_authsys_parms "XDR *xdrs" "struct authsys_parms *aupp"
+.Ft bool_t
+.Fn xdr_callhdr "XDR *xdrs" "struct rpc_msg *chdr"
+.Ft bool_t
+.Fn xdr_callmsg "XDR *xdrs" "struct rpc_msg *cmsg"
+.Ft bool_t
+.Fn xdr_opaque_auth "XDR *xdrs" "struct opaque_auth *ap"
+.Ft bool_t
+.Fn xdr_rejected_reply "XDR *xdrs" "struct rejected_reply *rr"
+.Ft bool_t
+.Fn xdr_replymsg "XDR *xdrs" "struct rpc_msg *rmsg"
+.Sh DESCRIPTION
+These routines are used for describing the
+RPC messages in XDR language.
+They should normally be used by those who do not
+want to use the RPC
+package directly.
+These routines return
+.Dv TRUE
+if they succeed,
+.Dv FALSE
+otherwise.
+.Sh Routines
+See
+.Xr rpc 3
+for the definition of the
+.Vt XDR
+data structure.
+.Bl -tag -width XXXXX
+.It Fn xdr_accepted_reply
+Used to translate between RPC
+reply messages and their external representation.
+It includes the status of the RPC
+call in the XDR language format.
+In the case of success, it also includes the call results.
+.It Fn xdr_authsys_parms
+Used for describing
+.Ux
+operating system credentials.
+It includes machine-name, uid, gid list, etc.
+.It Fn xdr_callhdr
+Used for describing
+RPC
+call header messages.
+It encodes the static part of the call message header in the
+XDR language format.
+It includes information such as transaction
+ID, RPC version number, program and version number.
+.It Fn xdr_callmsg
+Used for describing
+RPC call messages.
+This includes all the RPC
+call information such as transaction
+ID, RPC version number, program number, version number,
+authentication information, etc.
+This is normally used by servers to determine information about the client
+RPC call.
+.It Fn xdr_opaque_auth
+Used for describing RPC
+opaque authentication information messages.
+.It Fn xdr_rejected_reply
+Used for describing RPC reply messages.
+It encodes the rejected RPC message in the XDR language format.
+The message could be rejected either because of version
+number mis-match or because of authentication errors.
+.It Fn xdr_replymsg
+Used for describing RPC
+reply messages.
+It translates between the
+RPC reply message and its external representation.
+This reply could be either an acceptance,
+rejection or
+.Dv NULL .
+.El
+.Sh SEE ALSO
+.Xr rpc 3 ,
+.Xr xdr 3
diff --git a/lib/libc/rpc/rpcb_clnt.c b/lib/libc/rpc/rpcb_clnt.c
new file mode 100644
index 0000000..afef806
--- /dev/null
+++ b/lib/libc/rpc/rpcb_clnt.c
@@ -0,0 +1,1363 @@
+/* $NetBSD: rpcb_clnt.c,v 1.6 2000/07/16 06:41:43 itojun Exp $ */
+
+/*
+ * The contents of this file are subject to the Sun Standards
+ * License Version 1.0 the (the "License";) You may not use
+ * this file except in compliance with the License. You may
+ * obtain a copy of the License at lib/libc/rpc/LICENSE
+ *
+ * Software distributed under the License is distributed on
+ * an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either
+ * express or implied. See the License for the specific
+ * language governing rights and limitations under the License.
+ *
+ * The Original Code is Copyright 1998 by Sun Microsystems, Inc
+ *
+ * The Initial Developer of the Original Code is: Sun
+ * Microsystems, Inc.
+ *
+ * All Rights Reserved.
+ *
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/* #ident "@(#)rpcb_clnt.c 1.27 94/04/24 SMI" */
+
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rpcb_clnt.c 1.30 89/06/21 Copyr 1988 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * rpcb_clnt.c
+ * interface to rpcbind rpc service.
+ *
+ * Copyright (C) 1988, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/utsname.h>
+#include <rpc/rpc.h>
+#include <rpc/rpcb_prot.h>
+#include <rpc/nettype.h>
+#include <netconfig.h>
+#ifdef PORTMAP
+#include <netinet/in.h> /* FOR IPPROTO_TCP/UDP definitions */
+#include <rpc/pmap_prot.h>
+#endif /* PORTMAP */
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <syslog.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+static struct timeval tottimeout = { 60, 0 };
+static const struct timeval rmttimeout = { 3, 0 };
+static struct timeval rpcbrmttime = { 15, 0 };
+
+extern bool_t xdr_wrapstring(XDR *, char **);
+
+static const char nullstring[] = "\000";
+
+#define CACHESIZE 6
+
+struct address_cache {
+ char *ac_host;
+ char *ac_netid;
+ char *ac_uaddr;
+ struct netbuf *ac_taddr;
+ struct address_cache *ac_next;
+};
+
+static struct address_cache *front;
+static int cachesize;
+
+#define CLCR_GET_RPCB_TIMEOUT 1
+#define CLCR_SET_RPCB_TIMEOUT 2
+
+
+extern int __rpc_lowvers;
+
+static struct address_cache *check_cache(const char *, const char *);
+static void delete_cache(struct netbuf *);
+static void add_cache(const char *, const char *, struct netbuf *, char *);
+static CLIENT *getclnthandle(const char *, const struct netconfig *, char **);
+static CLIENT *local_rpcb(void);
+static struct netbuf *got_entry(rpcb_entry_list_ptr, const struct netconfig *);
+
+/*
+ * This routine adjusts the timeout used for calls to the remote rpcbind.
+ * Also, this routine can be used to set the use of portmapper version 2
+ * only when doing rpc_broadcasts
+ * These are private routines that may not be provided in future releases.
+ */
+bool_t
+__rpc_control(request, info)
+ int request;
+ void *info;
+{
+ switch (request) {
+ case CLCR_GET_RPCB_TIMEOUT:
+ *(struct timeval *)info = tottimeout;
+ break;
+ case CLCR_SET_RPCB_TIMEOUT:
+ tottimeout = *(struct timeval *)info;
+ break;
+ case CLCR_SET_LOWVERS:
+ __rpc_lowvers = *(int *)info;
+ break;
+ case CLCR_GET_LOWVERS:
+ *(int *)info = __rpc_lowvers;
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*
+ * It might seem that a reader/writer lock would be more reasonable here.
+ * However because getclnthandle(), the only user of the cache functions,
+ * may do a delete_cache() operation if a check_cache() fails to return an
+ * address useful to clnt_tli_create(), we may as well use a mutex.
+ */
+/*
+ * As it turns out, if the cache lock is *not* a reader/writer lock, we will
+ * block all clnt_create's if we are trying to connect to a host that's down,
+ * since the lock will be held all during that time.
+ */
+
+/*
+ * The routines check_cache(), add_cache(), delete_cache() manage the
+ * cache of rpcbind addresses for (host, netid).
+ */
+
+static struct address_cache *
+check_cache(host, netid)
+ const char *host, *netid;
+{
+ struct address_cache *cptr;
+
+ /* READ LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
+
+ for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
+ if (!strcmp(cptr->ac_host, host) &&
+ !strcmp(cptr->ac_netid, netid)) {
+#ifdef ND_DEBUG
+ fprintf(stderr, "Found cache entry for %s: %s\n",
+ host, netid);
+#endif
+ return (cptr);
+ }
+ }
+ return ((struct address_cache *) NULL);
+}
+
+static void
+delete_cache(addr)
+ struct netbuf *addr;
+{
+ struct address_cache *cptr, *prevptr = NULL;
+
+ /* WRITE LOCK HELD ON ENTRY: rpcbaddr_cache_lock */
+ for (cptr = front; cptr != NULL; cptr = cptr->ac_next) {
+ if (!memcmp(cptr->ac_taddr->buf, addr->buf, addr->len)) {
+ free(cptr->ac_host);
+ free(cptr->ac_netid);
+ free(cptr->ac_taddr->buf);
+ free(cptr->ac_taddr);
+ if (cptr->ac_uaddr)
+ free(cptr->ac_uaddr);
+ if (prevptr)
+ prevptr->ac_next = cptr->ac_next;
+ else
+ front = cptr->ac_next;
+ free(cptr);
+ cachesize--;
+ break;
+ }
+ prevptr = cptr;
+ }
+}
+
+static void
+add_cache(host, netid, taddr, uaddr)
+ const char *host, *netid;
+ char *uaddr;
+ struct netbuf *taddr;
+{
+ struct address_cache *ad_cache, *cptr, *prevptr;
+
+ ad_cache = (struct address_cache *)
+ malloc(sizeof (struct address_cache));
+ if (!ad_cache) {
+ return;
+ }
+ ad_cache->ac_host = strdup(host);
+ ad_cache->ac_netid = strdup(netid);
+ ad_cache->ac_uaddr = uaddr ? strdup(uaddr) : NULL;
+ ad_cache->ac_taddr = (struct netbuf *)malloc(sizeof (struct netbuf));
+ if (!ad_cache->ac_host || !ad_cache->ac_netid || !ad_cache->ac_taddr ||
+ (uaddr && !ad_cache->ac_uaddr)) {
+ goto out;
+ }
+ ad_cache->ac_taddr->len = ad_cache->ac_taddr->maxlen = taddr->len;
+ ad_cache->ac_taddr->buf = (char *) malloc(taddr->len);
+ if (ad_cache->ac_taddr->buf == NULL) {
+out:
+ if (ad_cache->ac_host)
+ free(ad_cache->ac_host);
+ if (ad_cache->ac_netid)
+ free(ad_cache->ac_netid);
+ if (ad_cache->ac_uaddr)
+ free(ad_cache->ac_uaddr);
+ if (ad_cache->ac_taddr)
+ free(ad_cache->ac_taddr);
+ free(ad_cache);
+ return;
+ }
+ memcpy(ad_cache->ac_taddr->buf, taddr->buf, taddr->len);
+#ifdef ND_DEBUG
+ fprintf(stderr, "Added to cache: %s : %s\n", host, netid);
+#endif
+
+/* VARIABLES PROTECTED BY rpcbaddr_cache_lock: cptr */
+
+ rwlock_wrlock(&rpcbaddr_cache_lock);
+ if (cachesize < CACHESIZE) {
+ ad_cache->ac_next = front;
+ front = ad_cache;
+ cachesize++;
+ } else {
+ /* Free the last entry */
+ cptr = front;
+ prevptr = NULL;
+ while (cptr->ac_next) {
+ prevptr = cptr;
+ cptr = cptr->ac_next;
+ }
+
+#ifdef ND_DEBUG
+ fprintf(stderr, "Deleted from cache: %s : %s\n",
+ cptr->ac_host, cptr->ac_netid);
+#endif
+ free(cptr->ac_host);
+ free(cptr->ac_netid);
+ free(cptr->ac_taddr->buf);
+ free(cptr->ac_taddr);
+ if (cptr->ac_uaddr)
+ free(cptr->ac_uaddr);
+
+ if (prevptr) {
+ prevptr->ac_next = NULL;
+ ad_cache->ac_next = front;
+ front = ad_cache;
+ } else {
+ front = ad_cache;
+ ad_cache->ac_next = NULL;
+ }
+ free(cptr);
+ }
+ rwlock_unlock(&rpcbaddr_cache_lock);
+}
+
+/*
+ * This routine will return a client handle that is connected to the
+ * rpcbind. If targaddr is non-NULL, the "universal address" of the
+ * host will be stored in *targaddr; the caller is responsible for
+ * freeing this string.
+ * On error, returns NULL and free's everything.
+ */
+static CLIENT *
+getclnthandle(host, nconf, targaddr)
+ const char *host;
+ const struct netconfig *nconf;
+ char **targaddr;
+{
+ CLIENT *client;
+ struct netbuf *addr, taddr;
+ struct netbuf addr_to_delete;
+ struct __rpc_sockinfo si;
+ struct addrinfo hints, *res, *tres;
+ struct address_cache *ad_cache;
+ char *tmpaddr;
+
+/* VARIABLES PROTECTED BY rpcbaddr_cache_lock: ad_cache */
+
+ /* Get the address of the rpcbind. Check cache first */
+ client = NULL;
+ addr_to_delete.len = 0;
+ rwlock_rdlock(&rpcbaddr_cache_lock);
+ ad_cache = NULL;
+ if (host != NULL)
+ ad_cache = check_cache(host, nconf->nc_netid);
+ if (ad_cache != NULL) {
+ addr = ad_cache->ac_taddr;
+ client = clnt_tli_create(RPC_ANYFD, nconf, addr,
+ (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0);
+ if (client != NULL) {
+ if (targaddr)
+ *targaddr = strdup(ad_cache->ac_uaddr);
+ rwlock_unlock(&rpcbaddr_cache_lock);
+ return (client);
+ }
+ addr_to_delete.len = addr->len;
+ addr_to_delete.buf = (char *)malloc(addr->len);
+ if (addr_to_delete.buf == NULL) {
+ addr_to_delete.len = 0;
+ } else {
+ memcpy(addr_to_delete.buf, addr->buf, addr->len);
+ }
+ }
+ rwlock_unlock(&rpcbaddr_cache_lock);
+ if (addr_to_delete.len != 0) {
+ /*
+ * Assume this may be due to cache data being
+ * outdated
+ */
+ rwlock_wrlock(&rpcbaddr_cache_lock);
+ delete_cache(&addr_to_delete);
+ rwlock_unlock(&rpcbaddr_cache_lock);
+ free(addr_to_delete.buf);
+ }
+ if (!__rpc_nconf2sockinfo(nconf, &si)) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return NULL;
+ }
+
+ memset(&hints, 0, sizeof hints);
+ hints.ai_family = si.si_af;
+ hints.ai_socktype = si.si_socktype;
+ hints.ai_protocol = si.si_proto;
+
+#ifdef CLNT_DEBUG
+ printf("trying netid %s family %d proto %d socktype %d\n",
+ nconf->nc_netid, si.si_af, si.si_proto, si.si_socktype);
+#endif
+
+ if (nconf->nc_protofmly != NULL && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
+ client = local_rpcb();
+ if (! client) {
+#ifdef ND_DEBUG
+ clnt_pcreateerror("rpcbind clnt interface");
+#endif
+ return (NULL);
+ } else {
+ struct sockaddr_un sun;
+ if (targaddr) {
+ *targaddr = malloc(sizeof(sun.sun_path));
+ if (*targaddr == NULL) {
+ CLNT_DESTROY(client);
+ return (NULL);
+ }
+ strncpy(*targaddr, _PATH_RPCBINDSOCK,
+ sizeof(sun.sun_path));
+ }
+ return (client);
+ }
+ } else {
+ if (getaddrinfo(host, "sunrpc", &hints, &res) != 0) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNHOST;
+ return NULL;
+ }
+ }
+
+ for (tres = res; tres != NULL; tres = tres->ai_next) {
+ taddr.buf = tres->ai_addr;
+ taddr.len = taddr.maxlen = tres->ai_addrlen;
+
+#ifdef ND_DEBUG
+ {
+ char *ua;
+
+ ua = taddr2uaddr(nconf, &taddr);
+ fprintf(stderr, "Got it [%s]\n", ua);
+ free(ua);
+ }
+#endif
+
+#ifdef ND_DEBUG
+ {
+ int i;
+
+ fprintf(stderr, "\tnetbuf len = %d, maxlen = %d\n",
+ taddr.len, taddr.maxlen);
+ fprintf(stderr, "\tAddress is ");
+ for (i = 0; i < taddr.len; i++)
+ fprintf(stderr, "%u.", ((char *)(taddr.buf))[i]);
+ fprintf(stderr, "\n");
+ }
+#endif
+ client = clnt_tli_create(RPC_ANYFD, nconf, &taddr,
+ (rpcprog_t)RPCBPROG, (rpcvers_t)RPCBVERS4, 0, 0);
+#ifdef ND_DEBUG
+ if (! client) {
+ clnt_pcreateerror("rpcbind clnt interface");
+ }
+#endif
+
+ if (client) {
+ tmpaddr = targaddr ? taddr2uaddr(nconf, &taddr) : NULL;
+ add_cache(host, nconf->nc_netid, &taddr, tmpaddr);
+ if (targaddr)
+ *targaddr = tmpaddr;
+ break;
+ }
+ }
+ if (res)
+ freeaddrinfo(res);
+ return (client);
+}
+
+/* XXX */
+#define IN4_LOCALHOST_STRING "127.0.0.1"
+#define IN6_LOCALHOST_STRING "::1"
+
+/*
+ * This routine will return a client handle that is connected to the local
+ * rpcbind. Returns NULL on error and free's everything.
+ */
+static CLIENT *
+local_rpcb()
+{
+ CLIENT *client;
+ static struct netconfig *loopnconf;
+ static char *hostname;
+ int sock;
+ size_t tsize;
+ struct netbuf nbuf;
+ struct sockaddr_un sun;
+
+ /*
+ * Try connecting to the local rpcbind through a local socket
+ * first. If this doesn't work, try all transports defined in
+ * the netconfig file.
+ */
+ memset(&sun, 0, sizeof sun);
+ sock = _socket(AF_LOCAL, SOCK_STREAM, 0);
+ if (sock < 0)
+ goto try_nconf;
+ sun.sun_family = AF_LOCAL;
+ strcpy(sun.sun_path, _PATH_RPCBINDSOCK);
+ nbuf.len = sun.sun_len = SUN_LEN(&sun);
+ nbuf.maxlen = sizeof (struct sockaddr_un);
+ nbuf.buf = &sun;
+
+ tsize = __rpc_get_t_size(AF_LOCAL, 0, 0);
+ client = clnt_vc_create(sock, &nbuf, (rpcprog_t)RPCBPROG,
+ (rpcvers_t)RPCBVERS, tsize, tsize);
+
+ if (client != NULL) {
+ /* Mark the socket to be closed in destructor */
+ (void) CLNT_CONTROL(client, CLSET_FD_CLOSE, NULL);
+ return client;
+ }
+
+ /* Nobody needs this socket anymore; free the descriptor. */
+ _close(sock);
+
+try_nconf:
+
+/* VARIABLES PROTECTED BY loopnconf_lock: loopnconf */
+ mutex_lock(&loopnconf_lock);
+ if (loopnconf == NULL) {
+ struct netconfig *nconf, *tmpnconf = NULL;
+ void *nc_handle;
+ int fd;
+
+ nc_handle = setnetconfig();
+ if (nc_handle == NULL) {
+ /* fails to open netconfig file */
+ syslog (LOG_ERR, "rpc: failed to open " NETCONFIG);
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ mutex_unlock(&loopnconf_lock);
+ return (NULL);
+ }
+ while ((nconf = getnetconfig(nc_handle)) != NULL) {
+#ifdef INET6
+ if ((strcmp(nconf->nc_protofmly, NC_INET6) == 0 ||
+#else
+ if ((
+#endif
+ strcmp(nconf->nc_protofmly, NC_INET) == 0) &&
+ (nconf->nc_semantics == NC_TPI_COTS ||
+ nconf->nc_semantics == NC_TPI_COTS_ORD)) {
+ fd = __rpc_nconf2fd(nconf);
+ /*
+ * Can't create a socket, assume that
+ * this family isn't configured in the kernel.
+ */
+ if (fd < 0)
+ continue;
+ _close(fd);
+ tmpnconf = nconf;
+ if (!strcmp(nconf->nc_protofmly, NC_INET))
+ hostname = IN4_LOCALHOST_STRING;
+ else
+ hostname = IN6_LOCALHOST_STRING;
+ }
+ }
+ if (tmpnconf == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ mutex_unlock(&loopnconf_lock);
+ return (NULL);
+ }
+ loopnconf = getnetconfigent(tmpnconf->nc_netid);
+ /* loopnconf is never freed */
+ endnetconfig(nc_handle);
+ }
+ mutex_unlock(&loopnconf_lock);
+ client = getclnthandle(hostname, loopnconf, NULL);
+ return (client);
+}
+
+/*
+ * Set a mapping between program, version and address.
+ * Calls the rpcbind service to do the mapping.
+ */
+bool_t
+rpcb_set(program, version, nconf, address)
+ rpcprog_t program;
+ rpcvers_t version;
+ const struct netconfig *nconf; /* Network structure of transport */
+ const struct netbuf *address; /* Services netconfig address */
+{
+ CLIENT *client;
+ bool_t rslt = FALSE;
+ RPCB parms;
+ char uidbuf[32];
+
+ /* parameter checking */
+ if (nconf == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (FALSE);
+ }
+ if (address == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+ return (FALSE);
+ }
+ client = local_rpcb();
+ if (! client) {
+ return (FALSE);
+ }
+
+ /* convert to universal */
+ /*LINTED const castaway*/
+ parms.r_addr = taddr2uaddr((struct netconfig *) nconf,
+ (struct netbuf *)address);
+ if (!parms.r_addr) {
+ CLNT_DESTROY(client);
+ rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
+ return (FALSE); /* no universal address */
+ }
+ parms.r_prog = program;
+ parms.r_vers = version;
+ parms.r_netid = nconf->nc_netid;
+ /*
+ * Though uid is not being used directly, we still send it for
+ * completeness. For non-unix platforms, perhaps some other
+ * string or an empty string can be sent.
+ */
+ (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
+ parms.r_owner = uidbuf;
+
+ CLNT_CALL(client, (rpcproc_t)RPCBPROC_SET, (xdrproc_t) xdr_rpcb,
+ (char *)(void *)&parms, (xdrproc_t) xdr_bool,
+ (char *)(void *)&rslt, tottimeout);
+
+ CLNT_DESTROY(client);
+ free(parms.r_addr);
+ return (rslt);
+}
+
+/*
+ * Remove the mapping between program, version and netbuf address.
+ * Calls the rpcbind service to do the un-mapping.
+ * If netbuf is NULL, unset for all the transports, otherwise unset
+ * only for the given transport.
+ */
+bool_t
+rpcb_unset(program, version, nconf)
+ rpcprog_t program;
+ rpcvers_t version;
+ const struct netconfig *nconf;
+{
+ CLIENT *client;
+ bool_t rslt = FALSE;
+ RPCB parms;
+ char uidbuf[32];
+
+ client = local_rpcb();
+ if (! client) {
+ return (FALSE);
+ }
+
+ parms.r_prog = program;
+ parms.r_vers = version;
+ if (nconf)
+ parms.r_netid = nconf->nc_netid;
+ else {
+ /*LINTED const castaway*/
+ parms.r_netid = (char *) &nullstring[0]; /* unsets all */
+ }
+ /*LINTED const castaway*/
+ parms.r_addr = (char *) &nullstring[0];
+ (void) snprintf(uidbuf, sizeof uidbuf, "%d", geteuid());
+ parms.r_owner = uidbuf;
+
+ CLNT_CALL(client, (rpcproc_t)RPCBPROC_UNSET, (xdrproc_t) xdr_rpcb,
+ (char *)(void *)&parms, (xdrproc_t) xdr_bool,
+ (char *)(void *)&rslt, tottimeout);
+
+ CLNT_DESTROY(client);
+ return (rslt);
+}
+
+/*
+ * From the merged list, find the appropriate entry
+ */
+static struct netbuf *
+got_entry(relp, nconf)
+ rpcb_entry_list_ptr relp;
+ const struct netconfig *nconf;
+{
+ struct netbuf *na = NULL;
+ rpcb_entry_list_ptr sp;
+ rpcb_entry *rmap;
+
+ for (sp = relp; sp != NULL; sp = sp->rpcb_entry_next) {
+ rmap = &sp->rpcb_entry_map;
+ if ((strcmp(nconf->nc_proto, rmap->r_nc_proto) == 0) &&
+ (strcmp(nconf->nc_protofmly, rmap->r_nc_protofmly) == 0) &&
+ (nconf->nc_semantics == rmap->r_nc_semantics) &&
+ (rmap->r_maddr != NULL) && (rmap->r_maddr[0] != 0)) {
+ na = uaddr2taddr(nconf, rmap->r_maddr);
+#ifdef ND_DEBUG
+ fprintf(stderr, "\tRemote address is [%s].\n",
+ rmap->r_maddr);
+ if (!na)
+ fprintf(stderr,
+ "\tCouldn't resolve remote address!\n");
+#endif
+ break;
+ }
+ }
+ return (na);
+}
+
+/*
+ * Quick check to see if rpcbind is up. Tries to connect over
+ * local transport.
+ */
+static bool_t
+__rpcbind_is_up()
+{
+ struct netconfig *nconf;
+ struct sockaddr_un sun;
+ void *localhandle;
+ int sock;
+
+ nconf = NULL;
+ localhandle = setnetconfig();
+ while ((nconf = getnetconfig(localhandle)) != NULL) {
+ if (nconf->nc_protofmly != NULL &&
+ strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0)
+ break;
+ }
+ if (nconf == NULL)
+ return (FALSE);
+
+ endnetconfig(localhandle);
+
+ memset(&sun, 0, sizeof sun);
+ sock = _socket(AF_LOCAL, SOCK_STREAM, 0);
+ if (sock < 0)
+ return (FALSE);
+ sun.sun_family = AF_LOCAL;
+ strncpy(sun.sun_path, _PATH_RPCBINDSOCK, sizeof(sun.sun_path));
+ sun.sun_len = SUN_LEN(&sun);
+
+ if (_connect(sock, (struct sockaddr *)&sun, sun.sun_len) < 0) {
+ _close(sock);
+ return (FALSE);
+ }
+
+ _close(sock);
+ return (TRUE);
+}
+
+/*
+ * An internal function which optimizes rpcb_getaddr function. It also
+ * returns the client handle that it uses to contact the remote rpcbind.
+ *
+ * The algorithm used: If the transports is TCP or UDP, it first tries
+ * version 2 (portmap), 4 and then 3 (svr4). This order should be
+ * changed in the next OS release to 4, 2 and 3. We are assuming that by
+ * that time, version 4 would be available on many machines on the network.
+ * With this algorithm, we get performance as well as a plan for
+ * obsoleting version 2.
+ *
+ * For all other transports, the algorithm remains as 4 and then 3.
+ *
+ * XXX: Due to some problems with t_connect(), we do not reuse the same client
+ * handle for COTS cases and hence in these cases we do not return the
+ * client handle. This code will change if t_connect() ever
+ * starts working properly. Also look under clnt_vc.c.
+ */
+struct netbuf *
+__rpcb_findaddr_timed(program, version, nconf, host, clpp, tp)
+ rpcprog_t program;
+ rpcvers_t version;
+ const struct netconfig *nconf;
+ const char *host;
+ CLIENT **clpp;
+ struct timeval *tp;
+{
+ static bool_t check_rpcbind = TRUE;
+ CLIENT *client = NULL;
+ RPCB parms;
+ enum clnt_stat clnt_st;
+ char *ua = NULL;
+ rpcvers_t vers;
+ struct netbuf *address = NULL;
+ rpcvers_t start_vers = RPCBVERS4;
+ struct netbuf servaddr;
+
+ /* parameter checking */
+ if (nconf == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+
+ parms.r_addr = NULL;
+
+ /*
+ * Use default total timeout if no timeout is specified.
+ */
+ if (tp == NULL)
+ tp = &tottimeout;
+
+#ifdef PORTMAP
+ /* Try version 2 for TCP or UDP */
+ if (strcmp(nconf->nc_protofmly, NC_INET) == 0) {
+ u_short port = 0;
+ struct netbuf remote;
+ rpcvers_t pmapvers = 2;
+ struct pmap pmapparms;
+
+ /*
+ * Try UDP only - there are some portmappers out
+ * there that use UDP only.
+ */
+ if (strcmp(nconf->nc_proto, NC_TCP) == 0) {
+ struct netconfig *newnconf;
+
+ if ((newnconf = getnetconfigent("udp")) == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+ client = getclnthandle(host, newnconf, &parms.r_addr);
+ freenetconfigent(newnconf);
+ } else {
+ client = getclnthandle(host, nconf, &parms.r_addr);
+ }
+ if (client == NULL)
+ return (NULL);
+
+ /*
+ * Set version and retry timeout.
+ */
+ CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime);
+ CLNT_CONTROL(client, CLSET_VERS, (char *)&pmapvers);
+
+ pmapparms.pm_prog = program;
+ pmapparms.pm_vers = version;
+ pmapparms.pm_prot = strcmp(nconf->nc_proto, NC_TCP) ?
+ IPPROTO_UDP : IPPROTO_TCP;
+ pmapparms.pm_port = 0; /* not needed */
+ clnt_st = CLNT_CALL(client, (rpcproc_t)PMAPPROC_GETPORT,
+ (xdrproc_t) xdr_pmap, (caddr_t)(void *)&pmapparms,
+ (xdrproc_t) xdr_u_short, (caddr_t)(void *)&port,
+ *tp);
+ if (clnt_st != RPC_SUCCESS) {
+ if ((clnt_st == RPC_PROGVERSMISMATCH) ||
+ (clnt_st == RPC_PROGUNAVAIL))
+ goto try_rpcbind; /* Try different versions */
+ rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+ goto error;
+ } else if (port == 0) {
+ address = NULL;
+ rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+ goto error;
+ }
+ port = htons(port);
+ CLNT_CONTROL(client, CLGET_SVC_ADDR, (char *)&remote);
+ if (((address = (struct netbuf *)
+ malloc(sizeof (struct netbuf))) == NULL) ||
+ ((address->buf = (char *)
+ malloc(remote.len)) == NULL)) {
+ rpc_createerr.cf_stat = RPC_SYSTEMERROR;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+ if (address) {
+ free(address);
+ address = NULL;
+ }
+ goto error;
+ }
+ memcpy(address->buf, remote.buf, remote.len);
+ memcpy(&((char *)address->buf)[sizeof (short)],
+ (char *)(void *)&port, sizeof (short));
+ address->len = address->maxlen = remote.len;
+ goto done;
+ }
+#endif /* PORTMAP */
+
+try_rpcbind:
+ /*
+ * Check if rpcbind is up. This prevents needless delays when
+ * accessing applications such as the keyserver while booting
+ * disklessly.
+ */
+ if (check_rpcbind && strcmp(nconf->nc_protofmly, NC_LOOPBACK) == 0) {
+ if (!__rpcbind_is_up()) {
+ rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+ rpc_createerr.cf_error.re_errno = 0;
+ goto error;
+ }
+ check_rpcbind = FALSE;
+ }
+
+ /*
+ * Now we try version 4 and then 3.
+ * We also send the remote system the address we used to
+ * contact it in case it can help to connect back with us
+ */
+ parms.r_prog = program;
+ parms.r_vers = version;
+ /*LINTED const castaway*/
+ parms.r_owner = (char *) &nullstring[0]; /* not needed; */
+ /* just for xdring */
+ parms.r_netid = nconf->nc_netid; /* not really needed */
+
+ /*
+ * If a COTS transport is being used, try getting address via CLTS
+ * transport. This works only with version 4.
+ */
+ if (nconf->nc_semantics == NC_TPI_COTS_ORD ||
+ nconf->nc_semantics == NC_TPI_COTS) {
+
+ void *handle;
+ struct netconfig *nconf_clts;
+ rpcb_entry_list_ptr relp = NULL;
+
+ if (client == NULL) {
+ /* This did not go through the above PORTMAP/TCP code */
+ if ((handle = __rpc_setconf("datagram_v")) != NULL) {
+ while ((nconf_clts = __rpc_getconf(handle))
+ != NULL) {
+ if (strcmp(nconf_clts->nc_protofmly,
+ nconf->nc_protofmly) != 0) {
+ continue;
+ }
+ client = getclnthandle(host, nconf_clts,
+ &parms.r_addr);
+ break;
+ }
+ __rpc_endconf(handle);
+ }
+ if (client == NULL)
+ goto regular_rpcbind; /* Go the regular way */
+ } else {
+ /* This is a UDP PORTMAP handle. Change to version 4 */
+ vers = RPCBVERS4;
+ CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
+ }
+ /*
+ * We also send the remote system the address we used to
+ * contact it in case it can help it connect back with us
+ */
+ if (parms.r_addr == NULL) {
+ /*LINTED const castaway*/
+ parms.r_addr = (char *) &nullstring[0]; /* for XDRing */
+ }
+
+ CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)&rpcbrmttime);
+
+ clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDRLIST,
+ (xdrproc_t) xdr_rpcb, (char *)(void *)&parms,
+ (xdrproc_t) xdr_rpcb_entry_list_ptr,
+ (char *)(void *)&relp, *tp);
+ if (clnt_st == RPC_SUCCESS) {
+ if ((address = got_entry(relp, nconf)) != NULL) {
+ xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr,
+ (char *)(void *)&relp);
+ CLNT_CONTROL(client, CLGET_SVC_ADDR,
+ (char *)(void *)&servaddr);
+ __rpc_fixup_addr(address, &servaddr);
+ goto done;
+ }
+ /* Entry not found for this transport */
+ xdr_free((xdrproc_t) xdr_rpcb_entry_list_ptr,
+ (char *)(void *)&relp);
+ /*
+ * XXX: should have perhaps returned with error but
+ * since the remote machine might not always be able
+ * to send the address on all transports, we try the
+ * regular way with regular_rpcbind
+ */
+ goto regular_rpcbind;
+ } else if ((clnt_st == RPC_PROGVERSMISMATCH) ||
+ (clnt_st == RPC_PROGUNAVAIL)) {
+ start_vers = RPCBVERS; /* Try version 3 now */
+ goto regular_rpcbind; /* Try different versions */
+ } else {
+ rpc_createerr.cf_stat = RPC_PMAPFAILURE;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+ goto error;
+ }
+ }
+
+regular_rpcbind:
+
+ /* Now the same transport is to be used to get the address */
+ if (client && ((nconf->nc_semantics == NC_TPI_COTS_ORD) ||
+ (nconf->nc_semantics == NC_TPI_COTS))) {
+ /* A CLTS type of client - destroy it */
+ CLNT_DESTROY(client);
+ client = NULL;
+ }
+
+ if (client == NULL) {
+ client = getclnthandle(host, nconf, &parms.r_addr);
+ if (client == NULL) {
+ goto error;
+ }
+ }
+ if (parms.r_addr == NULL) {
+ /*LINTED const castaway*/
+ parms.r_addr = (char *) &nullstring[0];
+ }
+
+ /* First try from start_vers and then version 3 (RPCBVERS) */
+
+ CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *) &rpcbrmttime);
+ for (vers = start_vers; vers >= RPCBVERS; vers--) {
+ /* Set the version */
+ CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
+ clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETADDR,
+ (xdrproc_t) xdr_rpcb, (char *)(void *)&parms,
+ (xdrproc_t) xdr_wrapstring, (char *)(void *) &ua, *tp);
+ if (clnt_st == RPC_SUCCESS) {
+ if ((ua == NULL) || (ua[0] == 0)) {
+ /* address unknown */
+ rpc_createerr.cf_stat = RPC_PROGNOTREGISTERED;
+ goto error;
+ }
+ address = uaddr2taddr(nconf, ua);
+#ifdef ND_DEBUG
+ fprintf(stderr, "\tRemote address is [%s]\n", ua);
+ if (!address)
+ fprintf(stderr,
+ "\tCouldn't resolve remote address!\n");
+#endif
+ xdr_free((xdrproc_t)xdr_wrapstring,
+ (char *)(void *)&ua);
+
+ if (! address) {
+ /* We don't know about your universal address */
+ rpc_createerr.cf_stat = RPC_N2AXLATEFAILURE;
+ goto error;
+ }
+ CLNT_CONTROL(client, CLGET_SVC_ADDR,
+ (char *)(void *)&servaddr);
+ __rpc_fixup_addr(address, &servaddr);
+ goto done;
+ } else if (clnt_st == RPC_PROGVERSMISMATCH) {
+ struct rpc_err rpcerr;
+
+ clnt_geterr(client, &rpcerr);
+ if (rpcerr.re_vers.low > RPCBVERS4)
+ goto error; /* a new version, can't handle */
+ } else if (clnt_st != RPC_PROGUNAVAIL) {
+ /* Cant handle this error */
+ rpc_createerr.cf_stat = clnt_st;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+ goto error;
+ }
+ }
+
+error:
+ if (client) {
+ CLNT_DESTROY(client);
+ client = NULL;
+ }
+done:
+ if (nconf->nc_semantics != NC_TPI_CLTS) {
+ /* This client is the connectionless one */
+ if (client) {
+ CLNT_DESTROY(client);
+ client = NULL;
+ }
+ }
+ if (clpp) {
+ *clpp = client;
+ } else if (client) {
+ CLNT_DESTROY(client);
+ }
+ if (parms.r_addr != NULL && parms.r_addr != nullstring)
+ free(parms.r_addr);
+ return (address);
+}
+
+
+/*
+ * Find the mapped address for program, version.
+ * Calls the rpcbind service remotely to do the lookup.
+ * Uses the transport specified in nconf.
+ * Returns FALSE (0) if no map exists, else returns 1.
+ *
+ * Assuming that the address is all properly allocated
+ */
+int
+rpcb_getaddr(program, version, nconf, address, host)
+ rpcprog_t program;
+ rpcvers_t version;
+ const struct netconfig *nconf;
+ struct netbuf *address;
+ const char *host;
+{
+ struct netbuf *na;
+
+ if ((na = __rpcb_findaddr_timed(program, version,
+ (struct netconfig *) nconf, (char *) host,
+ (CLIENT **) NULL, (struct timeval *) NULL)) == NULL)
+ return (FALSE);
+
+ if (na->len > address->maxlen) {
+ /* Too long address */
+ free(na->buf);
+ free(na);
+ rpc_createerr.cf_stat = RPC_FAILED;
+ return (FALSE);
+ }
+ memcpy(address->buf, na->buf, (size_t)na->len);
+ address->len = na->len;
+ free(na->buf);
+ free(na);
+ return (TRUE);
+}
+
+/*
+ * Get a copy of the current maps.
+ * Calls the rpcbind service remotely to get the maps.
+ *
+ * It returns only a list of the services
+ * It returns NULL on failure.
+ */
+rpcblist *
+rpcb_getmaps(nconf, host)
+ const struct netconfig *nconf;
+ const char *host;
+{
+ rpcblist_ptr head = NULL;
+ CLIENT *client;
+ enum clnt_stat clnt_st;
+ rpcvers_t vers = 0;
+
+ client = getclnthandle(host, nconf, NULL);
+ if (client == NULL) {
+ return (head);
+ }
+ clnt_st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP,
+ (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr,
+ (char *)(void *)&head, tottimeout);
+ if (clnt_st == RPC_SUCCESS)
+ goto done;
+
+ if ((clnt_st != RPC_PROGVERSMISMATCH) &&
+ (clnt_st != RPC_PROGUNAVAIL)) {
+ rpc_createerr.cf_stat = RPC_RPCBFAILURE;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+ goto done;
+ }
+
+ /* fall back to earlier version */
+ CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers);
+ if (vers == RPCBVERS4) {
+ vers = RPCBVERS;
+ CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
+ if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_DUMP,
+ (xdrproc_t) xdr_void, NULL, (xdrproc_t) xdr_rpcblist_ptr,
+ (char *)(void *)&head, tottimeout) == RPC_SUCCESS)
+ goto done;
+ }
+ rpc_createerr.cf_stat = RPC_RPCBFAILURE;
+ clnt_geterr(client, &rpc_createerr.cf_error);
+
+done:
+ CLNT_DESTROY(client);
+ return (head);
+}
+
+/*
+ * rpcbinder remote-call-service interface.
+ * This routine is used to call the rpcbind remote call service
+ * which will look up a service program in the address maps, and then
+ * remotely call that routine with the given parameters. This allows
+ * programs to do a lookup and call in one step.
+*/
+enum clnt_stat
+rpcb_rmtcall(nconf, host, prog, vers, proc, xdrargs, argsp,
+ xdrres, resp, tout, addr_ptr)
+ const struct netconfig *nconf; /* Netconfig structure */
+ const char *host; /* Remote host name */
+ rpcprog_t prog;
+ rpcvers_t vers;
+ rpcproc_t proc; /* Remote proc identifiers */
+ xdrproc_t xdrargs, xdrres; /* XDR routines */
+ caddr_t argsp, resp; /* Argument and Result */
+ struct timeval tout; /* Timeout value for this call */
+ const struct netbuf *addr_ptr; /* Preallocated netbuf address */
+{
+ CLIENT *client;
+ enum clnt_stat stat;
+ struct r_rpcb_rmtcallargs a;
+ struct r_rpcb_rmtcallres r;
+ rpcvers_t rpcb_vers;
+
+ stat = 0;
+ client = getclnthandle(host, nconf, NULL);
+ if (client == NULL) {
+ return (RPC_FAILED);
+ }
+ /*LINTED const castaway*/
+ CLNT_CONTROL(client, CLSET_RETRY_TIMEOUT, (char *)(void *)&rmttimeout);
+ a.prog = prog;
+ a.vers = vers;
+ a.proc = proc;
+ a.args.args_val = argsp;
+ a.xdr_args = xdrargs;
+ r.addr = NULL;
+ r.results.results_val = resp;
+ r.xdr_res = xdrres;
+
+ for (rpcb_vers = RPCBVERS4; rpcb_vers >= RPCBVERS; rpcb_vers--) {
+ CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&rpcb_vers);
+ stat = CLNT_CALL(client, (rpcproc_t)RPCBPROC_CALLIT,
+ (xdrproc_t) xdr_rpcb_rmtcallargs, (char *)(void *)&a,
+ (xdrproc_t) xdr_rpcb_rmtcallres, (char *)(void *)&r, tout);
+ if ((stat == RPC_SUCCESS) && (addr_ptr != NULL)) {
+ struct netbuf *na;
+ /*LINTED const castaway*/
+ na = uaddr2taddr((struct netconfig *) nconf, r.addr);
+ if (!na) {
+ stat = RPC_N2AXLATEFAILURE;
+ /*LINTED const castaway*/
+ ((struct netbuf *) addr_ptr)->len = 0;
+ goto error;
+ }
+ if (na->len > addr_ptr->maxlen) {
+ /* Too long address */
+ stat = RPC_FAILED; /* XXX A better error no */
+ free(na->buf);
+ free(na);
+ /*LINTED const castaway*/
+ ((struct netbuf *) addr_ptr)->len = 0;
+ goto error;
+ }
+ memcpy(addr_ptr->buf, na->buf, (size_t)na->len);
+ /*LINTED const castaway*/
+ ((struct netbuf *)addr_ptr)->len = na->len;
+ free(na->buf);
+ free(na);
+ break;
+ } else if ((stat != RPC_PROGVERSMISMATCH) &&
+ (stat != RPC_PROGUNAVAIL)) {
+ goto error;
+ }
+ }
+error:
+ CLNT_DESTROY(client);
+ if (r.addr)
+ xdr_free((xdrproc_t) xdr_wrapstring, (char *)(void *)&r.addr);
+ return (stat);
+}
+
+/*
+ * Gets the time on the remote host.
+ * Returns 1 if succeeds else 0.
+ */
+bool_t
+rpcb_gettime(host, timep)
+ const char *host;
+ time_t *timep;
+{
+ CLIENT *client = NULL;
+ void *handle;
+ struct netconfig *nconf;
+ rpcvers_t vers;
+ enum clnt_stat st;
+
+
+ if ((host == NULL) || (host[0] == 0)) {
+ time(timep);
+ return (TRUE);
+ }
+
+ if ((handle = __rpc_setconf("netpath")) == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (FALSE);
+ }
+ rpc_createerr.cf_stat = RPC_SUCCESS;
+ while (client == NULL) {
+ if ((nconf = __rpc_getconf(handle)) == NULL) {
+ if (rpc_createerr.cf_stat == RPC_SUCCESS)
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ break;
+ }
+ client = getclnthandle(host, nconf, NULL);
+ if (client)
+ break;
+ }
+ __rpc_endconf(handle);
+ if (client == (CLIENT *) NULL) {
+ return (FALSE);
+ }
+
+ st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME,
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_int, (char *)(void *)timep, tottimeout);
+
+ if ((st == RPC_PROGVERSMISMATCH) || (st == RPC_PROGUNAVAIL)) {
+ CLNT_CONTROL(client, CLGET_VERS, (char *)(void *)&vers);
+ if (vers == RPCBVERS4) {
+ /* fall back to earlier version */
+ vers = RPCBVERS;
+ CLNT_CONTROL(client, CLSET_VERS, (char *)(void *)&vers);
+ st = CLNT_CALL(client, (rpcproc_t)RPCBPROC_GETTIME,
+ (xdrproc_t) xdr_void, NULL,
+ (xdrproc_t) xdr_int, (char *)(void *)timep,
+ tottimeout);
+ }
+ }
+ CLNT_DESTROY(client);
+ return (st == RPC_SUCCESS? TRUE: FALSE);
+}
+
+/*
+ * Converts taddr to universal address. This routine should never
+ * really be called because local n2a libraries are always provided.
+ */
+char *
+rpcb_taddr2uaddr(nconf, taddr)
+ struct netconfig *nconf;
+ struct netbuf *taddr;
+{
+ CLIENT *client;
+ char *uaddr = NULL;
+
+
+ /* parameter checking */
+ if (nconf == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+ if (taddr == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+ return (NULL);
+ }
+ client = local_rpcb();
+ if (! client) {
+ return (NULL);
+ }
+
+ CLNT_CALL(client, (rpcproc_t)RPCBPROC_TADDR2UADDR,
+ (xdrproc_t) xdr_netbuf, (char *)(void *)taddr,
+ (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr, tottimeout);
+ CLNT_DESTROY(client);
+ return (uaddr);
+}
+
+/*
+ * Converts universal address to netbuf. This routine should never
+ * really be called because local n2a libraries are always provided.
+ */
+struct netbuf *
+rpcb_uaddr2taddr(nconf, uaddr)
+ struct netconfig *nconf;
+ char *uaddr;
+{
+ CLIENT *client;
+ struct netbuf *taddr;
+
+
+ /* parameter checking */
+ if (nconf == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNPROTO;
+ return (NULL);
+ }
+ if (uaddr == NULL) {
+ rpc_createerr.cf_stat = RPC_UNKNOWNADDR;
+ return (NULL);
+ }
+ client = local_rpcb();
+ if (! client) {
+ return (NULL);
+ }
+
+ taddr = (struct netbuf *)calloc(1, sizeof (struct netbuf));
+ if (taddr == NULL) {
+ CLNT_DESTROY(client);
+ return (NULL);
+ }
+ if (CLNT_CALL(client, (rpcproc_t)RPCBPROC_UADDR2TADDR,
+ (xdrproc_t) xdr_wrapstring, (char *)(void *)&uaddr,
+ (xdrproc_t) xdr_netbuf, (char *)(void *)taddr,
+ tottimeout) != RPC_SUCCESS) {
+ free(taddr);
+ taddr = NULL;
+ }
+ CLNT_DESTROY(client);
+ return (taddr);
+}
diff --git a/lib/libc/rpc/rpcb_prot.c b/lib/libc/rpc/rpcb_prot.c
new file mode 100644
index 0000000..f766749
--- /dev/null
+++ b/lib/libc/rpc/rpcb_prot.c
@@ -0,0 +1,332 @@
+/* $NetBSD: rpcb_prot.c,v 1.3 2000/07/14 08:40:42 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/* #ident "@(#)rpcb_prot.c 1.13 94/04/24 SMI" */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rpcb_prot.c 1.9 89/04/21 Copyr 1984 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * rpcb_prot.c
+ * XDR routines for the rpcbinder version 3.
+ *
+ * Copyright (C) 1984, 1988, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <rpc/rpc.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/rpcb_prot.h>
+#include "un-namespace.h"
+
+bool_t
+xdr_rpcb(xdrs, objp)
+ XDR *xdrs;
+ RPCB *objp;
+{
+ if (!xdr_u_int32_t(xdrs, &objp->r_prog)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int32_t(xdrs, &objp->r_vers)) {
+ return (FALSE);
+ }
+ if (!xdr_string(xdrs, &objp->r_netid, (u_int)~0)) {
+ return (FALSE);
+ }
+ if (!xdr_string(xdrs, &objp->r_addr, (u_int)~0)) {
+ return (FALSE);
+ }
+ if (!xdr_string(xdrs, &objp->r_owner, (u_int)~0)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*
+ * rpcblist_ptr implements a linked list. The RPCL definition from
+ * rpcb_prot.x is:
+ *
+ * struct rpcblist {
+ * rpcb rpcb_map;
+ * struct rpcblist *rpcb_next;
+ * };
+ * typedef rpcblist *rpcblist_ptr;
+ *
+ * Recall that "pointers" in XDR are encoded as a boolean, indicating whether
+ * there's any data behind the pointer, followed by the data (if any exists).
+ * The boolean can be interpreted as ``more data follows me''; if FALSE then
+ * nothing follows the boolean; if TRUE then the boolean is followed by an
+ * actual struct rpcb, and another rpcblist_ptr (declared in RPCL as "struct
+ * rpcblist *").
+ *
+ * This could be implemented via the xdr_pointer type, though this would
+ * result in one recursive call per element in the list. Rather than do that
+ * we can ``unwind'' the recursion into a while loop and use xdr_reference to
+ * serialize the rpcb elements.
+ */
+
+bool_t
+xdr_rpcblist_ptr(xdrs, rp)
+ XDR *xdrs;
+ rpcblist_ptr *rp;
+{
+ /*
+ * more_elements is pre-computed in case the direction is
+ * XDR_ENCODE or XDR_FREE. more_elements is overwritten by
+ * xdr_bool when the direction is XDR_DECODE.
+ */
+ bool_t more_elements;
+ int freeing = (xdrs->x_op == XDR_FREE);
+ rpcblist_ptr next;
+ rpcblist_ptr next_copy;
+
+ next = NULL;
+ for (;;) {
+ more_elements = (bool_t)(*rp != NULL);
+ if (! xdr_bool(xdrs, &more_elements)) {
+ return (FALSE);
+ }
+ if (! more_elements) {
+ return (TRUE); /* we are done */
+ }
+ /*
+ * the unfortunate side effect of non-recursion is that in
+ * the case of freeing we must remember the next object
+ * before we free the current object ...
+ */
+ if (freeing && *rp)
+ next = (*rp)->rpcb_next;
+ if (! xdr_reference(xdrs, (caddr_t *)rp,
+ (u_int)sizeof (rpcblist), (xdrproc_t)xdr_rpcb)) {
+ return (FALSE);
+ }
+ if (freeing) {
+ next_copy = next;
+ rp = &next_copy;
+ /*
+ * Note that in the subsequent iteration, next_copy
+ * gets nulled out by the xdr_reference
+ * but next itself survives.
+ */
+ } else if (*rp) {
+ rp = &((*rp)->rpcb_next);
+ }
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * xdr_rpcblist() is specified to take a RPCBLIST **, but is identical in
+ * functionality to xdr_rpcblist_ptr().
+ */
+bool_t
+xdr_rpcblist(xdrs, rp)
+ XDR *xdrs;
+ RPCBLIST **rp;
+{
+ bool_t dummy;
+
+ dummy = xdr_rpcblist_ptr(xdrs, (rpcblist_ptr *)rp);
+ return (dummy);
+}
+
+
+bool_t
+xdr_rpcb_entry(xdrs, objp)
+ XDR *xdrs;
+ rpcb_entry *objp;
+{
+ if (!xdr_string(xdrs, &objp->r_maddr, (u_int)~0)) {
+ return (FALSE);
+ }
+ if (!xdr_string(xdrs, &objp->r_nc_netid, (u_int)~0)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int32_t(xdrs, &objp->r_nc_semantics)) {
+ return (FALSE);
+ }
+ if (!xdr_string(xdrs, &objp->r_nc_protofmly, (u_int)~0)) {
+ return (FALSE);
+ }
+ if (!xdr_string(xdrs, &objp->r_nc_proto, (u_int)~0)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_rpcb_entry_list_ptr(xdrs, rp)
+ XDR *xdrs;
+ rpcb_entry_list_ptr *rp;
+{
+ /*
+ * more_elements is pre-computed in case the direction is
+ * XDR_ENCODE or XDR_FREE. more_elements is overwritten by
+ * xdr_bool when the direction is XDR_DECODE.
+ */
+ bool_t more_elements;
+ int freeing = (xdrs->x_op == XDR_FREE);
+ rpcb_entry_list_ptr next;
+ rpcb_entry_list_ptr next_copy;
+
+ next = NULL;
+ for (;;) {
+ more_elements = (bool_t)(*rp != NULL);
+ if (! xdr_bool(xdrs, &more_elements)) {
+ return (FALSE);
+ }
+ if (! more_elements) {
+ return (TRUE); /* we are done */
+ }
+ /*
+ * the unfortunate side effect of non-recursion is that in
+ * the case of freeing we must remember the next object
+ * before we free the current object ...
+ */
+ if (freeing)
+ next = (*rp)->rpcb_entry_next;
+ if (! xdr_reference(xdrs, (caddr_t *)rp,
+ (u_int)sizeof (rpcb_entry_list),
+ (xdrproc_t)xdr_rpcb_entry)) {
+ return (FALSE);
+ }
+ if (freeing && *rp) {
+ next_copy = next;
+ rp = &next_copy;
+ /*
+ * Note that in the subsequent iteration, next_copy
+ * gets nulled out by the xdr_reference
+ * but next itself survives.
+ */
+ } else if (*rp) {
+ rp = &((*rp)->rpcb_entry_next);
+ }
+ }
+ /*NOTREACHED*/
+}
+
+/*
+ * XDR remote call arguments
+ * written for XDR_ENCODE direction only
+ */
+bool_t
+xdr_rpcb_rmtcallargs(xdrs, p)
+ XDR *xdrs;
+ struct rpcb_rmtcallargs *p;
+{
+ struct r_rpcb_rmtcallargs *objp =
+ (struct r_rpcb_rmtcallargs *)(void *)p;
+ u_int lenposition, argposition, position;
+ int32_t *buf;
+
+ buf = XDR_INLINE(xdrs, 3 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_u_int32_t(xdrs, &objp->prog)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int32_t(xdrs, &objp->vers)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int32_t(xdrs, &objp->proc)) {
+ return (FALSE);
+ }
+ } else {
+ IXDR_PUT_U_INT32(buf, objp->prog);
+ IXDR_PUT_U_INT32(buf, objp->vers);
+ IXDR_PUT_U_INT32(buf, objp->proc);
+ }
+
+ /*
+ * All the jugglery for just getting the size of the arguments
+ */
+ lenposition = XDR_GETPOS(xdrs);
+ if (! xdr_u_int(xdrs, &(objp->args.args_len))) {
+ return (FALSE);
+ }
+ argposition = XDR_GETPOS(xdrs);
+ if (! (*objp->xdr_args)(xdrs, objp->args.args_val)) {
+ return (FALSE);
+ }
+ position = XDR_GETPOS(xdrs);
+ objp->args.args_len = (u_int)((u_long)position - (u_long)argposition);
+ XDR_SETPOS(xdrs, lenposition);
+ if (! xdr_u_int(xdrs, &(objp->args.args_len))) {
+ return (FALSE);
+ }
+ XDR_SETPOS(xdrs, position);
+ return (TRUE);
+}
+
+/*
+ * XDR remote call results
+ * written for XDR_DECODE direction only
+ */
+bool_t
+xdr_rpcb_rmtcallres(xdrs, p)
+ XDR *xdrs;
+ struct rpcb_rmtcallres *p;
+{
+ bool_t dummy;
+ struct r_rpcb_rmtcallres *objp = (struct r_rpcb_rmtcallres *)(void *)p;
+
+ if (!xdr_string(xdrs, &objp->addr, (u_int)~0)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int(xdrs, &objp->results.results_len)) {
+ return (FALSE);
+ }
+ dummy = (*(objp->xdr_res))(xdrs, objp->results.results_val);
+ return (dummy);
+}
+
+bool_t
+xdr_netbuf(xdrs, objp)
+ XDR *xdrs;
+ struct netbuf *objp;
+{
+ bool_t dummy;
+ void **pp;
+
+ if (!xdr_u_int32_t(xdrs, (u_int32_t *) &objp->maxlen)) {
+ return (FALSE);
+ }
+ pp = &objp->buf;
+ dummy = xdr_bytes(xdrs, (char **) pp,
+ (u_int *)&(objp->len), objp->maxlen);
+ return (dummy);
+}
diff --git a/lib/libc/rpc/rpcb_st_xdr.c b/lib/libc/rpc/rpcb_st_xdr.c
new file mode 100644
index 0000000..cf1e227
--- /dev/null
+++ b/lib/libc/rpc/rpcb_st_xdr.c
@@ -0,0 +1,275 @@
+/* $NetBSD: rpcb_st_xdr.c,v 1.3 2000/07/14 08:40:42 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright 1991 Sun Microsystems, Inc.
+ * rpcb_stat_xdr.c
+ */
+
+/*
+ * This file was generated from rpcb_prot.x, but includes only those
+ * routines used with the rpcbind stats facility.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <rpc/rpc.h>
+#include "un-namespace.h"
+
+/* Link list of all the stats about getport and getaddr */
+
+bool_t
+xdr_rpcbs_addrlist(xdrs, objp)
+ XDR *xdrs;
+ rpcbs_addrlist *objp;
+{
+ struct rpcbs_addrlist **pnext;
+
+ if (!xdr_u_int32_t(xdrs, &objp->prog)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int32_t(xdrs, &objp->vers)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->success)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->failure)) {
+ return (FALSE);
+ }
+ if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
+ return (FALSE);
+ }
+
+ pnext = &objp->next;
+
+ if (!xdr_pointer(xdrs, (char **) pnext,
+ sizeof (rpcbs_addrlist),
+ (xdrproc_t)xdr_rpcbs_addrlist)) {
+ return (FALSE);
+ }
+
+ return (TRUE);
+}
+
+/* Link list of all the stats about rmtcall */
+
+bool_t
+xdr_rpcbs_rmtcalllist(xdrs, objp)
+ XDR *xdrs;
+ rpcbs_rmtcalllist *objp;
+{
+ int32_t *buf;
+ struct rpcbs_rmtcalllist **pnext;
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_u_int32_t(xdrs, &objp->prog)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int32_t(xdrs, &objp->vers)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int32_t(xdrs, &objp->proc)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->success)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->failure)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->indirect)) {
+ return (FALSE);
+ }
+ } else {
+ IXDR_PUT_U_INT32(buf, objp->prog);
+ IXDR_PUT_U_INT32(buf, objp->vers);
+ IXDR_PUT_U_INT32(buf, objp->proc);
+ IXDR_PUT_INT32(buf, objp->success);
+ IXDR_PUT_INT32(buf, objp->failure);
+ IXDR_PUT_INT32(buf, objp->indirect);
+ }
+ if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
+ return (FALSE);
+ }
+ pnext = &objp->next;
+ if (!xdr_pointer(xdrs, (char **) pnext,
+ sizeof (rpcbs_rmtcalllist),
+ (xdrproc_t)xdr_rpcbs_rmtcalllist)) {
+ return (FALSE);
+ }
+ return (TRUE);
+ } else if (xdrs->x_op == XDR_DECODE) {
+ buf = XDR_INLINE(xdrs, 6 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_u_int32_t(xdrs, &objp->prog)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int32_t(xdrs, &objp->vers)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int32_t(xdrs, &objp->proc)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->success)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->failure)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->indirect)) {
+ return (FALSE);
+ }
+ } else {
+ objp->prog = (rpcprog_t)IXDR_GET_U_INT32(buf);
+ objp->vers = (rpcvers_t)IXDR_GET_U_INT32(buf);
+ objp->proc = (rpcproc_t)IXDR_GET_U_INT32(buf);
+ objp->success = (int)IXDR_GET_INT32(buf);
+ objp->failure = (int)IXDR_GET_INT32(buf);
+ objp->indirect = (int)IXDR_GET_INT32(buf);
+ }
+ if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
+ return (FALSE);
+ }
+ if (!xdr_pointer(xdrs, (char **) pnext,
+ sizeof (rpcbs_rmtcalllist),
+ (xdrproc_t)xdr_rpcbs_rmtcalllist)) {
+ return (FALSE);
+ }
+ return (TRUE);
+ }
+ if (!xdr_u_int32_t(xdrs, &objp->prog)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int32_t(xdrs, &objp->vers)) {
+ return (FALSE);
+ }
+ if (!xdr_u_int32_t(xdrs, &objp->proc)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->success)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->failure)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->indirect)) {
+ return (FALSE);
+ }
+ if (!xdr_string(xdrs, &objp->netid, (u_int)~0)) {
+ return (FALSE);
+ }
+ if (!xdr_pointer(xdrs, (char **) pnext,
+ sizeof (rpcbs_rmtcalllist),
+ (xdrproc_t)xdr_rpcbs_rmtcalllist)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_rpcbs_proc(xdrs, objp)
+ XDR *xdrs;
+ rpcbs_proc objp;
+{
+ if (!xdr_vector(xdrs, (char *)(void *)objp, RPCBSTAT_HIGHPROC,
+ sizeof (int), (xdrproc_t)xdr_int)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_rpcbs_addrlist_ptr(xdrs, objp)
+ XDR *xdrs;
+ rpcbs_addrlist_ptr *objp;
+{
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof (rpcbs_addrlist),
+ (xdrproc_t)xdr_rpcbs_addrlist)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_rpcbs_rmtcalllist_ptr(xdrs, objp)
+ XDR *xdrs;
+ rpcbs_rmtcalllist_ptr *objp;
+{
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof (rpcbs_rmtcalllist),
+ (xdrproc_t)xdr_rpcbs_rmtcalllist)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_rpcb_stat(xdrs, objp)
+ XDR *xdrs;
+ rpcb_stat *objp;
+{
+
+ if (!xdr_rpcbs_proc(xdrs, objp->info)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->setinfo)) {
+ return (FALSE);
+ }
+ if (!xdr_int(xdrs, &objp->unsetinfo)) {
+ return (FALSE);
+ }
+ if (!xdr_rpcbs_addrlist_ptr(xdrs, &objp->addrinfo)) {
+ return (FALSE);
+ }
+ if (!xdr_rpcbs_rmtcalllist_ptr(xdrs, &objp->rmtinfo)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*
+ * One rpcb_stat structure is returned for each version of rpcbind
+ * being monitored.
+ */
+bool_t
+xdr_rpcb_stat_byvers(xdrs, objp)
+ XDR *xdrs;
+ rpcb_stat_byvers objp;
+{
+ if (!xdr_vector(xdrs, (char *)(void *)objp, RPCBVERS_STAT,
+ sizeof (rpcb_stat), (xdrproc_t)xdr_rpcb_stat)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
diff --git a/lib/libc/rpc/rpcbind.3 b/lib/libc/rpc/rpcbind.3
new file mode 100644
index 0000000..0b716ca
--- /dev/null
+++ b/lib/libc/rpc/rpcbind.3
@@ -0,0 +1,194 @@
+.\" @(#)rpcbind.3n 1.25 93/05/07 SMI; from SVr4
+.\" Copyright 1989 AT&T
+.\" Copyright (c) 1988 Sun Microsystem's, Inc. - All Right's Reserved.
+.\" $NetBSD: rpcbind.3,v 1.2 2000/06/03 18:47:28 fvdl Exp $
+.\" $FreeBSD$
+.Dd May 7, 1993
+.Dt RPCBIND 3
+.Os
+.Sh NAME
+.Nm rpcb_getmaps ,
+.Nm rpcb_getaddr ,
+.Nm rpcb_gettime ,
+.Nm rpcb_rmtcall ,
+.Nm rpcb_set ,
+.Nm rpcb_unset
+.Nd library routines for RPC bind service
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In rpc/rpc.h
+.Ft "rpcblist *"
+.Fn rpcb_getmaps "const struct netconfig *netconf" "const char *host"
+.Ft bool_t
+.Fn rpcb_getaddr "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" "struct netbuf *svcaddr" "const char *host"
+.Ft bool_t
+.Fn rpcb_gettime "const char *host" "time_t * timep"
+.Ft "enum clnt_stat"
+.Fn rpcb_rmtcall "const struct netconfig *netconf" "const char *host" "const rpcprog_t prognum, const rpcvers_t versnum" "const rpcproc_t procnum, const xdrproc_t inproc" "const caddr_t in" "const xdrproc_t outproc" "const caddr_t out" "const struct timeval tout, const struct netbuf *svcaddr"
+.Ft bool_t
+.Fn rpcb_set "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf" "const struct netbuf *svcaddr"
+.Ft bool_t
+.Fn rpcb_unset "const rpcprog_t prognum" "const rpcvers_t versnum" "const struct netconfig *netconf"
+.Sh DESCRIPTION
+These routines allow client C programs to make procedure
+calls to the RPC binder service.
+(see
+.Xr rpcbind 8 )
+maintains a list of mappings between programs
+and their universal addresses.
+.Sh Routines
+.Bl -tag -width XXXXX
+.It Fn rpcb_getmaps
+An interface to the rpcbind service,
+which returns a list of the current
+RPC program-to-address mappings on
+.Fa host .
+It uses the transport specified through
+.Fa netconf
+to contact the remote rpcbind
+service on
+.Fa host .
+This routine will return
+.Dv NULL ,
+if the remote rpcbind could not be contacted.
+.It Fn rpcb_getaddr
+An interface to the rpcbind
+service, which finds the address of the service on
+.Fa host
+that is registered with program number
+.Fa prognum ,
+version
+.Fa versnum ,
+and speaks the transport protocol associated with
+.Fa netconf .
+The address found is returned in
+.Fa svcaddr .
+The
+.Fa svcaddr
+argument
+should be preallocated.
+This routine returns
+.Dv TRUE
+if it succeeds.
+A return value of
+.Dv FALSE
+means that the mapping does not exist
+or that the RPC
+system failed to contact the remote
+rpcbind service.
+In the latter case, the global variable
+.Va rpc_createerr
+(see
+.Xr rpc_clnt_create 3 )
+contains the
+RPC status.
+.It Fn rpcb_gettime
+This routine returns the time on
+.Fa host
+in
+.Fa timep .
+If
+.Fa host
+is
+.Dv NULL ,
+.Fn rpcb_gettime
+returns the time on its own machine.
+This routine returns
+.Dv TRUE
+if it succeeds,
+.Dv FALSE
+if it fails.
+The
+.Fn rpcb_gettime
+function
+can be used to synchronize the time between the
+client and the remote server.
+.It Fn rpcb_rmtcall
+An interface to the rpcbind service, which instructs
+rpcbind on
+.Fa host
+to make an RPC
+call on your behalf to a procedure on that host.
+The
+.Fn netconfig
+structure should correspond to a connectionless transport.
+The
+.Fa svcaddr
+argument
+will be modified to the server's address if the procedure succeeds
+(see
+.Fn rpc_call
+and
+.Fn clnt_call
+in
+.Xr rpc_clnt_calls 3
+for the definitions of other arguments).
+.Pp
+This procedure should normally be used for a
+.Dq ping
+and nothing else.
+This routine allows programs to do lookup and call, all in one step.
+.Pp
+Note: Even if the server is not running
+.Fn rpcb_rmtcall
+does not return any error messages to the caller.
+In such a case, the caller times out.
+.Pp
+Note:
+.Fn rpcb_rmtcall
+is only available for connectionless transports.
+.It Fn rpcb_set
+An interface to the rpcbind
+service, which establishes a mapping between the triple
+.Bq Fa prognum , versnum , netconf->nc_netid
+and
+.Fa svcaddr
+on the machine's rpcbind
+service.
+The value of
+.Fa nc_netid
+must correspond to a network identifier that is defined by the
+netconfig database.
+This routine returns
+.Dv TRUE
+if it succeeds,
+.Dv FALSE
+otherwise.
+(See also
+.Fn svc_reg
+in
+.Xr rpc_svc_calls 3 . )
+If there already exists such an entry with rpcbind,
+.Fn rpcb_set
+will fail.
+.It Fn rpcb_unset
+An interface to the rpcbind
+service, which destroys the mapping between the triple
+.Bq Fa prognum , versnum , netconf->nc_netid
+and the address on the machine's rpcbind
+service.
+If
+.Fa netconf
+is
+.Dv NULL ,
+.Fn rpcb_unset
+destroys all mapping between the triple
+.Bq Fa prognum , versnum , No all-transports
+and the addresses on the machine's rpcbind service.
+This routine returns
+.Dv TRUE
+if it succeeds,
+.Dv FALSE
+otherwise.
+Only the owner of the service or the super-user can destroy the mapping.
+(See also
+.Fn svc_unreg
+in
+.Xr rpc_svc_calls 3 . )
+.El
+.Sh SEE ALSO
+.Xr rpc_clnt_calls 3 ,
+.Xr rpc_svc_calls 3 ,
+.Xr rpcbind 8 ,
+.Xr rpcinfo 8
diff --git a/lib/libc/rpc/rpcdname.c b/lib/libc/rpc/rpcdname.c
new file mode 100644
index 0000000..d4455f4
--- /dev/null
+++ b/lib/libc/rpc/rpcdname.c
@@ -0,0 +1,82 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rpcdname.c 1.7 91/03/11 Copyr 1989 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * rpcdname.c
+ * Gets the default domain name
+ */
+
+#include "namespace.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include "un-namespace.h"
+
+static char *default_domain = 0;
+
+static char *
+get_default_domain()
+{
+ char temp[256];
+
+ if (default_domain)
+ return (default_domain);
+ if (getdomainname(temp, sizeof(temp)) < 0)
+ return (0);
+ if ((int) strlen(temp) > 0) {
+ default_domain = (char *)malloc((strlen(temp)+(unsigned)1));
+ if (default_domain == 0)
+ return (0);
+ (void) strcpy(default_domain, temp);
+ return (default_domain);
+ }
+ return (0);
+}
+
+/*
+ * This is a wrapper for the system call getdomainname which returns a
+ * ypclnt.h error code in the failure case. It also checks to see that
+ * the domain name is non-null, knowing that the null string is going to
+ * get rejected elsewhere in the NIS client package.
+ */
+int
+__rpc_get_default_domain(domain)
+ char **domain;
+{
+ if ((*domain = get_default_domain()) != 0)
+ return (0);
+ return (-1);
+}
diff --git a/lib/libc/rpc/rpcsec_gss_stub.c b/lib/libc/rpc/rpcsec_gss_stub.c
new file mode 100644
index 0000000..55eb106
--- /dev/null
+++ b/lib/libc/rpc/rpcsec_gss_stub.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 2006 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <rpc/rpc.h>
+#include <rpc/rpcsec_gss.h>
+
+bool_t
+__rpc_gss_wrap_stub(AUTH *auth, void *header, size_t headerlen, XDR* xdrs,
+ xdrproc_t xdr_args, void *args_ptr)
+{
+
+ return (FALSE);
+}
+
+bool_t
+__rpc_gss_unwrap_stub(AUTH *auth, XDR* xdrs, xdrproc_t xdr_args, void *args_ptr)
+{
+
+ return (FALSE);
+}
+
+__weak_reference(__rpc_gss_wrap_stub, __rpc_gss_wrap);
+__weak_reference(__rpc_gss_unwrap_stub, __rpc_gss_unwrap);
diff --git a/lib/libc/rpc/rtime.3 b/lib/libc/rpc/rtime.3
new file mode 100644
index 0000000..028d2be
--- /dev/null
+++ b/lib/libc/rpc/rtime.3
@@ -0,0 +1,50 @@
+.\" @(#)rtime.3n 2.1 88/08/08 4.0 RPCSRC; from 1.5 88/02/08 SMI
+.\" $FreeBSD$
+.\"
+.Dd November 22, 1987
+.Dt RTIME 3
+.Os
+.Sh NAME
+.Nm rtime
+.Nd "get remote time"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/types.h
+.In sys/time.h
+.In netinet/in.h
+.Ft int
+.Fo rtime
+.Fa "struct sockaddr_in *addrp"
+.Fa "struct timeval *timep"
+.Fa "struct timeval *timeout"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn rtime
+function
+consults the Internet Time Server at the address pointed to by
+.Fa addrp
+and returns the remote time in the
+.Vt timeval
+struct pointed to by
+.Fa timep .
+Normally, the
+.Tn UDP
+protocol is used when consulting the Time Server.
+The
+.Fa timeout
+argument specifies how long the
+routine should wait before giving
+up when waiting for a reply.
+If
+.Fa timeout
+is specified as
+.Dv NULL ,
+however, the routine will instead use
+.Tn TCP
+and block until a reply is received from the time server.
+.Sh RETURN VALUES
+.Rv -std rtime
+.Sh SEE ALSO
+.Xr timed 8
diff --git a/lib/libc/rpc/rtime.c b/lib/libc/rpc/rtime.c
new file mode 100644
index 0000000..39ac19b
--- /dev/null
+++ b/lib/libc/rpc/rtime.c
@@ -0,0 +1,160 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+
+ */
+
+/*
+ * rtime - get time from remote machine
+ *
+ * gets time, obtaining value from host
+ * on the udp/time socket. Since timeserver returns
+ * with time of day in seconds since Jan 1, 1900, must
+ * subtract seconds before Jan 1, 1970 to get
+ * what unix uses.
+ */
+#include "namespace.h"
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <netdb.h>
+#include "un-namespace.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rtime.c 2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+extern int _rpc_dtablesize( void );
+
+#define NYEARS (unsigned long)(1970 - 1900)
+#define TOFFSET (unsigned long)(60*60*24*(365*NYEARS + (NYEARS/4)))
+
+static void do_close( int );
+
+int
+rtime(addrp, timep, timeout)
+ struct sockaddr_in *addrp;
+ struct timeval *timep;
+ struct timeval *timeout;
+{
+ int s;
+ fd_set readfds;
+ int res;
+ unsigned long thetime;
+ struct sockaddr_in from;
+ socklen_t fromlen;
+ int type;
+ struct servent *serv;
+
+ if (timeout == NULL) {
+ type = SOCK_STREAM;
+ } else {
+ type = SOCK_DGRAM;
+ }
+ s = _socket(AF_INET, type, 0);
+ if (s < 0) {
+ return(-1);
+ }
+ addrp->sin_family = AF_INET;
+
+ /* TCP and UDP port are the same in this case */
+ if ((serv = getservbyname("time", "tcp")) == NULL) {
+ return(-1);
+ }
+
+ addrp->sin_port = serv->s_port;
+
+ if (type == SOCK_DGRAM) {
+ res = _sendto(s, (char *)&thetime, sizeof(thetime), 0,
+ (struct sockaddr *)addrp, sizeof(*addrp));
+ if (res < 0) {
+ do_close(s);
+ return(-1);
+ }
+ do {
+ FD_ZERO(&readfds);
+ FD_SET(s, &readfds);
+ res = _select(_rpc_dtablesize(), &readfds,
+ (fd_set *)NULL, (fd_set *)NULL, timeout);
+ } while (res < 0 && errno == EINTR);
+ if (res <= 0) {
+ if (res == 0) {
+ errno = ETIMEDOUT;
+ }
+ do_close(s);
+ return(-1);
+ }
+ fromlen = sizeof(from);
+ res = _recvfrom(s, (char *)&thetime, sizeof(thetime), 0,
+ (struct sockaddr *)&from, &fromlen);
+ do_close(s);
+ if (res < 0) {
+ return(-1);
+ }
+ } else {
+ if (_connect(s, (struct sockaddr *)addrp, sizeof(*addrp)) < 0) {
+ do_close(s);
+ return(-1);
+ }
+ res = _read(s, (char *)&thetime, sizeof(thetime));
+ do_close(s);
+ if (res < 0) {
+ return(-1);
+ }
+ }
+ if (res != sizeof(thetime)) {
+ errno = EIO;
+ return(-1);
+ }
+ thetime = ntohl(thetime);
+ timep->tv_sec = thetime - TOFFSET;
+ timep->tv_usec = 0;
+ return(0);
+}
+
+static void
+do_close(s)
+ int s;
+{
+ int save;
+
+ save = errno;
+ (void)_close(s);
+ errno = save;
+}
diff --git a/lib/libc/rpc/svc.c b/lib/libc/rpc/svc.c
new file mode 100644
index 0000000..282c2be
--- /dev/null
+++ b/lib/libc/rpc/svc.c
@@ -0,0 +1,789 @@
+/* $NetBSD: svc.c,v 1.21 2000/07/06 03:10:35 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)svc.c 2.4 88/08/11 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc.c, Server-side remote procedure call interface.
+ *
+ * There are two sets of procedures here. The xprt routines are
+ * for handling transport handles. The svc routines handle the
+ * list of service routines.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/poll.h>
+#include <assert.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rpc/rpc.h>
+#ifdef PORTMAP
+#include <rpc/pmap_clnt.h>
+#endif /* PORTMAP */
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+#define RQCRED_SIZE 400 /* this size is excessive */
+
+#define SVC_VERSQUIET 0x0001 /* keep quiet about vers mismatch */
+#define version_keepquiet(xp) (SVC_EXT(xp)->xp_flags & SVC_VERSQUIET)
+
+#define max(a, b) (a > b ? a : b)
+
+/*
+ * The services list
+ * Each entry represents a set of procedures (an rpc program).
+ * The dispatch routine takes request structs and runs the
+ * apropriate procedure.
+ */
+static struct svc_callout {
+ struct svc_callout *sc_next;
+ rpcprog_t sc_prog;
+ rpcvers_t sc_vers;
+ char *sc_netid;
+ void (*sc_dispatch)(struct svc_req *, SVCXPRT *);
+} *svc_head;
+
+static struct svc_callout *svc_find(rpcprog_t, rpcvers_t,
+ struct svc_callout **, char *);
+static void __xprt_do_unregister (SVCXPRT *xprt, bool_t dolock);
+
+/* *************** SVCXPRT related stuff **************** */
+
+/*
+ * Activate a transport handle.
+ */
+void
+xprt_register(xprt)
+ SVCXPRT *xprt;
+{
+ int sock;
+
+ assert(xprt != NULL);
+
+ sock = xprt->xp_fd;
+
+ rwlock_wrlock(&svc_fd_lock);
+ if (__svc_xports == NULL) {
+ __svc_xports = (SVCXPRT **)
+ mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *));
+ if (__svc_xports == NULL)
+ return;
+ memset(__svc_xports, '\0', FD_SETSIZE * sizeof(SVCXPRT *));
+ }
+ if (sock < FD_SETSIZE) {
+ __svc_xports[sock] = xprt;
+ FD_SET(sock, &svc_fdset);
+ svc_maxfd = max(svc_maxfd, sock);
+ }
+ rwlock_unlock(&svc_fd_lock);
+}
+
+void
+xprt_unregister(SVCXPRT *xprt)
+{
+ __xprt_do_unregister(xprt, TRUE);
+}
+
+void
+__xprt_unregister_unlocked(SVCXPRT *xprt)
+{
+ __xprt_do_unregister(xprt, FALSE);
+}
+
+/*
+ * De-activate a transport handle.
+ */
+static void
+__xprt_do_unregister(xprt, dolock)
+ SVCXPRT *xprt;
+ bool_t dolock;
+{
+ int sock;
+
+ assert(xprt != NULL);
+
+ sock = xprt->xp_fd;
+
+ if (dolock)
+ rwlock_wrlock(&svc_fd_lock);
+ if ((sock < FD_SETSIZE) && (__svc_xports[sock] == xprt)) {
+ __svc_xports[sock] = NULL;
+ FD_CLR(sock, &svc_fdset);
+ if (sock >= svc_maxfd) {
+ for (svc_maxfd--; svc_maxfd>=0; svc_maxfd--)
+ if (__svc_xports[svc_maxfd])
+ break;
+ }
+ }
+ if (dolock)
+ rwlock_unlock(&svc_fd_lock);
+}
+
+/*
+ * Add a service program to the callout list.
+ * The dispatch routine will be called when a rpc request for this
+ * program number comes in.
+ */
+bool_t
+svc_reg(xprt, prog, vers, dispatch, nconf)
+ SVCXPRT *xprt;
+ const rpcprog_t prog;
+ const rpcvers_t vers;
+ void (*dispatch)(struct svc_req *, SVCXPRT *);
+ const struct netconfig *nconf;
+{
+ bool_t dummy;
+ struct svc_callout *prev;
+ struct svc_callout *s;
+ struct netconfig *tnconf;
+ char *netid = NULL;
+ int flag = 0;
+
+/* VARIABLES PROTECTED BY svc_lock: s, prev, svc_head */
+
+ if (xprt->xp_netid) {
+ netid = strdup(xprt->xp_netid);
+ flag = 1;
+ } else if (nconf && nconf->nc_netid) {
+ netid = strdup(nconf->nc_netid);
+ flag = 1;
+ } else if ((tnconf = __rpcgettp(xprt->xp_fd)) != NULL) {
+ netid = strdup(tnconf->nc_netid);
+ flag = 1;
+ freenetconfigent(tnconf);
+ } /* must have been created with svc_raw_create */
+ if ((netid == NULL) && (flag == 1)) {
+ return (FALSE);
+ }
+
+ rwlock_wrlock(&svc_lock);
+ if ((s = svc_find(prog, vers, &prev, netid)) != NULL) {
+ if (netid)
+ free(netid);
+ if (s->sc_dispatch == dispatch)
+ goto rpcb_it; /* he is registering another xptr */
+ rwlock_unlock(&svc_lock);
+ return (FALSE);
+ }
+ s = mem_alloc(sizeof (struct svc_callout));
+ if (s == NULL) {
+ if (netid)
+ free(netid);
+ rwlock_unlock(&svc_lock);
+ return (FALSE);
+ }
+
+ s->sc_prog = prog;
+ s->sc_vers = vers;
+ s->sc_dispatch = dispatch;
+ s->sc_netid = netid;
+ s->sc_next = svc_head;
+ svc_head = s;
+
+ if ((xprt->xp_netid == NULL) && (flag == 1) && netid)
+ ((SVCXPRT *) xprt)->xp_netid = strdup(netid);
+
+rpcb_it:
+ rwlock_unlock(&svc_lock);
+ /* now register the information with the local binder service */
+ if (nconf) {
+ /*LINTED const castaway*/
+ dummy = rpcb_set(prog, vers, (struct netconfig *) nconf,
+ &((SVCXPRT *) xprt)->xp_ltaddr);
+ return (dummy);
+ }
+ return (TRUE);
+}
+
+/*
+ * Remove a service program from the callout list.
+ */
+void
+svc_unreg(prog, vers)
+ const rpcprog_t prog;
+ const rpcvers_t vers;
+{
+ struct svc_callout *prev;
+ struct svc_callout *s;
+
+ /* unregister the information anyway */
+ (void) rpcb_unset(prog, vers, NULL);
+ rwlock_wrlock(&svc_lock);
+ while ((s = svc_find(prog, vers, &prev, NULL)) != NULL) {
+ if (prev == NULL) {
+ svc_head = s->sc_next;
+ } else {
+ prev->sc_next = s->sc_next;
+ }
+ s->sc_next = NULL;
+ if (s->sc_netid)
+ mem_free(s->sc_netid, sizeof (s->sc_netid) + 1);
+ mem_free(s, sizeof (struct svc_callout));
+ }
+ rwlock_unlock(&svc_lock);
+}
+
+/* ********************** CALLOUT list related stuff ************* */
+
+#ifdef PORTMAP
+/*
+ * Add a service program to the callout list.
+ * The dispatch routine will be called when a rpc request for this
+ * program number comes in.
+ */
+bool_t
+svc_register(xprt, prog, vers, dispatch, protocol)
+ SVCXPRT *xprt;
+ u_long prog;
+ u_long vers;
+ void (*dispatch)(struct svc_req *, SVCXPRT *);
+ int protocol;
+{
+ struct svc_callout *prev;
+ struct svc_callout *s;
+
+ assert(xprt != NULL);
+ assert(dispatch != NULL);
+
+ if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) !=
+ NULL) {
+ if (s->sc_dispatch == dispatch)
+ goto pmap_it; /* he is registering another xptr */
+ return (FALSE);
+ }
+ s = mem_alloc(sizeof(struct svc_callout));
+ if (s == NULL) {
+ return (FALSE);
+ }
+ s->sc_prog = (rpcprog_t)prog;
+ s->sc_vers = (rpcvers_t)vers;
+ s->sc_dispatch = dispatch;
+ s->sc_next = svc_head;
+ svc_head = s;
+pmap_it:
+ /* now register the information with the local binder service */
+ if (protocol) {
+ return (pmap_set(prog, vers, protocol, xprt->xp_port));
+ }
+ return (TRUE);
+}
+
+/*
+ * Remove a service program from the callout list.
+ */
+void
+svc_unregister(prog, vers)
+ u_long prog;
+ u_long vers;
+{
+ struct svc_callout *prev;
+ struct svc_callout *s;
+
+ if ((s = svc_find((rpcprog_t)prog, (rpcvers_t)vers, &prev, NULL)) ==
+ NULL)
+ return;
+ if (prev == NULL) {
+ svc_head = s->sc_next;
+ } else {
+ prev->sc_next = s->sc_next;
+ }
+ s->sc_next = NULL;
+ mem_free(s, sizeof(struct svc_callout));
+ /* now unregister the information with the local binder service */
+ (void)pmap_unset(prog, vers);
+}
+#endif /* PORTMAP */
+
+/*
+ * Search the callout list for a program number, return the callout
+ * struct.
+ */
+static struct svc_callout *
+svc_find(prog, vers, prev, netid)
+ rpcprog_t prog;
+ rpcvers_t vers;
+ struct svc_callout **prev;
+ char *netid;
+{
+ struct svc_callout *s, *p;
+
+ assert(prev != NULL);
+
+ p = NULL;
+ for (s = svc_head; s != NULL; s = s->sc_next) {
+ if (((s->sc_prog == prog) && (s->sc_vers == vers)) &&
+ ((netid == NULL) || (s->sc_netid == NULL) ||
+ (strcmp(netid, s->sc_netid) == 0)))
+ break;
+ p = s;
+ }
+ *prev = p;
+ return (s);
+}
+
+/* ******************* REPLY GENERATION ROUTINES ************ */
+
+/*
+ * Send a reply to an rpc request
+ */
+bool_t
+svc_sendreply(xprt, xdr_results, xdr_location)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_results;
+ void * xdr_location;
+{
+ struct rpc_msg rply;
+
+ assert(xprt != NULL);
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = SUCCESS;
+ rply.acpted_rply.ar_results.where = xdr_location;
+ rply.acpted_rply.ar_results.proc = xdr_results;
+ return (SVC_REPLY(xprt, &rply));
+}
+
+/*
+ * No procedure error reply
+ */
+void
+svcerr_noproc(xprt)
+ SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ assert(xprt != NULL);
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = PROC_UNAVAIL;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Can't decode args error reply
+ */
+void
+svcerr_decode(xprt)
+ SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ assert(xprt != NULL);
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = GARBAGE_ARGS;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Some system error
+ */
+void
+svcerr_systemerr(xprt)
+ SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ assert(xprt != NULL);
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = SYSTEM_ERR;
+ SVC_REPLY(xprt, &rply);
+}
+
+#if 0
+/*
+ * Tell RPC package to not complain about version errors to the client. This
+ * is useful when revving broadcast protocols that sit on a fixed address.
+ * There is really one (or should be only one) example of this kind of
+ * protocol: the portmapper (or rpc binder).
+ */
+void
+__svc_versquiet_on(xprt)
+ SVCXPRT *xprt;
+{
+
+ SVC_EXT(xprt)->xp_flags |= SVC_VERSQUIET;
+}
+
+void
+__svc_versquiet_off(xprt)
+ SVCXPRT *xprt;
+{
+
+ SVC_EXT(xprt)->xp_flags &= ~SVC_VERSQUIET;
+}
+
+void
+svc_versquiet(xprt)
+ SVCXPRT *xprt;
+{
+ __svc_versquiet_on(xprt);
+}
+
+int
+__svc_versquiet_get(xprt)
+ SVCXPRT *xprt;
+{
+
+ return (SVC_EXT(xprt)->xp_flags & SVC_VERSQUIET);
+}
+#endif
+
+/*
+ * Authentication error reply
+ */
+void
+svcerr_auth(xprt, why)
+ SVCXPRT *xprt;
+ enum auth_stat why;
+{
+ struct rpc_msg rply;
+
+ assert(xprt != NULL);
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_DENIED;
+ rply.rjcted_rply.rj_stat = AUTH_ERROR;
+ rply.rjcted_rply.rj_why = why;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Auth too weak error reply
+ */
+void
+svcerr_weakauth(xprt)
+ SVCXPRT *xprt;
+{
+
+ assert(xprt != NULL);
+
+ svcerr_auth(xprt, AUTH_TOOWEAK);
+}
+
+/*
+ * Program unavailable error reply
+ */
+void
+svcerr_noprog(xprt)
+ SVCXPRT *xprt;
+{
+ struct rpc_msg rply;
+
+ assert(xprt != NULL);
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = PROG_UNAVAIL;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Program version mismatch error reply
+ */
+void
+svcerr_progvers(xprt, low_vers, high_vers)
+ SVCXPRT *xprt;
+ rpcvers_t low_vers;
+ rpcvers_t high_vers;
+{
+ struct rpc_msg rply;
+
+ assert(xprt != NULL);
+
+ rply.rm_direction = REPLY;
+ rply.rm_reply.rp_stat = MSG_ACCEPTED;
+ rply.acpted_rply.ar_verf = xprt->xp_verf;
+ rply.acpted_rply.ar_stat = PROG_MISMATCH;
+ rply.acpted_rply.ar_vers.low = (u_int32_t)low_vers;
+ rply.acpted_rply.ar_vers.high = (u_int32_t)high_vers;
+ SVC_REPLY(xprt, &rply);
+}
+
+/*
+ * Allocate a new server transport structure. All fields are
+ * initialized to zero and xp_p3 is initialized to point at an
+ * extension structure to hold various flags and authentication
+ * parameters.
+ */
+SVCXPRT *
+svc_xprt_alloc()
+{
+ SVCXPRT *xprt;
+ SVCXPRT_EXT *ext;
+
+ xprt = mem_alloc(sizeof(SVCXPRT));
+ memset(xprt, 0, sizeof(SVCXPRT));
+ ext = mem_alloc(sizeof(SVCXPRT_EXT));
+ memset(ext, 0, sizeof(SVCXPRT_EXT));
+ xprt->xp_p3 = ext;
+ ext->xp_auth.svc_ah_ops = &svc_auth_null_ops;
+
+ return (xprt);
+}
+
+/*
+ * Free a server transport structure.
+ */
+void
+svc_xprt_free(xprt)
+ SVCXPRT *xprt;
+{
+
+ mem_free(xprt->xp_p3, sizeof(SVCXPRT_EXT));
+ mem_free(xprt, sizeof(SVCXPRT));
+}
+
+/* ******************* SERVER INPUT STUFF ******************* */
+
+/*
+ * Get server side input from some transport.
+ *
+ * Statement of authentication parameters management:
+ * This function owns and manages all authentication parameters, specifically
+ * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and
+ * the "cooked" credentials (rqst->rq_clntcred).
+ * However, this function does not know the structure of the cooked
+ * credentials, so it make the following assumptions:
+ * a) the structure is contiguous (no pointers), and
+ * b) the cred structure size does not exceed RQCRED_SIZE bytes.
+ * In all events, all three parameters are freed upon exit from this routine.
+ * The storage is trivially management on the call stack in user land, but
+ * is mallocated in kernel land.
+ */
+
+void
+svc_getreq(rdfds)
+ int rdfds;
+{
+ fd_set readfds;
+
+ FD_ZERO(&readfds);
+ readfds.fds_bits[0] = rdfds;
+ svc_getreqset(&readfds);
+}
+
+void
+svc_getreqset(readfds)
+ fd_set *readfds;
+{
+ int bit, fd;
+ fd_mask mask, *maskp;
+ int sock;
+
+ assert(readfds != NULL);
+
+ maskp = readfds->fds_bits;
+ for (sock = 0; sock < FD_SETSIZE; sock += NFDBITS) {
+ for (mask = *maskp++; (bit = ffsl(mask)) != 0;
+ mask ^= (1ul << (bit - 1))) {
+ /* sock has input waiting */
+ fd = sock + bit - 1;
+ svc_getreq_common(fd);
+ }
+ }
+}
+
+void
+svc_getreq_common(fd)
+ int fd;
+{
+ SVCXPRT *xprt;
+ struct svc_req r;
+ struct rpc_msg msg;
+ int prog_found;
+ rpcvers_t low_vers;
+ rpcvers_t high_vers;
+ enum xprt_stat stat;
+ char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];
+
+ msg.rm_call.cb_cred.oa_base = cred_area;
+ msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);
+ r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]);
+
+ rwlock_rdlock(&svc_fd_lock);
+ xprt = __svc_xports[fd];
+ rwlock_unlock(&svc_fd_lock);
+ if (xprt == NULL)
+ /* But do we control sock? */
+ return;
+ /* now receive msgs from xprtprt (support batch calls) */
+ do {
+ if (SVC_RECV(xprt, &msg)) {
+
+ /* now find the exported program and call it */
+ struct svc_callout *s;
+ enum auth_stat why;
+
+ r.rq_xprt = xprt;
+ r.rq_prog = msg.rm_call.cb_prog;
+ r.rq_vers = msg.rm_call.cb_vers;
+ r.rq_proc = msg.rm_call.cb_proc;
+ r.rq_cred = msg.rm_call.cb_cred;
+ /* first authenticate the message */
+ if ((why = _authenticate(&r, &msg)) != AUTH_OK) {
+ /*
+ * RPCSEC_GSS uses this return code
+ * for requests that form part of its
+ * context establishment protocol and
+ * should not be dispatched to the
+ * application.
+ */
+ if (why != RPCSEC_GSS_NODISPATCH)
+ svcerr_auth(xprt, why);
+ goto call_done;
+ }
+ /* now match message with a registered service*/
+ prog_found = FALSE;
+ low_vers = (rpcvers_t) -1L;
+ high_vers = (rpcvers_t) 0L;
+ for (s = svc_head; s != NULL; s = s->sc_next) {
+ if (s->sc_prog == r.rq_prog) {
+ if (s->sc_vers == r.rq_vers) {
+ (*s->sc_dispatch)(&r, xprt);
+ goto call_done;
+ } /* found correct version */
+ prog_found = TRUE;
+ if (s->sc_vers < low_vers)
+ low_vers = s->sc_vers;
+ if (s->sc_vers > high_vers)
+ high_vers = s->sc_vers;
+ } /* found correct program */
+ }
+ /*
+ * if we got here, the program or version
+ * is not served ...
+ */
+ if (prog_found)
+ svcerr_progvers(xprt, low_vers, high_vers);
+ else
+ svcerr_noprog(xprt);
+ /* Fall through to ... */
+ }
+ /*
+ * Check if the xprt has been disconnected in a
+ * recursive call in the service dispatch routine.
+ * If so, then break.
+ */
+ rwlock_rdlock(&svc_fd_lock);
+ if (xprt != __svc_xports[fd]) {
+ rwlock_unlock(&svc_fd_lock);
+ break;
+ }
+ rwlock_unlock(&svc_fd_lock);
+call_done:
+ if ((stat = SVC_STAT(xprt)) == XPRT_DIED){
+ SVC_DESTROY(xprt);
+ break;
+ }
+ } while (stat == XPRT_MOREREQS);
+}
+
+
+void
+svc_getreq_poll(pfdp, pollretval)
+ struct pollfd *pfdp;
+ int pollretval;
+{
+ int i;
+ int fds_found;
+
+ for (i = fds_found = 0; fds_found < pollretval; i++) {
+ struct pollfd *p = &pfdp[i];
+
+ if (p->revents) {
+ /* fd has input waiting */
+ fds_found++;
+ /*
+ * We assume that this function is only called
+ * via someone _select()ing from svc_fdset or
+ * _poll()ing from svc_pollset[]. Thus it's safe
+ * to handle the POLLNVAL event by simply turning
+ * the corresponding bit off in svc_fdset. The
+ * svc_pollset[] array is derived from svc_fdset
+ * and so will also be updated eventually.
+ *
+ * XXX Should we do an xprt_unregister() instead?
+ */
+ if (p->revents & POLLNVAL) {
+ rwlock_wrlock(&svc_fd_lock);
+ FD_CLR(p->fd, &svc_fdset);
+ rwlock_unlock(&svc_fd_lock);
+ } else
+ svc_getreq_common(p->fd);
+ }
+ }
+}
+
+bool_t
+rpc_control(int what, void *arg)
+{
+ int val;
+
+ switch (what) {
+ case RPC_SVC_CONNMAXREC_SET:
+ val = *(int *)arg;
+ if (val <= 0)
+ return FALSE;
+ __svc_maxrec = val;
+ return TRUE;
+ case RPC_SVC_CONNMAXREC_GET:
+ *(int *)arg = __svc_maxrec;
+ return TRUE;
+ default:
+ break;
+ }
+ return FALSE;
+}
diff --git a/lib/libc/rpc/svc_auth.c b/lib/libc/rpc/svc_auth.c
new file mode 100644
index 0000000..b3894e6
--- /dev/null
+++ b/lib/libc/rpc/svc_auth.c
@@ -0,0 +1,234 @@
+/* $NetBSD: svc_auth.c,v 1.12 2000/07/06 03:10:35 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#ident "@(#)svc_auth.c 1.16 94/04/24 SMI"
+static char sccsid[] = "@(#)svc_auth.c 1.26 89/02/07 Copyr 1984 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc_auth.c, Server-side rpc authenticator interface.
+ *
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+/*
+ * svcauthsw is the bdevsw of server side authentication.
+ *
+ * Server side authenticators are called from authenticate by
+ * using the client auth struct flavor field to index into svcauthsw.
+ * The server auth flavors must implement a routine that looks
+ * like:
+ *
+ * enum auth_stat
+ * flavorx_auth(rqst, msg)
+ * struct svc_req *rqst;
+ * struct rpc_msg *msg;
+ *
+ */
+
+/* declarations to allow servers to specify new authentication flavors */
+struct authsvc {
+ int flavor;
+ enum auth_stat (*handler)(struct svc_req *, struct rpc_msg *);
+ struct authsvc *next;
+};
+static struct authsvc *Auths = NULL;
+
+struct svc_auth_ops svc_auth_null_ops;
+
+/*
+ * The call rpc message, msg has been obtained from the wire. The msg contains
+ * the raw form of credentials and verifiers. authenticate returns AUTH_OK
+ * if the msg is successfully authenticated. If AUTH_OK then the routine also
+ * does the following things:
+ * set rqst->rq_xprt->verf to the appropriate response verifier;
+ * sets rqst->rq_client_cred to the "cooked" form of the credentials.
+ *
+ * NB: rqst->rq_cxprt->verf must be pre-alloctaed;
+ * its length is set appropriately.
+ *
+ * The caller still owns and is responsible for msg->u.cmb.cred and
+ * msg->u.cmb.verf. The authentication system retains ownership of
+ * rqst->rq_client_cred, the cooked credentials.
+ *
+ * There is an assumption that any flavour less than AUTH_NULL is
+ * invalid.
+ */
+enum auth_stat
+_authenticate(rqst, msg)
+ struct svc_req *rqst;
+ struct rpc_msg *msg;
+{
+ int cred_flavor;
+ struct authsvc *asp;
+ enum auth_stat dummy;
+
+/* VARIABLES PROTECTED BY authsvc_lock: asp, Auths */
+
+ rqst->rq_cred = msg->rm_call.cb_cred;
+ SVC_AUTH(rqst->rq_xprt).svc_ah_ops = &svc_auth_null_ops;
+ SVC_AUTH(rqst->rq_xprt).svc_ah_private = NULL;
+ rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
+ rqst->rq_xprt->xp_verf.oa_length = 0;
+ cred_flavor = rqst->rq_cred.oa_flavor;
+ switch (cred_flavor) {
+ case AUTH_NULL:
+ dummy = _svcauth_null(rqst, msg);
+ return (dummy);
+ case AUTH_SYS:
+ dummy = _svcauth_unix(rqst, msg);
+ return (dummy);
+ case AUTH_SHORT:
+ dummy = _svcauth_short(rqst, msg);
+ return (dummy);
+#ifdef DES_BUILTIN
+ case AUTH_DES:
+ dummy = _svcauth_des(rqst, msg);
+ return (dummy);
+#endif
+ default:
+ break;
+ }
+
+ /* flavor doesn't match any of the builtin types, so try new ones */
+ mutex_lock(&authsvc_lock);
+ for (asp = Auths; asp; asp = asp->next) {
+ if (asp->flavor == cred_flavor) {
+ enum auth_stat as;
+
+ as = (*asp->handler)(rqst, msg);
+ mutex_unlock(&authsvc_lock);
+ return (as);
+ }
+ }
+ mutex_unlock(&authsvc_lock);
+
+ return (AUTH_REJECTEDCRED);
+}
+
+/*
+ * A set of null auth methods used by any authentication protocols
+ * that don't need to inspect or modify the message body.
+ */
+static bool_t
+svcauth_null_wrap(auth, xdrs, xdr_func, xdr_ptr)
+ SVCAUTH *auth;
+ XDR *xdrs;
+ xdrproc_t xdr_func;
+ caddr_t xdr_ptr;
+{
+
+ return (xdr_func(xdrs, xdr_ptr));
+}
+
+struct svc_auth_ops svc_auth_null_ops = {
+ svcauth_null_wrap,
+ svcauth_null_wrap,
+};
+
+/*ARGSUSED*/
+enum auth_stat
+_svcauth_null(rqst, msg)
+ struct svc_req *rqst;
+ struct rpc_msg *msg;
+{
+ return (AUTH_OK);
+}
+
+/*
+ * Allow the rpc service to register new authentication types that it is
+ * prepared to handle. When an authentication flavor is registered,
+ * the flavor is checked against already registered values. If not
+ * registered, then a new Auths entry is added on the list.
+ *
+ * There is no provision to delete a registration once registered.
+ *
+ * This routine returns:
+ * 0 if registration successful
+ * 1 if flavor already registered
+ * -1 if can't register (errno set)
+ */
+
+int
+svc_auth_reg(cred_flavor, handler)
+ int cred_flavor;
+ enum auth_stat (*handler)(struct svc_req *, struct rpc_msg *);
+{
+ struct authsvc *asp;
+
+ switch (cred_flavor) {
+ case AUTH_NULL:
+ case AUTH_SYS:
+ case AUTH_SHORT:
+#ifdef DES_BUILTIN
+ case AUTH_DES:
+#endif
+ /* already registered */
+ return (1);
+
+ default:
+ mutex_lock(&authsvc_lock);
+ for (asp = Auths; asp; asp = asp->next) {
+ if (asp->flavor == cred_flavor) {
+ /* already registered */
+ mutex_unlock(&authsvc_lock);
+ return (1);
+ }
+ }
+
+ /* this is a new one, so go ahead and register it */
+ asp = mem_alloc(sizeof (*asp));
+ if (asp == NULL) {
+ mutex_unlock(&authsvc_lock);
+ return (-1);
+ }
+ asp->flavor = cred_flavor;
+ asp->handler = handler;
+ asp->next = Auths;
+ Auths = asp;
+ mutex_unlock(&authsvc_lock);
+ break;
+ }
+ return (0);
+}
diff --git a/lib/libc/rpc/svc_auth_des.c b/lib/libc/rpc/svc_auth_des.c
new file mode 100644
index 0000000..de4d1b4
--- /dev/null
+++ b/lib/libc/rpc/svc_auth_des.c
@@ -0,0 +1,538 @@
+
+/*
+ * Copyright (c) 1988 by Sun Microsystems, Inc.
+ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * svcauth_des.c, server-side des authentication
+ *
+ * We insure for the service the following:
+ * (1) The timestamp microseconds do not exceed 1 million.
+ * (2) The timestamp plus the window is less than the current time.
+ * (3) The timestamp is not less than the one previously
+ * seen in the current session.
+ *
+ * It is up to the server to determine if the window size is
+ * too small .
+ *
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <rpc/des_crypt.h>
+#include <sys/param.h>
+#include <netinet/in.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/auth_des.h>
+#include <rpc/svc.h>
+#include <rpc/rpc_msg.h>
+#include <rpc/svc_auth.h>
+#include "libc_private.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)svcauth_des.c 2.3 89/07/11 4.0 RPCSRC; from 1.15 88/02/08 SMI";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+extern int key_decryptsession_pk(const char *, netobj *, des_block *);
+
+#define debug(msg) printf("svcauth_des: %s\n", msg)
+
+#define USEC_PER_SEC ((u_long) 1000000L)
+#define BEFORE(t1, t2) timercmp(t1, t2, <)
+
+/*
+ * LRU cache of conversation keys and some other useful items.
+ */
+#define AUTHDES_CACHESZ 64
+struct cache_entry {
+ des_block key; /* conversation key */
+ char *rname; /* client's name */
+ u_int window; /* credential lifetime window */
+ struct timeval laststamp; /* detect replays of creds */
+ char *localcred; /* generic local credential */
+};
+static struct cache_entry *authdes_cache/* [AUTHDES_CACHESZ] */;
+static short *authdes_lru/* [AUTHDES_CACHESZ] */;
+
+static void cache_init(); /* initialize the cache */
+static short cache_spot(); /* find an entry in the cache */
+static void cache_ref(/*short sid*/); /* note that sid was ref'd */
+
+static void invalidate(); /* invalidate entry in cache */
+
+/*
+ * cache statistics
+ */
+static struct {
+ u_long ncachehits; /* times cache hit, and is not replay */
+ u_long ncachereplays; /* times cache hit, and is replay */
+ u_long ncachemisses; /* times cache missed */
+} svcauthdes_stats;
+
+/*
+ * Service side authenticator for AUTH_DES
+ */
+enum auth_stat
+_svcauth_des(rqst, msg)
+ struct svc_req *rqst;
+ struct rpc_msg *msg;
+{
+
+ long *ixdr;
+ des_block cryptbuf[2];
+ struct authdes_cred *cred;
+ struct authdes_verf verf;
+ int status;
+ struct cache_entry *entry;
+ short sid = 0;
+ des_block *sessionkey;
+ des_block ivec;
+ u_int window;
+ struct timeval timestamp;
+ u_long namelen;
+ struct area {
+ struct authdes_cred area_cred;
+ char area_netname[MAXNETNAMELEN+1];
+ } *area;
+
+ if (authdes_cache == NULL) {
+ cache_init();
+ }
+
+ area = (struct area *)rqst->rq_clntcred;
+ cred = (struct authdes_cred *)&area->area_cred;
+
+ /*
+ * Get the credential
+ */
+ ixdr = (long *)msg->rm_call.cb_cred.oa_base;
+ cred->adc_namekind = IXDR_GET_ENUM(ixdr, enum authdes_namekind);
+ switch (cred->adc_namekind) {
+ case ADN_FULLNAME:
+ namelen = IXDR_GET_U_LONG(ixdr);
+ if (namelen > MAXNETNAMELEN) {
+ return (AUTH_BADCRED);
+ }
+ cred->adc_fullname.name = area->area_netname;
+ bcopy((char *)ixdr, cred->adc_fullname.name,
+ (u_int)namelen);
+ cred->adc_fullname.name[namelen] = 0;
+ ixdr += (RNDUP(namelen) / BYTES_PER_XDR_UNIT);
+ cred->adc_fullname.key.key.high = (u_long)*ixdr++;
+ cred->adc_fullname.key.key.low = (u_long)*ixdr++;
+ cred->adc_fullname.window = (u_long)*ixdr++;
+ break;
+ case ADN_NICKNAME:
+ cred->adc_nickname = (u_long)*ixdr++;
+ break;
+ default:
+ return (AUTH_BADCRED);
+ }
+
+ /*
+ * Get the verifier
+ */
+ ixdr = (long *)msg->rm_call.cb_verf.oa_base;
+ verf.adv_xtimestamp.key.high = (u_long)*ixdr++;
+ verf.adv_xtimestamp.key.low = (u_long)*ixdr++;
+ verf.adv_int_u = (u_long)*ixdr++;
+
+
+ /*
+ * Get the conversation key
+ */
+ if (cred->adc_namekind == ADN_FULLNAME) {
+ netobj pkey;
+ char pkey_data[1024];
+
+ sessionkey = &cred->adc_fullname.key;
+ if (! getpublickey(cred->adc_fullname.name, pkey_data)) {
+ debug("getpublickey");
+ return(AUTH_BADCRED);
+ }
+ pkey.n_bytes = pkey_data;
+ pkey.n_len = strlen(pkey_data) + 1;
+ if (key_decryptsession_pk(cred->adc_fullname.name, &pkey,
+ sessionkey) < 0) {
+ debug("decryptsessionkey");
+ return (AUTH_BADCRED); /* key not found */
+ }
+ } else { /* ADN_NICKNAME */
+ sid = (short)cred->adc_nickname;
+ if (sid < 0 || sid >= AUTHDES_CACHESZ) {
+ debug("bad nickname");
+ return (AUTH_BADCRED); /* garbled credential */
+ }
+ sessionkey = &authdes_cache[sid].key;
+ }
+
+
+ /*
+ * Decrypt the timestamp
+ */
+ cryptbuf[0] = verf.adv_xtimestamp;
+ if (cred->adc_namekind == ADN_FULLNAME) {
+ cryptbuf[1].key.high = cred->adc_fullname.window;
+ cryptbuf[1].key.low = verf.adv_winverf;
+ ivec.key.high = ivec.key.low = 0;
+ status = cbc_crypt((char *)sessionkey, (char *)cryptbuf,
+ 2*sizeof(des_block), DES_DECRYPT | DES_HW,
+ (char *)&ivec);
+ } else {
+ status = ecb_crypt((char *)sessionkey, (char *)cryptbuf,
+ sizeof(des_block), DES_DECRYPT | DES_HW);
+ }
+ if (DES_FAILED(status)) {
+ debug("decryption failure");
+ return (AUTH_FAILED); /* system error */
+ }
+
+ /*
+ * XDR the decrypted timestamp
+ */
+ ixdr = (long *)cryptbuf;
+ timestamp.tv_sec = IXDR_GET_LONG(ixdr);
+ timestamp.tv_usec = IXDR_GET_LONG(ixdr);
+
+ /*
+ * Check for valid credentials and verifiers.
+ * They could be invalid because the key was flushed
+ * out of the cache, and so a new session should begin.
+ * Be sure and send AUTH_REJECTED{CRED, VERF} if this is the case.
+ */
+ {
+ struct timeval current;
+ int nick;
+ int winverf;
+
+ if (cred->adc_namekind == ADN_FULLNAME) {
+ window = IXDR_GET_U_LONG(ixdr);
+ winverf = IXDR_GET_U_LONG(ixdr);
+ if (winverf != window - 1) {
+ debug("window verifier mismatch");
+ return (AUTH_BADCRED); /* garbled credential */
+ }
+ sid = cache_spot(sessionkey, cred->adc_fullname.name,
+ &timestamp);
+ if (sid < 0) {
+ debug("replayed credential");
+ return (AUTH_REJECTEDCRED); /* replay */
+ }
+ nick = 0;
+ } else { /* ADN_NICKNAME */
+ window = authdes_cache[sid].window;
+ nick = 1;
+ }
+
+ if ((u_long)timestamp.tv_usec >= USEC_PER_SEC) {
+ debug("invalid usecs");
+ /* cached out (bad key), or garbled verifier */
+ return (nick ? AUTH_REJECTEDVERF : AUTH_BADVERF);
+ }
+ if (nick && BEFORE(&timestamp,
+ &authdes_cache[sid].laststamp)) {
+ debug("timestamp before last seen");
+ return (AUTH_REJECTEDVERF); /* replay */
+ }
+ (void) gettimeofday(&current, (struct timezone *)NULL);
+ current.tv_sec -= window; /* allow for expiration */
+ if (!BEFORE(&current, &timestamp)) {
+ debug("timestamp expired");
+ /* replay, or garbled credential */
+ return (nick ? AUTH_REJECTEDVERF : AUTH_BADCRED);
+ }
+ }
+
+ /*
+ * Set up the reply verifier
+ */
+ verf.adv_nickname = (u_long)sid;
+
+ /*
+ * xdr the timestamp before encrypting
+ */
+ ixdr = (long *)cryptbuf;
+ IXDR_PUT_LONG(ixdr, timestamp.tv_sec - 1);
+ IXDR_PUT_LONG(ixdr, timestamp.tv_usec);
+
+ /*
+ * encrypt the timestamp
+ */
+ status = ecb_crypt((char *)sessionkey, (char *)cryptbuf,
+ sizeof(des_block), DES_ENCRYPT | DES_HW);
+ if (DES_FAILED(status)) {
+ debug("encryption failure");
+ return (AUTH_FAILED); /* system error */
+ }
+ verf.adv_xtimestamp = cryptbuf[0];
+
+ /*
+ * Serialize the reply verifier, and update rqst
+ */
+ ixdr = (long *)msg->rm_call.cb_verf.oa_base;
+ *ixdr++ = (long)verf.adv_xtimestamp.key.high;
+ *ixdr++ = (long)verf.adv_xtimestamp.key.low;
+ *ixdr++ = (long)verf.adv_int_u;
+
+ rqst->rq_xprt->xp_verf.oa_flavor = AUTH_DES;
+ rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base;
+ rqst->rq_xprt->xp_verf.oa_length =
+ (char *)ixdr - msg->rm_call.cb_verf.oa_base;
+
+ /*
+ * We succeeded, commit the data to the cache now and
+ * finish cooking the credential.
+ */
+ entry = &authdes_cache[sid];
+ entry->laststamp = timestamp;
+ cache_ref(sid);
+ if (cred->adc_namekind == ADN_FULLNAME) {
+ cred->adc_fullname.window = window;
+ cred->adc_nickname = (u_long)sid; /* save nickname */
+ if (entry->rname != NULL) {
+ mem_free(entry->rname, strlen(entry->rname) + 1);
+ }
+ entry->rname = (char *)mem_alloc((u_int)strlen(cred->adc_fullname.name)
+ + 1);
+ if (entry->rname != NULL) {
+ (void) strcpy(entry->rname, cred->adc_fullname.name);
+ } else {
+ debug("out of memory");
+ }
+ entry->key = *sessionkey;
+ entry->window = window;
+ invalidate(entry->localcred); /* mark any cached cred invalid */
+ } else { /* ADN_NICKNAME */
+ /*
+ * nicknames are cooked into fullnames
+ */
+ cred->adc_namekind = ADN_FULLNAME;
+ cred->adc_fullname.name = entry->rname;
+ cred->adc_fullname.key = entry->key;
+ cred->adc_fullname.window = entry->window;
+ }
+ return (AUTH_OK); /* we made it!*/
+}
+
+
+/*
+ * Initialize the cache
+ */
+static void
+cache_init()
+{
+ int i;
+
+ authdes_cache = (struct cache_entry *)
+ mem_alloc(sizeof(struct cache_entry) * AUTHDES_CACHESZ);
+ bzero((char *)authdes_cache,
+ sizeof(struct cache_entry) * AUTHDES_CACHESZ);
+
+ authdes_lru = (short *)mem_alloc(sizeof(short) * AUTHDES_CACHESZ);
+ /*
+ * Initialize the lru list
+ */
+ for (i = 0; i < AUTHDES_CACHESZ; i++) {
+ authdes_lru[i] = i;
+ }
+}
+
+
+/*
+ * Find the lru victim
+ */
+static short
+cache_victim()
+{
+ return (authdes_lru[AUTHDES_CACHESZ-1]);
+}
+
+/*
+ * Note that sid was referenced
+ */
+static void
+cache_ref(sid)
+ short sid;
+{
+ int i;
+ short curr;
+ short prev;
+
+ prev = authdes_lru[0];
+ authdes_lru[0] = sid;
+ for (i = 1; prev != sid; i++) {
+ curr = authdes_lru[i];
+ authdes_lru[i] = prev;
+ prev = curr;
+ }
+}
+
+
+/*
+ * Find a spot in the cache for a credential containing
+ * the items given. Return -1 if a replay is detected, otherwise
+ * return the spot in the cache.
+ */
+static short
+cache_spot(key, name, timestamp)
+ des_block *key;
+ char *name;
+ struct timeval *timestamp;
+{
+ struct cache_entry *cp;
+ int i;
+ u_long hi;
+
+ hi = key->key.high;
+ for (cp = authdes_cache, i = 0; i < AUTHDES_CACHESZ; i++, cp++) {
+ if (cp->key.key.high == hi &&
+ cp->key.key.low == key->key.low &&
+ cp->rname != NULL &&
+ bcmp(cp->rname, name, strlen(name) + 1) == 0) {
+ if (BEFORE(timestamp, &cp->laststamp)) {
+ svcauthdes_stats.ncachereplays++;
+ return (-1); /* replay */
+ }
+ svcauthdes_stats.ncachehits++;
+ return (i); /* refresh */
+ }
+ }
+ svcauthdes_stats.ncachemisses++;
+ return (cache_victim()); /* new credential */
+}
+
+
+#if (defined(sun) || defined(vax) || defined(__FreeBSD__))
+/*
+ * Local credential handling stuff.
+ * NOTE: bsd unix dependent.
+ * Other operating systems should put something else here.
+ */
+#define UNKNOWN -2 /* grouplen, if cached cred is unknown user */
+#define INVALID -1 /* grouplen, if cache entry is invalid */
+
+struct bsdcred {
+ uid_t uid; /* cached uid */
+ gid_t gid; /* cached gid */
+ int grouplen; /* length of cached groups */
+ gid_t groups[NGRPS]; /* cached groups */
+};
+
+/*
+ * Map a des credential into a unix cred.
+ * We cache the credential here so the application does
+ * not have to make an rpc call every time to interpret
+ * the credential.
+ */
+int
+authdes_getucred(adc, uid, gid, grouplen, groups)
+ struct authdes_cred *adc;
+ uid_t *uid;
+ gid_t *gid;
+ int *grouplen;
+ gid_t *groups;
+{
+ unsigned sid;
+ int i;
+ uid_t i_uid;
+ gid_t i_gid;
+ int i_grouplen;
+ struct bsdcred *cred;
+
+ sid = adc->adc_nickname;
+ if (sid >= AUTHDES_CACHESZ) {
+ debug("invalid nickname");
+ return (0);
+ }
+ cred = (struct bsdcred *)authdes_cache[sid].localcred;
+ if (cred == NULL) {
+ cred = (struct bsdcred *)mem_alloc(sizeof(struct bsdcred));
+ authdes_cache[sid].localcred = (char *)cred;
+ cred->grouplen = INVALID;
+ }
+ if (cred->grouplen == INVALID) {
+ /*
+ * not in cache: lookup
+ */
+ if (!netname2user(adc->adc_fullname.name, &i_uid, &i_gid,
+ &i_grouplen, groups))
+ {
+ debug("unknown netname");
+ cred->grouplen = UNKNOWN; /* mark as lookup up, but not found */
+ return (0);
+ }
+ debug("missed ucred cache");
+ *uid = cred->uid = i_uid;
+ *gid = cred->gid = i_gid;
+ *grouplen = cred->grouplen = i_grouplen;
+ for (i = i_grouplen - 1; i >= 0; i--) {
+ cred->groups[i] = groups[i]; /* int to short */
+ }
+ return (1);
+ } else if (cred->grouplen == UNKNOWN) {
+ /*
+ * Already lookup up, but no match found
+ */
+ return (0);
+ }
+
+ /*
+ * cached credentials
+ */
+ *uid = cred->uid;
+ *gid = cred->gid;
+ *grouplen = cred->grouplen;
+ for (i = cred->grouplen - 1; i >= 0; i--) {
+ groups[i] = cred->groups[i]; /* short to int */
+ }
+ return (1);
+}
+
+static void
+invalidate(cred)
+ char *cred;
+{
+ if (cred == NULL) {
+ return;
+ }
+ ((struct bsdcred *)cred)->grouplen = INVALID;
+}
+#endif
+
diff --git a/lib/libc/rpc/svc_auth_unix.c b/lib/libc/rpc/svc_auth_unix.c
new file mode 100644
index 0000000..4d6f102
--- /dev/null
+++ b/lib/libc/rpc/svc_auth_unix.c
@@ -0,0 +1,156 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)svc_auth_unix.c 2.3 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc_auth_unix.c
+ * Handles UNIX flavor authentication parameters on the service side of rpc.
+ * There are two svc auth implementations here: AUTH_UNIX and AUTH_SHORT.
+ * _svcauth_unix does full blown unix style uid,gid+gids auth,
+ * _svcauth_short uses a shorthand auth to index into a cache of longhand auths.
+ * Note: the shorthand has been gutted for efficiency.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ */
+
+#include "namespace.h"
+#include <assert.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <rpc/rpc.h>
+#include "un-namespace.h"
+
+/*
+ * Unix longhand authenticator
+ */
+enum auth_stat
+_svcauth_unix(rqst, msg)
+ struct svc_req *rqst;
+ struct rpc_msg *msg;
+{
+ enum auth_stat stat;
+ XDR xdrs;
+ struct authunix_parms *aup;
+ int32_t *buf;
+ struct area {
+ struct authunix_parms area_aup;
+ char area_machname[MAX_MACHINE_NAME+1];
+ int area_gids[NGRPS];
+ } *area;
+ u_int auth_len;
+ size_t str_len, gid_len;
+ u_int i;
+
+ assert(rqst != NULL);
+ assert(msg != NULL);
+
+ area = (struct area *) rqst->rq_clntcred;
+ aup = &area->area_aup;
+ aup->aup_machname = area->area_machname;
+ aup->aup_gids = area->area_gids;
+ auth_len = (u_int)msg->rm_call.cb_cred.oa_length;
+ xdrmem_create(&xdrs, msg->rm_call.cb_cred.oa_base, auth_len,XDR_DECODE);
+ buf = XDR_INLINE(&xdrs, auth_len);
+ if (buf != NULL) {
+ aup->aup_time = IXDR_GET_INT32(buf);
+ str_len = (size_t)IXDR_GET_U_INT32(buf);
+ if (str_len > MAX_MACHINE_NAME) {
+ stat = AUTH_BADCRED;
+ goto done;
+ }
+ memmove(aup->aup_machname, buf, str_len);
+ aup->aup_machname[str_len] = 0;
+ str_len = RNDUP(str_len);
+ buf += str_len / sizeof (int32_t);
+ aup->aup_uid = (int)IXDR_GET_INT32(buf);
+ aup->aup_gid = (int)IXDR_GET_INT32(buf);
+ gid_len = (size_t)IXDR_GET_U_INT32(buf);
+ if (gid_len > NGRPS) {
+ stat = AUTH_BADCRED;
+ goto done;
+ }
+ aup->aup_len = gid_len;
+ for (i = 0; i < gid_len; i++) {
+ aup->aup_gids[i] = (int)IXDR_GET_INT32(buf);
+ }
+ /*
+ * five is the smallest unix credentials structure -
+ * timestamp, hostname len (0), uid, gid, and gids len (0).
+ */
+ if ((5 + gid_len) * BYTES_PER_XDR_UNIT + str_len > auth_len) {
+ (void) printf("bad auth_len gid %ld str %ld auth %u\n",
+ (long)gid_len, (long)str_len, auth_len);
+ stat = AUTH_BADCRED;
+ goto done;
+ }
+ } else if (! xdr_authunix_parms(&xdrs, aup)) {
+ xdrs.x_op = XDR_FREE;
+ (void)xdr_authunix_parms(&xdrs, aup);
+ stat = AUTH_BADCRED;
+ goto done;
+ }
+
+ /* get the verifier */
+ if ((u_int)msg->rm_call.cb_verf.oa_length) {
+ rqst->rq_xprt->xp_verf.oa_flavor =
+ msg->rm_call.cb_verf.oa_flavor;
+ rqst->rq_xprt->xp_verf.oa_base =
+ msg->rm_call.cb_verf.oa_base;
+ rqst->rq_xprt->xp_verf.oa_length =
+ msg->rm_call.cb_verf.oa_length;
+ } else {
+ rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL;
+ rqst->rq_xprt->xp_verf.oa_length = 0;
+ }
+ stat = AUTH_OK;
+done:
+ XDR_DESTROY(&xdrs);
+ return (stat);
+}
+
+
+/*
+ * Shorthand unix authenticator
+ * Looks up longhand in a cache.
+ */
+/*ARGSUSED*/
+enum auth_stat
+_svcauth_short(rqst, msg)
+ struct svc_req *rqst;
+ struct rpc_msg *msg;
+{
+ return (AUTH_REJECTEDCRED);
+}
diff --git a/lib/libc/rpc/svc_dg.c b/lib/libc/rpc/svc_dg.c
new file mode 100644
index 0000000..a78b160
--- /dev/null
+++ b/lib/libc/rpc/svc_dg.c
@@ -0,0 +1,739 @@
+/* $NetBSD: svc_dg.c,v 1.4 2000/07/06 03:10:35 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#ident "@(#)svc_dg.c 1.17 94/04/24 SMI"
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc_dg.c, Server side for connectionless RPC.
+ *
+ * Does some caching in the hopes of achieving execute-at-most-once semantics.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <rpc/rpc.h>
+#include <rpc/svc_dg.h>
+#include <assert.h>
+#include <errno.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#ifdef RPC_CACHE_DEBUG
+#include <netconfig.h>
+#include <netdir.h>
+#endif
+#include <err.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+#define su_data(xprt) ((struct svc_dg_data *)(xprt->xp_p2))
+#define rpc_buffer(xprt) ((xprt)->xp_p1)
+
+#ifndef MAX
+#define MAX(a, b) (((a) > (b)) ? (a) : (b))
+#endif
+
+static void svc_dg_ops(SVCXPRT *);
+static enum xprt_stat svc_dg_stat(SVCXPRT *);
+static bool_t svc_dg_recv(SVCXPRT *, struct rpc_msg *);
+static bool_t svc_dg_reply(SVCXPRT *, struct rpc_msg *);
+static bool_t svc_dg_getargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t svc_dg_freeargs(SVCXPRT *, xdrproc_t, void *);
+static void svc_dg_destroy(SVCXPRT *);
+static bool_t svc_dg_control(SVCXPRT *, const u_int, void *);
+static int cache_get(SVCXPRT *, struct rpc_msg *, char **, size_t *);
+static void cache_set(SVCXPRT *, size_t);
+int svc_dg_enablecache(SVCXPRT *, u_int);
+
+/*
+ * Usage:
+ * xprt = svc_dg_create(sock, sendsize, recvsize);
+ * Does other connectionless specific initializations.
+ * Once *xprt is initialized, it is registered.
+ * see (svc.h, xprt_register). If recvsize or sendsize are 0 suitable
+ * system defaults are chosen.
+ * The routines returns NULL if a problem occurred.
+ */
+static const char svc_dg_str[] = "svc_dg_create: %s";
+static const char svc_dg_err1[] = "could not get transport information";
+static const char svc_dg_err2[] = "transport does not support data transfer";
+static const char svc_dg_err3[] = "getsockname failed";
+static const char svc_dg_err4[] = "cannot set IP_RECVDSTADDR";
+static const char __no_mem_str[] = "out of memory";
+
+SVCXPRT *
+svc_dg_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+ SVCXPRT *xprt;
+ struct svc_dg_data *su = NULL;
+ struct __rpc_sockinfo si;
+ struct sockaddr_storage ss;
+ socklen_t slen;
+
+ if (!__rpc_fd2sockinfo(fd, &si)) {
+ warnx(svc_dg_str, svc_dg_err1);
+ return (NULL);
+ }
+ /*
+ * Find the receive and the send size
+ */
+ sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
+ recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
+ if ((sendsize == 0) || (recvsize == 0)) {
+ warnx(svc_dg_str, svc_dg_err2);
+ return (NULL);
+ }
+
+ xprt = svc_xprt_alloc();
+ if (xprt == NULL)
+ goto freedata;
+
+ su = mem_alloc(sizeof (*su));
+ if (su == NULL)
+ goto freedata;
+ su->su_iosz = ((MAX(sendsize, recvsize) + 3) / 4) * 4;
+ if ((rpc_buffer(xprt) = mem_alloc(su->su_iosz)) == NULL)
+ goto freedata;
+ xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt), su->su_iosz,
+ XDR_DECODE);
+ su->su_cache = NULL;
+ xprt->xp_fd = fd;
+ xprt->xp_p2 = su;
+ xprt->xp_verf.oa_base = su->su_verfbody;
+ svc_dg_ops(xprt);
+ xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage);
+
+ slen = sizeof ss;
+ if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
+ warnx(svc_dg_str, svc_dg_err3);
+ goto freedata_nowarn;
+ }
+ xprt->xp_ltaddr.buf = mem_alloc(sizeof (struct sockaddr_storage));
+ xprt->xp_ltaddr.maxlen = sizeof (struct sockaddr_storage);
+ xprt->xp_ltaddr.len = slen;
+ memcpy(xprt->xp_ltaddr.buf, &ss, slen);
+
+ if (ss.ss_family == AF_INET) {
+ struct sockaddr_in *sin;
+ static const int true_value = 1;
+
+ sin = (struct sockaddr_in *)(void *)&ss;
+ if (sin->sin_addr.s_addr == INADDR_ANY) {
+ su->su_srcaddr.buf = mem_alloc(sizeof (ss));
+ su->su_srcaddr.maxlen = sizeof (ss);
+
+ if (_setsockopt(fd, IPPROTO_IP, IP_RECVDSTADDR,
+ &true_value, sizeof(true_value))) {
+ warnx(svc_dg_str, svc_dg_err4);
+ goto freedata_nowarn;
+ }
+ }
+ }
+
+ xprt_register(xprt);
+ return (xprt);
+freedata:
+ (void) warnx(svc_dg_str, __no_mem_str);
+freedata_nowarn:
+ if (xprt) {
+ if (su)
+ (void) mem_free(su, sizeof (*su));
+ svc_xprt_free(xprt);
+ }
+ return (NULL);
+}
+
+/*ARGSUSED*/
+static enum xprt_stat
+svc_dg_stat(xprt)
+ SVCXPRT *xprt;
+{
+ return (XPRT_IDLE);
+}
+
+static int
+svc_dg_recvfrom(int fd, char *buf, int buflen,
+ struct sockaddr *raddr, socklen_t *raddrlen,
+ struct sockaddr *laddr, socklen_t *laddrlen)
+{
+ struct msghdr msg;
+ struct iovec msg_iov[1];
+ struct sockaddr_in *lin = (struct sockaddr_in *)laddr;
+ int rlen;
+ bool_t have_lin = FALSE;
+ char tmp[CMSG_LEN(sizeof(*lin))];
+ struct cmsghdr *cmsg;
+
+ memset((char *)&msg, 0, sizeof(msg));
+ msg_iov[0].iov_base = buf;
+ msg_iov[0].iov_len = buflen;
+ msg.msg_iov = msg_iov;
+ msg.msg_iovlen = 1;
+ msg.msg_namelen = *raddrlen;
+ msg.msg_name = (char *)raddr;
+ if (laddr != NULL) {
+ msg.msg_control = (caddr_t)tmp;
+ msg.msg_controllen = CMSG_LEN(sizeof(*lin));
+ }
+ rlen = _recvmsg(fd, &msg, 0);
+ if (rlen >= 0)
+ *raddrlen = msg.msg_namelen;
+
+ if (rlen == -1 || laddr == NULL ||
+ msg.msg_controllen < sizeof(struct cmsghdr) ||
+ msg.msg_flags & MSG_CTRUNC)
+ return rlen;
+
+ for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL;
+ cmsg = CMSG_NXTHDR(&msg, cmsg)) {
+ if (cmsg->cmsg_level == IPPROTO_IP &&
+ cmsg->cmsg_type == IP_RECVDSTADDR) {
+ have_lin = TRUE;
+ memcpy(&lin->sin_addr,
+ (struct in_addr *)CMSG_DATA(cmsg),
+ sizeof(struct in_addr));
+ break;
+ }
+ }
+
+ lin->sin_family = AF_INET;
+ lin->sin_port = 0;
+ *laddrlen = sizeof(struct sockaddr_in);
+
+ if (!have_lin)
+ lin->sin_addr.s_addr = INADDR_ANY;
+
+ return rlen;
+}
+
+static bool_t
+svc_dg_recv(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ struct svc_dg_data *su = su_data(xprt);
+ XDR *xdrs = &(su->su_xdrs);
+ char *reply;
+ struct sockaddr_storage ss;
+ socklen_t alen;
+ size_t replylen;
+ ssize_t rlen;
+
+again:
+ alen = sizeof (struct sockaddr_storage);
+ rlen = svc_dg_recvfrom(xprt->xp_fd, rpc_buffer(xprt), su->su_iosz,
+ (struct sockaddr *)(void *)&ss, &alen,
+ (struct sockaddr *)su->su_srcaddr.buf, &su->su_srcaddr.len);
+ if (rlen == -1 && errno == EINTR)
+ goto again;
+ if (rlen == -1 || (rlen < (ssize_t)(4 * sizeof (u_int32_t))))
+ return (FALSE);
+ if (xprt->xp_rtaddr.len < alen) {
+ if (xprt->xp_rtaddr.len != 0)
+ mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.len);
+ xprt->xp_rtaddr.buf = mem_alloc(alen);
+ xprt->xp_rtaddr.len = alen;
+ }
+ memcpy(xprt->xp_rtaddr.buf, &ss, alen);
+#ifdef PORTMAP
+ if (ss.ss_family == AF_INET) {
+ xprt->xp_raddr = *(struct sockaddr_in *)xprt->xp_rtaddr.buf;
+ xprt->xp_addrlen = sizeof (struct sockaddr_in);
+ }
+#endif /* PORTMAP */
+ xdrs->x_op = XDR_DECODE;
+ XDR_SETPOS(xdrs, 0);
+ if (! xdr_callmsg(xdrs, msg)) {
+ return (FALSE);
+ }
+ su->su_xid = msg->rm_xid;
+ if (su->su_cache != NULL) {
+ if (cache_get(xprt, msg, &reply, &replylen)) {
+ (void)_sendto(xprt->xp_fd, reply, replylen, 0,
+ (struct sockaddr *)(void *)&ss, alen);
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+static int
+svc_dg_sendto(int fd, char *buf, int buflen,
+ const struct sockaddr *raddr, socklen_t raddrlen,
+ const struct sockaddr *laddr, socklen_t laddrlen)
+{
+ struct msghdr msg;
+ struct iovec msg_iov[1];
+ struct sockaddr_in *laddr_in = (struct sockaddr_in *)laddr;
+ struct in_addr *lin = &laddr_in->sin_addr;
+ char tmp[CMSG_SPACE(sizeof(*lin))];
+ struct cmsghdr *cmsg;
+
+ memset((char *)&msg, 0, sizeof(msg));
+ msg_iov[0].iov_base = buf;
+ msg_iov[0].iov_len = buflen;
+ msg.msg_iov = msg_iov;
+ msg.msg_iovlen = 1;
+ msg.msg_namelen = raddrlen;
+ msg.msg_name = (char *)raddr;
+
+ if (laddr != NULL && laddr->sa_family == AF_INET &&
+ lin->s_addr != INADDR_ANY) {
+ msg.msg_control = (caddr_t)tmp;
+ msg.msg_controllen = CMSG_LEN(sizeof(*lin));
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(*lin));
+ cmsg->cmsg_level = IPPROTO_IP;
+ cmsg->cmsg_type = IP_SENDSRCADDR;
+ memcpy(CMSG_DATA(cmsg), lin, sizeof(*lin));
+ }
+
+ return _sendmsg(fd, &msg, 0);
+}
+
+static bool_t
+svc_dg_reply(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ struct svc_dg_data *su = su_data(xprt);
+ XDR *xdrs = &(su->su_xdrs);
+ bool_t stat = TRUE;
+ size_t slen;
+ xdrproc_t xdr_proc;
+ caddr_t xdr_where;
+
+ xdrs->x_op = XDR_ENCODE;
+ XDR_SETPOS(xdrs, 0);
+ msg->rm_xid = su->su_xid;
+ if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
+ msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
+ xdr_proc = msg->acpted_rply.ar_results.proc;
+ xdr_where = msg->acpted_rply.ar_results.where;
+ msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
+ msg->acpted_rply.ar_results.where = NULL;
+
+ if (!xdr_replymsg(xdrs, msg) ||
+ !SVCAUTH_WRAP(&SVC_AUTH(xprt), xdrs, xdr_proc, xdr_where))
+ stat = FALSE;
+ } else {
+ stat = xdr_replymsg(xdrs, msg);
+ }
+ if (stat) {
+ slen = XDR_GETPOS(xdrs);
+ if (svc_dg_sendto(xprt->xp_fd, rpc_buffer(xprt), slen,
+ (struct sockaddr *)xprt->xp_rtaddr.buf,
+ (socklen_t)xprt->xp_rtaddr.len,
+ (struct sockaddr *)su->su_srcaddr.buf,
+ (socklen_t)su->su_srcaddr.len) == (ssize_t) slen) {
+ stat = TRUE;
+ if (su->su_cache)
+ cache_set(xprt, slen);
+ }
+ }
+ return (stat);
+}
+
+static bool_t
+svc_dg_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ void *args_ptr;
+{
+ struct svc_dg_data *su;
+
+ assert(xprt != NULL);
+ su = su_data(xprt);
+ return (SVCAUTH_UNWRAP(&SVC_AUTH(xprt),
+ &su->su_xdrs, xdr_args, args_ptr));
+}
+
+static bool_t
+svc_dg_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ void *args_ptr;
+{
+ XDR *xdrs = &(su_data(xprt)->su_xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return (*xdr_args)(xdrs, args_ptr);
+}
+
+static void
+svc_dg_destroy(xprt)
+ SVCXPRT *xprt;
+{
+ struct svc_dg_data *su = su_data(xprt);
+
+ xprt_unregister(xprt);
+ if (xprt->xp_fd != -1)
+ (void)_close(xprt->xp_fd);
+ XDR_DESTROY(&(su->su_xdrs));
+ (void) mem_free(rpc_buffer(xprt), su->su_iosz);
+ if (su->su_srcaddr.buf)
+ (void) mem_free(su->su_srcaddr.buf, su->su_srcaddr.maxlen);
+ (void) mem_free(su, sizeof (*su));
+ if (xprt->xp_rtaddr.buf)
+ (void) mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
+ if (xprt->xp_ltaddr.buf)
+ (void) mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
+ if (xprt->xp_tp)
+ (void) free(xprt->xp_tp);
+ svc_xprt_free(xprt);
+}
+
+static bool_t
+/*ARGSUSED*/
+svc_dg_control(xprt, rq, in)
+ SVCXPRT *xprt;
+ const u_int rq;
+ void *in;
+{
+ return (FALSE);
+}
+
+static void
+svc_dg_ops(xprt)
+ SVCXPRT *xprt;
+{
+ static struct xp_ops ops;
+ static struct xp_ops2 ops2;
+
+/* VARIABLES PROTECTED BY ops_lock: ops */
+
+ mutex_lock(&ops_lock);
+ if (ops.xp_recv == NULL) {
+ ops.xp_recv = svc_dg_recv;
+ ops.xp_stat = svc_dg_stat;
+ ops.xp_getargs = svc_dg_getargs;
+ ops.xp_reply = svc_dg_reply;
+ ops.xp_freeargs = svc_dg_freeargs;
+ ops.xp_destroy = svc_dg_destroy;
+ ops2.xp_control = svc_dg_control;
+ }
+ xprt->xp_ops = &ops;
+ xprt->xp_ops2 = &ops2;
+ mutex_unlock(&ops_lock);
+}
+
+/* The CACHING COMPONENT */
+
+/*
+ * Could have been a separate file, but some part of it depends upon the
+ * private structure of the client handle.
+ *
+ * Fifo cache for cl server
+ * Copies pointers to reply buffers into fifo cache
+ * Buffers are sent again if retransmissions are detected.
+ */
+
+#define SPARSENESS 4 /* 75% sparse */
+
+#define ALLOC(type, size) \
+ (type *) mem_alloc((sizeof (type) * (size)))
+
+#define MEMZERO(addr, type, size) \
+ (void) memset((void *) (addr), 0, sizeof (type) * (int) (size))
+
+#define FREE(addr, type, size) \
+ mem_free((addr), (sizeof (type) * (size)))
+
+/*
+ * An entry in the cache
+ */
+typedef struct cache_node *cache_ptr;
+struct cache_node {
+ /*
+ * Index into cache is xid, proc, vers, prog and address
+ */
+ u_int32_t cache_xid;
+ rpcproc_t cache_proc;
+ rpcvers_t cache_vers;
+ rpcprog_t cache_prog;
+ struct netbuf cache_addr;
+ /*
+ * The cached reply and length
+ */
+ char *cache_reply;
+ size_t cache_replylen;
+ /*
+ * Next node on the list, if there is a collision
+ */
+ cache_ptr cache_next;
+};
+
+/*
+ * The entire cache
+ */
+struct cl_cache {
+ u_int uc_size; /* size of cache */
+ cache_ptr *uc_entries; /* hash table of entries in cache */
+ cache_ptr *uc_fifo; /* fifo list of entries in cache */
+ u_int uc_nextvictim; /* points to next victim in fifo list */
+ rpcprog_t uc_prog; /* saved program number */
+ rpcvers_t uc_vers; /* saved version number */
+ rpcproc_t uc_proc; /* saved procedure number */
+};
+
+
+/*
+ * the hashing function
+ */
+#define CACHE_LOC(transp, xid) \
+ (xid % (SPARSENESS * ((struct cl_cache *) \
+ su_data(transp)->su_cache)->uc_size))
+
+/*
+ * Enable use of the cache. Returns 1 on success, 0 on failure.
+ * Note: there is no disable.
+ */
+static const char cache_enable_str[] = "svc_enablecache: %s %s";
+static const char alloc_err[] = "could not allocate cache ";
+static const char enable_err[] = "cache already enabled";
+
+int
+svc_dg_enablecache(transp, size)
+ SVCXPRT *transp;
+ u_int size;
+{
+ struct svc_dg_data *su = su_data(transp);
+ struct cl_cache *uc;
+
+ mutex_lock(&dupreq_lock);
+ if (su->su_cache != NULL) {
+ (void) warnx(cache_enable_str, enable_err, " ");
+ mutex_unlock(&dupreq_lock);
+ return (0);
+ }
+ uc = ALLOC(struct cl_cache, 1);
+ if (uc == NULL) {
+ warnx(cache_enable_str, alloc_err, " ");
+ mutex_unlock(&dupreq_lock);
+ return (0);
+ }
+ uc->uc_size = size;
+ uc->uc_nextvictim = 0;
+ uc->uc_entries = ALLOC(cache_ptr, size * SPARSENESS);
+ if (uc->uc_entries == NULL) {
+ warnx(cache_enable_str, alloc_err, "data");
+ FREE(uc, struct cl_cache, 1);
+ mutex_unlock(&dupreq_lock);
+ return (0);
+ }
+ MEMZERO(uc->uc_entries, cache_ptr, size * SPARSENESS);
+ uc->uc_fifo = ALLOC(cache_ptr, size);
+ if (uc->uc_fifo == NULL) {
+ warnx(cache_enable_str, alloc_err, "fifo");
+ FREE(uc->uc_entries, cache_ptr, size * SPARSENESS);
+ FREE(uc, struct cl_cache, 1);
+ mutex_unlock(&dupreq_lock);
+ return (0);
+ }
+ MEMZERO(uc->uc_fifo, cache_ptr, size);
+ su->su_cache = (char *)(void *)uc;
+ mutex_unlock(&dupreq_lock);
+ return (1);
+}
+
+/*
+ * Set an entry in the cache. It assumes that the uc entry is set from
+ * the earlier call to cache_get() for the same procedure. This will always
+ * happen because cache_get() is calle by svc_dg_recv and cache_set() is called
+ * by svc_dg_reply(). All this hoopla because the right RPC parameters are
+ * not available at svc_dg_reply time.
+ */
+
+static const char cache_set_str[] = "cache_set: %s";
+static const char cache_set_err1[] = "victim not found";
+static const char cache_set_err2[] = "victim alloc failed";
+static const char cache_set_err3[] = "could not allocate new rpc buffer";
+
+static void
+cache_set(xprt, replylen)
+ SVCXPRT *xprt;
+ size_t replylen;
+{
+ cache_ptr victim;
+ cache_ptr *vicp;
+ struct svc_dg_data *su = su_data(xprt);
+ struct cl_cache *uc = (struct cl_cache *) su->su_cache;
+ u_int loc;
+ char *newbuf;
+#ifdef RPC_CACHE_DEBUG
+ struct netconfig *nconf;
+ char *uaddr;
+#endif
+
+ mutex_lock(&dupreq_lock);
+ /*
+ * Find space for the new entry, either by
+ * reusing an old entry, or by mallocing a new one
+ */
+ victim = uc->uc_fifo[uc->uc_nextvictim];
+ if (victim != NULL) {
+ loc = CACHE_LOC(xprt, victim->cache_xid);
+ for (vicp = &uc->uc_entries[loc];
+ *vicp != NULL && *vicp != victim;
+ vicp = &(*vicp)->cache_next)
+ ;
+ if (*vicp == NULL) {
+ warnx(cache_set_str, cache_set_err1);
+ mutex_unlock(&dupreq_lock);
+ return;
+ }
+ *vicp = victim->cache_next; /* remove from cache */
+ newbuf = victim->cache_reply;
+ } else {
+ victim = ALLOC(struct cache_node, 1);
+ if (victim == NULL) {
+ warnx(cache_set_str, cache_set_err2);
+ mutex_unlock(&dupreq_lock);
+ return;
+ }
+ newbuf = mem_alloc(su->su_iosz);
+ if (newbuf == NULL) {
+ warnx(cache_set_str, cache_set_err3);
+ FREE(victim, struct cache_node, 1);
+ mutex_unlock(&dupreq_lock);
+ return;
+ }
+ }
+
+ /*
+ * Store it away
+ */
+#ifdef RPC_CACHE_DEBUG
+ if (nconf = getnetconfigent(xprt->xp_netid)) {
+ uaddr = taddr2uaddr(nconf, &xprt->xp_rtaddr);
+ freenetconfigent(nconf);
+ printf(
+ "cache set for xid= %x prog=%d vers=%d proc=%d for rmtaddr=%s\n",
+ su->su_xid, uc->uc_prog, uc->uc_vers,
+ uc->uc_proc, uaddr);
+ free(uaddr);
+ }
+#endif
+ victim->cache_replylen = replylen;
+ victim->cache_reply = rpc_buffer(xprt);
+ rpc_buffer(xprt) = newbuf;
+ xdrmem_create(&(su->su_xdrs), rpc_buffer(xprt),
+ su->su_iosz, XDR_ENCODE);
+ victim->cache_xid = su->su_xid;
+ victim->cache_proc = uc->uc_proc;
+ victim->cache_vers = uc->uc_vers;
+ victim->cache_prog = uc->uc_prog;
+ victim->cache_addr = xprt->xp_rtaddr;
+ victim->cache_addr.buf = ALLOC(char, xprt->xp_rtaddr.len);
+ (void) memcpy(victim->cache_addr.buf, xprt->xp_rtaddr.buf,
+ (size_t)xprt->xp_rtaddr.len);
+ loc = CACHE_LOC(xprt, victim->cache_xid);
+ victim->cache_next = uc->uc_entries[loc];
+ uc->uc_entries[loc] = victim;
+ uc->uc_fifo[uc->uc_nextvictim++] = victim;
+ uc->uc_nextvictim %= uc->uc_size;
+ mutex_unlock(&dupreq_lock);
+}
+
+/*
+ * Try to get an entry from the cache
+ * return 1 if found, 0 if not found and set the stage for cache_set()
+ */
+static int
+cache_get(xprt, msg, replyp, replylenp)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+ char **replyp;
+ size_t *replylenp;
+{
+ u_int loc;
+ cache_ptr ent;
+ struct svc_dg_data *su = su_data(xprt);
+ struct cl_cache *uc = (struct cl_cache *) su->su_cache;
+#ifdef RPC_CACHE_DEBUG
+ struct netconfig *nconf;
+ char *uaddr;
+#endif
+
+ mutex_lock(&dupreq_lock);
+ loc = CACHE_LOC(xprt, su->su_xid);
+ for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) {
+ if (ent->cache_xid == su->su_xid &&
+ ent->cache_proc == msg->rm_call.cb_proc &&
+ ent->cache_vers == msg->rm_call.cb_vers &&
+ ent->cache_prog == msg->rm_call.cb_prog &&
+ ent->cache_addr.len == xprt->xp_rtaddr.len &&
+ (memcmp(ent->cache_addr.buf, xprt->xp_rtaddr.buf,
+ xprt->xp_rtaddr.len) == 0)) {
+#ifdef RPC_CACHE_DEBUG
+ if (nconf = getnetconfigent(xprt->xp_netid)) {
+ uaddr = taddr2uaddr(nconf, &xprt->xp_rtaddr);
+ freenetconfigent(nconf);
+ printf(
+ "cache entry found for xid=%x prog=%d vers=%d proc=%d for rmtaddr=%s\n",
+ su->su_xid, msg->rm_call.cb_prog,
+ msg->rm_call.cb_vers,
+ msg->rm_call.cb_proc, uaddr);
+ free(uaddr);
+ }
+#endif
+ *replyp = ent->cache_reply;
+ *replylenp = ent->cache_replylen;
+ mutex_unlock(&dupreq_lock);
+ return (1);
+ }
+ }
+ /*
+ * Failed to find entry
+ * Remember a few things so we can do a set later
+ */
+ uc->uc_proc = msg->rm_call.cb_proc;
+ uc->uc_vers = msg->rm_call.cb_vers;
+ uc->uc_prog = msg->rm_call.cb_prog;
+ mutex_unlock(&dupreq_lock);
+ return (0);
+}
diff --git a/lib/libc/rpc/svc_generic.c b/lib/libc/rpc/svc_generic.c
new file mode 100644
index 0000000..7f6cfb8
--- /dev/null
+++ b/lib/libc/rpc/svc_generic.c
@@ -0,0 +1,311 @@
+/* $NetBSD: svc_generic.c,v 1.3 2000/07/06 03:10:35 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#ident "@(#)svc_generic.c 1.19 94/04/24 SMI"
+static char sccsid[] = "@(#)svc_generic.c 1.21 89/02/28 Copyr 1988 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc_generic.c, Server side for RPC.
+ *
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <rpc/rpc.h>
+#include <rpc/nettype.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+extern int __svc_vc_setflag(SVCXPRT *, int);
+
+/*
+ * The highest level interface for server creation.
+ * It tries for all the nettokens in that particular class of token
+ * and returns the number of handles it can create and/or find.
+ *
+ * It creates a link list of all the handles it could create.
+ * If svc_create() is called multiple times, it uses the handle
+ * created earlier instead of creating a new handle every time.
+ */
+int
+svc_create(dispatch, prognum, versnum, nettype)
+ void (*dispatch)(struct svc_req *, SVCXPRT *);
+ rpcprog_t prognum; /* Program number */
+ rpcvers_t versnum; /* Version number */
+ const char *nettype; /* Networktype token */
+{
+ struct xlist {
+ SVCXPRT *xprt; /* Server handle */
+ struct xlist *next; /* Next item */
+ } *l;
+ static struct xlist *xprtlist; /* A link list of all the handles */
+ int num = 0;
+ SVCXPRT *xprt;
+ struct netconfig *nconf;
+ void *handle;
+
+/* VARIABLES PROTECTED BY xprtlist_lock: xprtlist */
+
+ if ((handle = __rpc_setconf(nettype)) == NULL) {
+ warnx("svc_create: unknown protocol");
+ return (0);
+ }
+ while ((nconf = __rpc_getconf(handle)) != NULL) {
+ mutex_lock(&xprtlist_lock);
+ for (l = xprtlist; l; l = l->next) {
+ if (strcmp(l->xprt->xp_netid, nconf->nc_netid) == 0) {
+ /* Found an old one, use it */
+ (void) rpcb_unset(prognum, versnum, nconf);
+ if (svc_reg(l->xprt, prognum, versnum,
+ dispatch, nconf) == FALSE)
+ warnx(
+ "svc_create: could not register prog %u vers %u on %s",
+ (unsigned)prognum, (unsigned)versnum,
+ nconf->nc_netid);
+ else
+ num++;
+ break;
+ }
+ }
+ if (l == NULL) {
+ /* It was not found. Now create a new one */
+ xprt = svc_tp_create(dispatch, prognum, versnum, nconf);
+ if (xprt) {
+ l = (struct xlist *)malloc(sizeof (*l));
+ if (l == NULL) {
+ warnx("svc_create: no memory");
+ mutex_unlock(&xprtlist_lock);
+ return (0);
+ }
+ l->xprt = xprt;
+ l->next = xprtlist;
+ xprtlist = l;
+ num++;
+ }
+ }
+ mutex_unlock(&xprtlist_lock);
+ }
+ __rpc_endconf(handle);
+ /*
+ * In case of num == 0; the error messages are generated by the
+ * underlying layers; and hence not needed here.
+ */
+ return (num);
+}
+
+/*
+ * The high level interface to svc_tli_create().
+ * It tries to create a server for "nconf" and registers the service
+ * with the rpcbind. It calls svc_tli_create();
+ */
+SVCXPRT *
+svc_tp_create(dispatch, prognum, versnum, nconf)
+ void (*dispatch)(struct svc_req *, SVCXPRT *);
+ rpcprog_t prognum; /* Program number */
+ rpcvers_t versnum; /* Version number */
+ const struct netconfig *nconf; /* Netconfig structure for the network */
+{
+ SVCXPRT *xprt;
+
+ if (nconf == NULL) {
+ warnx(
+ "svc_tp_create: invalid netconfig structure for prog %u vers %u",
+ (unsigned)prognum, (unsigned)versnum);
+ return (NULL);
+ }
+ xprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0);
+ if (xprt == NULL) {
+ return (NULL);
+ }
+ /*LINTED const castaway*/
+ (void) rpcb_unset(prognum, versnum, (struct netconfig *) nconf);
+ if (svc_reg(xprt, prognum, versnum, dispatch, nconf) == FALSE) {
+ warnx(
+ "svc_tp_create: Could not register prog %u vers %u on %s",
+ (unsigned)prognum, (unsigned)versnum,
+ nconf->nc_netid);
+ SVC_DESTROY(xprt);
+ return (NULL);
+ }
+ return (xprt);
+}
+
+/*
+ * If fd is RPC_ANYFD, then it opens a fd for the given transport
+ * provider (nconf cannot be NULL then). If the t_state is T_UNBND and
+ * bindaddr is NON-NULL, it performs a t_bind using the bindaddr. For
+ * NULL bindadr and Connection oriented transports, the value of qlen
+ * is set to 8.
+ *
+ * If sendsz or recvsz are zero, their default values are chosen.
+ */
+SVCXPRT *
+svc_tli_create(fd, nconf, bindaddr, sendsz, recvsz)
+ int fd; /* Connection end point */
+ const struct netconfig *nconf; /* Netconfig struct for nettoken */
+ const struct t_bind *bindaddr; /* Local bind address */
+ u_int sendsz; /* Max sendsize */
+ u_int recvsz; /* Max recvsize */
+{
+ SVCXPRT *xprt = NULL; /* service handle */
+ bool_t madefd = FALSE; /* whether fd opened here */
+ struct __rpc_sockinfo si;
+ struct sockaddr_storage ss;
+ socklen_t slen;
+
+ if (fd == RPC_ANYFD) {
+ if (nconf == NULL) {
+ warnx("svc_tli_create: invalid netconfig");
+ return (NULL);
+ }
+ fd = __rpc_nconf2fd(nconf);
+ if (fd == -1) {
+ warnx(
+ "svc_tli_create: could not open connection for %s",
+ nconf->nc_netid);
+ return (NULL);
+ }
+ __rpc_nconf2sockinfo(nconf, &si);
+ madefd = TRUE;
+ } else {
+ /*
+ * It is an open descriptor. Get the transport info.
+ */
+ if (!__rpc_fd2sockinfo(fd, &si)) {
+ warnx(
+ "svc_tli_create: could not get transport information");
+ return (NULL);
+ }
+ }
+
+ /*
+ * If the fd is unbound, try to bind it.
+ */
+ if (madefd || !__rpc_sockisbound(fd)) {
+ if (bindaddr == NULL) {
+ if (bindresvport(fd, NULL) < 0) {
+ memset(&ss, 0, sizeof ss);
+ ss.ss_family = si.si_af;
+ ss.ss_len = si.si_alen;
+ if (_bind(fd, (struct sockaddr *)(void *)&ss,
+ (socklen_t)si.si_alen) < 0) {
+ warnx(
+ "svc_tli_create: could not bind to anonymous port");
+ goto freedata;
+ }
+ }
+ _listen(fd, SOMAXCONN);
+ } else {
+ if (_bind(fd,
+ (struct sockaddr *)bindaddr->addr.buf,
+ (socklen_t)si.si_alen) < 0) {
+ warnx(
+ "svc_tli_create: could not bind to requested address");
+ goto freedata;
+ }
+ _listen(fd, (int)bindaddr->qlen);
+ }
+
+ }
+ /*
+ * call transport specific function.
+ */
+ switch (si.si_socktype) {
+ case SOCK_STREAM:
+ slen = sizeof ss;
+ if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen)
+ == 0) {
+ /* accepted socket */
+ xprt = svc_fd_create(fd, sendsz, recvsz);
+ } else
+ xprt = svc_vc_create(fd, sendsz, recvsz);
+ if (!nconf || !xprt)
+ break;
+#if 0
+ /* XXX fvdl */
+ if (strcmp(nconf->nc_protofmly, "inet") == 0 ||
+ strcmp(nconf->nc_protofmly, "inet6") == 0)
+ (void) __svc_vc_setflag(xprt, TRUE);
+#endif
+ break;
+ case SOCK_DGRAM:
+ xprt = svc_dg_create(fd, sendsz, recvsz);
+ break;
+ default:
+ warnx("svc_tli_create: bad service type");
+ goto freedata;
+ }
+
+ if (xprt == NULL)
+ /*
+ * The error messages here are spitted out by the lower layers:
+ * svc_vc_create(), svc_fd_create() and svc_dg_create().
+ */
+ goto freedata;
+
+ /* Fill in type of service */
+ xprt->xp_type = __rpc_socktype2seman(si.si_socktype);
+
+ if (nconf) {
+ xprt->xp_netid = strdup(nconf->nc_netid);
+ xprt->xp_tp = strdup(nconf->nc_device);
+ }
+ return (xprt);
+
+freedata:
+ if (madefd)
+ (void)_close(fd);
+ if (xprt) {
+ if (!madefd) /* so that svc_destroy doesnt close fd */
+ xprt->xp_fd = RPC_ANYFD;
+ SVC_DESTROY(xprt);
+ }
+ return (NULL);
+}
diff --git a/lib/libc/rpc/svc_raw.c b/lib/libc/rpc/svc_raw.c
new file mode 100644
index 0000000..67bcba1
--- /dev/null
+++ b/lib/libc/rpc/svc_raw.c
@@ -0,0 +1,274 @@
+/* $NetBSD: svc_raw.c,v 1.14 2000/07/06 03:10:35 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/* #ident "@(#)svc_raw.c 1.16 94/04/24 SMI" */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)svc_raw.c 1.25 89/01/31 Copyr 1984 Sun Micro";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc_raw.c, This a toy for simple testing and timing.
+ * Interface to create an rpc client and server in the same UNIX process.
+ * This lets us similate rpc and get rpc (round trip) overhead, without
+ * any interference from the kernel.
+ *
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <rpc/rpc.h>
+#include <sys/types.h>
+#include <rpc/raw.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+#include "mt_misc.h"
+
+#ifndef UDPMSGSIZE
+#define UDPMSGSIZE 8800
+#endif
+
+/*
+ * This is the "network" that we will be moving data over
+ */
+static struct svc_raw_private {
+ char *raw_buf; /* should be shared with the cl handle */
+ SVCXPRT *server;
+ XDR xdr_stream;
+ char verf_body[MAX_AUTH_BYTES];
+} *svc_raw_private;
+
+static enum xprt_stat svc_raw_stat(SVCXPRT *);
+static bool_t svc_raw_recv(SVCXPRT *, struct rpc_msg *);
+static bool_t svc_raw_reply(SVCXPRT *, struct rpc_msg *);
+static bool_t svc_raw_getargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t svc_raw_freeargs(SVCXPRT *, xdrproc_t, void *);
+static void svc_raw_destroy(SVCXPRT *);
+static void svc_raw_ops(SVCXPRT *);
+static bool_t svc_raw_control(SVCXPRT *, const u_int, void *);
+
+char *__rpc_rawcombuf = NULL;
+
+SVCXPRT *
+svc_raw_create()
+{
+ struct svc_raw_private *srp;
+/* VARIABLES PROTECTED BY svcraw_lock: svc_raw_private, srp */
+
+ mutex_lock(&svcraw_lock);
+ srp = svc_raw_private;
+ if (srp == NULL) {
+ srp = (struct svc_raw_private *)calloc(1, sizeof (*srp));
+ if (srp == NULL) {
+ mutex_unlock(&svcraw_lock);
+ return (NULL);
+ }
+ if (__rpc_rawcombuf == NULL)
+ __rpc_rawcombuf = calloc(UDPMSGSIZE, sizeof (char));
+ srp->raw_buf = __rpc_rawcombuf; /* Share it with the client */
+ srp->server = svc_xprt_alloc();
+ svc_raw_private = srp;
+ }
+ srp->server->xp_fd = FD_SETSIZE;
+ srp->server->xp_port = 0;
+ svc_raw_ops(srp->server);
+ srp->server->xp_verf.oa_base = srp->verf_body;
+ xdrmem_create(&srp->xdr_stream, srp->raw_buf, UDPMSGSIZE, XDR_DECODE);
+ xprt_register(srp->server);
+ mutex_unlock(&svcraw_lock);
+ return (srp->server);
+}
+
+/*ARGSUSED*/
+static enum xprt_stat
+svc_raw_stat(xprt)
+SVCXPRT *xprt; /* args needed to satisfy ANSI-C typechecking */
+{
+ return (XPRT_IDLE);
+}
+
+/*ARGSUSED*/
+static bool_t
+svc_raw_recv(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ struct svc_raw_private *srp;
+ XDR *xdrs;
+
+ mutex_lock(&svcraw_lock);
+ srp = svc_raw_private;
+ if (srp == NULL) {
+ mutex_unlock(&svcraw_lock);
+ return (FALSE);
+ }
+ mutex_unlock(&svcraw_lock);
+
+ xdrs = &srp->xdr_stream;
+ xdrs->x_op = XDR_DECODE;
+ (void) XDR_SETPOS(xdrs, 0);
+ if (! xdr_callmsg(xdrs, msg)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*ARGSUSED*/
+static bool_t
+svc_raw_reply(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ struct svc_raw_private *srp;
+ XDR *xdrs;
+ bool_t stat;
+ xdrproc_t xdr_proc;
+ caddr_t xdr_where;
+
+ mutex_lock(&svcraw_lock);
+ srp = svc_raw_private;
+ if (srp == NULL) {
+ mutex_unlock(&svcraw_lock);
+ return (FALSE);
+ }
+ mutex_unlock(&svcraw_lock);
+
+ xdrs = &srp->xdr_stream;
+ xdrs->x_op = XDR_ENCODE;
+ (void) XDR_SETPOS(xdrs, 0);
+ if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
+ msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
+ xdr_proc = msg->acpted_rply.ar_results.proc;
+ xdr_where = msg->acpted_rply.ar_results.where;
+ msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
+ msg->acpted_rply.ar_results.where = NULL;
+
+ stat = xdr_replymsg(xdrs, msg) &&
+ SVCAUTH_WRAP(&SVC_AUTH(xprt), xdrs, xdr_proc, xdr_where);
+ } else {
+ stat = xdr_replymsg(xdrs, msg);
+ }
+ if (!stat) {
+ return (FALSE);
+ }
+ (void) XDR_GETPOS(xdrs); /* called just for overhead */
+ return (TRUE);
+}
+
+/*ARGSUSED*/
+static bool_t
+svc_raw_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ void *args_ptr;
+{
+ struct svc_raw_private *srp;
+
+ mutex_lock(&svcraw_lock);
+ srp = svc_raw_private;
+ if (srp == NULL) {
+ mutex_unlock(&svcraw_lock);
+ return (FALSE);
+ }
+ mutex_unlock(&svcraw_lock);
+
+ return (SVCAUTH_UNWRAP(&SVC_AUTH(xprt), &srp->xdr_stream,
+ xdr_args, args_ptr));
+}
+
+/*ARGSUSED*/
+static bool_t
+svc_raw_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ void *args_ptr;
+{
+ struct svc_raw_private *srp;
+ XDR *xdrs;
+
+ mutex_lock(&svcraw_lock);
+ srp = svc_raw_private;
+ if (srp == NULL) {
+ mutex_unlock(&svcraw_lock);
+ return (FALSE);
+ }
+ mutex_unlock(&svcraw_lock);
+
+ xdrs = &srp->xdr_stream;
+ xdrs->x_op = XDR_FREE;
+ return (*xdr_args)(xdrs, args_ptr);
+}
+
+/*ARGSUSED*/
+static void
+svc_raw_destroy(xprt)
+SVCXPRT *xprt;
+{
+}
+
+/*ARGSUSED*/
+static bool_t
+svc_raw_control(xprt, rq, in)
+ SVCXPRT *xprt;
+ const u_int rq;
+ void *in;
+{
+ return (FALSE);
+}
+
+static void
+svc_raw_ops(xprt)
+ SVCXPRT *xprt;
+{
+ static struct xp_ops ops;
+ static struct xp_ops2 ops2;
+
+/* VARIABLES PROTECTED BY ops_lock: ops */
+
+ mutex_lock(&ops_lock);
+ if (ops.xp_recv == NULL) {
+ ops.xp_recv = svc_raw_recv;
+ ops.xp_stat = svc_raw_stat;
+ ops.xp_getargs = svc_raw_getargs;
+ ops.xp_reply = svc_raw_reply;
+ ops.xp_freeargs = svc_raw_freeargs;
+ ops.xp_destroy = svc_raw_destroy;
+ ops2.xp_control = svc_raw_control;
+ }
+ xprt->xp_ops = &ops;
+ xprt->xp_ops2 = &ops2;
+ mutex_unlock(&ops_lock);
+}
diff --git a/lib/libc/rpc/svc_run.c b/lib/libc/rpc/svc_run.c
new file mode 100644
index 0000000..b4627d6
--- /dev/null
+++ b/lib/libc/rpc/svc_run.c
@@ -0,0 +1,98 @@
+/* $NetBSD: svc_run.c,v 1.17 2000/07/06 03:10:35 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "from: @(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";
+static char *sccsid = "from: @(#)svc_run.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * This is the rpc server side idle loop
+ * Wait for input, call server program.
+ */
+#include "namespace.h"
+#include "reentrant.h"
+#include <err.h>
+#include <errno.h>
+#include <rpc/rpc.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include <rpc/rpc.h>
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+void
+svc_run()
+{
+ fd_set readfds, cleanfds;
+ struct timeval timeout;
+
+ timeout.tv_sec = 30;
+ timeout.tv_usec = 0;
+
+ for (;;) {
+ rwlock_rdlock(&svc_fd_lock);
+ readfds = svc_fdset;
+ cleanfds = svc_fdset;
+ rwlock_unlock(&svc_fd_lock);
+ switch (_select(svc_maxfd+1, &readfds, NULL, NULL, &timeout)) {
+ case -1:
+ FD_ZERO(&readfds);
+ if (errno == EINTR) {
+ continue;
+ }
+ _warn("svc_run: - select failed");
+ return;
+ case 0:
+ __svc_clean_idle(&cleanfds, 30, FALSE);
+ continue;
+ default:
+ svc_getreqset(&readfds);
+ }
+ }
+}
+
+/*
+ * This function causes svc_run() to exit by telling it that it has no
+ * more work to do.
+ */
+void
+svc_exit()
+{
+ rwlock_wrlock(&svc_fd_lock);
+ FD_ZERO(&svc_fdset);
+ rwlock_unlock(&svc_fd_lock);
+}
diff --git a/lib/libc/rpc/svc_simple.c b/lib/libc/rpc/svc_simple.c
new file mode 100644
index 0000000..cf00727
--- /dev/null
+++ b/lib/libc/rpc/svc_simple.c
@@ -0,0 +1,313 @@
+/* $NetBSD: svc_simple.c,v 1.20 2000/07/06 03:10:35 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1986-1991 by Sun Microsystems Inc.
+ */
+
+/* #pragma ident "@(#)svc_simple.c 1.18 94/04/24 SMI" */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc_simple.c
+ * Simplified front end to rpc.
+ */
+
+/*
+ * This interface creates a virtual listener for all the services
+ * started thru rpc_reg(). It listens on the same endpoint for
+ * all the services and then executes the corresponding service
+ * for the given prognum and procnum.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <rpc/rpc.h>
+#include <rpc/nettype.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <err.h>
+#include "un-namespace.h"
+
+#include "rpc_com.h"
+#include "mt_misc.h"
+
+static void universal(struct svc_req *, SVCXPRT *);
+
+static struct proglst {
+ char *(*p_progname)(char *);
+ rpcprog_t p_prognum;
+ rpcvers_t p_versnum;
+ rpcproc_t p_procnum;
+ SVCXPRT *p_transp;
+ char *p_netid;
+ char *p_xdrbuf;
+ int p_recvsz;
+ xdrproc_t p_inproc, p_outproc;
+ struct proglst *p_nxt;
+} *proglst;
+
+static const char rpc_reg_err[] = "%s: %s";
+static const char rpc_reg_msg[] = "rpc_reg: ";
+static const char __reg_err1[] = "can't find appropriate transport";
+static const char __reg_err2[] = "can't get protocol info";
+static const char __reg_err3[] = "unsupported transport size";
+static const char __no_mem_str[] = "out of memory";
+
+/*
+ * For simplified, easy to use kind of rpc interfaces.
+ * nettype indicates the type of transport on which the service will be
+ * listening. Used for conservation of the system resource. Only one
+ * handle is created for all the services (actually one of each netid)
+ * and same xdrbuf is used for same netid. The size of the arguments
+ * is also limited by the recvsize for that transport, even if it is
+ * a COTS transport. This may be wrong, but for cases like these, they
+ * should not use the simplified interfaces like this.
+ */
+
+int
+rpc_reg(prognum, versnum, procnum, progname, inproc, outproc, nettype)
+ rpcprog_t prognum; /* program number */
+ rpcvers_t versnum; /* version number */
+ rpcproc_t procnum; /* procedure number */
+ char *(*progname)(char *); /* Server routine */
+ xdrproc_t inproc, outproc; /* in/out XDR procedures */
+ char *nettype; /* nettype */
+{
+ struct netconfig *nconf;
+ int done = FALSE;
+ void *handle;
+
+
+ if (procnum == NULLPROC) {
+ warnx("%s can't reassign procedure number %u", rpc_reg_msg,
+ NULLPROC);
+ return (-1);
+ }
+
+ if (nettype == NULL)
+ nettype = "netpath"; /* The default behavior */
+ if ((handle = __rpc_setconf(nettype)) == NULL) {
+ warnx(rpc_reg_err, rpc_reg_msg, __reg_err1);
+ return (-1);
+ }
+/* VARIABLES PROTECTED BY proglst_lock: proglst */
+ mutex_lock(&proglst_lock);
+ while ((nconf = __rpc_getconf(handle)) != NULL) {
+ struct proglst *pl;
+ SVCXPRT *svcxprt;
+ int madenow;
+ u_int recvsz;
+ char *xdrbuf;
+ char *netid;
+
+ madenow = FALSE;
+ svcxprt = NULL;
+ recvsz = 0;
+ xdrbuf = netid = NULL;
+ for (pl = proglst; pl; pl = pl->p_nxt) {
+ if (strcmp(pl->p_netid, nconf->nc_netid) == 0) {
+ svcxprt = pl->p_transp;
+ xdrbuf = pl->p_xdrbuf;
+ recvsz = pl->p_recvsz;
+ netid = pl->p_netid;
+ break;
+ }
+ }
+
+ if (svcxprt == NULL) {
+ struct __rpc_sockinfo si;
+
+ svcxprt = svc_tli_create(RPC_ANYFD, nconf, NULL, 0, 0);
+ if (svcxprt == NULL)
+ continue;
+ if (!__rpc_fd2sockinfo(svcxprt->xp_fd, &si)) {
+ warnx(rpc_reg_err, rpc_reg_msg, __reg_err2);
+ SVC_DESTROY(svcxprt);
+ continue;
+ }
+ recvsz = __rpc_get_t_size(si.si_af, si.si_proto, 0);
+ if (recvsz == 0) {
+ warnx(rpc_reg_err, rpc_reg_msg, __reg_err3);
+ SVC_DESTROY(svcxprt);
+ continue;
+ }
+ if (((xdrbuf = malloc((unsigned)recvsz)) == NULL) ||
+ ((netid = strdup(nconf->nc_netid)) == NULL)) {
+ warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str);
+ if (xdrbuf != NULL)
+ free(xdrbuf);
+ if (netid != NULL)
+ free(netid);
+ SVC_DESTROY(svcxprt);
+ break;
+ }
+ madenow = TRUE;
+ }
+ /*
+ * Check if this (program, version, netid) had already been
+ * registered. The check may save a few RPC calls to rpcbind
+ */
+ for (pl = proglst; pl; pl = pl->p_nxt)
+ if ((pl->p_prognum == prognum) &&
+ (pl->p_versnum == versnum) &&
+ (strcmp(pl->p_netid, netid) == 0))
+ break;
+ if (pl == NULL) { /* Not yet */
+ (void) rpcb_unset(prognum, versnum, nconf);
+ } else {
+ /* so that svc_reg does not call rpcb_set() */
+ nconf = NULL;
+ }
+
+ if (!svc_reg(svcxprt, prognum, versnum, universal, nconf)) {
+ warnx("%s couldn't register prog %u vers %u for %s",
+ rpc_reg_msg, (unsigned)prognum,
+ (unsigned)versnum, netid);
+ if (madenow) {
+ SVC_DESTROY(svcxprt);
+ free(xdrbuf);
+ free(netid);
+ }
+ continue;
+ }
+
+ pl = malloc(sizeof (struct proglst));
+ if (pl == NULL) {
+ warnx(rpc_reg_err, rpc_reg_msg, __no_mem_str);
+ if (madenow) {
+ SVC_DESTROY(svcxprt);
+ free(xdrbuf);
+ free(netid);
+ }
+ break;
+ }
+ pl->p_progname = progname;
+ pl->p_prognum = prognum;
+ pl->p_versnum = versnum;
+ pl->p_procnum = procnum;
+ pl->p_inproc = inproc;
+ pl->p_outproc = outproc;
+ pl->p_transp = svcxprt;
+ pl->p_xdrbuf = xdrbuf;
+ pl->p_recvsz = recvsz;
+ pl->p_netid = netid;
+ pl->p_nxt = proglst;
+ proglst = pl;
+ done = TRUE;
+ }
+ __rpc_endconf(handle);
+ mutex_unlock(&proglst_lock);
+
+ if (done == FALSE) {
+ warnx("%s cant find suitable transport for %s",
+ rpc_reg_msg, nettype);
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * The universal handler for the services registered using registerrpc.
+ * It handles both the connectionless and the connection oriented cases.
+ */
+
+static void
+universal(rqstp, transp)
+ struct svc_req *rqstp;
+ SVCXPRT *transp;
+{
+ rpcprog_t prog;
+ rpcvers_t vers;
+ rpcproc_t proc;
+ char *outdata;
+ char *xdrbuf;
+ struct proglst *pl;
+
+ /*
+ * enforce "procnum 0 is echo" convention
+ */
+ if (rqstp->rq_proc == NULLPROC) {
+ if (svc_sendreply(transp, (xdrproc_t) xdr_void, NULL) ==
+ FALSE) {
+ warnx("svc_sendreply failed");
+ }
+ return;
+ }
+ prog = rqstp->rq_prog;
+ vers = rqstp->rq_vers;
+ proc = rqstp->rq_proc;
+ mutex_lock(&proglst_lock);
+ for (pl = proglst; pl; pl = pl->p_nxt)
+ if (pl->p_prognum == prog && pl->p_procnum == proc &&
+ pl->p_versnum == vers &&
+ (strcmp(pl->p_netid, transp->xp_netid) == 0)) {
+ /* decode arguments into a CLEAN buffer */
+ xdrbuf = pl->p_xdrbuf;
+ /* Zero the arguments: reqd ! */
+ (void) memset(xdrbuf, 0, sizeof (pl->p_recvsz));
+ /*
+ * Assuming that sizeof (xdrbuf) would be enough
+ * for the arguments; if not then the program
+ * may bomb. BEWARE!
+ */
+ if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) {
+ svcerr_decode(transp);
+ mutex_unlock(&proglst_lock);
+ return;
+ }
+ outdata = (*(pl->p_progname))(xdrbuf);
+ if (outdata == NULL &&
+ pl->p_outproc != (xdrproc_t) xdr_void){
+ /* there was an error */
+ mutex_unlock(&proglst_lock);
+ return;
+ }
+ if (!svc_sendreply(transp, pl->p_outproc, outdata)) {
+ warnx(
+ "rpc: rpc_reg trouble replying to prog %u vers %u",
+ (unsigned)prog, (unsigned)vers);
+ mutex_unlock(&proglst_lock);
+ return;
+ }
+ /* free the decoded arguments */
+ (void)svc_freeargs(transp, pl->p_inproc, xdrbuf);
+ mutex_unlock(&proglst_lock);
+ return;
+ }
+ mutex_unlock(&proglst_lock);
+ /* This should never happen */
+ warnx("rpc: rpc_reg: never registered prog %u vers %u",
+ (unsigned)prog, (unsigned)vers);
+ return;
+}
diff --git a/lib/libc/rpc/svc_vc.c b/lib/libc/rpc/svc_vc.c
new file mode 100644
index 0000000..aded6b1
--- /dev/null
+++ b/lib/libc/rpc/svc_vc.c
@@ -0,0 +1,811 @@
+/* $NetBSD: svc_vc.c,v 1.7 2000/08/03 00:01:53 fvdl Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)svc_tcp.c 2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * svc_vc.c, Server side for Connection Oriented based RPC.
+ *
+ * Actually implements two flavors of transporter -
+ * a tcp rendezvouser (a listner and connection establisher)
+ * and a record/tcp stream.
+ */
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/poll.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <assert.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rpc/rpc.h>
+
+#include "rpc_com.h"
+#include "mt_misc.h"
+#include "un-namespace.h"
+
+static SVCXPRT *makefd_xprt(int, u_int, u_int);
+static bool_t rendezvous_request(SVCXPRT *, struct rpc_msg *);
+static enum xprt_stat rendezvous_stat(SVCXPRT *);
+static void svc_vc_destroy(SVCXPRT *);
+static void __svc_vc_dodestroy (SVCXPRT *);
+static int read_vc(void *, void *, int);
+static int write_vc(void *, void *, int);
+static enum xprt_stat svc_vc_stat(SVCXPRT *);
+static bool_t svc_vc_recv(SVCXPRT *, struct rpc_msg *);
+static bool_t svc_vc_getargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t svc_vc_freeargs(SVCXPRT *, xdrproc_t, void *);
+static bool_t svc_vc_reply(SVCXPRT *, struct rpc_msg *);
+static void svc_vc_rendezvous_ops(SVCXPRT *);
+static void svc_vc_ops(SVCXPRT *);
+static bool_t svc_vc_control(SVCXPRT *xprt, const u_int rq, void *in);
+static bool_t svc_vc_rendezvous_control (SVCXPRT *xprt, const u_int rq,
+ void *in);
+
+struct cf_rendezvous { /* kept in xprt->xp_p1 for rendezvouser */
+ u_int sendsize;
+ u_int recvsize;
+ int maxrec;
+};
+
+struct cf_conn { /* kept in xprt->xp_p1 for actual connection */
+ enum xprt_stat strm_stat;
+ u_int32_t x_id;
+ XDR xdrs;
+ char verf_body[MAX_AUTH_BYTES];
+ u_int sendsize;
+ u_int recvsize;
+ int maxrec;
+ bool_t nonblock;
+ struct timeval last_recv_time;
+};
+
+/*
+ * Usage:
+ * xprt = svc_vc_create(sock, send_buf_size, recv_buf_size);
+ *
+ * Creates, registers, and returns a (rpc) tcp based transporter.
+ * Once *xprt is initialized, it is registered as a transporter
+ * see (svc.h, xprt_register). This routine returns
+ * a NULL if a problem occurred.
+ *
+ * The filedescriptor passed in is expected to refer to a bound, but
+ * not yet connected socket.
+ *
+ * Since streams do buffered io similar to stdio, the caller can specify
+ * how big the send and receive buffers are via the second and third parms;
+ * 0 => use the system default.
+ */
+SVCXPRT *
+svc_vc_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+ SVCXPRT *xprt;
+ struct cf_rendezvous *r = NULL;
+ struct __rpc_sockinfo si;
+ struct sockaddr_storage sslocal;
+ socklen_t slen;
+
+ if (!__rpc_fd2sockinfo(fd, &si))
+ return NULL;
+
+ r = mem_alloc(sizeof(*r));
+ if (r == NULL) {
+ warnx("svc_vc_create: out of memory");
+ goto cleanup_svc_vc_create;
+ }
+ r->sendsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)sendsize);
+ r->recvsize = __rpc_get_t_size(si.si_af, si.si_proto, (int)recvsize);
+ r->maxrec = __svc_maxrec;
+ xprt = svc_xprt_alloc();
+ if (xprt == NULL) {
+ warnx("svc_vc_create: out of memory");
+ goto cleanup_svc_vc_create;
+ }
+ xprt->xp_p1 = r;
+ xprt->xp_verf = _null_auth;
+ svc_vc_rendezvous_ops(xprt);
+ xprt->xp_port = (u_short)-1; /* It is the rendezvouser */
+ xprt->xp_fd = fd;
+
+ slen = sizeof (struct sockaddr_storage);
+ if (_getsockname(fd, (struct sockaddr *)(void *)&sslocal, &slen) < 0) {
+ warnx("svc_vc_create: could not retrieve local addr");
+ goto cleanup_svc_vc_create;
+ }
+
+ xprt->xp_ltaddr.maxlen = xprt->xp_ltaddr.len = sslocal.ss_len;
+ xprt->xp_ltaddr.buf = mem_alloc((size_t)sslocal.ss_len);
+ if (xprt->xp_ltaddr.buf == NULL) {
+ warnx("svc_vc_create: no mem for local addr");
+ goto cleanup_svc_vc_create;
+ }
+ memcpy(xprt->xp_ltaddr.buf, &sslocal, (size_t)sslocal.ss_len);
+
+ xprt->xp_rtaddr.maxlen = sizeof (struct sockaddr_storage);
+ xprt_register(xprt);
+ return (xprt);
+cleanup_svc_vc_create:
+ if (xprt)
+ mem_free(xprt, sizeof(*xprt));
+ if (r != NULL)
+ mem_free(r, sizeof(*r));
+ return (NULL);
+}
+
+/*
+ * Like svtcp_create(), except the routine takes any *open* UNIX file
+ * descriptor as its first input.
+ */
+SVCXPRT *
+svc_fd_create(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+ struct sockaddr_storage ss;
+ socklen_t slen;
+ SVCXPRT *ret;
+
+ assert(fd != -1);
+
+ ret = makefd_xprt(fd, sendsize, recvsize);
+ if (ret == NULL)
+ return NULL;
+
+ slen = sizeof (struct sockaddr_storage);
+ if (_getsockname(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
+ warnx("svc_fd_create: could not retrieve local addr");
+ goto freedata;
+ }
+ ret->xp_ltaddr.maxlen = ret->xp_ltaddr.len = ss.ss_len;
+ ret->xp_ltaddr.buf = mem_alloc((size_t)ss.ss_len);
+ if (ret->xp_ltaddr.buf == NULL) {
+ warnx("svc_fd_create: no mem for local addr");
+ goto freedata;
+ }
+ memcpy(ret->xp_ltaddr.buf, &ss, (size_t)ss.ss_len);
+
+ slen = sizeof (struct sockaddr_storage);
+ if (_getpeername(fd, (struct sockaddr *)(void *)&ss, &slen) < 0) {
+ warnx("svc_fd_create: could not retrieve remote addr");
+ goto freedata;
+ }
+ ret->xp_rtaddr.maxlen = ret->xp_rtaddr.len = ss.ss_len;
+ ret->xp_rtaddr.buf = mem_alloc((size_t)ss.ss_len);
+ if (ret->xp_rtaddr.buf == NULL) {
+ warnx("svc_fd_create: no mem for local addr");
+ goto freedata;
+ }
+ memcpy(ret->xp_rtaddr.buf, &ss, (size_t)ss.ss_len);
+#ifdef PORTMAP
+ if (ss.ss_family == AF_INET || ss.ss_family == AF_LOCAL) {
+ ret->xp_raddr = *(struct sockaddr_in *)ret->xp_rtaddr.buf;
+ ret->xp_addrlen = sizeof (struct sockaddr_in);
+ }
+#endif /* PORTMAP */
+
+ return ret;
+
+freedata:
+ if (ret->xp_ltaddr.buf != NULL)
+ mem_free(ret->xp_ltaddr.buf, rep->xp_ltaddr.maxlen);
+
+ return NULL;
+}
+
+static SVCXPRT *
+makefd_xprt(fd, sendsize, recvsize)
+ int fd;
+ u_int sendsize;
+ u_int recvsize;
+{
+ SVCXPRT *xprt;
+ struct cf_conn *cd;
+ const char *netid;
+ struct __rpc_sockinfo si;
+
+ assert(fd != -1);
+
+ xprt = svc_xprt_alloc();
+ if (xprt == NULL) {
+ warnx("svc_vc: makefd_xprt: out of memory");
+ goto done;
+ }
+ cd = mem_alloc(sizeof(struct cf_conn));
+ if (cd == NULL) {
+ warnx("svc_tcp: makefd_xprt: out of memory");
+ svc_xprt_free(xprt);
+ xprt = NULL;
+ goto done;
+ }
+ cd->strm_stat = XPRT_IDLE;
+ xdrrec_create(&(cd->xdrs), sendsize, recvsize,
+ xprt, read_vc, write_vc);
+ xprt->xp_p1 = cd;
+ xprt->xp_verf.oa_base = cd->verf_body;
+ svc_vc_ops(xprt); /* truely deals with calls */
+ xprt->xp_port = 0; /* this is a connection, not a rendezvouser */
+ xprt->xp_fd = fd;
+ if (__rpc_fd2sockinfo(fd, &si) && __rpc_sockinfo2netid(&si, &netid))
+ xprt->xp_netid = strdup(netid);
+
+ xprt_register(xprt);
+done:
+ return (xprt);
+}
+
+/*ARGSUSED*/
+static bool_t
+rendezvous_request(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ int sock, flags;
+ struct cf_rendezvous *r;
+ struct cf_conn *cd;
+ struct sockaddr_storage addr;
+ socklen_t len;
+ struct __rpc_sockinfo si;
+ SVCXPRT *newxprt;
+ fd_set cleanfds;
+
+ assert(xprt != NULL);
+ assert(msg != NULL);
+
+ r = (struct cf_rendezvous *)xprt->xp_p1;
+again:
+ len = sizeof addr;
+ if ((sock = _accept(xprt->xp_fd, (struct sockaddr *)(void *)&addr,
+ &len)) < 0) {
+ if (errno == EINTR)
+ goto again;
+ /*
+ * Clean out the most idle file descriptor when we're
+ * running out.
+ */
+ if (errno == EMFILE || errno == ENFILE) {
+ cleanfds = svc_fdset;
+ __svc_clean_idle(&cleanfds, 0, FALSE);
+ goto again;
+ }
+ return (FALSE);
+ }
+ /*
+ * make a new transporter (re-uses xprt)
+ */
+ newxprt = makefd_xprt(sock, r->sendsize, r->recvsize);
+ newxprt->xp_rtaddr.buf = mem_alloc(len);
+ if (newxprt->xp_rtaddr.buf == NULL)
+ return (FALSE);
+ memcpy(newxprt->xp_rtaddr.buf, &addr, len);
+ newxprt->xp_rtaddr.len = len;
+#ifdef PORTMAP
+ if (addr.ss_family == AF_INET || addr.ss_family == AF_LOCAL) {
+ newxprt->xp_raddr = *(struct sockaddr_in *)newxprt->xp_rtaddr.buf;
+ newxprt->xp_addrlen = sizeof (struct sockaddr_in);
+ }
+#endif /* PORTMAP */
+ if (__rpc_fd2sockinfo(sock, &si) && si.si_proto == IPPROTO_TCP) {
+ len = 1;
+ /* XXX fvdl - is this useful? */
+ _setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, &len, sizeof (len));
+ }
+
+ cd = (struct cf_conn *)newxprt->xp_p1;
+
+ cd->recvsize = r->recvsize;
+ cd->sendsize = r->sendsize;
+ cd->maxrec = r->maxrec;
+
+ if (cd->maxrec != 0) {
+ flags = _fcntl(sock, F_GETFL, 0);
+ if (flags == -1)
+ return (FALSE);
+ if (_fcntl(sock, F_SETFL, flags | O_NONBLOCK) == -1)
+ return (FALSE);
+ if (cd->recvsize > cd->maxrec)
+ cd->recvsize = cd->maxrec;
+ cd->nonblock = TRUE;
+ __xdrrec_setnonblock(&cd->xdrs, cd->maxrec);
+ } else
+ cd->nonblock = FALSE;
+
+ gettimeofday(&cd->last_recv_time, NULL);
+
+ return (FALSE); /* there is never an rpc msg to be processed */
+}
+
+/*ARGSUSED*/
+static enum xprt_stat
+rendezvous_stat(xprt)
+ SVCXPRT *xprt;
+{
+
+ return (XPRT_IDLE);
+}
+
+static void
+svc_vc_destroy(xprt)
+ SVCXPRT *xprt;
+{
+ assert(xprt != NULL);
+
+ xprt_unregister(xprt);
+ __svc_vc_dodestroy(xprt);
+}
+
+static void
+__svc_vc_dodestroy(xprt)
+ SVCXPRT *xprt;
+{
+ struct cf_conn *cd;
+ struct cf_rendezvous *r;
+
+ cd = (struct cf_conn *)xprt->xp_p1;
+
+ if (xprt->xp_fd != RPC_ANYFD)
+ (void)_close(xprt->xp_fd);
+ if (xprt->xp_port != 0) {
+ /* a rendezvouser socket */
+ r = (struct cf_rendezvous *)xprt->xp_p1;
+ mem_free(r, sizeof (struct cf_rendezvous));
+ xprt->xp_port = 0;
+ } else {
+ /* an actual connection socket */
+ XDR_DESTROY(&(cd->xdrs));
+ mem_free(cd, sizeof(struct cf_conn));
+ }
+ if (xprt->xp_rtaddr.buf)
+ mem_free(xprt->xp_rtaddr.buf, xprt->xp_rtaddr.maxlen);
+ if (xprt->xp_ltaddr.buf)
+ mem_free(xprt->xp_ltaddr.buf, xprt->xp_ltaddr.maxlen);
+ if (xprt->xp_tp)
+ free(xprt->xp_tp);
+ if (xprt->xp_netid)
+ free(xprt->xp_netid);
+ svc_xprt_free(xprt);
+}
+
+/*ARGSUSED*/
+static bool_t
+svc_vc_control(xprt, rq, in)
+ SVCXPRT *xprt;
+ const u_int rq;
+ void *in;
+{
+ return (FALSE);
+}
+
+static bool_t
+svc_vc_rendezvous_control(xprt, rq, in)
+ SVCXPRT *xprt;
+ const u_int rq;
+ void *in;
+{
+ struct cf_rendezvous *cfp;
+
+ cfp = (struct cf_rendezvous *)xprt->xp_p1;
+ if (cfp == NULL)
+ return (FALSE);
+ switch (rq) {
+ case SVCGET_CONNMAXREC:
+ *(int *)in = cfp->maxrec;
+ break;
+ case SVCSET_CONNMAXREC:
+ cfp->maxrec = *(int *)in;
+ break;
+ default:
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+/*
+ * reads data from the tcp or uip connection.
+ * any error is fatal and the connection is closed.
+ * (And a read of zero bytes is a half closed stream => error.)
+ * All read operations timeout after 35 seconds. A timeout is
+ * fatal for the connection.
+ */
+static int
+read_vc(xprtp, buf, len)
+ void *xprtp;
+ void *buf;
+ int len;
+{
+ SVCXPRT *xprt;
+ int sock;
+ int milliseconds = 35 * 1000;
+ struct pollfd pollfd;
+ struct cf_conn *cfp;
+
+ xprt = (SVCXPRT *)xprtp;
+ assert(xprt != NULL);
+
+ sock = xprt->xp_fd;
+
+ cfp = (struct cf_conn *)xprt->xp_p1;
+
+ if (cfp->nonblock) {
+ len = _read(sock, buf, (size_t)len);
+ if (len < 0) {
+ if (errno == EAGAIN)
+ len = 0;
+ else
+ goto fatal_err;
+ }
+ if (len != 0)
+ gettimeofday(&cfp->last_recv_time, NULL);
+ return len;
+ }
+
+ do {
+ pollfd.fd = sock;
+ pollfd.events = POLLIN;
+ pollfd.revents = 0;
+ switch (_poll(&pollfd, 1, milliseconds)) {
+ case -1:
+ if (errno == EINTR)
+ continue;
+ /*FALLTHROUGH*/
+ case 0:
+ goto fatal_err;
+
+ default:
+ break;
+ }
+ } while ((pollfd.revents & POLLIN) == 0);
+
+ if ((len = _read(sock, buf, (size_t)len)) > 0) {
+ gettimeofday(&cfp->last_recv_time, NULL);
+ return (len);
+ }
+
+fatal_err:
+ ((struct cf_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED;
+ return (-1);
+}
+
+/*
+ * writes data to the tcp connection.
+ * Any error is fatal and the connection is closed.
+ */
+static int
+write_vc(xprtp, buf, len)
+ void *xprtp;
+ void *buf;
+ int len;
+{
+ SVCXPRT *xprt;
+ int i, cnt;
+ struct cf_conn *cd;
+ struct timeval tv0, tv1;
+
+ xprt = (SVCXPRT *)xprtp;
+ assert(xprt != NULL);
+
+ cd = (struct cf_conn *)xprt->xp_p1;
+
+ if (cd->nonblock)
+ gettimeofday(&tv0, NULL);
+
+ for (cnt = len; cnt > 0; cnt -= i, buf = (char *)buf + i) {
+ i = _write(xprt->xp_fd, buf, (size_t)cnt);
+ if (i < 0) {
+ if (errno != EAGAIN || !cd->nonblock) {
+ cd->strm_stat = XPRT_DIED;
+ return (-1);
+ }
+ if (cd->nonblock) {
+ /*
+ * For non-blocking connections, do not
+ * take more than 2 seconds writing the
+ * data out.
+ *
+ * XXX 2 is an arbitrary amount.
+ */
+ gettimeofday(&tv1, NULL);
+ if (tv1.tv_sec - tv0.tv_sec >= 2) {
+ cd->strm_stat = XPRT_DIED;
+ return (-1);
+ }
+ }
+ i = 0;
+ }
+ }
+
+ return (len);
+}
+
+static enum xprt_stat
+svc_vc_stat(xprt)
+ SVCXPRT *xprt;
+{
+ struct cf_conn *cd;
+
+ assert(xprt != NULL);
+
+ cd = (struct cf_conn *)(xprt->xp_p1);
+
+ if (cd->strm_stat == XPRT_DIED)
+ return (XPRT_DIED);
+ if (! xdrrec_eof(&(cd->xdrs)))
+ return (XPRT_MOREREQS);
+ return (XPRT_IDLE);
+}
+
+static bool_t
+svc_vc_recv(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ struct cf_conn *cd;
+ XDR *xdrs;
+
+ assert(xprt != NULL);
+ assert(msg != NULL);
+
+ cd = (struct cf_conn *)(xprt->xp_p1);
+ xdrs = &(cd->xdrs);
+
+ if (cd->nonblock) {
+ if (!__xdrrec_getrec(xdrs, &cd->strm_stat, TRUE))
+ return FALSE;
+ } else {
+ (void)xdrrec_skiprecord(xdrs);
+ }
+
+ xdrs->x_op = XDR_DECODE;
+ if (xdr_callmsg(xdrs, msg)) {
+ cd->x_id = msg->rm_xid;
+ return (TRUE);
+ }
+ cd->strm_stat = XPRT_DIED;
+ return (FALSE);
+}
+
+static bool_t
+svc_vc_getargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ void *args_ptr;
+{
+ struct cf_conn *cd;
+
+ assert(xprt != NULL);
+ cd = (struct cf_conn *)(xprt->xp_p1);
+ return (SVCAUTH_UNWRAP(&SVC_AUTH(xprt),
+ &cd->xdrs, xdr_args, args_ptr));
+}
+
+static bool_t
+svc_vc_freeargs(xprt, xdr_args, args_ptr)
+ SVCXPRT *xprt;
+ xdrproc_t xdr_args;
+ void *args_ptr;
+{
+ XDR *xdrs;
+
+ assert(xprt != NULL);
+ /* args_ptr may be NULL */
+
+ xdrs = &(((struct cf_conn *)(xprt->xp_p1))->xdrs);
+
+ xdrs->x_op = XDR_FREE;
+ return ((*xdr_args)(xdrs, args_ptr));
+}
+
+static bool_t
+svc_vc_reply(xprt, msg)
+ SVCXPRT *xprt;
+ struct rpc_msg *msg;
+{
+ struct cf_conn *cd;
+ XDR *xdrs;
+ bool_t rstat;
+ xdrproc_t xdr_proc;
+ caddr_t xdr_where;
+ u_int pos;
+
+ assert(xprt != NULL);
+ assert(msg != NULL);
+
+ cd = (struct cf_conn *)(xprt->xp_p1);
+ xdrs = &(cd->xdrs);
+
+ xdrs->x_op = XDR_ENCODE;
+ msg->rm_xid = cd->x_id;
+ rstat = TRUE;
+ if (msg->rm_reply.rp_stat == MSG_ACCEPTED &&
+ msg->rm_reply.rp_acpt.ar_stat == SUCCESS) {
+ xdr_proc = msg->acpted_rply.ar_results.proc;
+ xdr_where = msg->acpted_rply.ar_results.where;
+ msg->acpted_rply.ar_results.proc = (xdrproc_t) xdr_void;
+ msg->acpted_rply.ar_results.where = NULL;
+
+ pos = XDR_GETPOS(xdrs);
+ if (!xdr_replymsg(xdrs, msg) ||
+ !SVCAUTH_WRAP(&SVC_AUTH(xprt), xdrs, xdr_proc, xdr_where)) {
+ XDR_SETPOS(xdrs, pos);
+ rstat = FALSE;
+ }
+ } else {
+ rstat = xdr_replymsg(xdrs, msg);
+ }
+
+ if (rstat)
+ (void)xdrrec_endofrecord(xdrs, TRUE);
+
+ return (rstat);
+}
+
+static void
+svc_vc_ops(xprt)
+ SVCXPRT *xprt;
+{
+ static struct xp_ops ops;
+ static struct xp_ops2 ops2;
+
+/* VARIABLES PROTECTED BY ops_lock: ops, ops2 */
+
+ mutex_lock(&ops_lock);
+ if (ops.xp_recv == NULL) {
+ ops.xp_recv = svc_vc_recv;
+ ops.xp_stat = svc_vc_stat;
+ ops.xp_getargs = svc_vc_getargs;
+ ops.xp_reply = svc_vc_reply;
+ ops.xp_freeargs = svc_vc_freeargs;
+ ops.xp_destroy = svc_vc_destroy;
+ ops2.xp_control = svc_vc_control;
+ }
+ xprt->xp_ops = &ops;
+ xprt->xp_ops2 = &ops2;
+ mutex_unlock(&ops_lock);
+}
+
+static void
+svc_vc_rendezvous_ops(xprt)
+ SVCXPRT *xprt;
+{
+ static struct xp_ops ops;
+ static struct xp_ops2 ops2;
+
+ mutex_lock(&ops_lock);
+ if (ops.xp_recv == NULL) {
+ ops.xp_recv = rendezvous_request;
+ ops.xp_stat = rendezvous_stat;
+ ops.xp_getargs =
+ (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort;
+ ops.xp_reply =
+ (bool_t (*)(SVCXPRT *, struct rpc_msg *))abort;
+ ops.xp_freeargs =
+ (bool_t (*)(SVCXPRT *, xdrproc_t, void *))abort,
+ ops.xp_destroy = svc_vc_destroy;
+ ops2.xp_control = svc_vc_rendezvous_control;
+ }
+ xprt->xp_ops = &ops;
+ xprt->xp_ops2 = &ops2;
+ mutex_unlock(&ops_lock);
+}
+
+/*
+ * Get the effective UID of the sending process. Used by rpcbind, keyserv
+ * and rpc.yppasswdd on AF_LOCAL.
+ */
+int
+__rpc_get_local_uid(SVCXPRT *transp, uid_t *uid) {
+ int sock, ret;
+ gid_t egid;
+ uid_t euid;
+ struct sockaddr *sa;
+
+ sock = transp->xp_fd;
+ sa = (struct sockaddr *)transp->xp_rtaddr.buf;
+ if (sa->sa_family == AF_LOCAL) {
+ ret = getpeereid(sock, &euid, &egid);
+ if (ret == 0)
+ *uid = euid;
+ return (ret);
+ } else
+ return (-1);
+}
+
+/*
+ * Destroy xprts that have not have had any activity in 'timeout' seconds.
+ * If 'cleanblock' is true, blocking connections (the default) are also
+ * cleaned. If timeout is 0, the least active connection is picked.
+ */
+bool_t
+__svc_clean_idle(fd_set *fds, int timeout, bool_t cleanblock)
+{
+ int i, ncleaned;
+ SVCXPRT *xprt, *least_active;
+ struct timeval tv, tdiff, tmax;
+ struct cf_conn *cd;
+
+ gettimeofday(&tv, NULL);
+ tmax.tv_sec = tmax.tv_usec = 0;
+ least_active = NULL;
+ rwlock_wrlock(&svc_fd_lock);
+ for (i = ncleaned = 0; i <= svc_maxfd; i++) {
+ if (FD_ISSET(i, fds)) {
+ xprt = __svc_xports[i];
+ if (xprt == NULL || xprt->xp_ops == NULL ||
+ xprt->xp_ops->xp_recv != svc_vc_recv)
+ continue;
+ cd = (struct cf_conn *)xprt->xp_p1;
+ if (!cleanblock && !cd->nonblock)
+ continue;
+ if (timeout == 0) {
+ timersub(&tv, &cd->last_recv_time, &tdiff);
+ if (timercmp(&tdiff, &tmax, >)) {
+ tmax = tdiff;
+ least_active = xprt;
+ }
+ continue;
+ }
+ if (tv.tv_sec - cd->last_recv_time.tv_sec > timeout) {
+ __xprt_unregister_unlocked(xprt);
+ __svc_vc_dodestroy(xprt);
+ ncleaned++;
+ }
+ }
+ }
+ if (timeout == 0 && least_active != NULL) {
+ __xprt_unregister_unlocked(least_active);
+ __svc_vc_dodestroy(least_active);
+ ncleaned++;
+ }
+ rwlock_unlock(&svc_fd_lock);
+ return ncleaned > 0 ? TRUE : FALSE;
+}
diff --git a/lib/libc/softfloat/Makefile.inc b/lib/libc/softfloat/Makefile.inc
new file mode 100644
index 0000000..2213403
--- /dev/null
+++ b/lib/libc/softfloat/Makefile.inc
@@ -0,0 +1,30 @@
+# $NetBSD: Makefile.inc,v 1.10 2011/07/04 02:53:15 mrg Exp $
+# $FreeBSD$
+
+SOFTFLOAT_BITS?=64
+.PATH: ${LIBC_ARCH}/softfloat \
+ ${.CURDIR}/softfloat/bits${SOFTFLOAT_BITS} ${.CURDIR}/softfloat
+
+CFLAGS+= -I${.CURDIR}/${LIBC_ARCH}/softfloat -I${.CURDIR}/softfloat
+CFLAGS+= -DSOFTFLOAT_FOR_GCC
+
+SRCS+= softfloat.c
+
+SRCS+= fpgetround.c fpsetround.c fpgetmask.c fpsetmask.c \
+ fpgetsticky.c
+
+SRCS+= eqsf2.c nesf2.c gtsf2.c gesf2.c ltsf2.c lesf2.c negsf2.c \
+ eqdf2.c nedf2.c gtdf2.c gedf2.c ltdf2.c ledf2.c negdf2.c \
+ unordsf2.c unorddf2.c
+
+.if defined(SOFTFLOAT_128)
+CFLAGS+= -DFLOAT128
+SRCS+= eqtf2.c netf2.c gttf2.c getf2.c lttf2.c letf2.c negtf2.c
+.endif
+
+.if defined(SOFTFLOAT_X80)
+CFLAGS+= -DFLOATX80
+SRCS+= nexf2.c gtxf2.c gexf2.c negxf2.c
+.endif
+
+SYM_MAPS+= ${.CURDIR}/softfloat/Symbol.map
diff --git a/lib/libc/softfloat/README.NetBSD b/lib/libc/softfloat/README.NetBSD
new file mode 100644
index 0000000..c6ca7a8
--- /dev/null
+++ b/lib/libc/softfloat/README.NetBSD
@@ -0,0 +1,9 @@
+$NetBSD: README.NetBSD,v 1.2 2002/05/21 23:51:05 bjh21 Exp $
+$FreeBSD$
+
+This is a modified version of part of John Hauser's SoftFloat 2a package.
+This version has been heavily modified to support its use with GCC to
+implement built-in floating-point operations, but compiling
+softfloat.c without SOFTFLOAT_FOR_GCC defined should get you the same
+results as from the original.
+
diff --git a/lib/libc/softfloat/README.txt b/lib/libc/softfloat/README.txt
new file mode 100644
index 0000000..fe28ccc
--- /dev/null
+++ b/lib/libc/softfloat/README.txt
@@ -0,0 +1,40 @@
+$NetBSD: README.txt,v 1.1 2000/06/06 08:15:02 bjh21 Exp $
+$FreeBSD$
+
+Package Overview for SoftFloat Release 2a
+
+John R. Hauser
+1998 December 13
+
+
+SoftFloat is a software implementation of floating-point that conforms to
+the IEC/IEEE Standard for Binary Floating-Point Arithmetic. SoftFloat is
+distributed in the form of C source code. Compiling the SoftFloat sources
+generates two things:
+
+-- A SoftFloat object file (typically `softfloat.o') containing the complete
+ set of IEC/IEEE floating-point routines.
+
+-- A `timesoftfloat' program for evaluating the speed of the SoftFloat
+ routines. (The SoftFloat module is linked into this program.)
+
+The SoftFloat package is documented in four text files:
+
+ softfloat.txt Documentation for using the SoftFloat functions.
+ softfloat-source.txt Documentation for compiling SoftFloat.
+ softfloat-history.txt History of major changes to SoftFloat.
+ timesoftfloat.txt Documentation for using `timesoftfloat'.
+
+Other files in the package comprise the source code for SoftFloat.
+
+Please be aware that some work is involved in porting this software to other
+targets. It is not just a matter of getting `make' to complete without
+error messages. I would have written the code that way if I could, but
+there are fundamental differences between systems that I can't make go away.
+You should not attempt to compile SoftFloat without first reading both
+`softfloat.txt' and `softfloat-source.txt'.
+
+At the time of this writing, the most up-to-date information about
+SoftFloat and the latest release can be found at the Web page `http://
+HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/SoftFloat.html'.
+
diff --git a/lib/libc/softfloat/Symbol.map b/lib/libc/softfloat/Symbol.map
new file mode 100644
index 0000000..9c9662a
--- /dev/null
+++ b/lib/libc/softfloat/Symbol.map
@@ -0,0 +1,41 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ _fpgetmask;
+ fpgetmask;
+ _fpgetround;
+ fpgetround;
+ _fpgetsticky;
+ fpgetsticky;
+ _fpsetmask;
+ fpsetmask;
+ _fpsetround;
+ fpsetround;
+ _fpsetsticky;
+ fpsetsticky;
+};
+
+FBSDprivate_1.0 {
+ __softfloat_float_exception_flags;
+ __softfloat_float_exception_mask;
+ __softfloat_float_rounding_mode;
+ __softfloat_float_raise;
+ __eqdf2;
+ __eqsf2;
+ __gedf2;
+ __gesf2;
+ __gtdf2;
+ __gtsf2;
+ __ledf2;
+ __lesf2;
+ __ltdf2;
+ __ltsf2;
+ __nedf2;
+ __negdf2;
+ __negsf2;
+ __nesf2;
+ __unorddf2;
+ __unordsf2;
+};
diff --git a/lib/libc/softfloat/bits32/softfloat-macros b/lib/libc/softfloat/bits32/softfloat-macros
new file mode 100644
index 0000000..db4e038
--- /dev/null
+++ b/lib/libc/softfloat/bits32/softfloat-macros
@@ -0,0 +1,649 @@
+/* $FreeBSD$ */
+
+/*
+===============================================================================
+
+This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+Shifts `a' right by the number of bits given in `count'. If any nonzero
+bits are shifted off, they are ``jammed'' into the least significant bit of
+the result by setting the least significant bit to 1. The value of `count'
+can be arbitrarily large; in particular, if `count' is greater than 32, the
+result will be either 0 or 1, depending on whether `a' is zero or nonzero.
+The result is stored in the location pointed to by `zPtr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
+{
+ bits32 z;
+
+ if ( count == 0 ) {
+ z = a;
+ }
+ else if ( count < 32 ) {
+ z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 );
+ }
+ else {
+ z = ( a != 0 );
+ }
+ *zPtr = z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
+number of bits given in `count'. Any bits shifted off are lost. The value
+of `count' can be arbitrarily large; in particular, if `count' is greater
+than 64, the result will be 0. The result is broken into two 32-bit pieces
+which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shift64Right(
+ bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
+{
+ bits32 z0, z1;
+ int8 negCount = ( - count ) & 31;
+
+ if ( count == 0 ) {
+ z1 = a1;
+ z0 = a0;
+ }
+ else if ( count < 32 ) {
+ z1 = ( a0<<negCount ) | ( a1>>count );
+ z0 = a0>>count;
+ }
+ else {
+ z1 = ( count < 64 ) ? ( a0>>( count & 31 ) ) : 0;
+ z0 = 0;
+ }
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 64-bit value formed by concatenating `a0' and `a1' right by the
+number of bits given in `count'. If any nonzero bits are shifted off, they
+are ``jammed'' into the least significant bit of the result by setting the
+least significant bit to 1. The value of `count' can be arbitrarily large;
+in particular, if `count' is greater than 64, the result will be either 0
+or 1, depending on whether the concatenation of `a0' and `a1' is zero or
+nonzero. The result is broken into two 32-bit pieces which are stored at
+the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shift64RightJamming(
+ bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
+{
+ bits32 z0, z1;
+ int8 negCount = ( - count ) & 31;
+
+ if ( count == 0 ) {
+ z1 = a1;
+ z0 = a0;
+ }
+ else if ( count < 32 ) {
+ z1 = ( a0<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 );
+ z0 = a0>>count;
+ }
+ else {
+ if ( count == 32 ) {
+ z1 = a0 | ( a1 != 0 );
+ }
+ else if ( count < 64 ) {
+ z1 = ( a0>>( count & 31 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 );
+ }
+ else {
+ z1 = ( ( a0 | a1 ) != 0 );
+ }
+ z0 = 0;
+ }
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' right
+by 32 _plus_ the number of bits given in `count'. The shifted result is
+at most 64 nonzero bits; these are broken into two 32-bit pieces which are
+stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
+off form a third 32-bit result as follows: The _last_ bit shifted off is
+the most-significant bit of the extra result, and the other 31 bits of the
+extra result are all zero if and only if _all_but_the_last_ bits shifted off
+were all zero. This extra result is stored in the location pointed to by
+`z2Ptr'. The value of `count' can be arbitrarily large.
+ (This routine makes more sense if `a0', `a1', and `a2' are considered
+to form a fixed-point value with binary point between `a1' and `a2'. This
+fixed-point value is shifted right by the number of bits given in `count',
+and the integer part of the result is returned at the locations pointed to
+by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
+corrupted as described above, and is returned at the location pointed to by
+`z2Ptr'.)
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shift64ExtraRightJamming(
+ bits32 a0,
+ bits32 a1,
+ bits32 a2,
+ int16 count,
+ bits32 *z0Ptr,
+ bits32 *z1Ptr,
+ bits32 *z2Ptr
+ )
+{
+ bits32 z0, z1, z2;
+ int8 negCount = ( - count ) & 31;
+
+ if ( count == 0 ) {
+ z2 = a2;
+ z1 = a1;
+ z0 = a0;
+ }
+ else {
+ if ( count < 32 ) {
+ z2 = a1<<negCount;
+ z1 = ( a0<<negCount ) | ( a1>>count );
+ z0 = a0>>count;
+ }
+ else {
+ if ( count == 32 ) {
+ z2 = a1;
+ z1 = a0;
+ }
+ else {
+ a2 |= a1;
+ if ( count < 64 ) {
+ z2 = a0<<negCount;
+ z1 = a0>>( count & 31 );
+ }
+ else {
+ z2 = ( count == 64 ) ? a0 : ( a0 != 0 );
+ z1 = 0;
+ }
+ }
+ z0 = 0;
+ }
+ z2 |= ( a2 != 0 );
+ }
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 64-bit value formed by concatenating `a0' and `a1' left by the
+number of bits given in `count'. Any bits shifted off are lost. The value
+of `count' must be less than 32. The result is broken into two 32-bit
+pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shortShift64Left(
+ bits32 a0, bits32 a1, int16 count, bits32 *z0Ptr, bits32 *z1Ptr )
+{
+
+ *z1Ptr = a1<<count;
+ *z0Ptr =
+ ( count == 0 ) ? a0 : ( a0<<count ) | ( a1>>( ( - count ) & 31 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 96-bit value formed by concatenating `a0', `a1', and `a2' left
+by the number of bits given in `count'. Any bits shifted off are lost.
+The value of `count' must be less than 32. The result is broken into three
+32-bit pieces which are stored at the locations pointed to by `z0Ptr',
+`z1Ptr', and `z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shortShift96Left(
+ bits32 a0,
+ bits32 a1,
+ bits32 a2,
+ int16 count,
+ bits32 *z0Ptr,
+ bits32 *z1Ptr,
+ bits32 *z2Ptr
+ )
+{
+ bits32 z0, z1, z2;
+ int8 negCount;
+
+ z2 = a2<<count;
+ z1 = a1<<count;
+ z0 = a0<<count;
+ if ( 0 < count ) {
+ negCount = ( ( - count ) & 31 );
+ z1 |= a2>>negCount;
+ z0 |= a1>>negCount;
+ }
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Adds the 64-bit value formed by concatenating `a0' and `a1' to the 64-bit
+value formed by concatenating `b0' and `b1'. Addition is modulo 2^64, so
+any carry out is lost. The result is broken into two 32-bit pieces which
+are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ add64(
+ bits32 a0, bits32 a1, bits32 b0, bits32 b1, bits32 *z0Ptr, bits32 *z1Ptr )
+{
+ bits32 z1;
+
+ z1 = a1 + b1;
+ *z1Ptr = z1;
+ *z0Ptr = a0 + b0 + ( z1 < a1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Adds the 96-bit value formed by concatenating `a0', `a1', and `a2' to the
+96-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
+modulo 2^96, so any carry out is lost. The result is broken into three
+32-bit pieces which are stored at the locations pointed to by `z0Ptr',
+`z1Ptr', and `z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ add96(
+ bits32 a0,
+ bits32 a1,
+ bits32 a2,
+ bits32 b0,
+ bits32 b1,
+ bits32 b2,
+ bits32 *z0Ptr,
+ bits32 *z1Ptr,
+ bits32 *z2Ptr
+ )
+{
+ bits32 z0, z1, z2;
+ int8 carry0, carry1;
+
+ z2 = a2 + b2;
+ carry1 = ( z2 < a2 );
+ z1 = a1 + b1;
+ carry0 = ( z1 < a1 );
+ z0 = a0 + b0;
+ z1 += carry1;
+ z0 += ( z1 < (bits32)carry1 );
+ z0 += carry0;
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Subtracts the 64-bit value formed by concatenating `b0' and `b1' from the
+64-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
+2^64, so any borrow out (carry out) is lost. The result is broken into two
+32-bit pieces which are stored at the locations pointed to by `z0Ptr' and
+`z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ sub64(
+ bits32 a0, bits32 a1, bits32 b0, bits32 b1, bits32 *z0Ptr, bits32 *z1Ptr )
+{
+
+ *z1Ptr = a1 - b1;
+ *z0Ptr = a0 - b0 - ( a1 < b1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Subtracts the 96-bit value formed by concatenating `b0', `b1', and `b2' from
+the 96-bit value formed by concatenating `a0', `a1', and `a2'. Subtraction
+is modulo 2^96, so any borrow out (carry out) is lost. The result is broken
+into three 32-bit pieces which are stored at the locations pointed to by
+`z0Ptr', `z1Ptr', and `z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ sub96(
+ bits32 a0,
+ bits32 a1,
+ bits32 a2,
+ bits32 b0,
+ bits32 b1,
+ bits32 b2,
+ bits32 *z0Ptr,
+ bits32 *z1Ptr,
+ bits32 *z2Ptr
+ )
+{
+ bits32 z0, z1, z2;
+ int8 borrow0, borrow1;
+
+ z2 = a2 - b2;
+ borrow1 = ( a2 < b2 );
+ z1 = a1 - b1;
+ borrow0 = ( a1 < b1 );
+ z0 = a0 - b0;
+ z0 -= ( z1 < (bits32)borrow1 );
+ z1 -= borrow1;
+ z0 -= borrow0;
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Multiplies `a' by `b' to obtain a 64-bit product. The product is broken
+into two 32-bit pieces which are stored at the locations pointed to by
+`z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void mul32To64( bits32 a, bits32 b, bits32 *z0Ptr, bits32 *z1Ptr )
+{
+ bits16 aHigh, aLow, bHigh, bLow;
+ bits32 z0, zMiddleA, zMiddleB, z1;
+
+ aLow = a;
+ aHigh = a>>16;
+ bLow = b;
+ bHigh = b>>16;
+ z1 = ( (bits32) aLow ) * bLow;
+ zMiddleA = ( (bits32) aLow ) * bHigh;
+ zMiddleB = ( (bits32) aHigh ) * bLow;
+ z0 = ( (bits32) aHigh ) * bHigh;
+ zMiddleA += zMiddleB;
+ z0 += ( ( (bits32) ( zMiddleA < zMiddleB ) )<<16 ) + ( zMiddleA>>16 );
+ zMiddleA <<= 16;
+ z1 += zMiddleA;
+ z0 += ( z1 < zMiddleA );
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Multiplies the 64-bit value formed by concatenating `a0' and `a1' by `b'
+to obtain a 96-bit product. The product is broken into three 32-bit pieces
+which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
+`z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ mul64By32To96(
+ bits32 a0,
+ bits32 a1,
+ bits32 b,
+ bits32 *z0Ptr,
+ bits32 *z1Ptr,
+ bits32 *z2Ptr
+ )
+{
+ bits32 z0, z1, z2, more1;
+
+ mul32To64( a1, b, &z1, &z2 );
+ mul32To64( a0, b, &z0, &more1 );
+ add64( z0, more1, 0, z1, &z0, &z1 );
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Multiplies the 64-bit value formed by concatenating `a0' and `a1' to the
+64-bit value formed by concatenating `b0' and `b1' to obtain a 128-bit
+product. The product is broken into four 32-bit pieces which are stored at
+the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ mul64To128(
+ bits32 a0,
+ bits32 a1,
+ bits32 b0,
+ bits32 b1,
+ bits32 *z0Ptr,
+ bits32 *z1Ptr,
+ bits32 *z2Ptr,
+ bits32 *z3Ptr
+ )
+{
+ bits32 z0, z1, z2, z3;
+ bits32 more1, more2;
+
+ mul32To64( a1, b1, &z2, &z3 );
+ mul32To64( a1, b0, &z1, &more2 );
+ add64( z1, more2, 0, z2, &z1, &z2 );
+ mul32To64( a0, b0, &z0, &more1 );
+ add64( z0, more1, 0, z1, &z0, &z1 );
+ mul32To64( a0, b1, &more1, &more2 );
+ add64( more1, more2, 0, z2, &more1, &z2 );
+ add64( z0, z1, 0, more1, &z0, &z1 );
+ *z3Ptr = z3;
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns an approximation to the 32-bit integer quotient obtained by dividing
+`b' into the 64-bit value formed by concatenating `a0' and `a1'. The
+divisor `b' must be at least 2^31. If q is the exact quotient truncated
+toward zero, the approximation returned lies between q and q + 2 inclusive.
+If the exact quotient q is larger than 32 bits, the maximum positive 32-bit
+unsigned integer is returned.
+-------------------------------------------------------------------------------
+*/
+static bits32 estimateDiv64To32( bits32 a0, bits32 a1, bits32 b )
+{
+ bits32 b0, b1;
+ bits32 rem0, rem1, term0, term1;
+ bits32 z;
+
+ if ( b <= a0 ) return 0xFFFFFFFF;
+ b0 = b>>16;
+ z = ( b0<<16 <= a0 ) ? 0xFFFF0000 : ( a0 / b0 )<<16;
+ mul32To64( b, z, &term0, &term1 );
+ sub64( a0, a1, term0, term1, &rem0, &rem1 );
+ while ( ( (sbits32) rem0 ) < 0 ) {
+ z -= 0x10000;
+ b1 = b<<16;
+ add64( rem0, rem1, b0, b1, &rem0, &rem1 );
+ }
+ rem0 = ( rem0<<16 ) | ( rem1>>16 );
+ z |= ( b0<<16 <= rem0 ) ? 0xFFFF : rem0 / b0;
+ return z;
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Returns an approximation to the square root of the 32-bit significand given
+by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
+`aExp' (the least significant bit) is 1, the integer returned approximates
+2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
+is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
+case, the approximation returned lies strictly within +/-2 of the exact
+value.
+-------------------------------------------------------------------------------
+*/
+static bits32 estimateSqrt32( int16 aExp, bits32 a )
+{
+ static const bits16 sqrtOddAdjustments[] = {
+ 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
+ 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
+ };
+ static const bits16 sqrtEvenAdjustments[] = {
+ 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
+ 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
+ };
+ int8 index;
+ bits32 z;
+
+ index = ( a>>27 ) & 15;
+ if ( aExp & 1 ) {
+ z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ index ];
+ z = ( ( a / z )<<14 ) + ( z<<15 );
+ a >>= 1;
+ }
+ else {
+ z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ index ];
+ z = a / z + z;
+ z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
+ if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );
+ }
+ return ( ( estimateDiv64To32( a, 0, z ) )>>1 ) + ( z>>1 );
+
+}
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns the number of leading 0 bits before the most-significant 1 bit of
+`a'. If `a' is zero, 32 is returned.
+-------------------------------------------------------------------------------
+*/
+static int8 countLeadingZeros32( bits32 a )
+{
+ static const int8 countLeadingZerosHigh[] = {
+ 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ int8 shiftCount;
+
+ shiftCount = 0;
+ if ( a < 0x10000 ) {
+ shiftCount += 16;
+ a <<= 16;
+ }
+ if ( a < 0x1000000 ) {
+ shiftCount += 8;
+ a <<= 8;
+ }
+ shiftCount += countLeadingZerosHigh[ a>>24 ];
+ return shiftCount;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is
+equal to the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
+returns 0.
+-------------------------------------------------------------------------------
+*/
+INLINE flag eq64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
+{
+
+ return ( a0 == b0 ) && ( a1 == b1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
+than or equal to the 64-bit value formed by concatenating `b0' and `b1'.
+Otherwise, returns 0.
+-------------------------------------------------------------------------------
+*/
+INLINE flag le64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
+{
+
+ return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is less
+than the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
+returns 0.
+-------------------------------------------------------------------------------
+*/
+INLINE flag lt64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
+{
+
+ return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the 64-bit value formed by concatenating `a0' and `a1' is not
+equal to the 64-bit value formed by concatenating `b0' and `b1'. Otherwise,
+returns 0.
+-------------------------------------------------------------------------------
+*/
+INLINE flag ne64( bits32 a0, bits32 a1, bits32 b0, bits32 b1 )
+{
+
+ return ( a0 != b0 ) || ( a1 != b1 );
+
+}
+
diff --git a/lib/libc/softfloat/bits32/softfloat.c b/lib/libc/softfloat/bits32/softfloat.c
new file mode 100644
index 0000000..ad7c016
--- /dev/null
+++ b/lib/libc/softfloat/bits32/softfloat.c
@@ -0,0 +1,2347 @@
+/* $NetBSD: softfloat.c,v 1.1 2002/05/21 23:51:07 bjh21 Exp $ */
+
+/*
+ * This version hacked for use with gcc -msoft-float by bjh21.
+ * (Mostly a case of #ifdefing out things GCC doesn't need or provides
+ * itself).
+ */
+
+/*
+ * Things you may want to define:
+ *
+ * SOFTFLOAT_FOR_GCC - build only those functions necessary for GCC (with
+ * -msoft-float) to work. Include "softfloat-for-gcc.h" to get them
+ * properly renamed.
+ */
+
+/*
+ * This differs from the standard bits32/softfloat.c in that float64
+ * is defined to be a 64-bit integer rather than a structure. The
+ * structure is float64s, with translation between the two going via
+ * float64u.
+ */
+
+/*
+===============================================================================
+
+This C source file is part of the SoftFloat IEC/IEEE Floating-Point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef SOFTFLOAT_FOR_GCC
+#include "softfloat-for-gcc.h"
+#endif
+
+#include "milieu.h"
+#include "softfloat.h"
+
+/*
+ * Conversions between floats as stored in memory and floats as
+ * SoftFloat uses them
+ */
+#ifndef FLOAT64_DEMANGLE
+#define FLOAT64_DEMANGLE(a) (a)
+#endif
+#ifndef FLOAT64_MANGLE
+#define FLOAT64_MANGLE(a) (a)
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Floating-point rounding mode and exception flags.
+-------------------------------------------------------------------------------
+*/
+int float_rounding_mode = float_round_nearest_even;
+int float_exception_flags = 0;
+
+/*
+-------------------------------------------------------------------------------
+Primitive arithmetic functions, including multi-word arithmetic, and
+division and square root approximations. (Can be specialized to target if
+desired.)
+-------------------------------------------------------------------------------
+*/
+#include "softfloat-macros"
+
+/*
+-------------------------------------------------------------------------------
+Functions and definitions to determine: (1) whether tininess for underflow
+is detected before or after rounding by default, (2) what (if anything)
+happens when exceptions are raised, (3) how signaling NaNs are distinguished
+from quiet NaNs, (4) the default generated quiet NaNs, and (4) how NaNs
+are propagated from function inputs to output. These details are target-
+specific.
+-------------------------------------------------------------------------------
+*/
+#include "softfloat-specialize"
+
+/*
+-------------------------------------------------------------------------------
+Returns the fraction bits of the single-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE bits32 extractFloat32Frac( float32 a )
+{
+
+ return a & 0x007FFFFF;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the exponent bits of the single-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE int16 extractFloat32Exp( float32 a )
+{
+
+ return ( a>>23 ) & 0xFF;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the sign bit of the single-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE flag extractFloat32Sign( float32 a )
+{
+
+ return a>>31;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Normalizes the subnormal single-precision floating-point value represented
+by the denormalized significand `aSig'. The normalized exponent and
+significand are stored at the locations pointed to by `zExpPtr' and
+`zSigPtr', respectively.
+-------------------------------------------------------------------------------
+*/
+static void
+ normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr )
+{
+ int8 shiftCount;
+
+ shiftCount = countLeadingZeros32( aSig ) - 8;
+ *zSigPtr = aSig<<shiftCount;
+ *zExpPtr = 1 - shiftCount;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
+single-precision floating-point value, returning the result. After being
+shifted into the proper positions, the three fields are simply added
+together to form the result. This means that any integer portion of `zSig'
+will be added into the exponent. Since a properly normalized significand
+will have an integer portion equal to 1, the `zExp' input should be 1 less
+than the desired result exponent whenever `zSig' is a complete, normalized
+significand.
+-------------------------------------------------------------------------------
+*/
+INLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig )
+{
+
+ return ( ( (bits32) zSign )<<31 ) + ( ( (bits32) zExp )<<23 ) + zSig;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and significand `zSig', and returns the proper single-precision floating-
+point value corresponding to the abstract input. Ordinarily, the abstract
+value is simply rounded and packed into the single-precision format, with
+the inexact exception raised if the abstract input cannot be represented
+exactly. However, if the abstract value is too large, the overflow and
+inexact exceptions are raised and an infinity or maximal finite value is
+returned. If the abstract value is too small, the input value is rounded to
+a subnormal number, and the underflow and inexact exceptions are raised if
+the abstract input cannot be represented exactly as a subnormal single-
+precision floating-point number.
+ The input significand `zSig' has its binary point between bits 30
+and 29, which is 7 bits to the left of the usual location. This shifted
+significand must be normalized or smaller. If `zSig' is not normalized,
+`zExp' must be 0; in that case, the result returned is a subnormal number,
+and it must not require rounding. In the usual case that `zSig' is
+normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
+The handling of underflow and overflow follows the IEC/IEEE Standard for
+Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
+{
+ int8 roundingMode;
+ flag roundNearestEven;
+ int8 roundIncrement, roundBits;
+ flag isTiny;
+
+ roundingMode = float_rounding_mode;
+ roundNearestEven = roundingMode == float_round_nearest_even;
+ roundIncrement = 0x40;
+ if ( ! roundNearestEven ) {
+ if ( roundingMode == float_round_to_zero ) {
+ roundIncrement = 0;
+ }
+ else {
+ roundIncrement = 0x7F;
+ if ( zSign ) {
+ if ( roundingMode == float_round_up ) roundIncrement = 0;
+ }
+ else {
+ if ( roundingMode == float_round_down ) roundIncrement = 0;
+ }
+ }
+ }
+ roundBits = zSig & 0x7F;
+ if ( 0xFD <= (bits16) zExp ) {
+ if ( ( 0xFD < zExp )
+ || ( ( zExp == 0xFD )
+ && ( (sbits32) ( zSig + roundIncrement ) < 0 ) )
+ ) {
+ float_raise( float_flag_overflow | float_flag_inexact );
+ return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 );
+ }
+ if ( zExp < 0 ) {
+ isTiny =
+ ( float_detect_tininess == float_tininess_before_rounding )
+ || ( zExp < -1 )
+ || ( zSig + roundIncrement < 0x80000000 );
+ shift32RightJamming( zSig, - zExp, &zSig );
+ zExp = 0;
+ roundBits = zSig & 0x7F;
+ if ( isTiny && roundBits ) float_raise( float_flag_underflow );
+ }
+ }
+ if ( roundBits ) float_exception_flags |= float_flag_inexact;
+ zSig = ( zSig + roundIncrement )>>7;
+ zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
+ if ( zSig == 0 ) zExp = 0;
+ return packFloat32( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and significand `zSig', and returns the proper single-precision floating-
+point value corresponding to the abstract input. This routine is just like
+`roundAndPackFloat32' except that `zSig' does not have to be normalized.
+Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
+floating-point exponent.
+-------------------------------------------------------------------------------
+*/
+static float32
+ normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
+{
+ int8 shiftCount;
+
+ shiftCount = countLeadingZeros32( zSig ) - 1;
+ return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<<shiftCount );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the least-significant 32 fraction bits of the double-precision
+floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE bits32 extractFloat64Frac1( float64 a )
+{
+
+ return FLOAT64_DEMANGLE(a) & LIT64( 0x00000000FFFFFFFF );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the most-significant 20 fraction bits of the double-precision
+floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE bits32 extractFloat64Frac0( float64 a )
+{
+
+ return ( FLOAT64_DEMANGLE(a)>>32 ) & 0x000FFFFF;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the exponent bits of the double-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE int16 extractFloat64Exp( float64 a )
+{
+
+ return ( FLOAT64_DEMANGLE(a)>>52 ) & 0x7FF;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the sign bit of the double-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE flag extractFloat64Sign( float64 a )
+{
+
+ return FLOAT64_DEMANGLE(a)>>63;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Normalizes the subnormal double-precision floating-point value represented
+by the denormalized significand formed by the concatenation of `aSig0' and
+`aSig1'. The normalized exponent is stored at the location pointed to by
+`zExpPtr'. The most significant 21 bits of the normalized significand are
+stored at the location pointed to by `zSig0Ptr', and the least significant
+32 bits of the normalized significand are stored at the location pointed to
+by `zSig1Ptr'.
+-------------------------------------------------------------------------------
+*/
+static void
+ normalizeFloat64Subnormal(
+ bits32 aSig0,
+ bits32 aSig1,
+ int16 *zExpPtr,
+ bits32 *zSig0Ptr,
+ bits32 *zSig1Ptr
+ )
+{
+ int8 shiftCount;
+
+ if ( aSig0 == 0 ) {
+ shiftCount = countLeadingZeros32( aSig1 ) - 11;
+ if ( shiftCount < 0 ) {
+ *zSig0Ptr = aSig1>>( - shiftCount );
+ *zSig1Ptr = aSig1<<( shiftCount & 31 );
+ }
+ else {
+ *zSig0Ptr = aSig1<<shiftCount;
+ *zSig1Ptr = 0;
+ }
+ *zExpPtr = - shiftCount - 31;
+ }
+ else {
+ shiftCount = countLeadingZeros32( aSig0 ) - 11;
+ shortShift64Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
+ *zExpPtr = 1 - shiftCount;
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Packs the sign `zSign', the exponent `zExp', and the significand formed by
+the concatenation of `zSig0' and `zSig1' into a double-precision floating-
+point value, returning the result. After being shifted into the proper
+positions, the three fields `zSign', `zExp', and `zSig0' are simply added
+together to form the most significant 32 bits of the result. This means
+that any integer portion of `zSig0' will be added into the exponent. Since
+a properly normalized significand will have an integer portion equal to 1,
+the `zExp' input should be 1 less than the desired result exponent whenever
+`zSig0' and `zSig1' concatenated form a complete, normalized significand.
+-------------------------------------------------------------------------------
+*/
+INLINE float64
+ packFloat64( flag zSign, int16 zExp, bits32 zSig0, bits32 zSig1 )
+{
+
+ return FLOAT64_MANGLE( ( ( (bits64) zSign )<<63 ) +
+ ( ( (bits64) zExp )<<52 ) +
+ ( ( (bits64) zSig0 )<<32 ) + zSig1 );
+
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and extended significand formed by the concatenation of `zSig0', `zSig1',
+and `zSig2', and returns the proper double-precision floating-point value
+corresponding to the abstract input. Ordinarily, the abstract value is
+simply rounded and packed into the double-precision format, with the inexact
+exception raised if the abstract input cannot be represented exactly.
+However, if the abstract value is too large, the overflow and inexact
+exceptions are raised and an infinity or maximal finite value is returned.
+If the abstract value is too small, the input value is rounded to a
+subnormal number, and the underflow and inexact exceptions are raised if the
+abstract input cannot be represented exactly as a subnormal double-precision
+floating-point number.
+ The input significand must be normalized or smaller. If the input
+significand is not normalized, `zExp' must be 0; in that case, the result
+returned is a subnormal number, and it must not require rounding. In the
+usual case that the input significand is normalized, `zExp' must be 1 less
+than the ``true'' floating-point exponent. The handling of underflow and
+overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float64
+ roundAndPackFloat64(
+ flag zSign, int16 zExp, bits32 zSig0, bits32 zSig1, bits32 zSig2 )
+{
+ int8 roundingMode;
+ flag roundNearestEven, increment, isTiny;
+
+ roundingMode = float_rounding_mode;
+ roundNearestEven = ( roundingMode == float_round_nearest_even );
+ increment = ( (sbits32) zSig2 < 0 );
+ if ( ! roundNearestEven ) {
+ if ( roundingMode == float_round_to_zero ) {
+ increment = 0;
+ }
+ else {
+ if ( zSign ) {
+ increment = ( roundingMode == float_round_down ) && zSig2;
+ }
+ else {
+ increment = ( roundingMode == float_round_up ) && zSig2;
+ }
+ }
+ }
+ if ( 0x7FD <= (bits16) zExp ) {
+ if ( ( 0x7FD < zExp )
+ || ( ( zExp == 0x7FD )
+ && eq64( 0x001FFFFF, 0xFFFFFFFF, zSig0, zSig1 )
+ && increment
+ )
+ ) {
+ float_raise( float_flag_overflow | float_flag_inexact );
+ if ( ( roundingMode == float_round_to_zero )
+ || ( zSign && ( roundingMode == float_round_up ) )
+ || ( ! zSign && ( roundingMode == float_round_down ) )
+ ) {
+ return packFloat64( zSign, 0x7FE, 0x000FFFFF, 0xFFFFFFFF );
+ }
+ return packFloat64( zSign, 0x7FF, 0, 0 );
+ }
+ if ( zExp < 0 ) {
+ isTiny =
+ ( float_detect_tininess == float_tininess_before_rounding )
+ || ( zExp < -1 )
+ || ! increment
+ || lt64( zSig0, zSig1, 0x001FFFFF, 0xFFFFFFFF );
+ shift64ExtraRightJamming(
+ zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 );
+ zExp = 0;
+ if ( isTiny && zSig2 ) float_raise( float_flag_underflow );
+ if ( roundNearestEven ) {
+ increment = ( (sbits32) zSig2 < 0 );
+ }
+ else {
+ if ( zSign ) {
+ increment = ( roundingMode == float_round_down ) && zSig2;
+ }
+ else {
+ increment = ( roundingMode == float_round_up ) && zSig2;
+ }
+ }
+ }
+ }
+ if ( zSig2 ) float_exception_flags |= float_flag_inexact;
+ if ( increment ) {
+ add64( zSig0, zSig1, 0, 1, &zSig0, &zSig1 );
+ zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven );
+ }
+ else {
+ if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0;
+ }
+ return packFloat64( zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and significand formed by the concatenation of `zSig0' and `zSig1', and
+returns the proper double-precision floating-point value corresponding
+to the abstract input. This routine is just like `roundAndPackFloat64'
+except that the input significand has fewer bits and does not have to be
+normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
+point exponent.
+-------------------------------------------------------------------------------
+*/
+static float64
+ normalizeRoundAndPackFloat64(
+ flag zSign, int16 zExp, bits32 zSig0, bits32 zSig1 )
+{
+ int8 shiftCount;
+ bits32 zSig2;
+
+ if ( zSig0 == 0 ) {
+ zSig0 = zSig1;
+ zSig1 = 0;
+ zExp -= 32;
+ }
+ shiftCount = countLeadingZeros32( zSig0 ) - 11;
+ if ( 0 <= shiftCount ) {
+ zSig2 = 0;
+ shortShift64Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
+ }
+ else {
+ shift64ExtraRightJamming(
+ zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 );
+ }
+ zExp -= shiftCount;
+ return roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 32-bit two's complement integer `a' to
+the single-precision floating-point format. The conversion is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 int32_to_float32( int32 a )
+{
+ flag zSign;
+
+ if ( a == 0 ) return 0;
+ if ( a == (sbits32) 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
+ zSign = ( a < 0 );
+ return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 32-bit two's complement integer `a' to
+the double-precision floating-point format. The conversion is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 int32_to_float64( int32 a )
+{
+ flag zSign;
+ bits32 absA;
+ int8 shiftCount;
+ bits32 zSig0, zSig1;
+
+ if ( a == 0 ) return packFloat64( 0, 0, 0, 0 );
+ zSign = ( a < 0 );
+ absA = zSign ? - a : a;
+ shiftCount = countLeadingZeros32( absA ) - 11;
+ if ( 0 <= shiftCount ) {
+ zSig0 = absA<<shiftCount;
+ zSig1 = 0;
+ }
+ else {
+ shift64Right( absA, 0, - shiftCount, &zSig0, &zSig1 );
+ }
+ return packFloat64( zSign, 0x412 - shiftCount, zSig0, zSig1 );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the 32-bit two's complement integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode. If `a' is a NaN, the largest
+positive integer is returned. Otherwise, if the conversion overflows, the
+largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int32 float32_to_int32( float32 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits32 aSig, aSigExtra;
+ int32 z;
+ int8 roundingMode;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ shiftCount = aExp - 0x96;
+ if ( 0 <= shiftCount ) {
+ if ( 0x9E <= aExp ) {
+ if ( a != 0xCF000000 ) {
+ float_raise( float_flag_invalid );
+ if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
+ return 0x7FFFFFFF;
+ }
+ }
+ return (sbits32) 0x80000000;
+ }
+ z = ( aSig | 0x00800000 )<<shiftCount;
+ if ( aSign ) z = - z;
+ }
+ else {
+ if ( aExp < 0x7E ) {
+ aSigExtra = aExp | aSig;
+ z = 0;
+ }
+ else {
+ aSig |= 0x00800000;
+ aSigExtra = aSig<<( shiftCount & 31 );
+ z = aSig>>( - shiftCount );
+ }
+ if ( aSigExtra ) float_exception_flags |= float_flag_inexact;
+ roundingMode = float_rounding_mode;
+ if ( roundingMode == float_round_nearest_even ) {
+ if ( (sbits32) aSigExtra < 0 ) {
+ ++z;
+ if ( (bits32) ( aSigExtra<<1 ) == 0 ) z &= ~1;
+ }
+ if ( aSign ) z = - z;
+ }
+ else {
+ aSigExtra = ( aSigExtra != 0 );
+ if ( aSign ) {
+ z += ( roundingMode == float_round_down ) & aSigExtra;
+ z = - z;
+ }
+ else {
+ z += ( roundingMode == float_round_up ) & aSigExtra;
+ }
+ }
+ }
+ return z;
+
+}
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the 32-bit two's complement integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic, except that the conversion is always rounded toward zero.
+If `a' is a NaN, the largest positive integer is returned. Otherwise, if
+the conversion overflows, the largest integer with the same sign as `a' is
+returned.
+-------------------------------------------------------------------------------
+*/
+int32 float32_to_int32_round_to_zero( float32 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits32 aSig;
+ int32 z;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ shiftCount = aExp - 0x9E;
+ if ( 0 <= shiftCount ) {
+ if ( a != 0xCF000000 ) {
+ float_raise( float_flag_invalid );
+ if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF;
+ }
+ return (sbits32) 0x80000000;
+ }
+ else if ( aExp <= 0x7E ) {
+ if ( aExp | aSig ) float_exception_flags |= float_flag_inexact;
+ return 0;
+ }
+ aSig = ( aSig | 0x00800000 )<<8;
+ z = aSig>>( - shiftCount );
+ if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ if ( aSign ) z = - z;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the double-precision floating-point format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float32_to_float64( float32 a )
+{
+ flag aSign;
+ int16 aExp;
+ bits32 aSig, zSig0, zSig1;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ if ( aExp == 0xFF ) {
+ if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) );
+ return packFloat64( aSign, 0x7FF, 0, 0 );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return packFloat64( aSign, 0, 0, 0 );
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+ --aExp;
+ }
+ shift64Right( aSig, 0, 3, &zSig0, &zSig1 );
+ return packFloat64( aSign, aExp + 0x380, zSig0, zSig1 );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Rounds the single-precision floating-point value `a' to an integer,
+and returns the result as a single-precision floating-point value. The
+operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_round_to_int( float32 a )
+{
+ flag aSign;
+ int16 aExp;
+ bits32 lastBitMask, roundBitsMask;
+ int8 roundingMode;
+ float32 z;
+
+ aExp = extractFloat32Exp( a );
+ if ( 0x96 <= aExp ) {
+ if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) {
+ return propagateFloat32NaN( a, a );
+ }
+ return a;
+ }
+ if ( aExp <= 0x7E ) {
+ if ( (bits32) ( a<<1 ) == 0 ) return a;
+ float_exception_flags |= float_flag_inexact;
+ aSign = extractFloat32Sign( a );
+ switch ( float_rounding_mode ) {
+ case float_round_nearest_even:
+ if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) {
+ return packFloat32( aSign, 0x7F, 0 );
+ }
+ break;
+ case float_round_to_zero:
+ break;
+ case float_round_down:
+ return aSign ? 0xBF800000 : 0;
+ case float_round_up:
+ return aSign ? 0x80000000 : 0x3F800000;
+ }
+ return packFloat32( aSign, 0, 0 );
+ }
+ lastBitMask = 1;
+ lastBitMask <<= 0x96 - aExp;
+ roundBitsMask = lastBitMask - 1;
+ z = a;
+ roundingMode = float_rounding_mode;
+ if ( roundingMode == float_round_nearest_even ) {
+ z += lastBitMask>>1;
+ if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
+ }
+ else if ( roundingMode != float_round_to_zero ) {
+ if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) {
+ z += roundBitsMask;
+ }
+ }
+ z &= ~ roundBitsMask;
+ if ( z != a ) float_exception_flags |= float_flag_inexact;
+ return z;
+
+}
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the absolute values of the single-precision
+floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
+before being returned. `zSign' is ignored if the result is a NaN.
+The addition is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float32 addFloat32Sigs( float32 a, float32 b, flag zSign )
+{
+ int16 aExp, bExp, zExp;
+ bits32 aSig, bSig, zSig;
+ int16 expDiff;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ bSig = extractFloat32Frac( b );
+ bExp = extractFloat32Exp( b );
+ expDiff = aExp - bExp;
+ aSig <<= 6;
+ bSig <<= 6;
+ if ( 0 < expDiff ) {
+ if ( aExp == 0xFF ) {
+ if ( aSig ) return propagateFloat32NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ --expDiff;
+ }
+ else {
+ bSig |= 0x20000000;
+ }
+ shift32RightJamming( bSig, expDiff, &bSig );
+ zExp = aExp;
+ }
+ else if ( expDiff < 0 ) {
+ if ( bExp == 0xFF ) {
+ if ( bSig ) return propagateFloat32NaN( a, b );
+ return packFloat32( zSign, 0xFF, 0 );
+ }
+ if ( aExp == 0 ) {
+ ++expDiff;
+ }
+ else {
+ aSig |= 0x20000000;
+ }
+ shift32RightJamming( aSig, - expDiff, &aSig );
+ zExp = bExp;
+ }
+ else {
+ if ( aExp == 0xFF ) {
+ if ( aSig | bSig ) return propagateFloat32NaN( a, b );
+ return a;
+ }
+ if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 );
+ zSig = 0x40000000 + aSig + bSig;
+ zExp = aExp;
+ goto roundAndPack;
+ }
+ aSig |= 0x20000000;
+ zSig = ( aSig + bSig )<<1;
+ --zExp;
+ if ( (sbits32) zSig < 0 ) {
+ zSig = aSig + bSig;
+ ++zExp;
+ }
+ roundAndPack:
+ return roundAndPackFloat32( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the absolute values of the single-
+precision floating-point values `a' and `b'. If `zSign' is 1, the
+difference is negated before being returned. `zSign' is ignored if the
+result is a NaN. The subtraction is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
+{
+ int16 aExp, bExp, zExp;
+ bits32 aSig, bSig, zSig;
+ int16 expDiff;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ bSig = extractFloat32Frac( b );
+ bExp = extractFloat32Exp( b );
+ expDiff = aExp - bExp;
+ aSig <<= 7;
+ bSig <<= 7;
+ if ( 0 < expDiff ) goto aExpBigger;
+ if ( expDiff < 0 ) goto bExpBigger;
+ if ( aExp == 0xFF ) {
+ if ( aSig | bSig ) return propagateFloat32NaN( a, b );
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ if ( aExp == 0 ) {
+ aExp = 1;
+ bExp = 1;
+ }
+ if ( bSig < aSig ) goto aBigger;
+ if ( aSig < bSig ) goto bBigger;
+ return packFloat32( float_rounding_mode == float_round_down, 0, 0 );
+ bExpBigger:
+ if ( bExp == 0xFF ) {
+ if ( bSig ) return propagateFloat32NaN( a, b );
+ return packFloat32( zSign ^ 1, 0xFF, 0 );
+ }
+ if ( aExp == 0 ) {
+ ++expDiff;
+ }
+ else {
+ aSig |= 0x40000000;
+ }
+ shift32RightJamming( aSig, - expDiff, &aSig );
+ bSig |= 0x40000000;
+ bBigger:
+ zSig = bSig - aSig;
+ zExp = bExp;
+ zSign ^= 1;
+ goto normalizeRoundAndPack;
+ aExpBigger:
+ if ( aExp == 0xFF ) {
+ if ( aSig ) return propagateFloat32NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ --expDiff;
+ }
+ else {
+ bSig |= 0x40000000;
+ }
+ shift32RightJamming( bSig, expDiff, &bSig );
+ aSig |= 0x40000000;
+ aBigger:
+ zSig = aSig - bSig;
+ zExp = aExp;
+ normalizeRoundAndPack:
+ --zExp;
+ return normalizeRoundAndPackFloat32( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the single-precision floating-point values `a'
+and `b'. The operation is performed according to the IEC/IEEE Standard for
+Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_add( float32 a, float32 b )
+{
+ flag aSign, bSign;
+
+ aSign = extractFloat32Sign( a );
+ bSign = extractFloat32Sign( b );
+ if ( aSign == bSign ) {
+ return addFloat32Sigs( a, b, aSign );
+ }
+ else {
+ return subFloat32Sigs( a, b, aSign );
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the single-precision floating-point values
+`a' and `b'. The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_sub( float32 a, float32 b )
+{
+ flag aSign, bSign;
+
+ aSign = extractFloat32Sign( a );
+ bSign = extractFloat32Sign( b );
+ if ( aSign == bSign ) {
+ return subFloat32Sigs( a, b, aSign );
+ }
+ else {
+ return addFloat32Sigs( a, b, aSign );
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of multiplying the single-precision floating-point values
+`a' and `b'. The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_mul( float32 a, float32 b )
+{
+ flag aSign, bSign, zSign;
+ int16 aExp, bExp, zExp;
+ bits32 aSig, bSig, zSig0, zSig1;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ bSig = extractFloat32Frac( b );
+ bExp = extractFloat32Exp( b );
+ bSign = extractFloat32Sign( b );
+ zSign = aSign ^ bSign;
+ if ( aExp == 0xFF ) {
+ if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
+ return propagateFloat32NaN( a, b );
+ }
+ if ( ( bExp | bSig ) == 0 ) {
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ return packFloat32( zSign, 0xFF, 0 );
+ }
+ if ( bExp == 0xFF ) {
+ if ( bSig ) return propagateFloat32NaN( a, b );
+ if ( ( aExp | aSig ) == 0 ) {
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ return packFloat32( zSign, 0xFF, 0 );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+ }
+ if ( bExp == 0 ) {
+ if ( bSig == 0 ) return packFloat32( zSign, 0, 0 );
+ normalizeFloat32Subnormal( bSig, &bExp, &bSig );
+ }
+ zExp = aExp + bExp - 0x7F;
+ aSig = ( aSig | 0x00800000 )<<7;
+ bSig = ( bSig | 0x00800000 )<<8;
+ mul32To64( aSig, bSig, &zSig0, &zSig1 );
+ zSig0 |= ( zSig1 != 0 );
+ if ( 0 <= (sbits32) ( zSig0<<1 ) ) {
+ zSig0 <<= 1;
+ --zExp;
+ }
+ return roundAndPackFloat32( zSign, zExp, zSig0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of dividing the single-precision floating-point value `a'
+by the corresponding value `b'. The operation is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_div( float32 a, float32 b )
+{
+ flag aSign, bSign, zSign;
+ int16 aExp, bExp, zExp;
+ bits32 aSig, bSig, zSig, rem0, rem1, term0, term1;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ bSig = extractFloat32Frac( b );
+ bExp = extractFloat32Exp( b );
+ bSign = extractFloat32Sign( b );
+ zSign = aSign ^ bSign;
+ if ( aExp == 0xFF ) {
+ if ( aSig ) return propagateFloat32NaN( a, b );
+ if ( bExp == 0xFF ) {
+ if ( bSig ) return propagateFloat32NaN( a, b );
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ return packFloat32( zSign, 0xFF, 0 );
+ }
+ if ( bExp == 0xFF ) {
+ if ( bSig ) return propagateFloat32NaN( a, b );
+ return packFloat32( zSign, 0, 0 );
+ }
+ if ( bExp == 0 ) {
+ if ( bSig == 0 ) {
+ if ( ( aExp | aSig ) == 0 ) {
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ float_raise( float_flag_divbyzero );
+ return packFloat32( zSign, 0xFF, 0 );
+ }
+ normalizeFloat32Subnormal( bSig, &bExp, &bSig );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+ }
+ zExp = aExp - bExp + 0x7D;
+ aSig = ( aSig | 0x00800000 )<<7;
+ bSig = ( bSig | 0x00800000 )<<8;
+ if ( bSig <= ( aSig + aSig ) ) {
+ aSig >>= 1;
+ ++zExp;
+ }
+ zSig = estimateDiv64To32( aSig, 0, bSig );
+ if ( ( zSig & 0x3F ) <= 2 ) {
+ mul32To64( bSig, zSig, &term0, &term1 );
+ sub64( aSig, 0, term0, term1, &rem0, &rem1 );
+ while ( (sbits32) rem0 < 0 ) {
+ --zSig;
+ add64( rem0, rem1, 0, bSig, &rem0, &rem1 );
+ }
+ zSig |= ( rem1 != 0 );
+ }
+ return roundAndPackFloat32( zSign, zExp, zSig );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Returns the remainder of the single-precision floating-point value `a'
+with respect to the corresponding value `b'. The operation is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_rem( float32 a, float32 b )
+{
+ flag aSign, bSign, zSign;
+ int16 aExp, bExp, expDiff;
+ bits32 aSig, bSig, q, allZero, alternateASig;
+ sbits32 sigMean;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ bSig = extractFloat32Frac( b );
+ bExp = extractFloat32Exp( b );
+ bSign = extractFloat32Sign( b );
+ if ( aExp == 0xFF ) {
+ if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
+ return propagateFloat32NaN( a, b );
+ }
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ if ( bExp == 0xFF ) {
+ if ( bSig ) return propagateFloat32NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ if ( bSig == 0 ) {
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ normalizeFloat32Subnormal( bSig, &bExp, &bSig );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return a;
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+ }
+ expDiff = aExp - bExp;
+ aSig = ( aSig | 0x00800000 )<<8;
+ bSig = ( bSig | 0x00800000 )<<8;
+ if ( expDiff < 0 ) {
+ if ( expDiff < -1 ) return a;
+ aSig >>= 1;
+ }
+ q = ( bSig <= aSig );
+ if ( q ) aSig -= bSig;
+ expDiff -= 32;
+ while ( 0 < expDiff ) {
+ q = estimateDiv64To32( aSig, 0, bSig );
+ q = ( 2 < q ) ? q - 2 : 0;
+ aSig = - ( ( bSig>>2 ) * q );
+ expDiff -= 30;
+ }
+ expDiff += 32;
+ if ( 0 < expDiff ) {
+ q = estimateDiv64To32( aSig, 0, bSig );
+ q = ( 2 < q ) ? q - 2 : 0;
+ q >>= 32 - expDiff;
+ bSig >>= 2;
+ aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
+ }
+ else {
+ aSig >>= 2;
+ bSig >>= 2;
+ }
+ do {
+ alternateASig = aSig;
+ ++q;
+ aSig -= bSig;
+ } while ( 0 <= (sbits32) aSig );
+ sigMean = aSig + alternateASig;
+ if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
+ aSig = alternateASig;
+ }
+ zSign = ( (sbits32) aSig < 0 );
+ if ( zSign ) aSig = - aSig;
+ return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig );
+
+}
+#endif
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Returns the square root of the single-precision floating-point value `a'.
+The operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_sqrt( float32 a )
+{
+ flag aSign;
+ int16 aExp, zExp;
+ bits32 aSig, zSig, rem0, rem1, term0, term1;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ if ( aExp == 0xFF ) {
+ if ( aSig ) return propagateFloat32NaN( a, 0 );
+ if ( ! aSign ) return a;
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ if ( aSign ) {
+ if ( ( aExp | aSig ) == 0 ) return a;
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return 0;
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+ }
+ zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E;
+ aSig = ( aSig | 0x00800000 )<<8;
+ zSig = estimateSqrt32( aExp, aSig ) + 2;
+ if ( ( zSig & 0x7F ) <= 5 ) {
+ if ( zSig < 2 ) {
+ zSig = 0x7FFFFFFF;
+ goto roundAndPack;
+ }
+ else {
+ aSig >>= aExp & 1;
+ mul32To64( zSig, zSig, &term0, &term1 );
+ sub64( aSig, 0, term0, term1, &rem0, &rem1 );
+ while ( (sbits32) rem0 < 0 ) {
+ --zSig;
+ shortShift64Left( 0, zSig, 1, &term0, &term1 );
+ term1 |= 1;
+ add64( rem0, rem1, term0, term1, &rem0, &rem1 );
+ }
+ zSig |= ( ( rem0 | rem1 ) != 0 );
+ }
+ }
+ shift32RightJamming( zSig, 1, &zSig );
+ roundAndPack:
+ return roundAndPackFloat32( 0, zExp, zSig );
+
+}
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is equal to
+the corresponding value `b', and 0 otherwise. The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_eq( float32 a, float32 b )
+{
+
+ if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+ || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+ ) {
+ if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is less than
+or equal to the corresponding value `b', and 0 otherwise. The comparison
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_le( float32 a, float32 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+ || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ aSign = extractFloat32Sign( a );
+ bSign = extractFloat32Sign( b );
+ if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
+ return ( a == b ) || ( aSign ^ ( a < b ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise. The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_lt( float32 a, float32 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+ || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ aSign = extractFloat32Sign( a );
+ bSign = extractFloat32Sign( b );
+ if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
+ return ( a != b ) && ( aSign ^ ( a < b ) );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is equal to
+the corresponding value `b', and 0 otherwise. The invalid exception is
+raised if either operand is a NaN. Otherwise, the comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_eq_signaling( float32 a, float32 b )
+{
+
+ if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+ || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is less than or
+equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
+cause an exception. Otherwise, the comparison is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_le_quiet( float32 a, float32 b )
+{
+ flag aSign, bSign;
+ int16 aExp, bExp;
+
+ if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+ || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+ ) {
+ if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ aSign = extractFloat32Sign( a );
+ bSign = extractFloat32Sign( b );
+ if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
+ return ( a == b ) || ( aSign ^ ( a < b ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
+exception. Otherwise, the comparison is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_lt_quiet( float32 a, float32 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+ || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+ ) {
+ if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ aSign = extractFloat32Sign( a );
+ bSign = extractFloat32Sign( b );
+ if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
+ return ( a != b ) && ( aSign ^ ( a < b ) );
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the 32-bit two's complement integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode. If `a' is a NaN, the largest
+positive integer is returned. Otherwise, if the conversion overflows, the
+largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int32 float64_to_int32( float64 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits32 aSig0, aSig1, absZ, aSigExtra;
+ int32 z;
+ int8 roundingMode;
+
+ aSig1 = extractFloat64Frac1( a );
+ aSig0 = extractFloat64Frac0( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ shiftCount = aExp - 0x413;
+ if ( 0 <= shiftCount ) {
+ if ( 0x41E < aExp ) {
+ if ( ( aExp == 0x7FF ) && ( aSig0 | aSig1 ) ) aSign = 0;
+ goto invalid;
+ }
+ shortShift64Left(
+ aSig0 | 0x00100000, aSig1, shiftCount, &absZ, &aSigExtra );
+ if ( 0x80000000 < absZ ) goto invalid;
+ }
+ else {
+ aSig1 = ( aSig1 != 0 );
+ if ( aExp < 0x3FE ) {
+ aSigExtra = aExp | aSig0 | aSig1;
+ absZ = 0;
+ }
+ else {
+ aSig0 |= 0x00100000;
+ aSigExtra = ( aSig0<<( shiftCount & 31 ) ) | aSig1;
+ absZ = aSig0>>( - shiftCount );
+ }
+ }
+ roundingMode = float_rounding_mode;
+ if ( roundingMode == float_round_nearest_even ) {
+ if ( (sbits32) aSigExtra < 0 ) {
+ ++absZ;
+ if ( (bits32) ( aSigExtra<<1 ) == 0 ) absZ &= ~1;
+ }
+ z = aSign ? - absZ : absZ;
+ }
+ else {
+ aSigExtra = ( aSigExtra != 0 );
+ if ( aSign ) {
+ z = - ( absZ
+ + ( ( roundingMode == float_round_down ) & aSigExtra ) );
+ }
+ else {
+ z = absZ + ( ( roundingMode == float_round_up ) & aSigExtra );
+ }
+ }
+ if ( ( aSign ^ ( z < 0 ) ) && z ) {
+ invalid:
+ float_raise( float_flag_invalid );
+ return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
+ }
+ if ( aSigExtra ) float_exception_flags |= float_flag_inexact;
+ return z;
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the 32-bit two's complement integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic, except that the conversion is always rounded toward zero.
+If `a' is a NaN, the largest positive integer is returned. Otherwise, if
+the conversion overflows, the largest integer with the same sign as `a' is
+returned.
+-------------------------------------------------------------------------------
+*/
+int32 float64_to_int32_round_to_zero( float64 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits32 aSig0, aSig1, absZ, aSigExtra;
+ int32 z;
+
+ aSig1 = extractFloat64Frac1( a );
+ aSig0 = extractFloat64Frac0( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ shiftCount = aExp - 0x413;
+ if ( 0 <= shiftCount ) {
+ if ( 0x41E < aExp ) {
+ if ( ( aExp == 0x7FF ) && ( aSig0 | aSig1 ) ) aSign = 0;
+ goto invalid;
+ }
+ shortShift64Left(
+ aSig0 | 0x00100000, aSig1, shiftCount, &absZ, &aSigExtra );
+ }
+ else {
+ if ( aExp < 0x3FF ) {
+ if ( aExp | aSig0 | aSig1 ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ return 0;
+ }
+ aSig0 |= 0x00100000;
+ aSigExtra = ( aSig0<<( shiftCount & 31 ) ) | aSig1;
+ absZ = aSig0>>( - shiftCount );
+ }
+ z = aSign ? - absZ : absZ;
+ if ( ( aSign ^ ( z < 0 ) ) && z ) {
+ invalid:
+ float_raise( float_flag_invalid );
+ return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
+ }
+ if ( aSigExtra ) float_exception_flags |= float_flag_inexact;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the single-precision floating-point format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float64_to_float32( float64 a )
+{
+ flag aSign;
+ int16 aExp;
+ bits32 aSig0, aSig1, zSig;
+ bits32 allZero;
+
+ aSig1 = extractFloat64Frac1( a );
+ aSig0 = extractFloat64Frac0( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ if ( aExp == 0x7FF ) {
+ if ( aSig0 | aSig1 ) {
+ return commonNaNToFloat32( float64ToCommonNaN( a ) );
+ }
+ return packFloat32( aSign, 0xFF, 0 );
+ }
+ shift64RightJamming( aSig0, aSig1, 22, &allZero, &zSig );
+ if ( aExp ) zSig |= 0x40000000;
+ return roundAndPackFloat32( aSign, aExp - 0x381, zSig );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Rounds the double-precision floating-point value `a' to an integer,
+and returns the result as a double-precision floating-point value. The
+operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_round_to_int( float64 a )
+{
+ flag aSign;
+ int16 aExp;
+ bits32 lastBitMask, roundBitsMask;
+ int8 roundingMode;
+ float64 z;
+
+ aExp = extractFloat64Exp( a );
+ if ( 0x413 <= aExp ) {
+ if ( 0x433 <= aExp ) {
+ if ( ( aExp == 0x7FF )
+ && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) ) {
+ return propagateFloat64NaN( a, a );
+ }
+ return a;
+ }
+ lastBitMask = 1;
+ lastBitMask = ( lastBitMask<<( 0x432 - aExp ) )<<1;
+ roundBitsMask = lastBitMask - 1;
+ z = a;
+ roundingMode = float_rounding_mode;
+ if ( roundingMode == float_round_nearest_even ) {
+ if ( lastBitMask ) {
+ add64( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low );
+ if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
+ }
+ else {
+ if ( (sbits32) z.low < 0 ) {
+ ++z.high;
+ if ( (bits32) ( z.low<<1 ) == 0 ) z.high &= ~1;
+ }
+ }
+ }
+ else if ( roundingMode != float_round_to_zero ) {
+ if ( extractFloat64Sign( z )
+ ^ ( roundingMode == float_round_up ) ) {
+ add64( z.high, z.low, 0, roundBitsMask, &z.high, &z.low );
+ }
+ }
+ z.low &= ~ roundBitsMask;
+ }
+ else {
+ if ( aExp <= 0x3FE ) {
+ if ( ( ( (bits32) ( a.high<<1 ) ) | a.low ) == 0 ) return a;
+ float_exception_flags |= float_flag_inexact;
+ aSign = extractFloat64Sign( a );
+ switch ( float_rounding_mode ) {
+ case float_round_nearest_even:
+ if ( ( aExp == 0x3FE )
+ && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) )
+ ) {
+ return packFloat64( aSign, 0x3FF, 0, 0 );
+ }
+ break;
+ case float_round_down:
+ return
+ aSign ? packFloat64( 1, 0x3FF, 0, 0 )
+ : packFloat64( 0, 0, 0, 0 );
+ case float_round_up:
+ return
+ aSign ? packFloat64( 1, 0, 0, 0 )
+ : packFloat64( 0, 0x3FF, 0, 0 );
+ }
+ return packFloat64( aSign, 0, 0, 0 );
+ }
+ lastBitMask = 1;
+ lastBitMask <<= 0x413 - aExp;
+ roundBitsMask = lastBitMask - 1;
+ z.low = 0;
+ z.high = a.high;
+ roundingMode = float_rounding_mode;
+ if ( roundingMode == float_round_nearest_even ) {
+ z.high += lastBitMask>>1;
+ if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) {
+ z.high &= ~ lastBitMask;
+ }
+ }
+ else if ( roundingMode != float_round_to_zero ) {
+ if ( extractFloat64Sign( z )
+ ^ ( roundingMode == float_round_up ) ) {
+ z.high |= ( a.low != 0 );
+ z.high += roundBitsMask;
+ }
+ }
+ z.high &= ~ roundBitsMask;
+ }
+ if ( ( z.low != a.low ) || ( z.high != a.high ) ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ return z;
+
+}
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the absolute values of the double-precision
+floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
+before being returned. `zSign' is ignored if the result is a NaN.
+The addition is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float64 addFloat64Sigs( float64 a, float64 b, flag zSign )
+{
+ int16 aExp, bExp, zExp;
+ bits32 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
+ int16 expDiff;
+
+ aSig1 = extractFloat64Frac1( a );
+ aSig0 = extractFloat64Frac0( a );
+ aExp = extractFloat64Exp( a );
+ bSig1 = extractFloat64Frac1( b );
+ bSig0 = extractFloat64Frac0( b );
+ bExp = extractFloat64Exp( b );
+ expDiff = aExp - bExp;
+ if ( 0 < expDiff ) {
+ if ( aExp == 0x7FF ) {
+ if ( aSig0 | aSig1 ) return propagateFloat64NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ --expDiff;
+ }
+ else {
+ bSig0 |= 0x00100000;
+ }
+ shift64ExtraRightJamming(
+ bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 );
+ zExp = aExp;
+ }
+ else if ( expDiff < 0 ) {
+ if ( bExp == 0x7FF ) {
+ if ( bSig0 | bSig1 ) return propagateFloat64NaN( a, b );
+ return packFloat64( zSign, 0x7FF, 0, 0 );
+ }
+ if ( aExp == 0 ) {
+ ++expDiff;
+ }
+ else {
+ aSig0 |= 0x00100000;
+ }
+ shift64ExtraRightJamming(
+ aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 );
+ zExp = bExp;
+ }
+ else {
+ if ( aExp == 0x7FF ) {
+ if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
+ return propagateFloat64NaN( a, b );
+ }
+ return a;
+ }
+ add64( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
+ if ( aExp == 0 ) return packFloat64( zSign, 0, zSig0, zSig1 );
+ zSig2 = 0;
+ zSig0 |= 0x00200000;
+ zExp = aExp;
+ goto shiftRight1;
+ }
+ aSig0 |= 0x00100000;
+ add64( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
+ --zExp;
+ if ( zSig0 < 0x00200000 ) goto roundAndPack;
+ ++zExp;
+ shiftRight1:
+ shift64ExtraRightJamming( zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
+ roundAndPack:
+ return roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the absolute values of the double-
+precision floating-point values `a' and `b'. If `zSign' is 1, the
+difference is negated before being returned. `zSign' is ignored if the
+result is a NaN. The subtraction is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
+{
+ int16 aExp, bExp, zExp;
+ bits32 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1;
+ int16 expDiff;
+
+ aSig1 = extractFloat64Frac1( a );
+ aSig0 = extractFloat64Frac0( a );
+ aExp = extractFloat64Exp( a );
+ bSig1 = extractFloat64Frac1( b );
+ bSig0 = extractFloat64Frac0( b );
+ bExp = extractFloat64Exp( b );
+ expDiff = aExp - bExp;
+ shortShift64Left( aSig0, aSig1, 10, &aSig0, &aSig1 );
+ shortShift64Left( bSig0, bSig1, 10, &bSig0, &bSig1 );
+ if ( 0 < expDiff ) goto aExpBigger;
+ if ( expDiff < 0 ) goto bExpBigger;
+ if ( aExp == 0x7FF ) {
+ if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
+ return propagateFloat64NaN( a, b );
+ }
+ float_raise( float_flag_invalid );
+ return float64_default_nan;
+ }
+ if ( aExp == 0 ) {
+ aExp = 1;
+ bExp = 1;
+ }
+ if ( bSig0 < aSig0 ) goto aBigger;
+ if ( aSig0 < bSig0 ) goto bBigger;
+ if ( bSig1 < aSig1 ) goto aBigger;
+ if ( aSig1 < bSig1 ) goto bBigger;
+ return packFloat64( float_rounding_mode == float_round_down, 0, 0, 0 );
+ bExpBigger:
+ if ( bExp == 0x7FF ) {
+ if ( bSig0 | bSig1 ) return propagateFloat64NaN( a, b );
+ return packFloat64( zSign ^ 1, 0x7FF, 0, 0 );
+ }
+ if ( aExp == 0 ) {
+ ++expDiff;
+ }
+ else {
+ aSig0 |= 0x40000000;
+ }
+ shift64RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
+ bSig0 |= 0x40000000;
+ bBigger:
+ sub64( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 );
+ zExp = bExp;
+ zSign ^= 1;
+ goto normalizeRoundAndPack;
+ aExpBigger:
+ if ( aExp == 0x7FF ) {
+ if ( aSig0 | aSig1 ) return propagateFloat64NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ --expDiff;
+ }
+ else {
+ bSig0 |= 0x40000000;
+ }
+ shift64RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 );
+ aSig0 |= 0x40000000;
+ aBigger:
+ sub64( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
+ zExp = aExp;
+ normalizeRoundAndPack:
+ --zExp;
+ return normalizeRoundAndPackFloat64( zSign, zExp - 10, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the double-precision floating-point values `a'
+and `b'. The operation is performed according to the IEC/IEEE Standard for
+Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_add( float64 a, float64 b )
+{
+ flag aSign, bSign;
+
+ aSign = extractFloat64Sign( a );
+ bSign = extractFloat64Sign( b );
+ if ( aSign == bSign ) {
+ return addFloat64Sigs( a, b, aSign );
+ }
+ else {
+ return subFloat64Sigs( a, b, aSign );
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the double-precision floating-point values
+`a' and `b'. The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_sub( float64 a, float64 b )
+{
+ flag aSign, bSign;
+
+ aSign = extractFloat64Sign( a );
+ bSign = extractFloat64Sign( b );
+ if ( aSign == bSign ) {
+ return subFloat64Sigs( a, b, aSign );
+ }
+ else {
+ return addFloat64Sigs( a, b, aSign );
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of multiplying the double-precision floating-point values
+`a' and `b'. The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_mul( float64 a, float64 b )
+{
+ flag aSign, bSign, zSign;
+ int16 aExp, bExp, zExp;
+ bits32 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3;
+
+ aSig1 = extractFloat64Frac1( a );
+ aSig0 = extractFloat64Frac0( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ bSig1 = extractFloat64Frac1( b );
+ bSig0 = extractFloat64Frac0( b );
+ bExp = extractFloat64Exp( b );
+ bSign = extractFloat64Sign( b );
+ zSign = aSign ^ bSign;
+ if ( aExp == 0x7FF ) {
+ if ( ( aSig0 | aSig1 )
+ || ( ( bExp == 0x7FF ) && ( bSig0 | bSig1 ) ) ) {
+ return propagateFloat64NaN( a, b );
+ }
+ if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid;
+ return packFloat64( zSign, 0x7FF, 0, 0 );
+ }
+ if ( bExp == 0x7FF ) {
+ if ( bSig0 | bSig1 ) return propagateFloat64NaN( a, b );
+ if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
+ invalid:
+ float_raise( float_flag_invalid );
+ return float64_default_nan;
+ }
+ return packFloat64( zSign, 0x7FF, 0, 0 );
+ }
+ if ( aExp == 0 ) {
+ if ( ( aSig0 | aSig1 ) == 0 ) return packFloat64( zSign, 0, 0, 0 );
+ normalizeFloat64Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+ }
+ if ( bExp == 0 ) {
+ if ( ( bSig0 | bSig1 ) == 0 ) return packFloat64( zSign, 0, 0, 0 );
+ normalizeFloat64Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
+ }
+ zExp = aExp + bExp - 0x400;
+ aSig0 |= 0x00100000;
+ shortShift64Left( bSig0, bSig1, 12, &bSig0, &bSig1 );
+ mul64To128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 );
+ add64( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 );
+ zSig2 |= ( zSig3 != 0 );
+ if ( 0x00200000 <= zSig0 ) {
+ shift64ExtraRightJamming(
+ zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
+ ++zExp;
+ }
+ return roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of dividing the double-precision floating-point value `a'
+by the corresponding value `b'. The operation is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_div( float64 a, float64 b )
+{
+ flag aSign, bSign, zSign;
+ int16 aExp, bExp, zExp;
+ bits32 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
+ bits32 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
+
+ aSig1 = extractFloat64Frac1( a );
+ aSig0 = extractFloat64Frac0( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ bSig1 = extractFloat64Frac1( b );
+ bSig0 = extractFloat64Frac0( b );
+ bExp = extractFloat64Exp( b );
+ bSign = extractFloat64Sign( b );
+ zSign = aSign ^ bSign;
+ if ( aExp == 0x7FF ) {
+ if ( aSig0 | aSig1 ) return propagateFloat64NaN( a, b );
+ if ( bExp == 0x7FF ) {
+ if ( bSig0 | bSig1 ) return propagateFloat64NaN( a, b );
+ goto invalid;
+ }
+ return packFloat64( zSign, 0x7FF, 0, 0 );
+ }
+ if ( bExp == 0x7FF ) {
+ if ( bSig0 | bSig1 ) return propagateFloat64NaN( a, b );
+ return packFloat64( zSign, 0, 0, 0 );
+ }
+ if ( bExp == 0 ) {
+ if ( ( bSig0 | bSig1 ) == 0 ) {
+ if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
+ invalid:
+ float_raise( float_flag_invalid );
+ return float64_default_nan;
+ }
+ float_raise( float_flag_divbyzero );
+ return packFloat64( zSign, 0x7FF, 0, 0 );
+ }
+ normalizeFloat64Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
+ }
+ if ( aExp == 0 ) {
+ if ( ( aSig0 | aSig1 ) == 0 ) return packFloat64( zSign, 0, 0, 0 );
+ normalizeFloat64Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+ }
+ zExp = aExp - bExp + 0x3FD;
+ shortShift64Left( aSig0 | 0x00100000, aSig1, 11, &aSig0, &aSig1 );
+ shortShift64Left( bSig0 | 0x00100000, bSig1, 11, &bSig0, &bSig1 );
+ if ( le64( bSig0, bSig1, aSig0, aSig1 ) ) {
+ shift64Right( aSig0, aSig1, 1, &aSig0, &aSig1 );
+ ++zExp;
+ }
+ zSig0 = estimateDiv64To32( aSig0, aSig1, bSig0 );
+ mul64By32To96( bSig0, bSig1, zSig0, &term0, &term1, &term2 );
+ sub96( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 );
+ while ( (sbits32) rem0 < 0 ) {
+ --zSig0;
+ add96( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 );
+ }
+ zSig1 = estimateDiv64To32( rem1, rem2, bSig0 );
+ if ( ( zSig1 & 0x3FF ) <= 4 ) {
+ mul64By32To96( bSig0, bSig1, zSig1, &term1, &term2, &term3 );
+ sub96( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 );
+ while ( (sbits32) rem1 < 0 ) {
+ --zSig1;
+ add96( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 );
+ }
+ zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
+ }
+ shift64ExtraRightJamming( zSig0, zSig1, 0, 11, &zSig0, &zSig1, &zSig2 );
+ return roundAndPackFloat64( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Returns the remainder of the double-precision floating-point value `a'
+with respect to the corresponding value `b'. The operation is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_rem( float64 a, float64 b )
+{
+ flag aSign, bSign, zSign;
+ int16 aExp, bExp, expDiff;
+ bits32 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2;
+ bits32 allZero, alternateASig0, alternateASig1, sigMean1;
+ sbits32 sigMean0;
+ float64 z;
+
+ aSig1 = extractFloat64Frac1( a );
+ aSig0 = extractFloat64Frac0( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ bSig1 = extractFloat64Frac1( b );
+ bSig0 = extractFloat64Frac0( b );
+ bExp = extractFloat64Exp( b );
+ bSign = extractFloat64Sign( b );
+ if ( aExp == 0x7FF ) {
+ if ( ( aSig0 | aSig1 )
+ || ( ( bExp == 0x7FF ) && ( bSig0 | bSig1 ) ) ) {
+ return propagateFloat64NaN( a, b );
+ }
+ goto invalid;
+ }
+ if ( bExp == 0x7FF ) {
+ if ( bSig0 | bSig1 ) return propagateFloat64NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ if ( ( bSig0 | bSig1 ) == 0 ) {
+ invalid:
+ float_raise( float_flag_invalid );
+ return float64_default_nan;
+ }
+ normalizeFloat64Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
+ }
+ if ( aExp == 0 ) {
+ if ( ( aSig0 | aSig1 ) == 0 ) return a;
+ normalizeFloat64Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+ }
+ expDiff = aExp - bExp;
+ if ( expDiff < -1 ) return a;
+ shortShift64Left(
+ aSig0 | 0x00100000, aSig1, 11 - ( expDiff < 0 ), &aSig0, &aSig1 );
+ shortShift64Left( bSig0 | 0x00100000, bSig1, 11, &bSig0, &bSig1 );
+ q = le64( bSig0, bSig1, aSig0, aSig1 );
+ if ( q ) sub64( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
+ expDiff -= 32;
+ while ( 0 < expDiff ) {
+ q = estimateDiv64To32( aSig0, aSig1, bSig0 );
+ q = ( 4 < q ) ? q - 4 : 0;
+ mul64By32To96( bSig0, bSig1, q, &term0, &term1, &term2 );
+ shortShift96Left( term0, term1, term2, 29, &term1, &term2, &allZero );
+ shortShift64Left( aSig0, aSig1, 29, &aSig0, &allZero );
+ sub64( aSig0, 0, term1, term2, &aSig0, &aSig1 );
+ expDiff -= 29;
+ }
+ if ( -32 < expDiff ) {
+ q = estimateDiv64To32( aSig0, aSig1, bSig0 );
+ q = ( 4 < q ) ? q - 4 : 0;
+ q >>= - expDiff;
+ shift64Right( bSig0, bSig1, 8, &bSig0, &bSig1 );
+ expDiff += 24;
+ if ( expDiff < 0 ) {
+ shift64Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
+ }
+ else {
+ shortShift64Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 );
+ }
+ mul64By32To96( bSig0, bSig1, q, &term0, &term1, &term2 );
+ sub64( aSig0, aSig1, term1, term2, &aSig0, &aSig1 );
+ }
+ else {
+ shift64Right( aSig0, aSig1, 8, &aSig0, &aSig1 );
+ shift64Right( bSig0, bSig1, 8, &bSig0, &bSig1 );
+ }
+ do {
+ alternateASig0 = aSig0;
+ alternateASig1 = aSig1;
+ ++q;
+ sub64( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
+ } while ( 0 <= (sbits32) aSig0 );
+ add64(
+ aSig0, aSig1, alternateASig0, alternateASig1, &sigMean0, &sigMean1 );
+ if ( ( sigMean0 < 0 )
+ || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) {
+ aSig0 = alternateASig0;
+ aSig1 = alternateASig1;
+ }
+ zSign = ( (sbits32) aSig0 < 0 );
+ if ( zSign ) sub64( 0, 0, aSig0, aSig1, &aSig0, &aSig1 );
+ return
+ normalizeRoundAndPackFloat64( aSign ^ zSign, bExp - 4, aSig0, aSig1 );
+
+}
+#endif
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Returns the square root of the double-precision floating-point value `a'.
+The operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_sqrt( float64 a )
+{
+ flag aSign;
+ int16 aExp, zExp;
+ bits32 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0;
+ bits32 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
+ float64 z;
+
+ aSig1 = extractFloat64Frac1( a );
+ aSig0 = extractFloat64Frac0( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ if ( aExp == 0x7FF ) {
+ if ( aSig0 | aSig1 ) return propagateFloat64NaN( a, a );
+ if ( ! aSign ) return a;
+ goto invalid;
+ }
+ if ( aSign ) {
+ if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a;
+ invalid:
+ float_raise( float_flag_invalid );
+ return float64_default_nan;
+ }
+ if ( aExp == 0 ) {
+ if ( ( aSig0 | aSig1 ) == 0 ) return packFloat64( 0, 0, 0, 0 );
+ normalizeFloat64Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+ }
+ zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE;
+ aSig0 |= 0x00100000;
+ shortShift64Left( aSig0, aSig1, 11, &term0, &term1 );
+ zSig0 = ( estimateSqrt32( aExp, term0 )>>1 ) + 1;
+ if ( zSig0 == 0 ) zSig0 = 0x7FFFFFFF;
+ doubleZSig0 = zSig0 + zSig0;
+ shortShift64Left( aSig0, aSig1, 9 - ( aExp & 1 ), &aSig0, &aSig1 );
+ mul32To64( zSig0, zSig0, &term0, &term1 );
+ sub64( aSig0, aSig1, term0, term1, &rem0, &rem1 );
+ while ( (sbits32) rem0 < 0 ) {
+ --zSig0;
+ doubleZSig0 -= 2;
+ add64( rem0, rem1, 0, doubleZSig0 | 1, &rem0, &rem1 );
+ }
+ zSig1 = estimateDiv64To32( rem1, 0, doubleZSig0 );
+ if ( ( zSig1 & 0x1FF ) <= 5 ) {
+ if ( zSig1 == 0 ) zSig1 = 1;
+ mul32To64( doubleZSig0, zSig1, &term1, &term2 );
+ sub64( rem1, 0, term1, term2, &rem1, &rem2 );
+ mul32To64( zSig1, zSig1, &term2, &term3 );
+ sub96( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
+ while ( (sbits32) rem1 < 0 ) {
+ --zSig1;
+ shortShift64Left( 0, zSig1, 1, &term2, &term3 );
+ term3 |= 1;
+ term2 |= doubleZSig0;
+ add96( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 );
+ }
+ zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
+ }
+ shift64ExtraRightJamming( zSig0, zSig1, 0, 10, &zSig0, &zSig1, &zSig2 );
+ return roundAndPackFloat64( 0, zExp, zSig0, zSig1, zSig2 );
+
+}
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is equal to
+the corresponding value `b', and 0 otherwise. The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_eq( float64 a, float64 b )
+{
+
+ if ( ( ( extractFloat64Exp( a ) == 0x7FF )
+ && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) )
+ || ( ( extractFloat64Exp( b ) == 0x7FF )
+ && ( extractFloat64Frac0( b ) | extractFloat64Frac1( b ) ) )
+ ) {
+ if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ return ( a == b ) ||
+ ( (bits64) ( ( FLOAT64_DEMANGLE(a) | FLOAT64_DEMANGLE(b) )<<1 ) == 0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is less than
+or equal to the corresponding value `b', and 0 otherwise. The comparison
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_le( float64 a, float64 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat64Exp( a ) == 0x7FF )
+ && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) )
+ || ( ( extractFloat64Exp( b ) == 0x7FF )
+ && ( extractFloat64Frac0( b ) | extractFloat64Frac1( b ) ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ aSign = extractFloat64Sign( a );
+ bSign = extractFloat64Sign( b );
+ if ( aSign != bSign )
+ return aSign ||
+ ( (bits64) ( ( FLOAT64_DEMANGLE(a) | FLOAT64_DEMANGLE(b) )<<1 ) ==
+ 0 );
+ return ( a == b ) ||
+ ( aSign ^ ( FLOAT64_DEMANGLE(a) < FLOAT64_DEMANGLE(b) ) );
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise. The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_lt( float64 a, float64 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat64Exp( a ) == 0x7FF )
+ && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) )
+ || ( ( extractFloat64Exp( b ) == 0x7FF )
+ && ( extractFloat64Frac0( b ) | extractFloat64Frac1( b ) ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ aSign = extractFloat64Sign( a );
+ bSign = extractFloat64Sign( b );
+ if ( aSign != bSign )
+ return aSign &&
+ ( (bits64) ( ( FLOAT64_DEMANGLE(a) | FLOAT64_DEMANGLE(b) )<<1 ) !=
+ 0 );
+ return ( a != b ) &&
+ ( aSign ^ ( FLOAT64_DEMANGLE(a) < FLOAT64_DEMANGLE(b) ) );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is equal to
+the corresponding value `b', and 0 otherwise. The invalid exception is
+raised if either operand is a NaN. Otherwise, the comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_eq_signaling( float64 a, float64 b )
+{
+
+ if ( ( ( extractFloat64Exp( a ) == 0x7FF )
+ && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) )
+ || ( ( extractFloat64Exp( b ) == 0x7FF )
+ && ( extractFloat64Frac0( b ) | extractFloat64Frac1( b ) ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is less than or
+equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
+cause an exception. Otherwise, the comparison is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_le_quiet( float64 a, float64 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat64Exp( a ) == 0x7FF )
+ && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) )
+ || ( ( extractFloat64Exp( b ) == 0x7FF )
+ && ( extractFloat64Frac0( b ) | extractFloat64Frac1( b ) ) )
+ ) {
+ if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ aSign = extractFloat64Sign( a );
+ bSign = extractFloat64Sign( b );
+ if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 );
+ return ( a == b ) || ( aSign ^ ( a < b ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
+exception. Otherwise, the comparison is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_lt_quiet( float64 a, float64 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat64Exp( a ) == 0x7FF )
+ && ( extractFloat64Frac0( a ) | extractFloat64Frac1( a ) ) )
+ || ( ( extractFloat64Exp( b ) == 0x7FF )
+ && ( extractFloat64Frac0( b ) | extractFloat64Frac1( b ) ) )
+ ) {
+ if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ aSign = extractFloat64Sign( a );
+ bSign = extractFloat64Sign( b );
+ if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 );
+ return ( a != b ) && ( aSign ^ ( a < b ) );
+
+}
+
+#endif
diff --git a/lib/libc/softfloat/bits64/softfloat-macros b/lib/libc/softfloat/bits64/softfloat-macros
new file mode 100644
index 0000000..f4647de
--- /dev/null
+++ b/lib/libc/softfloat/bits64/softfloat-macros
@@ -0,0 +1,746 @@
+/* $NetBSD: softfloat-macros,v 1.2 2009/02/16 10:23:35 tron Exp $ */
+/* $FreeBSD$ */
+
+/*
+===============================================================================
+
+This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+Shifts `a' right by the number of bits given in `count'. If any nonzero
+bits are shifted off, they are ``jammed'' into the least significant bit of
+the result by setting the least significant bit to 1. The value of `count'
+can be arbitrarily large; in particular, if `count' is greater than 32, the
+result will be either 0 or 1, depending on whether `a' is zero or nonzero.
+The result is stored in the location pointed to by `zPtr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void shift32RightJamming( bits32 a, int16 count, bits32 *zPtr )
+{
+ bits32 z;
+
+ if ( count == 0 ) {
+ z = a;
+ }
+ else if ( count < 32 ) {
+ z = ( a>>count ) | ( ( a<<( ( - count ) & 31 ) ) != 0 );
+ }
+ else {
+ z = ( a != 0 );
+ }
+ *zPtr = z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts `a' right by the number of bits given in `count'. If any nonzero
+bits are shifted off, they are ``jammed'' into the least significant bit of
+the result by setting the least significant bit to 1. The value of `count'
+can be arbitrarily large; in particular, if `count' is greater than 64, the
+result will be either 0 or 1, depending on whether `a' is zero or nonzero.
+The result is stored in the location pointed to by `zPtr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void shift64RightJamming( bits64 a, int16 count, bits64 *zPtr )
+{
+ bits64 z;
+
+ if ( count == 0 ) {
+ z = a;
+ }
+ else if ( count < 64 ) {
+ z = ( a>>count ) | ( ( a<<( ( - count ) & 63 ) ) != 0 );
+ }
+ else {
+ z = ( a != 0 );
+ }
+ *zPtr = z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 128-bit value formed by concatenating `a0' and `a1' right by 64
+_plus_ the number of bits given in `count'. The shifted result is at most
+64 nonzero bits; this is stored at the location pointed to by `z0Ptr'. The
+bits shifted off form a second 64-bit result as follows: The _last_ bit
+shifted off is the most-significant bit of the extra result, and the other
+63 bits of the extra result are all zero if and only if _all_but_the_last_
+bits shifted off were all zero. This extra result is stored in the location
+pointed to by `z1Ptr'. The value of `count' can be arbitrarily large.
+ (This routine makes more sense if `a0' and `a1' are considered to form a
+fixed-point value with binary point between `a0' and `a1'. This fixed-point
+value is shifted right by the number of bits given in `count', and the
+integer part of the result is returned at the location pointed to by
+`z0Ptr'. The fractional part of the result may be slightly corrupted as
+described above, and is returned at the location pointed to by `z1Ptr'.)
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shift64ExtraRightJamming(
+ bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
+{
+ bits64 z0, z1;
+ int8 negCount = ( - count ) & 63;
+
+ if ( count == 0 ) {
+ z1 = a1;
+ z0 = a0;
+ }
+ else if ( count < 64 ) {
+ z1 = ( a0<<negCount ) | ( a1 != 0 );
+ z0 = a0>>count;
+ }
+ else {
+ if ( count == 64 ) {
+ z1 = a0 | ( a1 != 0 );
+ }
+ else {
+ z1 = ( ( a0 | a1 ) != 0 );
+ }
+ z0 = 0;
+ }
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
+number of bits given in `count'. Any bits shifted off are lost. The value
+of `count' can be arbitrarily large; in particular, if `count' is greater
+than 128, the result will be 0. The result is broken into two 64-bit pieces
+which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shift128Right(
+ bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
+{
+ bits64 z0, z1;
+ int8 negCount = ( - count ) & 63;
+
+ if ( count == 0 ) {
+ z1 = a1;
+ z0 = a0;
+ }
+ else if ( count < 64 ) {
+ z1 = ( a0<<negCount ) | ( a1>>count );
+ z0 = a0>>count;
+ }
+ else {
+ z1 = ( count < 64 ) ? ( a0>>( count & 63 ) ) : 0;
+ z0 = 0;
+ }
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 128-bit value formed by concatenating `a0' and `a1' right by the
+number of bits given in `count'. If any nonzero bits are shifted off, they
+are ``jammed'' into the least significant bit of the result by setting the
+least significant bit to 1. The value of `count' can be arbitrarily large;
+in particular, if `count' is greater than 128, the result will be either
+0 or 1, depending on whether the concatenation of `a0' and `a1' is zero or
+nonzero. The result is broken into two 64-bit pieces which are stored at
+the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shift128RightJamming(
+ bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
+{
+ bits64 z0, z1;
+ int8 negCount = ( - count ) & 63;
+
+ if ( count == 0 ) {
+ z1 = a1;
+ z0 = a0;
+ }
+ else if ( count < 64 ) {
+ z1 = ( a0<<negCount ) | ( a1>>count ) | ( ( a1<<negCount ) != 0 );
+ z0 = a0>>count;
+ }
+ else {
+ if ( count == 64 ) {
+ z1 = a0 | ( a1 != 0 );
+ }
+ else if ( count < 128 ) {
+ z1 = ( a0>>( count & 63 ) ) | ( ( ( a0<<negCount ) | a1 ) != 0 );
+ }
+ else {
+ z1 = ( ( a0 | a1 ) != 0 );
+ }
+ z0 = 0;
+ }
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' right
+by 64 _plus_ the number of bits given in `count'. The shifted result is
+at most 128 nonzero bits; these are broken into two 64-bit pieces which are
+stored at the locations pointed to by `z0Ptr' and `z1Ptr'. The bits shifted
+off form a third 64-bit result as follows: The _last_ bit shifted off is
+the most-significant bit of the extra result, and the other 63 bits of the
+extra result are all zero if and only if _all_but_the_last_ bits shifted off
+were all zero. This extra result is stored in the location pointed to by
+`z2Ptr'. The value of `count' can be arbitrarily large.
+ (This routine makes more sense if `a0', `a1', and `a2' are considered
+to form a fixed-point value with binary point between `a1' and `a2'. This
+fixed-point value is shifted right by the number of bits given in `count',
+and the integer part of the result is returned at the locations pointed to
+by `z0Ptr' and `z1Ptr'. The fractional part of the result may be slightly
+corrupted as described above, and is returned at the location pointed to by
+`z2Ptr'.)
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shift128ExtraRightJamming(
+ bits64 a0,
+ bits64 a1,
+ bits64 a2,
+ int16 count,
+ bits64 *z0Ptr,
+ bits64 *z1Ptr,
+ bits64 *z2Ptr
+ )
+{
+ bits64 z0, z1, z2;
+ int8 negCount = ( - count ) & 63;
+
+ if ( count == 0 ) {
+ z2 = a2;
+ z1 = a1;
+ z0 = a0;
+ }
+ else {
+ if ( count < 64 ) {
+ z2 = a1<<negCount;
+ z1 = ( a0<<negCount ) | ( a1>>count );
+ z0 = a0>>count;
+ }
+ else {
+ if ( count == 64 ) {
+ z2 = a1;
+ z1 = a0;
+ }
+ else {
+ a2 |= a1;
+ if ( count < 128 ) {
+ z2 = a0<<negCount;
+ z1 = a0>>( count & 63 );
+ }
+ else {
+ z2 = ( count == 128 ) ? a0 : ( a0 != 0 );
+ z1 = 0;
+ }
+ }
+ z0 = 0;
+ }
+ z2 |= ( a2 != 0 );
+ }
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 128-bit value formed by concatenating `a0' and `a1' left by the
+number of bits given in `count'. Any bits shifted off are lost. The value
+of `count' must be less than 64. The result is broken into two 64-bit
+pieces which are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shortShift128Left(
+ bits64 a0, bits64 a1, int16 count, bits64 *z0Ptr, bits64 *z1Ptr )
+{
+
+ *z1Ptr = a1<<count;
+ *z0Ptr =
+ ( count == 0 ) ? a0 : ( a0<<count ) | ( a1>>( ( - count ) & 63 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Shifts the 192-bit value formed by concatenating `a0', `a1', and `a2' left
+by the number of bits given in `count'. Any bits shifted off are lost.
+The value of `count' must be less than 64. The result is broken into three
+64-bit pieces which are stored at the locations pointed to by `z0Ptr',
+`z1Ptr', and `z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ shortShift192Left(
+ bits64 a0,
+ bits64 a1,
+ bits64 a2,
+ int16 count,
+ bits64 *z0Ptr,
+ bits64 *z1Ptr,
+ bits64 *z2Ptr
+ )
+{
+ bits64 z0, z1, z2;
+ int8 negCount;
+
+ z2 = a2<<count;
+ z1 = a1<<count;
+ z0 = a0<<count;
+ if ( 0 < count ) {
+ negCount = ( ( - count ) & 63 );
+ z1 |= a2>>negCount;
+ z0 |= a1>>negCount;
+ }
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
+value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so
+any carry out is lost. The result is broken into two 64-bit pieces which
+are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ add128(
+ bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
+{
+ bits64 z1;
+
+ z1 = a1 + b1;
+ *z1Ptr = z1;
+ *z0Ptr = a0 + b0 + ( z1 < a1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Adds the 192-bit value formed by concatenating `a0', `a1', and `a2' to the
+192-bit value formed by concatenating `b0', `b1', and `b2'. Addition is
+modulo 2^192, so any carry out is lost. The result is broken into three
+64-bit pieces which are stored at the locations pointed to by `z0Ptr',
+`z1Ptr', and `z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ add192(
+ bits64 a0,
+ bits64 a1,
+ bits64 a2,
+ bits64 b0,
+ bits64 b1,
+ bits64 b2,
+ bits64 *z0Ptr,
+ bits64 *z1Ptr,
+ bits64 *z2Ptr
+ )
+{
+ bits64 z0, z1, z2;
+ int8 carry0, carry1;
+
+ z2 = a2 + b2;
+ carry1 = ( z2 < a2 );
+ z1 = a1 + b1;
+ carry0 = ( z1 < a1 );
+ z0 = a0 + b0;
+ z1 += carry1;
+ z0 += ( z1 < (bits64)carry1 );
+ z0 += carry0;
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the
+128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
+2^128, so any borrow out (carry out) is lost. The result is broken into two
+64-bit pieces which are stored at the locations pointed to by `z0Ptr' and
+`z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ sub128(
+ bits64 a0, bits64 a1, bits64 b0, bits64 b1, bits64 *z0Ptr, bits64 *z1Ptr )
+{
+
+ *z1Ptr = a1 - b1;
+ *z0Ptr = a0 - b0 - ( a1 < b1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Subtracts the 192-bit value formed by concatenating `b0', `b1', and `b2'
+from the 192-bit value formed by concatenating `a0', `a1', and `a2'.
+Subtraction is modulo 2^192, so any borrow out (carry out) is lost. The
+result is broken into three 64-bit pieces which are stored at the locations
+pointed to by `z0Ptr', `z1Ptr', and `z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ sub192(
+ bits64 a0,
+ bits64 a1,
+ bits64 a2,
+ bits64 b0,
+ bits64 b1,
+ bits64 b2,
+ bits64 *z0Ptr,
+ bits64 *z1Ptr,
+ bits64 *z2Ptr
+ )
+{
+ bits64 z0, z1, z2;
+ int8 borrow0, borrow1;
+
+ z2 = a2 - b2;
+ borrow1 = ( a2 < b2 );
+ z1 = a1 - b1;
+ borrow0 = ( a1 < b1 );
+ z0 = a0 - b0;
+ z0 -= ( z1 < (bits64)borrow1 );
+ z1 -= borrow1;
+ z0 -= borrow0;
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Multiplies `a' by `b' to obtain a 128-bit product. The product is broken
+into two 64-bit pieces which are stored at the locations pointed to by
+`z0Ptr' and `z1Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void mul64To128( bits64 a, bits64 b, bits64 *z0Ptr, bits64 *z1Ptr )
+{
+ bits32 aHigh, aLow, bHigh, bLow;
+ bits64 z0, zMiddleA, zMiddleB, z1;
+
+ aLow = a;
+ aHigh = a>>32;
+ bLow = b;
+ bHigh = b>>32;
+ z1 = ( (bits64) aLow ) * bLow;
+ zMiddleA = ( (bits64) aLow ) * bHigh;
+ zMiddleB = ( (bits64) aHigh ) * bLow;
+ z0 = ( (bits64) aHigh ) * bHigh;
+ zMiddleA += zMiddleB;
+ z0 += ( ( (bits64) ( zMiddleA < zMiddleB ) )<<32 ) + ( zMiddleA>>32 );
+ zMiddleA <<= 32;
+ z1 += zMiddleA;
+ z0 += ( z1 < zMiddleA );
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Multiplies the 128-bit value formed by concatenating `a0' and `a1' by
+`b' to obtain a 192-bit product. The product is broken into three 64-bit
+pieces which are stored at the locations pointed to by `z0Ptr', `z1Ptr', and
+`z2Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ mul128By64To192(
+ bits64 a0,
+ bits64 a1,
+ bits64 b,
+ bits64 *z0Ptr,
+ bits64 *z1Ptr,
+ bits64 *z2Ptr
+ )
+{
+ bits64 z0, z1, z2, more1;
+
+ mul64To128( a1, b, &z1, &z2 );
+ mul64To128( a0, b, &z0, &more1 );
+ add128( z0, more1, 0, z1, &z0, &z1 );
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Multiplies the 128-bit value formed by concatenating `a0' and `a1' to the
+128-bit value formed by concatenating `b0' and `b1' to obtain a 256-bit
+product. The product is broken into four 64-bit pieces which are stored at
+the locations pointed to by `z0Ptr', `z1Ptr', `z2Ptr', and `z3Ptr'.
+-------------------------------------------------------------------------------
+*/
+INLINE void
+ mul128To256(
+ bits64 a0,
+ bits64 a1,
+ bits64 b0,
+ bits64 b1,
+ bits64 *z0Ptr,
+ bits64 *z1Ptr,
+ bits64 *z2Ptr,
+ bits64 *z3Ptr
+ )
+{
+ bits64 z0, z1, z2, z3;
+ bits64 more1, more2;
+
+ mul64To128( a1, b1, &z2, &z3 );
+ mul64To128( a1, b0, &z1, &more2 );
+ add128( z1, more2, 0, z2, &z1, &z2 );
+ mul64To128( a0, b0, &z0, &more1 );
+ add128( z0, more1, 0, z1, &z0, &z1 );
+ mul64To128( a0, b1, &more1, &more2 );
+ add128( more1, more2, 0, z2, &more1, &z2 );
+ add128( z0, z1, 0, more1, &z0, &z1 );
+ *z3Ptr = z3;
+ *z2Ptr = z2;
+ *z1Ptr = z1;
+ *z0Ptr = z0;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns an approximation to the 64-bit integer quotient obtained by dividing
+`b' into the 128-bit value formed by concatenating `a0' and `a1'. The
+divisor `b' must be at least 2^63. If q is the exact quotient truncated
+toward zero, the approximation returned lies between q and q + 2 inclusive.
+If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
+unsigned integer is returned.
+-------------------------------------------------------------------------------
+*/
+static bits64 estimateDiv128To64( bits64 a0, bits64 a1, bits64 b )
+{
+ bits64 b0, b1;
+ bits64 rem0, rem1, term0, term1;
+ bits64 z;
+
+ if ( b <= a0 ) return LIT64( 0xFFFFFFFFFFFFFFFF );
+ b0 = b>>32;
+ z = ( b0<<32 <= a0 ) ? LIT64( 0xFFFFFFFF00000000 ) : ( a0 / b0 )<<32;
+ mul64To128( b, z, &term0, &term1 );
+ sub128( a0, a1, term0, term1, &rem0, &rem1 );
+ while ( ( (sbits64) rem0 ) < 0 ) {
+ z -= LIT64( 0x100000000 );
+ b1 = b<<32;
+ add128( rem0, rem1, b0, b1, &rem0, &rem1 );
+ }
+ rem0 = ( rem0<<32 ) | ( rem1>>32 );
+ z |= ( b0<<32 <= rem0 ) ? 0xFFFFFFFF : rem0 / b0;
+ return z;
+
+}
+
+#if !defined(SOFTFLOAT_FOR_GCC) || defined(FLOATX80) || defined(FLOAT128)
+/*
+-------------------------------------------------------------------------------
+Returns an approximation to the square root of the 32-bit significand given
+by `a'. Considered as an integer, `a' must be at least 2^31. If bit 0 of
+`aExp' (the least significant bit) is 1, the integer returned approximates
+2^31*sqrt(`a'/2^31), where `a' is considered an integer. If bit 0 of `aExp'
+is 0, the integer returned approximates 2^31*sqrt(`a'/2^30). In either
+case, the approximation returned lies strictly within +/-2 of the exact
+value.
+-------------------------------------------------------------------------------
+*/
+static bits32 estimateSqrt32( int16 aExp, bits32 a )
+{
+ static const bits16 sqrtOddAdjustments[] = {
+ 0x0004, 0x0022, 0x005D, 0x00B1, 0x011D, 0x019F, 0x0236, 0x02E0,
+ 0x039C, 0x0468, 0x0545, 0x0631, 0x072B, 0x0832, 0x0946, 0x0A67
+ };
+ static const bits16 sqrtEvenAdjustments[] = {
+ 0x0A2D, 0x08AF, 0x075A, 0x0629, 0x051A, 0x0429, 0x0356, 0x029E,
+ 0x0200, 0x0179, 0x0109, 0x00AF, 0x0068, 0x0034, 0x0012, 0x0002
+ };
+ int8 idx;
+ bits32 z;
+
+ idx = ( a>>27 ) & 15;
+ if ( aExp & 1 ) {
+ z = 0x4000 + ( a>>17 ) - sqrtOddAdjustments[ idx ];
+ z = ( ( a / z )<<14 ) + ( z<<15 );
+ a >>= 1;
+ }
+ else {
+ z = 0x8000 + ( a>>17 ) - sqrtEvenAdjustments[ idx ];
+ z = a / z + z;
+ z = ( 0x20000 <= z ) ? 0xFFFF8000 : ( z<<15 );
+ if ( z <= a ) return (bits32) ( ( (sbits32) a )>>1 );
+ }
+ return ( (bits32) ( ( ( (bits64) a )<<31 ) / z ) ) + ( z>>1 );
+
+}
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns the number of leading 0 bits before the most-significant 1 bit of
+`a'. If `a' is zero, 32 is returned.
+-------------------------------------------------------------------------------
+*/
+static int8 countLeadingZeros32( bits32 a )
+{
+ static const int8 countLeadingZerosHigh[] = {
+ 8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+ };
+ int8 shiftCount;
+
+ shiftCount = 0;
+ if ( a < 0x10000 ) {
+ shiftCount += 16;
+ a <<= 16;
+ }
+ if ( a < 0x1000000 ) {
+ shiftCount += 8;
+ a <<= 8;
+ }
+ shiftCount += countLeadingZerosHigh[ a>>24 ];
+ return shiftCount;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the number of leading 0 bits before the most-significant 1 bit of
+`a'. If `a' is zero, 64 is returned.
+-------------------------------------------------------------------------------
+*/
+static int8 countLeadingZeros64( bits64 a )
+{
+ int8 shiftCount;
+
+ shiftCount = 0;
+ if ( a < ( (bits64) 1 )<<32 ) {
+ shiftCount += 32;
+ }
+ else {
+ a >>= 32;
+ }
+ shiftCount += countLeadingZeros32( a );
+ return shiftCount;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the 128-bit value formed by concatenating `a0' and `a1'
+is equal to the 128-bit value formed by concatenating `b0' and `b1'.
+Otherwise, returns 0.
+-------------------------------------------------------------------------------
+*/
+INLINE flag eq128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
+{
+
+ return ( a0 == b0 ) && ( a1 == b1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
+than or equal to the 128-bit value formed by concatenating `b0' and `b1'.
+Otherwise, returns 0.
+-------------------------------------------------------------------------------
+*/
+INLINE flag le128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
+{
+
+ return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 <= b1 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is less
+than the 128-bit value formed by concatenating `b0' and `b1'. Otherwise,
+returns 0.
+-------------------------------------------------------------------------------
+*/
+INLINE flag lt128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
+{
+
+ return ( a0 < b0 ) || ( ( a0 == b0 ) && ( a1 < b1 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the 128-bit value formed by concatenating `a0' and `a1' is
+not equal to the 128-bit value formed by concatenating `b0' and `b1'.
+Otherwise, returns 0.
+-------------------------------------------------------------------------------
+*/
+INLINE flag ne128( bits64 a0, bits64 a1, bits64 b0, bits64 b1 )
+{
+
+ return ( a0 != b0 ) || ( a1 != b1 );
+
+}
+
diff --git a/lib/libc/softfloat/bits64/softfloat.c b/lib/libc/softfloat/bits64/softfloat.c
new file mode 100644
index 0000000..79993fb
--- /dev/null
+++ b/lib/libc/softfloat/bits64/softfloat.c
@@ -0,0 +1,5599 @@
+/* $NetBSD: softfloat.c,v 1.8 2011/07/10 04:52:23 matt Exp $ */
+
+/*
+ * This version hacked for use with gcc -msoft-float by bjh21.
+ * (Mostly a case of #ifdefing out things GCC doesn't need or provides
+ * itself).
+ */
+
+/*
+ * Things you may want to define:
+ *
+ * SOFTFLOAT_FOR_GCC - build only those functions necessary for GCC (with
+ * -msoft-float) to work. Include "softfloat-for-gcc.h" to get them
+ * properly renamed.
+ */
+
+/*
+===============================================================================
+
+This C source file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef SOFTFLOAT_FOR_GCC
+#include "softfloat-for-gcc.h"
+#endif
+
+#include "milieu.h"
+#include "softfloat.h"
+
+/*
+ * Conversions between floats as stored in memory and floats as
+ * SoftFloat uses them
+ */
+#ifndef FLOAT64_DEMANGLE
+#define FLOAT64_DEMANGLE(a) (a)
+#endif
+#ifndef FLOAT64_MANGLE
+#define FLOAT64_MANGLE(a) (a)
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Floating-point rounding mode, extended double-precision rounding precision,
+and exception flags.
+-------------------------------------------------------------------------------
+*/
+int float_rounding_mode = float_round_nearest_even;
+int float_exception_flags = 0;
+#ifdef FLOATX80
+int8 floatx80_rounding_precision = 80;
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Primitive arithmetic functions, including multi-word arithmetic, and
+division and square root approximations. (Can be specialized to target if
+desired.)
+-------------------------------------------------------------------------------
+*/
+#include "softfloat-macros"
+
+/*
+-------------------------------------------------------------------------------
+Functions and definitions to determine: (1) whether tininess for underflow
+is detected before or after rounding by default, (2) what (if anything)
+happens when exceptions are raised, (3) how signaling NaNs are distinguished
+from quiet NaNs, (4) the default generated quiet NaNs, and (5) how NaNs
+are propagated from function inputs to output. These details are target-
+specific.
+-------------------------------------------------------------------------------
+*/
+#include "softfloat-specialize"
+
+#if !defined(SOFTFLOAT_FOR_GCC) || defined(FLOATX80) || defined(FLOAT128)
+/*
+-------------------------------------------------------------------------------
+Takes a 64-bit fixed-point value `absZ' with binary point between bits 6
+and 7, and returns the properly rounded 32-bit integer corresponding to the
+input. If `zSign' is 1, the input is negated before being converted to an
+integer. Bit 63 of `absZ' must be zero. Ordinarily, the fixed-point input
+is simply rounded to an integer, with the inexact exception raised if the
+input cannot be represented exactly as an integer. However, if the fixed-
+point input is too large, the invalid exception is raised and the largest
+positive or negative integer is returned.
+-------------------------------------------------------------------------------
+*/
+static int32 roundAndPackInt32( flag zSign, bits64 absZ )
+{
+ int8 roundingMode;
+ flag roundNearestEven;
+ int8 roundIncrement, roundBits;
+ int32 z;
+
+ roundingMode = float_rounding_mode;
+ roundNearestEven = ( roundingMode == float_round_nearest_even );
+ roundIncrement = 0x40;
+ if ( ! roundNearestEven ) {
+ if ( roundingMode == float_round_to_zero ) {
+ roundIncrement = 0;
+ }
+ else {
+ roundIncrement = 0x7F;
+ if ( zSign ) {
+ if ( roundingMode == float_round_up ) roundIncrement = 0;
+ }
+ else {
+ if ( roundingMode == float_round_down ) roundIncrement = 0;
+ }
+ }
+ }
+ roundBits = absZ & 0x7F;
+ absZ = ( absZ + roundIncrement )>>7;
+ absZ &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
+ z = absZ;
+ if ( zSign ) z = - z;
+ if ( ( absZ>>32 ) || ( z && ( ( z < 0 ) ^ zSign ) ) ) {
+ float_raise( float_flag_invalid );
+ return zSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
+ }
+ if ( roundBits ) float_exception_flags |= float_flag_inexact;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes the 128-bit fixed-point value formed by concatenating `absZ0' and
+`absZ1', with binary point between bits 63 and 64 (between the input words),
+and returns the properly rounded 64-bit integer corresponding to the input.
+If `zSign' is 1, the input is negated before being converted to an integer.
+Ordinarily, the fixed-point input is simply rounded to an integer, with
+the inexact exception raised if the input cannot be represented exactly as
+an integer. However, if the fixed-point input is too large, the invalid
+exception is raised and the largest positive or negative integer is
+returned.
+-------------------------------------------------------------------------------
+*/
+static int64 roundAndPackInt64( flag zSign, bits64 absZ0, bits64 absZ1 )
+{
+ int8 roundingMode;
+ flag roundNearestEven, increment;
+ int64 z;
+
+ roundingMode = float_rounding_mode;
+ roundNearestEven = ( roundingMode == float_round_nearest_even );
+ increment = ( (sbits64) absZ1 < 0 );
+ if ( ! roundNearestEven ) {
+ if ( roundingMode == float_round_to_zero ) {
+ increment = 0;
+ }
+ else {
+ if ( zSign ) {
+ increment = ( roundingMode == float_round_down ) && absZ1;
+ }
+ else {
+ increment = ( roundingMode == float_round_up ) && absZ1;
+ }
+ }
+ }
+ if ( increment ) {
+ ++absZ0;
+ if ( absZ0 == 0 ) goto overflow;
+ absZ0 &= ~ ( ( (bits64) ( absZ1<<1 ) == 0 ) & roundNearestEven );
+ }
+ z = absZ0;
+ if ( zSign ) z = - z;
+ if ( z && ( ( z < 0 ) ^ zSign ) ) {
+ overflow:
+ float_raise( float_flag_invalid );
+ return
+ zSign ? (sbits64) LIT64( 0x8000000000000000 )
+ : LIT64( 0x7FFFFFFFFFFFFFFF );
+ }
+ if ( absZ1 ) float_exception_flags |= float_flag_inexact;
+ return z;
+
+}
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns the fraction bits of the single-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE bits32 extractFloat32Frac( float32 a )
+{
+
+ return a & 0x007FFFFF;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the exponent bits of the single-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE int16 extractFloat32Exp( float32 a )
+{
+
+ return ( a>>23 ) & 0xFF;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the sign bit of the single-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE flag extractFloat32Sign( float32 a )
+{
+
+ return a>>31;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Normalizes the subnormal single-precision floating-point value represented
+by the denormalized significand `aSig'. The normalized exponent and
+significand are stored at the locations pointed to by `zExpPtr' and
+`zSigPtr', respectively.
+-------------------------------------------------------------------------------
+*/
+static void
+ normalizeFloat32Subnormal( bits32 aSig, int16 *zExpPtr, bits32 *zSigPtr )
+{
+ int8 shiftCount;
+
+ shiftCount = countLeadingZeros32( aSig ) - 8;
+ *zSigPtr = aSig<<shiftCount;
+ *zExpPtr = 1 - shiftCount;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
+single-precision floating-point value, returning the result. After being
+shifted into the proper positions, the three fields are simply added
+together to form the result. This means that any integer portion of `zSig'
+will be added into the exponent. Since a properly normalized significand
+will have an integer portion equal to 1, the `zExp' input should be 1 less
+than the desired result exponent whenever `zSig' is a complete, normalized
+significand.
+-------------------------------------------------------------------------------
+*/
+INLINE float32 packFloat32( flag zSign, int16 zExp, bits32 zSig )
+{
+
+ return ( ( (bits32) zSign )<<31 ) + ( ( (bits32) zExp )<<23 ) + zSig;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and significand `zSig', and returns the proper single-precision floating-
+point value corresponding to the abstract input. Ordinarily, the abstract
+value is simply rounded and packed into the single-precision format, with
+the inexact exception raised if the abstract input cannot be represented
+exactly. However, if the abstract value is too large, the overflow and
+inexact exceptions are raised and an infinity or maximal finite value is
+returned. If the abstract value is too small, the input value is rounded to
+a subnormal number, and the underflow and inexact exceptions are raised if
+the abstract input cannot be represented exactly as a subnormal single-
+precision floating-point number.
+ The input significand `zSig' has its binary point between bits 30
+and 29, which is 7 bits to the left of the usual location. This shifted
+significand must be normalized or smaller. If `zSig' is not normalized,
+`zExp' must be 0; in that case, the result returned is a subnormal number,
+and it must not require rounding. In the usual case that `zSig' is
+normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
+The handling of underflow and overflow follows the IEC/IEEE Standard for
+Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float32 roundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
+{
+ int8 roundingMode;
+ flag roundNearestEven;
+ int8 roundIncrement, roundBits;
+ flag isTiny;
+
+ roundingMode = float_rounding_mode;
+ roundNearestEven = ( roundingMode == float_round_nearest_even );
+ roundIncrement = 0x40;
+ if ( ! roundNearestEven ) {
+ if ( roundingMode == float_round_to_zero ) {
+ roundIncrement = 0;
+ }
+ else {
+ roundIncrement = 0x7F;
+ if ( zSign ) {
+ if ( roundingMode == float_round_up ) roundIncrement = 0;
+ }
+ else {
+ if ( roundingMode == float_round_down ) roundIncrement = 0;
+ }
+ }
+ }
+ roundBits = zSig & 0x7F;
+ if ( 0xFD <= (bits16) zExp ) {
+ if ( ( 0xFD < zExp )
+ || ( ( zExp == 0xFD )
+ && ( (sbits32) ( zSig + roundIncrement ) < 0 ) )
+ ) {
+ float_raise( float_flag_overflow | float_flag_inexact );
+ return packFloat32( zSign, 0xFF, 0 ) - ( roundIncrement == 0 );
+ }
+ if ( zExp < 0 ) {
+ isTiny =
+ ( float_detect_tininess == float_tininess_before_rounding )
+ || ( zExp < -1 )
+ || ( zSig + roundIncrement < 0x80000000 );
+ shift32RightJamming( zSig, - zExp, &zSig );
+ zExp = 0;
+ roundBits = zSig & 0x7F;
+ if ( isTiny && roundBits ) float_raise( float_flag_underflow );
+ }
+ }
+ if ( roundBits ) float_exception_flags |= float_flag_inexact;
+ zSig = ( zSig + roundIncrement )>>7;
+ zSig &= ~ ( ( ( roundBits ^ 0x40 ) == 0 ) & roundNearestEven );
+ if ( zSig == 0 ) zExp = 0;
+ return packFloat32( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and significand `zSig', and returns the proper single-precision floating-
+point value corresponding to the abstract input. This routine is just like
+`roundAndPackFloat32' except that `zSig' does not have to be normalized.
+Bit 31 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
+floating-point exponent.
+-------------------------------------------------------------------------------
+*/
+static float32
+ normalizeRoundAndPackFloat32( flag zSign, int16 zExp, bits32 zSig )
+{
+ int8 shiftCount;
+
+ shiftCount = countLeadingZeros32( zSig ) - 1;
+ return roundAndPackFloat32( zSign, zExp - shiftCount, zSig<<shiftCount );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the fraction bits of the double-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE bits64 extractFloat64Frac( float64 a )
+{
+
+ return FLOAT64_DEMANGLE(a) & LIT64( 0x000FFFFFFFFFFFFF );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the exponent bits of the double-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE int16 extractFloat64Exp( float64 a )
+{
+
+ return ( FLOAT64_DEMANGLE(a)>>52 ) & 0x7FF;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the sign bit of the double-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE flag extractFloat64Sign( float64 a )
+{
+
+ return FLOAT64_DEMANGLE(a)>>63;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Normalizes the subnormal double-precision floating-point value represented
+by the denormalized significand `aSig'. The normalized exponent and
+significand are stored at the locations pointed to by `zExpPtr' and
+`zSigPtr', respectively.
+-------------------------------------------------------------------------------
+*/
+static void
+ normalizeFloat64Subnormal( bits64 aSig, int16 *zExpPtr, bits64 *zSigPtr )
+{
+ int8 shiftCount;
+
+ shiftCount = countLeadingZeros64( aSig ) - 11;
+ *zSigPtr = aSig<<shiftCount;
+ *zExpPtr = 1 - shiftCount;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Packs the sign `zSign', exponent `zExp', and significand `zSig' into a
+double-precision floating-point value, returning the result. After being
+shifted into the proper positions, the three fields are simply added
+together to form the result. This means that any integer portion of `zSig'
+will be added into the exponent. Since a properly normalized significand
+will have an integer portion equal to 1, the `zExp' input should be 1 less
+than the desired result exponent whenever `zSig' is a complete, normalized
+significand.
+-------------------------------------------------------------------------------
+*/
+INLINE float64 packFloat64( flag zSign, int16 zExp, bits64 zSig )
+{
+
+ return FLOAT64_MANGLE( ( ( (bits64) zSign )<<63 ) +
+ ( ( (bits64) zExp )<<52 ) + zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and significand `zSig', and returns the proper double-precision floating-
+point value corresponding to the abstract input. Ordinarily, the abstract
+value is simply rounded and packed into the double-precision format, with
+the inexact exception raised if the abstract input cannot be represented
+exactly. However, if the abstract value is too large, the overflow and
+inexact exceptions are raised and an infinity or maximal finite value is
+returned. If the abstract value is too small, the input value is rounded to
+a subnormal number, and the underflow and inexact exceptions are raised if
+the abstract input cannot be represented exactly as a subnormal double-
+precision floating-point number.
+ The input significand `zSig' has its binary point between bits 62
+and 61, which is 10 bits to the left of the usual location. This shifted
+significand must be normalized or smaller. If `zSig' is not normalized,
+`zExp' must be 0; in that case, the result returned is a subnormal number,
+and it must not require rounding. In the usual case that `zSig' is
+normalized, `zExp' must be 1 less than the ``true'' floating-point exponent.
+The handling of underflow and overflow follows the IEC/IEEE Standard for
+Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float64 roundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
+{
+ int8 roundingMode;
+ flag roundNearestEven;
+ int16 roundIncrement, roundBits;
+ flag isTiny;
+
+ roundingMode = float_rounding_mode;
+ roundNearestEven = ( roundingMode == float_round_nearest_even );
+ roundIncrement = 0x200;
+ if ( ! roundNearestEven ) {
+ if ( roundingMode == float_round_to_zero ) {
+ roundIncrement = 0;
+ }
+ else {
+ roundIncrement = 0x3FF;
+ if ( zSign ) {
+ if ( roundingMode == float_round_up ) roundIncrement = 0;
+ }
+ else {
+ if ( roundingMode == float_round_down ) roundIncrement = 0;
+ }
+ }
+ }
+ roundBits = zSig & 0x3FF;
+ if ( 0x7FD <= (bits16) zExp ) {
+ if ( ( 0x7FD < zExp )
+ || ( ( zExp == 0x7FD )
+ && ( (sbits64) ( zSig + roundIncrement ) < 0 ) )
+ ) {
+ float_raise( float_flag_overflow | float_flag_inexact );
+ return FLOAT64_MANGLE(
+ FLOAT64_DEMANGLE(packFloat64( zSign, 0x7FF, 0 )) -
+ ( roundIncrement == 0 ));
+ }
+ if ( zExp < 0 ) {
+ isTiny =
+ ( float_detect_tininess == float_tininess_before_rounding )
+ || ( zExp < -1 )
+ || ( zSig + roundIncrement < LIT64( 0x8000000000000000 ) );
+ shift64RightJamming( zSig, - zExp, &zSig );
+ zExp = 0;
+ roundBits = zSig & 0x3FF;
+ if ( isTiny && roundBits ) float_raise( float_flag_underflow );
+ }
+ }
+ if ( roundBits ) float_exception_flags |= float_flag_inexact;
+ zSig = ( zSig + roundIncrement )>>10;
+ zSig &= ~ ( ( ( roundBits ^ 0x200 ) == 0 ) & roundNearestEven );
+ if ( zSig == 0 ) zExp = 0;
+ return packFloat64( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and significand `zSig', and returns the proper double-precision floating-
+point value corresponding to the abstract input. This routine is just like
+`roundAndPackFloat64' except that `zSig' does not have to be normalized.
+Bit 63 of `zSig' must be zero, and `zExp' must be 1 less than the ``true''
+floating-point exponent.
+-------------------------------------------------------------------------------
+*/
+static float64
+ normalizeRoundAndPackFloat64( flag zSign, int16 zExp, bits64 zSig )
+{
+ int8 shiftCount;
+
+ shiftCount = countLeadingZeros64( zSig ) - 1;
+ return roundAndPackFloat64( zSign, zExp - shiftCount, zSig<<shiftCount );
+
+}
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Returns the fraction bits of the extended double-precision floating-point
+value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE bits64 extractFloatx80Frac( floatx80 a )
+{
+
+ return a.low;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the exponent bits of the extended double-precision floating-point
+value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE int32 extractFloatx80Exp( floatx80 a )
+{
+
+ return a.high & 0x7FFF;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the sign bit of the extended double-precision floating-point value
+`a'.
+-------------------------------------------------------------------------------
+*/
+INLINE flag extractFloatx80Sign( floatx80 a )
+{
+
+ return a.high>>15;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Normalizes the subnormal extended double-precision floating-point value
+represented by the denormalized significand `aSig'. The normalized exponent
+and significand are stored at the locations pointed to by `zExpPtr' and
+`zSigPtr', respectively.
+-------------------------------------------------------------------------------
+*/
+static void
+ normalizeFloatx80Subnormal( bits64 aSig, int32 *zExpPtr, bits64 *zSigPtr )
+{
+ int8 shiftCount;
+
+ shiftCount = countLeadingZeros64( aSig );
+ *zSigPtr = aSig<<shiftCount;
+ *zExpPtr = 1 - shiftCount;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Packs the sign `zSign', exponent `zExp', and significand `zSig' into an
+extended double-precision floating-point value, returning the result.
+-------------------------------------------------------------------------------
+*/
+INLINE floatx80 packFloatx80( flag zSign, int32 zExp, bits64 zSig )
+{
+ floatx80 z;
+
+ z.low = zSig;
+ z.high = ( ( (bits16) zSign )<<15 ) + zExp;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and extended significand formed by the concatenation of `zSig0' and `zSig1',
+and returns the proper extended double-precision floating-point value
+corresponding to the abstract input. Ordinarily, the abstract value is
+rounded and packed into the extended double-precision format, with the
+inexact exception raised if the abstract input cannot be represented
+exactly. However, if the abstract value is too large, the overflow and
+inexact exceptions are raised and an infinity or maximal finite value is
+returned. If the abstract value is too small, the input value is rounded to
+a subnormal number, and the underflow and inexact exceptions are raised if
+the abstract input cannot be represented exactly as a subnormal extended
+double-precision floating-point number.
+ If `roundingPrecision' is 32 or 64, the result is rounded to the same
+number of bits as single or double precision, respectively. Otherwise, the
+result is rounded to the full precision of the extended double-precision
+format.
+ The input significand must be normalized or smaller. If the input
+significand is not normalized, `zExp' must be 0; in that case, the result
+returned is a subnormal number, and it must not require rounding. The
+handling of underflow and overflow follows the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static floatx80
+ roundAndPackFloatx80(
+ int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
+ )
+{
+ int8 roundingMode;
+ flag roundNearestEven, increment, isTiny;
+ int64 roundIncrement, roundMask, roundBits;
+
+ roundingMode = float_rounding_mode;
+ roundNearestEven = ( roundingMode == float_round_nearest_even );
+ if ( roundingPrecision == 80 ) goto precision80;
+ if ( roundingPrecision == 64 ) {
+ roundIncrement = LIT64( 0x0000000000000400 );
+ roundMask = LIT64( 0x00000000000007FF );
+ }
+ else if ( roundingPrecision == 32 ) {
+ roundIncrement = LIT64( 0x0000008000000000 );
+ roundMask = LIT64( 0x000000FFFFFFFFFF );
+ }
+ else {
+ goto precision80;
+ }
+ zSig0 |= ( zSig1 != 0 );
+ if ( ! roundNearestEven ) {
+ if ( roundingMode == float_round_to_zero ) {
+ roundIncrement = 0;
+ }
+ else {
+ roundIncrement = roundMask;
+ if ( zSign ) {
+ if ( roundingMode == float_round_up ) roundIncrement = 0;
+ }
+ else {
+ if ( roundingMode == float_round_down ) roundIncrement = 0;
+ }
+ }
+ }
+ roundBits = zSig0 & roundMask;
+ if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) {
+ if ( ( 0x7FFE < zExp )
+ || ( ( zExp == 0x7FFE ) && ( zSig0 + roundIncrement < zSig0 ) )
+ ) {
+ goto overflow;
+ }
+ if ( zExp <= 0 ) {
+ isTiny =
+ ( float_detect_tininess == float_tininess_before_rounding )
+ || ( zExp < 0 )
+ || ( zSig0 <= zSig0 + roundIncrement );
+ shift64RightJamming( zSig0, 1 - zExp, &zSig0 );
+ zExp = 0;
+ roundBits = zSig0 & roundMask;
+ if ( isTiny && roundBits ) float_raise( float_flag_underflow );
+ if ( roundBits ) float_exception_flags |= float_flag_inexact;
+ zSig0 += roundIncrement;
+ if ( (sbits64) zSig0 < 0 ) zExp = 1;
+ roundIncrement = roundMask + 1;
+ if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
+ roundMask |= roundIncrement;
+ }
+ zSig0 &= ~ roundMask;
+ return packFloatx80( zSign, zExp, zSig0 );
+ }
+ }
+ if ( roundBits ) float_exception_flags |= float_flag_inexact;
+ zSig0 += roundIncrement;
+ if ( zSig0 < roundIncrement ) {
+ ++zExp;
+ zSig0 = LIT64( 0x8000000000000000 );
+ }
+ roundIncrement = roundMask + 1;
+ if ( roundNearestEven && ( roundBits<<1 == roundIncrement ) ) {
+ roundMask |= roundIncrement;
+ }
+ zSig0 &= ~ roundMask;
+ if ( zSig0 == 0 ) zExp = 0;
+ return packFloatx80( zSign, zExp, zSig0 );
+ precision80:
+ increment = ( (sbits64) zSig1 < 0 );
+ if ( ! roundNearestEven ) {
+ if ( roundingMode == float_round_to_zero ) {
+ increment = 0;
+ }
+ else {
+ if ( zSign ) {
+ increment = ( roundingMode == float_round_down ) && zSig1;
+ }
+ else {
+ increment = ( roundingMode == float_round_up ) && zSig1;
+ }
+ }
+ }
+ if ( 0x7FFD <= (bits32) ( zExp - 1 ) ) {
+ if ( ( 0x7FFE < zExp )
+ || ( ( zExp == 0x7FFE )
+ && ( zSig0 == LIT64( 0xFFFFFFFFFFFFFFFF ) )
+ && increment
+ )
+ ) {
+ roundMask = 0;
+ overflow:
+ float_raise( float_flag_overflow | float_flag_inexact );
+ if ( ( roundingMode == float_round_to_zero )
+ || ( zSign && ( roundingMode == float_round_up ) )
+ || ( ! zSign && ( roundingMode == float_round_down ) )
+ ) {
+ return packFloatx80( zSign, 0x7FFE, ~ roundMask );
+ }
+ return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ }
+ if ( zExp <= 0 ) {
+ isTiny =
+ ( float_detect_tininess == float_tininess_before_rounding )
+ || ( zExp < 0 )
+ || ! increment
+ || ( zSig0 < LIT64( 0xFFFFFFFFFFFFFFFF ) );
+ shift64ExtraRightJamming( zSig0, zSig1, 1 - zExp, &zSig0, &zSig1 );
+ zExp = 0;
+ if ( isTiny && zSig1 ) float_raise( float_flag_underflow );
+ if ( zSig1 ) float_exception_flags |= float_flag_inexact;
+ if ( roundNearestEven ) {
+ increment = ( (sbits64) zSig1 < 0 );
+ }
+ else {
+ if ( zSign ) {
+ increment = ( roundingMode == float_round_down ) && zSig1;
+ }
+ else {
+ increment = ( roundingMode == float_round_up ) && zSig1;
+ }
+ }
+ if ( increment ) {
+ ++zSig0;
+ zSig0 &=
+ ~ ( ( (bits64) ( zSig1<<1 ) == 0 ) & roundNearestEven );
+ if ( (sbits64) zSig0 < 0 ) zExp = 1;
+ }
+ return packFloatx80( zSign, zExp, zSig0 );
+ }
+ }
+ if ( zSig1 ) float_exception_flags |= float_flag_inexact;
+ if ( increment ) {
+ ++zSig0;
+ if ( zSig0 == 0 ) {
+ ++zExp;
+ zSig0 = LIT64( 0x8000000000000000 );
+ }
+ else {
+ zSig0 &= ~ ( ( (bits64) ( zSig1<<1 ) == 0 ) & roundNearestEven );
+ }
+ }
+ else {
+ if ( zSig0 == 0 ) zExp = 0;
+ }
+ return packFloatx80( zSign, zExp, zSig0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent
+`zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
+and returns the proper extended double-precision floating-point value
+corresponding to the abstract input. This routine is just like
+`roundAndPackFloatx80' except that the input significand does not have to be
+normalized.
+-------------------------------------------------------------------------------
+*/
+static floatx80
+ normalizeRoundAndPackFloatx80(
+ int8 roundingPrecision, flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1
+ )
+{
+ int8 shiftCount;
+
+ if ( zSig0 == 0 ) {
+ zSig0 = zSig1;
+ zSig1 = 0;
+ zExp -= 64;
+ }
+ shiftCount = countLeadingZeros64( zSig0 );
+ shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
+ zExp -= shiftCount;
+ return
+ roundAndPackFloatx80( roundingPrecision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Returns the least-significant 64 fraction bits of the quadruple-precision
+floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE bits64 extractFloat128Frac1( float128 a )
+{
+
+ return a.low;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the most-significant 48 fraction bits of the quadruple-precision
+floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE bits64 extractFloat128Frac0( float128 a )
+{
+
+ return a.high & LIT64( 0x0000FFFFFFFFFFFF );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the exponent bits of the quadruple-precision floating-point value
+`a'.
+-------------------------------------------------------------------------------
+*/
+INLINE int32 extractFloat128Exp( float128 a )
+{
+
+ return ( a.high>>48 ) & 0x7FFF;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the sign bit of the quadruple-precision floating-point value `a'.
+-------------------------------------------------------------------------------
+*/
+INLINE flag extractFloat128Sign( float128 a )
+{
+
+ return a.high>>63;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Normalizes the subnormal quadruple-precision floating-point value
+represented by the denormalized significand formed by the concatenation of
+`aSig0' and `aSig1'. The normalized exponent is stored at the location
+pointed to by `zExpPtr'. The most significant 49 bits of the normalized
+significand are stored at the location pointed to by `zSig0Ptr', and the
+least significant 64 bits of the normalized significand are stored at the
+location pointed to by `zSig1Ptr'.
+-------------------------------------------------------------------------------
+*/
+static void
+ normalizeFloat128Subnormal(
+ bits64 aSig0,
+ bits64 aSig1,
+ int32 *zExpPtr,
+ bits64 *zSig0Ptr,
+ bits64 *zSig1Ptr
+ )
+{
+ int8 shiftCount;
+
+ if ( aSig0 == 0 ) {
+ shiftCount = countLeadingZeros64( aSig1 ) - 15;
+ if ( shiftCount < 0 ) {
+ *zSig0Ptr = aSig1>>( - shiftCount );
+ *zSig1Ptr = aSig1<<( shiftCount & 63 );
+ }
+ else {
+ *zSig0Ptr = aSig1<<shiftCount;
+ *zSig1Ptr = 0;
+ }
+ *zExpPtr = - shiftCount - 63;
+ }
+ else {
+ shiftCount = countLeadingZeros64( aSig0 ) - 15;
+ shortShift128Left( aSig0, aSig1, shiftCount, zSig0Ptr, zSig1Ptr );
+ *zExpPtr = 1 - shiftCount;
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Packs the sign `zSign', the exponent `zExp', and the significand formed
+by the concatenation of `zSig0' and `zSig1' into a quadruple-precision
+floating-point value, returning the result. After being shifted into the
+proper positions, the three fields `zSign', `zExp', and `zSig0' are simply
+added together to form the most significant 32 bits of the result. This
+means that any integer portion of `zSig0' will be added into the exponent.
+Since a properly normalized significand will have an integer portion equal
+to 1, the `zExp' input should be 1 less than the desired result exponent
+whenever `zSig0' and `zSig1' concatenated form a complete, normalized
+significand.
+-------------------------------------------------------------------------------
+*/
+INLINE float128
+ packFloat128( flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 )
+{
+ float128 z;
+
+ z.low = zSig1;
+ z.high = ( ( (bits64) zSign )<<63 ) + ( ( (bits64) zExp )<<48 ) + zSig0;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and extended significand formed by the concatenation of `zSig0', `zSig1',
+and `zSig2', and returns the proper quadruple-precision floating-point value
+corresponding to the abstract input. Ordinarily, the abstract value is
+simply rounded and packed into the quadruple-precision format, with the
+inexact exception raised if the abstract input cannot be represented
+exactly. However, if the abstract value is too large, the overflow and
+inexact exceptions are raised and an infinity or maximal finite value is
+returned. If the abstract value is too small, the input value is rounded to
+a subnormal number, and the underflow and inexact exceptions are raised if
+the abstract input cannot be represented exactly as a subnormal quadruple-
+precision floating-point number.
+ The input significand must be normalized or smaller. If the input
+significand is not normalized, `zExp' must be 0; in that case, the result
+returned is a subnormal number, and it must not require rounding. In the
+usual case that the input significand is normalized, `zExp' must be 1 less
+than the ``true'' floating-point exponent. The handling of underflow and
+overflow follows the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float128
+ roundAndPackFloat128(
+ flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1, bits64 zSig2 )
+{
+ int8 roundingMode;
+ flag roundNearestEven, increment, isTiny;
+
+ roundingMode = float_rounding_mode;
+ roundNearestEven = ( roundingMode == float_round_nearest_even );
+ increment = ( (sbits64) zSig2 < 0 );
+ if ( ! roundNearestEven ) {
+ if ( roundingMode == float_round_to_zero ) {
+ increment = 0;
+ }
+ else {
+ if ( zSign ) {
+ increment = ( roundingMode == float_round_down ) && zSig2;
+ }
+ else {
+ increment = ( roundingMode == float_round_up ) && zSig2;
+ }
+ }
+ }
+ if ( 0x7FFD <= (bits32) zExp ) {
+ if ( ( 0x7FFD < zExp )
+ || ( ( zExp == 0x7FFD )
+ && eq128(
+ LIT64( 0x0001FFFFFFFFFFFF ),
+ LIT64( 0xFFFFFFFFFFFFFFFF ),
+ zSig0,
+ zSig1
+ )
+ && increment
+ )
+ ) {
+ float_raise( float_flag_overflow | float_flag_inexact );
+ if ( ( roundingMode == float_round_to_zero )
+ || ( zSign && ( roundingMode == float_round_up ) )
+ || ( ! zSign && ( roundingMode == float_round_down ) )
+ ) {
+ return
+ packFloat128(
+ zSign,
+ 0x7FFE,
+ LIT64( 0x0000FFFFFFFFFFFF ),
+ LIT64( 0xFFFFFFFFFFFFFFFF )
+ );
+ }
+ return packFloat128( zSign, 0x7FFF, 0, 0 );
+ }
+ if ( zExp < 0 ) {
+ isTiny =
+ ( float_detect_tininess == float_tininess_before_rounding )
+ || ( zExp < -1 )
+ || ! increment
+ || lt128(
+ zSig0,
+ zSig1,
+ LIT64( 0x0001FFFFFFFFFFFF ),
+ LIT64( 0xFFFFFFFFFFFFFFFF )
+ );
+ shift128ExtraRightJamming(
+ zSig0, zSig1, zSig2, - zExp, &zSig0, &zSig1, &zSig2 );
+ zExp = 0;
+ if ( isTiny && zSig2 ) float_raise( float_flag_underflow );
+ if ( roundNearestEven ) {
+ increment = ( (sbits64) zSig2 < 0 );
+ }
+ else {
+ if ( zSign ) {
+ increment = ( roundingMode == float_round_down ) && zSig2;
+ }
+ else {
+ increment = ( roundingMode == float_round_up ) && zSig2;
+ }
+ }
+ }
+ }
+ if ( zSig2 ) float_exception_flags |= float_flag_inexact;
+ if ( increment ) {
+ add128( zSig0, zSig1, 0, 1, &zSig0, &zSig1 );
+ zSig1 &= ~ ( ( zSig2 + zSig2 == 0 ) & roundNearestEven );
+ }
+ else {
+ if ( ( zSig0 | zSig1 ) == 0 ) zExp = 0;
+ }
+ return packFloat128( zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes an abstract floating-point value having sign `zSign', exponent `zExp',
+and significand formed by the concatenation of `zSig0' and `zSig1', and
+returns the proper quadruple-precision floating-point value corresponding
+to the abstract input. This routine is just like `roundAndPackFloat128'
+except that the input significand has fewer bits and does not have to be
+normalized. In all cases, `zExp' must be 1 less than the ``true'' floating-
+point exponent.
+-------------------------------------------------------------------------------
+*/
+static float128
+ normalizeRoundAndPackFloat128(
+ flag zSign, int32 zExp, bits64 zSig0, bits64 zSig1 )
+{
+ int8 shiftCount;
+ bits64 zSig2;
+
+ if ( zSig0 == 0 ) {
+ zSig0 = zSig1;
+ zSig1 = 0;
+ zExp -= 64;
+ }
+ shiftCount = countLeadingZeros64( zSig0 ) - 15;
+ if ( 0 <= shiftCount ) {
+ zSig2 = 0;
+ shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
+ }
+ else {
+ shift128ExtraRightJamming(
+ zSig0, zSig1, 0, - shiftCount, &zSig0, &zSig1, &zSig2 );
+ }
+ zExp -= shiftCount;
+ return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 32-bit two's complement integer `a'
+to the single-precision floating-point format. The conversion is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 int32_to_float32( int32 a )
+{
+ flag zSign;
+
+ if ( a == 0 ) return 0;
+ if ( a == (sbits32) 0x80000000 ) return packFloat32( 1, 0x9E, 0 );
+ zSign = ( a < 0 );
+ return normalizeRoundAndPackFloat32( zSign, 0x9C, zSign ? - a : a );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC /* __floatunsisf is in libgcc */
+float32 uint32_to_float32( uint32 a )
+{
+ if ( a == 0 ) return 0;
+ if ( a & (bits32) 0x80000000 )
+ return normalizeRoundAndPackFloat32( 0, 0x9D, a >> 1 );
+ return normalizeRoundAndPackFloat32( 0, 0x9C, a );
+}
+#endif
+
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 32-bit two's complement integer `a'
+to the double-precision floating-point format. The conversion is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 int32_to_float64( int32 a )
+{
+ flag zSign;
+ uint32 absA;
+ int8 shiftCount;
+ bits64 zSig;
+
+ if ( a == 0 ) return 0;
+ zSign = ( a < 0 );
+ absA = zSign ? - a : a;
+ shiftCount = countLeadingZeros32( absA ) + 21;
+ zSig = absA;
+ return packFloat64( zSign, 0x432 - shiftCount, zSig<<shiftCount );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC /* __floatunsidf is in libgcc */
+float64 uint32_to_float64( uint32 a )
+{
+ int8 shiftCount;
+ bits64 zSig = a;
+
+ if ( a == 0 ) return 0;
+ shiftCount = countLeadingZeros32( a ) + 21;
+ return packFloat64( 0, 0x432 - shiftCount, zSig<<shiftCount );
+
+}
+#endif
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 32-bit two's complement integer `a'
+to the extended double-precision floating-point format. The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 int32_to_floatx80( int32 a )
+{
+ flag zSign;
+ uint32 absA;
+ int8 shiftCount;
+ bits64 zSig;
+
+ if ( a == 0 ) return packFloatx80( 0, 0, 0 );
+ zSign = ( a < 0 );
+ absA = zSign ? - a : a;
+ shiftCount = countLeadingZeros32( absA ) + 32;
+ zSig = absA;
+ return packFloatx80( zSign, 0x403E - shiftCount, zSig<<shiftCount );
+
+}
+
+floatx80 uint32_to_floatx80( uint32 a )
+{
+ int8 shiftCount;
+ bits64 zSig = a;
+
+ if ( a == 0 ) return packFloatx80( 0, 0, 0 );
+ shiftCount = countLeadingZeros32( a ) + 32;
+ return packFloatx80( 0, 0x403E - shiftCount, zSig<<shiftCount );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 32-bit two's complement integer `a' to
+the quadruple-precision floating-point format. The conversion is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 int32_to_float128( int32 a )
+{
+ flag zSign;
+ uint32 absA;
+ int8 shiftCount;
+ bits64 zSig0;
+
+ if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
+ zSign = ( a < 0 );
+ absA = zSign ? - a : a;
+ shiftCount = countLeadingZeros32( absA ) + 17;
+ zSig0 = absA;
+ return packFloat128( zSign, 0x402E - shiftCount, zSig0<<shiftCount, 0 );
+
+}
+
+float128 uint32_to_float128( uint32 a )
+{
+ int8 shiftCount;
+ bits64 zSig0 = a;
+
+ if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
+ shiftCount = countLeadingZeros32( a ) + 17;
+ return packFloat128( 0, 0x402E - shiftCount, zSig0<<shiftCount, 0 );
+
+}
+
+#endif
+
+#ifndef SOFTFLOAT_FOR_GCC /* __floatdi?f is in libgcc2.c */
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 64-bit two's complement integer `a'
+to the single-precision floating-point format. The conversion is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 int64_to_float32( int64 a )
+{
+ flag zSign;
+ uint64 absA;
+ int8 shiftCount;
+
+ if ( a == 0 ) return 0;
+ zSign = ( a < 0 );
+ absA = zSign ? - a : a;
+ shiftCount = countLeadingZeros64( absA ) - 40;
+ if ( 0 <= shiftCount ) {
+ return packFloat32( zSign, 0x95 - shiftCount, absA<<shiftCount );
+ }
+ else {
+ shiftCount += 7;
+ if ( shiftCount < 0 ) {
+ shift64RightJamming( absA, - shiftCount, &absA );
+ }
+ else {
+ absA <<= shiftCount;
+ }
+ return roundAndPackFloat32( zSign, 0x9C - shiftCount, absA );
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 64-bit two's complement integer `a'
+to the double-precision floating-point format. The conversion is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 int64_to_float64( int64 a )
+{
+ flag zSign;
+
+ if ( a == 0 ) return 0;
+ if ( a == (sbits64) LIT64( 0x8000000000000000 ) ) {
+ return packFloat64( 1, 0x43E, 0 );
+ }
+ zSign = ( a < 0 );
+ return normalizeRoundAndPackFloat64( zSign, 0x43C, zSign ? - a : a );
+
+}
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 64-bit two's complement integer `a'
+to the extended double-precision floating-point format. The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 int64_to_floatx80( int64 a )
+{
+ flag zSign;
+ uint64 absA;
+ int8 shiftCount;
+
+ if ( a == 0 ) return packFloatx80( 0, 0, 0 );
+ zSign = ( a < 0 );
+ absA = zSign ? - a : a;
+ shiftCount = countLeadingZeros64( absA );
+ return packFloatx80( zSign, 0x403E - shiftCount, absA<<shiftCount );
+
+}
+
+#endif
+
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the 64-bit two's complement integer `a' to
+the quadruple-precision floating-point format. The conversion is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 int64_to_float128( int64 a )
+{
+ flag zSign;
+ uint64 absA;
+ int8 shiftCount;
+ int32 zExp;
+ bits64 zSig0, zSig1;
+
+ if ( a == 0 ) return packFloat128( 0, 0, 0, 0 );
+ zSign = ( a < 0 );
+ absA = zSign ? - a : a;
+ shiftCount = countLeadingZeros64( absA ) + 49;
+ zExp = 0x406E - shiftCount;
+ if ( 64 <= shiftCount ) {
+ zSig1 = 0;
+ zSig0 = absA;
+ shiftCount -= 64;
+ }
+ else {
+ zSig1 = absA;
+ zSig0 = 0;
+ }
+ shortShift128Left( zSig0, zSig1, shiftCount, &zSig0, &zSig1 );
+ return packFloat128( zSign, zExp, zSig0, zSig1 );
+
+}
+
+#endif
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the 32-bit two's complement integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode. If `a' is a NaN, the largest
+positive integer is returned. Otherwise, if the conversion overflows, the
+largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int32 float32_to_int32( float32 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits32 aSig;
+ bits64 aSig64;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ if ( ( aExp == 0xFF ) && aSig ) aSign = 0;
+ if ( aExp ) aSig |= 0x00800000;
+ shiftCount = 0xAF - aExp;
+ aSig64 = aSig;
+ aSig64 <<= 32;
+ if ( 0 < shiftCount ) shift64RightJamming( aSig64, shiftCount, &aSig64 );
+ return roundAndPackInt32( aSign, aSig64 );
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the 32-bit two's complement integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic, except that the conversion is always rounded toward zero.
+If `a' is a NaN, the largest positive integer is returned. Otherwise, if
+the conversion overflows, the largest integer with the same sign as `a' is
+returned.
+-------------------------------------------------------------------------------
+*/
+int32 float32_to_int32_round_to_zero( float32 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits32 aSig;
+ int32 z;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ shiftCount = aExp - 0x9E;
+ if ( 0 <= shiftCount ) {
+ if ( a != 0xCF000000 ) {
+ float_raise( float_flag_invalid );
+ if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) return 0x7FFFFFFF;
+ }
+ return (sbits32) 0x80000000;
+ }
+ else if ( aExp <= 0x7E ) {
+ if ( aExp | aSig ) float_exception_flags |= float_flag_inexact;
+ return 0;
+ }
+ aSig = ( aSig | 0x00800000 )<<8;
+ z = aSig>>( - shiftCount );
+ if ( (bits32) ( aSig<<( shiftCount & 31 ) ) ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ if ( aSign ) z = - z;
+ return z;
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC /* __fix?fdi provided by libgcc2.c */
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the 64-bit two's complement integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode. If `a' is a NaN, the largest
+positive integer is returned. Otherwise, if the conversion overflows, the
+largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int64 float32_to_int64( float32 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits32 aSig;
+ bits64 aSig64, aSigExtra;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ shiftCount = 0xBE - aExp;
+ if ( shiftCount < 0 ) {
+ float_raise( float_flag_invalid );
+ if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
+ return LIT64( 0x7FFFFFFFFFFFFFFF );
+ }
+ return (sbits64) LIT64( 0x8000000000000000 );
+ }
+ if ( aExp ) aSig |= 0x00800000;
+ aSig64 = aSig;
+ aSig64 <<= 40;
+ shift64ExtraRightJamming( aSig64, 0, shiftCount, &aSig64, &aSigExtra );
+ return roundAndPackInt64( aSign, aSig64, aSigExtra );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the 64-bit two's complement integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic, except that the conversion is always rounded toward zero. If
+`a' is a NaN, the largest positive integer is returned. Otherwise, if the
+conversion overflows, the largest integer with the same sign as `a' is
+returned.
+-------------------------------------------------------------------------------
+*/
+int64 float32_to_int64_round_to_zero( float32 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits32 aSig;
+ bits64 aSig64;
+ int64 z;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ shiftCount = aExp - 0xBE;
+ if ( 0 <= shiftCount ) {
+ if ( a != 0xDF000000 ) {
+ float_raise( float_flag_invalid );
+ if ( ! aSign || ( ( aExp == 0xFF ) && aSig ) ) {
+ return LIT64( 0x7FFFFFFFFFFFFFFF );
+ }
+ }
+ return (sbits64) LIT64( 0x8000000000000000 );
+ }
+ else if ( aExp <= 0x7E ) {
+ if ( aExp | aSig ) float_exception_flags |= float_flag_inexact;
+ return 0;
+ }
+ aSig64 = aSig | 0x00800000;
+ aSig64 <<= 40;
+ z = aSig64>>( - shiftCount );
+ if ( (bits64) ( aSig64<<( shiftCount & 63 ) ) ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ if ( aSign ) z = - z;
+ return z;
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the double-precision floating-point format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float32_to_float64( float32 a )
+{
+ flag aSign;
+ int16 aExp;
+ bits32 aSig;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ if ( aExp == 0xFF ) {
+ if ( aSig ) return commonNaNToFloat64( float32ToCommonNaN( a ) );
+ return packFloat64( aSign, 0x7FF, 0 );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return packFloat64( aSign, 0, 0 );
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+ --aExp;
+ }
+ return packFloat64( aSign, aExp + 0x380, ( (bits64) aSig )<<29 );
+
+}
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the extended double-precision floating-point format. The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 float32_to_floatx80( float32 a )
+{
+ flag aSign;
+ int16 aExp;
+ bits32 aSig;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ if ( aExp == 0xFF ) {
+ if ( aSig ) return commonNaNToFloatx80( float32ToCommonNaN( a ) );
+ return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+ }
+ aSig |= 0x00800000;
+ return packFloatx80( aSign, aExp + 0x3F80, ( (bits64) aSig )<<40 );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the double-precision floating-point format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float32_to_float128( float32 a )
+{
+ flag aSign;
+ int16 aExp;
+ bits32 aSig;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ if ( aExp == 0xFF ) {
+ if ( aSig ) return commonNaNToFloat128( float32ToCommonNaN( a ) );
+ return packFloat128( aSign, 0x7FFF, 0, 0 );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 );
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+ --aExp;
+ }
+ return packFloat128( aSign, aExp + 0x3F80, ( (bits64) aSig )<<25, 0 );
+
+}
+
+#endif
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Rounds the single-precision floating-point value `a' to an integer, and
+returns the result as a single-precision floating-point value. The
+operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_round_to_int( float32 a )
+{
+ flag aSign;
+ int16 aExp;
+ bits32 lastBitMask, roundBitsMask;
+ int8 roundingMode;
+ float32 z;
+
+ aExp = extractFloat32Exp( a );
+ if ( 0x96 <= aExp ) {
+ if ( ( aExp == 0xFF ) && extractFloat32Frac( a ) ) {
+ return propagateFloat32NaN( a, a );
+ }
+ return a;
+ }
+ if ( aExp <= 0x7E ) {
+ if ( (bits32) ( a<<1 ) == 0 ) return a;
+ float_exception_flags |= float_flag_inexact;
+ aSign = extractFloat32Sign( a );
+ switch ( float_rounding_mode ) {
+ case float_round_nearest_even:
+ if ( ( aExp == 0x7E ) && extractFloat32Frac( a ) ) {
+ return packFloat32( aSign, 0x7F, 0 );
+ }
+ break;
+ case float_round_to_zero:
+ break;
+ case float_round_down:
+ return aSign ? 0xBF800000 : 0;
+ case float_round_up:
+ return aSign ? 0x80000000 : 0x3F800000;
+ }
+ return packFloat32( aSign, 0, 0 );
+ }
+ lastBitMask = 1;
+ lastBitMask <<= 0x96 - aExp;
+ roundBitsMask = lastBitMask - 1;
+ z = a;
+ roundingMode = float_rounding_mode;
+ if ( roundingMode == float_round_nearest_even ) {
+ z += lastBitMask>>1;
+ if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
+ }
+ else if ( roundingMode != float_round_to_zero ) {
+ if ( extractFloat32Sign( z ) ^ ( roundingMode == float_round_up ) ) {
+ z += roundBitsMask;
+ }
+ }
+ z &= ~ roundBitsMask;
+ if ( z != a ) float_exception_flags |= float_flag_inexact;
+ return z;
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the absolute values of the single-precision
+floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
+before being returned. `zSign' is ignored if the result is a NaN.
+The addition is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float32 addFloat32Sigs( float32 a, float32 b, flag zSign )
+{
+ int16 aExp, bExp, zExp;
+ bits32 aSig, bSig, zSig;
+ int16 expDiff;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ bSig = extractFloat32Frac( b );
+ bExp = extractFloat32Exp( b );
+ expDiff = aExp - bExp;
+ aSig <<= 6;
+ bSig <<= 6;
+ if ( 0 < expDiff ) {
+ if ( aExp == 0xFF ) {
+ if ( aSig ) return propagateFloat32NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ --expDiff;
+ }
+ else {
+ bSig |= 0x20000000;
+ }
+ shift32RightJamming( bSig, expDiff, &bSig );
+ zExp = aExp;
+ }
+ else if ( expDiff < 0 ) {
+ if ( bExp == 0xFF ) {
+ if ( bSig ) return propagateFloat32NaN( a, b );
+ return packFloat32( zSign, 0xFF, 0 );
+ }
+ if ( aExp == 0 ) {
+ ++expDiff;
+ }
+ else {
+ aSig |= 0x20000000;
+ }
+ shift32RightJamming( aSig, - expDiff, &aSig );
+ zExp = bExp;
+ }
+ else {
+ if ( aExp == 0xFF ) {
+ if ( aSig | bSig ) return propagateFloat32NaN( a, b );
+ return a;
+ }
+ if ( aExp == 0 ) return packFloat32( zSign, 0, ( aSig + bSig )>>6 );
+ zSig = 0x40000000 + aSig + bSig;
+ zExp = aExp;
+ goto roundAndPack;
+ }
+ aSig |= 0x20000000;
+ zSig = ( aSig + bSig )<<1;
+ --zExp;
+ if ( (sbits32) zSig < 0 ) {
+ zSig = aSig + bSig;
+ ++zExp;
+ }
+ roundAndPack:
+ return roundAndPackFloat32( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the absolute values of the single-
+precision floating-point values `a' and `b'. If `zSign' is 1, the
+difference is negated before being returned. `zSign' is ignored if the
+result is a NaN. The subtraction is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float32 subFloat32Sigs( float32 a, float32 b, flag zSign )
+{
+ int16 aExp, bExp, zExp;
+ bits32 aSig, bSig, zSig;
+ int16 expDiff;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ bSig = extractFloat32Frac( b );
+ bExp = extractFloat32Exp( b );
+ expDiff = aExp - bExp;
+ aSig <<= 7;
+ bSig <<= 7;
+ if ( 0 < expDiff ) goto aExpBigger;
+ if ( expDiff < 0 ) goto bExpBigger;
+ if ( aExp == 0xFF ) {
+ if ( aSig | bSig ) return propagateFloat32NaN( a, b );
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ if ( aExp == 0 ) {
+ aExp = 1;
+ bExp = 1;
+ }
+ if ( bSig < aSig ) goto aBigger;
+ if ( aSig < bSig ) goto bBigger;
+ return packFloat32( float_rounding_mode == float_round_down, 0, 0 );
+ bExpBigger:
+ if ( bExp == 0xFF ) {
+ if ( bSig ) return propagateFloat32NaN( a, b );
+ return packFloat32( zSign ^ 1, 0xFF, 0 );
+ }
+ if ( aExp == 0 ) {
+ ++expDiff;
+ }
+ else {
+ aSig |= 0x40000000;
+ }
+ shift32RightJamming( aSig, - expDiff, &aSig );
+ bSig |= 0x40000000;
+ bBigger:
+ zSig = bSig - aSig;
+ zExp = bExp;
+ zSign ^= 1;
+ goto normalizeRoundAndPack;
+ aExpBigger:
+ if ( aExp == 0xFF ) {
+ if ( aSig ) return propagateFloat32NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ --expDiff;
+ }
+ else {
+ bSig |= 0x40000000;
+ }
+ shift32RightJamming( bSig, expDiff, &bSig );
+ aSig |= 0x40000000;
+ aBigger:
+ zSig = aSig - bSig;
+ zExp = aExp;
+ normalizeRoundAndPack:
+ --zExp;
+ return normalizeRoundAndPackFloat32( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the single-precision floating-point values `a'
+and `b'. The operation is performed according to the IEC/IEEE Standard for
+Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_add( float32 a, float32 b )
+{
+ flag aSign, bSign;
+
+ aSign = extractFloat32Sign( a );
+ bSign = extractFloat32Sign( b );
+ if ( aSign == bSign ) {
+ return addFloat32Sigs( a, b, aSign );
+ }
+ else {
+ return subFloat32Sigs( a, b, aSign );
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the single-precision floating-point values
+`a' and `b'. The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_sub( float32 a, float32 b )
+{
+ flag aSign, bSign;
+
+ aSign = extractFloat32Sign( a );
+ bSign = extractFloat32Sign( b );
+ if ( aSign == bSign ) {
+ return subFloat32Sigs( a, b, aSign );
+ }
+ else {
+ return addFloat32Sigs( a, b, aSign );
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of multiplying the single-precision floating-point values
+`a' and `b'. The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_mul( float32 a, float32 b )
+{
+ flag aSign, bSign, zSign;
+ int16 aExp, bExp, zExp;
+ bits32 aSig, bSig;
+ bits64 zSig64;
+ bits32 zSig;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ bSig = extractFloat32Frac( b );
+ bExp = extractFloat32Exp( b );
+ bSign = extractFloat32Sign( b );
+ zSign = aSign ^ bSign;
+ if ( aExp == 0xFF ) {
+ if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
+ return propagateFloat32NaN( a, b );
+ }
+ if ( ( bExp | bSig ) == 0 ) {
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ return packFloat32( zSign, 0xFF, 0 );
+ }
+ if ( bExp == 0xFF ) {
+ if ( bSig ) return propagateFloat32NaN( a, b );
+ if ( ( aExp | aSig ) == 0 ) {
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ return packFloat32( zSign, 0xFF, 0 );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+ }
+ if ( bExp == 0 ) {
+ if ( bSig == 0 ) return packFloat32( zSign, 0, 0 );
+ normalizeFloat32Subnormal( bSig, &bExp, &bSig );
+ }
+ zExp = aExp + bExp - 0x7F;
+ aSig = ( aSig | 0x00800000 )<<7;
+ bSig = ( bSig | 0x00800000 )<<8;
+ shift64RightJamming( ( (bits64) aSig ) * bSig, 32, &zSig64 );
+ zSig = zSig64;
+ if ( 0 <= (sbits32) ( zSig<<1 ) ) {
+ zSig <<= 1;
+ --zExp;
+ }
+ return roundAndPackFloat32( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of dividing the single-precision floating-point value `a'
+by the corresponding value `b'. The operation is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_div( float32 a, float32 b )
+{
+ flag aSign, bSign, zSign;
+ int16 aExp, bExp, zExp;
+ bits32 aSig, bSig, zSig;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ bSig = extractFloat32Frac( b );
+ bExp = extractFloat32Exp( b );
+ bSign = extractFloat32Sign( b );
+ zSign = aSign ^ bSign;
+ if ( aExp == 0xFF ) {
+ if ( aSig ) return propagateFloat32NaN( a, b );
+ if ( bExp == 0xFF ) {
+ if ( bSig ) return propagateFloat32NaN( a, b );
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ return packFloat32( zSign, 0xFF, 0 );
+ }
+ if ( bExp == 0xFF ) {
+ if ( bSig ) return propagateFloat32NaN( a, b );
+ return packFloat32( zSign, 0, 0 );
+ }
+ if ( bExp == 0 ) {
+ if ( bSig == 0 ) {
+ if ( ( aExp | aSig ) == 0 ) {
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ float_raise( float_flag_divbyzero );
+ return packFloat32( zSign, 0xFF, 0 );
+ }
+ normalizeFloat32Subnormal( bSig, &bExp, &bSig );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+ }
+ zExp = aExp - bExp + 0x7D;
+ aSig = ( aSig | 0x00800000 )<<7;
+ bSig = ( bSig | 0x00800000 )<<8;
+ if ( bSig <= ( aSig + aSig ) ) {
+ aSig >>= 1;
+ ++zExp;
+ }
+ zSig = ( ( (bits64) aSig )<<32 ) / bSig;
+ if ( ( zSig & 0x3F ) == 0 ) {
+ zSig |= ( (bits64) bSig * zSig != ( (bits64) aSig )<<32 );
+ }
+ return roundAndPackFloat32( zSign, zExp, zSig );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Returns the remainder of the single-precision floating-point value `a'
+with respect to the corresponding value `b'. The operation is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_rem( float32 a, float32 b )
+{
+ flag aSign, bSign, zSign;
+ int16 aExp, bExp, expDiff;
+ bits32 aSig, bSig;
+ bits32 q;
+ bits64 aSig64, bSig64, q64;
+ bits32 alternateASig;
+ sbits32 sigMean;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ bSig = extractFloat32Frac( b );
+ bExp = extractFloat32Exp( b );
+ bSign = extractFloat32Sign( b );
+ if ( aExp == 0xFF ) {
+ if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
+ return propagateFloat32NaN( a, b );
+ }
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ if ( bExp == 0xFF ) {
+ if ( bSig ) return propagateFloat32NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ if ( bSig == 0 ) {
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ normalizeFloat32Subnormal( bSig, &bExp, &bSig );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return a;
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+ }
+ expDiff = aExp - bExp;
+ aSig |= 0x00800000;
+ bSig |= 0x00800000;
+ if ( expDiff < 32 ) {
+ aSig <<= 8;
+ bSig <<= 8;
+ if ( expDiff < 0 ) {
+ if ( expDiff < -1 ) return a;
+ aSig >>= 1;
+ }
+ q = ( bSig <= aSig );
+ if ( q ) aSig -= bSig;
+ if ( 0 < expDiff ) {
+ q = ( ( (bits64) aSig )<<32 ) / bSig;
+ q >>= 32 - expDiff;
+ bSig >>= 2;
+ aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
+ }
+ else {
+ aSig >>= 2;
+ bSig >>= 2;
+ }
+ }
+ else {
+ if ( bSig <= aSig ) aSig -= bSig;
+ aSig64 = ( (bits64) aSig )<<40;
+ bSig64 = ( (bits64) bSig )<<40;
+ expDiff -= 64;
+ while ( 0 < expDiff ) {
+ q64 = estimateDiv128To64( aSig64, 0, bSig64 );
+ q64 = ( 2 < q64 ) ? q64 - 2 : 0;
+ aSig64 = - ( ( bSig * q64 )<<38 );
+ expDiff -= 62;
+ }
+ expDiff += 64;
+ q64 = estimateDiv128To64( aSig64, 0, bSig64 );
+ q64 = ( 2 < q64 ) ? q64 - 2 : 0;
+ q = q64>>( 64 - expDiff );
+ bSig <<= 6;
+ aSig = ( ( aSig64>>33 )<<( expDiff - 1 ) ) - bSig * q;
+ }
+ do {
+ alternateASig = aSig;
+ ++q;
+ aSig -= bSig;
+ } while ( 0 <= (sbits32) aSig );
+ sigMean = aSig + alternateASig;
+ if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
+ aSig = alternateASig;
+ }
+ zSign = ( (sbits32) aSig < 0 );
+ if ( zSign ) aSig = - aSig;
+ return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig );
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Returns the square root of the single-precision floating-point value `a'.
+The operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float32_sqrt( float32 a )
+{
+ flag aSign;
+ int16 aExp, zExp;
+ bits32 aSig, zSig;
+ bits64 rem, term;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ if ( aExp == 0xFF ) {
+ if ( aSig ) return propagateFloat32NaN( a, 0 );
+ if ( ! aSign ) return a;
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ if ( aSign ) {
+ if ( ( aExp | aSig ) == 0 ) return a;
+ float_raise( float_flag_invalid );
+ return float32_default_nan;
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return 0;
+ normalizeFloat32Subnormal( aSig, &aExp, &aSig );
+ }
+ zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E;
+ aSig = ( aSig | 0x00800000 )<<8;
+ zSig = estimateSqrt32( aExp, aSig ) + 2;
+ if ( ( zSig & 0x7F ) <= 5 ) {
+ if ( zSig < 2 ) {
+ zSig = 0x7FFFFFFF;
+ goto roundAndPack;
+ }
+ aSig >>= aExp & 1;
+ term = ( (bits64) zSig ) * zSig;
+ rem = ( ( (bits64) aSig )<<32 ) - term;
+ while ( (sbits64) rem < 0 ) {
+ --zSig;
+ rem += ( ( (bits64) zSig )<<1 ) | 1;
+ }
+ zSig |= ( rem != 0 );
+ }
+ shift32RightJamming( zSig, 1, &zSig );
+ roundAndPack:
+ return roundAndPackFloat32( 0, zExp, zSig );
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is equal to
+the corresponding value `b', and 0 otherwise. The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_eq( float32 a, float32 b )
+{
+
+ if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+ || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+ ) {
+ if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is less than
+or equal to the corresponding value `b', and 0 otherwise. The comparison
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_le( float32 a, float32 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+ || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ aSign = extractFloat32Sign( a );
+ bSign = extractFloat32Sign( b );
+ if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
+ return ( a == b ) || ( aSign ^ ( a < b ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise. The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_lt( float32 a, float32 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+ || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ aSign = extractFloat32Sign( a );
+ bSign = extractFloat32Sign( b );
+ if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
+ return ( a != b ) && ( aSign ^ ( a < b ) );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is equal to
+the corresponding value `b', and 0 otherwise. The invalid exception is
+raised if either operand is a NaN. Otherwise, the comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_eq_signaling( float32 a, float32 b )
+{
+
+ if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+ || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is less than or
+equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
+cause an exception. Otherwise, the comparison is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_le_quiet( float32 a, float32 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+ || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+ ) {
+ if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ aSign = extractFloat32Sign( a );
+ bSign = extractFloat32Sign( b );
+ if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
+ return ( a == b ) || ( aSign ^ ( a < b ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
+exception. Otherwise, the comparison is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float32_lt_quiet( float32 a, float32 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
+ || ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
+ ) {
+ if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ aSign = extractFloat32Sign( a );
+ bSign = extractFloat32Sign( b );
+ if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
+ return ( a != b ) && ( aSign ^ ( a < b ) );
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the 32-bit two's complement integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode. If `a' is a NaN, the largest
+positive integer is returned. Otherwise, if the conversion overflows, the
+largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int32 float64_to_int32( float64 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits64 aSig;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
+ if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
+ shiftCount = 0x42C - aExp;
+ if ( 0 < shiftCount ) shift64RightJamming( aSig, shiftCount, &aSig );
+ return roundAndPackInt32( aSign, aSig );
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the 32-bit two's complement integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic, except that the conversion is always rounded toward zero.
+If `a' is a NaN, the largest positive integer is returned. Otherwise, if
+the conversion overflows, the largest integer with the same sign as `a' is
+returned.
+-------------------------------------------------------------------------------
+*/
+int32 float64_to_int32_round_to_zero( float64 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits64 aSig, savedASig;
+ int32 z;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ if ( 0x41E < aExp ) {
+ if ( ( aExp == 0x7FF ) && aSig ) aSign = 0;
+ goto invalid;
+ }
+ else if ( aExp < 0x3FF ) {
+ if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
+ return 0;
+ }
+ aSig |= LIT64( 0x0010000000000000 );
+ shiftCount = 0x433 - aExp;
+ savedASig = aSig;
+ aSig >>= shiftCount;
+ z = aSig;
+ if ( aSign ) z = - z;
+ if ( ( z < 0 ) ^ aSign ) {
+ invalid:
+ float_raise( float_flag_invalid );
+ return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
+ }
+ if ( ( aSig<<shiftCount ) != savedASig ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ return z;
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC /* Not needed */
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the 64-bit two's complement integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode. If `a' is a NaN, the largest
+positive integer is returned. Otherwise, if the conversion overflows, the
+largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int64 float64_to_int64( float64 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits64 aSig, aSigExtra;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
+ shiftCount = 0x433 - aExp;
+ if ( shiftCount <= 0 ) {
+ if ( 0x43E < aExp ) {
+ float_raise( float_flag_invalid );
+ if ( ! aSign
+ || ( ( aExp == 0x7FF )
+ && ( aSig != LIT64( 0x0010000000000000 ) ) )
+ ) {
+ return LIT64( 0x7FFFFFFFFFFFFFFF );
+ }
+ return (sbits64) LIT64( 0x8000000000000000 );
+ }
+ aSigExtra = 0;
+ aSig <<= - shiftCount;
+ }
+ else {
+ shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra );
+ }
+ return roundAndPackInt64( aSign, aSig, aSigExtra );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the 64-bit two's complement integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic, except that the conversion is always rounded toward zero.
+If `a' is a NaN, the largest positive integer is returned. Otherwise, if
+the conversion overflows, the largest integer with the same sign as `a' is
+returned.
+-------------------------------------------------------------------------------
+*/
+int64 float64_to_int64_round_to_zero( float64 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits64 aSig;
+ int64 z;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ if ( aExp ) aSig |= LIT64( 0x0010000000000000 );
+ shiftCount = aExp - 0x433;
+ if ( 0 <= shiftCount ) {
+ if ( 0x43E <= aExp ) {
+ if ( a != LIT64( 0xC3E0000000000000 ) ) {
+ float_raise( float_flag_invalid );
+ if ( ! aSign
+ || ( ( aExp == 0x7FF )
+ && ( aSig != LIT64( 0x0010000000000000 ) ) )
+ ) {
+ return LIT64( 0x7FFFFFFFFFFFFFFF );
+ }
+ }
+ return (sbits64) LIT64( 0x8000000000000000 );
+ }
+ z = aSig<<shiftCount;
+ }
+ else {
+ if ( aExp < 0x3FE ) {
+ if ( aExp | aSig ) float_exception_flags |= float_flag_inexact;
+ return 0;
+ }
+ z = aSig>>( - shiftCount );
+ if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ }
+ if ( aSign ) z = - z;
+ return z;
+
+}
+#endif /* !SOFTFLOAT_FOR_GCC */
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the single-precision floating-point format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float64_to_float32( float64 a )
+{
+ flag aSign;
+ int16 aExp;
+ bits64 aSig;
+ bits32 zSig;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ if ( aExp == 0x7FF ) {
+ if ( aSig ) return commonNaNToFloat32( float64ToCommonNaN( a ) );
+ return packFloat32( aSign, 0xFF, 0 );
+ }
+ shift64RightJamming( aSig, 22, &aSig );
+ zSig = aSig;
+ if ( aExp || zSig ) {
+ zSig |= 0x40000000;
+ aExp -= 0x381;
+ }
+ return roundAndPackFloat32( aSign, aExp, zSig );
+
+}
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the extended double-precision floating-point format. The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 float64_to_floatx80( float64 a )
+{
+ flag aSign;
+ int16 aExp;
+ bits64 aSig;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ if ( aExp == 0x7FF ) {
+ if ( aSig ) return commonNaNToFloatx80( float64ToCommonNaN( a ) );
+ return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return packFloatx80( aSign, 0, 0 );
+ normalizeFloat64Subnormal( aSig, &aExp, &aSig );
+ }
+ return
+ packFloatx80(
+ aSign, aExp + 0x3C00, ( aSig | LIT64( 0x0010000000000000 ) )<<11 );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the quadruple-precision floating-point format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float64_to_float128( float64 a )
+{
+ flag aSign;
+ int16 aExp;
+ bits64 aSig, zSig0, zSig1;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ if ( aExp == 0x7FF ) {
+ if ( aSig ) return commonNaNToFloat128( float64ToCommonNaN( a ) );
+ return packFloat128( aSign, 0x7FFF, 0, 0 );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return packFloat128( aSign, 0, 0, 0 );
+ normalizeFloat64Subnormal( aSig, &aExp, &aSig );
+ --aExp;
+ }
+ shift128Right( aSig, 0, 4, &zSig0, &zSig1 );
+ return packFloat128( aSign, aExp + 0x3C00, zSig0, zSig1 );
+
+}
+
+#endif
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Rounds the double-precision floating-point value `a' to an integer, and
+returns the result as a double-precision floating-point value. The
+operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_round_to_int( float64 a )
+{
+ flag aSign;
+ int16 aExp;
+ bits64 lastBitMask, roundBitsMask;
+ int8 roundingMode;
+ float64 z;
+
+ aExp = extractFloat64Exp( a );
+ if ( 0x433 <= aExp ) {
+ if ( ( aExp == 0x7FF ) && extractFloat64Frac( a ) ) {
+ return propagateFloat64NaN( a, a );
+ }
+ return a;
+ }
+ if ( aExp < 0x3FF ) {
+ if ( (bits64) ( a<<1 ) == 0 ) return a;
+ float_exception_flags |= float_flag_inexact;
+ aSign = extractFloat64Sign( a );
+ switch ( float_rounding_mode ) {
+ case float_round_nearest_even:
+ if ( ( aExp == 0x3FE ) && extractFloat64Frac( a ) ) {
+ return packFloat64( aSign, 0x3FF, 0 );
+ }
+ break;
+ case float_round_to_zero:
+ break;
+ case float_round_down:
+ return aSign ? LIT64( 0xBFF0000000000000 ) : 0;
+ case float_round_up:
+ return
+ aSign ? LIT64( 0x8000000000000000 ) : LIT64( 0x3FF0000000000000 );
+ }
+ return packFloat64( aSign, 0, 0 );
+ }
+ lastBitMask = 1;
+ lastBitMask <<= 0x433 - aExp;
+ roundBitsMask = lastBitMask - 1;
+ z = a;
+ roundingMode = float_rounding_mode;
+ if ( roundingMode == float_round_nearest_even ) {
+ z += lastBitMask>>1;
+ if ( ( z & roundBitsMask ) == 0 ) z &= ~ lastBitMask;
+ }
+ else if ( roundingMode != float_round_to_zero ) {
+ if ( extractFloat64Sign( z ) ^ ( roundingMode == float_round_up ) ) {
+ z += roundBitsMask;
+ }
+ }
+ z &= ~ roundBitsMask;
+ if ( z != a ) float_exception_flags |= float_flag_inexact;
+ return z;
+
+}
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the absolute values of the double-precision
+floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
+before being returned. `zSign' is ignored if the result is a NaN.
+The addition is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float64 addFloat64Sigs( float64 a, float64 b, flag zSign )
+{
+ int16 aExp, bExp, zExp;
+ bits64 aSig, bSig, zSig;
+ int16 expDiff;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ bSig = extractFloat64Frac( b );
+ bExp = extractFloat64Exp( b );
+ expDiff = aExp - bExp;
+ aSig <<= 9;
+ bSig <<= 9;
+ if ( 0 < expDiff ) {
+ if ( aExp == 0x7FF ) {
+ if ( aSig ) return propagateFloat64NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ --expDiff;
+ }
+ else {
+ bSig |= LIT64( 0x2000000000000000 );
+ }
+ shift64RightJamming( bSig, expDiff, &bSig );
+ zExp = aExp;
+ }
+ else if ( expDiff < 0 ) {
+ if ( bExp == 0x7FF ) {
+ if ( bSig ) return propagateFloat64NaN( a, b );
+ return packFloat64( zSign, 0x7FF, 0 );
+ }
+ if ( aExp == 0 ) {
+ ++expDiff;
+ }
+ else {
+ aSig |= LIT64( 0x2000000000000000 );
+ }
+ shift64RightJamming( aSig, - expDiff, &aSig );
+ zExp = bExp;
+ }
+ else {
+ if ( aExp == 0x7FF ) {
+ if ( aSig | bSig ) return propagateFloat64NaN( a, b );
+ return a;
+ }
+ if ( aExp == 0 ) return packFloat64( zSign, 0, ( aSig + bSig )>>9 );
+ zSig = LIT64( 0x4000000000000000 ) + aSig + bSig;
+ zExp = aExp;
+ goto roundAndPack;
+ }
+ aSig |= LIT64( 0x2000000000000000 );
+ zSig = ( aSig + bSig )<<1;
+ --zExp;
+ if ( (sbits64) zSig < 0 ) {
+ zSig = aSig + bSig;
+ ++zExp;
+ }
+ roundAndPack:
+ return roundAndPackFloat64( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the absolute values of the double-
+precision floating-point values `a' and `b'. If `zSign' is 1, the
+difference is negated before being returned. `zSign' is ignored if the
+result is a NaN. The subtraction is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float64 subFloat64Sigs( float64 a, float64 b, flag zSign )
+{
+ int16 aExp, bExp, zExp;
+ bits64 aSig, bSig, zSig;
+ int16 expDiff;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ bSig = extractFloat64Frac( b );
+ bExp = extractFloat64Exp( b );
+ expDiff = aExp - bExp;
+ aSig <<= 10;
+ bSig <<= 10;
+ if ( 0 < expDiff ) goto aExpBigger;
+ if ( expDiff < 0 ) goto bExpBigger;
+ if ( aExp == 0x7FF ) {
+ if ( aSig | bSig ) return propagateFloat64NaN( a, b );
+ float_raise( float_flag_invalid );
+ return float64_default_nan;
+ }
+ if ( aExp == 0 ) {
+ aExp = 1;
+ bExp = 1;
+ }
+ if ( bSig < aSig ) goto aBigger;
+ if ( aSig < bSig ) goto bBigger;
+ return packFloat64( float_rounding_mode == float_round_down, 0, 0 );
+ bExpBigger:
+ if ( bExp == 0x7FF ) {
+ if ( bSig ) return propagateFloat64NaN( a, b );
+ return packFloat64( zSign ^ 1, 0x7FF, 0 );
+ }
+ if ( aExp == 0 ) {
+ ++expDiff;
+ }
+ else {
+ aSig |= LIT64( 0x4000000000000000 );
+ }
+ shift64RightJamming( aSig, - expDiff, &aSig );
+ bSig |= LIT64( 0x4000000000000000 );
+ bBigger:
+ zSig = bSig - aSig;
+ zExp = bExp;
+ zSign ^= 1;
+ goto normalizeRoundAndPack;
+ aExpBigger:
+ if ( aExp == 0x7FF ) {
+ if ( aSig ) return propagateFloat64NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ --expDiff;
+ }
+ else {
+ bSig |= LIT64( 0x4000000000000000 );
+ }
+ shift64RightJamming( bSig, expDiff, &bSig );
+ aSig |= LIT64( 0x4000000000000000 );
+ aBigger:
+ zSig = aSig - bSig;
+ zExp = aExp;
+ normalizeRoundAndPack:
+ --zExp;
+ return normalizeRoundAndPackFloat64( zSign, zExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the double-precision floating-point values `a'
+and `b'. The operation is performed according to the IEC/IEEE Standard for
+Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_add( float64 a, float64 b )
+{
+ flag aSign, bSign;
+
+ aSign = extractFloat64Sign( a );
+ bSign = extractFloat64Sign( b );
+ if ( aSign == bSign ) {
+ return addFloat64Sigs( a, b, aSign );
+ }
+ else {
+ return subFloat64Sigs( a, b, aSign );
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the double-precision floating-point values
+`a' and `b'. The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_sub( float64 a, float64 b )
+{
+ flag aSign, bSign;
+
+ aSign = extractFloat64Sign( a );
+ bSign = extractFloat64Sign( b );
+ if ( aSign == bSign ) {
+ return subFloat64Sigs( a, b, aSign );
+ }
+ else {
+ return addFloat64Sigs( a, b, aSign );
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of multiplying the double-precision floating-point values
+`a' and `b'. The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_mul( float64 a, float64 b )
+{
+ flag aSign, bSign, zSign;
+ int16 aExp, bExp, zExp;
+ bits64 aSig, bSig, zSig0, zSig1;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ bSig = extractFloat64Frac( b );
+ bExp = extractFloat64Exp( b );
+ bSign = extractFloat64Sign( b );
+ zSign = aSign ^ bSign;
+ if ( aExp == 0x7FF ) {
+ if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
+ return propagateFloat64NaN( a, b );
+ }
+ if ( ( bExp | bSig ) == 0 ) {
+ float_raise( float_flag_invalid );
+ return float64_default_nan;
+ }
+ return packFloat64( zSign, 0x7FF, 0 );
+ }
+ if ( bExp == 0x7FF ) {
+ if ( bSig ) return propagateFloat64NaN( a, b );
+ if ( ( aExp | aSig ) == 0 ) {
+ float_raise( float_flag_invalid );
+ return float64_default_nan;
+ }
+ return packFloat64( zSign, 0x7FF, 0 );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return packFloat64( zSign, 0, 0 );
+ normalizeFloat64Subnormal( aSig, &aExp, &aSig );
+ }
+ if ( bExp == 0 ) {
+ if ( bSig == 0 ) return packFloat64( zSign, 0, 0 );
+ normalizeFloat64Subnormal( bSig, &bExp, &bSig );
+ }
+ zExp = aExp + bExp - 0x3FF;
+ aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10;
+ bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
+ mul64To128( aSig, bSig, &zSig0, &zSig1 );
+ zSig0 |= ( zSig1 != 0 );
+ if ( 0 <= (sbits64) ( zSig0<<1 ) ) {
+ zSig0 <<= 1;
+ --zExp;
+ }
+ return roundAndPackFloat64( zSign, zExp, zSig0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of dividing the double-precision floating-point value `a'
+by the corresponding value `b'. The operation is performed according to
+the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_div( float64 a, float64 b )
+{
+ flag aSign, bSign, zSign;
+ int16 aExp, bExp, zExp;
+ bits64 aSig, bSig, zSig;
+ bits64 rem0, rem1;
+ bits64 term0, term1;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ bSig = extractFloat64Frac( b );
+ bExp = extractFloat64Exp( b );
+ bSign = extractFloat64Sign( b );
+ zSign = aSign ^ bSign;
+ if ( aExp == 0x7FF ) {
+ if ( aSig ) return propagateFloat64NaN( a, b );
+ if ( bExp == 0x7FF ) {
+ if ( bSig ) return propagateFloat64NaN( a, b );
+ float_raise( float_flag_invalid );
+ return float64_default_nan;
+ }
+ return packFloat64( zSign, 0x7FF, 0 );
+ }
+ if ( bExp == 0x7FF ) {
+ if ( bSig ) return propagateFloat64NaN( a, b );
+ return packFloat64( zSign, 0, 0 );
+ }
+ if ( bExp == 0 ) {
+ if ( bSig == 0 ) {
+ if ( ( aExp | aSig ) == 0 ) {
+ float_raise( float_flag_invalid );
+ return float64_default_nan;
+ }
+ float_raise( float_flag_divbyzero );
+ return packFloat64( zSign, 0x7FF, 0 );
+ }
+ normalizeFloat64Subnormal( bSig, &bExp, &bSig );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return packFloat64( zSign, 0, 0 );
+ normalizeFloat64Subnormal( aSig, &aExp, &aSig );
+ }
+ zExp = aExp - bExp + 0x3FD;
+ aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<10;
+ bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
+ if ( bSig <= ( aSig + aSig ) ) {
+ aSig >>= 1;
+ ++zExp;
+ }
+ zSig = estimateDiv128To64( aSig, 0, bSig );
+ if ( ( zSig & 0x1FF ) <= 2 ) {
+ mul64To128( bSig, zSig, &term0, &term1 );
+ sub128( aSig, 0, term0, term1, &rem0, &rem1 );
+ while ( (sbits64) rem0 < 0 ) {
+ --zSig;
+ add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
+ }
+ zSig |= ( rem1 != 0 );
+ }
+ return roundAndPackFloat64( zSign, zExp, zSig );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Returns the remainder of the double-precision floating-point value `a'
+with respect to the corresponding value `b'. The operation is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_rem( float64 a, float64 b )
+{
+ flag aSign, bSign, zSign;
+ int16 aExp, bExp, expDiff;
+ bits64 aSig, bSig;
+ bits64 q, alternateASig;
+ sbits64 sigMean;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ bSig = extractFloat64Frac( b );
+ bExp = extractFloat64Exp( b );
+ bSign = extractFloat64Sign( b );
+ if ( aExp == 0x7FF ) {
+ if ( aSig || ( ( bExp == 0x7FF ) && bSig ) ) {
+ return propagateFloat64NaN( a, b );
+ }
+ float_raise( float_flag_invalid );
+ return float64_default_nan;
+ }
+ if ( bExp == 0x7FF ) {
+ if ( bSig ) return propagateFloat64NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ if ( bSig == 0 ) {
+ float_raise( float_flag_invalid );
+ return float64_default_nan;
+ }
+ normalizeFloat64Subnormal( bSig, &bExp, &bSig );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return a;
+ normalizeFloat64Subnormal( aSig, &aExp, &aSig );
+ }
+ expDiff = aExp - bExp;
+ aSig = ( aSig | LIT64( 0x0010000000000000 ) )<<11;
+ bSig = ( bSig | LIT64( 0x0010000000000000 ) )<<11;
+ if ( expDiff < 0 ) {
+ if ( expDiff < -1 ) return a;
+ aSig >>= 1;
+ }
+ q = ( bSig <= aSig );
+ if ( q ) aSig -= bSig;
+ expDiff -= 64;
+ while ( 0 < expDiff ) {
+ q = estimateDiv128To64( aSig, 0, bSig );
+ q = ( 2 < q ) ? q - 2 : 0;
+ aSig = - ( ( bSig>>2 ) * q );
+ expDiff -= 62;
+ }
+ expDiff += 64;
+ if ( 0 < expDiff ) {
+ q = estimateDiv128To64( aSig, 0, bSig );
+ q = ( 2 < q ) ? q - 2 : 0;
+ q >>= 64 - expDiff;
+ bSig >>= 2;
+ aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
+ }
+ else {
+ aSig >>= 2;
+ bSig >>= 2;
+ }
+ do {
+ alternateASig = aSig;
+ ++q;
+ aSig -= bSig;
+ } while ( 0 <= (sbits64) aSig );
+ sigMean = aSig + alternateASig;
+ if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
+ aSig = alternateASig;
+ }
+ zSign = ( (sbits64) aSig < 0 );
+ if ( zSign ) aSig = - aSig;
+ return normalizeRoundAndPackFloat64( aSign ^ zSign, bExp, aSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the square root of the double-precision floating-point value `a'.
+The operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float64_sqrt( float64 a )
+{
+ flag aSign;
+ int16 aExp, zExp;
+ bits64 aSig, zSig, doubleZSig;
+ bits64 rem0, rem1, term0, term1;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+ if ( aExp == 0x7FF ) {
+ if ( aSig ) return propagateFloat64NaN( a, a );
+ if ( ! aSign ) return a;
+ float_raise( float_flag_invalid );
+ return float64_default_nan;
+ }
+ if ( aSign ) {
+ if ( ( aExp | aSig ) == 0 ) return a;
+ float_raise( float_flag_invalid );
+ return float64_default_nan;
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return 0;
+ normalizeFloat64Subnormal( aSig, &aExp, &aSig );
+ }
+ zExp = ( ( aExp - 0x3FF )>>1 ) + 0x3FE;
+ aSig |= LIT64( 0x0010000000000000 );
+ zSig = estimateSqrt32( aExp, aSig>>21 );
+ aSig <<= 9 - ( aExp & 1 );
+ zSig = estimateDiv128To64( aSig, 0, zSig<<32 ) + ( zSig<<30 );
+ if ( ( zSig & 0x1FF ) <= 5 ) {
+ doubleZSig = zSig<<1;
+ mul64To128( zSig, zSig, &term0, &term1 );
+ sub128( aSig, 0, term0, term1, &rem0, &rem1 );
+ while ( (sbits64) rem0 < 0 ) {
+ --zSig;
+ doubleZSig -= 2;
+ add128( rem0, rem1, zSig>>63, doubleZSig | 1, &rem0, &rem1 );
+ }
+ zSig |= ( ( rem0 | rem1 ) != 0 );
+ }
+ return roundAndPackFloat64( 0, zExp, zSig );
+
+}
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is equal to the
+corresponding value `b', and 0 otherwise. The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_eq( float64 a, float64 b )
+{
+
+ if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+ || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+ ) {
+ if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ return ( a == b ) ||
+ ( (bits64) ( ( FLOAT64_DEMANGLE(a) | FLOAT64_DEMANGLE(b) )<<1 ) == 0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is less than or
+equal to the corresponding value `b', and 0 otherwise. The comparison is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_le( float64 a, float64 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+ || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ aSign = extractFloat64Sign( a );
+ bSign = extractFloat64Sign( b );
+ if ( aSign != bSign )
+ return aSign ||
+ ( (bits64) ( ( FLOAT64_DEMANGLE(a) | FLOAT64_DEMANGLE(b) )<<1 ) ==
+ 0 );
+ return ( a == b ) ||
+ ( aSign ^ ( FLOAT64_DEMANGLE(a) < FLOAT64_DEMANGLE(b) ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise. The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_lt( float64 a, float64 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+ || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ aSign = extractFloat64Sign( a );
+ bSign = extractFloat64Sign( b );
+ if ( aSign != bSign )
+ return aSign &&
+ ( (bits64) ( ( FLOAT64_DEMANGLE(a) | FLOAT64_DEMANGLE(b) )<<1 ) !=
+ 0 );
+ return ( a != b ) &&
+ ( aSign ^ ( FLOAT64_DEMANGLE(a) < FLOAT64_DEMANGLE(b) ) );
+
+}
+
+#ifndef SOFTFLOAT_FOR_GCC
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is equal to the
+corresponding value `b', and 0 otherwise. The invalid exception is raised
+if either operand is a NaN. Otherwise, the comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_eq_signaling( float64 a, float64 b )
+{
+
+ if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+ || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ return ( a == b ) || ( (bits64) ( ( a | b )<<1 ) == 0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is less than or
+equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
+cause an exception. Otherwise, the comparison is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_le_quiet( float64 a, float64 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+ || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+ ) {
+ if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ aSign = extractFloat64Sign( a );
+ bSign = extractFloat64Sign( b );
+ if ( aSign != bSign ) return aSign || ( (bits64) ( ( a | b )<<1 ) == 0 );
+ return ( a == b ) || ( aSign ^ ( a < b ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
+exception. Otherwise, the comparison is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float64_lt_quiet( float64 a, float64 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat64Exp( a ) == 0x7FF ) && extractFloat64Frac( a ) )
+ || ( ( extractFloat64Exp( b ) == 0x7FF ) && extractFloat64Frac( b ) )
+ ) {
+ if ( float64_is_signaling_nan( a ) || float64_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ aSign = extractFloat64Sign( a );
+ bSign = extractFloat64Sign( b );
+ if ( aSign != bSign ) return aSign && ( (bits64) ( ( a | b )<<1 ) != 0 );
+ return ( a != b ) && ( aSign ^ ( a < b ) );
+
+}
+#endif
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point value `a' to the 32-bit two's complement integer format. The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic---which means in particular that the conversion
+is rounded according to the current rounding mode. If `a' is a NaN, the
+largest positive integer is returned. Otherwise, if the conversion
+overflows, the largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int32 floatx80_to_int32( floatx80 a )
+{
+ flag aSign;
+ int32 aExp, shiftCount;
+ bits64 aSig;
+
+ aSig = extractFloatx80Frac( a );
+ aExp = extractFloatx80Exp( a );
+ aSign = extractFloatx80Sign( a );
+ if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
+ shiftCount = 0x4037 - aExp;
+ if ( shiftCount <= 0 ) shiftCount = 1;
+ shift64RightJamming( aSig, shiftCount, &aSig );
+ return roundAndPackInt32( aSign, aSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point value `a' to the 32-bit two's complement integer format. The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic, except that the conversion is always rounded
+toward zero. If `a' is a NaN, the largest positive integer is returned.
+Otherwise, if the conversion overflows, the largest integer with the same
+sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int32 floatx80_to_int32_round_to_zero( floatx80 a )
+{
+ flag aSign;
+ int32 aExp, shiftCount;
+ bits64 aSig, savedASig;
+ int32 z;
+
+ aSig = extractFloatx80Frac( a );
+ aExp = extractFloatx80Exp( a );
+ aSign = extractFloatx80Sign( a );
+ if ( 0x401E < aExp ) {
+ if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) aSign = 0;
+ goto invalid;
+ }
+ else if ( aExp < 0x3FFF ) {
+ if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
+ return 0;
+ }
+ shiftCount = 0x403E - aExp;
+ savedASig = aSig;
+ aSig >>= shiftCount;
+ z = aSig;
+ if ( aSign ) z = - z;
+ if ( ( z < 0 ) ^ aSign ) {
+ invalid:
+ float_raise( float_flag_invalid );
+ return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
+ }
+ if ( ( aSig<<shiftCount ) != savedASig ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point value `a' to the 64-bit two's complement integer format. The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic---which means in particular that the conversion
+is rounded according to the current rounding mode. If `a' is a NaN,
+the largest positive integer is returned. Otherwise, if the conversion
+overflows, the largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int64 floatx80_to_int64( floatx80 a )
+{
+ flag aSign;
+ int32 aExp, shiftCount;
+ bits64 aSig, aSigExtra;
+
+ aSig = extractFloatx80Frac( a );
+ aExp = extractFloatx80Exp( a );
+ aSign = extractFloatx80Sign( a );
+ shiftCount = 0x403E - aExp;
+ if ( shiftCount <= 0 ) {
+ if ( shiftCount ) {
+ float_raise( float_flag_invalid );
+ if ( ! aSign
+ || ( ( aExp == 0x7FFF )
+ && ( aSig != LIT64( 0x8000000000000000 ) ) )
+ ) {
+ return LIT64( 0x7FFFFFFFFFFFFFFF );
+ }
+ return (sbits64) LIT64( 0x8000000000000000 );
+ }
+ aSigExtra = 0;
+ }
+ else {
+ shift64ExtraRightJamming( aSig, 0, shiftCount, &aSig, &aSigExtra );
+ }
+ return roundAndPackInt64( aSign, aSig, aSigExtra );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point value `a' to the 64-bit two's complement integer format. The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic, except that the conversion is always rounded
+toward zero. If `a' is a NaN, the largest positive integer is returned.
+Otherwise, if the conversion overflows, the largest integer with the same
+sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int64 floatx80_to_int64_round_to_zero( floatx80 a )
+{
+ flag aSign;
+ int32 aExp, shiftCount;
+ bits64 aSig;
+ int64 z;
+
+ aSig = extractFloatx80Frac( a );
+ aExp = extractFloatx80Exp( a );
+ aSign = extractFloatx80Sign( a );
+ shiftCount = aExp - 0x403E;
+ if ( 0 <= shiftCount ) {
+ aSig &= LIT64( 0x7FFFFFFFFFFFFFFF );
+ if ( ( a.high != 0xC03E ) || aSig ) {
+ float_raise( float_flag_invalid );
+ if ( ! aSign || ( ( aExp == 0x7FFF ) && aSig ) ) {
+ return LIT64( 0x7FFFFFFFFFFFFFFF );
+ }
+ }
+ return (sbits64) LIT64( 0x8000000000000000 );
+ }
+ else if ( aExp < 0x3FFF ) {
+ if ( aExp | aSig ) float_exception_flags |= float_flag_inexact;
+ return 0;
+ }
+ z = aSig>>( - shiftCount );
+ if ( (bits64) ( aSig<<( shiftCount & 63 ) ) ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ if ( aSign ) z = - z;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point value `a' to the single-precision floating-point format. The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 floatx80_to_float32( floatx80 a )
+{
+ flag aSign;
+ int32 aExp;
+ bits64 aSig;
+
+ aSig = extractFloatx80Frac( a );
+ aExp = extractFloatx80Exp( a );
+ aSign = extractFloatx80Sign( a );
+ if ( aExp == 0x7FFF ) {
+ if ( (bits64) ( aSig<<1 ) ) {
+ return commonNaNToFloat32( floatx80ToCommonNaN( a ) );
+ }
+ return packFloat32( aSign, 0xFF, 0 );
+ }
+ shift64RightJamming( aSig, 33, &aSig );
+ if ( aExp || aSig ) aExp -= 0x3F81;
+ return roundAndPackFloat32( aSign, aExp, aSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point value `a' to the double-precision floating-point format. The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 floatx80_to_float64( floatx80 a )
+{
+ flag aSign;
+ int32 aExp;
+ bits64 aSig, zSig;
+
+ aSig = extractFloatx80Frac( a );
+ aExp = extractFloatx80Exp( a );
+ aSign = extractFloatx80Sign( a );
+ if ( aExp == 0x7FFF ) {
+ if ( (bits64) ( aSig<<1 ) ) {
+ return commonNaNToFloat64( floatx80ToCommonNaN( a ) );
+ }
+ return packFloat64( aSign, 0x7FF, 0 );
+ }
+ shift64RightJamming( aSig, 1, &zSig );
+ if ( aExp || aSig ) aExp -= 0x3C01;
+ return roundAndPackFloat64( aSign, aExp, zSig );
+
+}
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point value `a' to the quadruple-precision floating-point format. The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 floatx80_to_float128( floatx80 a )
+{
+ flag aSign;
+ int16 aExp;
+ bits64 aSig, zSig0, zSig1;
+
+ aSig = extractFloatx80Frac( a );
+ aExp = extractFloatx80Exp( a );
+ aSign = extractFloatx80Sign( a );
+ if ( ( aExp == 0x7FFF ) && (bits64) ( aSig<<1 ) ) {
+ return commonNaNToFloat128( floatx80ToCommonNaN( a ) );
+ }
+ shift128Right( aSig<<1, 0, 16, &zSig0, &zSig1 );
+ return packFloat128( aSign, aExp, zSig0, zSig1 );
+
+}
+
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Rounds the extended double-precision floating-point value `a' to an integer,
+and returns the result as an extended quadruple-precision floating-point
+value. The operation is performed according to the IEC/IEEE Standard for
+Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_round_to_int( floatx80 a )
+{
+ flag aSign;
+ int32 aExp;
+ bits64 lastBitMask, roundBitsMask;
+ int8 roundingMode;
+ floatx80 z;
+
+ aExp = extractFloatx80Exp( a );
+ if ( 0x403E <= aExp ) {
+ if ( ( aExp == 0x7FFF ) && (bits64) ( extractFloatx80Frac( a )<<1 ) ) {
+ return propagateFloatx80NaN( a, a );
+ }
+ return a;
+ }
+ if ( aExp < 0x3FFF ) {
+ if ( ( aExp == 0 )
+ && ( (bits64) ( extractFloatx80Frac( a )<<1 ) == 0 ) ) {
+ return a;
+ }
+ float_exception_flags |= float_flag_inexact;
+ aSign = extractFloatx80Sign( a );
+ switch ( float_rounding_mode ) {
+ case float_round_nearest_even:
+ if ( ( aExp == 0x3FFE ) && (bits64) ( extractFloatx80Frac( a )<<1 )
+ ) {
+ return
+ packFloatx80( aSign, 0x3FFF, LIT64( 0x8000000000000000 ) );
+ }
+ break;
+ case float_round_to_zero:
+ break;
+ case float_round_down:
+ return
+ aSign ?
+ packFloatx80( 1, 0x3FFF, LIT64( 0x8000000000000000 ) )
+ : packFloatx80( 0, 0, 0 );
+ case float_round_up:
+ return
+ aSign ? packFloatx80( 1, 0, 0 )
+ : packFloatx80( 0, 0x3FFF, LIT64( 0x8000000000000000 ) );
+ }
+ return packFloatx80( aSign, 0, 0 );
+ }
+ lastBitMask = 1;
+ lastBitMask <<= 0x403E - aExp;
+ roundBitsMask = lastBitMask - 1;
+ z = a;
+ roundingMode = float_rounding_mode;
+ if ( roundingMode == float_round_nearest_even ) {
+ z.low += lastBitMask>>1;
+ if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
+ }
+ else if ( roundingMode != float_round_to_zero ) {
+ if ( extractFloatx80Sign( z ) ^ ( roundingMode == float_round_up ) ) {
+ z.low += roundBitsMask;
+ }
+ }
+ z.low &= ~ roundBitsMask;
+ if ( z.low == 0 ) {
+ ++z.high;
+ z.low = LIT64( 0x8000000000000000 );
+ }
+ if ( z.low != a.low ) float_exception_flags |= float_flag_inexact;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the absolute values of the extended double-
+precision floating-point values `a' and `b'. If `zSign' is 1, the sum is
+negated before being returned. `zSign' is ignored if the result is a NaN.
+The addition is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static floatx80 addFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
+{
+ int32 aExp, bExp, zExp;
+ bits64 aSig, bSig, zSig0, zSig1;
+ int32 expDiff;
+
+ aSig = extractFloatx80Frac( a );
+ aExp = extractFloatx80Exp( a );
+ bSig = extractFloatx80Frac( b );
+ bExp = extractFloatx80Exp( b );
+ expDiff = aExp - bExp;
+ if ( 0 < expDiff ) {
+ if ( aExp == 0x7FFF ) {
+ if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) --expDiff;
+ shift64ExtraRightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
+ zExp = aExp;
+ }
+ else if ( expDiff < 0 ) {
+ if ( bExp == 0x7FFF ) {
+ if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+ return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ }
+ if ( aExp == 0 ) ++expDiff;
+ shift64ExtraRightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
+ zExp = bExp;
+ }
+ else {
+ if ( aExp == 0x7FFF ) {
+ if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
+ return propagateFloatx80NaN( a, b );
+ }
+ return a;
+ }
+ zSig1 = 0;
+ zSig0 = aSig + bSig;
+ if ( aExp == 0 ) {
+ normalizeFloatx80Subnormal( zSig0, &zExp, &zSig0 );
+ goto roundAndPack;
+ }
+ zExp = aExp;
+ goto shiftRight1;
+ }
+ zSig0 = aSig + bSig;
+ if ( (sbits64) zSig0 < 0 ) goto roundAndPack;
+ shiftRight1:
+ shift64ExtraRightJamming( zSig0, zSig1, 1, &zSig0, &zSig1 );
+ zSig0 |= LIT64( 0x8000000000000000 );
+ ++zExp;
+ roundAndPack:
+ return
+ roundAndPackFloatx80(
+ floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the absolute values of the extended
+double-precision floating-point values `a' and `b'. If `zSign' is 1, the
+difference is negated before being returned. `zSign' is ignored if the
+result is a NaN. The subtraction is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static floatx80 subFloatx80Sigs( floatx80 a, floatx80 b, flag zSign )
+{
+ int32 aExp, bExp, zExp;
+ bits64 aSig, bSig, zSig0, zSig1;
+ int32 expDiff;
+ floatx80 z;
+
+ aSig = extractFloatx80Frac( a );
+ aExp = extractFloatx80Exp( a );
+ bSig = extractFloatx80Frac( b );
+ bExp = extractFloatx80Exp( b );
+ expDiff = aExp - bExp;
+ if ( 0 < expDiff ) goto aExpBigger;
+ if ( expDiff < 0 ) goto bExpBigger;
+ if ( aExp == 0x7FFF ) {
+ if ( (bits64) ( ( aSig | bSig )<<1 ) ) {
+ return propagateFloatx80NaN( a, b );
+ }
+ float_raise( float_flag_invalid );
+ z.low = floatx80_default_nan_low;
+ z.high = floatx80_default_nan_high;
+ return z;
+ }
+ if ( aExp == 0 ) {
+ aExp = 1;
+ bExp = 1;
+ }
+ zSig1 = 0;
+ if ( bSig < aSig ) goto aBigger;
+ if ( aSig < bSig ) goto bBigger;
+ return packFloatx80( float_rounding_mode == float_round_down, 0, 0 );
+ bExpBigger:
+ if ( bExp == 0x7FFF ) {
+ if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+ return packFloatx80( zSign ^ 1, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ }
+ if ( aExp == 0 ) ++expDiff;
+ shift128RightJamming( aSig, 0, - expDiff, &aSig, &zSig1 );
+ bBigger:
+ sub128( bSig, 0, aSig, zSig1, &zSig0, &zSig1 );
+ zExp = bExp;
+ zSign ^= 1;
+ goto normalizeRoundAndPack;
+ aExpBigger:
+ if ( aExp == 0x7FFF ) {
+ if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) --expDiff;
+ shift128RightJamming( bSig, 0, expDiff, &bSig, &zSig1 );
+ aBigger:
+ sub128( aSig, 0, bSig, zSig1, &zSig0, &zSig1 );
+ zExp = aExp;
+ normalizeRoundAndPack:
+ return
+ normalizeRoundAndPackFloatx80(
+ floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the extended double-precision floating-point
+values `a' and `b'. The operation is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_add( floatx80 a, floatx80 b )
+{
+ flag aSign, bSign;
+
+ aSign = extractFloatx80Sign( a );
+ bSign = extractFloatx80Sign( b );
+ if ( aSign == bSign ) {
+ return addFloatx80Sigs( a, b, aSign );
+ }
+ else {
+ return subFloatx80Sigs( a, b, aSign );
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the extended double-precision floating-
+point values `a' and `b'. The operation is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_sub( floatx80 a, floatx80 b )
+{
+ flag aSign, bSign;
+
+ aSign = extractFloatx80Sign( a );
+ bSign = extractFloatx80Sign( b );
+ if ( aSign == bSign ) {
+ return subFloatx80Sigs( a, b, aSign );
+ }
+ else {
+ return addFloatx80Sigs( a, b, aSign );
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of multiplying the extended double-precision floating-
+point values `a' and `b'. The operation is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_mul( floatx80 a, floatx80 b )
+{
+ flag aSign, bSign, zSign;
+ int32 aExp, bExp, zExp;
+ bits64 aSig, bSig, zSig0, zSig1;
+ floatx80 z;
+
+ aSig = extractFloatx80Frac( a );
+ aExp = extractFloatx80Exp( a );
+ aSign = extractFloatx80Sign( a );
+ bSig = extractFloatx80Frac( b );
+ bExp = extractFloatx80Exp( b );
+ bSign = extractFloatx80Sign( b );
+ zSign = aSign ^ bSign;
+ if ( aExp == 0x7FFF ) {
+ if ( (bits64) ( aSig<<1 )
+ || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
+ return propagateFloatx80NaN( a, b );
+ }
+ if ( ( bExp | bSig ) == 0 ) goto invalid;
+ return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ }
+ if ( bExp == 0x7FFF ) {
+ if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+ if ( ( aExp | aSig ) == 0 ) {
+ invalid:
+ float_raise( float_flag_invalid );
+ z.low = floatx80_default_nan_low;
+ z.high = floatx80_default_nan_high;
+ return z;
+ }
+ return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
+ normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
+ }
+ if ( bExp == 0 ) {
+ if ( bSig == 0 ) return packFloatx80( zSign, 0, 0 );
+ normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
+ }
+ zExp = aExp + bExp - 0x3FFE;
+ mul64To128( aSig, bSig, &zSig0, &zSig1 );
+ if ( 0 < (sbits64) zSig0 ) {
+ shortShift128Left( zSig0, zSig1, 1, &zSig0, &zSig1 );
+ --zExp;
+ }
+ return
+ roundAndPackFloatx80(
+ floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of dividing the extended double-precision floating-point
+value `a' by the corresponding value `b'. The operation is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_div( floatx80 a, floatx80 b )
+{
+ flag aSign, bSign, zSign;
+ int32 aExp, bExp, zExp;
+ bits64 aSig, bSig, zSig0, zSig1;
+ bits64 rem0, rem1, rem2, term0, term1, term2;
+ floatx80 z;
+
+ aSig = extractFloatx80Frac( a );
+ aExp = extractFloatx80Exp( a );
+ aSign = extractFloatx80Sign( a );
+ bSig = extractFloatx80Frac( b );
+ bExp = extractFloatx80Exp( b );
+ bSign = extractFloatx80Sign( b );
+ zSign = aSign ^ bSign;
+ if ( aExp == 0x7FFF ) {
+ if ( (bits64) ( aSig<<1 ) ) return propagateFloatx80NaN( a, b );
+ if ( bExp == 0x7FFF ) {
+ if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+ goto invalid;
+ }
+ return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ }
+ if ( bExp == 0x7FFF ) {
+ if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+ return packFloatx80( zSign, 0, 0 );
+ }
+ if ( bExp == 0 ) {
+ if ( bSig == 0 ) {
+ if ( ( aExp | aSig ) == 0 ) {
+ invalid:
+ float_raise( float_flag_invalid );
+ z.low = floatx80_default_nan_low;
+ z.high = floatx80_default_nan_high;
+ return z;
+ }
+ float_raise( float_flag_divbyzero );
+ return packFloatx80( zSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ }
+ normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
+ }
+ if ( aExp == 0 ) {
+ if ( aSig == 0 ) return packFloatx80( zSign, 0, 0 );
+ normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
+ }
+ zExp = aExp - bExp + 0x3FFE;
+ rem1 = 0;
+ if ( bSig <= aSig ) {
+ shift128Right( aSig, 0, 1, &aSig, &rem1 );
+ ++zExp;
+ }
+ zSig0 = estimateDiv128To64( aSig, rem1, bSig );
+ mul64To128( bSig, zSig0, &term0, &term1 );
+ sub128( aSig, rem1, term0, term1, &rem0, &rem1 );
+ while ( (sbits64) rem0 < 0 ) {
+ --zSig0;
+ add128( rem0, rem1, 0, bSig, &rem0, &rem1 );
+ }
+ zSig1 = estimateDiv128To64( rem1, 0, bSig );
+ if ( (bits64) ( zSig1<<1 ) <= 8 ) {
+ mul64To128( bSig, zSig1, &term1, &term2 );
+ sub128( rem1, 0, term1, term2, &rem1, &rem2 );
+ while ( (sbits64) rem1 < 0 ) {
+ --zSig1;
+ add128( rem1, rem2, 0, bSig, &rem1, &rem2 );
+ }
+ zSig1 |= ( ( rem1 | rem2 ) != 0 );
+ }
+ return
+ roundAndPackFloatx80(
+ floatx80_rounding_precision, zSign, zExp, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the remainder of the extended double-precision floating-point value
+`a' with respect to the corresponding value `b'. The operation is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_rem( floatx80 a, floatx80 b )
+{
+ flag aSign, bSign, zSign;
+ int32 aExp, bExp, expDiff;
+ bits64 aSig0, aSig1, bSig;
+ bits64 q, term0, term1, alternateASig0, alternateASig1;
+ floatx80 z;
+
+ aSig0 = extractFloatx80Frac( a );
+ aExp = extractFloatx80Exp( a );
+ aSign = extractFloatx80Sign( a );
+ bSig = extractFloatx80Frac( b );
+ bExp = extractFloatx80Exp( b );
+ bSign = extractFloatx80Sign( b );
+ if ( aExp == 0x7FFF ) {
+ if ( (bits64) ( aSig0<<1 )
+ || ( ( bExp == 0x7FFF ) && (bits64) ( bSig<<1 ) ) ) {
+ return propagateFloatx80NaN( a, b );
+ }
+ goto invalid;
+ }
+ if ( bExp == 0x7FFF ) {
+ if ( (bits64) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ if ( bSig == 0 ) {
+ invalid:
+ float_raise( float_flag_invalid );
+ z.low = floatx80_default_nan_low;
+ z.high = floatx80_default_nan_high;
+ return z;
+ }
+ normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
+ }
+ if ( aExp == 0 ) {
+ if ( (bits64) ( aSig0<<1 ) == 0 ) return a;
+ normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
+ }
+ bSig |= LIT64( 0x8000000000000000 );
+ zSign = aSign;
+ expDiff = aExp - bExp;
+ aSig1 = 0;
+ if ( expDiff < 0 ) {
+ if ( expDiff < -1 ) return a;
+ shift128Right( aSig0, 0, 1, &aSig0, &aSig1 );
+ expDiff = 0;
+ }
+ q = ( bSig <= aSig0 );
+ if ( q ) aSig0 -= bSig;
+ expDiff -= 64;
+ while ( 0 < expDiff ) {
+ q = estimateDiv128To64( aSig0, aSig1, bSig );
+ q = ( 2 < q ) ? q - 2 : 0;
+ mul64To128( bSig, q, &term0, &term1 );
+ sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
+ shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 );
+ expDiff -= 62;
+ }
+ expDiff += 64;
+ if ( 0 < expDiff ) {
+ q = estimateDiv128To64( aSig0, aSig1, bSig );
+ q = ( 2 < q ) ? q - 2 : 0;
+ q >>= 64 - expDiff;
+ mul64To128( bSig, q<<( 64 - expDiff ), &term0, &term1 );
+ sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
+ shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 );
+ while ( le128( term0, term1, aSig0, aSig1 ) ) {
+ ++q;
+ sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
+ }
+ }
+ else {
+ term1 = 0;
+ term0 = bSig;
+ }
+ sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 );
+ if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 )
+ || ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 )
+ && ( q & 1 ) )
+ ) {
+ aSig0 = alternateASig0;
+ aSig1 = alternateASig1;
+ zSign = ! zSign;
+ }
+ return
+ normalizeRoundAndPackFloatx80(
+ 80, zSign, bExp + expDiff, aSig0, aSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the square root of the extended double-precision floating-point
+value `a'. The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_sqrt( floatx80 a )
+{
+ flag aSign;
+ int32 aExp, zExp;
+ bits64 aSig0, aSig1, zSig0, zSig1, doubleZSig0;
+ bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
+ floatx80 z;
+
+ aSig0 = extractFloatx80Frac( a );
+ aExp = extractFloatx80Exp( a );
+ aSign = extractFloatx80Sign( a );
+ if ( aExp == 0x7FFF ) {
+ if ( (bits64) ( aSig0<<1 ) ) return propagateFloatx80NaN( a, a );
+ if ( ! aSign ) return a;
+ goto invalid;
+ }
+ if ( aSign ) {
+ if ( ( aExp | aSig0 ) == 0 ) return a;
+ invalid:
+ float_raise( float_flag_invalid );
+ z.low = floatx80_default_nan_low;
+ z.high = floatx80_default_nan_high;
+ return z;
+ }
+ if ( aExp == 0 ) {
+ if ( aSig0 == 0 ) return packFloatx80( 0, 0, 0 );
+ normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
+ }
+ zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFF;
+ zSig0 = estimateSqrt32( aExp, aSig0>>32 );
+ shift128Right( aSig0, 0, 2 + ( aExp & 1 ), &aSig0, &aSig1 );
+ zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 );
+ doubleZSig0 = zSig0<<1;
+ mul64To128( zSig0, zSig0, &term0, &term1 );
+ sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
+ while ( (sbits64) rem0 < 0 ) {
+ --zSig0;
+ doubleZSig0 -= 2;
+ add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 );
+ }
+ zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 );
+ if ( ( zSig1 & LIT64( 0x3FFFFFFFFFFFFFFF ) ) <= 5 ) {
+ if ( zSig1 == 0 ) zSig1 = 1;
+ mul64To128( doubleZSig0, zSig1, &term1, &term2 );
+ sub128( rem1, 0, term1, term2, &rem1, &rem2 );
+ mul64To128( zSig1, zSig1, &term2, &term3 );
+ sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
+ while ( (sbits64) rem1 < 0 ) {
+ --zSig1;
+ shortShift128Left( 0, zSig1, 1, &term2, &term3 );
+ term3 |= 1;
+ term2 |= doubleZSig0;
+ add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 );
+ }
+ zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
+ }
+ shortShift128Left( 0, zSig1, 1, &zSig0, &zSig1 );
+ zSig0 |= doubleZSig0;
+ return
+ roundAndPackFloatx80(
+ floatx80_rounding_precision, 0, zExp, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is
+equal to the corresponding value `b', and 0 otherwise. The comparison is
+performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_eq( floatx80 a, floatx80 b )
+{
+
+ if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
+ && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+ || ( ( extractFloatx80Exp( b ) == 0x7FFF )
+ && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+ ) {
+ if ( floatx80_is_signaling_nan( a )
+ || floatx80_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ return
+ ( a.low == b.low )
+ && ( ( a.high == b.high )
+ || ( ( a.low == 0 )
+ && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) )
+ );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is
+less than or equal to the corresponding value `b', and 0 otherwise. The
+comparison is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_le( floatx80 a, floatx80 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
+ && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+ || ( ( extractFloatx80Exp( b ) == 0x7FFF )
+ && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ aSign = extractFloatx80Sign( a );
+ bSign = extractFloatx80Sign( b );
+ if ( aSign != bSign ) {
+ return
+ aSign
+ || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+ == 0 );
+ }
+ return
+ aSign ? le128( b.high, b.low, a.high, a.low )
+ : le128( a.high, a.low, b.high, b.low );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is
+less than the corresponding value `b', and 0 otherwise. The comparison
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_lt( floatx80 a, floatx80 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
+ && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+ || ( ( extractFloatx80Exp( b ) == 0x7FFF )
+ && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ aSign = extractFloatx80Sign( a );
+ bSign = extractFloatx80Sign( b );
+ if ( aSign != bSign ) {
+ return
+ aSign
+ && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+ != 0 );
+ }
+ return
+ aSign ? lt128( b.high, b.low, a.high, a.low )
+ : lt128( a.high, a.low, b.high, b.low );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is equal
+to the corresponding value `b', and 0 otherwise. The invalid exception is
+raised if either operand is a NaN. Otherwise, the comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_eq_signaling( floatx80 a, floatx80 b )
+{
+
+ if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
+ && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+ || ( ( extractFloatx80Exp( b ) == 0x7FFF )
+ && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ return
+ ( a.low == b.low )
+ && ( ( a.high == b.high )
+ || ( ( a.low == 0 )
+ && ( (bits16) ( ( a.high | b.high )<<1 ) == 0 ) )
+ );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is less
+than or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs
+do not cause an exception. Otherwise, the comparison is performed according
+to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_le_quiet( floatx80 a, floatx80 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
+ && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+ || ( ( extractFloatx80Exp( b ) == 0x7FFF )
+ && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+ ) {
+ if ( floatx80_is_signaling_nan( a )
+ || floatx80_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ aSign = extractFloatx80Sign( a );
+ bSign = extractFloatx80Sign( b );
+ if ( aSign != bSign ) {
+ return
+ aSign
+ || ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+ == 0 );
+ }
+ return
+ aSign ? le128( b.high, b.low, a.high, a.low )
+ : le128( a.high, a.low, b.high, b.low );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is less
+than the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause
+an exception. Otherwise, the comparison is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_lt_quiet( floatx80 a, floatx80 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloatx80Exp( a ) == 0x7FFF )
+ && (bits64) ( extractFloatx80Frac( a )<<1 ) )
+ || ( ( extractFloatx80Exp( b ) == 0x7FFF )
+ && (bits64) ( extractFloatx80Frac( b )<<1 ) )
+ ) {
+ if ( floatx80_is_signaling_nan( a )
+ || floatx80_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ aSign = extractFloatx80Sign( a );
+ bSign = extractFloatx80Sign( b );
+ if ( aSign != bSign ) {
+ return
+ aSign
+ && ( ( ( (bits16) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+ != 0 );
+ }
+ return
+ aSign ? lt128( b.high, b.low, a.high, a.low )
+ : lt128( a.high, a.low, b.high, b.low );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point
+value `a' to the 32-bit two's complement integer format. The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode. If `a' is a NaN, the largest
+positive integer is returned. Otherwise, if the conversion overflows, the
+largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int32 float128_to_int32( float128 a )
+{
+ flag aSign;
+ int32 aExp, shiftCount;
+ bits64 aSig0, aSig1;
+
+ aSig1 = extractFloat128Frac1( a );
+ aSig0 = extractFloat128Frac0( a );
+ aExp = extractFloat128Exp( a );
+ aSign = extractFloat128Sign( a );
+ if ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) aSign = 0;
+ if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
+ aSig0 |= ( aSig1 != 0 );
+ shiftCount = 0x4028 - aExp;
+ if ( 0 < shiftCount ) shift64RightJamming( aSig0, shiftCount, &aSig0 );
+ return roundAndPackInt32( aSign, aSig0 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point
+value `a' to the 32-bit two's complement integer format. The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic, except that the conversion is always rounded toward zero. If
+`a' is a NaN, the largest positive integer is returned. Otherwise, if the
+conversion overflows, the largest integer with the same sign as `a' is
+returned.
+-------------------------------------------------------------------------------
+*/
+int32 float128_to_int32_round_to_zero( float128 a )
+{
+ flag aSign;
+ int32 aExp, shiftCount;
+ bits64 aSig0, aSig1, savedASig;
+ int32 z;
+
+ aSig1 = extractFloat128Frac1( a );
+ aSig0 = extractFloat128Frac0( a );
+ aExp = extractFloat128Exp( a );
+ aSign = extractFloat128Sign( a );
+ aSig0 |= ( aSig1 != 0 );
+ if ( 0x401E < aExp ) {
+ if ( ( aExp == 0x7FFF ) && aSig0 ) aSign = 0;
+ goto invalid;
+ }
+ else if ( aExp < 0x3FFF ) {
+ if ( aExp || aSig0 ) float_exception_flags |= float_flag_inexact;
+ return 0;
+ }
+ aSig0 |= LIT64( 0x0001000000000000 );
+ shiftCount = 0x402F - aExp;
+ savedASig = aSig0;
+ aSig0 >>= shiftCount;
+ z = aSig0;
+ if ( aSign ) z = - z;
+ if ( ( z < 0 ) ^ aSign ) {
+ invalid:
+ float_raise( float_flag_invalid );
+ return aSign ? (sbits32) 0x80000000 : 0x7FFFFFFF;
+ }
+ if ( ( aSig0<<shiftCount ) != savedASig ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point
+value `a' to the 64-bit two's complement integer format. The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic---which means in particular that the conversion is rounded
+according to the current rounding mode. If `a' is a NaN, the largest
+positive integer is returned. Otherwise, if the conversion overflows, the
+largest integer with the same sign as `a' is returned.
+-------------------------------------------------------------------------------
+*/
+int64 float128_to_int64( float128 a )
+{
+ flag aSign;
+ int32 aExp, shiftCount;
+ bits64 aSig0, aSig1;
+
+ aSig1 = extractFloat128Frac1( a );
+ aSig0 = extractFloat128Frac0( a );
+ aExp = extractFloat128Exp( a );
+ aSign = extractFloat128Sign( a );
+ if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
+ shiftCount = 0x402F - aExp;
+ if ( shiftCount <= 0 ) {
+ if ( 0x403E < aExp ) {
+ float_raise( float_flag_invalid );
+ if ( ! aSign
+ || ( ( aExp == 0x7FFF )
+ && ( aSig1 || ( aSig0 != LIT64( 0x0001000000000000 ) ) )
+ )
+ ) {
+ return LIT64( 0x7FFFFFFFFFFFFFFF );
+ }
+ return (sbits64) LIT64( 0x8000000000000000 );
+ }
+ shortShift128Left( aSig0, aSig1, - shiftCount, &aSig0, &aSig1 );
+ }
+ else {
+ shift64ExtraRightJamming( aSig0, aSig1, shiftCount, &aSig0, &aSig1 );
+ }
+ return roundAndPackInt64( aSign, aSig0, aSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point
+value `a' to the 64-bit two's complement integer format. The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic, except that the conversion is always rounded toward zero.
+If `a' is a NaN, the largest positive integer is returned. Otherwise, if
+the conversion overflows, the largest integer with the same sign as `a' is
+returned.
+-------------------------------------------------------------------------------
+*/
+int64 float128_to_int64_round_to_zero( float128 a )
+{
+ flag aSign;
+ int32 aExp, shiftCount;
+ bits64 aSig0, aSig1;
+ int64 z;
+
+ aSig1 = extractFloat128Frac1( a );
+ aSig0 = extractFloat128Frac0( a );
+ aExp = extractFloat128Exp( a );
+ aSign = extractFloat128Sign( a );
+ if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
+ shiftCount = aExp - 0x402F;
+ if ( 0 < shiftCount ) {
+ if ( 0x403E <= aExp ) {
+ aSig0 &= LIT64( 0x0000FFFFFFFFFFFF );
+ if ( ( a.high == LIT64( 0xC03E000000000000 ) )
+ && ( aSig1 < LIT64( 0x0002000000000000 ) ) ) {
+ if ( aSig1 ) float_exception_flags |= float_flag_inexact;
+ }
+ else {
+ float_raise( float_flag_invalid );
+ if ( ! aSign || ( ( aExp == 0x7FFF ) && ( aSig0 | aSig1 ) ) ) {
+ return LIT64( 0x7FFFFFFFFFFFFFFF );
+ }
+ }
+ return (sbits64) LIT64( 0x8000000000000000 );
+ }
+ z = ( aSig0<<shiftCount ) | ( aSig1>>( ( - shiftCount ) & 63 ) );
+ if ( (bits64) ( aSig1<<shiftCount ) ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ }
+ else {
+ if ( aExp < 0x3FFF ) {
+ if ( aExp | aSig0 | aSig1 ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ return 0;
+ }
+ z = aSig0>>( - shiftCount );
+ if ( aSig1
+ || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ }
+ if ( aSign ) z = - z;
+ return z;
+
+}
+
+#if (defined(SOFTFLOATSPARC64_FOR_GCC) || defined(SOFTFLOAT_FOR_GCC)) \
+ && defined(SOFTFLOAT_NEED_FIXUNS)
+/*
+ * just like above - but do not care for overflow of signed results
+ */
+uint64 float128_to_uint64_round_to_zero( float128 a )
+{
+ flag aSign;
+ int32 aExp, shiftCount;
+ bits64 aSig0, aSig1;
+ uint64 z;
+
+ aSig1 = extractFloat128Frac1( a );
+ aSig0 = extractFloat128Frac0( a );
+ aExp = extractFloat128Exp( a );
+ aSign = extractFloat128Sign( a );
+ if ( aExp ) aSig0 |= LIT64( 0x0001000000000000 );
+ shiftCount = aExp - 0x402F;
+ if ( 0 < shiftCount ) {
+ if ( 0x403F <= aExp ) {
+ aSig0 &= LIT64( 0x0000FFFFFFFFFFFF );
+ if ( ( a.high == LIT64( 0xC03E000000000000 ) )
+ && ( aSig1 < LIT64( 0x0002000000000000 ) ) ) {
+ if ( aSig1 ) float_exception_flags |= float_flag_inexact;
+ }
+ else {
+ float_raise( float_flag_invalid );
+ }
+ return LIT64( 0xFFFFFFFFFFFFFFFF );
+ }
+ z = ( aSig0<<shiftCount ) | ( aSig1>>( ( - shiftCount ) & 63 ) );
+ if ( (bits64) ( aSig1<<shiftCount ) ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ }
+ else {
+ if ( aExp < 0x3FFF ) {
+ if ( aExp | aSig0 | aSig1 ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ return 0;
+ }
+ z = aSig0>>( - shiftCount );
+ if (aSig1 || ( shiftCount && (bits64) ( aSig0<<( shiftCount & 63 ) ) ) ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ }
+ if ( aSign ) z = - z;
+ return z;
+
+}
+#endif /* (SOFTFLOATSPARC64_FOR_GCC || SOFTFLOAT_FOR_GCC) && SOFTFLOAT_NEED_FIXUNS */
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point
+value `a' to the single-precision floating-point format. The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float32 float128_to_float32( float128 a )
+{
+ flag aSign;
+ int32 aExp;
+ bits64 aSig0, aSig1;
+ bits32 zSig;
+
+ aSig1 = extractFloat128Frac1( a );
+ aSig0 = extractFloat128Frac0( a );
+ aExp = extractFloat128Exp( a );
+ aSign = extractFloat128Sign( a );
+ if ( aExp == 0x7FFF ) {
+ if ( aSig0 | aSig1 ) {
+ return commonNaNToFloat32( float128ToCommonNaN( a ) );
+ }
+ return packFloat32( aSign, 0xFF, 0 );
+ }
+ aSig0 |= ( aSig1 != 0 );
+ shift64RightJamming( aSig0, 18, &aSig0 );
+ zSig = aSig0;
+ if ( aExp || zSig ) {
+ zSig |= 0x40000000;
+ aExp -= 0x3F81;
+ }
+ return roundAndPackFloat32( aSign, aExp, zSig );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point
+value `a' to the double-precision floating-point format. The conversion
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float64 float128_to_float64( float128 a )
+{
+ flag aSign;
+ int32 aExp;
+ bits64 aSig0, aSig1;
+
+ aSig1 = extractFloat128Frac1( a );
+ aSig0 = extractFloat128Frac0( a );
+ aExp = extractFloat128Exp( a );
+ aSign = extractFloat128Sign( a );
+ if ( aExp == 0x7FFF ) {
+ if ( aSig0 | aSig1 ) {
+ return commonNaNToFloat64( float128ToCommonNaN( a ) );
+ }
+ return packFloat64( aSign, 0x7FF, 0 );
+ }
+ shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 );
+ aSig0 |= ( aSig1 != 0 );
+ if ( aExp || aSig0 ) {
+ aSig0 |= LIT64( 0x4000000000000000 );
+ aExp -= 0x3C01;
+ }
+ return roundAndPackFloat64( aSign, aExp, aSig0 );
+
+}
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point
+value `a' to the extended double-precision floating-point format. The
+conversion is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+floatx80 float128_to_floatx80( float128 a )
+{
+ flag aSign;
+ int32 aExp;
+ bits64 aSig0, aSig1;
+
+ aSig1 = extractFloat128Frac1( a );
+ aSig0 = extractFloat128Frac0( a );
+ aExp = extractFloat128Exp( a );
+ aSign = extractFloat128Sign( a );
+ if ( aExp == 0x7FFF ) {
+ if ( aSig0 | aSig1 ) {
+ return commonNaNToFloatx80( float128ToCommonNaN( a ) );
+ }
+ return packFloatx80( aSign, 0x7FFF, LIT64( 0x8000000000000000 ) );
+ }
+ if ( aExp == 0 ) {
+ if ( ( aSig0 | aSig1 ) == 0 ) return packFloatx80( aSign, 0, 0 );
+ normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+ }
+ else {
+ aSig0 |= LIT64( 0x0001000000000000 );
+ }
+ shortShift128Left( aSig0, aSig1, 15, &aSig0, &aSig1 );
+ return roundAndPackFloatx80( 80, aSign, aExp, aSig0, aSig1 );
+
+}
+
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Rounds the quadruple-precision floating-point value `a' to an integer, and
+returns the result as a quadruple-precision floating-point value. The
+operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float128_round_to_int( float128 a )
+{
+ flag aSign;
+ int32 aExp;
+ bits64 lastBitMask, roundBitsMask;
+ int8 roundingMode;
+ float128 z;
+
+ aExp = extractFloat128Exp( a );
+ if ( 0x402F <= aExp ) {
+ if ( 0x406F <= aExp ) {
+ if ( ( aExp == 0x7FFF )
+ && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) )
+ ) {
+ return propagateFloat128NaN( a, a );
+ }
+ return a;
+ }
+ lastBitMask = 1;
+ lastBitMask = ( lastBitMask<<( 0x406E - aExp ) )<<1;
+ roundBitsMask = lastBitMask - 1;
+ z = a;
+ roundingMode = float_rounding_mode;
+ if ( roundingMode == float_round_nearest_even ) {
+ if ( lastBitMask ) {
+ add128( z.high, z.low, 0, lastBitMask>>1, &z.high, &z.low );
+ if ( ( z.low & roundBitsMask ) == 0 ) z.low &= ~ lastBitMask;
+ }
+ else {
+ if ( (sbits64) z.low < 0 ) {
+ ++z.high;
+ if ( (bits64) ( z.low<<1 ) == 0 ) z.high &= ~1;
+ }
+ }
+ }
+ else if ( roundingMode != float_round_to_zero ) {
+ if ( extractFloat128Sign( z )
+ ^ ( roundingMode == float_round_up ) ) {
+ add128( z.high, z.low, 0, roundBitsMask, &z.high, &z.low );
+ }
+ }
+ z.low &= ~ roundBitsMask;
+ }
+ else {
+ if ( aExp < 0x3FFF ) {
+ if ( ( ( (bits64) ( a.high<<1 ) ) | a.low ) == 0 ) return a;
+ float_exception_flags |= float_flag_inexact;
+ aSign = extractFloat128Sign( a );
+ switch ( float_rounding_mode ) {
+ case float_round_nearest_even:
+ if ( ( aExp == 0x3FFE )
+ && ( extractFloat128Frac0( a )
+ | extractFloat128Frac1( a ) )
+ ) {
+ return packFloat128( aSign, 0x3FFF, 0, 0 );
+ }
+ break;
+ case float_round_to_zero:
+ break;
+ case float_round_down:
+ return
+ aSign ? packFloat128( 1, 0x3FFF, 0, 0 )
+ : packFloat128( 0, 0, 0, 0 );
+ case float_round_up:
+ return
+ aSign ? packFloat128( 1, 0, 0, 0 )
+ : packFloat128( 0, 0x3FFF, 0, 0 );
+ }
+ return packFloat128( aSign, 0, 0, 0 );
+ }
+ lastBitMask = 1;
+ lastBitMask <<= 0x402F - aExp;
+ roundBitsMask = lastBitMask - 1;
+ z.low = 0;
+ z.high = a.high;
+ roundingMode = float_rounding_mode;
+ if ( roundingMode == float_round_nearest_even ) {
+ z.high += lastBitMask>>1;
+ if ( ( ( z.high & roundBitsMask ) | a.low ) == 0 ) {
+ z.high &= ~ lastBitMask;
+ }
+ }
+ else if ( roundingMode != float_round_to_zero ) {
+ if ( extractFloat128Sign( z )
+ ^ ( roundingMode == float_round_up ) ) {
+ z.high |= ( a.low != 0 );
+ z.high += roundBitsMask;
+ }
+ }
+ z.high &= ~ roundBitsMask;
+ }
+ if ( ( z.low != a.low ) || ( z.high != a.high ) ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the absolute values of the quadruple-precision
+floating-point values `a' and `b'. If `zSign' is 1, the sum is negated
+before being returned. `zSign' is ignored if the result is a NaN.
+The addition is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float128 addFloat128Sigs( float128 a, float128 b, flag zSign )
+{
+ int32 aExp, bExp, zExp;
+ bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
+ int32 expDiff;
+
+ aSig1 = extractFloat128Frac1( a );
+ aSig0 = extractFloat128Frac0( a );
+ aExp = extractFloat128Exp( a );
+ bSig1 = extractFloat128Frac1( b );
+ bSig0 = extractFloat128Frac0( b );
+ bExp = extractFloat128Exp( b );
+ expDiff = aExp - bExp;
+ if ( 0 < expDiff ) {
+ if ( aExp == 0x7FFF ) {
+ if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ --expDiff;
+ }
+ else {
+ bSig0 |= LIT64( 0x0001000000000000 );
+ }
+ shift128ExtraRightJamming(
+ bSig0, bSig1, 0, expDiff, &bSig0, &bSig1, &zSig2 );
+ zExp = aExp;
+ }
+ else if ( expDiff < 0 ) {
+ if ( bExp == 0x7FFF ) {
+ if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+ return packFloat128( zSign, 0x7FFF, 0, 0 );
+ }
+ if ( aExp == 0 ) {
+ ++expDiff;
+ }
+ else {
+ aSig0 |= LIT64( 0x0001000000000000 );
+ }
+ shift128ExtraRightJamming(
+ aSig0, aSig1, 0, - expDiff, &aSig0, &aSig1, &zSig2 );
+ zExp = bExp;
+ }
+ else {
+ if ( aExp == 0x7FFF ) {
+ if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
+ return propagateFloat128NaN( a, b );
+ }
+ return a;
+ }
+ add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
+ if ( aExp == 0 ) return packFloat128( zSign, 0, zSig0, zSig1 );
+ zSig2 = 0;
+ zSig0 |= LIT64( 0x0002000000000000 );
+ zExp = aExp;
+ goto shiftRight1;
+ }
+ aSig0 |= LIT64( 0x0001000000000000 );
+ add128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
+ --zExp;
+ if ( zSig0 < LIT64( 0x0002000000000000 ) ) goto roundAndPack;
+ ++zExp;
+ shiftRight1:
+ shift128ExtraRightJamming(
+ zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
+ roundAndPack:
+ return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the absolute values of the quadruple-
+precision floating-point values `a' and `b'. If `zSign' is 1, the
+difference is negated before being returned. `zSign' is ignored if the
+result is a NaN. The subtraction is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+static float128 subFloat128Sigs( float128 a, float128 b, flag zSign )
+{
+ int32 aExp, bExp, zExp;
+ bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1;
+ int32 expDiff;
+ float128 z;
+
+ aSig1 = extractFloat128Frac1( a );
+ aSig0 = extractFloat128Frac0( a );
+ aExp = extractFloat128Exp( a );
+ bSig1 = extractFloat128Frac1( b );
+ bSig0 = extractFloat128Frac0( b );
+ bExp = extractFloat128Exp( b );
+ expDiff = aExp - bExp;
+ shortShift128Left( aSig0, aSig1, 14, &aSig0, &aSig1 );
+ shortShift128Left( bSig0, bSig1, 14, &bSig0, &bSig1 );
+ if ( 0 < expDiff ) goto aExpBigger;
+ if ( expDiff < 0 ) goto bExpBigger;
+ if ( aExp == 0x7FFF ) {
+ if ( aSig0 | aSig1 | bSig0 | bSig1 ) {
+ return propagateFloat128NaN( a, b );
+ }
+ float_raise( float_flag_invalid );
+ z.low = float128_default_nan_low;
+ z.high = float128_default_nan_high;
+ return z;
+ }
+ if ( aExp == 0 ) {
+ aExp = 1;
+ bExp = 1;
+ }
+ if ( bSig0 < aSig0 ) goto aBigger;
+ if ( aSig0 < bSig0 ) goto bBigger;
+ if ( bSig1 < aSig1 ) goto aBigger;
+ if ( aSig1 < bSig1 ) goto bBigger;
+ return packFloat128( float_rounding_mode == float_round_down, 0, 0, 0 );
+ bExpBigger:
+ if ( bExp == 0x7FFF ) {
+ if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+ return packFloat128( zSign ^ 1, 0x7FFF, 0, 0 );
+ }
+ if ( aExp == 0 ) {
+ ++expDiff;
+ }
+ else {
+ aSig0 |= LIT64( 0x4000000000000000 );
+ }
+ shift128RightJamming( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
+ bSig0 |= LIT64( 0x4000000000000000 );
+ bBigger:
+ sub128( bSig0, bSig1, aSig0, aSig1, &zSig0, &zSig1 );
+ zExp = bExp;
+ zSign ^= 1;
+ goto normalizeRoundAndPack;
+ aExpBigger:
+ if ( aExp == 0x7FFF ) {
+ if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ --expDiff;
+ }
+ else {
+ bSig0 |= LIT64( 0x4000000000000000 );
+ }
+ shift128RightJamming( bSig0, bSig1, expDiff, &bSig0, &bSig1 );
+ aSig0 |= LIT64( 0x4000000000000000 );
+ aBigger:
+ sub128( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1 );
+ zExp = aExp;
+ normalizeRoundAndPack:
+ --zExp;
+ return normalizeRoundAndPackFloat128( zSign, zExp - 14, zSig0, zSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of adding the quadruple-precision floating-point values
+`a' and `b'. The operation is performed according to the IEC/IEEE Standard
+for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float128_add( float128 a, float128 b )
+{
+ flag aSign, bSign;
+
+ aSign = extractFloat128Sign( a );
+ bSign = extractFloat128Sign( b );
+ if ( aSign == bSign ) {
+ return addFloat128Sigs( a, b, aSign );
+ }
+ else {
+ return subFloat128Sigs( a, b, aSign );
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of subtracting the quadruple-precision floating-point
+values `a' and `b'. The operation is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float128_sub( float128 a, float128 b )
+{
+ flag aSign, bSign;
+
+ aSign = extractFloat128Sign( a );
+ bSign = extractFloat128Sign( b );
+ if ( aSign == bSign ) {
+ return subFloat128Sigs( a, b, aSign );
+ }
+ else {
+ return addFloat128Sigs( a, b, aSign );
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of multiplying the quadruple-precision floating-point
+values `a' and `b'. The operation is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float128_mul( float128 a, float128 b )
+{
+ flag aSign, bSign, zSign;
+ int32 aExp, bExp, zExp;
+ bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2, zSig3;
+ float128 z;
+
+ aSig1 = extractFloat128Frac1( a );
+ aSig0 = extractFloat128Frac0( a );
+ aExp = extractFloat128Exp( a );
+ aSign = extractFloat128Sign( a );
+ bSig1 = extractFloat128Frac1( b );
+ bSig0 = extractFloat128Frac0( b );
+ bExp = extractFloat128Exp( b );
+ bSign = extractFloat128Sign( b );
+ zSign = aSign ^ bSign;
+ if ( aExp == 0x7FFF ) {
+ if ( ( aSig0 | aSig1 )
+ || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) {
+ return propagateFloat128NaN( a, b );
+ }
+ if ( ( bExp | bSig0 | bSig1 ) == 0 ) goto invalid;
+ return packFloat128( zSign, 0x7FFF, 0, 0 );
+ }
+ if ( bExp == 0x7FFF ) {
+ if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+ if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
+ invalid:
+ float_raise( float_flag_invalid );
+ z.low = float128_default_nan_low;
+ z.high = float128_default_nan_high;
+ return z;
+ }
+ return packFloat128( zSign, 0x7FFF, 0, 0 );
+ }
+ if ( aExp == 0 ) {
+ if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
+ normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+ }
+ if ( bExp == 0 ) {
+ if ( ( bSig0 | bSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
+ normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
+ }
+ zExp = aExp + bExp - 0x4000;
+ aSig0 |= LIT64( 0x0001000000000000 );
+ shortShift128Left( bSig0, bSig1, 16, &bSig0, &bSig1 );
+ mul128To256( aSig0, aSig1, bSig0, bSig1, &zSig0, &zSig1, &zSig2, &zSig3 );
+ add128( zSig0, zSig1, aSig0, aSig1, &zSig0, &zSig1 );
+ zSig2 |= ( zSig3 != 0 );
+ if ( LIT64( 0x0002000000000000 ) <= zSig0 ) {
+ shift128ExtraRightJamming(
+ zSig0, zSig1, zSig2, 1, &zSig0, &zSig1, &zSig2 );
+ ++zExp;
+ }
+ return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of dividing the quadruple-precision floating-point value
+`a' by the corresponding value `b'. The operation is performed according to
+the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float128_div( float128 a, float128 b )
+{
+ flag aSign, bSign, zSign;
+ int32 aExp, bExp, zExp;
+ bits64 aSig0, aSig1, bSig0, bSig1, zSig0, zSig1, zSig2;
+ bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
+ float128 z;
+
+ aSig1 = extractFloat128Frac1( a );
+ aSig0 = extractFloat128Frac0( a );
+ aExp = extractFloat128Exp( a );
+ aSign = extractFloat128Sign( a );
+ bSig1 = extractFloat128Frac1( b );
+ bSig0 = extractFloat128Frac0( b );
+ bExp = extractFloat128Exp( b );
+ bSign = extractFloat128Sign( b );
+ zSign = aSign ^ bSign;
+ if ( aExp == 0x7FFF ) {
+ if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, b );
+ if ( bExp == 0x7FFF ) {
+ if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+ goto invalid;
+ }
+ return packFloat128( zSign, 0x7FFF, 0, 0 );
+ }
+ if ( bExp == 0x7FFF ) {
+ if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+ return packFloat128( zSign, 0, 0, 0 );
+ }
+ if ( bExp == 0 ) {
+ if ( ( bSig0 | bSig1 ) == 0 ) {
+ if ( ( aExp | aSig0 | aSig1 ) == 0 ) {
+ invalid:
+ float_raise( float_flag_invalid );
+ z.low = float128_default_nan_low;
+ z.high = float128_default_nan_high;
+ return z;
+ }
+ float_raise( float_flag_divbyzero );
+ return packFloat128( zSign, 0x7FFF, 0, 0 );
+ }
+ normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
+ }
+ if ( aExp == 0 ) {
+ if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( zSign, 0, 0, 0 );
+ normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+ }
+ zExp = aExp - bExp + 0x3FFD;
+ shortShift128Left(
+ aSig0 | LIT64( 0x0001000000000000 ), aSig1, 15, &aSig0, &aSig1 );
+ shortShift128Left(
+ bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 );
+ if ( le128( bSig0, bSig1, aSig0, aSig1 ) ) {
+ shift128Right( aSig0, aSig1, 1, &aSig0, &aSig1 );
+ ++zExp;
+ }
+ zSig0 = estimateDiv128To64( aSig0, aSig1, bSig0 );
+ mul128By64To192( bSig0, bSig1, zSig0, &term0, &term1, &term2 );
+ sub192( aSig0, aSig1, 0, term0, term1, term2, &rem0, &rem1, &rem2 );
+ while ( (sbits64) rem0 < 0 ) {
+ --zSig0;
+ add192( rem0, rem1, rem2, 0, bSig0, bSig1, &rem0, &rem1, &rem2 );
+ }
+ zSig1 = estimateDiv128To64( rem1, rem2, bSig0 );
+ if ( ( zSig1 & 0x3FFF ) <= 4 ) {
+ mul128By64To192( bSig0, bSig1, zSig1, &term1, &term2, &term3 );
+ sub192( rem1, rem2, 0, term1, term2, term3, &rem1, &rem2, &rem3 );
+ while ( (sbits64) rem1 < 0 ) {
+ --zSig1;
+ add192( rem1, rem2, rem3, 0, bSig0, bSig1, &rem1, &rem2, &rem3 );
+ }
+ zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
+ }
+ shift128ExtraRightJamming( zSig0, zSig1, 0, 15, &zSig0, &zSig1, &zSig2 );
+ return roundAndPackFloat128( zSign, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the remainder of the quadruple-precision floating-point value `a'
+with respect to the corresponding value `b'. The operation is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float128_rem( float128 a, float128 b )
+{
+ flag aSign, bSign, zSign;
+ int32 aExp, bExp, expDiff;
+ bits64 aSig0, aSig1, bSig0, bSig1, q, term0, term1, term2;
+ bits64 allZero, alternateASig0, alternateASig1, sigMean1;
+ sbits64 sigMean0;
+ float128 z;
+
+ aSig1 = extractFloat128Frac1( a );
+ aSig0 = extractFloat128Frac0( a );
+ aExp = extractFloat128Exp( a );
+ aSign = extractFloat128Sign( a );
+ bSig1 = extractFloat128Frac1( b );
+ bSig0 = extractFloat128Frac0( b );
+ bExp = extractFloat128Exp( b );
+ bSign = extractFloat128Sign( b );
+ if ( aExp == 0x7FFF ) {
+ if ( ( aSig0 | aSig1 )
+ || ( ( bExp == 0x7FFF ) && ( bSig0 | bSig1 ) ) ) {
+ return propagateFloat128NaN( a, b );
+ }
+ goto invalid;
+ }
+ if ( bExp == 0x7FFF ) {
+ if ( bSig0 | bSig1 ) return propagateFloat128NaN( a, b );
+ return a;
+ }
+ if ( bExp == 0 ) {
+ if ( ( bSig0 | bSig1 ) == 0 ) {
+ invalid:
+ float_raise( float_flag_invalid );
+ z.low = float128_default_nan_low;
+ z.high = float128_default_nan_high;
+ return z;
+ }
+ normalizeFloat128Subnormal( bSig0, bSig1, &bExp, &bSig0, &bSig1 );
+ }
+ if ( aExp == 0 ) {
+ if ( ( aSig0 | aSig1 ) == 0 ) return a;
+ normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+ }
+ expDiff = aExp - bExp;
+ if ( expDiff < -1 ) return a;
+ shortShift128Left(
+ aSig0 | LIT64( 0x0001000000000000 ),
+ aSig1,
+ 15 - ( expDiff < 0 ),
+ &aSig0,
+ &aSig1
+ );
+ shortShift128Left(
+ bSig0 | LIT64( 0x0001000000000000 ), bSig1, 15, &bSig0, &bSig1 );
+ q = le128( bSig0, bSig1, aSig0, aSig1 );
+ if ( q ) sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
+ expDiff -= 64;
+ while ( 0 < expDiff ) {
+ q = estimateDiv128To64( aSig0, aSig1, bSig0 );
+ q = ( 4 < q ) ? q - 4 : 0;
+ mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 );
+ shortShift192Left( term0, term1, term2, 61, &term1, &term2, &allZero );
+ shortShift128Left( aSig0, aSig1, 61, &aSig0, &allZero );
+ sub128( aSig0, 0, term1, term2, &aSig0, &aSig1 );
+ expDiff -= 61;
+ }
+ if ( -64 < expDiff ) {
+ q = estimateDiv128To64( aSig0, aSig1, bSig0 );
+ q = ( 4 < q ) ? q - 4 : 0;
+ q >>= - expDiff;
+ shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 );
+ expDiff += 52;
+ if ( expDiff < 0 ) {
+ shift128Right( aSig0, aSig1, - expDiff, &aSig0, &aSig1 );
+ }
+ else {
+ shortShift128Left( aSig0, aSig1, expDiff, &aSig0, &aSig1 );
+ }
+ mul128By64To192( bSig0, bSig1, q, &term0, &term1, &term2 );
+ sub128( aSig0, aSig1, term1, term2, &aSig0, &aSig1 );
+ }
+ else {
+ shift128Right( aSig0, aSig1, 12, &aSig0, &aSig1 );
+ shift128Right( bSig0, bSig1, 12, &bSig0, &bSig1 );
+ }
+ do {
+ alternateASig0 = aSig0;
+ alternateASig1 = aSig1;
+ ++q;
+ sub128( aSig0, aSig1, bSig0, bSig1, &aSig0, &aSig1 );
+ } while ( 0 <= (sbits64) aSig0 );
+ add128(
+ aSig0, aSig1, alternateASig0, alternateASig1, (bits64 *)&sigMean0, &sigMean1 );
+ if ( ( sigMean0 < 0 )
+ || ( ( ( sigMean0 | sigMean1 ) == 0 ) && ( q & 1 ) ) ) {
+ aSig0 = alternateASig0;
+ aSig1 = alternateASig1;
+ }
+ zSign = ( (sbits64) aSig0 < 0 );
+ if ( zSign ) sub128( 0, 0, aSig0, aSig1, &aSig0, &aSig1 );
+ return
+ normalizeRoundAndPackFloat128( aSign ^ zSign, bExp - 4, aSig0, aSig1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the square root of the quadruple-precision floating-point value `a'.
+The operation is performed according to the IEC/IEEE Standard for Binary
+Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+float128 float128_sqrt( float128 a )
+{
+ flag aSign;
+ int32 aExp, zExp;
+ bits64 aSig0, aSig1, zSig0, zSig1, zSig2, doubleZSig0;
+ bits64 rem0, rem1, rem2, rem3, term0, term1, term2, term3;
+ float128 z;
+
+ aSig1 = extractFloat128Frac1( a );
+ aSig0 = extractFloat128Frac0( a );
+ aExp = extractFloat128Exp( a );
+ aSign = extractFloat128Sign( a );
+ if ( aExp == 0x7FFF ) {
+ if ( aSig0 | aSig1 ) return propagateFloat128NaN( a, a );
+ if ( ! aSign ) return a;
+ goto invalid;
+ }
+ if ( aSign ) {
+ if ( ( aExp | aSig0 | aSig1 ) == 0 ) return a;
+ invalid:
+ float_raise( float_flag_invalid );
+ z.low = float128_default_nan_low;
+ z.high = float128_default_nan_high;
+ return z;
+ }
+ if ( aExp == 0 ) {
+ if ( ( aSig0 | aSig1 ) == 0 ) return packFloat128( 0, 0, 0, 0 );
+ normalizeFloat128Subnormal( aSig0, aSig1, &aExp, &aSig0, &aSig1 );
+ }
+ zExp = ( ( aExp - 0x3FFF )>>1 ) + 0x3FFE;
+ aSig0 |= LIT64( 0x0001000000000000 );
+ zSig0 = estimateSqrt32( aExp, aSig0>>17 );
+ shortShift128Left( aSig0, aSig1, 13 - ( aExp & 1 ), &aSig0, &aSig1 );
+ zSig0 = estimateDiv128To64( aSig0, aSig1, zSig0<<32 ) + ( zSig0<<30 );
+ doubleZSig0 = zSig0<<1;
+ mul64To128( zSig0, zSig0, &term0, &term1 );
+ sub128( aSig0, aSig1, term0, term1, &rem0, &rem1 );
+ while ( (sbits64) rem0 < 0 ) {
+ --zSig0;
+ doubleZSig0 -= 2;
+ add128( rem0, rem1, zSig0>>63, doubleZSig0 | 1, &rem0, &rem1 );
+ }
+ zSig1 = estimateDiv128To64( rem1, 0, doubleZSig0 );
+ if ( ( zSig1 & 0x1FFF ) <= 5 ) {
+ if ( zSig1 == 0 ) zSig1 = 1;
+ mul64To128( doubleZSig0, zSig1, &term1, &term2 );
+ sub128( rem1, 0, term1, term2, &rem1, &rem2 );
+ mul64To128( zSig1, zSig1, &term2, &term3 );
+ sub192( rem1, rem2, 0, 0, term2, term3, &rem1, &rem2, &rem3 );
+ while ( (sbits64) rem1 < 0 ) {
+ --zSig1;
+ shortShift128Left( 0, zSig1, 1, &term2, &term3 );
+ term3 |= 1;
+ term2 |= doubleZSig0;
+ add192( rem1, rem2, rem3, 0, term2, term3, &rem1, &rem2, &rem3 );
+ }
+ zSig1 |= ( ( rem1 | rem2 | rem3 ) != 0 );
+ }
+ shift128ExtraRightJamming( zSig0, zSig1, 0, 14, &zSig0, &zSig1, &zSig2 );
+ return roundAndPackFloat128( 0, zExp, zSig0, zSig1, zSig2 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is equal to
+the corresponding value `b', and 0 otherwise. The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float128_eq( float128 a, float128 b )
+{
+
+ if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
+ && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+ || ( ( extractFloat128Exp( b ) == 0x7FFF )
+ && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+ ) {
+ if ( float128_is_signaling_nan( a )
+ || float128_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ return
+ ( a.low == b.low )
+ && ( ( a.high == b.high )
+ || ( ( a.low == 0 )
+ && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) )
+ );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is less than
+or equal to the corresponding value `b', and 0 otherwise. The comparison
+is performed according to the IEC/IEEE Standard for Binary Floating-Point
+Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float128_le( float128 a, float128 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
+ && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+ || ( ( extractFloat128Exp( b ) == 0x7FFF )
+ && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ aSign = extractFloat128Sign( a );
+ bSign = extractFloat128Sign( b );
+ if ( aSign != bSign ) {
+ return
+ aSign
+ || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+ == 0 );
+ }
+ return
+ aSign ? le128( b.high, b.low, a.high, a.low )
+ : le128( a.high, a.low, b.high, b.low );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise. The comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float128_lt( float128 a, float128 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
+ && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+ || ( ( extractFloat128Exp( b ) == 0x7FFF )
+ && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ aSign = extractFloat128Sign( a );
+ bSign = extractFloat128Sign( b );
+ if ( aSign != bSign ) {
+ return
+ aSign
+ && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+ != 0 );
+ }
+ return
+ aSign ? lt128( b.high, b.low, a.high, a.low )
+ : lt128( a.high, a.low, b.high, b.low );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is equal to
+the corresponding value `b', and 0 otherwise. The invalid exception is
+raised if either operand is a NaN. Otherwise, the comparison is performed
+according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float128_eq_signaling( float128 a, float128 b )
+{
+
+ if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
+ && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+ || ( ( extractFloat128Exp( b ) == 0x7FFF )
+ && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+ ) {
+ float_raise( float_flag_invalid );
+ return 0;
+ }
+ return
+ ( a.low == b.low )
+ && ( ( a.high == b.high )
+ || ( ( a.low == 0 )
+ && ( (bits64) ( ( a.high | b.high )<<1 ) == 0 ) )
+ );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is less than
+or equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
+cause an exception. Otherwise, the comparison is performed according to the
+IEC/IEEE Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float128_le_quiet( float128 a, float128 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
+ && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+ || ( ( extractFloat128Exp( b ) == 0x7FFF )
+ && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+ ) {
+ if ( float128_is_signaling_nan( a )
+ || float128_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ aSign = extractFloat128Sign( a );
+ bSign = extractFloat128Sign( b );
+ if ( aSign != bSign ) {
+ return
+ aSign
+ || ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+ == 0 );
+ }
+ return
+ aSign ? le128( b.high, b.low, a.high, a.low )
+ : le128( a.high, a.low, b.high, b.low );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is less than
+the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
+exception. Otherwise, the comparison is performed according to the IEC/IEEE
+Standard for Binary Floating-Point Arithmetic.
+-------------------------------------------------------------------------------
+*/
+flag float128_lt_quiet( float128 a, float128 b )
+{
+ flag aSign, bSign;
+
+ if ( ( ( extractFloat128Exp( a ) == 0x7FFF )
+ && ( extractFloat128Frac0( a ) | extractFloat128Frac1( a ) ) )
+ || ( ( extractFloat128Exp( b ) == 0x7FFF )
+ && ( extractFloat128Frac0( b ) | extractFloat128Frac1( b ) ) )
+ ) {
+ if ( float128_is_signaling_nan( a )
+ || float128_is_signaling_nan( b ) ) {
+ float_raise( float_flag_invalid );
+ }
+ return 0;
+ }
+ aSign = extractFloat128Sign( a );
+ bSign = extractFloat128Sign( b );
+ if ( aSign != bSign ) {
+ return
+ aSign
+ && ( ( ( (bits64) ( ( a.high | b.high )<<1 ) ) | a.low | b.low )
+ != 0 );
+ }
+ return
+ aSign ? lt128( b.high, b.low, a.high, a.low )
+ : lt128( a.high, a.low, b.high, b.low );
+
+}
+
+#endif
+
+
+#if defined(SOFTFLOAT_FOR_GCC) && defined(SOFTFLOAT_NEED_FIXUNS)
+
+/*
+ * These two routines are not part of the original softfloat distribution.
+ *
+ * They are based on the corresponding conversions to integer but return
+ * unsigned numbers instead since these functions are required by GCC.
+ *
+ * Added by Mark Brinicombe <mark@NetBSD.org> 27/09/97
+ *
+ * float64 version overhauled for SoftFloat 2a [bjh21 2000-07-15]
+ */
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point value
+`a' to the 32-bit unsigned integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-point
+Arithmetic, except that the conversion is always rounded toward zero. If
+`a' is a NaN, the largest positive integer is returned. If the conversion
+overflows, the largest integer positive is returned.
+-------------------------------------------------------------------------------
+*/
+uint32 float64_to_uint32_round_to_zero( float64 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits64 aSig, savedASig;
+ uint32 z;
+
+ aSig = extractFloat64Frac( a );
+ aExp = extractFloat64Exp( a );
+ aSign = extractFloat64Sign( a );
+
+ if (aSign) {
+ float_raise( float_flag_invalid );
+ return(0);
+ }
+
+ if ( 0x41E < aExp ) {
+ float_raise( float_flag_invalid );
+ return 0xffffffff;
+ }
+ else if ( aExp < 0x3FF ) {
+ if ( aExp || aSig ) float_exception_flags |= float_flag_inexact;
+ return 0;
+ }
+ aSig |= LIT64( 0x0010000000000000 );
+ shiftCount = 0x433 - aExp;
+ savedASig = aSig;
+ aSig >>= shiftCount;
+ z = aSig;
+ if ( ( aSig<<shiftCount ) != savedASig ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point value
+`a' to the 32-bit unsigned integer format. The conversion is
+performed according to the IEC/IEEE Standard for Binary Floating-point
+Arithmetic, except that the conversion is always rounded toward zero. If
+`a' is a NaN, the largest positive integer is returned. If the conversion
+overflows, the largest positive integer is returned.
+-------------------------------------------------------------------------------
+*/
+uint32 float32_to_uint32_round_to_zero( float32 a )
+{
+ flag aSign;
+ int16 aExp, shiftCount;
+ bits32 aSig;
+ uint32 z;
+
+ aSig = extractFloat32Frac( a );
+ aExp = extractFloat32Exp( a );
+ aSign = extractFloat32Sign( a );
+ shiftCount = aExp - 0x9E;
+
+ if (aSign) {
+ float_raise( float_flag_invalid );
+ return(0);
+ }
+ if ( 0 < shiftCount ) {
+ float_raise( float_flag_invalid );
+ return 0xFFFFFFFF;
+ }
+ else if ( aExp <= 0x7E ) {
+ if ( aExp | aSig ) float_exception_flags |= float_flag_inexact;
+ return 0;
+ }
+ aSig = ( aSig | 0x800000 )<<8;
+ z = aSig>>( - shiftCount );
+ if ( aSig<<( shiftCount & 31 ) ) {
+ float_exception_flags |= float_flag_inexact;
+ }
+ return z;
+
+}
+
+#endif
diff --git a/lib/libc/softfloat/eqdf2.c b/lib/libc/softfloat/eqdf2.c
new file mode 100644
index 0000000..68bb55c
--- /dev/null
+++ b/lib/libc/softfloat/eqdf2.c
@@ -0,0 +1,22 @@
+/* $NetBSD: eqdf2.c,v 1.1 2000/06/06 08:15:02 bjh21 Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+flag __eqdf2(float64, float64);
+
+flag
+__eqdf2(float64 a, float64 b)
+{
+
+ /* libgcc1.c says !(a == b) */
+ return !float64_eq(a, b);
+}
diff --git a/lib/libc/softfloat/eqsf2.c b/lib/libc/softfloat/eqsf2.c
new file mode 100644
index 0000000..d45b806
--- /dev/null
+++ b/lib/libc/softfloat/eqsf2.c
@@ -0,0 +1,22 @@
+/* $NetBSD: eqsf2.c,v 1.1 2000/06/06 08:15:03 bjh21 Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+flag __eqsf2(float32, float32);
+
+flag
+__eqsf2(float32 a, float32 b)
+{
+
+ /* libgcc1.c says !(a == b) */
+ return !float32_eq(a, b);
+}
diff --git a/lib/libc/softfloat/eqtf2.c b/lib/libc/softfloat/eqtf2.c
new file mode 100644
index 0000000..1839404
--- /dev/null
+++ b/lib/libc/softfloat/eqtf2.c
@@ -0,0 +1,24 @@
+/* $NetBSD: eqtf2.c,v 1.1 2011/01/17 10:08:35 matt Exp $ */
+
+/*
+ * Written by Matt Thomas, 2011. This file is in the Public Domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#ifdef FLOAT128
+flag __eqtf2(float128, float128);
+
+flag
+__eqtf2(float128 a, float128 b)
+{
+
+ /* libgcc1.c says !(a == b) */
+ return !float128_eq(a, b);
+}
+#endif /* FLOAT128 */
diff --git a/lib/libc/softfloat/fpgetmask.c b/lib/libc/softfloat/fpgetmask.c
new file mode 100644
index 0000000..20c6928
--- /dev/null
+++ b/lib/libc/softfloat/fpgetmask.c
@@ -0,0 +1,53 @@
+/* $NetBSD: fpgetmask.c,v 1.4 2008/04/28 20:23:00 martin Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+
+#include <ieeefp.h>
+#ifdef SOFTFLOAT_FOR_GCC
+#include "softfloat-for-gcc.h"
+#endif
+#include "milieu.h"
+#include "softfloat.h"
+
+#ifdef __weak_alias
+__weak_alias(fpgetmask,_fpgetmask)
+#endif
+
+fp_except
+fpgetmask(void)
+{
+
+ return float_exception_mask;
+}
diff --git a/lib/libc/softfloat/fpgetround.c b/lib/libc/softfloat/fpgetround.c
new file mode 100644
index 0000000..6ff1ffd
--- /dev/null
+++ b/lib/libc/softfloat/fpgetround.c
@@ -0,0 +1,53 @@
+/* $NetBSD: fpgetround.c,v 1.3 2008/04/28 20:23:00 martin Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+
+#include <ieeefp.h>
+#ifdef SOFTFLOAT_FOR_GCC
+#include "softfloat-for-gcc.h"
+#endif
+#include "milieu.h"
+#include "softfloat.h"
+
+#ifdef __weak_alias
+__weak_alias(fpgetround,_fpgetround)
+#endif
+
+fp_rnd_t
+fpgetround(void)
+{
+
+ return float_rounding_mode;
+}
diff --git a/lib/libc/softfloat/fpgetsticky.c b/lib/libc/softfloat/fpgetsticky.c
new file mode 100644
index 0000000..f7ef466
--- /dev/null
+++ b/lib/libc/softfloat/fpgetsticky.c
@@ -0,0 +1,53 @@
+/* $NetBSD: fpgetsticky.c,v 1.3 2008/04/28 20:23:00 martin Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+
+#include <ieeefp.h>
+#ifdef SOFTFLOAT_FOR_GCC
+#include "softfloat-for-gcc.h"
+#endif
+#include "milieu.h"
+#include "softfloat.h"
+
+#ifdef __weak_alias
+__weak_alias(fpgetsticky,_fpgetsticky)
+#endif
+
+fp_except
+fpgetsticky(void)
+{
+
+ return float_exception_flags;
+}
diff --git a/lib/libc/softfloat/fpsetmask.c b/lib/libc/softfloat/fpsetmask.c
new file mode 100644
index 0000000..47dcc95
--- /dev/null
+++ b/lib/libc/softfloat/fpsetmask.c
@@ -0,0 +1,56 @@
+/* $NetBSD: fpsetmask.c,v 1.4 2008/04/28 20:23:00 martin Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+
+#include <ieeefp.h>
+#ifdef SOFTFLOAT_FOR_GCC
+#include "softfloat-for-gcc.h"
+#endif
+#include "milieu.h"
+#include "softfloat.h"
+
+#ifdef __weak_alias
+__weak_alias(fpsetmask,_fpsetmask)
+#endif
+
+fp_except
+fpsetmask(fp_except mask)
+{
+ fp_except old;
+
+ old = float_exception_mask;
+ float_exception_mask = mask;
+ return old;
+}
diff --git a/lib/libc/softfloat/fpsetround.c b/lib/libc/softfloat/fpsetround.c
new file mode 100644
index 0000000..ecdb6ad
--- /dev/null
+++ b/lib/libc/softfloat/fpsetround.c
@@ -0,0 +1,56 @@
+/* $NetBSD: fpsetround.c,v 1.3 2008/04/28 20:23:00 martin Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+
+#include <ieeefp.h>
+#ifdef SOFTFLOAT_FOR_GCC
+#include "softfloat-for-gcc.h"
+#endif
+#include "milieu.h"
+#include "softfloat.h"
+
+#ifdef __weak_alias
+__weak_alias(fpsetround,_fpsetround)
+#endif
+
+fp_rnd_t
+fpsetround(fp_rnd_t rnd_dir)
+{
+ fp_rnd_t old;
+
+ old = float_rounding_mode;
+ float_rounding_mode = rnd_dir;
+ return old;
+}
diff --git a/lib/libc/softfloat/fpsetsticky.c b/lib/libc/softfloat/fpsetsticky.c
new file mode 100644
index 0000000..526b19f
--- /dev/null
+++ b/lib/libc/softfloat/fpsetsticky.c
@@ -0,0 +1,56 @@
+/* $NetBSD: fpsetsticky.c,v 1.3 2008/04/28 20:23:00 martin Exp $ */
+
+/*-
+ * Copyright (c) 1997 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Neil A. Carson and Mark Brinicombe
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+
+#include <ieeefp.h>
+#ifdef SOFTFLOAT_FOR_GCC
+#include "softfloat-for-gcc.h"
+#endif
+#include "milieu.h"
+#include "softfloat.h"
+
+#ifdef __weak_alias
+__weak_alias(fpsetsticky,_fpsetsticky)
+#endif
+
+fp_except
+fpsetsticky(fp_except except)
+{
+ fp_except old;
+
+ old = float_exception_flags;
+ float_exception_flags = except;
+ return old;
+}
diff --git a/lib/libc/softfloat/gedf2.c b/lib/libc/softfloat/gedf2.c
new file mode 100644
index 0000000..76e25de
--- /dev/null
+++ b/lib/libc/softfloat/gedf2.c
@@ -0,0 +1,22 @@
+/* $NetBSD: gedf2.c,v 1.1 2000/06/06 08:15:05 bjh21 Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+flag __gedf2(float64, float64);
+
+flag
+__gedf2(float64 a, float64 b)
+{
+
+ /* libgcc1.c says (a >= b) - 1 */
+ return float64_le(b, a) - 1;
+}
diff --git a/lib/libc/softfloat/gesf2.c b/lib/libc/softfloat/gesf2.c
new file mode 100644
index 0000000..b22e13a
--- /dev/null
+++ b/lib/libc/softfloat/gesf2.c
@@ -0,0 +1,22 @@
+/* $NetBSD: gesf2.c,v 1.1 2000/06/06 08:15:05 bjh21 Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+flag __gesf2(float32, float32);
+
+flag
+__gesf2(float32 a, float32 b)
+{
+
+ /* libgcc1.c says (a >= b) - 1 */
+ return float32_le(b, a) - 1;
+}
diff --git a/lib/libc/softfloat/getf2.c b/lib/libc/softfloat/getf2.c
new file mode 100644
index 0000000..8639c4d
--- /dev/null
+++ b/lib/libc/softfloat/getf2.c
@@ -0,0 +1,26 @@
+/* $NetBSD: getf2.c,v 1.1 2011/01/17 10:08:35 matt Exp $ */
+
+/*
+ * Written by Matt Thomas, 2011. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef FLOAT128
+
+flag __getf2(float128, float128);
+
+flag
+__getf2(float128 a, float128 b)
+{
+
+ /* libgcc1.c says (a >= b) - 1 */
+ return float128_le(b, a) - 1;
+}
+
+#endif /* FLOAT128 */
diff --git a/lib/libc/softfloat/gexf2.c b/lib/libc/softfloat/gexf2.c
new file mode 100644
index 0000000..70cf1c3
--- /dev/null
+++ b/lib/libc/softfloat/gexf2.c
@@ -0,0 +1,25 @@
+/* $NetBSD: gexf2.c,v 1.2 2004/09/27 10:16:24 he Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef FLOATX80
+
+flag __gexf2(floatx80, floatx80);
+
+flag
+__gexf2(floatx80 a, floatx80 b)
+{
+
+ /* libgcc1.c says (a >= b) - 1 */
+ return floatx80_le(b, a) - 1;
+}
+#endif /* FLOATX80 */
diff --git a/lib/libc/softfloat/gtdf2.c b/lib/libc/softfloat/gtdf2.c
new file mode 100644
index 0000000..ff5764a
--- /dev/null
+++ b/lib/libc/softfloat/gtdf2.c
@@ -0,0 +1,22 @@
+/* $NetBSD: gtdf2.c,v 1.1 2000/06/06 08:15:05 bjh21 Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+flag __gtdf2(float64, float64);
+
+flag
+__gtdf2(float64 a, float64 b)
+{
+
+ /* libgcc1.c says a > b */
+ return float64_lt(b, a);
+}
diff --git a/lib/libc/softfloat/gtsf2.c b/lib/libc/softfloat/gtsf2.c
new file mode 100644
index 0000000..8e7e7a9
--- /dev/null
+++ b/lib/libc/softfloat/gtsf2.c
@@ -0,0 +1,22 @@
+/* $NetBSD: gtsf2.c,v 1.1 2000/06/06 08:15:06 bjh21 Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+flag __gtsf2(float32, float32);
+
+flag
+__gtsf2(float32 a, float32 b)
+{
+
+ /* libgcc1.c says a > b */
+ return float32_lt(b, a);
+}
diff --git a/lib/libc/softfloat/gttf2.c b/lib/libc/softfloat/gttf2.c
new file mode 100644
index 0000000..519ea84
--- /dev/null
+++ b/lib/libc/softfloat/gttf2.c
@@ -0,0 +1,26 @@
+/* $NetBSD: gttf2.c,v 1.1 2011/01/17 10:08:35 matt Exp $ */
+
+/*
+ * Written by Matt Thomas, 2011. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef FLOAT128
+
+flag __gttf2(float128, float128);
+
+flag
+__gttf2(float128 a, float128 b)
+{
+
+ /* libgcc1.c says a > b */
+ return float128_lt(b, a);
+}
+
+#endif /* FLOAT128 */
diff --git a/lib/libc/softfloat/gtxf2.c b/lib/libc/softfloat/gtxf2.c
new file mode 100644
index 0000000..fe8be52
--- /dev/null
+++ b/lib/libc/softfloat/gtxf2.c
@@ -0,0 +1,25 @@
+/* $NetBSD: gtxf2.c,v 1.2 2004/09/27 10:16:24 he Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef FLOATX80
+
+flag __gtxf2(floatx80, floatx80);
+
+flag
+__gtxf2(floatx80 a, floatx80 b)
+{
+
+ /* libgcc1.c says a > b */
+ return floatx80_lt(b, a);
+}
+#endif /* FLOATX80 */
diff --git a/lib/libc/softfloat/ledf2.c b/lib/libc/softfloat/ledf2.c
new file mode 100644
index 0000000..7d3e8fb
--- /dev/null
+++ b/lib/libc/softfloat/ledf2.c
@@ -0,0 +1,22 @@
+/* $NetBSD: ledf2.c,v 1.1 2000/06/06 08:15:06 bjh21 Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+flag __ledf2(float64, float64);
+
+flag
+__ledf2(float64 a, float64 b)
+{
+
+ /* libgcc1.c says 1 - (a <= b) */
+ return 1 - float64_le(a, b);
+}
diff --git a/lib/libc/softfloat/lesf2.c b/lib/libc/softfloat/lesf2.c
new file mode 100644
index 0000000..6fa13e5
--- /dev/null
+++ b/lib/libc/softfloat/lesf2.c
@@ -0,0 +1,22 @@
+/* $NetBSD: lesf2.c,v 1.1 2000/06/06 08:15:06 bjh21 Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+flag __lesf2(float32, float32);
+
+flag
+__lesf2(float32 a, float32 b)
+{
+
+ /* libgcc1.c says 1 - (a <= b) */
+ return 1 - float32_le(a, b);
+}
diff --git a/lib/libc/softfloat/letf2.c b/lib/libc/softfloat/letf2.c
new file mode 100644
index 0000000..e9a18f8
--- /dev/null
+++ b/lib/libc/softfloat/letf2.c
@@ -0,0 +1,26 @@
+/* $NetBSD: letf2.c,v 1.1 2011/01/17 10:08:35 matt Exp $ */
+
+/*
+ * Written by Matt Thomas, 2011. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef FLOAT128
+
+flag __letf2(float128, float128);
+
+flag
+__letf2(float128 a, float128 b)
+{
+
+ /* libgcc1.c says 1 - (a <= b) */
+ return 1 - float128_le(a, b);
+}
+
+#endif /* FLOAT128 */
diff --git a/lib/libc/softfloat/ltdf2.c b/lib/libc/softfloat/ltdf2.c
new file mode 100644
index 0000000..b8c668c
--- /dev/null
+++ b/lib/libc/softfloat/ltdf2.c
@@ -0,0 +1,22 @@
+/* $NetBSD: ltdf2.c,v 1.1 2000/06/06 08:15:06 bjh21 Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+flag __ltdf2(float64, float64);
+
+flag
+__ltdf2(float64 a, float64 b)
+{
+
+ /* libgcc1.c says -(a < b) */
+ return -float64_lt(a, b);
+}
diff --git a/lib/libc/softfloat/ltsf2.c b/lib/libc/softfloat/ltsf2.c
new file mode 100644
index 0000000..8a1e8fa9
--- /dev/null
+++ b/lib/libc/softfloat/ltsf2.c
@@ -0,0 +1,22 @@
+/* $NetBSD: ltsf2.c,v 1.1 2000/06/06 08:15:06 bjh21 Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+flag __ltsf2(float32, float32);
+
+flag
+__ltsf2(float32 a, float32 b)
+{
+
+ /* libgcc1.c says -(a < b) */
+ return -float32_lt(a, b);
+}
diff --git a/lib/libc/softfloat/lttf2.c b/lib/libc/softfloat/lttf2.c
new file mode 100644
index 0000000..13c01b1
--- /dev/null
+++ b/lib/libc/softfloat/lttf2.c
@@ -0,0 +1,26 @@
+/* $NetBSD: lttf2.c,v 1.1 2011/01/17 10:08:35 matt Exp $ */
+
+/*
+ * Written by Matt Thomas, 2011. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef FLOAT128
+
+flag __lttf2(float128, float128);
+
+flag
+__lttf2(float128 a, float128 b)
+{
+
+ /* libgcc1.c says -(a < b) */
+ return -float128_lt(a, b);
+}
+
+#endif /* FLOAT128 */
diff --git a/lib/libc/softfloat/nedf2.c b/lib/libc/softfloat/nedf2.c
new file mode 100644
index 0000000..61f5044
--- /dev/null
+++ b/lib/libc/softfloat/nedf2.c
@@ -0,0 +1,22 @@
+/* $NetBSD: nedf2.c,v 1.1 2000/06/06 08:15:07 bjh21 Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+flag __nedf2(float64, float64);
+
+flag
+__nedf2(float64 a, float64 b)
+{
+
+ /* libgcc1.c says a != b */
+ return !float64_eq(a, b);
+}
diff --git a/lib/libc/softfloat/negdf2.c b/lib/libc/softfloat/negdf2.c
new file mode 100644
index 0000000..2485d58
--- /dev/null
+++ b/lib/libc/softfloat/negdf2.c
@@ -0,0 +1,22 @@
+/* $NetBSD: negdf2.c,v 1.1 2000/06/06 08:15:07 bjh21 Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+float64 __negdf2(float64);
+
+float64
+__negdf2(float64 a)
+{
+
+ /* libgcc1.c says -a */
+ return a ^ FLOAT64_MANGLE(0x8000000000000000ULL);
+}
diff --git a/lib/libc/softfloat/negsf2.c b/lib/libc/softfloat/negsf2.c
new file mode 100644
index 0000000..78f6c6b
--- /dev/null
+++ b/lib/libc/softfloat/negsf2.c
@@ -0,0 +1,22 @@
+/* $NetBSD: negsf2.c,v 1.1 2000/06/06 08:15:07 bjh21 Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+float32 __negsf2(float32);
+
+float32
+__negsf2(float32 a)
+{
+
+ /* libgcc1.c says INTIFY(-a) */
+ return a ^ 0x80000000;
+}
diff --git a/lib/libc/softfloat/negtf2.c b/lib/libc/softfloat/negtf2.c
new file mode 100644
index 0000000..5be582d
--- /dev/null
+++ b/lib/libc/softfloat/negtf2.c
@@ -0,0 +1,27 @@
+/* $NetBSD: negtf2.c,v 1.1 2011/01/17 10:08:35 matt Exp $ */
+
+/*
+ * Written by Matt Thomas, 2011. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef FLOAT128
+
+float128 __negtf2(float128);
+
+float128
+__negtf2(float128 a)
+{
+
+ /* libgcc1.c says -a */
+ a.high ^= FLOAT64_MANGLE(0x8000000000000000ULL);
+ return a;
+}
+
+#endif /* FLOAT128 */
diff --git a/lib/libc/softfloat/negxf2.c b/lib/libc/softfloat/negxf2.c
new file mode 100644
index 0000000..0e2d08b
--- /dev/null
+++ b/lib/libc/softfloat/negxf2.c
@@ -0,0 +1,25 @@
+/* $NetBSD: negxf2.c,v 1.2 2004/09/27 10:16:24 he Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef FLOATX80
+
+floatx80 __negxf2(floatx80);
+
+floatx80
+__negxf2(floatx80 a)
+{
+
+ /* libgcc1.c says -a */
+ return __mulxf3(a,__floatsixf(-1));
+}
+#endif /* FLOATX80 */
diff --git a/lib/libc/softfloat/nesf2.c b/lib/libc/softfloat/nesf2.c
new file mode 100644
index 0000000..b8317cb
--- /dev/null
+++ b/lib/libc/softfloat/nesf2.c
@@ -0,0 +1,22 @@
+/* $NetBSD: nesf2.c,v 1.1 2000/06/06 08:15:07 bjh21 Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+flag __nesf2(float32, float32);
+
+flag
+__nesf2(float32 a, float32 b)
+{
+
+ /* libgcc1.c says a != b */
+ return !float32_eq(a, b);
+}
diff --git a/lib/libc/softfloat/netf2.c b/lib/libc/softfloat/netf2.c
new file mode 100644
index 0000000..26e17cd
--- /dev/null
+++ b/lib/libc/softfloat/netf2.c
@@ -0,0 +1,26 @@
+/* $NetBSD: netf2.c,v 1.1 2011/01/17 10:08:35 matt Exp $ */
+
+/*
+ * Written by Matt Thomas, 2011. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef FLOAT128
+
+flag __netf2(float128, float128);
+
+flag
+__netf2(float128 a, float128 b)
+{
+
+ /* libgcc1.c says a != b */
+ return !float128_eq(a, b);
+}
+
+#endif /* FLOAT128 */
diff --git a/lib/libc/softfloat/nexf2.c b/lib/libc/softfloat/nexf2.c
new file mode 100644
index 0000000..153a703
--- /dev/null
+++ b/lib/libc/softfloat/nexf2.c
@@ -0,0 +1,25 @@
+/* $NetBSD: nexf2.c,v 1.2 2004/09/27 10:16:24 he Exp $ */
+
+/*
+ * Written by Ben Harris, 2000. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#ifdef FLOATX80
+
+flag __nexf2(floatx80, floatx80);
+
+flag
+__nexf2(floatx80 a, floatx80 b)
+{
+
+ /* libgcc1.c says a != b */
+ return !floatx80_eq(a, b);
+}
+#endif /* FLOATX80 */
diff --git a/lib/libc/softfloat/softfloat-for-gcc.h b/lib/libc/softfloat/softfloat-for-gcc.h
new file mode 100644
index 0000000..cf17e56
--- /dev/null
+++ b/lib/libc/softfloat/softfloat-for-gcc.h
@@ -0,0 +1,169 @@
+/* $NetBSD: softfloat-for-gcc.h,v 1.8 2009/12/14 01:07:42 matt Exp $ */
+/* $FreeBSD$ */
+
+/*
+ * Move private identifiers with external linkage into implementation
+ * namespace. -- Klaus Klein <kleink@NetBSD.org>, May 5, 1999
+ */
+#define float_exception_flags __softfloat_float_exception_flags
+#define float_exception_mask __softfloat_float_exception_mask
+#define float_rounding_mode __softfloat_float_rounding_mode
+#define float_raise __softfloat_float_raise
+/* The following batch are called by GCC through wrappers */
+#define float32_eq __softfloat_float32_eq
+#define float32_le __softfloat_float32_le
+#define float32_lt __softfloat_float32_lt
+#define float64_eq __softfloat_float64_eq
+#define float64_le __softfloat_float64_le
+#define float64_lt __softfloat_float64_lt
+#define float128_eq __softfloat_float128_eq
+#define float128_le __softfloat_float128_le
+#define float128_lt __softfloat_float128_lt
+
+/*
+ * Macros to define functions with the GCC expected names
+ */
+
+#define float32_add __addsf3
+#define float64_add __adddf3
+#define floatx80_add __addxf3
+#define float128_add __addtf3
+
+#define float32_sub __subsf3
+#define float64_sub __subdf3
+#define floatx80_sub __subxf3
+#define float128_sub __subtf3
+
+#define float32_mul __mulsf3
+#define float64_mul __muldf3
+#define floatx80_mul __mulxf3
+#define float128_mul __multf3
+
+#define float32_div __divsf3
+#define float64_div __divdf3
+#define floatx80_div __divxf3
+#define float128_div __divtf3
+
+#if 0
+#define float32_neg __negsf2
+#define float64_neg __negdf2
+#define floatx80_neg __negxf2
+#define float128_neg __negtf2
+#endif
+
+#define int32_to_float32 __floatsisf
+#define int32_to_float64 __floatsidf
+#define int32_to_floatx80 __floatsixf
+#define int32_to_float128 __floatsitf
+
+#define int64_to_float32 __floatdisf
+#define int64_to_float64 __floatdidf
+#define int64_to_floatx80 __floatdixf
+#define int64_to_float128 __floatditf
+
+#define int128_to_float32 __floattisf
+#define int128_to_float64 __floattidf
+#define int128_to_floatx80 __floattixf
+#define int128_to_float128 __floattitf
+
+#define uint32_to_float32 __floatunsisf
+#define uint32_to_float64 __floatunsidf
+#define uint32_to_floatx80 __floatunsixf
+#define uint32_to_float128 __floatunsitf
+
+#define uint64_to_float32 __floatundisf
+#define uint64_to_float64 __floatundidf
+#define uint64_to_floatx80 __floatundixf
+#define uint64_to_float128 __floatunditf
+
+#define uint128_to_float32 __floatuntisf
+#define uint128_to_float64 __floatuntidf
+#define uint128_to_floatx80 __floatuntixf
+#define uint128_to_float128 __floatuntitf
+
+#define float32_to_int32_round_to_zero __fixsfsi
+#define float64_to_int32_round_to_zero __fixdfsi
+#define floatx80_to_int32_round_to_zero __fixxfsi
+#define float128_to_int32_round_to_zero __fixtfsi
+
+#define float32_to_int64_round_to_zero __fixsfdi
+#define float64_to_int64_round_to_zero __fixdfdi
+#define floatx80_to_int64_round_to_zero __fixxfdi
+#define float128_to_int64_round_to_zero __fixtfdi
+
+#define float32_to_int128_round_to_zero __fixsfti
+#define float64_to_int128_round_to_zero __fixdfti
+#define floatx80_to_int128_round_to_zero __fixxfti
+#define float128_to_int128_round_to_zero __fixtfti
+
+#define float32_to_uint32_round_to_zero __fixunssfsi
+#define float64_to_uint32_round_to_zero __fixunsdfsi
+#define floatx80_to_uint32_round_to_zero __fixunsxfsi
+#define float128_to_uint32_round_to_zero __fixunstfsi
+
+#define float32_to_uint64_round_to_zero __fixunssfdi
+#define float64_to_uint64_round_to_zero __fixunsdfdi
+#define floatx80_to_uint64_round_to_zero __fixunsxfdi
+#define float128_to_uint64_round_to_zero __fixunstfdi
+
+#define float32_to_uint128_round_to_zero __fixunssfti
+#define float64_to_uint128_round_to_zero __fixunsdfti
+#define floatx80_to_uint128_round_to_zero __fixunsxfti
+#define float128_to_uint128_round_to_zero __fixunstfti
+
+#define float32_to_float64 __extendsfdf2
+#define float32_to_floatx80 __extendsfxf2
+#define float32_to_float128 __extendsftf2
+#define float64_to_floatx80 __extenddfxf2
+#define float64_to_float128 __extenddftf2
+
+#define float128_to_float64 __trunctfdf2
+#define floatx80_to_float64 __truncxfdf2
+#define float128_to_float32 __trunctfsf2
+#define floatx80_to_float32 __truncxfsf2
+#define float64_to_float32 __truncdfsf2
+
+#if 0
+#define float32_cmp __cmpsf2
+#define float32_unord __unordsf2
+#define float32_eq __eqsf2
+#define float32_ne __nesf2
+#define float32_ge __gesf2
+#define float32_lt __ltsf2
+#define float32_le __lesf2
+#define float32_gt __gtsf2
+#endif
+
+#if 0
+#define float64_cmp __cmpdf2
+#define float64_unord __unorddf2
+#define float64_eq __eqdf2
+#define float64_ne __nedf2
+#define float64_ge __gedf2
+#define float64_lt __ltdf2
+#define float64_le __ledf2
+#define float64_gt __gtdf2
+#endif
+
+/* XXX not in libgcc */
+#if 1
+#define floatx80_cmp __cmpxf2
+#define floatx80_unord __unordxf2
+#define floatx80_eq __eqxf2
+#define floatx80_ne __nexf2
+#define floatx80_ge __gexf2
+#define floatx80_lt __ltxf2
+#define floatx80_le __lexf2
+#define floatx80_gt __gtxf2
+#endif
+
+#if 0
+#define float128_cmp __cmptf2
+#define float128_unord __unordtf2
+#define float128_eq __eqtf2
+#define float128_ne __netf2
+#define float128_ge __getf2
+#define float128_lt __lttf2
+#define float128_le __letf2
+#define float128_gt __gttf2
+#endif
diff --git a/lib/libc/softfloat/softfloat-history.txt b/lib/libc/softfloat/softfloat-history.txt
new file mode 100644
index 0000000..d8c98db
--- /dev/null
+++ b/lib/libc/softfloat/softfloat-history.txt
@@ -0,0 +1,53 @@
+$NetBSD: softfloat-history.txt,v 1.1 2000/06/06 08:15:08 bjh21 Exp $
+$FreeBSD$
+
+History of Major Changes to SoftFloat, up to Release 2a
+
+John R. Hauser
+1998 December 16
+
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Release 2a (1998 December)
+
+-- Added functions to convert between 64-bit integers (int64) and all
+ supported floating-point formats.
+
+-- Fixed a bug in all 64-bit-version square root functions except
+ `float32_sqrt' that caused the result sometimes to be off by 1 unit in
+ the last place (1 ulp) from what it should be. (Bug discovered by Paul
+ Donahue.)
+
+-- Improved the makefiles.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Release 2 (1997 June)
+
+-- Created the 64-bit (bits64) version, adding the floatx80 and float128
+ formats.
+
+-- Changed the source directory structure, splitting the sources into a
+ `bits32' and a `bits64' version. Renamed `environment.h' to `milieu.h'
+ (to avoid confusion with environment variables).
+
+-- Fixed a small error that caused `float64_round_to_int' often to round the
+ wrong way in nearest/even mode when the operand was between 2^20 and 2^21
+ and halfway between two integers.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Release 1a (1996 July)
+
+-- Corrected a mistake that caused borderline underflow cases not to raise
+ the underflow flag when they should have. (Problem reported by Doug
+ Priest.)
+
+-- Added the `float_detect_tininess' variable to control whether tininess is
+ detected before or after rounding.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Release 1 (1996 July)
+
+-- Original release.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
diff --git a/lib/libc/softfloat/softfloat-source.txt b/lib/libc/softfloat/softfloat-source.txt
new file mode 100644
index 0000000..2a15f2a
--- /dev/null
+++ b/lib/libc/softfloat/softfloat-source.txt
@@ -0,0 +1,384 @@
+$NetBSD: softfloat-source.txt,v 1.2 2006/11/24 19:46:58 christos Exp $
+$FreeBSD$
+
+SoftFloat Release 2a Source Documentation
+
+John R. Hauser
+1998 December 14
+
+
+-------------------------------------------------------------------------------
+Introduction
+
+SoftFloat is a software implementation of floating-point that conforms to
+the IEC/IEEE Standard for Binary Floating-Point Arithmetic. SoftFloat can
+support four floating-point formats: single precision, double precision,
+extended double precision, and quadruple precision. All operations required
+by the IEEE Standard are implemented, except for conversions to and from
+decimal. SoftFloat is distributed in the form of C source code, so a
+C compiler is needed to compile the code. Support for the extended double-
+precision and quadruple-precision formats is dependent on the C compiler
+implementing a 64-bit integer type.
+
+This document gives information needed for compiling and/or porting
+SoftFloat.
+
+The source code for SoftFloat is intended to be relatively machine-
+independent and should be compilable using any ISO/ANSI C compiler. At the
+time of this writing, SoftFloat has been successfully compiled with the GNU
+C Compiler (`gcc') for several platforms.
+
+
+-------------------------------------------------------------------------------
+Limitations
+
+SoftFloat as written requires an ISO/ANSI-style C compiler. No attempt has
+been made to accommodate compilers that are not ISO-conformant. Older ``K&R-
+style'' compilers are not adequate for compiling SoftFloat. All testing I
+have done so far has been with the GNU C Compiler. Compilation with other
+compilers should be possible but has not been tested.
+
+The SoftFloat sources assume that source code file names can be longer than
+8 characters. In order to compile under an MS-DOS-type system, many of the
+source files will need to be renamed, and the source and makefiles edited
+appropriately. Once compiled, the SoftFloat binary does not depend on the
+existence of long file names.
+
+The underlying machine is assumed to be binary with a word size that is a
+power of 2. Bytes are 8 bits. Support for the extended double-precision
+and quadruple-precision formats depends on the C compiler implementing
+a 64-bit integer type. If the largest integer type supported by the
+C compiler is 32 bits, SoftFloat is limited to the single- and double-
+precision formats.
+
+
+-------------------------------------------------------------------------------
+Contents
+
+ Introduction
+ Limitations
+ Contents
+ Legal Notice
+ SoftFloat Source Directory Structure
+ SoftFloat Source Files
+ processors/*.h
+ softfloat/bits*/*/softfloat.h
+ softfloat/bits*/*/milieu.h
+ softfloat/bits*/*/softfloat-specialize
+ softfloat/bits*/softfloat-macros
+ softfloat/bits*/softfloat.c
+ Steps to Creating a `softfloat.o'
+ Making `softfloat.o' a Library
+ Testing SoftFloat
+ Timing SoftFloat
+ Compiler Options and Efficiency
+ Processor-Specific Optimization of `softfloat.c' Using `softfloat-macros'
+ Contact Information
+
+
+
+-------------------------------------------------------------------------------
+Legal Notice
+
+SoftFloat was written by John R. Hauser. This work was made possible in
+part by the International Computer Science Institute, located at Suite 600,
+1947 Center Street, Berkeley, California 94704. Funding was partially
+provided by the National Science Foundation under grant MIP-9311980. The
+original version of this code was written as part of a project to build
+a fixed-point vector processor in collaboration with the University of
+California at Berkeley, overseen by Profs. Nelson Morgan and John Wawrzynek.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+
+-------------------------------------------------------------------------------
+SoftFloat Source Directory Structure
+
+Because SoftFloat is targeted to multiple platforms, its source code
+is slightly scattered between target-specific and target-independent
+directories and files. The directory structure is as follows:
+
+ processors
+ softfloat
+ bits64
+ templates
+ 386-Win32-gcc
+ SPARC-Solaris-gcc
+ bits32
+ templates
+ 386-Win32-gcc
+ SPARC-Solaris-gcc
+
+The two topmost directories and their contents are:
+
+ softfloat - Most of the source code needed for SoftFloat.
+ processors - Target-specific header files that are not specific to
+ SoftFloat.
+
+The `softfloat' directory is further split into two parts:
+
+ bits64 - SoftFloat implementation using 64-bit integers.
+ bits32 - SoftFloat implementation using only 32-bit integers.
+
+Within these directories are subdirectories for each of the targeted
+platforms. The SoftFloat source code is distributed with targets
+`386-Win32-gcc' and `SPARC-Solaris-gcc' (and perhaps others) already
+prepared for both the 32-bit and 64-bit implementations. Source files that
+are not within these target-specific subdirectories are intended to be
+target-independent.
+
+The naming convention used for the target-specific directories is
+`<processor>-<executable-type>-<compiler>'. The names of the supplied
+target directories should be interpreted as follows:
+
+ <processor>:
+ 386 - Intel 386-compatible processor.
+ SPARC - SPARC processor (as used by Sun machines).
+ <executable-type>:
+ Win32 - Microsoft Win32 executable.
+ Solaris - Sun Solaris executable.
+ <compiler>:
+ gcc - GNU C Compiler.
+
+You do not need to maintain this convention if you do not want to.
+
+Alongside the supplied target-specific directories is a `templates'
+directory containing a set of ``generic'' target-specific source files. A
+new target directory can be created by copying the `templates' directory and
+editing the files inside. (Complete instructions for porting SoftFloat to a
+new target are in the section _Steps_to_Creating_a_`softfloat.o'_.) Note
+that the `templates' directory will not work as a target directory without
+some editing. To avoid confusion, it would be wise to refrain from editing
+the files inside `templates' directly.
+
+
+-------------------------------------------------------------------------------
+SoftFloat Source Files
+
+The purpose of each source file is described below. In the following,
+the `*' symbol is used in place of the name of a specific target, such as
+`386-Win32-gcc' or `SPARC-Solaris-gcc', or in place of some other text, as
+in `bits*' for either `bits32' or `bits64'.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+processors/*.h
+
+The target-specific `processors' header file defines integer types
+of various sizes, and also defines certain C preprocessor macros that
+characterize the target. The two examples supplied are `386-gcc.h' and
+`SPARC-gcc.h'. The naming convention used for processor header files is
+`<processor>-<compiler>.h'.
+
+If 64-bit integers are supported by the compiler, the macro name `BITS64'
+should be defined here along with the corresponding 64-bit integer
+types. In addition, the function-like macro `LIT64' must be defined for
+constructing 64-bit integer literals (constants). The `LIT64' macro is used
+consistently in the SoftFloat code to annotate 64-bit literals.
+
+If `BITS64' is not defined, only the 32-bit version of SoftFloat can be
+compiled. If `BITS64' _is_ defined, either can be compiled.
+
+If an inlining attribute (such as an `inline' keyword) is provided by the
+compiler, the macro `INLINE' should be defined to the appropriate keyword.
+If not, `INLINE' can be set to the keyword `static'. The `INLINE' macro
+appears in the SoftFloat source code before every function that should
+be inlined by the compiler. SoftFloat depends on inlining to obtain
+good speed. Even if inlining cannot be forced with a language keyword,
+the compiler may still be able to perform inlining on its own as an
+optimization. If a command-line option is needed to convince the compiler
+to perform this optimization, this should be assured in the makefile. (See
+the section _Compiler_Options_and_Efficiency_ below.)
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+softfloat/bits*/*/softfloat.h
+
+The target-specific `softfloat.h' header file defines the SoftFloat
+interface as seen by clients.
+
+Unlike the actual function definitions in `softfloat.c', the declarations
+in `softfloat.h' do not use any of the types defined by the `processors'
+header file. This is done so that clients will not have to include the
+`processors' header file in order to use SoftFloat. Nevertheless, the
+target-specific declarations in `softfloat.h' must match what `softfloat.c'
+expects. For example, if `int32' is defined as `int' in the `processors'
+header file, then in `softfloat.h' the output of `float32_to_int32' should
+be stated as `int', although in `softfloat.c' it is given in target-
+independent form as `int32'.
+
+For the `bits64' implementation of SoftFloat, the macro names `FLOATX80' and
+`FLOAT128' must be defined in order for the extended double-precision and
+quadruple-precision formats to be enabled in the code. Conversely, either
+or both of the extended formats can be disabled by simply removing the
+`#define' of the respective macro. When an extended format is not enabled,
+none of the functions that either input or output the format are defined,
+and no space is taken up in `softfloat.o' by such functions. There is no
+provision for disabling the usual single- and double-precision formats.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+softfloat/bits*/*/milieu.h
+
+The target-specific `milieu.h' header file provides declarations that are
+needed to compile SoftFloat. In addition, deviations from ISO/ANSI C by
+the compiler (such as names not properly declared in system header files)
+are corrected in this header if possible.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+softfloat/bits*/*/softfloat-specialize
+
+This target-specific C source fragment defines:
+
+-- whether tininess for underflow is detected before or after rounding by
+ default;
+-- what (if anything) special happens when exceptions are raised;
+-- how signaling NaNs are distinguished from quiet NaNs;
+-- the default generated quiet NaNs; and
+-- how NaNs are propagated from function inputs to output.
+
+These details are not decided by the IEC/IEEE Standard. This fragment is
+included verbatim within `softfloat.c' when SoftFloat is compiled.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+softfloat/bits*/softfloat-macros
+
+This target-independent C source fragment defines a number of arithmetic
+functions used as primitives within the `softfloat.c' source. Most of the
+functions defined here are intended to be inlined for efficiency. This
+fragment is included verbatim within `softfloat.c' when SoftFloat is
+compiled.
+
+Target-specific variations on this file are possible. See the section
+_Processor-Specific_Optimization_of_`softfloat.c'_Using_`softfloat-macros'_
+below.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+softfloat/bits*/softfloat.c
+
+The target-independent `softfloat.c' source file contains the body of the
+SoftFloat implementation.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+The inclusion of the files above within each other (using `#include') can be
+shown graphically as follows:
+
+ softfloat/bits*/softfloat.c
+ softfloat/bits*/*/milieu.h
+ processors/*.h
+ softfloat/bits*/*/softfloat.h
+ softfloat/bits*/*/softfloat-specialize
+ softfloat/bits*/softfloat-macros
+
+Note in particular that `softfloat.c' does not include the `processors'
+header file directly. Rather, `softfloat.c' includes the target-specific
+`milieu.h' header file, which in turn includes the processor header file.
+
+
+-------------------------------------------------------------------------------
+Steps to Creating a `softfloat.o'
+
+Porting and/or compiling SoftFloat involves the following steps:
+
+1. If one does not already exist, create an appropriate `.h' file in the
+ `processors' directory.
+
+2. If `BITS64' is defined in the `processors' header file, choose whether
+ to compile the 32-bit or 64-bit implementation of SoftFloat. If
+ `BITS64' is not defined, your only choice is the 32-bit implementation.
+ The remaining steps occur within either the `bits32' or `bits64'
+ subdirectories.
+
+3. If one does not already exist, create an appropriate target-specific
+ subdirectory by copying the given `templates' directory.
+
+4. In the target-specific subdirectory, edit the files `softfloat-specialize'
+ and `softfloat.h' to define the desired exception handling functions
+ and mode control values. In the `softfloat.h' header file, ensure also
+ that all declarations give the proper target-specific type (such as
+ `int' or `long') corresponding to the target-independent type used in
+ `softfloat.c' (such as `int32'). None of the type names declared in the
+ `processors' header file should appear in `softfloat.h'.
+
+5. In the target-specific subdirectory, edit the files `milieu.h' and
+ `Makefile' to reflect the current environment.
+
+6. In the target-specific subdirectory, execute `make'.
+
+For the targets that are supplied, if the expected compiler is available
+(usually `gcc'), it should only be necessary to execute `make' in the
+target-specific subdirectory.
+
+
+-------------------------------------------------------------------------------
+Making `softfloat.o' a Library
+
+SoftFloat is not made into a software library by the supplied makefile.
+If desired, `softfloat.o' can easily be put into its own library (in Unix,
+`softfloat.a') using the usual system tool (in Unix, `ar').
+
+
+-------------------------------------------------------------------------------
+Testing SoftFloat
+
+SoftFloat can be tested using the `testsoftfloat' program by the same
+author. The `testsoftfloat' program is part of the TestFloat package
+available at the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/
+TestFloat.html'.
+
+
+-------------------------------------------------------------------------------
+Timing SoftFloat
+
+A program called `timesoftfloat' for timing the SoftFloat functions is
+included with the SoftFloat source code. Compiling `timesoftfloat' should
+pose no difficulties once `softfloat.o' exists. The supplied makefile
+will create a `timesoftfloat' executable by default after generating
+`softfloat.o'. See `timesoftfloat.txt' for documentation about using
+`timesoftfloat'.
+
+
+-------------------------------------------------------------------------------
+Compiler Options and Efficiency
+
+In order to get good speed with SoftFloat, it is important that the compiler
+inline the routines that have been marked `INLINE' in the code. Even if
+inlining cannot be forced by an appropriate definition of the `INLINE'
+macro, the compiler may still be able to perform inlining on its own as
+an optimization. In that case, the makefile should be edited to give the
+compiler whatever option is required to cause it to inline small functions.
+
+The ability of the processor to do fast shifts has been assumed. Efficiency
+will not be as good on processors for which this is not the case (such as
+the original Motorola 68000 or Intel 8086 processors).
+
+
+-------------------------------------------------------------------------------
+Processor-Specific Optimization of `softfloat.c' Using `softfloat-macros'
+
+The `softfloat-macros' source fragment defines arithmetic functions used
+as primitives by `softfloat.c'. This file has been written in a target-
+independent form. For a given target, it may be possible to improve on
+these functions using target-specific and/or non-ISO-C features (such
+as `asm' statements). For example, one of the ``macro'' functions takes
+two word-size integers and returns their full product in two words.
+This operation can be done directly in hardware on many processors; but
+because it is not available through standard C, the function defined in
+`softfloat-macros' uses four multiplies to achieve the same result.
+
+To address these shortcomings, a customized version of `softfloat-macros'
+can be created in any of the target-specific subdirectories. A simple
+modification to the target's makefile should be sufficient to ensure that
+the custom version is used instead of the generic one.
+
+
+-------------------------------------------------------------------------------
+Contact Information
+
+At the time of this writing, the most up-to-date information about
+SoftFloat and the latest release can be found at the Web page `http://
+HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/SoftFloat.html'.
+
+
diff --git a/lib/libc/softfloat/softfloat-specialize b/lib/libc/softfloat/softfloat-specialize
new file mode 100644
index 0000000..b5eb8c3
--- /dev/null
+++ b/lib/libc/softfloat/softfloat-specialize
@@ -0,0 +1,521 @@
+/* $NetBSD: softfloat-specialize,v 1.6 2011/03/06 10:27:37 martin Exp $ */
+/* $FreeBSD$ */
+
+/* This is a derivative work. */
+
+/*
+===============================================================================
+
+This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+#include <signal.h>
+#include <string.h>
+#include <unistd.h>
+
+/*
+-------------------------------------------------------------------------------
+Underflow tininess-detection mode, statically initialized to default value.
+(The declaration in `softfloat.h' must match the `int8' type here.)
+-------------------------------------------------------------------------------
+*/
+#ifdef SOFTFLOAT_FOR_GCC
+static
+#endif
+#ifdef __sparc64__
+int8 float_detect_tininess = float_tininess_before_rounding;
+#else
+int8 float_detect_tininess = float_tininess_after_rounding;
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Raises the exceptions specified by `flags'. Floating-point traps can be
+defined here if desired. It is currently not possible for such a trap to
+substitute a result value. If traps are not implemented, this routine
+should be simply `float_exception_flags |= flags;'.
+-------------------------------------------------------------------------------
+*/
+#ifdef SOFTFLOAT_FOR_GCC
+#define float_exception_mask __softfloat_float_exception_mask
+#endif
+int float_exception_mask = 0;
+void float_raise( int flags )
+{
+
+ float_exception_flags |= flags;
+
+ if ( flags & float_exception_mask ) {
+#if 0
+ siginfo_t info;
+ memset(&info, 0, sizeof info);
+ info.si_signo = SIGFPE;
+ info.si_pid = getpid();
+ info.si_uid = geteuid();
+ if (flags & float_flag_underflow)
+ info.si_code = FPE_FLTUND;
+ else if (flags & float_flag_overflow)
+ info.si_code = FPE_FLTOVF;
+ else if (flags & float_flag_divbyzero)
+ info.si_code = FPE_FLTDIV;
+ else if (flags & float_flag_invalid)
+ info.si_code = FPE_FLTINV;
+ else if (flags & float_flag_inexact)
+ info.si_code = FPE_FLTRES;
+ sigqueueinfo(getpid(), &info);
+#else
+ raise( SIGFPE );
+#endif
+ }
+}
+#undef float_exception_mask
+
+/*
+-------------------------------------------------------------------------------
+Internal canonical NaN format.
+-------------------------------------------------------------------------------
+*/
+typedef struct {
+ flag sign;
+ bits64 high, low;
+} commonNaNT;
+
+/*
+-------------------------------------------------------------------------------
+The pattern for a default generated single-precision NaN.
+-------------------------------------------------------------------------------
+*/
+#define float32_default_nan 0xFFFFFFFF
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is a NaN;
+otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+#ifdef SOFTFLOAT_FOR_GCC
+static
+#endif
+flag float32_is_nan( float32 a )
+{
+
+ return ( 0xFF000000 < (bits32) ( a<<1 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is a signaling
+NaN; otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \
+ !defined(SOFTFLOAT_M68K_FOR_GCC)
+static
+#endif
+flag float32_is_signaling_nan( float32 a )
+{
+
+ return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point NaN
+`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
+exception is raised.
+-------------------------------------------------------------------------------
+*/
+static commonNaNT float32ToCommonNaN( float32 a )
+{
+ commonNaNT z;
+
+ if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+ z.sign = a>>31;
+ z.low = 0;
+ z.high = ( (bits64) a )<<41;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the canonical NaN `a' to the single-
+precision floating-point format.
+-------------------------------------------------------------------------------
+*/
+static float32 commonNaNToFloat32( commonNaNT a )
+{
+
+ return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes two single-precision floating-point values `a' and `b', one of which
+is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
+signaling NaN, the invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static float32 propagateFloat32NaN( float32 a, float32 b )
+{
+ flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+
+ aIsNaN = float32_is_nan( a );
+ aIsSignalingNaN = float32_is_signaling_nan( a );
+ bIsNaN = float32_is_nan( b );
+ bIsSignalingNaN = float32_is_signaling_nan( b );
+ a |= 0x00400000;
+ b |= 0x00400000;
+ if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
+ if ( aIsNaN ) {
+ return ( aIsSignalingNaN & bIsNaN ) ? b : a;
+ }
+ else {
+ return b;
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+The pattern for a default generated double-precision NaN.
+-------------------------------------------------------------------------------
+*/
+#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is a NaN;
+otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+#ifdef SOFTFLOAT_FOR_GCC
+static
+#endif
+flag float64_is_nan( float64 a )
+{
+
+ return ( LIT64( 0xFFE0000000000000 ) <
+ (bits64) ( FLOAT64_DEMANGLE(a)<<1 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is a signaling
+NaN; otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+#if defined(SOFTFLOAT_FOR_GCC) && !defined(SOFTFLOATSPARC64_FOR_GCC) && \
+ !defined(SOFTFLOATM68K_FOR_GCC)
+static
+#endif
+flag float64_is_signaling_nan( float64 a )
+{
+
+ return
+ ( ( ( FLOAT64_DEMANGLE(a)>>51 ) & 0xFFF ) == 0xFFE )
+ && ( FLOAT64_DEMANGLE(a) & LIT64( 0x0007FFFFFFFFFFFF ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point NaN
+`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
+exception is raised.
+-------------------------------------------------------------------------------
+*/
+static commonNaNT float64ToCommonNaN( float64 a )
+{
+ commonNaNT z;
+
+ if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+ z.sign = FLOAT64_DEMANGLE(a)>>63;
+ z.low = 0;
+ z.high = FLOAT64_DEMANGLE(a)<<12;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the canonical NaN `a' to the double-
+precision floating-point format.
+-------------------------------------------------------------------------------
+*/
+static float64 commonNaNToFloat64( commonNaNT a )
+{
+
+ return FLOAT64_MANGLE(
+ ( ( (bits64) a.sign )<<63 )
+ | LIT64( 0x7FF8000000000000 )
+ | ( a.high>>12 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes two double-precision floating-point values `a' and `b', one of which
+is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
+signaling NaN, the invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static float64 propagateFloat64NaN( float64 a, float64 b )
+{
+ flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+
+ aIsNaN = float64_is_nan( a );
+ aIsSignalingNaN = float64_is_signaling_nan( a );
+ bIsNaN = float64_is_nan( b );
+ bIsSignalingNaN = float64_is_signaling_nan( b );
+ a |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
+ b |= FLOAT64_MANGLE(LIT64( 0x0008000000000000 ));
+ if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
+ if ( aIsNaN ) {
+ return ( aIsSignalingNaN & bIsNaN ) ? b : a;
+ }
+ else {
+ return b;
+ }
+
+}
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+The pattern for a default generated extended double-precision NaN. The
+`high' and `low' values hold the most- and least-significant bits,
+respectively.
+-------------------------------------------------------------------------------
+*/
+#define floatx80_default_nan_high 0xFFFF
+#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is a
+NaN; otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_is_nan( floatx80 a )
+{
+
+ return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is a
+signaling NaN; otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_is_signaling_nan( floatx80 a )
+{
+ bits64 aLow;
+
+ aLow = a.low & ~ LIT64( 0x4000000000000000 );
+ return
+ ( ( a.high & 0x7FFF ) == 0x7FFF )
+ && (bits64) ( aLow<<1 )
+ && ( a.low == aLow );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
+invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static commonNaNT floatx80ToCommonNaN( floatx80 a )
+{
+ commonNaNT z;
+
+ if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+ z.sign = a.high>>15;
+ z.low = 0;
+ z.high = a.low<<1;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the canonical NaN `a' to the extended
+double-precision floating-point format.
+-------------------------------------------------------------------------------
+*/
+static floatx80 commonNaNToFloatx80( commonNaNT a )
+{
+ floatx80 z;
+
+ z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
+ z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes two extended double-precision floating-point values `a' and `b', one
+of which is a NaN, and returns the appropriate NaN result. If either `a' or
+`b' is a signaling NaN, the invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
+{
+ flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+
+ aIsNaN = floatx80_is_nan( a );
+ aIsSignalingNaN = floatx80_is_signaling_nan( a );
+ bIsNaN = floatx80_is_nan( b );
+ bIsSignalingNaN = floatx80_is_signaling_nan( b );
+ a.low |= LIT64( 0xC000000000000000 );
+ b.low |= LIT64( 0xC000000000000000 );
+ if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
+ if ( aIsNaN ) {
+ return ( aIsSignalingNaN & bIsNaN ) ? b : a;
+ }
+ else {
+ return b;
+ }
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+The pattern for a default generated quadruple-precision NaN. The `high' and
+`low' values hold the most- and least-significant bits, respectively.
+-------------------------------------------------------------------------------
+*/
+#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
+#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
+otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag float128_is_nan( float128 a )
+{
+
+ return
+ ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
+ && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is a
+signaling NaN; otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag float128_is_signaling_nan( float128 a )
+{
+
+ return
+ ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
+ && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point NaN
+`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
+exception is raised.
+-------------------------------------------------------------------------------
+*/
+static commonNaNT float128ToCommonNaN( float128 a )
+{
+ commonNaNT z;
+
+ if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+ z.sign = a.high>>63;
+ shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the canonical NaN `a' to the quadruple-
+precision floating-point format.
+-------------------------------------------------------------------------------
+*/
+static float128 commonNaNToFloat128( commonNaNT a )
+{
+ float128 z;
+
+ shift128Right( a.high, a.low, 16, &z.high, &z.low );
+ z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes two quadruple-precision floating-point values `a' and `b', one of
+which is a NaN, and returns the appropriate NaN result. If either `a' or
+`b' is a signaling NaN, the invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static float128 propagateFloat128NaN( float128 a, float128 b )
+{
+ flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+
+ aIsNaN = float128_is_nan( a );
+ aIsSignalingNaN = float128_is_signaling_nan( a );
+ bIsNaN = float128_is_nan( b );
+ bIsSignalingNaN = float128_is_signaling_nan( b );
+ a.high |= LIT64( 0x0000800000000000 );
+ b.high |= LIT64( 0x0000800000000000 );
+ if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
+ if ( aIsNaN ) {
+ return ( aIsSignalingNaN & bIsNaN ) ? b : a;
+ }
+ else {
+ return b;
+ }
+
+}
+
+#endif
+
diff --git a/lib/libc/softfloat/softfloat.txt b/lib/libc/softfloat/softfloat.txt
new file mode 100644
index 0000000..414506f
--- /dev/null
+++ b/lib/libc/softfloat/softfloat.txt
@@ -0,0 +1,373 @@
+$NetBSD: softfloat.txt,v 1.2 2006/11/24 19:46:58 christos Exp $
+$FreeBSD$
+
+SoftFloat Release 2a General Documentation
+
+John R. Hauser
+1998 December 13
+
+
+-------------------------------------------------------------------------------
+Introduction
+
+SoftFloat is a software implementation of floating-point that conforms to
+the IEC/IEEE Standard for Binary Floating-Point Arithmetic. As many as four
+formats are supported: single precision, double precision, extended double
+precision, and quadruple precision. All operations required by the standard
+are implemented, except for conversions to and from decimal.
+
+This document gives information about the types defined and the routines
+implemented by SoftFloat. It does not attempt to define or explain the
+IEC/IEEE Floating-Point Standard. Details about the standard are available
+elsewhere.
+
+
+-------------------------------------------------------------------------------
+Limitations
+
+SoftFloat is written in C and is designed to work with other C code. The
+SoftFloat header files assume an ISO/ANSI-style C compiler. No attempt
+has been made to accommodate compilers that are not ISO-conformant. In
+particular, the distributed header files will not be acceptable to any
+compiler that does not recognize function prototypes.
+
+Support for the extended double-precision and quadruple-precision formats
+depends on a C compiler that implements 64-bit integer arithmetic. If the
+largest integer format supported by the C compiler is 32 bits, SoftFloat is
+limited to only single and double precisions. When that is the case, all
+references in this document to the extended double precision, quadruple
+precision, and 64-bit integers should be ignored.
+
+
+-------------------------------------------------------------------------------
+Contents
+
+ Introduction
+ Limitations
+ Contents
+ Legal Notice
+ Types and Functions
+ Rounding Modes
+ Extended Double-Precision Rounding Precision
+ Exceptions and Exception Flags
+ Function Details
+ Conversion Functions
+ Standard Arithmetic Functions
+ Remainder Functions
+ Round-to-Integer Functions
+ Comparison Functions
+ Signaling NaN Test Functions
+ Raise-Exception Function
+ Contact Information
+
+
+
+-------------------------------------------------------------------------------
+Legal Notice
+
+SoftFloat was written by John R. Hauser. This work was made possible in
+part by the International Computer Science Institute, located at Suite 600,
+1947 Center Street, Berkeley, California 94704. Funding was partially
+provided by the National Science Foundation under grant MIP-9311980. The
+original version of this code was written as part of a project to build
+a fixed-point vector processor in collaboration with the University of
+California at Berkeley, overseen by Profs. Nelson Morgan and John Wawrzynek.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+
+-------------------------------------------------------------------------------
+Types and Functions
+
+When 64-bit integers are supported by the compiler, the `softfloat.h' header
+file defines four types: `float32' (single precision), `float64' (double
+precision), `floatx80' (extended double precision), and `float128'
+(quadruple precision). The `float32' and `float64' types are defined in
+terms of 32-bit and 64-bit integer types, respectively, while the `float128'
+type is defined as a structure of two 64-bit integers, taking into account
+the byte order of the particular machine being used. The `floatx80' type
+is defined as a structure containing one 16-bit and one 64-bit integer, with
+the machine's byte order again determining the order of the `high' and `low'
+fields.
+
+When 64-bit integers are _not_ supported by the compiler, the `softfloat.h'
+header file defines only two types: `float32' and `float64'. Because
+ISO/ANSI C guarantees at least one built-in integer type of 32 bits,
+the `float32' type is identified with an appropriate integer type. The
+`float64' type is defined as a structure of two 32-bit integers, with the
+machine's byte order determining the order of the fields.
+
+In either case, the types in `softfloat.h' are defined such that if a system
+implements the usual C `float' and `double' types according to the IEC/IEEE
+Standard, then the `float32' and `float64' types should be indistinguishable
+in memory from the native `float' and `double' types. (On the other hand,
+when `float32' or `float64' values are placed in processor registers by
+the compiler, the type of registers used may differ from those used for the
+native `float' and `double' types.)
+
+SoftFloat implements the following arithmetic operations:
+
+-- Conversions among all the floating-point formats, and also between
+ integers (32-bit and 64-bit) and any of the floating-point formats.
+
+-- The usual add, subtract, multiply, divide, and square root operations
+ for all floating-point formats.
+
+-- For each format, the floating-point remainder operation defined by the
+ IEC/IEEE Standard.
+
+-- For each floating-point format, a ``round to integer'' operation that
+ rounds to the nearest integer value in the same format. (The floating-
+ point formats can hold integer values, of course.)
+
+-- Comparisons between two values in the same floating-point format.
+
+The only functions required by the IEC/IEEE Standard that are not provided
+are conversions to and from decimal.
+
+
+-------------------------------------------------------------------------------
+Rounding Modes
+
+All four rounding modes prescribed by the IEC/IEEE Standard are implemented
+for all operations that require rounding. The rounding mode is selected
+by the global variable `float_rounding_mode'. This variable may be set
+to one of the values `float_round_nearest_even', `float_round_to_zero',
+`float_round_down', or `float_round_up'. The rounding mode is initialized
+to nearest/even.
+
+
+-------------------------------------------------------------------------------
+Extended Double-Precision Rounding Precision
+
+For extended double precision (`floatx80') only, the rounding precision
+of the standard arithmetic operations is controlled by the global variable
+`floatx80_rounding_precision'. The operations affected are:
+
+ floatx80_add floatx80_sub floatx80_mul floatx80_div floatx80_sqrt
+
+When `floatx80_rounding_precision' is set to its default value of 80, these
+operations are rounded (as usual) to the full precision of the extended
+double-precision format. Setting `floatx80_rounding_precision' to 32
+or to 64 causes the operations listed to be rounded to reduced precision
+equivalent to single precision (`float32') or to double precision
+(`float64'), respectively. When rounding to reduced precision, additional
+bits in the result significand beyond the rounding point are set to zero.
+The consequences of setting `floatx80_rounding_precision' to a value other
+than 32, 64, or 80 is not specified. Operations other than the ones listed
+above are not affected by `floatx80_rounding_precision'.
+
+
+-------------------------------------------------------------------------------
+Exceptions and Exception Flags
+
+All five exception flags required by the IEC/IEEE Standard are
+implemented. Each flag is stored as a unique bit in the global variable
+`float_exception_flags'. The positions of the exception flag bits within
+this variable are determined by the bit masks `float_flag_inexact',
+`float_flag_underflow', `float_flag_overflow', `float_flag_divbyzero', and
+`float_flag_invalid'. The exception flags variable is initialized to all 0,
+meaning no exceptions.
+
+An individual exception flag can be cleared with the statement
+
+ float_exception_flags &= ~ float_flag_<exception>;
+
+where `<exception>' is the appropriate name. To raise a floating-point
+exception, the SoftFloat function `float_raise' should be used (see below).
+
+In the terminology of the IEC/IEEE Standard, SoftFloat can detect tininess
+for underflow either before or after rounding. The choice is made by
+the global variable `float_detect_tininess', which can be set to either
+`float_tininess_before_rounding' or `float_tininess_after_rounding'.
+Detecting tininess after rounding is better because it results in fewer
+spurious underflow signals. The other option is provided for compatibility
+with some systems. Like most systems, SoftFloat always detects loss of
+accuracy for underflow as an inexact result.
+
+
+-------------------------------------------------------------------------------
+Function Details
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Conversion Functions
+
+All conversions among the floating-point formats are supported, as are all
+conversions between a floating-point format and 32-bit and 64-bit signed
+integers. The complete set of conversion functions is:
+
+ int32_to_float32 int64_to_float32
+ int32_to_float64 int64_to_float32
+ int32_to_floatx80 int64_to_floatx80
+ int32_to_float128 int64_to_float128
+
+ float32_to_int32 float32_to_int64
+ float32_to_int32 float64_to_int64
+ floatx80_to_int32 floatx80_to_int64
+ float128_to_int32 float128_to_int64
+
+ float32_to_float64 float32_to_floatx80 float32_to_float128
+ float64_to_float32 float64_to_floatx80 float64_to_float128
+ floatx80_to_float32 floatx80_to_float64 floatx80_to_float128
+ float128_to_float32 float128_to_float64 float128_to_floatx80
+
+Each conversion function takes one operand of the appropriate type and
+returns one result. Conversions from a smaller to a larger floating-point
+format are always exact and so require no rounding. Conversions from 32-bit
+integers to double precision and larger formats are also exact, and likewise
+for conversions from 64-bit integers to extended double and quadruple
+precisions.
+
+Conversions from floating-point to integer raise the invalid exception if
+the source value cannot be rounded to a representable integer of the desired
+size (32 or 64 bits). If the floating-point operand is a NaN, the largest
+positive integer is returned. Otherwise, if the conversion overflows, the
+largest integer with the same sign as the operand is returned.
+
+On conversions to integer, if the floating-point operand is not already an
+integer value, the operand is rounded according to the current rounding
+mode as specified by `float_rounding_mode'. Because C (and perhaps other
+languages) require that conversions to integers be rounded toward zero, the
+following functions are provided for improved speed and convenience:
+
+ float32_to_int32_round_to_zero float32_to_int64_round_to_zero
+ float64_to_int32_round_to_zero float64_to_int64_round_to_zero
+ floatx80_to_int32_round_to_zero floatx80_to_int64_round_to_zero
+ float128_to_int32_round_to_zero float128_to_int64_round_to_zero
+
+These variant functions ignore `float_rounding_mode' and always round toward
+zero.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Standard Arithmetic Functions
+
+The following standard arithmetic functions are provided:
+
+ float32_add float32_sub float32_mul float32_div float32_sqrt
+ float64_add float64_sub float64_mul float64_div float64_sqrt
+ floatx80_add floatx80_sub floatx80_mul floatx80_div floatx80_sqrt
+ float128_add float128_sub float128_mul float128_div float128_sqrt
+
+Each function takes two operands, except for `sqrt' which takes only one.
+The operands and result are all of the same type.
+
+Rounding of the extended double-precision (`floatx80') functions is affected
+by the `floatx80_rounding_precision' variable, as explained above in the
+section _Extended_Double-Precision_Rounding_Precision_.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Remainder Functions
+
+For each format, SoftFloat implements the remainder function according to
+the IEC/IEEE Standard. The remainder functions are:
+
+ float32_rem
+ float64_rem
+ floatx80_rem
+ float128_rem
+
+Each remainder function takes two operands. The operands and result are all
+of the same type. Given operands x and y, the remainder functions return
+the value x - n*y, where n is the integer closest to x/y. If x/y is exactly
+halfway between two integers, n is the even integer closest to x/y. The
+remainder functions are always exact and so require no rounding.
+
+Depending on the relative magnitudes of the operands, the remainder
+functions can take considerably longer to execute than the other SoftFloat
+functions. This is inherent in the remainder operation itself and is not a
+flaw in the SoftFloat implementation.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Round-to-Integer Functions
+
+For each format, SoftFloat implements the round-to-integer function
+specified by the IEC/IEEE Standard. The functions are:
+
+ float32_round_to_int
+ float64_round_to_int
+ floatx80_round_to_int
+ float128_round_to_int
+
+Each function takes a single floating-point operand and returns a result of
+the same type. (Note that the result is not an integer type.) The operand
+is rounded to an exact integer according to the current rounding mode, and
+the resulting integer value is returned in the same floating-point format.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Comparison Functions
+
+The following floating-point comparison functions are provided:
+
+ float32_eq float32_le float32_lt
+ float64_eq float64_le float64_lt
+ floatx80_eq floatx80_le floatx80_lt
+ float128_eq float128_le float128_lt
+
+Each function takes two operands of the same type and returns a 1 or 0
+representing either _true_ or _false_. The abbreviation `eq' stands for
+``equal'' (=); `le' stands for ``less than or equal'' (<=); and `lt' stands
+for ``less than'' (<).
+
+The standard greater-than (>), greater-than-or-equal (>=), and not-equal
+(!=) functions are easily obtained using the functions provided. The
+not-equal function is just the logical complement of the equal function.
+The greater-than-or-equal function is identical to the less-than-or-equal
+function with the operands reversed; and the greater-than function can be
+obtained from the less-than function in the same way.
+
+The IEC/IEEE Standard specifies that the less-than-or-equal and less-than
+functions raise the invalid exception if either input is any kind of NaN.
+The equal functions, on the other hand, are defined not to raise the invalid
+exception on quiet NaNs. For completeness, SoftFloat provides the following
+additional functions:
+
+ float32_eq_signaling float32_le_quiet float32_lt_quiet
+ float64_eq_signaling float64_le_quiet float64_lt_quiet
+ floatx80_eq_signaling floatx80_le_quiet floatx80_lt_quiet
+ float128_eq_signaling float128_le_quiet float128_lt_quiet
+
+The `signaling' equal functions are identical to the standard functions
+except that the invalid exception is raised for any NaN input. Likewise,
+the `quiet' comparison functions are identical to their counterparts except
+that the invalid exception is not raised for quiet NaNs.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Signaling NaN Test Functions
+
+The following functions test whether a floating-point value is a signaling
+NaN:
+
+ float32_is_signaling_nan
+ float64_is_signaling_nan
+ floatx80_is_signaling_nan
+ float128_is_signaling_nan
+
+The functions take one operand and return 1 if the operand is a signaling
+NaN and 0 otherwise.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+Raise-Exception Function
+
+SoftFloat provides a function for raising floating-point exceptions:
+
+ float_raise
+
+The function takes a mask indicating the set of exceptions to raise. No
+result is returned. In addition to setting the specified exception flags,
+this function may cause a trap or abort appropriate for the current system.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+-------------------------------------------------------------------------------
+Contact Information
+
+At the time of this writing, the most up-to-date information about
+SoftFloat and the latest release can be found at the Web page `http://
+HTTP.CS.Berkeley.EDU/~jhauser/arithmetic/SoftFloat.html'.
+
+
diff --git a/lib/libc/softfloat/templates/milieu.h b/lib/libc/softfloat/templates/milieu.h
new file mode 100644
index 0000000..b7bd8e5
--- /dev/null
+++ b/lib/libc/softfloat/templates/milieu.h
@@ -0,0 +1,49 @@
+/* $FreeBSD$ */
+
+/*
+===============================================================================
+
+This C header file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+Include common integer types and flags.
+-------------------------------------------------------------------------------
+*/
+#include "../../../processors/!!!processor.h"
+
+/*
+-------------------------------------------------------------------------------
+Symbolic Boolean literals.
+-------------------------------------------------------------------------------
+*/
+enum {
+ FALSE = 0,
+ TRUE = 1
+};
+
diff --git a/lib/libc/softfloat/templates/softfloat-specialize b/lib/libc/softfloat/templates/softfloat-specialize
new file mode 100644
index 0000000..a1dc4de
--- /dev/null
+++ b/lib/libc/softfloat/templates/softfloat-specialize
@@ -0,0 +1,465 @@
+/* $FreeBSD$ */
+
+/*
+===============================================================================
+
+This C source fragment is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+Underflow tininess-detection mode, statically initialized to default value.
+(The declaration in `softfloat.h' must match the `int8' type here.)
+-------------------------------------------------------------------------------
+*/
+int8 float_detect_tininess = float_tininess_after_rounding;
+
+/*
+-------------------------------------------------------------------------------
+Raises the exceptions specified by `flags'. Floating-point traps can be
+defined here if desired. It is currently not possible for such a trap to
+substitute a result value. If traps are not implemented, this routine
+should be simply `float_exception_flags |= flags;'.
+-------------------------------------------------------------------------------
+*/
+void float_raise( int8 flags )
+{
+
+ float_exception_flags |= flags;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Internal canonical NaN format.
+-------------------------------------------------------------------------------
+*/
+typedef struct {
+ flag sign;
+ bits64 high, low;
+} commonNaNT;
+
+/*
+-------------------------------------------------------------------------------
+The pattern for a default generated single-precision NaN.
+-------------------------------------------------------------------------------
+*/
+#define float32_default_nan 0xFFFFFFFF
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is a NaN;
+otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag float32_is_nan( float32 a )
+{
+
+ return ( 0xFF000000 < (bits32) ( a<<1 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the single-precision floating-point value `a' is a signaling
+NaN; otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag float32_is_signaling_nan( float32 a )
+{
+
+ return ( ( ( a>>22 ) & 0x1FF ) == 0x1FE ) && ( a & 0x003FFFFF );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the single-precision floating-point NaN
+`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
+exception is raised.
+-------------------------------------------------------------------------------
+*/
+static commonNaNT float32ToCommonNaN( float32 a )
+{
+ commonNaNT z;
+
+ if ( float32_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+ z.sign = a>>31;
+ z.low = 0;
+ z.high = ( (bits64) a )<<41;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the canonical NaN `a' to the single-
+precision floating-point format.
+-------------------------------------------------------------------------------
+*/
+static float32 commonNaNToFloat32( commonNaNT a )
+{
+
+ return ( ( (bits32) a.sign )<<31 ) | 0x7FC00000 | ( a.high>>41 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes two single-precision floating-point values `a' and `b', one of which
+is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
+signaling NaN, the invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static float32 propagateFloat32NaN( float32 a, float32 b )
+{
+ flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+
+ aIsNaN = float32_is_nan( a );
+ aIsSignalingNaN = float32_is_signaling_nan( a );
+ bIsNaN = float32_is_nan( b );
+ bIsSignalingNaN = float32_is_signaling_nan( b );
+ a |= 0x00400000;
+ b |= 0x00400000;
+ if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
+ if ( aIsNaN ) {
+ return ( aIsSignalingNaN & bIsNaN ) ? b : a;
+ }
+ else {
+ return b;
+ }
+
+}
+
+/*
+-------------------------------------------------------------------------------
+The pattern for a default generated double-precision NaN.
+-------------------------------------------------------------------------------
+*/
+#define float64_default_nan LIT64( 0xFFFFFFFFFFFFFFFF )
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is a NaN;
+otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag float64_is_nan( float64 a )
+{
+
+ return ( LIT64( 0xFFE0000000000000 ) < (bits64) ( a<<1 ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the double-precision floating-point value `a' is a signaling
+NaN; otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag float64_is_signaling_nan( float64 a )
+{
+
+ return
+ ( ( ( a>>51 ) & 0xFFF ) == 0xFFE )
+ && ( a & LIT64( 0x0007FFFFFFFFFFFF ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the double-precision floating-point NaN
+`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
+exception is raised.
+-------------------------------------------------------------------------------
+*/
+static commonNaNT float64ToCommonNaN( float64 a )
+{
+ commonNaNT z;
+
+ if ( float64_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+ z.sign = a>>63;
+ z.low = 0;
+ z.high = a<<12;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the canonical NaN `a' to the double-
+precision floating-point format.
+-------------------------------------------------------------------------------
+*/
+static float64 commonNaNToFloat64( commonNaNT a )
+{
+
+ return
+ ( ( (bits64) a.sign )<<63 )
+ | LIT64( 0x7FF8000000000000 )
+ | ( a.high>>12 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes two double-precision floating-point values `a' and `b', one of which
+is a NaN, and returns the appropriate NaN result. If either `a' or `b' is a
+signaling NaN, the invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static float64 propagateFloat64NaN( float64 a, float64 b )
+{
+ flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+
+ aIsNaN = float64_is_nan( a );
+ aIsSignalingNaN = float64_is_signaling_nan( a );
+ bIsNaN = float64_is_nan( b );
+ bIsSignalingNaN = float64_is_signaling_nan( b );
+ a |= LIT64( 0x0008000000000000 );
+ b |= LIT64( 0x0008000000000000 );
+ if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
+ if ( aIsNaN ) {
+ return ( aIsSignalingNaN & bIsNaN ) ? b : a;
+ }
+ else {
+ return b;
+ }
+
+}
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+The pattern for a default generated extended double-precision NaN. The
+`high' and `low' values hold the most- and least-significant bits,
+respectively.
+-------------------------------------------------------------------------------
+*/
+#define floatx80_default_nan_high 0xFFFF
+#define floatx80_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is a
+NaN; otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_is_nan( floatx80 a )
+{
+
+ return ( ( a.high & 0x7FFF ) == 0x7FFF ) && (bits64) ( a.low<<1 );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the extended double-precision floating-point value `a' is a
+signaling NaN; otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag floatx80_is_signaling_nan( floatx80 a )
+{
+ bits64 aLow;
+
+ aLow = a.low & ~ LIT64( 0x4000000000000000 );
+ return
+ ( ( a.high & 0x7FFF ) == 0x7FFF )
+ && (bits64) ( aLow<<1 )
+ && ( a.low == aLow );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the extended double-precision floating-
+point NaN `a' to the canonical NaN format. If `a' is a signaling NaN, the
+invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static commonNaNT floatx80ToCommonNaN( floatx80 a )
+{
+ commonNaNT z;
+
+ if ( floatx80_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+ z.sign = a.high>>15;
+ z.low = 0;
+ z.high = a.low<<1;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the canonical NaN `a' to the extended
+double-precision floating-point format.
+-------------------------------------------------------------------------------
+*/
+static floatx80 commonNaNToFloatx80( commonNaNT a )
+{
+ floatx80 z;
+
+ z.low = LIT64( 0xC000000000000000 ) | ( a.high>>1 );
+ z.high = ( ( (bits16) a.sign )<<15 ) | 0x7FFF;
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes two extended double-precision floating-point values `a' and `b', one
+of which is a NaN, and returns the appropriate NaN result. If either `a' or
+`b' is a signaling NaN, the invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static floatx80 propagateFloatx80NaN( floatx80 a, floatx80 b )
+{
+ flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+
+ aIsNaN = floatx80_is_nan( a );
+ aIsSignalingNaN = floatx80_is_signaling_nan( a );
+ bIsNaN = floatx80_is_nan( b );
+ bIsSignalingNaN = floatx80_is_signaling_nan( b );
+ a.low |= LIT64( 0xC000000000000000 );
+ b.low |= LIT64( 0xC000000000000000 );
+ if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
+ if ( aIsNaN ) {
+ return ( aIsSignalingNaN & bIsNaN ) ? b : a;
+ }
+ else {
+ return b;
+ }
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+The pattern for a default generated quadruple-precision NaN. The `high' and
+`low' values hold the most- and least-significant bits, respectively.
+-------------------------------------------------------------------------------
+*/
+#define float128_default_nan_high LIT64( 0xFFFFFFFFFFFFFFFF )
+#define float128_default_nan_low LIT64( 0xFFFFFFFFFFFFFFFF )
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is a NaN;
+otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag float128_is_nan( float128 a )
+{
+
+ return
+ ( LIT64( 0xFFFE000000000000 ) <= (bits64) ( a.high<<1 ) )
+ && ( a.low || ( a.high & LIT64( 0x0000FFFFFFFFFFFF ) ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns 1 if the quadruple-precision floating-point value `a' is a
+signaling NaN; otherwise returns 0.
+-------------------------------------------------------------------------------
+*/
+flag float128_is_signaling_nan( float128 a )
+{
+
+ return
+ ( ( ( a.high>>47 ) & 0xFFFF ) == 0xFFFE )
+ && ( a.low || ( a.high & LIT64( 0x00007FFFFFFFFFFF ) ) );
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the quadruple-precision floating-point NaN
+`a' to the canonical NaN format. If `a' is a signaling NaN, the invalid
+exception is raised.
+-------------------------------------------------------------------------------
+*/
+static commonNaNT float128ToCommonNaN( float128 a )
+{
+ commonNaNT z;
+
+ if ( float128_is_signaling_nan( a ) ) float_raise( float_flag_invalid );
+ z.sign = a.high>>63;
+ shortShift128Left( a.high, a.low, 16, &z.high, &z.low );
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Returns the result of converting the canonical NaN `a' to the quadruple-
+precision floating-point format.
+-------------------------------------------------------------------------------
+*/
+static float128 commonNaNToFloat128( commonNaNT a )
+{
+ float128 z;
+
+ shift128Right( a.high, a.low, 16, &z.high, &z.low );
+ z.high |= ( ( (bits64) a.sign )<<63 ) | LIT64( 0x7FFF800000000000 );
+ return z;
+
+}
+
+/*
+-------------------------------------------------------------------------------
+Takes two quadruple-precision floating-point values `a' and `b', one of
+which is a NaN, and returns the appropriate NaN result. If either `a' or
+`b' is a signaling NaN, the invalid exception is raised.
+-------------------------------------------------------------------------------
+*/
+static float128 propagateFloat128NaN( float128 a, float128 b )
+{
+ flag aIsNaN, aIsSignalingNaN, bIsNaN, bIsSignalingNaN;
+
+ aIsNaN = float128_is_nan( a );
+ aIsSignalingNaN = float128_is_signaling_nan( a );
+ bIsNaN = float128_is_nan( b );
+ bIsSignalingNaN = float128_is_signaling_nan( b );
+ a.high |= LIT64( 0x0000800000000000 );
+ b.high |= LIT64( 0x0000800000000000 );
+ if ( aIsSignalingNaN | bIsSignalingNaN ) float_raise( float_flag_invalid );
+ if ( aIsNaN ) {
+ return ( aIsSignalingNaN & bIsNaN ) ? b : a;
+ }
+ else {
+ return b;
+ }
+
+}
+
+#endif
+
diff --git a/lib/libc/softfloat/templates/softfloat.h b/lib/libc/softfloat/templates/softfloat.h
new file mode 100644
index 0000000..070aab2
--- /dev/null
+++ b/lib/libc/softfloat/templates/softfloat.h
@@ -0,0 +1,291 @@
+/* $FreeBSD$ */
+
+/*
+===============================================================================
+
+This C header file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+/*
+-------------------------------------------------------------------------------
+The macro `FLOATX80' must be defined to enable the extended double-precision
+floating-point format `floatx80'. If this macro is not defined, the
+`floatx80' type will not be defined, and none of the functions that either
+input or output the `floatx80' type will be defined. The same applies to
+the `FLOAT128' macro and the quadruple-precision format `float128'.
+-------------------------------------------------------------------------------
+*/
+#define FLOATX80
+#define FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point types.
+-------------------------------------------------------------------------------
+*/
+typedef !!!bits32 float32;
+typedef !!!bits64 float64;
+#ifdef FLOATX80
+typedef struct {
+ !!!bits16 high;
+ !!!bits64 low;
+} floatx80;
+#endif
+#ifdef FLOAT128
+typedef struct {
+ !!!bits64 high, low;
+} float128;
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point underflow tininess-detection mode.
+-------------------------------------------------------------------------------
+*/
+extern !!!int8 float_detect_tininess;
+enum {
+ float_tininess_after_rounding = 0,
+ float_tininess_before_rounding = 1
+};
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point rounding mode.
+-------------------------------------------------------------------------------
+*/
+extern !!!int8 float_rounding_mode;
+enum {
+ float_round_nearest_even = 0,
+ float_round_to_zero = 1,
+ float_round_down = 2,
+ float_round_up = 3
+};
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE floating-point exception flags.
+-------------------------------------------------------------------------------
+*/
+extern !!!int8 float_exception_flags;
+enum {
+ float_flag_inexact = 1,
+ float_flag_underflow = 2,
+ float_flag_overflow = 4,
+ float_flag_divbyzero = 8,
+ float_flag_invalid = 16
+};
+
+/*
+-------------------------------------------------------------------------------
+Routine to raise any or all of the software IEC/IEEE floating-point
+exception flags.
+-------------------------------------------------------------------------------
+*/
+void float_raise( !!!int8 );
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE integer-to-floating-point conversion routines.
+-------------------------------------------------------------------------------
+*/
+float32 int32_to_float32( !!!int32 );
+float64 int32_to_float64( !!!int32 );
+#ifdef FLOATX80
+floatx80 int32_to_floatx80( !!!int32 );
+#endif
+#ifdef FLOAT128
+float128 int32_to_float128( !!!int32 );
+#endif
+float32 int64_to_float32( !!!int64 );
+float64 int64_to_float64( !!!int64 );
+#ifdef FLOATX80
+floatx80 int64_to_floatx80( !!!int64 );
+#endif
+#ifdef FLOAT128
+float128 int64_to_float128( !!!int64 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE single-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+!!!int32 float32_to_int32( float32 );
+!!!int32 float32_to_int32_round_to_zero( float32 );
+!!!int64 float32_to_int64( float32 );
+!!!int64 float32_to_int64_round_to_zero( float32 );
+float64 float32_to_float64( float32 );
+#ifdef FLOATX80
+floatx80 float32_to_floatx80( float32 );
+#endif
+#ifdef FLOAT128
+float128 float32_to_float128( float32 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE single-precision operations.
+-------------------------------------------------------------------------------
+*/
+float32 float32_round_to_int( float32 );
+float32 float32_add( float32, float32 );
+float32 float32_sub( float32, float32 );
+float32 float32_mul( float32, float32 );
+float32 float32_div( float32, float32 );
+float32 float32_rem( float32, float32 );
+float32 float32_sqrt( float32 );
+!!!flag float32_eq( float32, float32 );
+!!!flag float32_le( float32, float32 );
+!!!flag float32_lt( float32, float32 );
+!!!flag float32_eq_signaling( float32, float32 );
+!!!flag float32_le_quiet( float32, float32 );
+!!!flag float32_lt_quiet( float32, float32 );
+!!!flag float32_is_signaling_nan( float32 );
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE double-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+!!!int32 float64_to_int32( float64 );
+!!!int32 float64_to_int32_round_to_zero( float64 );
+!!!int64 float64_to_int64( float64 );
+!!!int64 float64_to_int64_round_to_zero( float64 );
+float32 float64_to_float32( float64 );
+#ifdef FLOATX80
+floatx80 float64_to_floatx80( float64 );
+#endif
+#ifdef FLOAT128
+float128 float64_to_float128( float64 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE double-precision operations.
+-------------------------------------------------------------------------------
+*/
+float64 float64_round_to_int( float64 );
+float64 float64_add( float64, float64 );
+float64 float64_sub( float64, float64 );
+float64 float64_mul( float64, float64 );
+float64 float64_div( float64, float64 );
+float64 float64_rem( float64, float64 );
+float64 float64_sqrt( float64 );
+!!!flag float64_eq( float64, float64 );
+!!!flag float64_le( float64, float64 );
+!!!flag float64_lt( float64, float64 );
+!!!flag float64_eq_signaling( float64, float64 );
+!!!flag float64_le_quiet( float64, float64 );
+!!!flag float64_lt_quiet( float64, float64 );
+!!!flag float64_is_signaling_nan( float64 );
+
+#ifdef FLOATX80
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+!!!int32 floatx80_to_int32( floatx80 );
+!!!int32 floatx80_to_int32_round_to_zero( floatx80 );
+!!!int64 floatx80_to_int64( floatx80 );
+!!!int64 floatx80_to_int64_round_to_zero( floatx80 );
+float32 floatx80_to_float32( floatx80 );
+float64 floatx80_to_float64( floatx80 );
+#ifdef FLOAT128
+float128 floatx80_to_float128( floatx80 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision rounding precision. Valid
+values are 32, 64, and 80.
+-------------------------------------------------------------------------------
+*/
+extern !!!int8 floatx80_rounding_precision;
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE extended double-precision operations.
+-------------------------------------------------------------------------------
+*/
+floatx80 floatx80_round_to_int( floatx80 );
+floatx80 floatx80_add( floatx80, floatx80 );
+floatx80 floatx80_sub( floatx80, floatx80 );
+floatx80 floatx80_mul( floatx80, floatx80 );
+floatx80 floatx80_div( floatx80, floatx80 );
+floatx80 floatx80_rem( floatx80, floatx80 );
+floatx80 floatx80_sqrt( floatx80 );
+!!!flag floatx80_eq( floatx80, floatx80 );
+!!!flag floatx80_le( floatx80, floatx80 );
+!!!flag floatx80_lt( floatx80, floatx80 );
+!!!flag floatx80_eq_signaling( floatx80, floatx80 );
+!!!flag floatx80_le_quiet( floatx80, floatx80 );
+!!!flag floatx80_lt_quiet( floatx80, floatx80 );
+!!!flag floatx80_is_signaling_nan( floatx80 );
+
+#endif
+
+#ifdef FLOAT128
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE quadruple-precision conversion routines.
+-------------------------------------------------------------------------------
+*/
+!!!int32 float128_to_int32( float128 );
+!!!int32 float128_to_int32_round_to_zero( float128 );
+!!!int64 float128_to_int64( float128 );
+!!!int64 float128_to_int64_round_to_zero( float128 );
+float32 float128_to_float32( float128 );
+float64 float128_to_float64( float128 );
+#ifdef FLOATX80
+floatx80 float128_to_floatx80( float128 );
+#endif
+
+/*
+-------------------------------------------------------------------------------
+Software IEC/IEEE quadruple-precision operations.
+-------------------------------------------------------------------------------
+*/
+float128 float128_round_to_int( float128 );
+float128 float128_add( float128, float128 );
+float128 float128_sub( float128, float128 );
+float128 float128_mul( float128, float128 );
+float128 float128_div( float128, float128 );
+float128 float128_rem( float128, float128 );
+float128 float128_sqrt( float128 );
+!!!flag float128_eq( float128, float128 );
+!!!flag float128_le( float128, float128 );
+!!!flag float128_lt( float128, float128 );
+!!!flag float128_eq_signaling( float128, float128 );
+!!!flag float128_le_quiet( float128, float128 );
+!!!flag float128_lt_quiet( float128, float128 );
+!!!flag float128_is_signaling_nan( float128 );
+
+#endif
+
diff --git a/lib/libc/softfloat/timesoftfloat.c b/lib/libc/softfloat/timesoftfloat.c
new file mode 100644
index 0000000..98b6ba2
--- /dev/null
+++ b/lib/libc/softfloat/timesoftfloat.c
@@ -0,0 +1,2639 @@
+/* $NetBSD: timesoftfloat.c,v 1.1 2000/06/06 08:15:11 bjh21 Exp $ */
+
+/*
+===============================================================================
+
+This C source file is part of the SoftFloat IEC/IEEE Floating-point
+Arithmetic Package, Release 2a.
+
+Written by John R. Hauser. This work was made possible in part by the
+International Computer Science Institute, located at Suite 600, 1947 Center
+Street, Berkeley, California 94704. Funding was partially provided by the
+National Science Foundation under grant MIP-9311980. The original version
+of this code was written as part of a project to build a fixed-point vector
+processor in collaboration with the University of California at Berkeley,
+overseen by Profs. Nelson Morgan and John Wawrzynek. More information
+is available through the Web page `http://HTTP.CS.Berkeley.EDU/~jhauser/
+arithmetic/SoftFloat.html'.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+Derivative works are acceptable, even for commercial purposes, so long as
+(1) they include prominent notice that the work is derivative, and (2) they
+include prominent notice akin to these four paragraphs for those parts of
+this code that are retained.
+
+===============================================================================
+*/
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdio.h>
+#include <time.h>
+#include "milieu.h"
+#include "softfloat.h"
+
+enum {
+ minIterations = 1000
+};
+
+static void fail( const char *message, ... )
+{
+ va_list varArgs;
+
+ fputs( "timesoftfloat: ", stderr );
+ va_start( varArgs, message );
+ vfprintf( stderr, message, varArgs );
+ va_end( varArgs );
+ fputs( ".\n", stderr );
+ exit( EXIT_FAILURE );
+
+}
+
+static char *functionName;
+static char *roundingPrecisionName, *roundingModeName, *tininessModeName;
+
+static void reportTime( int32 count, long clocks )
+{
+
+ printf(
+ "%8.1f kops/s: %s",
+ ( count / ( ( (float) clocks ) / CLOCKS_PER_SEC ) ) / 1000,
+ functionName
+ );
+ if ( roundingModeName ) {
+ if ( roundingPrecisionName ) {
+ fputs( ", precision ", stdout );
+ fputs( roundingPrecisionName, stdout );
+ }
+ fputs( ", rounding ", stdout );
+ fputs( roundingModeName, stdout );
+ if ( tininessModeName ) {
+ fputs( ", tininess ", stdout );
+ fputs( tininessModeName, stdout );
+ fputs( " rounding", stdout );
+ }
+ }
+ fputc( '\n', stdout );
+
+}
+
+enum {
+ numInputs_int32 = 32
+};
+
+static const int32 inputs_int32[ numInputs_int32 ] = {
+ 0xFFFFBB79, 0x405CF80F, 0x00000000, 0xFFFFFD04,
+ 0xFFF20002, 0x0C8EF795, 0xF00011FF, 0x000006CA,
+ 0x00009BFE, 0xFF4862E3, 0x9FFFEFFE, 0xFFFFFFB7,
+ 0x0BFF7FFF, 0x0000F37A, 0x0011DFFE, 0x00000006,
+ 0xFFF02006, 0xFFFFF7D1, 0x10200003, 0xDE8DF765,
+ 0x00003E02, 0x000019E8, 0x0008FFFE, 0xFFFFFB5C,
+ 0xFFDF7FFE, 0x07C42FBF, 0x0FFFE3FF, 0x040B9F13,
+ 0xBFFFFFF8, 0x0001BF56, 0x000017F6, 0x000A908A
+};
+
+static void time_a_int32_z_float32( float32 function( int32 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_int32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_int32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_a_int32_z_float64( float64 function( int32 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_int32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_int32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#ifdef FLOATX80
+
+static void time_a_int32_z_floatx80( floatx80 function( int32 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_int32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_int32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+static void time_a_int32_z_float128( float128 function( int32 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_int32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_int32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int32 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#endif
+
+enum {
+ numInputs_int64 = 32
+};
+
+static const int64 inputs_int64[ numInputs_int64 ] = {
+ LIT64( 0xFBFFC3FFFFFFFFFF ),
+ LIT64( 0x0000000003C589BC ),
+ LIT64( 0x00000000400013FE ),
+ LIT64( 0x0000000000186171 ),
+ LIT64( 0xFFFFFFFFFFFEFBFA ),
+ LIT64( 0xFFFFFD79E6DFFC73 ),
+ LIT64( 0x0000000010001DFF ),
+ LIT64( 0xDD1A0F0C78513710 ),
+ LIT64( 0xFFFF83FFFFFEFFFE ),
+ LIT64( 0x00756EBD1AD0C1C7 ),
+ LIT64( 0x0003FDFFFFFFFFBE ),
+ LIT64( 0x0007D0FB2C2CA951 ),
+ LIT64( 0x0007FC0007FFFFFE ),
+ LIT64( 0x0000001F942B18BB ),
+ LIT64( 0x0000080101FFFFFE ),
+ LIT64( 0xFFFFFFFFFFFF0978 ),
+ LIT64( 0x000000000008BFFF ),
+ LIT64( 0x0000000006F5AF08 ),
+ LIT64( 0xFFDEFF7FFFFFFFFE ),
+ LIT64( 0x0000000000000003 ),
+ LIT64( 0x3FFFFFFFFF80007D ),
+ LIT64( 0x0000000000000078 ),
+ LIT64( 0xFFF80000007FDFFD ),
+ LIT64( 0x1BBC775B78016AB0 ),
+ LIT64( 0xFFF9001FFFFFFFFE ),
+ LIT64( 0xFFFD4767AB98E43F ),
+ LIT64( 0xFFFFFEFFFE00001E ),
+ LIT64( 0xFFFFFFFFFFF04EFD ),
+ LIT64( 0x07FFFFFFFFFFF7FF ),
+ LIT64( 0xFFFC9EAA38F89050 ),
+ LIT64( 0x00000020FBFFFFFE ),
+ LIT64( 0x0000099AE6455357 )
+};
+
+static void time_a_int64_z_float32( float32 function( int64 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_int64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_int64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_a_int64_z_float64( float64 function( int64 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_int64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_int64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#ifdef FLOATX80
+
+static void time_a_int64_z_floatx80( floatx80 function( int64 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_int64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_int64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+static void time_a_int64_z_float128( float128 function( int64 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_int64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_int64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_int64 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#endif
+
+enum {
+ numInputs_float32 = 32
+};
+
+static const float32 inputs_float32[ numInputs_float32 ] = {
+ 0x4EFA0000, 0xC1D0B328, 0x80000000, 0x3E69A31E,
+ 0xAF803EFF, 0x3F800000, 0x17BF8000, 0xE74A301A,
+ 0x4E010003, 0x7EE3C75D, 0xBD803FE0, 0xBFFEFF00,
+ 0x7981F800, 0x431FFFFC, 0xC100C000, 0x3D87EFFF,
+ 0x4103FEFE, 0xBC000007, 0xBF01F7FF, 0x4E6C6B5C,
+ 0xC187FFFE, 0xC58B9F13, 0x4F88007F, 0xDF004007,
+ 0xB7FFD7FE, 0x7E8001FB, 0x46EFFBFF, 0x31C10000,
+ 0xDB428661, 0x33F89B1F, 0xA3BFEFFF, 0x537BFFBE
+};
+
+static void time_a_float32_z_int32( int32 function( float32 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_float32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_float32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_a_float32_z_int64( int64 function( float32 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_float32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_float32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_a_float32_z_float64( float64 function( float32 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_float32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_float32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#ifdef FLOATX80
+
+static void time_a_float32_z_floatx80( floatx80 function( float32 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_float32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_float32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+static void time_a_float32_z_float128( float128 function( float32 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_float32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_float32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#endif
+
+static void time_az_float32( float32 function( float32 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_float32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_float32[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_ab_float32_z_flag( flag function( float32, float32 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNumA, inputNumB;
+
+ count = 0;
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function(
+ inputs_float32[ inputNumA ], inputs_float32[ inputNumB ] );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_float32 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_float32 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function(
+ inputs_float32[ inputNumA ], inputs_float32[ inputNumB ] );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_float32 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_float32 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_abz_float32( float32 function( float32, float32 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNumA, inputNumB;
+
+ count = 0;
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function(
+ inputs_float32[ inputNumA ], inputs_float32[ inputNumB ] );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_float32 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_float32 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function(
+ inputs_float32[ inputNumA ], inputs_float32[ inputNumB ] );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_float32 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_float32 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static const float32 inputs_float32_pos[ numInputs_float32 ] = {
+ 0x4EFA0000, 0x41D0B328, 0x00000000, 0x3E69A31E,
+ 0x2F803EFF, 0x3F800000, 0x17BF8000, 0x674A301A,
+ 0x4E010003, 0x7EE3C75D, 0x3D803FE0, 0x3FFEFF00,
+ 0x7981F800, 0x431FFFFC, 0x4100C000, 0x3D87EFFF,
+ 0x4103FEFE, 0x3C000007, 0x3F01F7FF, 0x4E6C6B5C,
+ 0x4187FFFE, 0x458B9F13, 0x4F88007F, 0x5F004007,
+ 0x37FFD7FE, 0x7E8001FB, 0x46EFFBFF, 0x31C10000,
+ 0x5B428661, 0x33F89B1F, 0x23BFEFFF, 0x537BFFBE
+};
+
+static void time_az_float32_pos( float32 function( float32 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_float32_pos[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_float32_pos[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float32 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+enum {
+ numInputs_float64 = 32
+};
+
+static const float64 inputs_float64[ numInputs_float64 ] = {
+ LIT64( 0x422FFFC008000000 ),
+ LIT64( 0xB7E0000480000000 ),
+ LIT64( 0xF3FD2546120B7935 ),
+ LIT64( 0x3FF0000000000000 ),
+ LIT64( 0xCE07F766F09588D6 ),
+ LIT64( 0x8000000000000000 ),
+ LIT64( 0x3FCE000400000000 ),
+ LIT64( 0x8313B60F0032BED8 ),
+ LIT64( 0xC1EFFFFFC0002000 ),
+ LIT64( 0x3FB3C75D224F2B0F ),
+ LIT64( 0x7FD00000004000FF ),
+ LIT64( 0xA12FFF8000001FFF ),
+ LIT64( 0x3EE0000000FE0000 ),
+ LIT64( 0x0010000080000004 ),
+ LIT64( 0x41CFFFFE00000020 ),
+ LIT64( 0x40303FFFFFFFFFFD ),
+ LIT64( 0x3FD000003FEFFFFF ),
+ LIT64( 0xBFD0000010000000 ),
+ LIT64( 0xB7FC6B5C16CA55CF ),
+ LIT64( 0x413EEB940B9D1301 ),
+ LIT64( 0xC7E00200001FFFFF ),
+ LIT64( 0x47F00021FFFFFFFE ),
+ LIT64( 0xBFFFFFFFF80000FF ),
+ LIT64( 0xC07FFFFFE00FFFFF ),
+ LIT64( 0x001497A63740C5E8 ),
+ LIT64( 0xC4BFFFE0001FFFFF ),
+ LIT64( 0x96FFDFFEFFFFFFFF ),
+ LIT64( 0x403FC000000001FE ),
+ LIT64( 0xFFD00000000001F6 ),
+ LIT64( 0x0640400002000000 ),
+ LIT64( 0x479CEE1E4F789FE0 ),
+ LIT64( 0xC237FFFFFFFFFDFE )
+};
+
+static void time_a_float64_z_int32( int32 function( float64 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_float64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_float64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_a_float64_z_int64( int64 function( float64 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_float64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_float64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_a_float64_z_float32( float32 function( float64 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_float64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_float64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#ifdef FLOATX80
+
+static void time_a_float64_z_floatx80( floatx80 function( float64 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_float64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_float64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+static void time_a_float64_z_float128( float128 function( float64 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_float64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_float64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#endif
+
+static void time_az_float64( float64 function( float64 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_float64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_float64[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_ab_float64_z_flag( flag function( float64, float64 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNumA, inputNumB;
+
+ count = 0;
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function(
+ inputs_float64[ inputNumA ], inputs_float64[ inputNumB ] );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_float64 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_float64 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function(
+ inputs_float64[ inputNumA ], inputs_float64[ inputNumB ] );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_float64 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_float64 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_abz_float64( float64 function( float64, float64 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNumA, inputNumB;
+
+ count = 0;
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function(
+ inputs_float64[ inputNumA ], inputs_float64[ inputNumB ] );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_float64 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_float64 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function(
+ inputs_float64[ inputNumA ], inputs_float64[ inputNumB ] );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_float64 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_float64 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static const float64 inputs_float64_pos[ numInputs_float64 ] = {
+ LIT64( 0x422FFFC008000000 ),
+ LIT64( 0x37E0000480000000 ),
+ LIT64( 0x73FD2546120B7935 ),
+ LIT64( 0x3FF0000000000000 ),
+ LIT64( 0x4E07F766F09588D6 ),
+ LIT64( 0x0000000000000000 ),
+ LIT64( 0x3FCE000400000000 ),
+ LIT64( 0x0313B60F0032BED8 ),
+ LIT64( 0x41EFFFFFC0002000 ),
+ LIT64( 0x3FB3C75D224F2B0F ),
+ LIT64( 0x7FD00000004000FF ),
+ LIT64( 0x212FFF8000001FFF ),
+ LIT64( 0x3EE0000000FE0000 ),
+ LIT64( 0x0010000080000004 ),
+ LIT64( 0x41CFFFFE00000020 ),
+ LIT64( 0x40303FFFFFFFFFFD ),
+ LIT64( 0x3FD000003FEFFFFF ),
+ LIT64( 0x3FD0000010000000 ),
+ LIT64( 0x37FC6B5C16CA55CF ),
+ LIT64( 0x413EEB940B9D1301 ),
+ LIT64( 0x47E00200001FFFFF ),
+ LIT64( 0x47F00021FFFFFFFE ),
+ LIT64( 0x3FFFFFFFF80000FF ),
+ LIT64( 0x407FFFFFE00FFFFF ),
+ LIT64( 0x001497A63740C5E8 ),
+ LIT64( 0x44BFFFE0001FFFFF ),
+ LIT64( 0x16FFDFFEFFFFFFFF ),
+ LIT64( 0x403FC000000001FE ),
+ LIT64( 0x7FD00000000001F6 ),
+ LIT64( 0x0640400002000000 ),
+ LIT64( 0x479CEE1E4F789FE0 ),
+ LIT64( 0x4237FFFFFFFFFDFE )
+};
+
+static void time_az_float64_pos( float64 function( float64 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ function( inputs_float64_pos[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ function( inputs_float64_pos[ inputNum ] );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float64 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#ifdef FLOATX80
+
+enum {
+ numInputs_floatx80 = 32
+};
+
+static const struct {
+ bits16 high;
+ bits64 low;
+} inputs_floatx80[ numInputs_floatx80 ] = {
+ { 0xC03F, LIT64( 0xA9BE15A19C1E8B62 ) },
+ { 0x8000, LIT64( 0x0000000000000000 ) },
+ { 0x75A8, LIT64( 0xE59591E4788957A5 ) },
+ { 0xBFFF, LIT64( 0xFFF0000000000040 ) },
+ { 0x0CD8, LIT64( 0xFC000000000007FE ) },
+ { 0x43BA, LIT64( 0x99A4000000000000 ) },
+ { 0x3FFF, LIT64( 0x8000000000000000 ) },
+ { 0x4081, LIT64( 0x94FBF1BCEB5545F0 ) },
+ { 0x403E, LIT64( 0xFFF0000000002000 ) },
+ { 0x3FFE, LIT64( 0xC860E3C75D224F28 ) },
+ { 0x407E, LIT64( 0xFC00000FFFFFFFFE ) },
+ { 0x737A, LIT64( 0x800000007FFDFFFE ) },
+ { 0x4044, LIT64( 0xFFFFFF80000FFFFF ) },
+ { 0xBBFE, LIT64( 0x8000040000001FFE ) },
+ { 0xC002, LIT64( 0xFF80000000000020 ) },
+ { 0xDE8D, LIT64( 0xFFFFFFFFFFE00004 ) },
+ { 0xC004, LIT64( 0x8000000000003FFB ) },
+ { 0x407F, LIT64( 0x800000000003FFFE ) },
+ { 0xC000, LIT64( 0xA459EE6A5C16CA55 ) },
+ { 0x8003, LIT64( 0xC42CBF7399AEEB94 ) },
+ { 0xBF7F, LIT64( 0xF800000000000006 ) },
+ { 0xC07F, LIT64( 0xBF56BE8871F28FEA ) },
+ { 0xC07E, LIT64( 0xFFFF77FFFFFFFFFE ) },
+ { 0xADC9, LIT64( 0x8000000FFFFFFFDE ) },
+ { 0xC001, LIT64( 0xEFF7FFFFFFFFFFFF ) },
+ { 0x4001, LIT64( 0xBE84F30125C497A6 ) },
+ { 0xC06B, LIT64( 0xEFFFFFFFFFFFFFFF ) },
+ { 0x4080, LIT64( 0xFFFFFFFFBFFFFFFF ) },
+ { 0x87E9, LIT64( 0x81FFFFFFFFFFFBFF ) },
+ { 0xA63F, LIT64( 0x801FFFFFFEFFFFFE ) },
+ { 0x403C, LIT64( 0x801FFFFFFFF7FFFF ) },
+ { 0x4018, LIT64( 0x8000000000080003 ) }
+};
+
+static void time_a_floatx80_z_int32( int32 function( floatx80 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+ floatx80 a;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_floatx80[ inputNum ].low;
+ a.high = inputs_floatx80[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_floatx80[ inputNum ].low;
+ a.high = inputs_floatx80[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_a_floatx80_z_int64( int64 function( floatx80 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+ floatx80 a;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_floatx80[ inputNum ].low;
+ a.high = inputs_floatx80[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_floatx80[ inputNum ].low;
+ a.high = inputs_floatx80[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_a_floatx80_z_float32( float32 function( floatx80 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+ floatx80 a;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_floatx80[ inputNum ].low;
+ a.high = inputs_floatx80[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_floatx80[ inputNum ].low;
+ a.high = inputs_floatx80[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_a_floatx80_z_float64( float64 function( floatx80 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+ floatx80 a;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_floatx80[ inputNum ].low;
+ a.high = inputs_floatx80[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_floatx80[ inputNum ].low;
+ a.high = inputs_floatx80[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#ifdef FLOAT128
+
+static void time_a_floatx80_z_float128( float128 function( floatx80 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+ floatx80 a;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_floatx80[ inputNum ].low;
+ a.high = inputs_floatx80[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_floatx80[ inputNum ].low;
+ a.high = inputs_floatx80[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#endif
+
+static void time_az_floatx80( floatx80 function( floatx80 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+ floatx80 a;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_floatx80[ inputNum ].low;
+ a.high = inputs_floatx80[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_floatx80[ inputNum ].low;
+ a.high = inputs_floatx80[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_ab_floatx80_z_flag( flag function( floatx80, floatx80 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNumA, inputNumB;
+ floatx80 a, b;
+
+ count = 0;
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_floatx80[ inputNumA ].low;
+ a.high = inputs_floatx80[ inputNumA ].high;
+ b.low = inputs_floatx80[ inputNumB ].low;
+ b.high = inputs_floatx80[ inputNumB ].high;
+ function( a, b );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_floatx80 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_floatx80[ inputNumA ].low;
+ a.high = inputs_floatx80[ inputNumA ].high;
+ b.low = inputs_floatx80[ inputNumB ].low;
+ b.high = inputs_floatx80[ inputNumB ].high;
+ function( a, b );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_floatx80 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_abz_floatx80( floatx80 function( floatx80, floatx80 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNumA, inputNumB;
+ floatx80 a, b;
+
+ count = 0;
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_floatx80[ inputNumA ].low;
+ a.high = inputs_floatx80[ inputNumA ].high;
+ b.low = inputs_floatx80[ inputNumB ].low;
+ b.high = inputs_floatx80[ inputNumB ].high;
+ function( a, b );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_floatx80 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_floatx80[ inputNumA ].low;
+ a.high = inputs_floatx80[ inputNumA ].high;
+ b.low = inputs_floatx80[ inputNumB ].low;
+ b.high = inputs_floatx80[ inputNumB ].high;
+ function( a, b );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_floatx80 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static const struct {
+ bits16 high;
+ bits64 low;
+} inputs_floatx80_pos[ numInputs_floatx80 ] = {
+ { 0x403F, LIT64( 0xA9BE15A19C1E8B62 ) },
+ { 0x0000, LIT64( 0x0000000000000000 ) },
+ { 0x75A8, LIT64( 0xE59591E4788957A5 ) },
+ { 0x3FFF, LIT64( 0xFFF0000000000040 ) },
+ { 0x0CD8, LIT64( 0xFC000000000007FE ) },
+ { 0x43BA, LIT64( 0x99A4000000000000 ) },
+ { 0x3FFF, LIT64( 0x8000000000000000 ) },
+ { 0x4081, LIT64( 0x94FBF1BCEB5545F0 ) },
+ { 0x403E, LIT64( 0xFFF0000000002000 ) },
+ { 0x3FFE, LIT64( 0xC860E3C75D224F28 ) },
+ { 0x407E, LIT64( 0xFC00000FFFFFFFFE ) },
+ { 0x737A, LIT64( 0x800000007FFDFFFE ) },
+ { 0x4044, LIT64( 0xFFFFFF80000FFFFF ) },
+ { 0x3BFE, LIT64( 0x8000040000001FFE ) },
+ { 0x4002, LIT64( 0xFF80000000000020 ) },
+ { 0x5E8D, LIT64( 0xFFFFFFFFFFE00004 ) },
+ { 0x4004, LIT64( 0x8000000000003FFB ) },
+ { 0x407F, LIT64( 0x800000000003FFFE ) },
+ { 0x4000, LIT64( 0xA459EE6A5C16CA55 ) },
+ { 0x0003, LIT64( 0xC42CBF7399AEEB94 ) },
+ { 0x3F7F, LIT64( 0xF800000000000006 ) },
+ { 0x407F, LIT64( 0xBF56BE8871F28FEA ) },
+ { 0x407E, LIT64( 0xFFFF77FFFFFFFFFE ) },
+ { 0x2DC9, LIT64( 0x8000000FFFFFFFDE ) },
+ { 0x4001, LIT64( 0xEFF7FFFFFFFFFFFF ) },
+ { 0x4001, LIT64( 0xBE84F30125C497A6 ) },
+ { 0x406B, LIT64( 0xEFFFFFFFFFFFFFFF ) },
+ { 0x4080, LIT64( 0xFFFFFFFFBFFFFFFF ) },
+ { 0x07E9, LIT64( 0x81FFFFFFFFFFFBFF ) },
+ { 0x263F, LIT64( 0x801FFFFFFEFFFFFE ) },
+ { 0x403C, LIT64( 0x801FFFFFFFF7FFFF ) },
+ { 0x4018, LIT64( 0x8000000000080003 ) }
+};
+
+static void time_az_floatx80_pos( floatx80 function( floatx80 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+ floatx80 a;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_floatx80_pos[ inputNum ].low;
+ a.high = inputs_floatx80_pos[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_floatx80_pos[ inputNum ].low;
+ a.high = inputs_floatx80_pos[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_floatx80 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#endif
+
+#ifdef FLOAT128
+
+enum {
+ numInputs_float128 = 32
+};
+
+static const struct {
+ bits64 high, low;
+} inputs_float128[ numInputs_float128 ] = {
+ { LIT64( 0x3FDA200000100000 ), LIT64( 0x0000000000000000 ) },
+ { LIT64( 0x3FFF000000000000 ), LIT64( 0x0000000000000000 ) },
+ { LIT64( 0x85F14776190C8306 ), LIT64( 0xD8715F4E3D54BB92 ) },
+ { LIT64( 0xF2B00000007FFFFF ), LIT64( 0xFFFFFFFFFFF7FFFF ) },
+ { LIT64( 0x8000000000000000 ), LIT64( 0x0000000000000000 ) },
+ { LIT64( 0xBFFFFFFFFFE00000 ), LIT64( 0x0000008000000000 ) },
+ { LIT64( 0x407F1719CE722F3E ), LIT64( 0xDA6B3FE5FF29425B ) },
+ { LIT64( 0x43FFFF8000000000 ), LIT64( 0x0000000000400000 ) },
+ { LIT64( 0x401E000000000100 ), LIT64( 0x0000000000002000 ) },
+ { LIT64( 0x3FFED71DACDA8E47 ), LIT64( 0x4860E3C75D224F28 ) },
+ { LIT64( 0xBF7ECFC1E90647D1 ), LIT64( 0x7A124FE55623EE44 ) },
+ { LIT64( 0x0DF7007FFFFFFFFF ), LIT64( 0xFFFFFFFFEFFFFFFF ) },
+ { LIT64( 0x3FE5FFEFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFEFFF ) },
+ { LIT64( 0x403FFFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFBFE ) },
+ { LIT64( 0xBFFB2FBF7399AFEB ), LIT64( 0xA459EE6A5C16CA55 ) },
+ { LIT64( 0xBDB8FFFFFFFFFFFC ), LIT64( 0x0000000000000400 ) },
+ { LIT64( 0x3FC8FFDFFFFFFFFF ), LIT64( 0xFFFFFFFFF0000000 ) },
+ { LIT64( 0x3FFBFFFFFFDFFFFF ), LIT64( 0xFFF8000000000000 ) },
+ { LIT64( 0x407043C11737BE84 ), LIT64( 0xDDD58212ADC937F4 ) },
+ { LIT64( 0x8001000000000000 ), LIT64( 0x0000001000000001 ) },
+ { LIT64( 0xC036FFFFFFFFFFFF ), LIT64( 0xFE40000000000000 ) },
+ { LIT64( 0x4002FFFFFE000002 ), LIT64( 0x0000000000000000 ) },
+ { LIT64( 0x4000C3FEDE897773 ), LIT64( 0x326AC4FD8EFBE6DC ) },
+ { LIT64( 0xBFFF0000000FFFFF ), LIT64( 0xFFFFFE0000000000 ) },
+ { LIT64( 0x62C3E502146E426D ), LIT64( 0x43F3CAA0DC7DF1A0 ) },
+ { LIT64( 0xB5CBD32E52BB570E ), LIT64( 0xBCC477CB11C6236C ) },
+ { LIT64( 0xE228FFFFFFC00000 ), LIT64( 0x0000000000000000 ) },
+ { LIT64( 0x3F80000000000000 ), LIT64( 0x0000000080000008 ) },
+ { LIT64( 0xC1AFFFDFFFFFFFFF ), LIT64( 0xFFFC000000000000 ) },
+ { LIT64( 0xC96F000000000000 ), LIT64( 0x00000001FFFBFFFF ) },
+ { LIT64( 0x3DE09BFE7923A338 ), LIT64( 0xBCC8FBBD7CEC1F4F ) },
+ { LIT64( 0x401CFFFFFFFFFFFF ), LIT64( 0xFFFFFFFEFFFFFF80 ) }
+};
+
+static void time_a_float128_z_int32( int32 function( float128 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+ float128 a;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_float128[ inputNum ].low;
+ a.high = inputs_float128[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_float128[ inputNum ].low;
+ a.high = inputs_float128[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_a_float128_z_int64( int64 function( float128 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+ float128 a;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_float128[ inputNum ].low;
+ a.high = inputs_float128[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_float128[ inputNum ].low;
+ a.high = inputs_float128[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_a_float128_z_float32( float32 function( float128 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+ float128 a;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_float128[ inputNum ].low;
+ a.high = inputs_float128[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_float128[ inputNum ].low;
+ a.high = inputs_float128[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_a_float128_z_float64( float64 function( float128 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+ float128 a;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_float128[ inputNum ].low;
+ a.high = inputs_float128[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_float128[ inputNum ].low;
+ a.high = inputs_float128[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#ifdef FLOATX80
+
+static void time_a_float128_z_floatx80( floatx80 function( float128 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+ float128 a;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_float128[ inputNum ].low;
+ a.high = inputs_float128[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_float128[ inputNum ].low;
+ a.high = inputs_float128[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#endif
+
+static void time_az_float128( float128 function( float128 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+ float128 a;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_float128[ inputNum ].low;
+ a.high = inputs_float128[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_float128[ inputNum ].low;
+ a.high = inputs_float128[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_ab_float128_z_flag( flag function( float128, float128 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNumA, inputNumB;
+ float128 a, b;
+
+ count = 0;
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_float128[ inputNumA ].low;
+ a.high = inputs_float128[ inputNumA ].high;
+ b.low = inputs_float128[ inputNumB ].low;
+ b.high = inputs_float128[ inputNumB ].high;
+ function( a, b );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_float128 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_float128 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_float128[ inputNumA ].low;
+ a.high = inputs_float128[ inputNumA ].high;
+ b.low = inputs_float128[ inputNumB ].low;
+ b.high = inputs_float128[ inputNumB ].high;
+ function( a, b );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_float128 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_float128 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static void time_abz_float128( float128 function( float128, float128 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNumA, inputNumB;
+ float128 a, b;
+
+ count = 0;
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_float128[ inputNumA ].low;
+ a.high = inputs_float128[ inputNumA ].high;
+ b.low = inputs_float128[ inputNumB ].low;
+ b.high = inputs_float128[ inputNumB ].high;
+ function( a, b );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_float128 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_float128 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNumA = 0;
+ inputNumB = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_float128[ inputNumA ].low;
+ a.high = inputs_float128[ inputNumA ].high;
+ b.low = inputs_float128[ inputNumB ].low;
+ b.high = inputs_float128[ inputNumB ].high;
+ function( a, b );
+ inputNumA = ( inputNumA + 1 ) & ( numInputs_float128 - 1 );
+ if ( inputNumA == 0 ) ++inputNumB;
+ inputNumB = ( inputNumB + 1 ) & ( numInputs_float128 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+static const struct {
+ bits64 high, low;
+} inputs_float128_pos[ numInputs_float128 ] = {
+ { LIT64( 0x3FDA200000100000 ), LIT64( 0x0000000000000000 ) },
+ { LIT64( 0x3FFF000000000000 ), LIT64( 0x0000000000000000 ) },
+ { LIT64( 0x05F14776190C8306 ), LIT64( 0xD8715F4E3D54BB92 ) },
+ { LIT64( 0x72B00000007FFFFF ), LIT64( 0xFFFFFFFFFFF7FFFF ) },
+ { LIT64( 0x0000000000000000 ), LIT64( 0x0000000000000000 ) },
+ { LIT64( 0x3FFFFFFFFFE00000 ), LIT64( 0x0000008000000000 ) },
+ { LIT64( 0x407F1719CE722F3E ), LIT64( 0xDA6B3FE5FF29425B ) },
+ { LIT64( 0x43FFFF8000000000 ), LIT64( 0x0000000000400000 ) },
+ { LIT64( 0x401E000000000100 ), LIT64( 0x0000000000002000 ) },
+ { LIT64( 0x3FFED71DACDA8E47 ), LIT64( 0x4860E3C75D224F28 ) },
+ { LIT64( 0x3F7ECFC1E90647D1 ), LIT64( 0x7A124FE55623EE44 ) },
+ { LIT64( 0x0DF7007FFFFFFFFF ), LIT64( 0xFFFFFFFFEFFFFFFF ) },
+ { LIT64( 0x3FE5FFEFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFEFFF ) },
+ { LIT64( 0x403FFFFFFFFFFFFF ), LIT64( 0xFFFFFFFFFFFFFBFE ) },
+ { LIT64( 0x3FFB2FBF7399AFEB ), LIT64( 0xA459EE6A5C16CA55 ) },
+ { LIT64( 0x3DB8FFFFFFFFFFFC ), LIT64( 0x0000000000000400 ) },
+ { LIT64( 0x3FC8FFDFFFFFFFFF ), LIT64( 0xFFFFFFFFF0000000 ) },
+ { LIT64( 0x3FFBFFFFFFDFFFFF ), LIT64( 0xFFF8000000000000 ) },
+ { LIT64( 0x407043C11737BE84 ), LIT64( 0xDDD58212ADC937F4 ) },
+ { LIT64( 0x0001000000000000 ), LIT64( 0x0000001000000001 ) },
+ { LIT64( 0x4036FFFFFFFFFFFF ), LIT64( 0xFE40000000000000 ) },
+ { LIT64( 0x4002FFFFFE000002 ), LIT64( 0x0000000000000000 ) },
+ { LIT64( 0x4000C3FEDE897773 ), LIT64( 0x326AC4FD8EFBE6DC ) },
+ { LIT64( 0x3FFF0000000FFFFF ), LIT64( 0xFFFFFE0000000000 ) },
+ { LIT64( 0x62C3E502146E426D ), LIT64( 0x43F3CAA0DC7DF1A0 ) },
+ { LIT64( 0x35CBD32E52BB570E ), LIT64( 0xBCC477CB11C6236C ) },
+ { LIT64( 0x6228FFFFFFC00000 ), LIT64( 0x0000000000000000 ) },
+ { LIT64( 0x3F80000000000000 ), LIT64( 0x0000000080000008 ) },
+ { LIT64( 0x41AFFFDFFFFFFFFF ), LIT64( 0xFFFC000000000000 ) },
+ { LIT64( 0x496F000000000000 ), LIT64( 0x00000001FFFBFFFF ) },
+ { LIT64( 0x3DE09BFE7923A338 ), LIT64( 0xBCC8FBBD7CEC1F4F ) },
+ { LIT64( 0x401CFFFFFFFFFFFF ), LIT64( 0xFFFFFFFEFFFFFF80 ) }
+};
+
+static void time_az_float128_pos( float128 function( float128 ) )
+{
+ clock_t startClock, endClock;
+ int32 count, i;
+ int8 inputNum;
+ float128 a;
+
+ count = 0;
+ inputNum = 0;
+ startClock = clock();
+ do {
+ for ( i = minIterations; i; --i ) {
+ a.low = inputs_float128_pos[ inputNum ].low;
+ a.high = inputs_float128_pos[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 );
+ }
+ count += minIterations;
+ } while ( clock() - startClock < CLOCKS_PER_SEC );
+ inputNum = 0;
+ startClock = clock();
+ for ( i = count; i; --i ) {
+ a.low = inputs_float128_pos[ inputNum ].low;
+ a.high = inputs_float128_pos[ inputNum ].high;
+ function( a );
+ inputNum = ( inputNum + 1 ) & ( numInputs_float128 - 1 );
+ }
+ endClock = clock();
+ reportTime( count, endClock - startClock );
+
+}
+
+#endif
+
+enum {
+ INT32_TO_FLOAT32 = 1,
+ INT32_TO_FLOAT64,
+#ifdef FLOATX80
+ INT32_TO_FLOATX80,
+#endif
+#ifdef FLOAT128
+ INT32_TO_FLOAT128,
+#endif
+ INT64_TO_FLOAT32,
+ INT64_TO_FLOAT64,
+#ifdef FLOATX80
+ INT64_TO_FLOATX80,
+#endif
+#ifdef FLOAT128
+ INT64_TO_FLOAT128,
+#endif
+ FLOAT32_TO_INT32,
+ FLOAT32_TO_INT32_ROUND_TO_ZERO,
+ FLOAT32_TO_INT64,
+ FLOAT32_TO_INT64_ROUND_TO_ZERO,
+ FLOAT32_TO_FLOAT64,
+#ifdef FLOATX80
+ FLOAT32_TO_FLOATX80,
+#endif
+#ifdef FLOAT128
+ FLOAT32_TO_FLOAT128,
+#endif
+ FLOAT32_ROUND_TO_INT,
+ FLOAT32_ADD,
+ FLOAT32_SUB,
+ FLOAT32_MUL,
+ FLOAT32_DIV,
+ FLOAT32_REM,
+ FLOAT32_SQRT,
+ FLOAT32_EQ,
+ FLOAT32_LE,
+ FLOAT32_LT,
+ FLOAT32_EQ_SIGNALING,
+ FLOAT32_LE_QUIET,
+ FLOAT32_LT_QUIET,
+ FLOAT64_TO_INT32,
+ FLOAT64_TO_INT32_ROUND_TO_ZERO,
+ FLOAT64_TO_INT64,
+ FLOAT64_TO_INT64_ROUND_TO_ZERO,
+ FLOAT64_TO_FLOAT32,
+#ifdef FLOATX80
+ FLOAT64_TO_FLOATX80,
+#endif
+#ifdef FLOAT128
+ FLOAT64_TO_FLOAT128,
+#endif
+ FLOAT64_ROUND_TO_INT,
+ FLOAT64_ADD,
+ FLOAT64_SUB,
+ FLOAT64_MUL,
+ FLOAT64_DIV,
+ FLOAT64_REM,
+ FLOAT64_SQRT,
+ FLOAT64_EQ,
+ FLOAT64_LE,
+ FLOAT64_LT,
+ FLOAT64_EQ_SIGNALING,
+ FLOAT64_LE_QUIET,
+ FLOAT64_LT_QUIET,
+#ifdef FLOATX80
+ FLOATX80_TO_INT32,
+ FLOATX80_TO_INT32_ROUND_TO_ZERO,
+ FLOATX80_TO_INT64,
+ FLOATX80_TO_INT64_ROUND_TO_ZERO,
+ FLOATX80_TO_FLOAT32,
+ FLOATX80_TO_FLOAT64,
+#ifdef FLOAT128
+ FLOATX80_TO_FLOAT128,
+#endif
+ FLOATX80_ROUND_TO_INT,
+ FLOATX80_ADD,
+ FLOATX80_SUB,
+ FLOATX80_MUL,
+ FLOATX80_DIV,
+ FLOATX80_REM,
+ FLOATX80_SQRT,
+ FLOATX80_EQ,
+ FLOATX80_LE,
+ FLOATX80_LT,
+ FLOATX80_EQ_SIGNALING,
+ FLOATX80_LE_QUIET,
+ FLOATX80_LT_QUIET,
+#endif
+#ifdef FLOAT128
+ FLOAT128_TO_INT32,
+ FLOAT128_TO_INT32_ROUND_TO_ZERO,
+ FLOAT128_TO_INT64,
+ FLOAT128_TO_INT64_ROUND_TO_ZERO,
+ FLOAT128_TO_FLOAT32,
+ FLOAT128_TO_FLOAT64,
+#ifdef FLOATX80
+ FLOAT128_TO_FLOATX80,
+#endif
+ FLOAT128_ROUND_TO_INT,
+ FLOAT128_ADD,
+ FLOAT128_SUB,
+ FLOAT128_MUL,
+ FLOAT128_DIV,
+ FLOAT128_REM,
+ FLOAT128_SQRT,
+ FLOAT128_EQ,
+ FLOAT128_LE,
+ FLOAT128_LT,
+ FLOAT128_EQ_SIGNALING,
+ FLOAT128_LE_QUIET,
+ FLOAT128_LT_QUIET,
+#endif
+ NUM_FUNCTIONS
+};
+
+static struct {
+ char *name;
+ int8 numInputs;
+ flag roundingPrecision, roundingMode;
+ flag tininessMode, tininessModeAtReducedPrecision;
+} functions[ NUM_FUNCTIONS ] = {
+ { 0, 0, 0, 0, 0, 0 },
+ { "int32_to_float32", 1, FALSE, TRUE, FALSE, FALSE },
+ { "int32_to_float64", 1, FALSE, FALSE, FALSE, FALSE },
+#ifdef FLOATX80
+ { "int32_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE },
+#endif
+#ifdef FLOAT128
+ { "int32_to_float128", 1, FALSE, FALSE, FALSE, FALSE },
+#endif
+ { "int64_to_float32", 1, FALSE, TRUE, FALSE, FALSE },
+ { "int64_to_float64", 1, FALSE, TRUE, FALSE, FALSE },
+#ifdef FLOATX80
+ { "int64_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE },
+#endif
+#ifdef FLOAT128
+ { "int64_to_float128", 1, FALSE, FALSE, FALSE, FALSE },
+#endif
+ { "float32_to_int32", 1, FALSE, TRUE, FALSE, FALSE },
+ { "float32_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
+ { "float32_to_int64", 1, FALSE, TRUE, FALSE, FALSE },
+ { "float32_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
+ { "float32_to_float64", 1, FALSE, FALSE, FALSE, FALSE },
+#ifdef FLOATX80
+ { "float32_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE },
+#endif
+#ifdef FLOAT128
+ { "float32_to_float128", 1, FALSE, FALSE, FALSE, FALSE },
+#endif
+ { "float32_round_to_int", 1, FALSE, TRUE, FALSE, FALSE },
+ { "float32_add", 2, FALSE, TRUE, FALSE, FALSE },
+ { "float32_sub", 2, FALSE, TRUE, FALSE, FALSE },
+ { "float32_mul", 2, FALSE, TRUE, TRUE, FALSE },
+ { "float32_div", 2, FALSE, TRUE, FALSE, FALSE },
+ { "float32_rem", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float32_sqrt", 1, FALSE, TRUE, FALSE, FALSE },
+ { "float32_eq", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float32_le", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float32_lt", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float32_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float32_le_quiet", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float32_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float64_to_int32", 1, FALSE, TRUE, FALSE, FALSE },
+ { "float64_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
+ { "float64_to_int64", 1, FALSE, TRUE, FALSE, FALSE },
+ { "float64_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
+ { "float64_to_float32", 1, FALSE, TRUE, TRUE, FALSE },
+#ifdef FLOATX80
+ { "float64_to_floatx80", 1, FALSE, FALSE, FALSE, FALSE },
+#endif
+#ifdef FLOAT128
+ { "float64_to_float128", 1, FALSE, FALSE, FALSE, FALSE },
+#endif
+ { "float64_round_to_int", 1, FALSE, TRUE, FALSE, FALSE },
+ { "float64_add", 2, FALSE, TRUE, FALSE, FALSE },
+ { "float64_sub", 2, FALSE, TRUE, FALSE, FALSE },
+ { "float64_mul", 2, FALSE, TRUE, TRUE, FALSE },
+ { "float64_div", 2, FALSE, TRUE, FALSE, FALSE },
+ { "float64_rem", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float64_sqrt", 1, FALSE, TRUE, FALSE, FALSE },
+ { "float64_eq", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float64_le", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float64_lt", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float64_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float64_le_quiet", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float64_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE },
+#ifdef FLOATX80
+ { "floatx80_to_int32", 1, FALSE, TRUE, FALSE, FALSE },
+ { "floatx80_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
+ { "floatx80_to_int64", 1, FALSE, TRUE, FALSE, FALSE },
+ { "floatx80_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
+ { "floatx80_to_float32", 1, FALSE, TRUE, TRUE, FALSE },
+ { "floatx80_to_float64", 1, FALSE, TRUE, TRUE, FALSE },
+#ifdef FLOAT128
+ { "floatx80_to_float128", 1, FALSE, FALSE, FALSE, FALSE },
+#endif
+ { "floatx80_round_to_int", 1, FALSE, TRUE, FALSE, FALSE },
+ { "floatx80_add", 2, TRUE, TRUE, FALSE, TRUE },
+ { "floatx80_sub", 2, TRUE, TRUE, FALSE, TRUE },
+ { "floatx80_mul", 2, TRUE, TRUE, TRUE, TRUE },
+ { "floatx80_div", 2, TRUE, TRUE, FALSE, TRUE },
+ { "floatx80_rem", 2, FALSE, FALSE, FALSE, FALSE },
+ { "floatx80_sqrt", 1, TRUE, TRUE, FALSE, FALSE },
+ { "floatx80_eq", 2, FALSE, FALSE, FALSE, FALSE },
+ { "floatx80_le", 2, FALSE, FALSE, FALSE, FALSE },
+ { "floatx80_lt", 2, FALSE, FALSE, FALSE, FALSE },
+ { "floatx80_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE },
+ { "floatx80_le_quiet", 2, FALSE, FALSE, FALSE, FALSE },
+ { "floatx80_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE },
+#endif
+#ifdef FLOAT128
+ { "float128_to_int32", 1, FALSE, TRUE, FALSE, FALSE },
+ { "float128_to_int32_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
+ { "float128_to_int64", 1, FALSE, TRUE, FALSE, FALSE },
+ { "float128_to_int64_round_to_zero", 1, FALSE, FALSE, FALSE, FALSE },
+ { "float128_to_float32", 1, FALSE, TRUE, TRUE, FALSE },
+ { "float128_to_float64", 1, FALSE, TRUE, TRUE, FALSE },
+#ifdef FLOATX80
+ { "float128_to_floatx80", 1, FALSE, TRUE, TRUE, FALSE },
+#endif
+ { "float128_round_to_int", 1, FALSE, TRUE, FALSE, FALSE },
+ { "float128_add", 2, FALSE, TRUE, FALSE, FALSE },
+ { "float128_sub", 2, FALSE, TRUE, FALSE, FALSE },
+ { "float128_mul", 2, FALSE, TRUE, TRUE, FALSE },
+ { "float128_div", 2, FALSE, TRUE, FALSE, FALSE },
+ { "float128_rem", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float128_sqrt", 1, FALSE, TRUE, FALSE, FALSE },
+ { "float128_eq", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float128_le", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float128_lt", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float128_eq_signaling", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float128_le_quiet", 2, FALSE, FALSE, FALSE, FALSE },
+ { "float128_lt_quiet", 2, FALSE, FALSE, FALSE, FALSE },
+#endif
+};
+
+enum {
+ ROUND_NEAREST_EVEN = 1,
+ ROUND_TO_ZERO,
+ ROUND_DOWN,
+ ROUND_UP,
+ NUM_ROUNDINGMODES
+};
+enum {
+ TININESS_BEFORE_ROUNDING = 1,
+ TININESS_AFTER_ROUNDING,
+ NUM_TININESSMODES
+};
+
+static void
+ timeFunctionVariety(
+ uint8 functionCode,
+ int8 roundingPrecision,
+ int8 roundingMode,
+ int8 tininessMode
+ )
+{
+ uint8 roundingCode;
+ int8 tininessCode;
+
+ functionName = functions[ functionCode ].name;
+ if ( roundingPrecision == 32 ) {
+ roundingPrecisionName = "32";
+ }
+ else if ( roundingPrecision == 64 ) {
+ roundingPrecisionName = "64";
+ }
+ else if ( roundingPrecision == 80 ) {
+ roundingPrecisionName = "80";
+ }
+ else {
+ roundingPrecisionName = 0;
+ }
+#ifdef FLOATX80
+ floatx80_rounding_precision = roundingPrecision;
+#endif
+ switch ( roundingMode ) {
+ case 0:
+ roundingModeName = 0;
+ roundingCode = float_round_nearest_even;
+ break;
+ case ROUND_NEAREST_EVEN:
+ roundingModeName = "nearest_even";
+ roundingCode = float_round_nearest_even;
+ break;
+ case ROUND_TO_ZERO:
+ roundingModeName = "to_zero";
+ roundingCode = float_round_to_zero;
+ break;
+ case ROUND_DOWN:
+ roundingModeName = "down";
+ roundingCode = float_round_down;
+ break;
+ case ROUND_UP:
+ roundingModeName = "up";
+ roundingCode = float_round_up;
+ break;
+ }
+ float_rounding_mode = roundingCode;
+ switch ( tininessMode ) {
+ case 0:
+ tininessModeName = 0;
+ tininessCode = float_tininess_after_rounding;
+ break;
+ case TININESS_BEFORE_ROUNDING:
+ tininessModeName = "before";
+ tininessCode = float_tininess_before_rounding;
+ break;
+ case TININESS_AFTER_ROUNDING:
+ tininessModeName = "after";
+ tininessCode = float_tininess_after_rounding;
+ break;
+ }
+ float_detect_tininess = tininessCode;
+ switch ( functionCode ) {
+ case INT32_TO_FLOAT32:
+ time_a_int32_z_float32( int32_to_float32 );
+ break;
+ case INT32_TO_FLOAT64:
+ time_a_int32_z_float64( int32_to_float64 );
+ break;
+#ifdef FLOATX80
+ case INT32_TO_FLOATX80:
+ time_a_int32_z_floatx80( int32_to_floatx80 );
+ break;
+#endif
+#ifdef FLOAT128
+ case INT32_TO_FLOAT128:
+ time_a_int32_z_float128( int32_to_float128 );
+ break;
+#endif
+ case INT64_TO_FLOAT32:
+ time_a_int64_z_float32( int64_to_float32 );
+ break;
+ case INT64_TO_FLOAT64:
+ time_a_int64_z_float64( int64_to_float64 );
+ break;
+#ifdef FLOATX80
+ case INT64_TO_FLOATX80:
+ time_a_int64_z_floatx80( int64_to_floatx80 );
+ break;
+#endif
+#ifdef FLOAT128
+ case INT64_TO_FLOAT128:
+ time_a_int64_z_float128( int64_to_float128 );
+ break;
+#endif
+ case FLOAT32_TO_INT32:
+ time_a_float32_z_int32( float32_to_int32 );
+ break;
+ case FLOAT32_TO_INT32_ROUND_TO_ZERO:
+ time_a_float32_z_int32( float32_to_int32_round_to_zero );
+ break;
+ case FLOAT32_TO_INT64:
+ time_a_float32_z_int64( float32_to_int64 );
+ break;
+ case FLOAT32_TO_INT64_ROUND_TO_ZERO:
+ time_a_float32_z_int64( float32_to_int64_round_to_zero );
+ break;
+ case FLOAT32_TO_FLOAT64:
+ time_a_float32_z_float64( float32_to_float64 );
+ break;
+#ifdef FLOATX80
+ case FLOAT32_TO_FLOATX80:
+ time_a_float32_z_floatx80( float32_to_floatx80 );
+ break;
+#endif
+#ifdef FLOAT128
+ case FLOAT32_TO_FLOAT128:
+ time_a_float32_z_float128( float32_to_float128 );
+ break;
+#endif
+ case FLOAT32_ROUND_TO_INT:
+ time_az_float32( float32_round_to_int );
+ break;
+ case FLOAT32_ADD:
+ time_abz_float32( float32_add );
+ break;
+ case FLOAT32_SUB:
+ time_abz_float32( float32_sub );
+ break;
+ case FLOAT32_MUL:
+ time_abz_float32( float32_mul );
+ break;
+ case FLOAT32_DIV:
+ time_abz_float32( float32_div );
+ break;
+ case FLOAT32_REM:
+ time_abz_float32( float32_rem );
+ break;
+ case FLOAT32_SQRT:
+ time_az_float32_pos( float32_sqrt );
+ break;
+ case FLOAT32_EQ:
+ time_ab_float32_z_flag( float32_eq );
+ break;
+ case FLOAT32_LE:
+ time_ab_float32_z_flag( float32_le );
+ break;
+ case FLOAT32_LT:
+ time_ab_float32_z_flag( float32_lt );
+ break;
+ case FLOAT32_EQ_SIGNALING:
+ time_ab_float32_z_flag( float32_eq_signaling );
+ break;
+ case FLOAT32_LE_QUIET:
+ time_ab_float32_z_flag( float32_le_quiet );
+ break;
+ case FLOAT32_LT_QUIET:
+ time_ab_float32_z_flag( float32_lt_quiet );
+ break;
+ case FLOAT64_TO_INT32:
+ time_a_float64_z_int32( float64_to_int32 );
+ break;
+ case FLOAT64_TO_INT32_ROUND_TO_ZERO:
+ time_a_float64_z_int32( float64_to_int32_round_to_zero );
+ break;
+ case FLOAT64_TO_INT64:
+ time_a_float64_z_int64( float64_to_int64 );
+ break;
+ case FLOAT64_TO_INT64_ROUND_TO_ZERO:
+ time_a_float64_z_int64( float64_to_int64_round_to_zero );
+ break;
+ case FLOAT64_TO_FLOAT32:
+ time_a_float64_z_float32( float64_to_float32 );
+ break;
+#ifdef FLOATX80
+ case FLOAT64_TO_FLOATX80:
+ time_a_float64_z_floatx80( float64_to_floatx80 );
+ break;
+#endif
+#ifdef FLOAT128
+ case FLOAT64_TO_FLOAT128:
+ time_a_float64_z_float128( float64_to_float128 );
+ break;
+#endif
+ case FLOAT64_ROUND_TO_INT:
+ time_az_float64( float64_round_to_int );
+ break;
+ case FLOAT64_ADD:
+ time_abz_float64( float64_add );
+ break;
+ case FLOAT64_SUB:
+ time_abz_float64( float64_sub );
+ break;
+ case FLOAT64_MUL:
+ time_abz_float64( float64_mul );
+ break;
+ case FLOAT64_DIV:
+ time_abz_float64( float64_div );
+ break;
+ case FLOAT64_REM:
+ time_abz_float64( float64_rem );
+ break;
+ case FLOAT64_SQRT:
+ time_az_float64_pos( float64_sqrt );
+ break;
+ case FLOAT64_EQ:
+ time_ab_float64_z_flag( float64_eq );
+ break;
+ case FLOAT64_LE:
+ time_ab_float64_z_flag( float64_le );
+ break;
+ case FLOAT64_LT:
+ time_ab_float64_z_flag( float64_lt );
+ break;
+ case FLOAT64_EQ_SIGNALING:
+ time_ab_float64_z_flag( float64_eq_signaling );
+ break;
+ case FLOAT64_LE_QUIET:
+ time_ab_float64_z_flag( float64_le_quiet );
+ break;
+ case FLOAT64_LT_QUIET:
+ time_ab_float64_z_flag( float64_lt_quiet );
+ break;
+#ifdef FLOATX80
+ case FLOATX80_TO_INT32:
+ time_a_floatx80_z_int32( floatx80_to_int32 );
+ break;
+ case FLOATX80_TO_INT32_ROUND_TO_ZERO:
+ time_a_floatx80_z_int32( floatx80_to_int32_round_to_zero );
+ break;
+ case FLOATX80_TO_INT64:
+ time_a_floatx80_z_int64( floatx80_to_int64 );
+ break;
+ case FLOATX80_TO_INT64_ROUND_TO_ZERO:
+ time_a_floatx80_z_int64( floatx80_to_int64_round_to_zero );
+ break;
+ case FLOATX80_TO_FLOAT32:
+ time_a_floatx80_z_float32( floatx80_to_float32 );
+ break;
+ case FLOATX80_TO_FLOAT64:
+ time_a_floatx80_z_float64( floatx80_to_float64 );
+ break;
+#ifdef FLOAT128
+ case FLOATX80_TO_FLOAT128:
+ time_a_floatx80_z_float128( floatx80_to_float128 );
+ break;
+#endif
+ case FLOATX80_ROUND_TO_INT:
+ time_az_floatx80( floatx80_round_to_int );
+ break;
+ case FLOATX80_ADD:
+ time_abz_floatx80( floatx80_add );
+ break;
+ case FLOATX80_SUB:
+ time_abz_floatx80( floatx80_sub );
+ break;
+ case FLOATX80_MUL:
+ time_abz_floatx80( floatx80_mul );
+ break;
+ case FLOATX80_DIV:
+ time_abz_floatx80( floatx80_div );
+ break;
+ case FLOATX80_REM:
+ time_abz_floatx80( floatx80_rem );
+ break;
+ case FLOATX80_SQRT:
+ time_az_floatx80_pos( floatx80_sqrt );
+ break;
+ case FLOATX80_EQ:
+ time_ab_floatx80_z_flag( floatx80_eq );
+ break;
+ case FLOATX80_LE:
+ time_ab_floatx80_z_flag( floatx80_le );
+ break;
+ case FLOATX80_LT:
+ time_ab_floatx80_z_flag( floatx80_lt );
+ break;
+ case FLOATX80_EQ_SIGNALING:
+ time_ab_floatx80_z_flag( floatx80_eq_signaling );
+ break;
+ case FLOATX80_LE_QUIET:
+ time_ab_floatx80_z_flag( floatx80_le_quiet );
+ break;
+ case FLOATX80_LT_QUIET:
+ time_ab_floatx80_z_flag( floatx80_lt_quiet );
+ break;
+#endif
+#ifdef FLOAT128
+ case FLOAT128_TO_INT32:
+ time_a_float128_z_int32( float128_to_int32 );
+ break;
+ case FLOAT128_TO_INT32_ROUND_TO_ZERO:
+ time_a_float128_z_int32( float128_to_int32_round_to_zero );
+ break;
+ case FLOAT128_TO_INT64:
+ time_a_float128_z_int64( float128_to_int64 );
+ break;
+ case FLOAT128_TO_INT64_ROUND_TO_ZERO:
+ time_a_float128_z_int64( float128_to_int64_round_to_zero );
+ break;
+ case FLOAT128_TO_FLOAT32:
+ time_a_float128_z_float32( float128_to_float32 );
+ break;
+ case FLOAT128_TO_FLOAT64:
+ time_a_float128_z_float64( float128_to_float64 );
+ break;
+#ifdef FLOATX80
+ case FLOAT128_TO_FLOATX80:
+ time_a_float128_z_floatx80( float128_to_floatx80 );
+ break;
+#endif
+ case FLOAT128_ROUND_TO_INT:
+ time_az_float128( float128_round_to_int );
+ break;
+ case FLOAT128_ADD:
+ time_abz_float128( float128_add );
+ break;
+ case FLOAT128_SUB:
+ time_abz_float128( float128_sub );
+ break;
+ case FLOAT128_MUL:
+ time_abz_float128( float128_mul );
+ break;
+ case FLOAT128_DIV:
+ time_abz_float128( float128_div );
+ break;
+ case FLOAT128_REM:
+ time_abz_float128( float128_rem );
+ break;
+ case FLOAT128_SQRT:
+ time_az_float128_pos( float128_sqrt );
+ break;
+ case FLOAT128_EQ:
+ time_ab_float128_z_flag( float128_eq );
+ break;
+ case FLOAT128_LE:
+ time_ab_float128_z_flag( float128_le );
+ break;
+ case FLOAT128_LT:
+ time_ab_float128_z_flag( float128_lt );
+ break;
+ case FLOAT128_EQ_SIGNALING:
+ time_ab_float128_z_flag( float128_eq_signaling );
+ break;
+ case FLOAT128_LE_QUIET:
+ time_ab_float128_z_flag( float128_le_quiet );
+ break;
+ case FLOAT128_LT_QUIET:
+ time_ab_float128_z_flag( float128_lt_quiet );
+ break;
+#endif
+ }
+
+}
+
+static void
+ timeFunction(
+ uint8 functionCode,
+ int8 roundingPrecisionIn,
+ int8 roundingModeIn,
+ int8 tininessModeIn
+ )
+{
+ int8 roundingPrecision, roundingMode, tininessMode;
+
+ roundingPrecision = 32;
+ for (;;) {
+ if ( ! functions[ functionCode ].roundingPrecision ) {
+ roundingPrecision = 0;
+ }
+ else if ( roundingPrecisionIn ) {
+ roundingPrecision = roundingPrecisionIn;
+ }
+ for ( roundingMode = 1;
+ roundingMode < NUM_ROUNDINGMODES;
+ ++roundingMode
+ ) {
+ if ( ! functions[ functionCode ].roundingMode ) {
+ roundingMode = 0;
+ }
+ else if ( roundingModeIn ) {
+ roundingMode = roundingModeIn;
+ }
+ for ( tininessMode = 1;
+ tininessMode < NUM_TININESSMODES;
+ ++tininessMode
+ ) {
+ if ( ( roundingPrecision == 32 )
+ || ( roundingPrecision == 64 ) ) {
+ if ( ! functions[ functionCode ]
+ .tininessModeAtReducedPrecision
+ ) {
+ tininessMode = 0;
+ }
+ else if ( tininessModeIn ) {
+ tininessMode = tininessModeIn;
+ }
+ }
+ else {
+ if ( ! functions[ functionCode ].tininessMode ) {
+ tininessMode = 0;
+ }
+ else if ( tininessModeIn ) {
+ tininessMode = tininessModeIn;
+ }
+ }
+ timeFunctionVariety(
+ functionCode, roundingPrecision, roundingMode, tininessMode
+ );
+ if ( tininessModeIn || ! tininessMode ) break;
+ }
+ if ( roundingModeIn || ! roundingMode ) break;
+ }
+ if ( roundingPrecisionIn || ! roundingPrecision ) break;
+ if ( roundingPrecision == 80 ) {
+ break;
+ }
+ else if ( roundingPrecision == 64 ) {
+ roundingPrecision = 80;
+ }
+ else if ( roundingPrecision == 32 ) {
+ roundingPrecision = 64;
+ }
+ }
+
+}
+
+main( int argc, char **argv )
+{
+ char *argPtr;
+ flag functionArgument;
+ uint8 functionCode;
+ int8 operands, roundingPrecision, roundingMode, tininessMode;
+
+ if ( argc <= 1 ) goto writeHelpMessage;
+ functionArgument = FALSE;
+ functionCode = 0;
+ operands = 0;
+ roundingPrecision = 0;
+ roundingMode = 0;
+ tininessMode = 0;
+ --argc;
+ ++argv;
+ while ( argc && ( argPtr = argv[ 0 ] ) ) {
+ if ( argPtr[ 0 ] == '-' ) ++argPtr;
+ if ( strcmp( argPtr, "help" ) == 0 ) {
+ writeHelpMessage:
+ fputs(
+"timesoftfloat [<option>...] <function>\n"
+" <option>: (* is default)\n"
+" -help --Write this message and exit.\n"
+#ifdef FLOATX80
+" -precision32 --Only time rounding precision equivalent to float32.\n"
+" -precision64 --Only time rounding precision equivalent to float64.\n"
+" -precision80 --Only time maximum rounding precision.\n"
+#endif
+" -nearesteven --Only time rounding to nearest/even.\n"
+" -tozero --Only time rounding to zero.\n"
+" -down --Only time rounding down.\n"
+" -up --Only time rounding up.\n"
+" -tininessbefore --Only time underflow tininess before rounding.\n"
+" -tininessafter --Only time underflow tininess after rounding.\n"
+" <function>:\n"
+" int32_to_<float> <float>_add <float>_eq\n"
+" <float>_to_int32 <float>_sub <float>_le\n"
+" <float>_to_int32_round_to_zero <float>_mul <float>_lt\n"
+" int64_to_<float> <float>_div <float>_eq_signaling\n"
+" <float>_to_int64 <float>_rem <float>_le_quiet\n"
+" <float>_to_int64_round_to_zero <float>_lt_quiet\n"
+" <float>_to_<float>\n"
+" <float>_round_to_int\n"
+" <float>_sqrt\n"
+" -all1 --All 1-operand functions.\n"
+" -all2 --All 2-operand functions.\n"
+" -all --All functions.\n"
+" <float>:\n"
+" float32 --Single precision.\n"
+" float64 --Double precision.\n"
+#ifdef FLOATX80
+" floatx80 --Extended double precision.\n"
+#endif
+#ifdef FLOAT128
+" float128 --Quadruple precision.\n"
+#endif
+ ,
+ stdout
+ );
+ return EXIT_SUCCESS;
+ }
+#ifdef FLOATX80
+ else if ( strcmp( argPtr, "precision32" ) == 0 ) {
+ roundingPrecision = 32;
+ }
+ else if ( strcmp( argPtr, "precision64" ) == 0 ) {
+ roundingPrecision = 64;
+ }
+ else if ( strcmp( argPtr, "precision80" ) == 0 ) {
+ roundingPrecision = 80;
+ }
+#endif
+ else if ( ( strcmp( argPtr, "nearesteven" ) == 0 )
+ || ( strcmp( argPtr, "nearest_even" ) == 0 ) ) {
+ roundingMode = ROUND_NEAREST_EVEN;
+ }
+ else if ( ( strcmp( argPtr, "tozero" ) == 0 )
+ || ( strcmp( argPtr, "to_zero" ) == 0 ) ) {
+ roundingMode = ROUND_TO_ZERO;
+ }
+ else if ( strcmp( argPtr, "down" ) == 0 ) {
+ roundingMode = ROUND_DOWN;
+ }
+ else if ( strcmp( argPtr, "up" ) == 0 ) {
+ roundingMode = ROUND_UP;
+ }
+ else if ( strcmp( argPtr, "tininessbefore" ) == 0 ) {
+ tininessMode = TININESS_BEFORE_ROUNDING;
+ }
+ else if ( strcmp( argPtr, "tininessafter" ) == 0 ) {
+ tininessMode = TININESS_AFTER_ROUNDING;
+ }
+ else if ( strcmp( argPtr, "all1" ) == 0 ) {
+ functionArgument = TRUE;
+ functionCode = 0;
+ operands = 1;
+ }
+ else if ( strcmp( argPtr, "all2" ) == 0 ) {
+ functionArgument = TRUE;
+ functionCode = 0;
+ operands = 2;
+ }
+ else if ( strcmp( argPtr, "all" ) == 0 ) {
+ functionArgument = TRUE;
+ functionCode = 0;
+ operands = 0;
+ }
+ else {
+ for ( functionCode = 1;
+ functionCode < NUM_FUNCTIONS;
+ ++functionCode
+ ) {
+ if ( strcmp( argPtr, functions[ functionCode ].name ) == 0 ) {
+ break;
+ }
+ }
+ if ( functionCode == NUM_FUNCTIONS ) {
+ fail( "Invalid option or function `%s'", argv[ 0 ] );
+ }
+ functionArgument = TRUE;
+ }
+ --argc;
+ ++argv;
+ }
+ if ( ! functionArgument ) fail( "Function argument required" );
+ if ( functionCode ) {
+ timeFunction(
+ functionCode, roundingPrecision, roundingMode, tininessMode );
+ }
+ else if ( operands == 1 ) {
+ for ( functionCode = 1; functionCode < NUM_FUNCTIONS; ++functionCode
+ ) {
+ if ( functions[ functionCode ].numInputs == 1 ) {
+ timeFunction(
+ functionCode, roundingPrecision, roundingMode, tininessMode
+ );
+ }
+ }
+ }
+ else if ( operands == 2 ) {
+ for ( functionCode = 1; functionCode < NUM_FUNCTIONS; ++functionCode
+ ) {
+ if ( functions[ functionCode ].numInputs == 2 ) {
+ timeFunction(
+ functionCode, roundingPrecision, roundingMode, tininessMode
+ );
+ }
+ }
+ }
+ else {
+ for ( functionCode = 1; functionCode < NUM_FUNCTIONS; ++functionCode
+ ) {
+ timeFunction(
+ functionCode, roundingPrecision, roundingMode, tininessMode );
+ }
+ }
+ return EXIT_SUCCESS;
+
+}
+
diff --git a/lib/libc/softfloat/timesoftfloat.txt b/lib/libc/softfloat/timesoftfloat.txt
new file mode 100644
index 0000000..addc647
--- /dev/null
+++ b/lib/libc/softfloat/timesoftfloat.txt
@@ -0,0 +1,150 @@
+$NetBSD: timesoftfloat.txt,v 1.1 2000/06/06 08:15:11 bjh21 Exp $
+$FreeBSD$
+
+Documentation for the `timesoftfloat' Program of SoftFloat Release 2a
+
+John R. Hauser
+1998 December 14
+
+
+-------------------------------------------------------------------------------
+Introduction
+
+The `timesoftfloat' program evaluates the speed of SoftFloat's floating-
+point routines. Each routine can be evaluated for every relevant rounding
+mode, tininess mode, and/or rounding precision.
+
+
+-------------------------------------------------------------------------------
+Contents
+
+ Introduction
+ Contents
+ Legal Notice
+ Executing `timesoftfloat'
+ Options
+ -help
+ -precision32, -precision64, -precision80
+ -nearesteven, -tozero, -down, -up
+ -tininessbefore, -tininessafter
+ Function Sets
+
+
+
+-------------------------------------------------------------------------------
+Legal Notice
+
+The `timesoftfloat' program was written by John R. Hauser.
+
+THIS SOFTWARE IS DISTRIBUTED AS IS, FOR FREE. Although reasonable effort
+has been made to avoid it, THIS SOFTWARE MAY CONTAIN FAULTS THAT WILL AT
+TIMES RESULT IN INCORRECT BEHAVIOR. USE OF THIS SOFTWARE IS RESTRICTED TO
+PERSONS AND ORGANIZATIONS WHO CAN AND WILL TAKE FULL RESPONSIBILITY FOR ANY
+AND ALL LOSSES, COSTS, OR OTHER PROBLEMS ARISING FROM ITS USE.
+
+
+-------------------------------------------------------------------------------
+Executing `timesoftfloat'
+
+The `timesoftfloat' program is intended to be invoked from a command line
+interpreter as follows:
+
+ timesoftfloat [<option>...] <function>
+
+Here square brackets ([]) indicate optional items, while angled brackets
+(<>) denote parameters to be filled in. The `<function>' argument is
+the name of the SoftFloat routine to evaluate, such as `float32_add' or
+`float64_to_int32'. The allowed options are detailed in the next section,
+_Options_. If `timesoftfloat' is executed without any arguments, a summary
+of usage is written. It is also possible to evaluate all machine functions
+in a single invocation as explained in the section _Function_Sets_ later in
+this document.
+
+Ordinarily, a function's speed will be evaulated separately for each of
+the four rounding modes, one after the other. If the rounding mode is not
+supposed to have any affect on the results of a function--for instance,
+some operations do not require rounding--only the nearest/even rounding mode
+is timed. In the same way, if a function is affected by the way in which
+underflow tininess is detected, `timesoftfloat' times the function both with
+tininess detected before rounding and after rounding. For extended double-
+precision operations affected by rounding precision control, `timesoftfloat'
+also times the function for all three rounding precision modes, one after
+the other. Evaluation of a function can be limited to a single rounding
+mode, a single tininess mode, and/or a single rounding precision with
+appropriate options (see _Options_).
+
+For each function and mode evaluated, `timesoftfloat' reports the speed of
+the function in kops/s, or ``thousands of operations per second''. This
+unit of measure differs from the traditional MFLOPS (``millions of floating-
+point operations per second'') only in being a factor of 1000 smaller.
+(1000 kops/s is exactly 1 MFLOPS.) Speeds are reported in thousands instead
+of millions because software floating-point often executes at less than
+1 MFLOPS.
+
+The speeds reported by `timesoftfloat' may be affected somewhat by other
+programs executing at the same time as `timesoftfloat'.
+
+Note that the remainder operations (`float32_rem', `float64_rem',
+`floatx80_rem' and `float128_rem') will be markedly slower than other
+operations, particularly for extended double precision (`floatx80') and
+quadruple precision (`float128'). This is inherent to the remainder
+function itself and is not a failing of the SoftFloat implementation.
+
+
+-------------------------------------------------------------------------------
+Options
+
+The `timesoftfloat' program accepts several command options. If mutually
+contradictory options are given, the last one has priority.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+-help
+
+The `-help' option causes a summary of program usage to be written, after
+which the program exits.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+-precision32, -precision64, -precision80
+
+For extended double-precision functions affected by rounding precision
+control, the `-precision32' option restricts evaluation to only the cases
+in which rounding precision is equivalent to single precision. The other
+rounding precision options are not timed. Likewise, the `-precision64'
+and `-precision80' options fix the rounding precision equivalent to double
+precision or extended double precision, respectively. These options are
+ignored for functions not affected by rounding precision control.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+-nearesteven, -tozero, -down, -up
+
+The `-nearesteven' option restricts evaluation to only the cases in which
+the rounding mode is nearest/even. The other rounding mode options are not
+timed. Likewise, `-tozero' forces rounding to zero; `-down' forces rounding
+down; and `-up' forces rounding up. These options are ignored for functions
+that are exact and thus do not round.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+-tininessbefore, -tininessafter
+
+The `-tininessbefore' option restricts evaluation to only the cases
+detecting underflow tininess before rounding. Tininess after rounding
+is not timed. Likewise, `-tininessafter' forces underflow tininess to be
+detected after rounding only. These options are ignored for functions not
+affected by the way in which underflow tininess is detected.
+
+- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
+
+
+-------------------------------------------------------------------------------
+Function Sets
+
+Just as `timesoftfloat' can test an operation for all four rounding modes in
+sequence, multiple operations can also be tested with a single invocation.
+Three sets are recognized: `-all1', `-all2', and `-all'. The set `-all1'
+comprises all one-operand functions; `-all2' is all two-operand functions;
+and `-all' is all functions. A function set can be used in place of a
+function name in the command line, as in
+
+ timesoftfloat [<option>...] -all
+
+
diff --git a/lib/libc/softfloat/unorddf2.c b/lib/libc/softfloat/unorddf2.c
new file mode 100644
index 0000000..2986c82
--- /dev/null
+++ b/lib/libc/softfloat/unorddf2.c
@@ -0,0 +1,26 @@
+/* $NetBSD: unorddf2.c,v 1.1 2003/05/06 08:58:19 rearnsha Exp $ */
+
+/*
+ * Written by Richard Earnshaw, 2003. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+flag __unorddf2(float64, float64);
+
+flag
+__unorddf2(float64 a, float64 b)
+{
+ /*
+ * The comparison is unordered if either input is a NaN.
+ * Test for this by comparing each operand with itself.
+ * We must perform both comparisons to correctly check for
+ * signalling NaNs.
+ */
+ return 1 ^ (float64_eq(a, a) & float64_eq(b, b));
+}
diff --git a/lib/libc/softfloat/unordsf2.c b/lib/libc/softfloat/unordsf2.c
new file mode 100644
index 0000000..e2f4c8f
--- /dev/null
+++ b/lib/libc/softfloat/unordsf2.c
@@ -0,0 +1,26 @@
+/* $NetBSD: unordsf2.c,v 1.1 2003/05/06 08:58:20 rearnsha Exp $ */
+
+/*
+ * Written by Richard Earnshaw, 2003. This file is in the Public Domain.
+ */
+
+#include "softfloat-for-gcc.h"
+#include "milieu.h"
+#include "softfloat.h"
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+flag __unordsf2(float32, float32);
+
+flag
+__unordsf2(float32 a, float32 b)
+{
+ /*
+ * The comparison is unordered if either input is a NaN.
+ * Test for this by comparing each operand with itself.
+ * We must perform both comparisons to correctly check for
+ * signalling NaNs.
+ */
+ return 1 ^ (float32_eq(a, a) & float32_eq(b, b));
+}
diff --git a/lib/libc/sparc64/Makefile.inc b/lib/libc/sparc64/Makefile.inc
new file mode 100644
index 0000000..76cc8b9
--- /dev/null
+++ b/lib/libc/sparc64/Makefile.inc
@@ -0,0 +1,11 @@
+# $FreeBSD$
+#
+# Machine dependent definitions for the ultra sparc architecture.
+#
+
+.include "fpu/Makefile.inc"
+
+# Long double is quad precision
+GDTOASRCS+=strtorQ.c
+MDSRCS+=machdep_ldisQ.c
+SYM_MAPS+=${.CURDIR}/sparc64/Symbol.map
diff --git a/lib/libc/sparc64/SYS.h b/lib/libc/sparc64/SYS.h
new file mode 100644
index 0000000..0bc7840
--- /dev/null
+++ b/lib/libc/sparc64/SYS.h
@@ -0,0 +1,85 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)SYS.h 5.5 (Berkeley) 5/7/91
+ * from: FreeBSD: src/lib/libc/i386/SYS.h,v 1.20 2001/01/29
+ * $FreeBSD$
+ */
+
+#include <sys/syscall.h>
+
+#include <machine/asm.h>
+#include <machine/utrap.h>
+
+#define ERROR() \
+ mov %o7, %g1 ; \
+ call HIDENAME(cerror) ; \
+ mov %g1, %o7
+
+#define _SYSENTRY(x) \
+ENTRY(__CONCAT(__sys_,x)) ; \
+ .weak CNAME(x) ; \
+ .type CNAME(x),@function ; \
+ .set CNAME(x),CNAME(__CONCAT(__sys_,x)) ; \
+ .weak CNAME(__CONCAT(_,x)) ; \
+ .type CNAME(__CONCAT(_,x)), @function ; \
+ .set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x))
+
+#define _SYSEND(x) \
+ .size CNAME(__CONCAT(__sys_,x)), . - CNAME(__CONCAT(__sys_,x)) ; \
+ .size CNAME(__CONCAT(_,x)), . - CNAME(__CONCAT(__sys_,x)) ; \
+ .size CNAME(__CONCAT(,x)), . - CNAME(__CONCAT(__sys_,x))
+
+#define _SYSCALL(x) \
+ mov __CONCAT(SYS_,x), %g1 ; \
+ ta %xcc, ST_SYSCALL ; \
+ bcc,a,pt %xcc, 1f ; \
+ nop ; \
+ ERROR() ; \
+1:
+
+#define RSYSCALL(x) \
+_SYSENTRY(x) ; \
+ _SYSCALL(x) ; \
+ retl ; \
+ nop ; \
+ _SYSEND(x)
+
+#define PSEUDO(x) \
+ENTRY(__CONCAT(__sys_,x)) ; \
+ .weak CNAME(__CONCAT(_,x)) ; \
+ .type CNAME(__CONCAT(_,x)),@function ; \
+ .set CNAME(__CONCAT(_,x)),CNAME(__CONCAT(__sys_,x)) ; \
+ _SYSCALL(x) ; \
+ retl ; \
+ nop ; \
+ .size CNAME(__CONCAT(__sys_,x)), . - CNAME(__CONCAT(__sys_,x)) ; \
+ .size CNAME(__CONCAT(_,x)), . - CNAME(__CONCAT(__sys_,x))
diff --git a/lib/libc/sparc64/Symbol.map b/lib/libc/sparc64/Symbol.map
new file mode 100644
index 0000000..4f90486
--- /dev/null
+++ b/lib/libc/sparc64/Symbol.map
@@ -0,0 +1,98 @@
+/*
+ * $FreeBSD$
+ */
+
+/*
+ * This only needs to contain symbols that are not listed in
+ * symbol maps from other parts of libc (i.e., not found in
+ * stdlib/Symbol.map, string/Symbol.map, sys/Symbol.map, ...).
+ */
+FBSD_1.0 {
+ /* PSEUDO syscalls */
+ _exit;
+
+ _mcount;
+ _setjmp;
+ _longjmp;
+ fabs;
+ __flt_rounds;
+ fpgetmask;
+ fpgetround;
+ fpgetsticky;
+ fpsetmask;
+ fpsetround;
+ __infinity;
+ __nan;
+ makecontext;
+ setjmp;
+ longjmp;
+ sigsetjmp;
+ siglongjmp;
+ htonl;
+ htons;
+ ntohl;
+ ntohs;
+ brk;
+ exect;
+ sbrk;
+ vfork;
+
+ /* SCD libc 64 psABI */
+ _Qp_sqrt;
+ _Qp_add;
+ _Qp_div;
+ _Qp_mul;
+ _Qp_sub;
+ _Qp_dtoq;
+ _Qp_itoq;
+ _Qp_stoq;
+ _Qp_xtoq;
+ _Qp_uitoq;
+ _Qp_uxtoq;
+ _Qp_qtod;
+ _Qp_qtoi;
+ _Qp_qtos;
+ _Qp_qtox;
+ _Qp_qtoui;
+ _Qp_qtoux;
+ _Qp_feq;
+ _Qp_fge;
+ _Qp_fgt;
+ _Qp_fle;
+ _Qp_flt;
+ _Qp_fne;
+ _Qp_cmp;
+ _Qp_cmpe;
+ __dtoul;
+ __sparc_utrap_install;
+};
+
+FBSDprivate_1.0 {
+ /* PSEUDO syscalls */
+ __sys_getlogin;
+ _getlogin;
+ __sys_exit;
+
+ _set_tp;
+ ___longjmp;
+ __makecontext;
+ __longjmp;
+ signalcontext;
+ __signalcontext;
+ __siglongjmp;
+ .curbrk;
+ .minbrk;
+ __sys_brk;
+ _brk;
+ .cerror;
+ __sys_exect;
+ _exect;
+ _end;
+ __sys_sbrk;
+ _sbrk;
+ __sys_vfork;
+ _vfork;
+
+ /* used in src/lib/csu/sparc64/crt1.c */
+ __sparc_utrap_setup;
+};
diff --git a/lib/libc/sparc64/_fpmath.h b/lib/libc/sparc64/_fpmath.h
new file mode 100644
index 0000000..f323815
--- /dev/null
+++ b/lib/libc/sparc64/_fpmath.h
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2003 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 2002, 2003 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+union IEEEl2bits {
+ long double e;
+ struct {
+ unsigned int sign :1;
+ unsigned int exp :15;
+ unsigned long manh :48;
+ unsigned long manl :64;
+ } bits;
+ struct {
+ unsigned int expsign :16;
+ unsigned long manh :48;
+ unsigned long manl :64;
+ } xbits;
+};
+
+#define mask_nbit_l(u) ((void)0)
+#define LDBL_IMPLICIT_NBIT
+#define LDBL_NBIT 0
+
+#define LDBL_MANH_SIZE 48
+#define LDBL_MANL_SIZE 64
+
+#define LDBL_TO_ARRAY32(u, a) do { \
+ (a)[0] = (uint32_t)(u).bits.manl; \
+ (a)[1] = (uint32_t)((u).bits.manl >> 32); \
+ (a)[2] = (uint32_t)(u).bits.manh; \
+ (a)[3] = (uint32_t)((u).bits.manh >> 32); \
+} while(0)
diff --git a/lib/libc/sparc64/arith.h b/lib/libc/sparc64/arith.h
new file mode 100644
index 0000000..3c35b80
--- /dev/null
+++ b/lib/libc/sparc64/arith.h
@@ -0,0 +1,19 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * NOTE: The definitions in this file must be correct or strtod(3) and
+ * floating point formats in printf(3) will break! The file can be
+ * generated by running contrib/gdtoa/arithchk.c on the target
+ * architecture. See contrib/gdtoa/gdtoaimp.h for details.
+ */
+
+#define IEEE_MC68k
+#define Arith_Kind_ASL 2
+#define Long int
+#define Intcast (int)(long)
+#define Double_Align
+#define X64_bit_pointers
diff --git a/lib/libc/sparc64/fpu/Makefile.inc b/lib/libc/sparc64/fpu/Makefile.inc
new file mode 100644
index 0000000..1974d8a
--- /dev/null
+++ b/lib/libc/sparc64/fpu/Makefile.inc
@@ -0,0 +1,8 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/sparc64/fpu
+
+CFLAGS+= -I${.CURDIR}/sparc64/sys
+
+SRCS+= fpu.c fpu_add.c fpu_compare.c fpu_div.c fpu_explode.c fpu_implode.c \
+ fpu_mul.c fpu_qp.c fpu_reg.S fpu_sqrt.c fpu_subr.c
diff --git a/lib/libc/sparc64/fpu/fpu.c b/lib/libc/sparc64/fpu/fpu.c
new file mode 100644
index 0000000..4e92788
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu.c
@@ -0,0 +1,461 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*-
+ * Copyright 2001 by Thomas Moestl <tmm@FreeBSD.org>. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * @(#)fpu.c 8.1 (Berkeley) 6/11/93
+ * $NetBSD: fpu.c,v 1.11 2000/12/06 01:47:50 mrg Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+
+#include "namespace.h"
+#include <errno.h>
+#include <signal.h>
+#ifdef FPU_DEBUG
+#include <stdio.h>
+#endif
+#include <stdlib.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+#include <machine/fp.h>
+#include <machine/frame.h>
+#include <machine/fsr.h>
+#include <machine/instr.h>
+#include <machine/pcb.h>
+#include <machine/tstate.h>
+
+#include "__sparc_utrap_private.h"
+#include "fpu_emu.h"
+#include "fpu_extern.h"
+
+/*
+ * Translate current exceptions into `first' exception. The
+ * bits go the wrong way for ffs() (0x10 is most important, etc).
+ * There are only 5, so do it the obvious way.
+ */
+#define X1(x) x
+#define X2(x) x,x
+#define X4(x) x,x,x,x
+#define X8(x) X4(x),X4(x)
+#define X16(x) X8(x),X8(x)
+
+static const char cx_to_trapx[] = {
+ X1(FSR_NX),
+ X2(FSR_DZ),
+ X4(FSR_UF),
+ X8(FSR_OF),
+ X16(FSR_NV)
+};
+
+#ifdef FPU_DEBUG
+#ifdef FPU_DEBUG_MASK
+int __fpe_debug = FPU_DEBUG_MASK;
+#else
+int __fpe_debug = 0;
+#endif
+#endif /* FPU_DEBUG */
+
+static int __fpu_execute(struct utrapframe *, struct fpemu *, u_int32_t,
+ u_long);
+
+/*
+ * Need to use an fpstate on the stack; we could switch, so we cannot safely
+ * modify the pcb one, it might get overwritten.
+ */
+int
+__fpu_exception(struct utrapframe *uf)
+{
+ struct fpemu fe;
+ u_long fsr, tstate;
+ u_int insn;
+ int sig;
+
+ fsr = uf->uf_fsr;
+
+ switch (FSR_GET_FTT(fsr)) {
+ case FSR_FTT_NONE:
+ __utrap_write("lost FPU trap type\n");
+ return (0);
+ case FSR_FTT_IEEE:
+ return (SIGFPE);
+ case FSR_FTT_SEQERR:
+ __utrap_write("FPU sequence error\n");
+ return (SIGFPE);
+ case FSR_FTT_HWERR:
+ __utrap_write("FPU hardware error\n");
+ return (SIGFPE);
+ case FSR_FTT_UNFIN:
+ case FSR_FTT_UNIMP:
+ break;
+ default:
+ __utrap_write("unknown FPU error\n");
+ return (SIGFPE);
+ }
+
+ fe.fe_fsr = fsr & ~FSR_FTT_MASK;
+ insn = *(u_int32_t *)uf->uf_pc;
+ if (IF_OP(insn) != IOP_MISC || (IF_F3_OP3(insn) != INS2_FPop1 &&
+ IF_F3_OP3(insn) != INS2_FPop2))
+ __utrap_panic("bogus FP fault");
+ tstate = uf->uf_state;
+ sig = __fpu_execute(uf, &fe, insn, tstate);
+ if (sig != 0)
+ return (sig);
+ __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr));
+ return (0);
+}
+
+#ifdef FPU_DEBUG
+/*
+ * Dump a `fpn' structure.
+ */
+void
+__fpu_dumpfpn(struct fpn *fp)
+{
+ static const char *const class[] = {
+ "SNAN", "QNAN", "ZERO", "NUM", "INF"
+ };
+
+ printf("%s %c.%x %x %x %xE%d", class[fp->fp_class + 2],
+ fp->fp_sign ? '-' : ' ',
+ fp->fp_mant[0], fp->fp_mant[1],
+ fp->fp_mant[2], fp->fp_mant[3],
+ fp->fp_exp);
+}
+#endif
+
+static const int opmask[] = {0, 0, 1, 3, 1};
+
+/* Decode 5 bit register field depending on the type. */
+#define RN_DECODE(tp, rn) \
+ ((tp) >= FTYPE_DBL ? INSFPdq_RN(rn) & ~opmask[tp] : (rn))
+
+/*
+ * Helper for forming the below case statements. Build only the op3 and opf
+ * field of the instruction, these are the only ones that need to match.
+ */
+#define FOP(op3, opf) \
+ ((op3) << IF_F3_OP3_SHIFT | (opf) << IF_F3_OPF_SHIFT)
+
+/*
+ * Implement a move operation for all supported operand types. The additional
+ * nand and xor parameters will be applied to the upper 32 bit word of the
+ * source operand. This allows to implement fabs and fneg (for fp operands
+ * only!) using this functions, too, by passing (1 << 31) for one of the
+ * parameters, and 0 for the other.
+ */
+static void
+__fpu_mov(struct fpemu *fe, int type, int rd, int rs2, u_int32_t nand,
+ u_int32_t xor)
+{
+
+ if (type == FTYPE_INT || type == FTYPE_SNG)
+ __fpu_setreg(rd, (__fpu_getreg(rs2) & ~nand) ^ xor);
+ else {
+ /*
+ * Need to use the double versions to be able to access
+ * the upper 32 fp registers.
+ */
+ __fpu_setreg64(rd, (__fpu_getreg64(rs2) &
+ ~((u_int64_t)nand << 32)) ^ ((u_int64_t)xor << 32));
+ if (type == FTYPE_EXT)
+ __fpu_setreg64(rd + 2, __fpu_getreg64(rs2 + 2));
+ }
+}
+
+static __inline void
+__fpu_ccmov(struct fpemu *fe, int type, int rd, int rs2,
+ u_int32_t insn, int fcc)
+{
+
+ if (IF_F4_COND(insn) == fcc)
+ __fpu_mov(fe, type, rd, rs2, 0, 0);
+}
+
+static int
+__fpu_cmpck(struct fpemu *fe)
+{
+ u_long fsr;
+ int cx;
+
+ /*
+ * The only possible exception here is NV; catch it
+ * early and get out, as there is no result register.
+ */
+ cx = fe->fe_cx;
+ fsr = fe->fe_fsr | (cx << FSR_CEXC_SHIFT);
+ if (cx != 0) {
+ if (fsr & (FSR_NV << FSR_TEM_SHIFT)) {
+ fe->fe_fsr = (fsr & ~FSR_FTT_MASK) |
+ FSR_FTT(FSR_FTT_IEEE);
+ return (SIGFPE);
+ }
+ fsr |= FSR_NV << FSR_AEXC_SHIFT;
+ }
+ fe->fe_fsr = fsr;
+ return (0);
+}
+
+/*
+ * Execute an FPU instruction (one that runs entirely in the FPU; not
+ * FBfcc or STF, for instance). On return, fe->fe_fs->fs_fsr will be
+ * modified to reflect the setting the hardware would have left.
+ *
+ * Note that we do not catch all illegal opcodes, so you can, for instance,
+ * multiply two integers this way.
+ */
+static int
+__fpu_execute(struct utrapframe *uf, struct fpemu *fe, u_int32_t insn,
+ u_long tstate)
+{
+ struct fpn *fp;
+ int opf, rs1, rs2, rd, type, mask, cx, cond;
+ u_long reg, fsr;
+ u_int space[4];
+
+ /*
+ * `Decode' and execute instruction. Start with no exceptions.
+ * The type of almost any OPF opcode is in the bottom two bits, so we
+ * squish them out here.
+ */
+ opf = insn & (IF_MASK(IF_F3_OP3_SHIFT, IF_F3_OP3_BITS) |
+ IF_MASK(IF_F3_OPF_SHIFT + 2, IF_F3_OPF_BITS - 2));
+ type = IF_F3_OPF(insn) & 3;
+ rs1 = RN_DECODE(type, IF_F3_RS1(insn));
+ rs2 = RN_DECODE(type, IF_F3_RS2(insn));
+ rd = RN_DECODE(type, IF_F3_RD(insn));
+ cond = 0;
+#ifdef notdef
+ if ((rs1 | rs2 | rd) & opmask[type])
+ return (SIGILL);
+#endif
+ fsr = fe->fe_fsr;
+ fe->fe_fsr &= ~FSR_CEXC_MASK;
+ fe->fe_cx = 0;
+ switch (opf) {
+ case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_FCC(0))):
+ __fpu_ccmov(fe, type, rd, rs2, insn, FSR_GET_FCC0(fsr));
+ return (0);
+ case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_FCC(1))):
+ __fpu_ccmov(fe, type, rd, rs2, insn, FSR_GET_FCC1(fsr));
+ return (0);
+ case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_FCC(2))):
+ __fpu_ccmov(fe, type, rd, rs2, insn, FSR_GET_FCC2(fsr));
+ return (0);
+ case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_FCC(3))):
+ __fpu_ccmov(fe, type, rd, rs2, insn, FSR_GET_FCC3(fsr));
+ return (0);
+ case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_ICC)):
+ __fpu_ccmov(fe, type, rd, rs2, insn,
+ (tstate & TSTATE_ICC_MASK) >> TSTATE_ICC_SHIFT);
+ return (0);
+ case FOP(INS2_FPop2, INSFP2_FMOV_CC(IFCC_XCC)):
+ __fpu_ccmov(fe, type, rd, rs2, insn,
+ (tstate & TSTATE_XCC_MASK) >> (TSTATE_XCC_SHIFT));
+ return (0);
+ case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_Z)):
+ reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
+ if (reg == 0)
+ __fpu_mov(fe, type, rd, rs2, 0, 0);
+ return (0);
+ case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_LEZ)):
+ reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
+ if (reg <= 0)
+ __fpu_mov(fe, type, rd, rs2, 0, 0);
+ return (0);
+ case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_LZ)):
+ reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
+ if (reg < 0)
+ __fpu_mov(fe, type, rd, rs2, 0, 0);
+ return (0);
+ case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_NZ)):
+ reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
+ if (reg != 0)
+ __fpu_mov(fe, type, rd, rs2, 0, 0);
+ return (0);
+ case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_GZ)):
+ reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
+ if (reg > 0)
+ __fpu_mov(fe, type, rd, rs2, 0, 0);
+ return (0);
+ case FOP(INS2_FPop2, INSFP2_FMOV_RC(IRCOND_GEZ)):
+ reg = __emul_fetch_reg(uf, IF_F4_RS1(insn));
+ if (reg >= 0)
+ __fpu_mov(fe, type, rd, rs2, 0, 0);
+ return (0);
+ case FOP(INS2_FPop2, INSFP2_FCMP):
+ __fpu_explode(fe, &fe->fe_f1, type, rs1);
+ __fpu_explode(fe, &fe->fe_f2, type, rs2);
+ __fpu_compare(fe, 0, IF_F3_CC(insn));
+ return (__fpu_cmpck(fe));
+ case FOP(INS2_FPop2, INSFP2_FCMPE):
+ __fpu_explode(fe, &fe->fe_f1, type, rs1);
+ __fpu_explode(fe, &fe->fe_f2, type, rs2);
+ __fpu_compare(fe, 1, IF_F3_CC(insn));
+ return (__fpu_cmpck(fe));
+ case FOP(INS2_FPop1, INSFP1_FMOV):
+ __fpu_mov(fe, type, rd, rs2, 0, 0);
+ return (0);
+ case FOP(INS2_FPop1, INSFP1_FNEG):
+ __fpu_mov(fe, type, rd, rs2, 0, (1 << 31));
+ return (0);
+ case FOP(INS2_FPop1, INSFP1_FABS):
+ __fpu_mov(fe, type, rd, rs2, (1 << 31), 0);
+ return (0);
+ case FOP(INS2_FPop1, INSFP1_FSQRT):
+ __fpu_explode(fe, &fe->fe_f1, type, rs2);
+ fp = __fpu_sqrt(fe);
+ break;
+ case FOP(INS2_FPop1, INSFP1_FADD):
+ __fpu_explode(fe, &fe->fe_f1, type, rs1);
+ __fpu_explode(fe, &fe->fe_f2, type, rs2);
+ fp = __fpu_add(fe);
+ break;
+ case FOP(INS2_FPop1, INSFP1_FSUB):
+ __fpu_explode(fe, &fe->fe_f1, type, rs1);
+ __fpu_explode(fe, &fe->fe_f2, type, rs2);
+ fp = __fpu_sub(fe);
+ break;
+ case FOP(INS2_FPop1, INSFP1_FMUL):
+ __fpu_explode(fe, &fe->fe_f1, type, rs1);
+ __fpu_explode(fe, &fe->fe_f2, type, rs2);
+ fp = __fpu_mul(fe);
+ break;
+ case FOP(INS2_FPop1, INSFP1_FDIV):
+ __fpu_explode(fe, &fe->fe_f1, type, rs1);
+ __fpu_explode(fe, &fe->fe_f2, type, rs2);
+ fp = __fpu_div(fe);
+ break;
+ case FOP(INS2_FPop1, INSFP1_FsMULd):
+ case FOP(INS2_FPop1, INSFP1_FdMULq):
+ if (type == FTYPE_EXT)
+ return (SIGILL);
+ __fpu_explode(fe, &fe->fe_f1, type, rs1);
+ __fpu_explode(fe, &fe->fe_f2, type, rs2);
+ type++; /* single to double, or double to quad */
+ /*
+ * Recalculate rd (the old type applied for the source regs
+ * only, the target one has a different size).
+ */
+ rd = RN_DECODE(type, IF_F3_RD(insn));
+ fp = __fpu_mul(fe);
+ break;
+ case FOP(INS2_FPop1, INSFP1_FxTOs):
+ case FOP(INS2_FPop1, INSFP1_FxTOd):
+ case FOP(INS2_FPop1, INSFP1_FxTOq):
+ type = FTYPE_LNG;
+ rs2 = RN_DECODE(type, IF_F3_RS2(insn));
+ __fpu_explode(fe, fp = &fe->fe_f1, type, rs2);
+ /* sneaky; depends on instruction encoding */
+ type = (IF_F3_OPF(insn) >> 2) & 3;
+ rd = RN_DECODE(type, IF_F3_RD(insn));
+ break;
+ case FOP(INS2_FPop1, INSFP1_FTOx):
+ __fpu_explode(fe, fp = &fe->fe_f1, type, rs2);
+ type = FTYPE_LNG;
+ rd = RN_DECODE(type, IF_F3_RD(insn));
+ break;
+ case FOP(INS2_FPop1, INSFP1_FTOs):
+ case FOP(INS2_FPop1, INSFP1_FTOd):
+ case FOP(INS2_FPop1, INSFP1_FTOq):
+ case FOP(INS2_FPop1, INSFP1_FTOi):
+ __fpu_explode(fe, fp = &fe->fe_f1, type, rs2);
+ /* sneaky; depends on instruction encoding */
+ type = (IF_F3_OPF(insn) >> 2) & 3;
+ rd = RN_DECODE(type, IF_F3_RD(insn));
+ break;
+ default:
+ return (SIGILL);
+ }
+
+ /*
+ * ALU operation is complete. Collapse the result and then check
+ * for exceptions. If we got any, and they are enabled, do not
+ * alter the destination register, just stop with an exception.
+ * Otherwise set new current exceptions and accrue.
+ */
+ __fpu_implode(fe, fp, type, space);
+ cx = fe->fe_cx;
+ if (cx != 0) {
+ mask = (fsr >> FSR_TEM_SHIFT) & FSR_TEM_MASK;
+ if (cx & mask) {
+ /* not accrued??? */
+ fsr = (fsr & ~FSR_FTT_MASK) |
+ FSR_FTT(FSR_FTT_IEEE) |
+ FSR_CEXC(cx_to_trapx[(cx & mask) - 1]);
+ return (SIGFPE);
+ }
+ fsr |= (cx << FSR_CEXC_SHIFT) | (cx << FSR_AEXC_SHIFT);
+ }
+ fe->fe_fsr = fsr;
+ if (type == FTYPE_INT || type == FTYPE_SNG)
+ __fpu_setreg(rd, space[0]);
+ else {
+ __fpu_setreg64(rd, ((u_int64_t)space[0] << 32) | space[1]);
+ if (type == FTYPE_EXT)
+ __fpu_setreg64(rd + 2,
+ ((u_int64_t)space[2] << 32) | space[3]);
+ }
+ return (0); /* success */
+}
diff --git a/lib/libc/sparc64/fpu/fpu_add.c b/lib/libc/sparc64/fpu/fpu_add.c
new file mode 100644
index 0000000..af493cd
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu_add.c
@@ -0,0 +1,214 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fpu_add.c 8.1 (Berkeley) 6/11/93
+ * $NetBSD: fpu_add.c,v 1.3 1996/03/14 19:41:52 christos Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Perform an FPU add (return x + y).
+ *
+ * To subtract, negate y and call add.
+ */
+
+#include <sys/param.h>
+
+#include <machine/frame.h>
+#include <machine/fp.h>
+#include <machine/fsr.h>
+#include <machine/instr.h>
+
+#include "fpu_arith.h"
+#include "fpu_emu.h"
+#include "fpu_extern.h"
+#include "__sparc_utrap_private.h"
+
+struct fpn *
+__fpu_add(fe)
+ struct fpemu *fe;
+{
+ struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2, *r;
+ u_int r0, r1, r2, r3;
+ int rd;
+
+ /*
+ * Put the `heavier' operand on the right (see fpu_emu.h).
+ * Then we will have one of the following cases, taken in the
+ * following order:
+ *
+ * - y = NaN. Implied: if only one is a signalling NaN, y is.
+ * The result is y.
+ * - y = Inf. Implied: x != NaN (is 0, number, or Inf: the NaN
+ * case was taken care of earlier).
+ * If x = -y, the result is NaN. Otherwise the result
+ * is y (an Inf of whichever sign).
+ * - y is 0. Implied: x = 0.
+ * If x and y differ in sign (one positive, one negative),
+ * the result is +0 except when rounding to -Inf. If same:
+ * +0 + +0 = +0; -0 + -0 = -0.
+ * - x is 0. Implied: y != 0.
+ * Result is y.
+ * - other. Implied: both x and y are numbers.
+ * Do addition a la Hennessey & Patterson.
+ */
+ ORDER(x, y);
+ if (ISNAN(y))
+ return (y);
+ if (ISINF(y)) {
+ if (ISINF(x) && x->fp_sign != y->fp_sign)
+ return (__fpu_newnan(fe));
+ return (y);
+ }
+ rd = FSR_GET_RD(fe->fe_fsr);
+ if (ISZERO(y)) {
+ if (rd != FSR_RD_NINF) /* only -0 + -0 gives -0 */
+ y->fp_sign &= x->fp_sign;
+ else /* any -0 operand gives -0 */
+ y->fp_sign |= x->fp_sign;
+ return (y);
+ }
+ if (ISZERO(x))
+ return (y);
+ /*
+ * We really have two numbers to add, although their signs may
+ * differ. Make the exponents match, by shifting the smaller
+ * number right (e.g., 1.011 => 0.1011) and increasing its
+ * exponent (2^3 => 2^4). Note that we do not alter the exponents
+ * of x and y here.
+ */
+ r = &fe->fe_f3;
+ r->fp_class = FPC_NUM;
+ if (x->fp_exp == y->fp_exp) {
+ r->fp_exp = x->fp_exp;
+ r->fp_sticky = 0;
+ } else {
+ if (x->fp_exp < y->fp_exp) {
+ /*
+ * Try to avoid subtract case iii (see below).
+ * This also guarantees that x->fp_sticky = 0.
+ */
+ SWAP(x, y);
+ }
+ /* now x->fp_exp > y->fp_exp */
+ r->fp_exp = x->fp_exp;
+ r->fp_sticky = __fpu_shr(y, x->fp_exp - y->fp_exp);
+ }
+ r->fp_sign = x->fp_sign;
+ if (x->fp_sign == y->fp_sign) {
+ FPU_DECL_CARRY
+
+ /*
+ * The signs match, so we simply add the numbers. The result
+ * may be `supernormal' (as big as 1.111...1 + 1.111...1, or
+ * 11.111...0). If so, a single bit shift-right will fix it
+ * (but remember to adjust the exponent).
+ */
+ /* r->fp_mant = x->fp_mant + y->fp_mant */
+ FPU_ADDS(r->fp_mant[3], x->fp_mant[3], y->fp_mant[3]);
+ FPU_ADDCS(r->fp_mant[2], x->fp_mant[2], y->fp_mant[2]);
+ FPU_ADDCS(r->fp_mant[1], x->fp_mant[1], y->fp_mant[1]);
+ FPU_ADDC(r0, x->fp_mant[0], y->fp_mant[0]);
+ if ((r->fp_mant[0] = r0) >= FP_2) {
+ (void) __fpu_shr(r, 1);
+ r->fp_exp++;
+ }
+ } else {
+ FPU_DECL_CARRY
+
+ /*
+ * The signs differ, so things are rather more difficult.
+ * H&P would have us negate the negative operand and add;
+ * this is the same as subtracting the negative operand.
+ * This is quite a headache. Instead, we will subtract
+ * y from x, regardless of whether y itself is the negative
+ * operand. When this is done one of three conditions will
+ * hold, depending on the magnitudes of x and y:
+ * case i) |x| > |y|. The result is just x - y,
+ * with x's sign, but it may need to be normalized.
+ * case ii) |x| = |y|. The result is 0 (maybe -0)
+ * so must be fixed up.
+ * case iii) |x| < |y|. We goofed; the result should
+ * be (y - x), with the same sign as y.
+ * We could compare |x| and |y| here and avoid case iii,
+ * but that would take just as much work as the subtract.
+ * We can tell case iii has occurred by an overflow.
+ *
+ * N.B.: since x->fp_exp >= y->fp_exp, x->fp_sticky = 0.
+ */
+ /* r->fp_mant = x->fp_mant - y->fp_mant */
+ FPU_SET_CARRY(y->fp_sticky);
+ FPU_SUBCS(r3, x->fp_mant[3], y->fp_mant[3]);
+ FPU_SUBCS(r2, x->fp_mant[2], y->fp_mant[2]);
+ FPU_SUBCS(r1, x->fp_mant[1], y->fp_mant[1]);
+ FPU_SUBC(r0, x->fp_mant[0], y->fp_mant[0]);
+ if (r0 < FP_2) {
+ /* cases i and ii */
+ if ((r0 | r1 | r2 | r3) == 0) {
+ /* case ii */
+ r->fp_class = FPC_ZERO;
+ r->fp_sign = rd == FSR_RD_NINF;
+ return (r);
+ }
+ } else {
+ /*
+ * Oops, case iii. This can only occur when the
+ * exponents were equal, in which case neither
+ * x nor y have sticky bits set. Flip the sign
+ * (to y's sign) and negate the result to get y - x.
+ */
+#ifdef DIAGNOSTIC
+ if (x->fp_exp != y->fp_exp || r->fp_sticky)
+ __utrap_panic("fpu_add");
+#endif
+ r->fp_sign = y->fp_sign;
+ FPU_SUBS(r3, 0, r3);
+ FPU_SUBCS(r2, 0, r2);
+ FPU_SUBCS(r1, 0, r1);
+ FPU_SUBC(r0, 0, r0);
+ }
+ r->fp_mant[3] = r3;
+ r->fp_mant[2] = r2;
+ r->fp_mant[1] = r1;
+ r->fp_mant[0] = r0;
+ if (r0 < FP_1)
+ __fpu_norm(r);
+ }
+ return (r);
+}
diff --git a/lib/libc/sparc64/fpu/fpu_arith.h b/lib/libc/sparc64/fpu/fpu_arith.h
new file mode 100644
index 0000000..292cd70
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu_arith.h
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fpu_arith.h 8.1 (Berkeley) 6/11/93
+ * $NetBSD: fpu_arith.h,v 1.3 2000/07/24 04:11:03 mycroft Exp $
+ * $FreeBSD$
+ */
+
+/*
+ * Extended-precision arithmetic.
+ *
+ * We hold the notion of a `carry register', which may or may not be a
+ * machine carry bit or register. On the SPARC, it is just the machine's
+ * carry bit.
+ *
+ * In the worst case, you can compute the carry from x+y as
+ * (unsigned)(x + y) < (unsigned)x
+ * and from x+y+c as
+ * ((unsigned)(x + y + c) <= (unsigned)x && (y|c) != 0)
+ * for example.
+ */
+
+/* set up for extended-precision arithemtic */
+#define FPU_DECL_CARRY
+
+/*
+ * We have three kinds of add:
+ * add with carry: r = x + y + c
+ * add (ignoring current carry) and set carry: c'r = x + y + 0
+ * add with carry and set carry: c'r = x + y + c
+ * The macros use `C' for `use carry' and `S' for `set carry'.
+ * Note that the state of the carry is undefined after ADDC and SUBC,
+ * so if all you have for these is `add with carry and set carry',
+ * that is OK.
+ *
+ * The same goes for subtract, except that we compute x - y - c.
+ *
+ * Finally, we have a way to get the carry into a `regular' variable,
+ * or set it from a value. SET_CARRY turns 0 into no-carry, nonzero
+ * into carry; GET_CARRY sets its argument to 0 or 1.
+ */
+#define FPU_ADDC(r, x, y) \
+ __asm __volatile("addx %1,%2,%0" : "=r"(r) : "r"(x), "r"(y))
+#define FPU_ADDS(r, x, y) \
+ __asm __volatile("addcc %1,%2,%0" : "=r"(r) : "r"(x), "r"(y))
+#define FPU_ADDCS(r, x, y) \
+ __asm __volatile("addxcc %1,%2,%0" : "=r"(r) : "r"(x), "r"(y))
+#define FPU_SUBC(r, x, y) \
+ __asm __volatile("subx %1,%2,%0" : "=r"(r) : "r"(x), "r"(y))
+#define FPU_SUBS(r, x, y) \
+ __asm __volatile("subcc %1,%2,%0" : "=r"(r) : "r"(x), "r"(y))
+#define FPU_SUBCS(r, x, y) \
+ __asm __volatile("subxcc %1,%2,%0" : "=r"(r) : "r"(x), "r"(y))
+
+#define FPU_GET_CARRY(r) __asm __volatile("addx %%g0,%%g0,%0" : "=r"(r))
+#define FPU_SET_CARRY(v) __asm __volatile("addcc %0,-1,%%g0" : : "r"(v))
+
+#define FPU_SHL1_BY_ADD /* shift left 1 faster by ADDC than (a<<1)|(b>>31) */
diff --git a/lib/libc/sparc64/fpu/fpu_compare.c b/lib/libc/sparc64/fpu/fpu_compare.c
new file mode 100644
index 0000000..84b00bf
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu_compare.c
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fpu_compare.c 8.1 (Berkeley) 6/11/93
+ * $NetBSD: fpu_compare.c,v 1.3 2001/08/26 05:46:31 eeh Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * CMP and CMPE instructions.
+ *
+ * These rely on the fact that our internal wide format is achieved by
+ * adding zero bits to the end of narrower mantissas.
+ */
+
+#include <sys/types.h>
+
+#include <machine/frame.h>
+#include <machine/fp.h>
+#include <machine/fsr.h>
+
+#include "fpu_arith.h"
+#include "fpu_emu.h"
+#include "fpu_extern.h"
+
+static u_long fcc_nmask[] = {
+ ~FSR_FCC0_MASK,
+ ~FSR_FCC1_MASK,
+ ~FSR_FCC2_MASK,
+ ~FSR_FCC3_MASK
+};
+
+/* XXX: we don't use the FSR_FCCx macros here; it's much easier this way. */
+static int fcc_shift[] = {
+ FSR_FCC0_SHIFT,
+ FSR_FCC1_SHIFT,
+ FSR_FCC2_SHIFT,
+ FSR_FCC3_SHIFT
+};
+
+/*
+ * Perform a compare instruction (with or without unordered exception).
+ * This updates the fcc field in the fsr.
+ *
+ * If either operand is NaN, the result is unordered. For cmpe, this
+ * causes an NV exception. Everything else is ordered:
+ * |Inf| > |numbers| > |0|.
+ * We already arranged for fp_class(Inf) > fp_class(numbers) > fp_class(0),
+ * so we get this directly. Note, however, that two zeros compare equal
+ * regardless of sign, while everything else depends on sign.
+ *
+ * Incidentally, two Infs of the same sign compare equal (per the 80387
+ * manual---it would be nice if the SPARC documentation were more
+ * complete).
+ */
+void
+__fpu_compare(struct fpemu *fe, int cmpe, int fcc)
+{
+ struct fpn *a, *b;
+ int cc;
+ FPU_DECL_CARRY
+
+ a = &fe->fe_f1;
+ b = &fe->fe_f2;
+
+ if (ISNAN(a) || ISNAN(b)) {
+ /*
+ * In any case, we already got an exception for signalling
+ * NaNs; here we may replace that one with an identical
+ * exception, but so what?.
+ */
+ if (cmpe)
+ fe->fe_cx = FSR_NV;
+ cc = FSR_CC_UO;
+ goto done;
+ }
+
+ /*
+ * Must handle both-zero early to avoid sign goofs. Otherwise,
+ * at most one is 0, and if the signs differ we are done.
+ */
+ if (ISZERO(a) && ISZERO(b)) {
+ cc = FSR_CC_EQ;
+ goto done;
+ }
+ if (a->fp_sign) { /* a < 0 (or -0) */
+ if (!b->fp_sign) { /* b >= 0 (or if a = -0, b > 0) */
+ cc = FSR_CC_LT;
+ goto done;
+ }
+ } else { /* a > 0 (or +0) */
+ if (b->fp_sign) { /* b <= -0 (or if a = +0, b < 0) */
+ cc = FSR_CC_GT;
+ goto done;
+ }
+ }
+
+ /*
+ * Now the signs are the same (but may both be negative). All
+ * we have left are these cases:
+ *
+ * |a| < |b| [classes or values differ]
+ * |a| > |b| [classes or values differ]
+ * |a| == |b| [classes and values identical]
+ *
+ * We define `diff' here to expand these as:
+ *
+ * |a| < |b|, a,b >= 0: a < b => FSR_CC_LT
+ * |a| < |b|, a,b < 0: a > b => FSR_CC_GT
+ * |a| > |b|, a,b >= 0: a > b => FSR_CC_GT
+ * |a| > |b|, a,b < 0: a < b => FSR_CC_LT
+ */
+#define opposite_cc(cc) ((cc) == FSR_CC_LT ? FSR_CC_GT : FSR_CC_LT)
+#define diff(magnitude) (a->fp_sign ? opposite_cc(magnitude) : (magnitude))
+ if (a->fp_class < b->fp_class) { /* |a| < |b| */
+ cc = diff(FSR_CC_LT);
+ goto done;
+ }
+ if (a->fp_class > b->fp_class) { /* |a| > |b| */
+ cc = diff(FSR_CC_GT);
+ goto done;
+ }
+ /* now none can be 0: only Inf and numbers remain */
+ if (ISINF(a)) { /* |Inf| = |Inf| */
+ cc = FSR_CC_EQ;
+ goto done;
+ }
+ /*
+ * Only numbers remain. To compare two numbers in magnitude, we
+ * simply subtract them.
+ */
+ a = __fpu_sub(fe);
+ if (a->fp_class == FPC_ZERO)
+ cc = FSR_CC_EQ;
+ else
+ cc = diff(FSR_CC_GT);
+
+done:
+ fe->fe_fsr = (fe->fe_fsr & fcc_nmask[fcc]) |
+ ((u_long)cc << fcc_shift[fcc]);
+}
diff --git a/lib/libc/sparc64/fpu/fpu_div.c b/lib/libc/sparc64/fpu/fpu_div.c
new file mode 100644
index 0000000..4748daf
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu_div.c
@@ -0,0 +1,270 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fpu_div.c 8.1 (Berkeley) 6/11/93
+ * $NetBSD: fpu_div.c,v 1.2 1994/11/20 20:52:38 deraadt Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Perform an FPU divide (return x / y).
+ */
+
+#include <sys/types.h>
+
+#include <machine/frame.h>
+#include <machine/fp.h>
+#include <machine/fsr.h>
+
+#include "fpu_arith.h"
+#include "fpu_emu.h"
+#include "fpu_extern.h"
+
+/*
+ * Division of normal numbers is done as follows:
+ *
+ * x and y are floating point numbers, i.e., in the form 1.bbbb * 2^e.
+ * If X and Y are the mantissas (1.bbbb's), the quotient is then:
+ *
+ * q = (X / Y) * 2^((x exponent) - (y exponent))
+ *
+ * Since X and Y are both in [1.0,2.0), the quotient's mantissa (X / Y)
+ * will be in [0.5,2.0). Moreover, it will be less than 1.0 if and only
+ * if X < Y. In that case, it will have to be shifted left one bit to
+ * become a normal number, and the exponent decremented. Thus, the
+ * desired exponent is:
+ *
+ * left_shift = x->fp_mant < y->fp_mant;
+ * result_exp = x->fp_exp - y->fp_exp - left_shift;
+ *
+ * The quotient mantissa X/Y can then be computed one bit at a time
+ * using the following algorithm:
+ *
+ * Q = 0; -- Initial quotient.
+ * R = X; -- Initial remainder,
+ * if (left_shift) -- but fixed up in advance.
+ * R *= 2;
+ * for (bit = FP_NMANT; --bit >= 0; R *= 2) {
+ * if (R >= Y) {
+ * Q |= 1 << bit;
+ * R -= Y;
+ * }
+ * }
+ *
+ * The subtraction R -= Y always removes the uppermost bit from R (and
+ * can sometimes remove additional lower-order 1 bits); this proof is
+ * left to the reader.
+ *
+ * This loop correctly calculates the guard and round bits since they are
+ * included in the expanded internal representation. The sticky bit
+ * is to be set if and only if any other bits beyond guard and round
+ * would be set. From the above it is obvious that this is true if and
+ * only if the remainder R is nonzero when the loop terminates.
+ *
+ * Examining the loop above, we can see that the quotient Q is built
+ * one bit at a time ``from the top down''. This means that we can
+ * dispense with the multi-word arithmetic and just build it one word
+ * at a time, writing each result word when it is done.
+ *
+ * Furthermore, since X and Y are both in [1.0,2.0), we know that,
+ * initially, R >= Y. (Recall that, if X < Y, R is set to X * 2 and
+ * is therefore at in [2.0,4.0).) Thus Q is sure to have bit FP_NMANT-1
+ * set, and R can be set initially to either X - Y (when X >= Y) or
+ * 2X - Y (when X < Y). In addition, comparing R and Y is difficult,
+ * so we will simply calculate R - Y and see if that underflows.
+ * This leads to the following revised version of the algorithm:
+ *
+ * R = X;
+ * bit = FP_1;
+ * D = R - Y;
+ * if (D >= 0) {
+ * result_exp = x->fp_exp - y->fp_exp;
+ * R = D;
+ * q = bit;
+ * bit >>= 1;
+ * } else {
+ * result_exp = x->fp_exp - y->fp_exp - 1;
+ * q = 0;
+ * }
+ * R <<= 1;
+ * do {
+ * D = R - Y;
+ * if (D >= 0) {
+ * q |= bit;
+ * R = D;
+ * }
+ * R <<= 1;
+ * } while ((bit >>= 1) != 0);
+ * Q[0] = q;
+ * for (i = 1; i < 4; i++) {
+ * q = 0, bit = 1 << 31;
+ * do {
+ * D = R - Y;
+ * if (D >= 0) {
+ * q |= bit;
+ * R = D;
+ * }
+ * R <<= 1;
+ * } while ((bit >>= 1) != 0);
+ * Q[i] = q;
+ * }
+ *
+ * This can be refined just a bit further by moving the `R <<= 1'
+ * calculations to the front of the do-loops and eliding the first one.
+ * The process can be terminated immediately whenever R becomes 0, but
+ * this is relatively rare, and we do not bother.
+ */
+
+struct fpn *
+__fpu_div(fe)
+ struct fpemu *fe;
+{
+ struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2;
+ u_int q, bit;
+ u_int r0, r1, r2, r3, d0, d1, d2, d3, y0, y1, y2, y3;
+ FPU_DECL_CARRY
+
+ /*
+ * Since divide is not commutative, we cannot just use ORDER.
+ * Check either operand for NaN first; if there is at least one,
+ * order the signalling one (if only one) onto the right, then
+ * return it. Otherwise we have the following cases:
+ *
+ * Inf / Inf = NaN, plus NV exception
+ * Inf / num = Inf [i.e., return x #]
+ * Inf / 0 = Inf [i.e., return x #]
+ * 0 / Inf = 0 [i.e., return x #]
+ * 0 / num = 0 [i.e., return x #]
+ * 0 / 0 = NaN, plus NV exception
+ * num / Inf = 0 #
+ * num / num = num (do the divide)
+ * num / 0 = Inf #, plus DZ exception
+ *
+ * # Sign of result is XOR of operand signs.
+ */
+ if (ISNAN(x) || ISNAN(y)) {
+ ORDER(x, y);
+ return (y);
+ }
+ if (ISINF(x) || ISZERO(x)) {
+ if (x->fp_class == y->fp_class)
+ return (__fpu_newnan(fe));
+ x->fp_sign ^= y->fp_sign;
+ return (x);
+ }
+
+ x->fp_sign ^= y->fp_sign;
+ if (ISINF(y)) {
+ x->fp_class = FPC_ZERO;
+ return (x);
+ }
+ if (ISZERO(y)) {
+ fe->fe_cx = FSR_DZ;
+ x->fp_class = FPC_INF;
+ return (x);
+ }
+
+ /*
+ * Macros for the divide. See comments at top for algorithm.
+ * Note that we expand R, D, and Y here.
+ */
+
+#define SUBTRACT /* D = R - Y */ \
+ FPU_SUBS(d3, r3, y3); FPU_SUBCS(d2, r2, y2); \
+ FPU_SUBCS(d1, r1, y1); FPU_SUBC(d0, r0, y0)
+
+#define NONNEGATIVE /* D >= 0 */ \
+ ((int)d0 >= 0)
+
+#ifdef FPU_SHL1_BY_ADD
+#define SHL1 /* R <<= 1 */ \
+ FPU_ADDS(r3, r3, r3); FPU_ADDCS(r2, r2, r2); \
+ FPU_ADDCS(r1, r1, r1); FPU_ADDC(r0, r0, r0)
+#else
+#define SHL1 \
+ r0 = (r0 << 1) | (r1 >> 31), r1 = (r1 << 1) | (r2 >> 31), \
+ r2 = (r2 << 1) | (r3 >> 31), r3 <<= 1
+#endif
+
+#define LOOP /* do ... while (bit >>= 1) */ \
+ do { \
+ SHL1; \
+ SUBTRACT; \
+ if (NONNEGATIVE) { \
+ q |= bit; \
+ r0 = d0, r1 = d1, r2 = d2, r3 = d3; \
+ } \
+ } while ((bit >>= 1) != 0)
+
+#define WORD(r, i) /* calculate r->fp_mant[i] */ \
+ q = 0; \
+ bit = 1 << 31; \
+ LOOP; \
+ (x)->fp_mant[i] = q
+
+ /* Setup. Note that we put our result in x. */
+ r0 = x->fp_mant[0];
+ r1 = x->fp_mant[1];
+ r2 = x->fp_mant[2];
+ r3 = x->fp_mant[3];
+ y0 = y->fp_mant[0];
+ y1 = y->fp_mant[1];
+ y2 = y->fp_mant[2];
+ y3 = y->fp_mant[3];
+
+ bit = FP_1;
+ SUBTRACT;
+ if (NONNEGATIVE) {
+ x->fp_exp -= y->fp_exp;
+ r0 = d0, r1 = d1, r2 = d2, r3 = d3;
+ q = bit;
+ bit >>= 1;
+ } else {
+ x->fp_exp -= y->fp_exp + 1;
+ q = 0;
+ }
+ LOOP;
+ x->fp_mant[0] = q;
+ WORD(x, 1);
+ WORD(x, 2);
+ WORD(x, 3);
+ x->fp_sticky = r0 | r1 | r2 | r3;
+
+ return (x);
+}
diff --git a/lib/libc/sparc64/fpu/fpu_emu.h b/lib/libc/sparc64/fpu/fpu_emu.h
new file mode 100644
index 0000000..0822de8
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu_emu.h
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fpu_emu.h 8.1 (Berkeley) 6/11/93
+ * $NetBSD: fpu_emu.h,v 1.4 2000/08/03 18:32:07 eeh Exp $
+ * $FreeBSD$
+ */
+
+/*
+ * Floating point emulator (tailored for SPARC, but structurally
+ * machine-independent).
+ *
+ * Floating point numbers are carried around internally in an `expanded'
+ * or `unpacked' form consisting of:
+ * - sign
+ * - unbiased exponent
+ * - mantissa (`1.' + 112-bit fraction + guard + round)
+ * - sticky bit
+ * Any implied `1' bit is inserted, giving a 113-bit mantissa that is
+ * always nonzero. Additional low-order `guard' and `round' bits are
+ * scrunched in, making the entire mantissa 115 bits long. This is divided
+ * into four 32-bit words, with `spare' bits left over in the upper part
+ * of the top word (the high bits of fp_mant[0]). An internal `exploded'
+ * number is thus kept within the half-open interval [1.0,2.0) (but see
+ * the `number classes' below). This holds even for denormalized numbers:
+ * when we explode an external denorm, we normalize it, introducing low-order
+ * zero bits, so that the rest of the code always sees normalized values.
+ *
+ * Note that a number of our algorithms use the `spare' bits at the top.
+ * The most demanding algorithm---the one for sqrt---depends on two such
+ * bits, so that it can represent values up to (but not including) 8.0,
+ * and then it needs a carry on top of that, so that we need three `spares'.
+ *
+ * The sticky-word is 32 bits so that we can use `OR' operators to goosh
+ * whole words from the mantissa into it.
+ *
+ * All operations are done in this internal extended precision. According
+ * to Hennesey & Patterson, Appendix A, rounding can be repeated---that is,
+ * it is OK to do a+b in extended precision and then round the result to
+ * single precision---provided single, double, and extended precisions are
+ * `far enough apart' (they always are), but we will try to avoid any such
+ * extra work where possible.
+ */
+
+#ifndef _SPARC64_FPU_FPU_EMU_H_
+#define _SPARC64_FPU_FPU_EMU_H_
+
+#include "fpu_reg.h"
+
+struct fpn {
+ int fp_class; /* see below */
+ int fp_sign; /* 0 => positive, 1 => negative */
+ int fp_exp; /* exponent (unbiased) */
+ int fp_sticky; /* nonzero bits lost at right end */
+ u_int fp_mant[4]; /* 115-bit mantissa */
+};
+
+#define FP_NMANT 115 /* total bits in mantissa (incl g,r) */
+#define FP_NG 2 /* number of low-order guard bits */
+#define FP_LG ((FP_NMANT - 1) & 31) /* log2(1.0) for fp_mant[0] */
+#define FP_LG2 ((FP_NMANT - 1) & 63) /* log2(1.0) for fp_mant[0] and fp_mant[1] */
+#define FP_QUIETBIT (1 << (FP_LG - 1)) /* Quiet bit in NaNs (0.5) */
+#define FP_1 (1 << FP_LG) /* 1.0 in fp_mant[0] */
+#define FP_2 (1 << (FP_LG + 1)) /* 2.0 in fp_mant[0] */
+
+/*
+ * Number classes. Since zero, Inf, and NaN cannot be represented using
+ * the above layout, we distinguish these from other numbers via a class.
+ * In addition, to make computation easier and to follow Appendix N of
+ * the SPARC Version 8 standard, we give each kind of NaN a separate class.
+ */
+#define FPC_SNAN -2 /* signalling NaN (sign irrelevant) */
+#define FPC_QNAN -1 /* quiet NaN (sign irrelevant) */
+#define FPC_ZERO 0 /* zero (sign matters) */
+#define FPC_NUM 1 /* number (sign matters) */
+#define FPC_INF 2 /* infinity (sign matters) */
+
+#define ISNAN(fp) ((fp)->fp_class < 0)
+#define ISZERO(fp) ((fp)->fp_class == 0)
+#define ISINF(fp) ((fp)->fp_class == FPC_INF)
+
+/*
+ * ORDER(x,y) `sorts' a pair of `fpn *'s so that the right operand (y) points
+ * to the `more significant' operand for our purposes. Appendix N says that
+ * the result of a computation involving two numbers are:
+ *
+ * If both are SNaN: operand 2, converted to Quiet
+ * If only one is SNaN: the SNaN operand, converted to Quiet
+ * If both are QNaN: operand 2
+ * If only one is QNaN: the QNaN operand
+ *
+ * In addition, in operations with an Inf operand, the result is usually
+ * Inf. The class numbers are carefully arranged so that if
+ * (unsigned)class(op1) > (unsigned)class(op2)
+ * then op1 is the one we want; otherwise op2 is the one we want.
+ */
+#define ORDER(x, y) { \
+ if ((u_int)(x)->fp_class > (u_int)(y)->fp_class) \
+ SWAP(x, y); \
+}
+#define SWAP(x, y) { \
+ register struct fpn *swap; \
+ swap = (x), (x) = (y), (y) = swap; \
+}
+
+/*
+ * Floating point operand types. FTYPE_LNG is syntethic (it does not occur in
+ * instructions).
+ */
+#define FTYPE_INT INSFP_i
+#define FTYPE_SNG INSFP_s
+#define FTYPE_DBL INSFP_d
+#define FTYPE_EXT INSFP_q
+#define FTYPE_LNG 4
+
+/*
+ * Emulator state.
+ */
+struct fpemu {
+ u_long fe_fsr; /* fsr copy (modified during op) */
+ int fe_cx; /* exceptions */
+ int pad; /* align access to following fields */
+ struct fpn fe_f1; /* operand 1 */
+ struct fpn fe_f2; /* operand 2, if required */
+ struct fpn fe_f3; /* available storage for result */
+};
+
+/*
+ * Arithmetic functions.
+ * Each of these may modify its inputs (f1,f2) and/or the temporary.
+ * Each returns a pointer to the result and/or sets exceptions.
+ */
+#define __fpu_sub(fe) (ISNAN(&(fe)->fe_f2) ? 0 : ((fe)->fe_f2.fp_sign ^= 1), \
+ __fpu_add(fe))
+
+#ifdef FPU_DEBUG
+#define FPE_INSN 0x1
+#define FPE_REG 0x2
+extern int __fpe_debug;
+void __fpu_dumpfpn(struct fpn *);
+#define DPRINTF(x, y) if (__fpe_debug & (x)) printf y
+#define DUMPFPN(x, f) if (__fpe_debug & (x)) __fpu_dumpfpn((f))
+#else
+#define DPRINTF(x, y)
+#define DUMPFPN(x, f)
+#endif
+
+#endif /* !_SPARC64_FPU_FPU_EXTERN_H_ */
diff --git a/lib/libc/sparc64/fpu/fpu_explode.c b/lib/libc/sparc64/fpu/fpu_explode.c
new file mode 100644
index 0000000..474e0df
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu_explode.c
@@ -0,0 +1,324 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fpu_explode.c 8.1 (Berkeley) 6/11/93
+ * $NetBSD: fpu_explode.c,v 1.5 2000/08/03 18:32:08 eeh Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * FPU subroutines: `explode' the machine's `packed binary' format numbers
+ * into our internal format.
+ */
+
+#include <sys/param.h>
+
+#ifdef FPU_DEBUG
+#include <stdio.h>
+#endif
+
+#include <machine/frame.h>
+#include <machine/fp.h>
+#include <machine/fsr.h>
+#include <machine/ieee.h>
+#include <machine/instr.h>
+
+#include "fpu_arith.h"
+#include "fpu_emu.h"
+#include "fpu_extern.h"
+#include "__sparc_utrap_private.h"
+
+/*
+ * N.B.: in all of the following, we assume the FP format is
+ *
+ * ---------------------------
+ * | s | exponent | fraction |
+ * ---------------------------
+ *
+ * (which represents -1**s * 1.fraction * 2**exponent), so that the
+ * sign bit is way at the top (bit 31), the exponent is next, and
+ * then the remaining bits mark the fraction. A zero exponent means
+ * zero or denormalized (0.fraction rather than 1.fraction), and the
+ * maximum possible exponent, 2bias+1, signals inf (fraction==0) or NaN.
+ *
+ * Since the sign bit is always the topmost bit---this holds even for
+ * integers---we set that outside all the *tof functions. Each function
+ * returns the class code for the new number (but note that we use
+ * FPC_QNAN for all NaNs; fpu_explode will fix this if appropriate).
+ */
+
+/*
+ * int -> fpn.
+ */
+int
+__fpu_itof(fp, i)
+ struct fpn *fp;
+ u_int i;
+{
+
+ if (i == 0)
+ return (FPC_ZERO);
+ /*
+ * The value FP_1 represents 2^FP_LG, so set the exponent
+ * there and let normalization fix it up. Convert negative
+ * numbers to sign-and-magnitude. Note that this relies on
+ * fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
+ */
+ fp->fp_exp = FP_LG;
+ /*
+ * The sign bit decides whether i should be interpreted as
+ * a signed or unsigned entity.
+ */
+ if (fp->fp_sign && (int)i < 0)
+ fp->fp_mant[0] = -i;
+ else
+ fp->fp_mant[0] = i;
+ fp->fp_mant[1] = 0;
+ fp->fp_mant[2] = 0;
+ fp->fp_mant[3] = 0;
+ __fpu_norm(fp);
+ return (FPC_NUM);
+}
+
+/*
+ * 64-bit int -> fpn.
+ */
+int
+__fpu_xtof(fp, i)
+ struct fpn *fp;
+ u_int64_t i;
+{
+
+ if (i == 0)
+ return (FPC_ZERO);
+ /*
+ * The value FP_1 represents 2^FP_LG, so set the exponent
+ * there and let normalization fix it up. Convert negative
+ * numbers to sign-and-magnitude. Note that this relies on
+ * fpu_norm()'s handling of `supernormals'; see fpu_subr.c.
+ */
+ fp->fp_exp = FP_LG2;
+ /*
+ * The sign bit decides whether i should be interpreted as
+ * a signed or unsigned entity.
+ */
+ if (fp->fp_sign && (int64_t)i < 0)
+ *((int64_t *)fp->fp_mant) = -i;
+ else
+ *((int64_t *)fp->fp_mant) = i;
+ fp->fp_mant[2] = 0;
+ fp->fp_mant[3] = 0;
+ __fpu_norm(fp);
+ return (FPC_NUM);
+}
+
+#define mask(nbits) ((1L << (nbits)) - 1)
+
+/*
+ * All external floating formats convert to internal in the same manner,
+ * as defined here. Note that only normals get an implied 1.0 inserted.
+ */
+#define FP_TOF(exp, expbias, allfrac, f0, f1, f2, f3) \
+ if (exp == 0) { \
+ if (allfrac == 0) \
+ return (FPC_ZERO); \
+ fp->fp_exp = 1 - expbias; \
+ fp->fp_mant[0] = f0; \
+ fp->fp_mant[1] = f1; \
+ fp->fp_mant[2] = f2; \
+ fp->fp_mant[3] = f3; \
+ __fpu_norm(fp); \
+ return (FPC_NUM); \
+ } \
+ if (exp == (2 * expbias + 1)) { \
+ if (allfrac == 0) \
+ return (FPC_INF); \
+ fp->fp_mant[0] = f0; \
+ fp->fp_mant[1] = f1; \
+ fp->fp_mant[2] = f2; \
+ fp->fp_mant[3] = f3; \
+ return (FPC_QNAN); \
+ } \
+ fp->fp_exp = exp - expbias; \
+ fp->fp_mant[0] = FP_1 | f0; \
+ fp->fp_mant[1] = f1; \
+ fp->fp_mant[2] = f2; \
+ fp->fp_mant[3] = f3; \
+ return (FPC_NUM)
+
+/*
+ * 32-bit single precision -> fpn.
+ * We assume a single occupies at most (64-FP_LG) bits in the internal
+ * format: i.e., needs at most fp_mant[0] and fp_mant[1].
+ */
+int
+__fpu_stof(fp, i)
+ struct fpn *fp;
+ u_int i;
+{
+ int exp;
+ u_int frac, f0, f1;
+#define SNG_SHIFT (SNG_FRACBITS - FP_LG)
+
+ exp = (i >> (32 - 1 - SNG_EXPBITS)) & mask(SNG_EXPBITS);
+ frac = i & mask(SNG_FRACBITS);
+ f0 = frac >> SNG_SHIFT;
+ f1 = frac << (32 - SNG_SHIFT);
+ FP_TOF(exp, SNG_EXP_BIAS, frac, f0, f1, 0, 0);
+}
+
+/*
+ * 64-bit double -> fpn.
+ * We assume this uses at most (96-FP_LG) bits.
+ */
+int
+__fpu_dtof(fp, i, j)
+ struct fpn *fp;
+ u_int i, j;
+{
+ int exp;
+ u_int frac, f0, f1, f2;
+#define DBL_SHIFT (DBL_FRACBITS - 32 - FP_LG)
+
+ exp = (i >> (32 - 1 - DBL_EXPBITS)) & mask(DBL_EXPBITS);
+ frac = i & mask(DBL_FRACBITS - 32);
+ f0 = frac >> DBL_SHIFT;
+ f1 = (frac << (32 - DBL_SHIFT)) | (j >> DBL_SHIFT);
+ f2 = j << (32 - DBL_SHIFT);
+ frac |= j;
+ FP_TOF(exp, DBL_EXP_BIAS, frac, f0, f1, f2, 0);
+}
+
+/*
+ * 128-bit extended -> fpn.
+ */
+int
+__fpu_qtof(fp, i, j, k, l)
+ struct fpn *fp;
+ u_int i, j, k, l;
+{
+ int exp;
+ u_int frac, f0, f1, f2, f3;
+#define EXT_SHIFT (-(EXT_FRACBITS - 3 * 32 - FP_LG)) /* left shift! */
+
+ /*
+ * Note that ext and fpn `line up', hence no shifting needed.
+ */
+ exp = (i >> (32 - 1 - EXT_EXPBITS)) & mask(EXT_EXPBITS);
+ frac = i & mask(EXT_FRACBITS - 3 * 32);
+ f0 = (frac << EXT_SHIFT) | (j >> (32 - EXT_SHIFT));
+ f1 = (j << EXT_SHIFT) | (k >> (32 - EXT_SHIFT));
+ f2 = (k << EXT_SHIFT) | (l >> (32 - EXT_SHIFT));
+ f3 = l << EXT_SHIFT;
+ frac |= j | k | l;
+ FP_TOF(exp, EXT_EXP_BIAS, frac, f0, f1, f2, f3);
+}
+
+/*
+ * Explode the contents of a / regpair / regquad.
+ * If the input is a signalling NaN, an NV (invalid) exception
+ * will be set. (Note that nothing but NV can occur until ALU
+ * operations are performed.)
+ */
+void
+__fpu_explode(fe, fp, type, reg)
+ struct fpemu *fe;
+ struct fpn *fp;
+ int type, reg;
+{
+ u_int64_t l0, l1;
+ u_int32_t s;
+
+ if (type == FTYPE_LNG || type == FTYPE_DBL || type == FTYPE_EXT) {
+ l0 = __fpu_getreg64(reg & ~1);
+ fp->fp_sign = l0 >> 63;
+ } else {
+ s = __fpu_getreg(reg);
+ fp->fp_sign = s >> 31;
+ }
+ fp->fp_sticky = 0;
+ switch (type) {
+ case FTYPE_LNG:
+ s = __fpu_xtof(fp, l0);
+ break;
+
+ case FTYPE_INT:
+ s = __fpu_itof(fp, s);
+ break;
+
+ case FTYPE_SNG:
+ s = __fpu_stof(fp, s);
+ break;
+
+ case FTYPE_DBL:
+ s = __fpu_dtof(fp, l0 >> 32, l0 & 0xffffffff);
+ break;
+
+ case FTYPE_EXT:
+ l1 = __fpu_getreg64((reg & ~1) + 2);
+ s = __fpu_qtof(fp, l0 >> 32, l0 & 0xffffffff, l1 >> 32,
+ l1 & 0xffffffff);
+ break;
+
+ default:
+ __utrap_panic("fpu_explode");
+ }
+
+ if (s == FPC_QNAN && (fp->fp_mant[0] & FP_QUIETBIT) == 0) {
+ /*
+ * Input is a signalling NaN. All operations that return
+ * an input NaN operand put it through a ``NaN conversion'',
+ * which basically just means ``turn on the quiet bit''.
+ * We do this here so that all NaNs internally look quiet
+ * (we can tell signalling ones by their class).
+ */
+ fp->fp_mant[0] |= FP_QUIETBIT;
+ fe->fe_cx = FSR_NV; /* assert invalid operand */
+ s = FPC_SNAN;
+ }
+ fp->fp_class = s;
+ DPRINTF(FPE_REG, ("fpu_explode: %%%c%d => ", (type == FTYPE_LNG) ? 'x' :
+ ((type == FTYPE_INT) ? 'i' :
+ ((type == FTYPE_SNG) ? 's' :
+ ((type == FTYPE_DBL) ? 'd' :
+ ((type == FTYPE_EXT) ? 'q' : '?')))),
+ reg));
+ DUMPFPN(FPE_REG, fp);
+ DPRINTF(FPE_REG, ("\n"));
+}
diff --git a/lib/libc/sparc64/fpu/fpu_extern.h b/lib/libc/sparc64/fpu/fpu_extern.h
new file mode 100644
index 0000000..a5fb942
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu_extern.h
@@ -0,0 +1,85 @@
+/*-
+ * Copyright (c) 1995 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Christos Zoulas.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $NetBSD: fpu_extern.h,v 1.4 2000/08/03 18:32:08 eeh Exp $
+ * $FreeBSD$
+ */
+
+#ifndef _SPARC64_FPU_FPU_EXTERN_H_
+#define _SPARC64_FPU_FPU_EXTERN_H_
+
+struct utrapframe;
+struct fpemu;
+struct fpn;
+
+/* fpu.c */
+int __fpu_exception(struct utrapframe *tf);
+
+/* fpu_add.c */
+struct fpn *__fpu_add(struct fpemu *);
+
+/* fpu_compare.c */
+void __fpu_compare(struct fpemu *, int, int);
+
+/* fpu_div.c */
+struct fpn *__fpu_div(struct fpemu *);
+
+/* fpu_explode.c */
+int __fpu_itof(struct fpn *, u_int);
+int __fpu_xtof(struct fpn *, u_int64_t);
+int __fpu_stof(struct fpn *, u_int);
+int __fpu_dtof(struct fpn *, u_int, u_int);
+int __fpu_qtof(struct fpn *, u_int, u_int, u_int, u_int);
+void __fpu_explode(struct fpemu *, struct fpn *, int, int);
+
+/* fpu_implode.c */
+u_int __fpu_ftoi(struct fpemu *, struct fpn *);
+u_int __fpu_ftox(struct fpemu *, struct fpn *, u_int *);
+u_int __fpu_ftos(struct fpemu *, struct fpn *);
+u_int __fpu_ftod(struct fpemu *, struct fpn *, u_int *);
+u_int __fpu_ftoq(struct fpemu *, struct fpn *, u_int *);
+void __fpu_implode(struct fpemu *, struct fpn *, int, u_int *);
+
+/* fpu_mul.c */
+struct fpn *__fpu_mul(struct fpemu *);
+
+/* fpu_sqrt.c */
+struct fpn *__fpu_sqrt(struct fpemu *);
+
+/* fpu_subr.c */
+/*
+ * Shift a number right some number of bits, taking care of round/sticky.
+ * Note that the result is probably not a well-formed number (it will lack
+ * the normal 1-bit mant[0]&FP_1).
+ */
+int __fpu_shr(register struct fpn *, register int);
+void __fpu_norm(register struct fpn *);
+/* Build a new Quiet NaN (sign=0, frac=all 1's). */
+struct fpn *__fpu_newnan(register struct fpemu *);
+
+#endif /* !_SPARC64_FPU_FPU_EXTERN_H_ */
diff --git a/lib/libc/sparc64/fpu/fpu_implode.c b/lib/libc/sparc64/fpu/fpu_implode.c
new file mode 100644
index 0000000..2a2a9d0
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu_implode.c
@@ -0,0 +1,542 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fpu_implode.c 8.1 (Berkeley) 6/11/93
+ * $NetBSD: fpu_implode.c,v 1.8 2001/08/26 05:44:46 eeh Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * FPU subroutines: `implode' internal format numbers into the machine's
+ * `packed binary' format.
+ */
+
+#include <sys/param.h>
+
+#ifdef FPU_DEBUG
+#include <stdio.h>
+#endif
+
+#include <machine/frame.h>
+#include <machine/fp.h>
+#include <machine/fsr.h>
+#include <machine/ieee.h>
+#include <machine/instr.h>
+
+#include "fpu_arith.h"
+#include "fpu_emu.h"
+#include "fpu_extern.h"
+#include "__sparc_utrap_private.h"
+
+static int fpround(struct fpemu *, struct fpn *);
+static int toinf(struct fpemu *, int);
+
+/*
+ * Round a number (algorithm from Motorola MC68882 manual, modified for
+ * our internal format). Set inexact exception if rounding is required.
+ * Return true iff we rounded up.
+ *
+ * After rounding, we discard the guard and round bits by shifting right
+ * 2 bits (a la fpu_shr(), but we do not bother with fp->fp_sticky).
+ * This saves effort later.
+ *
+ * Note that we may leave the value 2.0 in fp->fp_mant; it is the caller's
+ * responsibility to fix this if necessary.
+ */
+static int
+fpround(struct fpemu *fe, struct fpn *fp)
+{
+ u_int m0, m1, m2, m3;
+ int gr, s;
+
+ m0 = fp->fp_mant[0];
+ m1 = fp->fp_mant[1];
+ m2 = fp->fp_mant[2];
+ m3 = fp->fp_mant[3];
+ gr = m3 & 3;
+ s = fp->fp_sticky;
+
+ /* mant >>= FP_NG */
+ m3 = (m3 >> FP_NG) | (m2 << (32 - FP_NG));
+ m2 = (m2 >> FP_NG) | (m1 << (32 - FP_NG));
+ m1 = (m1 >> FP_NG) | (m0 << (32 - FP_NG));
+ m0 >>= FP_NG;
+
+ if ((gr | s) == 0) /* result is exact: no rounding needed */
+ goto rounddown;
+
+ fe->fe_cx |= FSR_NX; /* inexact */
+
+ /* Go to rounddown to round down; break to round up. */
+ switch (FSR_GET_RD(fe->fe_fsr)) {
+ case FSR_RD_N:
+ default:
+ /*
+ * Round only if guard is set (gr & 2). If guard is set,
+ * but round & sticky both clear, then we want to round
+ * but have a tie, so round to even, i.e., add 1 iff odd.
+ */
+ if ((gr & 2) == 0)
+ goto rounddown;
+ if ((gr & 1) || fp->fp_sticky || (m3 & 1))
+ break;
+ goto rounddown;
+
+ case FSR_RD_Z:
+ /* Round towards zero, i.e., down. */
+ goto rounddown;
+
+ case FSR_RD_NINF:
+ /* Round towards -Inf: up if negative, down if positive. */
+ if (fp->fp_sign)
+ break;
+ goto rounddown;
+
+ case FSR_RD_PINF:
+ /* Round towards +Inf: up if positive, down otherwise. */
+ if (!fp->fp_sign)
+ break;
+ goto rounddown;
+ }
+
+ /* Bump low bit of mantissa, with carry. */
+ FPU_ADDS(m3, m3, 1);
+ FPU_ADDCS(m2, m2, 0);
+ FPU_ADDCS(m1, m1, 0);
+ FPU_ADDC(m0, m0, 0);
+ fp->fp_mant[0] = m0;
+ fp->fp_mant[1] = m1;
+ fp->fp_mant[2] = m2;
+ fp->fp_mant[3] = m3;
+ return (1);
+
+rounddown:
+ fp->fp_mant[0] = m0;
+ fp->fp_mant[1] = m1;
+ fp->fp_mant[2] = m2;
+ fp->fp_mant[3] = m3;
+ return (0);
+}
+
+/*
+ * For overflow: return true if overflow is to go to +/-Inf, according
+ * to the sign of the overflowing result. If false, overflow is to go
+ * to the largest magnitude value instead.
+ */
+static int
+toinf(struct fpemu *fe, int sign)
+{
+ int inf;
+
+ /* look at rounding direction */
+ switch (FSR_GET_RD(fe->fe_fsr)) {
+ default:
+ case FSR_RD_N: /* the nearest value is always Inf */
+ inf = 1;
+ break;
+
+ case FSR_RD_Z: /* toward 0 => never towards Inf */
+ inf = 0;
+ break;
+
+ case FSR_RD_PINF: /* toward +Inf iff positive */
+ inf = sign == 0;
+ break;
+
+ case FSR_RD_NINF: /* toward -Inf iff negative */
+ inf = sign;
+ break;
+ }
+ return (inf);
+}
+
+/*
+ * fpn -> int (int value returned as return value).
+ *
+ * N.B.: this conversion always rounds towards zero (this is a peculiarity
+ * of the SPARC instruction set).
+ */
+u_int
+__fpu_ftoi(fe, fp)
+ struct fpemu *fe;
+ struct fpn *fp;
+{
+ u_int i;
+ int sign, exp;
+
+ sign = fp->fp_sign;
+ switch (fp->fp_class) {
+ case FPC_ZERO:
+ return (0);
+
+ case FPC_NUM:
+ /*
+ * If exp >= 2^32, overflow. Otherwise shift value right
+ * into last mantissa word (this will not exceed 0xffffffff),
+ * shifting any guard and round bits out into the sticky
+ * bit. Then ``round'' towards zero, i.e., just set an
+ * inexact exception if sticky is set (see round()).
+ * If the result is > 0x80000000, or is positive and equals
+ * 0x80000000, overflow; otherwise the last fraction word
+ * is the result.
+ */
+ if ((exp = fp->fp_exp) >= 32)
+ break;
+ /* NB: the following includes exp < 0 cases */
+ if (__fpu_shr(fp, FP_NMANT - 1 - exp) != 0)
+ fe->fe_cx |= FSR_NX;
+ i = fp->fp_mant[3];
+ if (i >= ((u_int)0x80000000 + sign))
+ break;
+ return (sign ? -i : i);
+
+ default: /* Inf, qNaN, sNaN */
+ break;
+ }
+ /* overflow: replace any inexact exception with invalid */
+ fe->fe_cx = (fe->fe_cx & ~FSR_NX) | FSR_NV;
+ return (0x7fffffff + sign);
+}
+
+/*
+ * fpn -> extended int (high bits of int value returned as return value).
+ *
+ * N.B.: this conversion always rounds towards zero (this is a peculiarity
+ * of the SPARC instruction set).
+ */
+u_int
+__fpu_ftox(fe, fp, res)
+ struct fpemu *fe;
+ struct fpn *fp;
+ u_int *res;
+{
+ u_int64_t i;
+ int sign, exp;
+
+ sign = fp->fp_sign;
+ switch (fp->fp_class) {
+ case FPC_ZERO:
+ i = 0;
+ goto done;
+
+ case FPC_NUM:
+ /*
+ * If exp >= 2^64, overflow. Otherwise shift value
+ * right into last mantissa word (this will not exceed
+ * 0xffffffffffffffff), shifting any guard and round
+ * bits out into the sticky bit. Then ``round'' towards
+ * zero, i.e., just set an inexact exception if sticky
+ * is set (see round()).
+ * If the result is > 0x8000000000000000, or is positive
+ * and equals 0x8000000000000000, overflow; otherwise
+ * the last fraction word is the result.
+ */
+ if ((exp = fp->fp_exp) >= 64)
+ break;
+ /* NB: the following includes exp < 0 cases */
+ if (__fpu_shr(fp, FP_NMANT - 1 - exp) != 0)
+ fe->fe_cx |= FSR_NX;
+ i = ((u_int64_t)fp->fp_mant[2]<<32)|fp->fp_mant[3];
+ if (i >= ((u_int64_t)0x8000000000000000LL + sign))
+ break;
+ if (sign)
+ i = -i;
+ goto done;
+
+ default: /* Inf, qNaN, sNaN */
+ break;
+ }
+ /* overflow: replace any inexact exception with invalid */
+ fe->fe_cx = (fe->fe_cx & ~FSR_NX) | FSR_NV;
+ i = 0x7fffffffffffffffLL + sign;
+done:
+ res[1] = i & 0xffffffff;
+ return (i >> 32);
+}
+
+/*
+ * fpn -> single (32 bit single returned as return value).
+ * We assume <= 29 bits in a single-precision fraction (1.f part).
+ */
+u_int
+__fpu_ftos(fe, fp)
+ struct fpemu *fe;
+ struct fpn *fp;
+{
+ u_int sign = fp->fp_sign << 31;
+ int exp;
+
+#define SNG_EXP(e) ((e) << SNG_FRACBITS) /* makes e an exponent */
+#define SNG_MASK (SNG_EXP(1) - 1) /* mask for fraction */
+
+ /* Take care of non-numbers first. */
+ if (ISNAN(fp)) {
+ /*
+ * Preserve upper bits of NaN, per SPARC V8 appendix N.
+ * Note that fp->fp_mant[0] has the quiet bit set,
+ * even if it is classified as a signalling NaN.
+ */
+ (void) __fpu_shr(fp, FP_NMANT - 1 - SNG_FRACBITS);
+ exp = SNG_EXP_INFNAN;
+ goto done;
+ }
+ if (ISINF(fp))
+ return (sign | SNG_EXP(SNG_EXP_INFNAN));
+ if (ISZERO(fp))
+ return (sign);
+
+ /*
+ * Normals (including subnormals). Drop all the fraction bits
+ * (including the explicit ``implied'' 1 bit) down into the
+ * single-precision range. If the number is subnormal, move
+ * the ``implied'' 1 into the explicit range as well, and shift
+ * right to introduce leading zeroes. Rounding then acts
+ * differently for normals and subnormals: the largest subnormal
+ * may round to the smallest normal (1.0 x 2^minexp), or may
+ * remain subnormal. A number that is subnormal before rounding
+ * will signal an underflow if the result is inexact or if underflow
+ * traps are enabled.
+ *
+ * Rounding a normal, on the other hand, always produces another
+ * normal (although either way the result might be too big for
+ * single precision, and cause an overflow). If rounding a
+ * normal produces 2.0 in the fraction, we need not adjust that
+ * fraction at all, since both 1.0 and 2.0 are zero under the
+ * fraction mask.
+ *
+ * Note that the guard and round bits vanish from the number after
+ * rounding.
+ */
+ if ((exp = fp->fp_exp + SNG_EXP_BIAS) <= 0) { /* subnormal */
+ /* -NG for g,r; -SNG_FRACBITS-exp for fraction */
+ (void) __fpu_shr(fp, FP_NMANT - FP_NG - SNG_FRACBITS - exp);
+ if (fpround(fe, fp) && fp->fp_mant[3] == SNG_EXP(1)) {
+ fe->fe_cx |= FSR_UF;
+ return (sign | SNG_EXP(1) | 0);
+ }
+ if ((fe->fe_cx & FSR_NX) ||
+ (fe->fe_fsr & (FSR_UF << FSR_TEM_SHIFT)))
+ fe->fe_cx |= FSR_UF;
+ return (sign | SNG_EXP(0) | fp->fp_mant[3]);
+ }
+ /* -FP_NG for g,r; -1 for implied 1; -SNG_FRACBITS for fraction */
+ (void) __fpu_shr(fp, FP_NMANT - FP_NG - 1 - SNG_FRACBITS);
+#ifdef DIAGNOSTIC
+ if ((fp->fp_mant[3] & SNG_EXP(1 << FP_NG)) == 0)
+ __utrap_panic("fpu_ftos");
+#endif
+ if (fpround(fe, fp) && fp->fp_mant[3] == SNG_EXP(2))
+ exp++;
+ if (exp >= SNG_EXP_INFNAN) {
+ /* overflow to inf or to max single */
+ fe->fe_cx |= FSR_OF | FSR_NX;
+ if (toinf(fe, sign))
+ return (sign | SNG_EXP(SNG_EXP_INFNAN));
+ return (sign | SNG_EXP(SNG_EXP_INFNAN - 1) | SNG_MASK);
+ }
+done:
+ /* phew, made it */
+ return (sign | SNG_EXP(exp) | (fp->fp_mant[3] & SNG_MASK));
+}
+
+/*
+ * fpn -> double (32 bit high-order result returned; 32-bit low order result
+ * left in res[1]). Assumes <= 61 bits in double precision fraction.
+ *
+ * This code mimics fpu_ftos; see it for comments.
+ */
+u_int
+__fpu_ftod(fe, fp, res)
+ struct fpemu *fe;
+ struct fpn *fp;
+ u_int *res;
+{
+ u_int sign = fp->fp_sign << 31;
+ int exp;
+
+#define DBL_EXP(e) ((e) << (DBL_FRACBITS & 31))
+#define DBL_MASK (DBL_EXP(1) - 1)
+
+ if (ISNAN(fp)) {
+ (void) __fpu_shr(fp, FP_NMANT - 1 - DBL_FRACBITS);
+ exp = DBL_EXP_INFNAN;
+ goto done;
+ }
+ if (ISINF(fp)) {
+ sign |= DBL_EXP(DBL_EXP_INFNAN);
+ goto zero;
+ }
+ if (ISZERO(fp)) {
+zero: res[1] = 0;
+ return (sign);
+ }
+
+ if ((exp = fp->fp_exp + DBL_EXP_BIAS) <= 0) {
+ (void) __fpu_shr(fp, FP_NMANT - FP_NG - DBL_FRACBITS - exp);
+ if (fpround(fe, fp) && fp->fp_mant[2] == DBL_EXP(1)) {
+ fe->fe_cx |= FSR_UF;
+ res[1] = 0;
+ return (sign | DBL_EXP(1) | 0);
+ }
+ if ((fe->fe_cx & FSR_NX) ||
+ (fe->fe_fsr & (FSR_UF << FSR_TEM_SHIFT)))
+ fe->fe_cx |= FSR_UF;
+ exp = 0;
+ goto done;
+ }
+ (void) __fpu_shr(fp, FP_NMANT - FP_NG - 1 - DBL_FRACBITS);
+ if (fpround(fe, fp) && fp->fp_mant[2] == DBL_EXP(2))
+ exp++;
+ if (exp >= DBL_EXP_INFNAN) {
+ fe->fe_cx |= FSR_OF | FSR_NX;
+ if (toinf(fe, sign)) {
+ res[1] = 0;
+ return (sign | DBL_EXP(DBL_EXP_INFNAN) | 0);
+ }
+ res[1] = ~0;
+ return (sign | DBL_EXP(DBL_EXP_INFNAN - 1) | DBL_MASK);
+ }
+done:
+ res[1] = fp->fp_mant[3];
+ return (sign | DBL_EXP(exp) | (fp->fp_mant[2] & DBL_MASK));
+}
+
+/*
+ * fpn -> extended (32 bit high-order result returned; low-order fraction
+ * words left in res[1]..res[3]). Like ftod, which is like ftos ... but
+ * our internal format *is* extended precision, plus 2 bits for guard/round,
+ * so we can avoid a small bit of work.
+ */
+u_int
+__fpu_ftoq(fe, fp, res)
+ struct fpemu *fe;
+ struct fpn *fp;
+ u_int *res;
+{
+ u_int sign = fp->fp_sign << 31;
+ int exp;
+
+#define EXT_EXP(e) ((e) << (EXT_FRACBITS & 31))
+#define EXT_MASK (EXT_EXP(1) - 1)
+
+ if (ISNAN(fp)) {
+ (void) __fpu_shr(fp, 2); /* since we are not rounding */
+ exp = EXT_EXP_INFNAN;
+ goto done;
+ }
+ if (ISINF(fp)) {
+ sign |= EXT_EXP(EXT_EXP_INFNAN);
+ goto zero;
+ }
+ if (ISZERO(fp)) {
+zero: res[1] = res[2] = res[3] = 0;
+ return (sign);
+ }
+
+ if ((exp = fp->fp_exp + EXT_EXP_BIAS) <= 0) {
+ (void) __fpu_shr(fp, FP_NMANT - FP_NG - EXT_FRACBITS - exp);
+ if (fpround(fe, fp) && fp->fp_mant[0] == EXT_EXP(1)) {
+ fe->fe_cx |= FSR_UF;
+ res[1] = res[2] = res[3] = 0;
+ return (sign | EXT_EXP(1) | 0);
+ }
+ if ((fe->fe_cx & FSR_NX) ||
+ (fe->fe_fsr & (FSR_UF << FSR_TEM_SHIFT)))
+ fe->fe_cx |= FSR_UF;
+ exp = 0;
+ goto done;
+ }
+ /* Since internal == extended, no need to shift here. */
+ if (fpround(fe, fp) && fp->fp_mant[0] == EXT_EXP(2))
+ exp++;
+ if (exp >= EXT_EXP_INFNAN) {
+ fe->fe_cx |= FSR_OF | FSR_NX;
+ if (toinf(fe, sign)) {
+ res[1] = res[2] = res[3] = 0;
+ return (sign | EXT_EXP(EXT_EXP_INFNAN) | 0);
+ }
+ res[1] = res[2] = res[3] = ~0;
+ return (sign | EXT_EXP(EXT_EXP_INFNAN - 1) | EXT_MASK);
+ }
+done:
+ res[1] = fp->fp_mant[1];
+ res[2] = fp->fp_mant[2];
+ res[3] = fp->fp_mant[3];
+ return (sign | EXT_EXP(exp) | (fp->fp_mant[0] & EXT_MASK));
+}
+
+/*
+ * Implode an fpn, writing the result into the given space.
+ */
+void
+__fpu_implode(fe, fp, type, space)
+ struct fpemu *fe;
+ struct fpn *fp;
+ int type;
+ u_int *space;
+{
+
+ switch (type) {
+ case FTYPE_LNG:
+ space[0] = __fpu_ftox(fe, fp, space);
+ break;
+
+ case FTYPE_INT:
+ space[0] = __fpu_ftoi(fe, fp);
+ break;
+
+ case FTYPE_SNG:
+ space[0] = __fpu_ftos(fe, fp);
+ break;
+
+ case FTYPE_DBL:
+ space[0] = __fpu_ftod(fe, fp, space);
+ break;
+
+ case FTYPE_EXT:
+ /* funky rounding precision options ?? */
+ space[0] = __fpu_ftoq(fe, fp, space);
+ break;
+
+ default:
+ __utrap_panic("fpu_implode");
+ }
+ DPRINTF(FPE_REG, ("fpu_implode: %x %x %x %x\n",
+ space[0], space[1], space[2], space[3]));
+}
diff --git a/lib/libc/sparc64/fpu/fpu_mul.c b/lib/libc/sparc64/fpu/fpu_mul.c
new file mode 100644
index 0000000..3fe27c4
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu_mul.c
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fpu_mul.c 8.1 (Berkeley) 6/11/93
+ * $NetBSD: fpu_mul.c,v 1.2 1994/11/20 20:52:44 deraadt Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Perform an FPU multiply (return x * y).
+ */
+
+#include <sys/types.h>
+
+#include <machine/frame.h>
+#include <machine/fp.h>
+
+#include "fpu_arith.h"
+#include "fpu_emu.h"
+#include "fpu_extern.h"
+
+/*
+ * The multiplication algorithm for normal numbers is as follows:
+ *
+ * The fraction of the product is built in the usual stepwise fashion.
+ * Each step consists of shifting the accumulator right one bit
+ * (maintaining any guard bits) and, if the next bit in y is set,
+ * adding the multiplicand (x) to the accumulator. Then, in any case,
+ * we advance one bit leftward in y. Algorithmically:
+ *
+ * A = 0;
+ * for (bit = 0; bit < FP_NMANT; bit++) {
+ * sticky |= A & 1, A >>= 1;
+ * if (Y & (1 << bit))
+ * A += X;
+ * }
+ *
+ * (X and Y here represent the mantissas of x and y respectively.)
+ * The resultant accumulator (A) is the product's mantissa. It may
+ * be as large as 11.11111... in binary and hence may need to be
+ * shifted right, but at most one bit.
+ *
+ * Since we do not have efficient multiword arithmetic, we code the
+ * accumulator as four separate words, just like any other mantissa.
+ * We use local `register' variables in the hope that this is faster
+ * than memory. We keep x->fp_mant in locals for the same reason.
+ *
+ * In the algorithm above, the bits in y are inspected one at a time.
+ * We will pick them up 32 at a time and then deal with those 32, one
+ * at a time. Note, however, that we know several things about y:
+ *
+ * - the guard and round bits at the bottom are sure to be zero;
+ *
+ * - often many low bits are zero (y is often from a single or double
+ * precision source);
+ *
+ * - bit FP_NMANT-1 is set, and FP_1*2 fits in a word.
+ *
+ * We can also test for 32-zero-bits swiftly. In this case, the center
+ * part of the loop---setting sticky, shifting A, and not adding---will
+ * run 32 times without adding X to A. We can do a 32-bit shift faster
+ * by simply moving words. Since zeros are common, we optimize this case.
+ * Furthermore, since A is initially zero, we can omit the shift as well
+ * until we reach a nonzero word.
+ */
+struct fpn *
+__fpu_mul(fe)
+ struct fpemu *fe;
+{
+ struct fpn *x = &fe->fe_f1, *y = &fe->fe_f2;
+ u_int a3, a2, a1, a0, x3, x2, x1, x0, bit, m;
+ int sticky;
+ FPU_DECL_CARRY
+
+ /*
+ * Put the `heavier' operand on the right (see fpu_emu.h).
+ * Then we will have one of the following cases, taken in the
+ * following order:
+ *
+ * - y = NaN. Implied: if only one is a signalling NaN, y is.
+ * The result is y.
+ * - y = Inf. Implied: x != NaN (is 0, number, or Inf: the NaN
+ * case was taken care of earlier).
+ * If x = 0, the result is NaN. Otherwise the result
+ * is y, with its sign reversed if x is negative.
+ * - x = 0. Implied: y is 0 or number.
+ * The result is 0 (with XORed sign as usual).
+ * - other. Implied: both x and y are numbers.
+ * The result is x * y (XOR sign, multiply bits, add exponents).
+ */
+ ORDER(x, y);
+ if (ISNAN(y))
+ return (y);
+ if (ISINF(y)) {
+ if (ISZERO(x))
+ return (__fpu_newnan(fe));
+ y->fp_sign ^= x->fp_sign;
+ return (y);
+ }
+ if (ISZERO(x)) {
+ x->fp_sign ^= y->fp_sign;
+ return (x);
+ }
+
+ /*
+ * Setup. In the code below, the mask `m' will hold the current
+ * mantissa byte from y. The variable `bit' denotes the bit
+ * within m. We also define some macros to deal with everything.
+ */
+ x3 = x->fp_mant[3];
+ x2 = x->fp_mant[2];
+ x1 = x->fp_mant[1];
+ x0 = x->fp_mant[0];
+ sticky = a3 = a2 = a1 = a0 = 0;
+
+#define ADD /* A += X */ \
+ FPU_ADDS(a3, a3, x3); \
+ FPU_ADDCS(a2, a2, x2); \
+ FPU_ADDCS(a1, a1, x1); \
+ FPU_ADDC(a0, a0, x0)
+
+#define SHR1 /* A >>= 1, with sticky */ \
+ sticky |= a3 & 1, a3 = (a3 >> 1) | (a2 << 31), \
+ a2 = (a2 >> 1) | (a1 << 31), a1 = (a1 >> 1) | (a0 << 31), a0 >>= 1
+
+#define SHR32 /* A >>= 32, with sticky */ \
+ sticky |= a3, a3 = a2, a2 = a1, a1 = a0, a0 = 0
+
+#define STEP /* each 1-bit step of the multiplication */ \
+ SHR1; if (bit & m) { ADD; }; bit <<= 1
+
+ /*
+ * We are ready to begin. The multiply loop runs once for each
+ * of the four 32-bit words. Some words, however, are special.
+ * As noted above, the low order bits of Y are often zero. Even
+ * if not, the first loop can certainly skip the guard bits.
+ * The last word of y has its highest 1-bit in position FP_NMANT-1,
+ * so we stop the loop when we move past that bit.
+ */
+ if ((m = y->fp_mant[3]) == 0) {
+ /* SHR32; */ /* unneeded since A==0 */
+ } else {
+ bit = 1 << FP_NG;
+ do {
+ STEP;
+ } while (bit != 0);
+ }
+ if ((m = y->fp_mant[2]) == 0) {
+ SHR32;
+ } else {
+ bit = 1;
+ do {
+ STEP;
+ } while (bit != 0);
+ }
+ if ((m = y->fp_mant[1]) == 0) {
+ SHR32;
+ } else {
+ bit = 1;
+ do {
+ STEP;
+ } while (bit != 0);
+ }
+ m = y->fp_mant[0]; /* definitely != 0 */
+ bit = 1;
+ do {
+ STEP;
+ } while (bit <= m);
+
+ /*
+ * Done with mantissa calculation. Get exponent and handle
+ * 11.111...1 case, then put result in place. We reuse x since
+ * it already has the right class (FP_NUM).
+ */
+ m = x->fp_exp + y->fp_exp;
+ if (a0 >= FP_2) {
+ SHR1;
+ m++;
+ }
+ x->fp_sign ^= y->fp_sign;
+ x->fp_exp = m;
+ x->fp_sticky = sticky;
+ x->fp_mant[3] = a3;
+ x->fp_mant[2] = a2;
+ x->fp_mant[1] = a1;
+ x->fp_mant[0] = a0;
+ return (x);
+}
diff --git a/lib/libc/sparc64/fpu/fpu_qp.c b/lib/libc/sparc64/fpu/fpu_qp.c
new file mode 100644
index 0000000..8578e01
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu_qp.c
@@ -0,0 +1,163 @@
+/*-
+ * Copyright (c) 2002 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <machine/fsr.h>
+
+#include "fpu_emu.h"
+#include "fpu_extern.h"
+
+#define _QP_OP(op) \
+void _Qp_ ## op(u_int *c, u_int *a, u_int *b); \
+void \
+_Qp_ ## op(u_int *c, u_int *a, u_int *b) \
+{ \
+ struct fpemu fe; \
+ struct fpn *r; \
+ __asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \
+ fe.fe_cx = 0; \
+ fe.fe_f1.fp_sign = a[0] >> 31; \
+ fe.fe_f1.fp_sticky = 0; \
+ fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, a[0], a[1], a[2], a[3]); \
+ fe.fe_f2.fp_sign = b[0] >> 31; \
+ fe.fe_f2.fp_sticky = 0; \
+ fe.fe_f2.fp_class = __fpu_qtof(&fe.fe_f2, b[0], b[1], b[2], b[3]); \
+ r = __fpu_ ## op(&fe); \
+ c[0] = __fpu_ftoq(&fe, r, c); \
+ fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT; \
+ __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); \
+}
+
+#define _QP_TTOQ(qname, fname, ntype, signpos, atype, ...) \
+void _Qp_ ## qname ## toq(u_int *c, ntype n); \
+void \
+_Qp_ ## qname ## toq(u_int *c, ntype n) \
+{ \
+ struct fpemu fe; \
+ union { atype a[2]; ntype n; } u = { .n = n }; \
+ __asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \
+ fe.fe_cx = 0; \
+ fe.fe_f1.fp_sign = (signpos >= 0) ? u.a[0] >> signpos : 0; \
+ fe.fe_f1.fp_sticky = 0; \
+ fe.fe_f1.fp_class = __fpu_ ## fname ## tof(&fe.fe_f1, __VA_ARGS__); \
+ c[0] = __fpu_ftoq(&fe, &fe.fe_f1, c); \
+ fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT; \
+ __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); \
+}
+
+#define _QP_QTOT(qname, fname, type, ...) \
+type _Qp_qto ## qname(u_int *c); \
+type \
+_Qp_qto ## qname(u_int *c) \
+{ \
+ struct fpemu fe; \
+ union { u_int a; type n; } u; \
+ __asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \
+ fe.fe_cx = 0; \
+ fe.fe_f1.fp_sign = c[0] >> 31; \
+ fe.fe_f1.fp_sticky = 0; \
+ fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, c[0], c[1], c[2], c[3]); \
+ u.a = __fpu_fto ## fname(&fe, &fe.fe_f1, ## __VA_ARGS__); \
+ fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT; \
+ __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); \
+ return (u.n); \
+}
+
+#define FCC_EQ(fcc) ((fcc) == FSR_CC_EQ)
+#define FCC_GE(fcc) ((fcc) == FSR_CC_EQ || (fcc) == FSR_CC_GT)
+#define FCC_GT(fcc) ((fcc) == FSR_CC_GT)
+#define FCC_LE(fcc) ((fcc) == FSR_CC_EQ || (fcc) == FSR_CC_LT)
+#define FCC_LT(fcc) ((fcc) == FSR_CC_LT)
+#define FCC_NE(fcc) ((fcc) != FSR_CC_EQ)
+#define FCC_ID(fcc) (fcc)
+
+#define _QP_CMP(name, cmpe, test) \
+int _Qp_ ## name(u_int *a, u_int *b) ; \
+int \
+_Qp_ ## name(u_int *a, u_int *b) \
+{ \
+ struct fpemu fe; \
+ __asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :); \
+ fe.fe_cx = 0; \
+ fe.fe_f1.fp_sign = a[0] >> 31; \
+ fe.fe_f1.fp_sticky = 0; \
+ fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, a[0], a[1], a[2], a[3]); \
+ fe.fe_f2.fp_sign = b[0] >> 31; \
+ fe.fe_f2.fp_sticky = 0; \
+ fe.fe_f2.fp_class = __fpu_qtof(&fe.fe_f2, b[0], b[1], b[2], b[3]); \
+ __fpu_compare(&fe, cmpe, 0); \
+ fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT; \
+ __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr)); \
+ return (test(FSR_GET_FCC0(fe.fe_fsr))); \
+}
+
+void _Qp_sqrt(u_int *c, u_int *a);
+void
+_Qp_sqrt(u_int *c, u_int *a)
+{
+ struct fpemu fe;
+ struct fpn *r;
+ __asm __volatile("stx %%fsr, %0" : "=m" (fe.fe_fsr) :);
+ fe.fe_cx = 0;
+ fe.fe_f1.fp_sign = a[0] >> 31;
+ fe.fe_f1.fp_sticky = 0;
+ fe.fe_f1.fp_class = __fpu_qtof(&fe.fe_f1, a[0], a[1], a[2], a[3]);
+ r = __fpu_sqrt(&fe);
+ c[0] = __fpu_ftoq(&fe, r, c);
+ fe.fe_fsr |= fe.fe_cx << FSR_AEXC_SHIFT;
+ __asm __volatile("ldx %0, %%fsr" : : "m" (fe.fe_fsr));
+}
+
+_QP_OP(add)
+_QP_OP(div)
+_QP_OP(mul)
+_QP_OP(sub)
+
+_QP_TTOQ(d, d, double, 31, u_int, u.a[0], u.a[1])
+_QP_TTOQ(i, i, int, 31, u_int, u.a[0])
+_QP_TTOQ(s, s, float, 31, u_int, u.a[0])
+_QP_TTOQ(x, x, long, 63, u_long, u.a[0])
+_QP_TTOQ(ui, i, u_int, -1, u_int, u.a[0])
+_QP_TTOQ(ux, x, u_long, -1, u_long, u.a[0])
+
+_QP_QTOT(d, d, double, &u.a)
+_QP_QTOT(i, i, int)
+_QP_QTOT(s, s, float)
+_QP_QTOT(x, x, long, &u.a)
+_QP_QTOT(ui, i, u_int)
+_QP_QTOT(ux, x, u_long, &u.a)
+
+_QP_CMP(feq, 0, FCC_EQ)
+_QP_CMP(fge, 1, FCC_GE)
+_QP_CMP(fgt, 1, FCC_GT)
+_QP_CMP(fle, 1, FCC_LE)
+_QP_CMP(flt, 1, FCC_LT)
+_QP_CMP(fne, 0, FCC_NE)
+_QP_CMP(cmp, 0, FCC_ID)
+_QP_CMP(cmpe, 1, FCC_ID)
diff --git a/lib/libc/sparc64/fpu/fpu_reg.S b/lib/libc/sparc64/fpu/fpu_reg.S
new file mode 100644
index 0000000..781b4fe
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu_reg.S
@@ -0,0 +1,194 @@
+/*-
+ * Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Define arrays of leaf functions to load/store fp registers to memory. See
+ * fpu_reg.h for the definitions to use this from C code. The function sizes
+ * defines there must be kept in sync with this file!
+ */
+
+.macro ld32 reg
+ retl
+ ld [%o0], %f\reg
+.endm
+
+.macro st32 reg
+ retl
+ st %f\reg, [%o0]
+.endm
+
+.macro ld64 reg
+ retl
+ ldd [%o0], %f\reg
+.endm
+
+.macro st64 reg
+ retl
+ std %f\reg, [%o0]
+.endm
+
+/* The actual function arrays. */
+ .globl __fpu_ld32
+__fpu_ld32:
+ ld32 0
+ ld32 1
+ ld32 2
+ ld32 3
+ ld32 4
+ ld32 5
+ ld32 6
+ ld32 7
+ ld32 8
+ ld32 9
+ ld32 10
+ ld32 11
+ ld32 12
+ ld32 13
+ ld32 14
+ ld32 15
+ ld32 16
+ ld32 17
+ ld32 18
+ ld32 19
+ ld32 20
+ ld32 21
+ ld32 22
+ ld32 23
+ ld32 24
+ ld32 25
+ ld32 26
+ ld32 27
+ ld32 28
+ ld32 29
+ ld32 30
+ ld32 31
+
+ .globl __fpu_st32
+__fpu_st32:
+ st32 0
+ st32 1
+ st32 2
+ st32 3
+ st32 4
+ st32 5
+ st32 6
+ st32 7
+ st32 8
+ st32 9
+ st32 10
+ st32 11
+ st32 12
+ st32 13
+ st32 14
+ st32 15
+ st32 16
+ st32 17
+ st32 18
+ st32 19
+ st32 20
+ st32 21
+ st32 22
+ st32 23
+ st32 24
+ st32 25
+ st32 26
+ st32 27
+ st32 28
+ st32 29
+ st32 30
+ st32 31
+
+ .globl __fpu_ld64
+__fpu_ld64:
+ ld64 0
+ ld64 2
+ ld64 4
+ ld64 6
+ ld64 8
+ ld64 10
+ ld64 12
+ ld64 14
+ ld64 16
+ ld64 18
+ ld64 20
+ ld64 22
+ ld64 24
+ ld64 26
+ ld64 28
+ ld64 30
+ ld64 32
+ ld64 34
+ ld64 36
+ ld64 38
+ ld64 40
+ ld64 42
+ ld64 44
+ ld64 46
+ ld64 48
+ ld64 50
+ ld64 52
+ ld64 54
+ ld64 56
+ ld64 58
+ ld64 60
+ ld64 62
+
+ .globl __fpu_st64
+__fpu_st64:
+ st64 0
+ st64 2
+ st64 4
+ st64 6
+ st64 8
+ st64 10
+ st64 12
+ st64 14
+ st64 16
+ st64 18
+ st64 20
+ st64 22
+ st64 24
+ st64 26
+ st64 28
+ st64 30
+ st64 32
+ st64 34
+ st64 36
+ st64 38
+ st64 40
+ st64 42
+ st64 44
+ st64 46
+ st64 48
+ st64 50
+ st64 52
+ st64 54
+ st64 56
+ st64 58
+ st64 60
+ st64 62
diff --git a/lib/libc/sparc64/fpu/fpu_reg.h b/lib/libc/sparc64/fpu/fpu_reg.h
new file mode 100644
index 0000000..b8b7229
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu_reg.h
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _LIBC_SPARC64_FPU_FPU_REG_H_
+#define _LIBC_SPARC64_FPU_FPU_REG_H_
+
+/*
+ * These are not really of type char[]. They are are arrays of functions defined
+ * in fpu_reg.S; each array member loads/stores a certain fpu register of the
+ * given size.
+ */
+extern char __fpu_ld32[];
+extern char __fpu_st32[];
+extern char __fpu_ld64[];
+extern char __fpu_st64[];
+
+/* Size of the functions in the arrays. */
+#define FPU_LD32_SZ 8
+#define FPU_ST32_SZ 8
+#define FPU_LD64_SZ 8
+#define FPU_ST64_SZ 8
+
+/* Typedefs for convenient casts in the functions below. */
+typedef void (fp_ldst32_fn)(u_int32_t *);
+typedef void (fp_ldst64_fn)(u_int64_t *);
+
+/*
+ * These are the functions that are actually used in the fpu emulation code to
+ * access the fp registers. They are usually not used more than once, so
+ * cacheing needs not be done here.
+ */
+static __inline u_int32_t
+__fpu_getreg(int r)
+{
+ u_int32_t rv;
+
+ ((fp_ldst32_fn *)&__fpu_st32[r * FPU_ST32_SZ])(&rv);
+ return (rv);
+}
+
+static __inline u_int64_t
+__fpu_getreg64(int r)
+{
+ u_int64_t rv;
+
+ ((fp_ldst64_fn *)&__fpu_st64[(r >> 1) * FPU_ST64_SZ])(&rv);
+ return (rv);
+}
+
+static __inline void
+__fpu_setreg(int r, u_int32_t v)
+{
+
+ ((fp_ldst32_fn *)&__fpu_ld32[r * FPU_LD32_SZ])(&v);
+}
+
+static __inline void
+__fpu_setreg64(int r, u_int64_t v)
+{
+
+ ((fp_ldst64_fn *)&__fpu_ld64[(r >> 1) * FPU_LD64_SZ])(&v);
+}
+
+#endif /* _LIBC_SPARC64_FPU_FPU_REG_H_ */
diff --git a/lib/libc/sparc64/fpu/fpu_sqrt.c b/lib/libc/sparc64/fpu/fpu_sqrt.c
new file mode 100644
index 0000000..364384b
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu_sqrt.c
@@ -0,0 +1,397 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fpu_sqrt.c 8.1 (Berkeley) 6/11/93
+ * $NetBSD: fpu_sqrt.c,v 1.2 1994/11/20 20:52:46 deraadt Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Perform an FPU square root (return sqrt(x)).
+ */
+
+#include <sys/types.h>
+
+#include <machine/frame.h>
+#include <machine/fp.h>
+
+#include "fpu_arith.h"
+#include "fpu_emu.h"
+#include "fpu_extern.h"
+
+/*
+ * Our task is to calculate the square root of a floating point number x0.
+ * This number x normally has the form:
+ *
+ * exp
+ * x = mant * 2 (where 1 <= mant < 2 and exp is an integer)
+ *
+ * This can be left as it stands, or the mantissa can be doubled and the
+ * exponent decremented:
+ *
+ * exp-1
+ * x = (2 * mant) * 2 (where 2 <= 2 * mant < 4)
+ *
+ * If the exponent `exp' is even, the square root of the number is best
+ * handled using the first form, and is by definition equal to:
+ *
+ * exp/2
+ * sqrt(x) = sqrt(mant) * 2
+ *
+ * If exp is odd, on the other hand, it is convenient to use the second
+ * form, giving:
+ *
+ * (exp-1)/2
+ * sqrt(x) = sqrt(2 * mant) * 2
+ *
+ * In the first case, we have
+ *
+ * 1 <= mant < 2
+ *
+ * and therefore
+ *
+ * sqrt(1) <= sqrt(mant) < sqrt(2)
+ *
+ * while in the second case we have
+ *
+ * 2 <= 2*mant < 4
+ *
+ * and therefore
+ *
+ * sqrt(2) <= sqrt(2*mant) < sqrt(4)
+ *
+ * so that in any case, we are sure that
+ *
+ * sqrt(1) <= sqrt(n * mant) < sqrt(4), n = 1 or 2
+ *
+ * or
+ *
+ * 1 <= sqrt(n * mant) < 2, n = 1 or 2.
+ *
+ * This root is therefore a properly formed mantissa for a floating
+ * point number. The exponent of sqrt(x) is either exp/2 or (exp-1)/2
+ * as above. This leaves us with the problem of finding the square root
+ * of a fixed-point number in the range [1..4).
+ *
+ * Though it may not be instantly obvious, the following square root
+ * algorithm works for any integer x of an even number of bits, provided
+ * that no overflows occur:
+ *
+ * let q = 0
+ * for k = NBITS-1 to 0 step -1 do -- for each digit in the answer...
+ * x *= 2 -- multiply by radix, for next digit
+ * if x >= 2q + 2^k then -- if adding 2^k does not
+ * x -= 2q + 2^k -- exceed the correct root,
+ * q += 2^k -- add 2^k and adjust x
+ * fi
+ * done
+ * sqrt = q / 2^(NBITS/2) -- (and any remainder is in x)
+ *
+ * If NBITS is odd (so that k is initially even), we can just add another
+ * zero bit at the top of x. Doing so means that q is not going to acquire
+ * a 1 bit in the first trip around the loop (since x0 < 2^NBITS). If the
+ * final value in x is not needed, or can be off by a factor of 2, this is
+ * equivalant to moving the `x *= 2' step to the bottom of the loop:
+ *
+ * for k = NBITS-1 to 0 step -1 do if ... fi; x *= 2; done
+ *
+ * and the result q will then be sqrt(x0) * 2^floor(NBITS / 2).
+ * (Since the algorithm is destructive on x, we will call x's initial
+ * value, for which q is some power of two times its square root, x0.)
+ *
+ * If we insert a loop invariant y = 2q, we can then rewrite this using
+ * C notation as:
+ *
+ * q = y = 0; x = x0;
+ * for (k = NBITS; --k >= 0;) {
+ * #if (NBITS is even)
+ * x *= 2;
+ * #endif
+ * t = y + (1 << k);
+ * if (x >= t) {
+ * x -= t;
+ * q += 1 << k;
+ * y += 1 << (k + 1);
+ * }
+ * #if (NBITS is odd)
+ * x *= 2;
+ * #endif
+ * }
+ *
+ * If x0 is fixed point, rather than an integer, we can simply alter the
+ * scale factor between q and sqrt(x0). As it happens, we can easily arrange
+ * for the scale factor to be 2**0 or 1, so that sqrt(x0) == q.
+ *
+ * In our case, however, x0 (and therefore x, y, q, and t) are multiword
+ * integers, which adds some complication. But note that q is built one
+ * bit at a time, from the top down, and is not used itself in the loop
+ * (we use 2q as held in y instead). This means we can build our answer
+ * in an integer, one word at a time, which saves a bit of work. Also,
+ * since 1 << k is always a `new' bit in q, 1 << k and 1 << (k+1) are
+ * `new' bits in y and we can set them with an `or' operation rather than
+ * a full-blown multiword add.
+ *
+ * We are almost done, except for one snag. We must prove that none of our
+ * intermediate calculations can overflow. We know that x0 is in [1..4)
+ * and therefore the square root in q will be in [1..2), but what about x,
+ * y, and t?
+ *
+ * We know that y = 2q at the beginning of each loop. (The relation only
+ * fails temporarily while y and q are being updated.) Since q < 2, y < 4.
+ * The sum in t can, in our case, be as much as y+(1<<1) = y+2 < 6, and.
+ * Furthermore, we can prove with a bit of work that x never exceeds y by
+ * more than 2, so that even after doubling, 0 <= x < 8. (This is left as
+ * an exercise to the reader, mostly because I have become tired of working
+ * on this comment.)
+ *
+ * If our floating point mantissas (which are of the form 1.frac) occupy
+ * B+1 bits, our largest intermediary needs at most B+3 bits, or two extra.
+ * In fact, we want even one more bit (for a carry, to avoid compares), or
+ * three extra. There is a comment in fpu_emu.h reminding maintainers of
+ * this, so we have some justification in assuming it.
+ */
+struct fpn *
+__fpu_sqrt(fe)
+ struct fpemu *fe;
+{
+ struct fpn *x = &fe->fe_f1;
+ u_int bit, q, tt;
+ u_int x0, x1, x2, x3;
+ u_int y0, y1, y2, y3;
+ u_int d0, d1, d2, d3;
+ int e;
+
+ /*
+ * Take care of special cases first. In order:
+ *
+ * sqrt(NaN) = NaN
+ * sqrt(+0) = +0
+ * sqrt(-0) = -0
+ * sqrt(x < 0) = NaN (including sqrt(-Inf))
+ * sqrt(+Inf) = +Inf
+ *
+ * Then all that remains are numbers with mantissas in [1..2).
+ */
+ if (ISNAN(x) || ISZERO(x))
+ return (x);
+ if (x->fp_sign)
+ return (__fpu_newnan(fe));
+ if (ISINF(x))
+ return (x);
+
+ /*
+ * Calculate result exponent. As noted above, this may involve
+ * doubling the mantissa. We will also need to double x each
+ * time around the loop, so we define a macro for this here, and
+ * we break out the multiword mantissa.
+ */
+#ifdef FPU_SHL1_BY_ADD
+#define DOUBLE_X { \
+ FPU_ADDS(x3, x3, x3); FPU_ADDCS(x2, x2, x2); \
+ FPU_ADDCS(x1, x1, x1); FPU_ADDC(x0, x0, x0); \
+}
+#else
+#define DOUBLE_X { \
+ x0 = (x0 << 1) | (x1 >> 31); x1 = (x1 << 1) | (x2 >> 31); \
+ x2 = (x2 << 1) | (x3 >> 31); x3 <<= 1; \
+}
+#endif
+#if (FP_NMANT & 1) != 0
+# define ODD_DOUBLE DOUBLE_X
+# define EVEN_DOUBLE /* nothing */
+#else
+# define ODD_DOUBLE /* nothing */
+# define EVEN_DOUBLE DOUBLE_X
+#endif
+ x0 = x->fp_mant[0];
+ x1 = x->fp_mant[1];
+ x2 = x->fp_mant[2];
+ x3 = x->fp_mant[3];
+ e = x->fp_exp;
+ if (e & 1) /* exponent is odd; use sqrt(2mant) */
+ DOUBLE_X;
+ /* THE FOLLOWING ASSUMES THAT RIGHT SHIFT DOES SIGN EXTENSION */
+ x->fp_exp = e >> 1; /* calculates (e&1 ? (e-1)/2 : e/2 */
+
+ /*
+ * Now calculate the mantissa root. Since x is now in [1..4),
+ * we know that the first trip around the loop will definitely
+ * set the top bit in q, so we can do that manually and start
+ * the loop at the next bit down instead. We must be sure to
+ * double x correctly while doing the `known q=1.0'.
+ *
+ * We do this one mantissa-word at a time, as noted above, to
+ * save work. To avoid `(1 << 31) << 1', we also do the top bit
+ * outside of each per-word loop.
+ *
+ * The calculation `t = y + bit' breaks down into `t0 = y0, ...,
+ * t3 = y3, t? |= bit' for the appropriate word. Since the bit
+ * is always a `new' one, this means that three of the `t?'s are
+ * just the corresponding `y?'; we use `#define's here for this.
+ * The variable `tt' holds the actual `t?' variable.
+ */
+
+ /* calculate q0 */
+#define t0 tt
+ bit = FP_1;
+ EVEN_DOUBLE;
+ /* if (x >= (t0 = y0 | bit)) { */ /* always true */
+ q = bit;
+ x0 -= bit;
+ y0 = bit << 1;
+ /* } */
+ ODD_DOUBLE;
+ while ((bit >>= 1) != 0) { /* for remaining bits in q0 */
+ EVEN_DOUBLE;
+ t0 = y0 | bit; /* t = y + bit */
+ if (x0 >= t0) { /* if x >= t then */
+ x0 -= t0; /* x -= t */
+ q |= bit; /* q += bit */
+ y0 |= bit << 1; /* y += bit << 1 */
+ }
+ ODD_DOUBLE;
+ }
+ x->fp_mant[0] = q;
+#undef t0
+
+ /* calculate q1. note (y0&1)==0. */
+#define t0 y0
+#define t1 tt
+ q = 0;
+ y1 = 0;
+ bit = 1 << 31;
+ EVEN_DOUBLE;
+ t1 = bit;
+ FPU_SUBS(d1, x1, t1);
+ FPU_SUBC(d0, x0, t0); /* d = x - t */
+ if ((int)d0 >= 0) { /* if d >= 0 (i.e., x >= t) then */
+ x0 = d0, x1 = d1; /* x -= t */
+ q = bit; /* q += bit */
+ y0 |= 1; /* y += bit << 1 */
+ }
+ ODD_DOUBLE;
+ while ((bit >>= 1) != 0) { /* for remaining bits in q1 */
+ EVEN_DOUBLE; /* as before */
+ t1 = y1 | bit;
+ FPU_SUBS(d1, x1, t1);
+ FPU_SUBC(d0, x0, t0);
+ if ((int)d0 >= 0) {
+ x0 = d0, x1 = d1;
+ q |= bit;
+ y1 |= bit << 1;
+ }
+ ODD_DOUBLE;
+ }
+ x->fp_mant[1] = q;
+#undef t1
+
+ /* calculate q2. note (y1&1)==0; y0 (aka t0) is fixed. */
+#define t1 y1
+#define t2 tt
+ q = 0;
+ y2 = 0;
+ bit = 1 << 31;
+ EVEN_DOUBLE;
+ t2 = bit;
+ FPU_SUBS(d2, x2, t2);
+ FPU_SUBCS(d1, x1, t1);
+ FPU_SUBC(d0, x0, t0);
+ if ((int)d0 >= 0) {
+ x0 = d0, x1 = d1, x2 = d2;
+ q = bit;
+ y1 |= 1; /* now t1, y1 are set in concrete */
+ }
+ ODD_DOUBLE;
+ while ((bit >>= 1) != 0) {
+ EVEN_DOUBLE;
+ t2 = y2 | bit;
+ FPU_SUBS(d2, x2, t2);
+ FPU_SUBCS(d1, x1, t1);
+ FPU_SUBC(d0, x0, t0);
+ if ((int)d0 >= 0) {
+ x0 = d0, x1 = d1, x2 = d2;
+ q |= bit;
+ y2 |= bit << 1;
+ }
+ ODD_DOUBLE;
+ }
+ x->fp_mant[2] = q;
+#undef t2
+
+ /* calculate q3. y0, t0, y1, t1 all fixed; y2, t2, almost done. */
+#define t2 y2
+#define t3 tt
+ q = 0;
+ y3 = 0;
+ bit = 1 << 31;
+ EVEN_DOUBLE;
+ t3 = bit;
+ FPU_SUBS(d3, x3, t3);
+ FPU_SUBCS(d2, x2, t2);
+ FPU_SUBCS(d1, x1, t1);
+ FPU_SUBC(d0, x0, t0);
+ if ((int)d0 >= 0) {
+ x0 = d0, x1 = d1, x2 = d2; x3 = d3;
+ q = bit;
+ y2 |= 1;
+ }
+ ODD_DOUBLE;
+ while ((bit >>= 1) != 0) {
+ EVEN_DOUBLE;
+ t3 = y3 | bit;
+ FPU_SUBS(d3, x3, t3);
+ FPU_SUBCS(d2, x2, t2);
+ FPU_SUBCS(d1, x1, t1);
+ FPU_SUBC(d0, x0, t0);
+ if ((int)d0 >= 0) {
+ x0 = d0, x1 = d1, x2 = d2; x3 = d3;
+ q |= bit;
+ y3 |= bit << 1;
+ }
+ ODD_DOUBLE;
+ }
+ x->fp_mant[3] = q;
+
+ /*
+ * The result, which includes guard and round bits, is exact iff
+ * x is now zero; any nonzero bits in x represent sticky bits.
+ */
+ x->fp_sticky = x0 | x1 | x2 | x3;
+ return (x);
+}
diff --git a/lib/libc/sparc64/fpu/fpu_subr.c b/lib/libc/sparc64/fpu/fpu_subr.c
new file mode 100644
index 0000000..074e959
--- /dev/null
+++ b/lib/libc/sparc64/fpu/fpu_subr.c
@@ -0,0 +1,221 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Lawrence Berkeley Laboratory.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fpu_subr.c 8.1 (Berkeley) 6/11/93
+ * $NetBSD: fpu_subr.c,v 1.3 1996/03/14 19:42:01 christos Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * FPU subroutines.
+ */
+
+#include <sys/param.h>
+
+#include <machine/frame.h>
+#include <machine/fp.h>
+#include <machine/fsr.h>
+#include <machine/instr.h>
+
+#include "fpu_arith.h"
+#include "fpu_emu.h"
+#include "fpu_extern.h"
+#include "__sparc_utrap_private.h"
+
+/*
+ * Shift the given number right rsh bits. Any bits that `fall off' will get
+ * shoved into the sticky field; we return the resulting sticky. Note that
+ * shifting NaNs is legal (this will never shift all bits out); a NaN's
+ * sticky field is ignored anyway.
+ */
+int
+__fpu_shr(struct fpn *fp, int rsh)
+{
+ u_int m0, m1, m2, m3, s;
+ int lsh;
+
+#ifdef DIAGNOSTIC
+ if (rsh <= 0 || (fp->fp_class != FPC_NUM && !ISNAN(fp)))
+ __utrap_panic("fpu_rightshift 1");
+#endif
+
+ m0 = fp->fp_mant[0];
+ m1 = fp->fp_mant[1];
+ m2 = fp->fp_mant[2];
+ m3 = fp->fp_mant[3];
+
+ /* If shifting all the bits out, take a shortcut. */
+ if (rsh >= FP_NMANT) {
+#ifdef DIAGNOSTIC
+ if ((m0 | m1 | m2 | m3) == 0)
+ __utrap_panic("fpu_rightshift 2");
+#endif
+ fp->fp_mant[0] = 0;
+ fp->fp_mant[1] = 0;
+ fp->fp_mant[2] = 0;
+ fp->fp_mant[3] = 0;
+#ifdef notdef
+ if ((m0 | m1 | m2 | m3) == 0)
+ fp->fp_class = FPC_ZERO;
+ else
+#endif
+ fp->fp_sticky = 1;
+ return (1);
+ }
+
+ /* Squish out full words. */
+ s = fp->fp_sticky;
+ if (rsh >= 32 * 3) {
+ s |= m3 | m2 | m1;
+ m3 = m0, m2 = 0, m1 = 0, m0 = 0;
+ } else if (rsh >= 32 * 2) {
+ s |= m3 | m2;
+ m3 = m1, m2 = m0, m1 = 0, m0 = 0;
+ } else if (rsh >= 32) {
+ s |= m3;
+ m3 = m2, m2 = m1, m1 = m0, m0 = 0;
+ }
+
+ /* Handle any remaining partial word. */
+ if ((rsh &= 31) != 0) {
+ lsh = 32 - rsh;
+ s |= m3 << lsh;
+ m3 = (m3 >> rsh) | (m2 << lsh);
+ m2 = (m2 >> rsh) | (m1 << lsh);
+ m1 = (m1 >> rsh) | (m0 << lsh);
+ m0 >>= rsh;
+ }
+ fp->fp_mant[0] = m0;
+ fp->fp_mant[1] = m1;
+ fp->fp_mant[2] = m2;
+ fp->fp_mant[3] = m3;
+ fp->fp_sticky = s;
+ return (s);
+}
+
+/*
+ * Force a number to be normal, i.e., make its fraction have all zero
+ * bits before FP_1, then FP_1, then all 1 bits. This is used for denorms
+ * and (sometimes) for intermediate results.
+ *
+ * Internally, this may use a `supernormal' -- a number whose fp_mant
+ * is greater than or equal to 2.0 -- so as a side effect you can hand it
+ * a supernormal and it will fix it (provided fp->fp_mant[3] == 0).
+ */
+void
+__fpu_norm(struct fpn *fp)
+{
+ u_int m0, m1, m2, m3, top, sup, nrm;
+ int lsh, rsh, exp;
+
+ exp = fp->fp_exp;
+ m0 = fp->fp_mant[0];
+ m1 = fp->fp_mant[1];
+ m2 = fp->fp_mant[2];
+ m3 = fp->fp_mant[3];
+
+ /* Handle severe subnormals with 32-bit moves. */
+ if (m0 == 0) {
+ if (m1)
+ m0 = m1, m1 = m2, m2 = m3, m3 = 0, exp -= 32;
+ else if (m2)
+ m0 = m2, m1 = m3, m2 = 0, m3 = 0, exp -= 2 * 32;
+ else if (m3)
+ m0 = m3, m1 = 0, m2 = 0, m3 = 0, exp -= 3 * 32;
+ else {
+ fp->fp_class = FPC_ZERO;
+ return;
+ }
+ }
+
+ /* Now fix any supernormal or remaining subnormal. */
+ nrm = FP_1;
+ sup = nrm << 1;
+ if (m0 >= sup) {
+ /*
+ * We have a supernormal number. We need to shift it right.
+ * We may assume m3==0.
+ */
+ for (rsh = 1, top = m0 >> 1; top >= sup; rsh++) /* XXX slow */
+ top >>= 1;
+ exp += rsh;
+ lsh = 32 - rsh;
+ m3 = m2 << lsh;
+ m2 = (m2 >> rsh) | (m1 << lsh);
+ m1 = (m1 >> rsh) | (m0 << lsh);
+ m0 = top;
+ } else if (m0 < nrm) {
+ /*
+ * We have a regular denorm (a subnormal number), and need
+ * to shift it left.
+ */
+ for (lsh = 1, top = m0 << 1; top < nrm; lsh++) /* XXX slow */
+ top <<= 1;
+ exp -= lsh;
+ rsh = 32 - lsh;
+ m0 = top | (m1 >> rsh);
+ m1 = (m1 << lsh) | (m2 >> rsh);
+ m2 = (m2 << lsh) | (m3 >> rsh);
+ m3 <<= lsh;
+ }
+
+ fp->fp_exp = exp;
+ fp->fp_mant[0] = m0;
+ fp->fp_mant[1] = m1;
+ fp->fp_mant[2] = m2;
+ fp->fp_mant[3] = m3;
+}
+
+/*
+ * Concoct a `fresh' Quiet NaN per Appendix N.
+ * As a side effect, we set NV (invalid) for the current exceptions.
+ */
+struct fpn *
+__fpu_newnan(struct fpemu *fe)
+{
+ struct fpn *fp;
+
+ fe->fe_cx = FSR_NV;
+ fp = &fe->fe_f3;
+ fp->fp_class = FPC_QNAN;
+ fp->fp_sign = 0;
+ fp->fp_mant[0] = FP_1 - 1;
+ fp->fp_mant[1] = fp->fp_mant[2] = fp->fp_mant[3] = ~0;
+ return (fp);
+}
diff --git a/lib/libc/sparc64/gd_qnan.h b/lib/libc/sparc64/gd_qnan.h
new file mode 100644
index 0000000..7c9f929
--- /dev/null
+++ b/lib/libc/sparc64/gd_qnan.h
@@ -0,0 +1,21 @@
+/*
+ * MD header for contrib/gdtoa
+ *
+ * This file can be generated by compiling and running contrib/gdtoa/qnan.c
+ * on the target architecture after arith.h has been generated.
+ *
+ * $FreeBSD$
+ */
+
+#define f_QNAN 0x7fc00000
+#define d_QNAN0 0x7ff80000
+#define d_QNAN1 0x00000000
+#define ld_QNAN0 0x7fff8000
+#define ld_QNAN1 0x00000000
+#define ld_QNAN2 0x00000000
+#define ld_QNAN3 0x00000000
+#define ldus_QNAN0 0x7fff
+#define ldus_QNAN1 0x8000
+#define ldus_QNAN2 0x0000
+#define ldus_QNAN3 0x0000
+#define ldus_QNAN4 0x0000
diff --git a/lib/libc/sparc64/gen/Makefile.inc b/lib/libc/sparc64/gen/Makefile.inc
new file mode 100644
index 0000000..d3fbfe4
--- /dev/null
+++ b/lib/libc/sparc64/gen/Makefile.inc
@@ -0,0 +1,6 @@
+# $FreeBSD$
+
+SRCS+= _ctx_start.S _setjmp.S fabs.S fixunsdfsi.S flt_rounds.c fpgetmask.c \
+ fpgetround.c fpgetsticky.c fpsetmask.c fpsetround.c \
+ getcontextx.c infinity.c ldexp.c makecontext.c \
+ signalcontext.c setjmp.S sigsetjmp.S _set_tp.c
diff --git a/lib/libc/sparc64/gen/_ctx_start.S b/lib/libc/sparc64/gen/_ctx_start.S
new file mode 100644
index 0000000..4ba3fd8
--- /dev/null
+++ b/lib/libc/sparc64/gen/_ctx_start.S
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2003 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ENTRY(_ctx_start)
+ call %g1
+ mov %g2, %l0
+ call _ctx_done
+ mov %l0, %o0
+ illtrap
+END(_ctx_start)
diff --git a/lib/libc/sparc64/gen/_set_tp.c b/lib/libc/sparc64/gen/_set_tp.c
new file mode 100644
index 0000000..cf9db26
--- /dev/null
+++ b/lib/libc/sparc64/gen/_set_tp.c
@@ -0,0 +1,34 @@
+/*-
+ * Copyright (c) 2004 Doug Rabson
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+void
+_set_tp(void *tpval)
+{
+
+ __asm __volatile("mov %0, %%g7" : : "r" (tpval));
+}
diff --git a/lib/libc/sparc64/gen/_setjmp.S b/lib/libc/sparc64/gen/_setjmp.S
new file mode 100644
index 0000000..724c2c0
--- /dev/null
+++ b/lib/libc/sparc64/gen/_setjmp.S
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Header: _setjmp.s,v 1.1 91/07/06 16:45:53 torek Exp
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ .asciz "@(#)_setjmp.s 8.1 (Berkeley) 6/4/93"
+#if 0
+ RCSID("$NetBSD: _setjmp.S,v 1.4 1998/10/08 02:27:59 eeh Exp $")
+#endif
+#endif /* LIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "assym.s"
+
+ .register %g2,#ignore
+ .register %g3,#ignore
+
+/*
+ * C library -- _setjmp, _longjmp
+ *
+ * _longjmp(a,v)
+ * will generate a "return(v?v:1)" from
+ * the last call to
+ * _setjmp(a)
+ * by restoring the previous context.
+ * The previous signal state is NOT restored.
+ */
+
+ENTRY(_setjmp)
+ stx %sp, [%o0 + _JB_SP]
+ stx %o7, [%o0 + _JB_PC]
+ retl
+ clr %o0
+END(_setjmp)
+
+ .weak CNAME(_longjmp)
+ .set CNAME(_longjmp),CNAME(___longjmp)
+ENTRY(___longjmp)
+ save %sp, -CCFSZ, %sp
+ flushw
+ ldx [%i0 + _JB_SP], %fp
+ ldx [%i0 + _JB_PC], %i7
+ mov 1, %i0
+ movrnz %i1, %i1, %i0
+ ret
+ restore
+END(___longjmp)
diff --git a/lib/libc/sparc64/gen/assym.s b/lib/libc/sparc64/gen/assym.s
new file mode 100644
index 0000000..7b205db
--- /dev/null
+++ b/lib/libc/sparc64/gen/assym.s
@@ -0,0 +1,18 @@
+/*
+ * Offsets into into structures used from asm. Must be kept in sync with
+ * appropriate headers.
+ *
+ * $FreeBSD$
+ */
+
+#define _JB_FP 0x0
+#define _JB_PC 0x8
+#define _JB_SP 0x10
+#define _JB_SIGMASK 0x18
+#define _JB_SIGFLAG 0x28
+
+#define SIG_BLOCK 1
+#define SIG_SETMASK 3
+
+#define FSR_RD_MASK 0xc0000000
+#define FSR_RD_RD_Z 0x40000000
diff --git a/lib/libc/sparc64/gen/fabs.S b/lib/libc/sparc64/gen/fabs.S
new file mode 100644
index 0000000..bbc744a
--- /dev/null
+++ b/lib/libc/sparc64/gen/fabs.S
@@ -0,0 +1,35 @@
+/*-
+ * Copyright (c) 2002 by Thomas Moestl <tmm@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * double fabs(double);
+ */
+ENTRY(fabs)
+ retl
+ fabsd %f0, %f0
+END(fabs)
diff --git a/lib/libc/sparc64/gen/fixunsdfsi.S b/lib/libc/sparc64/gen/fixunsdfsi.S
new file mode 100644
index 0000000..77c3059
--- /dev/null
+++ b/lib/libc/sparc64/gen/fixunsdfsi.S
@@ -0,0 +1,93 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Header: fixunsdfsi.s,v 1.3 91/10/08 00:03:15 torek Exp
+ */
+
+#include <machine/asm.h>
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ .asciz "@(#)fixunsdfsi.s 8.1 (Berkeley) 6/4/93"
+#if 0
+ RCSID("$NetBSD: fixunsdfsi.S,v 1.3 2000/07/25 04:26:12 mycroft Exp $")
+#endif
+#endif /* LIBC_SCCS and not lint */
+__FBSDID("$FreeBSD$");
+
+/*
+ * Convert double to unsigned integer (for gcc).
+ *
+ * I have made the output for NaN agree with the Sun compiler, not
+ * that it really matters, by using `fbul,a'.
+ */
+
+
+ .align 8
+.Lbig:
+ .word 0x43e00000 ! .double 2^63
+ .word 0 ! (who me, not trust the assembler?)
+
+/*
+ * Same as above but to unsigned long
+ */
+ENTRY(__dtoul)
+ PIC_PROLOGUE(%o4, %o5)
+ sub %sp, 16, %sp
+ std %f2, [%sp + CCFSZ + SPOFF + 8]
+ SET(.Lbig, %o5, %o3)
+ ldd [%o3], %f2
+ fcmped %f0, %f2 ! d < 2^63, or NaN, or -Inf?
+ fbul,a 1f ! if so, use fdtox to convert to long
+ fdtox %f0, %f0 ! (this includes negatives!)
+
+ ! d does not fit in a long, so subtract 2^63, convert,
+ ! and add 2^63 again (sigh). Just hope the intermediate
+ ! fits (if not, the result is undefined anyway).
+
+ fsubd %f0, %f2, %f0 ! d -= 2^63
+ fdtox %f0, %f0 ! convert to long
+ std %f0, [%sp + CCFSZ + SPOFF] ! move into return reg
+ ldx [%sp + CCFSZ + SPOFF], %o0
+ sethi %hi(0x80000000), %o1
+ sllx %o1, 32, %o1
+ add %o0, %o1, %o0 ! add 2^63
+ ldd [%sp + CCFSZ + SPOFF + 8], %f2
+ retl
+ add %sp, 16, %sp
+
+1:
+ std %f0, [%sp + CCFSZ + SPOFF] ! return result
+ ldx [%sp + CCFSZ + SPOFF], %o0
+ ldd [%sp + CCFSZ + SPOFF + 8], %f2
+ retl
+ add %sp, 16, %sp
+END(__dtoul)
diff --git a/lib/libc/sparc64/gen/flt_rounds.c b/lib/libc/sparc64/gen/flt_rounds.c
new file mode 100644
index 0000000..706ef5a
--- /dev/null
+++ b/lib/libc/sparc64/gen/flt_rounds.c
@@ -0,0 +1,26 @@
+/*
+ * Written by J.T. Conklin, Apr 10, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <machine/float.h>
+
+static const int map[] = {
+ 1, /* round to nearest */
+ 0, /* round to zero */
+ 2, /* round to positive infinity */
+ 3 /* round to negative infinity */
+};
+
+int
+__flt_rounds()
+{
+ int x;
+
+ __asm("st %%fsr,%0" : "=m" (*&x));
+ return map[(x >> 30) & 0x03];
+}
diff --git a/lib/libc/sparc64/gen/fpgetmask.c b/lib/libc/sparc64/gen/fpgetmask.c
new file mode 100644
index 0000000..05b151a
--- /dev/null
+++ b/lib/libc/sparc64/gen/fpgetmask.c
@@ -0,0 +1,22 @@
+/* $NetBSD: fpgetmask.c,v 1.2 2002/01/13 21:45:50 thorpej Exp $ */
+
+/*
+ * Written by J.T. Conklin, Apr 10, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+
+#include <machine/fsr.h>
+#include <ieeefp.h>
+
+fp_except_t
+fpgetmask()
+{
+ unsigned int x;
+
+ __asm__("st %%fsr,%0" : "=m" (x));
+ return (FSR_GET_TEM(x));
+}
diff --git a/lib/libc/sparc64/gen/fpgetround.c b/lib/libc/sparc64/gen/fpgetround.c
new file mode 100644
index 0000000..dbc90d7
--- /dev/null
+++ b/lib/libc/sparc64/gen/fpgetround.c
@@ -0,0 +1,21 @@
+/* $NetBSD: fpgetround.c,v 1.2 2002/01/13 21:45:50 thorpej Exp $ */
+
+/*
+ * Written by J.T. Conklin, Apr 10, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/fsr.h>
+#include <ieeefp.h>
+
+fp_rnd_t
+fpgetround()
+{
+ unsigned int x;
+
+ __asm__("st %%fsr,%0" : "=m" (x));
+ return ((fp_rnd_t)FSR_GET_RD(x));
+}
diff --git a/lib/libc/sparc64/gen/fpgetsticky.c b/lib/libc/sparc64/gen/fpgetsticky.c
new file mode 100644
index 0000000..274566a
--- /dev/null
+++ b/lib/libc/sparc64/gen/fpgetsticky.c
@@ -0,0 +1,21 @@
+/* $NetBSD: fpgetsticky.c,v 1.2 2002/01/13 21:45:50 thorpej Exp $ */
+
+/*
+ * Written by J.T. Conklin, Apr 10, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/fsr.h>
+#include <ieeefp.h>
+
+fp_except_t
+fpgetsticky()
+{
+ unsigned int x;
+
+ __asm__("st %%fsr,%0" : "=m" (x));
+ return (FSR_GET_AEXC(x));
+}
diff --git a/lib/libc/sparc64/gen/fpsetmask.c b/lib/libc/sparc64/gen/fpsetmask.c
new file mode 100644
index 0000000..9aefb13
--- /dev/null
+++ b/lib/libc/sparc64/gen/fpsetmask.c
@@ -0,0 +1,28 @@
+/*
+ * Written by J.T. Conklin, Apr 10, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/fsr.h>
+#include <ieeefp.h>
+
+fp_except_t
+fpsetmask(mask)
+ fp_except_t mask;
+{
+ fp_except_t old;
+ fp_except_t new;
+
+ __asm__("st %%fsr,%0" : "=m" (old));
+
+ new = old;
+ new &= ~FSR_TEM_MASK;
+ new |= FSR_TEM(mask & FSR_EXC_MASK);
+
+ __asm__("ld %0,%%fsr" : : "m" (new));
+
+ return (FSR_GET_TEM(old));
+}
diff --git a/lib/libc/sparc64/gen/fpsetround.c b/lib/libc/sparc64/gen/fpsetround.c
new file mode 100644
index 0000000..1e27f59
--- /dev/null
+++ b/lib/libc/sparc64/gen/fpsetround.c
@@ -0,0 +1,30 @@
+/* $NetBSD: fpsetround.c,v 1.2 2002/01/13 21:45:51 thorpej Exp $ */
+
+/*
+ * Written by J.T. Conklin, Apr 10, 1995
+ * Public domain.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/fsr.h>
+#include <ieeefp.h>
+
+fp_rnd_t
+fpsetround(rnd_dir)
+ fp_rnd_t rnd_dir;
+{
+ unsigned int old;
+ unsigned int new;
+
+ __asm__("st %%fsr,%0" : "=m" (old));
+
+ new = old;
+ new &= ~FSR_RD_MASK;
+ new |= FSR_RD((unsigned int)rnd_dir & 0x03);
+
+ __asm__("ld %0,%%fsr" : : "m" (new));
+
+ return ((fp_rnd_t)FSR_GET_RD(old));
+}
diff --git a/lib/libc/sparc64/gen/getcontextx.c b/lib/libc/sparc64/gen/getcontextx.c
new file mode 100644
index 0000000..307978a
--- /dev/null
+++ b/lib/libc/sparc64/gen/getcontextx.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 Konstantin Belousov <kib@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/ucontext.h>
+#include <errno.h>
+#include <stdlib.h>
+
+int
+__getcontextx_size(void)
+{
+
+ return (sizeof(ucontext_t));
+}
+
+int
+__fillcontextx(char *ctx)
+{
+ ucontext_t *ucp;
+
+ ucp = (ucontext_t *)ctx;
+ return (getcontext(ucp));
+}
+
+__weak_reference(__getcontextx, getcontextx);
+
+ucontext_t *
+__getcontextx(void)
+{
+ char *ctx;
+ int error;
+
+ ctx = malloc(__getcontextx_size());
+ if (ctx == NULL)
+ return (NULL);
+ if (__fillcontextx(ctx) == -1) {
+ error = errno;
+ free(ctx);
+ errno = error;
+ return (NULL);
+ }
+ return ((ucontext_t *)ctx);
+}
diff --git a/lib/libc/sparc64/gen/infinity.c b/lib/libc/sparc64/gen/infinity.c
new file mode 100644
index 0000000..6d0d934
--- /dev/null
+++ b/lib/libc/sparc64/gen/infinity.c
@@ -0,0 +1,17 @@
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: infinity.c,v 1.2 1998/11/14 19:31:02 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+/* infinity.c */
+
+#include <math.h>
+
+/* bytes for +Infinity on a sparc */
+const union __infinity_un __infinity = { { 0x7f, 0xf0, 0, 0, 0, 0, 0, 0 } };
+
+/* bytes for NaN */
+const union __nan_un __nan = { { 0xff, 0xc0, 0, 0 } };
diff --git a/lib/libc/sparc64/gen/makecontext.c b/lib/libc/sparc64/gen/makecontext.c
new file mode 100644
index 0000000..95795de
--- /dev/null
+++ b/lib/libc/sparc64/gen/makecontext.c
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 2003 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/signal.h>
+#include <sys/ucontext.h>
+
+#include <machine/frame.h>
+#include <machine/tstate.h>
+
+#include <errno.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+__weak_reference(__makecontext, makecontext);
+
+void _ctx_done(ucontext_t *ucp);
+void _ctx_start(void);
+
+void
+__makecontext(ucontext_t *ucp, void (*start)(void), int argc, ...)
+{
+ mcontext_t *mc;
+ uint64_t sp;
+ va_list ap;
+ int i;
+
+ mc = &ucp->uc_mcontext;
+ if (ucp == NULL ||
+ (mc->mc_flags & ((1L << _MC_VERSION_BITS) - 1)) != _MC_VERSION)
+ return;
+ if ((argc < 0) || (argc > 6) ||
+ (ucp->uc_stack.ss_sp == NULL) ||
+ (ucp->uc_stack.ss_size < MINSIGSTKSZ)) {
+ mc->mc_flags = 0;
+ return;
+ }
+ mc = &ucp->uc_mcontext;
+ sp = (uint64_t)ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size;
+ va_start(ap, argc);
+ for (i = 0; i < argc; i++)
+ mc->mc_out[i] = va_arg(ap, uint64_t);
+ va_end(ap);
+ mc->mc_global[1] = (uint64_t)start;
+ mc->mc_global[2] = (uint64_t)ucp;
+ mc->mc_out[6] = sp - SPOFF - sizeof(struct frame);
+ mc->mc_tnpc = (uint64_t)_ctx_start + 4;
+ mc->mc_tpc = (uint64_t)_ctx_start;
+}
+
+void
+_ctx_done(ucontext_t *ucp)
+{
+
+ if (ucp->uc_link == NULL)
+ exit(0);
+ else {
+ ucp->uc_mcontext.mc_flags = 0;
+ setcontext((const ucontext_t *)ucp->uc_link);
+ abort();
+ }
+}
diff --git a/lib/libc/sparc64/gen/setjmp.S b/lib/libc/sparc64/gen/setjmp.S
new file mode 100644
index 0000000..8161b7a
--- /dev/null
+++ b/lib/libc/sparc64/gen/setjmp.S
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Header: _setjmp.s,v 1.1 91/07/06 16:45:53 torek Exp
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ .asciz "@(#)_setjmp.s 8.1 (Berkeley) 6/4/93"
+#if 0
+ RCSID("$NetBSD: _setjmp.S,v 1.4 1998/10/08 02:27:59 eeh Exp $")
+#endif
+#endif /* LIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "assym.s"
+
+ .register %g2,#ignore
+ .register %g3,#ignore
+
+/*
+ * C library -- setjmp, longjmp
+ *
+ * longjmp(a,v)
+ * will generate a "return(v?v:1)" from
+ * the last call to
+ * setjmp(a)
+ * by restoring the previous context.
+ */
+
+ENTRY(setjmp)
+ save %sp, -CCFSZ, %sp
+ mov SIG_BLOCK, %o0
+ clr %o1
+ call CNAME(sigprocmask)
+ add %i0, _JB_SIGMASK, %o2
+ restore
+ stx %sp, [%o0 + _JB_SP]
+ stx %o7, [%o0 + _JB_PC]
+ retl
+ clr %o0
+END(setjmp)
+
+ .weak CNAME(longjmp)
+ .set CNAME(longjmp),CNAME(__longjmp)
+ENTRY(__longjmp)
+ save %sp, -CCFSZ, %sp
+ flushw
+ mov SIG_SETMASK, %o0
+ add %i0, _JB_SIGMASK, %o1
+ call CNAME(sigprocmask)
+ clr %o2
+ ldx [%i0 + _JB_SP], %fp
+ ldx [%i0 + _JB_PC], %i7
+ mov 1, %i0
+ movrnz %i1, %i1, %i0
+ ret
+ restore
+END(__longjmp)
diff --git a/lib/libc/sparc64/gen/signalcontext.c b/lib/libc/sparc64/gen/signalcontext.c
new file mode 100644
index 0000000..622f36f
--- /dev/null
+++ b/lib/libc/sparc64/gen/signalcontext.c
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 2003 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/ucontext.h>
+
+#include <machine/frame.h>
+#include <machine/sigframe.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <strings.h>
+#include <unistd.h>
+
+__weak_reference(__signalcontext, signalcontext);
+
+extern void _ctx_start(void);
+
+int
+__signalcontext(ucontext_t *ucp, int sig, __sighandler_t *func)
+{
+ struct sigframe *sfp;
+ struct frame *fp;
+ mcontext_t *mc;
+
+ mc = &ucp->uc_mcontext;
+ sfp = (struct sigframe *)(mc->mc_sp + SPOFF) - 1;
+ fp = (struct frame *)sfp - 1;
+
+ bzero(fp, sizeof(*fp));
+
+ bzero(sfp, sizeof(*sfp));
+ bcopy(ucp, &sfp->sf_uc, sizeof(*ucp));
+ sfp->sf_si.si_signo = sig;
+
+ mc->mc_global[1] = (uint64_t)func;
+ mc->mc_global[2] = (uint64_t)ucp;
+ mc->mc_out[0] = sig;
+ mc->mc_out[1] = (uint64_t)&sfp->sf_si;
+ mc->mc_out[2] = (uint64_t)&sfp->sf_uc;
+ mc->mc_out[6] = (uint64_t)fp - SPOFF;
+ mc->mc_tnpc = (uint64_t)_ctx_start + 4;
+ mc->mc_tpc = (uint64_t)_ctx_start;
+
+ ucp->uc_link = &sfp->sf_uc;
+ sigdelset(&ucp->uc_sigmask, sig);
+
+ return (0);
+}
diff --git a/lib/libc/sparc64/gen/sigsetjmp.S b/lib/libc/sparc64/gen/sigsetjmp.S
new file mode 100644
index 0000000..4e44566
--- /dev/null
+++ b/lib/libc/sparc64/gen/sigsetjmp.S
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1995 Paul Kranenburg
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by Paul Kranenburg.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "assym.s"
+
+ENTRY(sigsetjmp)
+ PIC_PROLOGUE(%o3, %o2)
+ SET(CNAME(setjmp), %o2, %o3)
+ SET(CNAME(_setjmp), %o2, %o4)
+ movrnz %o1, %o3, %o4
+ jmp %o4
+ stx %o1, [%o0 + _JB_SIGFLAG]
+END(sigsetjmp)
+
+ .weak CNAME(siglongjmp);
+ .set CNAME(siglongjmp),CNAME(__siglongjmp);
+ENTRY(__siglongjmp)
+ PIC_PROLOGUE(%o3, %o2)
+ SET(CNAME(longjmp), %o2, %o3)
+ SET(CNAME(_longjmp), %o2, %o4)
+ ldx [%o0 + _JB_SIGFLAG], %o2
+ movrnz %o2, %o3, %o4
+ jmp %o4
+ nop
+END(__siglongjmp)
diff --git a/lib/libc/sparc64/string/Makefile.inc b/lib/libc/sparc64/string/Makefile.inc
new file mode 100644
index 0000000..e8c0da7
--- /dev/null
+++ b/lib/libc/sparc64/string/Makefile.inc
@@ -0,0 +1 @@
+# $FreeBSD$
diff --git a/lib/libc/sparc64/sys/Makefile.inc b/lib/libc/sparc64/sys/Makefile.inc
new file mode 100644
index 0000000..dedf783
--- /dev/null
+++ b/lib/libc/sparc64/sys/Makefile.inc
@@ -0,0 +1,23 @@
+# $FreeBSD$
+
+SRCS+= __sparc_sigtramp_setup.c \
+ __sparc_utrap.c \
+ __sparc_utrap_align.c \
+ __sparc_utrap_emul.c \
+ __sparc_utrap_fp_disabled.S \
+ __sparc_utrap_gen.S \
+ __sparc_utrap_install.c \
+ __sparc_utrap_setup.c \
+ sigcode.S
+
+CFLAGS+= -I${.CURDIR}/sparc64/fpu
+
+MDASM+= brk.S cerror.S exect.S pipe.S ptrace.S sbrk.S setlogin.S sigaction.S
+
+# Don't generate default code for these syscalls:
+NOASM= break.o exit.o getlogin.o openbsd_poll.o sstk.o yield.o
+
+PSEUDO= _getlogin.o _exit.o
+.if !defined(WITHOUT_SYSCALL_COMPAT)
+PSEUDO+= _pread.o _pwrite.o _lseek.o _mmap.o _ftruncate.o _truncate.o
+.endif
diff --git a/lib/libc/sparc64/sys/__sparc_sigtramp_setup.c b/lib/libc/sparc64/sys/__sparc_sigtramp_setup.c
new file mode 100644
index 0000000..4475c6d
--- /dev/null
+++ b/lib/libc/sparc64/sys/__sparc_sigtramp_setup.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2002 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <machine/utrap.h>
+#include <machine/sysarch.h>
+
+#include <stdlib.h>
+
+extern char __sigtramp[];
+
+static const struct sparc_sigtramp_install_args sia = { __sigtramp, NULL };
+
+void
+__sparc_sigtramp_setup(void)
+{
+
+ sysarch(SPARC_SIGTRAMP_INSTALL, (void *)&sia);
+}
diff --git a/lib/libc/sparc64/sys/__sparc_utrap.c b/lib/libc/sparc64/sys/__sparc_utrap.c
new file mode 100644
index 0000000..7a5dafa
--- /dev/null
+++ b/lib/libc/sparc64/sys/__sparc_utrap.c
@@ -0,0 +1,141 @@
+/*-
+ * Copyright (c) 2001 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <machine/utrap.h>
+#include <machine/sysarch.h>
+
+#include <errno.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include "fpu_extern.h"
+#include "__sparc_utrap_private.h"
+
+extern ssize_t __sys_write(int, const void *, size_t);
+extern int __sys_kill(pid_t, int);
+extern pid_t __sys_getpid(void);
+
+static const char *utrap_msg[] = {
+ "reserved",
+ "instruction access exception",
+ "instruction access error",
+ "instruction access protection",
+ "illtrap instruction",
+ "illegal instruction",
+ "privileged opcode",
+ "floating point disabled",
+ "floating point exception ieee 754",
+ "floating point exception other",
+ "tag overflow",
+ "division by zero",
+ "data access exception",
+ "data access error",
+ "data access protection",
+ "memory address not aligned",
+ "privileged action",
+ "async data error",
+ "trap instruction 16",
+ "trap instruction 17",
+ "trap instruction 18",
+ "trap instruction 19",
+ "trap instruction 20",
+ "trap instruction 21",
+ "trap instruction 22",
+ "trap instruction 23",
+ "trap instruction 24",
+ "trap instruction 25",
+ "trap instruction 26",
+ "trap instruction 27",
+ "trap instruction 28",
+ "trap instruction 29",
+ "trap instruction 30",
+ "trap instruction 31",
+};
+
+void
+__sparc_utrap(struct utrapframe *uf)
+{
+ int sig;
+
+ switch (uf->uf_type) {
+ case UT_FP_EXCEPTION_IEEE_754:
+ case UT_FP_EXCEPTION_OTHER:
+ sig = __fpu_exception(uf);
+ break;
+ case UT_ILLEGAL_INSTRUCTION:
+ sig = __emul_insn(uf);
+ break;
+ case UT_MEM_ADDRESS_NOT_ALIGNED:
+ sig = __unaligned_fixup(uf);
+ break;
+ default:
+ break;
+ }
+ if (sig) {
+ __utrap_write("__sparc_utrap: fatal ");
+ __utrap_write(utrap_msg[uf->uf_type]);
+ __utrap_write("\n");
+ __utrap_kill_self(sig);
+ }
+ UF_DONE(uf);
+}
+
+void
+__utrap_write(const char *str)
+{
+ int berrno;
+
+ berrno = errno;
+ __sys_write(STDERR_FILENO, str, strlen(str));
+ errno = berrno;
+}
+
+void
+__utrap_kill_self(int sig)
+{
+ int berrno;
+
+ berrno = errno;
+ __sys_kill(__sys_getpid(), sig);
+ errno = berrno;
+}
+
+void
+__utrap_panic(const char *msg)
+{
+
+ __utrap_write(msg);
+ __utrap_write("\n");
+ __utrap_kill_self(SIGKILL);
+}
diff --git a/lib/libc/sparc64/sys/__sparc_utrap_align.c b/lib/libc/sparc64/sys/__sparc_utrap_align.c
new file mode 100644
index 0000000..9b59826
--- /dev/null
+++ b/lib/libc/sparc64/sys/__sparc_utrap_align.c
@@ -0,0 +1,117 @@
+/*-
+ * Copyright (c) 2002 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <machine/cpufunc.h>
+#include <machine/instr.h>
+
+#include <signal.h>
+
+#include "__sparc_utrap_private.h"
+
+static u_long
+__unaligned_load(u_char *p, int size)
+{
+ u_long val;
+ int i;
+
+ val = 0;
+ for (i = 0; i < size; i++)
+ val = (val << 8) | p[i];
+ return (val);
+}
+
+static void
+__unaligned_store(u_char *p, u_long val, int size)
+{
+ int i;
+
+ for (i = 0; i < size; i++)
+ p[i] = val >> ((size - i - 1) * 8);
+}
+
+int
+__unaligned_fixup(struct utrapframe *uf)
+{
+ u_char *addr;
+ u_long val;
+ u_int insn;
+ int sig;
+
+ sig = 0;
+ addr = (u_char *)uf->uf_sfar;
+ insn = *(u_int *)uf->uf_pc;
+ flushw();
+ switch (IF_OP(insn)) {
+ case IOP_LDST:
+ switch (IF_F3_OP3(insn)) {
+ case INS3_LDUH:
+ val = __unaligned_load(addr, 2);
+ __emul_store_reg(uf, IF_F3_RD(insn), val);
+ break;
+ case INS3_LDUW:
+ val = __unaligned_load(addr, 4);
+ __emul_store_reg(uf, IF_F3_RD(insn), val);
+ break;
+ case INS3_LDX:
+ val = __unaligned_load(addr, 8);
+ __emul_store_reg(uf, IF_F3_RD(insn), val);
+ break;
+ case INS3_LDSH:
+ val = __unaligned_load(addr, 2);
+ __emul_store_reg(uf, IF_F3_RD(insn),
+ IF_SEXT(val, 16));
+ break;
+ case INS3_LDSW:
+ val = __unaligned_load(addr, 4);
+ __emul_store_reg(uf, IF_F3_RD(insn),
+ IF_SEXT(val, 32));
+ break;
+ case INS3_STH:
+ val = __emul_fetch_reg(uf, IF_F3_RD(insn));
+ __unaligned_store(addr, val, 2);
+ break;
+ case INS3_STW:
+ val = __emul_fetch_reg(uf, IF_F3_RD(insn));
+ __unaligned_store(addr, val, 4);
+ break;
+ case INS3_STX:
+ val = __emul_fetch_reg(uf, IF_F3_RD(insn));
+ __unaligned_store(addr, val, 8);
+ break;
+ default:
+ sig = SIGILL;
+ break;
+ }
+ break;
+ default:
+ sig = SIGILL;
+ break;
+ }
+ return (sig);
+}
diff --git a/lib/libc/sparc64/sys/__sparc_utrap_emul.c b/lib/libc/sparc64/sys/__sparc_utrap_emul.c
new file mode 100644
index 0000000..6c6dd1b
--- /dev/null
+++ b/lib/libc/sparc64/sys/__sparc_utrap_emul.c
@@ -0,0 +1,155 @@
+/*-
+ * Copyright (c) 2001 by Thomas Moestl <tmm@FreeBSD.org>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ * USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <machine/cpufunc.h>
+#include <machine/frame.h>
+#include <machine/instr.h>
+
+#include <signal.h>
+
+#include "__sparc_utrap_private.h"
+#include "fpu_reg.h"
+
+int
+__emul_insn(struct utrapframe *uf)
+{
+ u_long reg, res;
+ u_long *addr;
+ u_int insn;
+ int sig;
+ int rd;
+ int i;
+
+ sig = 0;
+ insn = *(u_int *)uf->uf_pc;
+ flushw();
+ switch (IF_OP(insn)) {
+ case IOP_MISC:
+ switch (IF_F3_OP3(insn)) {
+ case INS2_POPC:
+ if (IF_F3_RS1(insn) != 0) {
+ sig = SIGILL;
+ break;
+ }
+ reg = __emul_f3_op2(uf, insn);
+ for (i = 0; i < 64; i++)
+ res += (reg >> i) & 1;
+ __emul_store_reg(uf, IF_F3_RD(insn), res);
+ break;
+ default:
+ sig = SIGILL;
+ break;
+ }
+ break;
+ case IOP_LDST:
+ switch (IF_F3_OP3(insn)) {
+ case INS3_LDQF:
+ rd = INSFPdq_RN(IF_F3_RD(insn));
+ addr = (u_long *)__emul_f3_memop_addr(uf, insn);
+ __fpu_setreg64(rd, addr[0]);
+ __fpu_setreg64(rd + 2, addr[1]);
+ break;
+ case INS3_STQF:
+ rd = INSFPdq_RN(IF_F3_RD(insn));
+ addr = (u_long *)__emul_f3_memop_addr(uf, insn);
+ addr[0] = __fpu_getreg64(rd);
+ addr[1] = __fpu_getreg64(rd + 2);
+ break;
+ default:
+ sig = SIGILL;
+ break;
+ }
+ break;
+ default:
+ sig = SIGILL;
+ break;
+ }
+ return (sig);
+}
+
+u_long
+__emul_fetch_reg(struct utrapframe *uf, int reg)
+{
+ struct frame *frm;
+
+ if (reg == IREG_G0)
+ return (0);
+ else if (reg < IREG_O0) /* global */
+ return (uf->uf_global[reg]);
+ else if (reg < IREG_L0) /* out */
+ return (uf->uf_out[reg - IREG_O0]);
+ else { /* local, in */
+ /*
+ * The in registers are immediately after the locals in
+ * the frame.
+ */
+ frm = (struct frame *)(uf->uf_out[6] + SPOFF);
+ return (frm->fr_local[reg - IREG_L0]);
+ }
+}
+
+void
+__emul_store_reg(struct utrapframe *uf, int reg, u_long val)
+{
+ struct frame *frm;
+
+ if (reg == IREG_G0)
+ return;
+ if (reg < IREG_O0) /* global */
+ uf->uf_global[reg] = val;
+ else if (reg < IREG_L0) /* out */
+ uf->uf_out[reg - IREG_O0] = val;
+ else {
+ /*
+ * The in registers are immediately after the locals in
+ * the frame.
+ */
+ frm = (struct frame *)(uf->uf_out[6] + SPOFF);
+ frm->fr_local[reg - IREG_L0] = val;
+ }
+}
+
+u_long
+__emul_f3_op2(struct utrapframe *uf, u_int insn)
+{
+
+ if (IF_F3_I(insn) != 0)
+ return (IF_SIMM(insn, 13));
+ else
+ return (__emul_fetch_reg(uf, IF_F3_RS2(insn)));
+}
+
+u_long
+__emul_f3_memop_addr(struct utrapframe *uf, u_int insn)
+{
+ u_long addr;
+
+ addr = __emul_f3_op2(uf, insn) + __emul_fetch_reg(uf, IF_F3_RS1(insn));
+ return (addr);
+}
diff --git a/lib/libc/sparc64/sys/__sparc_utrap_fp_disabled.S b/lib/libc/sparc64/sys/__sparc_utrap_fp_disabled.S
new file mode 100644
index 0000000..502f81a
--- /dev/null
+++ b/lib/libc/sparc64/sys/__sparc_utrap_fp_disabled.S
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2001 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/utrap.h>
+
+ENTRY(__sparc_utrap_fp_disabled)
+ ta %xcc, ST_FP_RESTORE
+ jmpl %l6, %g0
+ return %l7
+END(__sparc_utrap_fp_disabled)
diff --git a/lib/libc/sparc64/sys/__sparc_utrap_gen.S b/lib/libc/sparc64/sys/__sparc_utrap_gen.S
new file mode 100644
index 0000000..6f6f0e3
--- /dev/null
+++ b/lib/libc/sparc64/sys/__sparc_utrap_gen.S
@@ -0,0 +1,107 @@
+/*-
+ * Copyright (c) 2001 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+ .register %g2, #ignore
+ .register %g3, #ignore
+ .register %g6, #ignore
+ .register %g7, #ignore
+
+#include <machine/tstate.h>
+#include <machine/utrap.h>
+
+#include "assym.s"
+
+ENTRY(__sparc_utrap_gen)
+ sub %sp, UF_SIZEOF, %sp
+
+ stx %o0, [%sp + SPOFF + CCFSZ + UF_TYPE]
+ stx %o3, [%sp + SPOFF + CCFSZ + UF_TAR]
+ stx %o4, [%sp + SPOFF + CCFSZ + UF_SFAR]
+ stx %o5, [%sp + SPOFF + CCFSZ + UF_SFSR]
+
+ stx %l4, [%sp + SPOFF + CCFSZ + UF_FSR]
+ stx %l5, [%sp + SPOFF + CCFSZ + UF_STATE]
+ stx %l6, [%sp + SPOFF + CCFSZ + UF_PC]
+ stx %l7, [%sp + SPOFF + CCFSZ + UF_NPC]
+
+ stx %g1, [%sp + SPOFF + CCFSZ + UF_G1]
+ stx %g2, [%sp + SPOFF + CCFSZ + UF_G2]
+ stx %g3, [%sp + SPOFF + CCFSZ + UF_G3]
+ stx %g4, [%sp + SPOFF + CCFSZ + UF_G4]
+ stx %g5, [%sp + SPOFF + CCFSZ + UF_G5]
+ stx %g6, [%sp + SPOFF + CCFSZ + UF_G6]
+ stx %g7, [%sp + SPOFF + CCFSZ + UF_G7]
+
+ stx %i0, [%sp + SPOFF + CCFSZ + UF_O0]
+ stx %i1, [%sp + SPOFF + CCFSZ + UF_O1]
+ stx %i2, [%sp + SPOFF + CCFSZ + UF_O2]
+ stx %i3, [%sp + SPOFF + CCFSZ + UF_O3]
+ stx %i4, [%sp + SPOFF + CCFSZ + UF_O4]
+ stx %i5, [%sp + SPOFF + CCFSZ + UF_O5]
+ stx %i6, [%sp + SPOFF + CCFSZ + UF_O6]
+ stx %i7, [%sp + SPOFF + CCFSZ + UF_O7]
+
+ rd %y, %l6
+
+ call __sparc_utrap
+ add %sp, SPOFF + CCFSZ, %o0
+
+ wr %l6, 0, %y
+
+ ldx [%sp + SPOFF + CCFSZ + UF_G1], %g1
+ ldx [%sp + SPOFF + CCFSZ + UF_G2], %g2
+ ldx [%sp + SPOFF + CCFSZ + UF_G3], %g3
+ ldx [%sp + SPOFF + CCFSZ + UF_G4], %g4
+ ldx [%sp + SPOFF + CCFSZ + UF_G5], %g5
+ ldx [%sp + SPOFF + CCFSZ + UF_G6], %g6
+ ldx [%sp + SPOFF + CCFSZ + UF_G7], %g7
+
+ ldx [%sp + SPOFF + CCFSZ + UF_O0], %i0
+ ldx [%sp + SPOFF + CCFSZ + UF_O1], %i1
+ ldx [%sp + SPOFF + CCFSZ + UF_O2], %i2
+ ldx [%sp + SPOFF + CCFSZ + UF_O3], %i3
+ ldx [%sp + SPOFF + CCFSZ + UF_O4], %i4
+ ldx [%sp + SPOFF + CCFSZ + UF_O5], %i5
+ ldx [%sp + SPOFF + CCFSZ + UF_O6], %i6
+ ldx [%sp + SPOFF + CCFSZ + UF_O7], %i7
+
+ ldx [%sp + SPOFF + CCFSZ + UF_STATE], %l5
+ ! Restore %asi and %ccr from the passed tstate
+ srlx %l5, TSTATE_CCR_SHIFT, %l4
+ and %l4, CCR_MASK, %l4
+ wr %l4, 0, %ccr
+ srlx %l5, TSTATE_ASI_SHIFT, %l4
+ and %l4, ASI_MASK, %l4
+ wr %l4, 0, %asi
+ ldx [%sp + SPOFF + CCFSZ + UF_PC], %l6
+ ldx [%sp + SPOFF + CCFSZ + UF_NPC], %l7
+
+ jmpl %l6, %g0
+ return %l7
+END(__sparc_utrap_gen)
diff --git a/lib/libc/sparc64/sys/__sparc_utrap_install.c b/lib/libc/sparc64/sys/__sparc_utrap_install.c
new file mode 100644
index 0000000..7b1a5e7
--- /dev/null
+++ b/lib/libc/sparc64/sys/__sparc_utrap_install.c
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2001 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <machine/utrap.h>
+#include <machine/sysarch.h>
+
+int
+__sparc_utrap_install(utrap_entry_t type, utrap_handler_t new_precise,
+ utrap_handler_t new_deferred, utrap_handler_t *old_precise,
+ utrap_handler_t *old_deferred)
+{
+ struct sparc_utrap_install_args uia;
+ struct sparc_utrap_args ua[1];
+
+ ua[0].type = type;
+ ua[0].new_precise = new_precise;
+ ua[0].new_deferred = new_deferred;
+ ua[0].old_precise = old_precise;
+ ua[0].old_deferred = old_deferred;
+ uia.num = 1;
+ uia.handlers = ua;
+ return (sysarch(SPARC_UTRAP_INSTALL, &uia));
+}
diff --git a/lib/libc/sparc64/sys/__sparc_utrap_private.h b/lib/libc/sparc64/sys/__sparc_utrap_private.h
new file mode 100644
index 0000000..8b9ae9e
--- /dev/null
+++ b/lib/libc/sparc64/sys/__sparc_utrap_private.h
@@ -0,0 +1,66 @@
+/*-
+ * Copyright (c) 2001 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef ___SPARC_UTRAP_PRIVATE_H_
+#define ___SPARC_UTRAP_PRIVATE_H_
+
+#define UF_DONE(uf) do { \
+ uf->uf_pc = uf->uf_npc; \
+ uf->uf_npc = uf->uf_pc + 4; \
+} while (0)
+
+struct utrapframe {
+ u_long uf_global[8];
+ u_long uf_out[8];
+ u_long uf_pc;
+ u_long uf_npc;
+ u_long uf_sfar;
+ u_long uf_sfsr;
+ u_long uf_tar;
+ u_long uf_type;
+ u_long uf_state;
+ u_long uf_fsr;
+};
+
+extern char __sparc_utrap_fp_disabled[];
+extern char __sparc_utrap_gen[];
+
+int __emul_insn(struct utrapframe *uf);
+u_long __emul_fetch_reg(struct utrapframe *uf, int reg);
+void __emul_store_reg(struct utrapframe *uf, int reg, u_long val);
+u_long __emul_f3_op2(struct utrapframe *uf, u_int insn);
+u_long __emul_f3_memop_addr(struct utrapframe *uf, u_int insn);
+int __unaligned_fixup(struct utrapframe *uf);
+
+void __sparc_utrap(struct utrapframe *);
+
+void __utrap_write(const char *);
+void __utrap_kill_self(int);
+void __utrap_panic(const char *);
+
+#endif
diff --git a/lib/libc/sparc64/sys/__sparc_utrap_setup.c b/lib/libc/sparc64/sys/__sparc_utrap_setup.c
new file mode 100644
index 0000000..f4a624b
--- /dev/null
+++ b/lib/libc/sparc64/sys/__sparc_utrap_setup.c
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2001 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <machine/utrap.h>
+#include <machine/sysarch.h>
+
+#include <stdlib.h>
+
+#include "__sparc_utrap_private.h"
+
+static const struct sparc_utrap_args ua[] = {
+ { UT_FP_DISABLED, __sparc_utrap_fp_disabled, NULL, NULL, NULL },
+ { UT_FP_EXCEPTION_IEEE_754, __sparc_utrap_gen, NULL, NULL, NULL },
+ { UT_FP_EXCEPTION_OTHER, __sparc_utrap_gen, NULL, NULL, NULL },
+ { UT_ILLEGAL_INSTRUCTION, __sparc_utrap_gen, NULL, NULL, NULL },
+ { UT_MEM_ADDRESS_NOT_ALIGNED, __sparc_utrap_gen, NULL, NULL, NULL },
+};
+
+static const struct sparc_utrap_install_args uia[] = {
+ { sizeof (ua) / sizeof (*ua), ua }
+};
+
+void __sparc_utrap_setup(void) __attribute__((constructor));
+
+void
+__sparc_utrap_setup(void)
+{
+
+ sysarch(SPARC_UTRAP_INSTALL, &uia);
+}
diff --git a/lib/libc/sparc64/sys/assym.s b/lib/libc/sparc64/sys/assym.s
new file mode 100644
index 0000000..2e799f6
--- /dev/null
+++ b/lib/libc/sparc64/sys/assym.s
@@ -0,0 +1,39 @@
+/*
+ * Offsets into structures used from asm. Must be kept in sync with
+ * appropriate headers.
+ *
+ * $FreeBSD$
+ */
+
+#define FPRS_FEF 0x4
+
+#define CCR_MASK 0xff
+#define ASI_MASK 0xff
+
+#define UF_G0 0x0
+#define UF_G1 0x8
+#define UF_G2 0x10
+#define UF_G3 0x18
+#define UF_G4 0x20
+#define UF_G5 0x28
+#define UF_G6 0x30
+#define UF_G7 0x38
+#define UF_O0 0x40
+#define UF_O1 0x48
+#define UF_O2 0x50
+#define UF_O3 0x58
+#define UF_O4 0x60
+#define UF_O5 0x68
+#define UF_O6 0x70
+#define UF_O7 0x78
+#define UF_PC 0x80
+#define UF_NPC 0x88
+#define UF_SFAR 0x90
+#define UF_SFSR 0x98
+#define UF_TAR 0xa0
+#define UF_TYPE 0xa8
+#define UF_STATE 0xb0
+#define UF_FSR 0xb8
+#define UF_SIZEOF 0xc0
+
+#define SF_UC 0x0
diff --git a/lib/libc/sparc64/sys/brk.S b/lib/libc/sparc64/sys/brk.S
new file mode 100644
index 0000000..0167c4e
--- /dev/null
+++ b/lib/libc/sparc64/sys/brk.S
@@ -0,0 +1,65 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Header: brk.s,v 1.3 92/06/25 12:56:05 mccanne Exp
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)brk.s 8.1 (Berkeley) 6/4/93"
+#if 0
+ RCSID("$NetBSD: brk.S,v 1.9 2000/07/25 20:15:40 mycroft Exp $")
+#endif
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl HIDENAME(curbrk)
+ .globl HIDENAME(minbrk)
+
+_SYSENTRY(brk)
+ PIC_PROLOGUE(%o3, %o2)
+ SET(HIDENAME(minbrk), %o2, %o3)
+ ldx [%o3], %o4
+ cmp %o4, %o0
+ movg %xcc, %o4, %o0
+ mov %o0, %o4
+ mov SYS_break, %g1
+ ta %xcc, ST_SYSCALL
+ bcc,a,pt %xcc, 1f
+ nop
+ ERROR()
+1: SET(HIDENAME(curbrk), %o2, %o3)
+ retl
+ stx %o4, [%o3]
+_SYSEND(brk)
diff --git a/lib/libc/sparc64/sys/cerror.S b/lib/libc/sparc64/sys/cerror.S
new file mode 100644
index 0000000..9f903ea
--- /dev/null
+++ b/lib/libc/sparc64/sys/cerror.S
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: FreeBSD: src/lib/libc/i386/sys/cerror.S,v 1.11 2001/08/13
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .text
+ .align 16
+ .globl HIDENAME(cerror)
+ .type HIDENAME(cerror),@function
+
+ /*
+ * The __error() function is thread aware. For non-threaded
+ * programs and the initial threaded in threaded programs,
+ * it returns a pointer to the global errno variable.
+ */
+ .globl CNAME(__error)
+HIDENAME(cerror):
+ save %sp, -CCFSZ, %sp
+ call CNAME(__error)
+ nop
+ stw %i0, [%o0]
+ mov -1, %i0
+ ret
+ restore %g0, -1, %o1
+END(HIDENAME(cerror))
diff --git a/lib/libc/sparc64/sys/exect.S b/lib/libc/sparc64/sys/exect.S
new file mode 100644
index 0000000..f6af223
--- /dev/null
+++ b/lib/libc/sparc64/sys/exect.S
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Header: exect.s,v 1.1 91/07/06 13:05:57 torek Exp
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+ .asciz "@(#)exect.s 8.1 (Berkeley) 6/4/93"
+#if 0
+ RCSID("$NetBSD: exect.S,v 1.1 1998/09/11 04:56:34 eeh Exp $")
+#endif
+#endif /* LIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+_SYSENTRY(exect)
+ mov SYS_execve, %g1
+ ta %xcc, ST_SYSCALL
+ ERROR()
+_SYSEND(exect)
diff --git a/lib/libc/sparc64/sys/pipe.S b/lib/libc/sparc64/sys/pipe.S
new file mode 100644
index 0000000..8940544
--- /dev/null
+++ b/lib/libc/sparc64/sys/pipe.S
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Header: pipe.s,v 1.1 91/07/06 13:05:58 torek Exp
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)pipe.s 8.1 (Berkeley) 6/4/93"
+#if 0
+ RCSID("$NetBSD: pipe.S,v 1.3 2000/09/28 08:38:55 kleink Exp $")
+#endif
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+_SYSENTRY(pipe)
+ mov %o0, %o2
+ mov SYS_pipe, %g1
+ ta %xcc, ST_SYSCALL
+ bcc,a,pt %xcc, 1f
+ stw %o0, [%o2]
+ ERROR()
+1: stw %o1, [%o2 + 4]
+ retl
+ clr %o0
+_SYSEND(pipe)
diff --git a/lib/libc/sparc64/sys/ptrace.S b/lib/libc/sparc64/sys/ptrace.S
new file mode 100644
index 0000000..eb415cd
--- /dev/null
+++ b/lib/libc/sparc64/sys/ptrace.S
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Header: ptrace.s,v 1.2 91/12/20 01:59:00 leres Exp
+ * from: NetBSD: ptrace.S,v 1.4 2000/07/24 00:11:10 mycroft Exp
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)ptrace.s 8.1 (Berkeley) 6/4/93"
+#if 0
+ RCSID("$NetBSD: ptrace.S,v 1.4 2000/07/24 00:11:10 mycroft Exp $")
+#endif
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+_SYSENTRY(ptrace)
+ save %sp, -CCFSZ, %sp
+ call CNAME(__error)
+ nop
+ stw %g0, [%o0]
+ restore
+ _SYSCALL(ptrace)
+ retl
+ nop
+_SYSEND(ptrace)
diff --git a/lib/libc/sparc64/sys/sbrk.S b/lib/libc/sparc64/sys/sbrk.S
new file mode 100644
index 0000000..c8c6e97
--- /dev/null
+++ b/lib/libc/sparc64/sys/sbrk.S
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Header: brk.s,v 1.3 92/06/25 12:56:05 mccanne Exp
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)sbrk.s 8.1 (Berkeley) 6/4/93"
+#if 0
+ RCSID("$NetBSD: sbrk.S,v 1.7 2000/07/25 15:14:46 mycroft Exp $")
+#endif
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .data
+ .globl HIDENAME(curbrk)
+ .globl HIDENAME(minbrk)
+ .type HIDENAME(curbrk),@object
+ .type HIDENAME(minbrk),@object
+ .align 8
+HIDENAME(curbrk):
+ .xword CNAME(_end)
+HIDENAME(minbrk):
+ .xword CNAME(_end)
+
+_SYSENTRY(sbrk)
+ PIC_PROLOGUE(%o3, %o2)
+ SET(HIDENAME(curbrk), %o2, %o3)
+ ldx [%o3], %o4
+ add %o4, %o0, %o5
+ mov %o5, %o0
+ mov SYS_break, %g1
+ ta %xcc, ST_SYSCALL
+ bcc,a,pt %xcc, 1f
+ mov %o4, %o0
+ ERROR()
+1: retl
+ stx %o5, [%o3]
+_SYSEND(sbrk)
diff --git a/lib/libc/sparc64/sys/setlogin.S b/lib/libc/sparc64/sys/setlogin.S
new file mode 100644
index 0000000..d7595cf
--- /dev/null
+++ b/lib/libc/sparc64/sys/setlogin.S
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This software was developed by the Computer Systems Engineering group
+ * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
+ * contributed to Berkeley.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * from: Header: setlogin.s,v 1.1 91/07/06 13:06:00 torek Exp
+ */
+
+#if defined(SYSLIBC_SCCS) && !defined(lint)
+ .asciz "@(#)setlogin.s 8.1 (Berkeley) 6/4/93"
+#if 0
+ RCSID("$NetBSD: setlogin.S,v 1.3 2000/07/21 03:14:15 eeh Exp $")
+#endif
+#endif /* SYSLIBC_SCCS and not lint */
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+ .globl CNAME(_logname_valid) /* in _getlogin() */
+
+_SYSENTRY(setlogin)
+ _SYSCALL(setlogin)
+ PIC_PROLOGUE(%o3, %o2)
+ SET(CNAME(_logname_valid), %o2, %o3)
+ retl
+ stw %g0, [%o3]
+_SYSEND(setlogin)
diff --git a/lib/libc/sparc64/sys/sigaction.S b/lib/libc/sparc64/sys/sigaction.S
new file mode 100644
index 0000000..7d32f97
--- /dev/null
+++ b/lib/libc/sparc64/sys/sigaction.S
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2002 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "SYS.h"
+
+_SYSENTRY(sigaction)
+ PIC_PROLOGUE(%o3, %o4)
+ SET(sigcode_installed, %o4, %o3)
+ lduw [%o3], %o4
+ brnz,a,pt %o4, 1f
+ nop
+ save %sp, -CCFSZ, %sp
+ call __sparc_sigtramp_setup
+ nop
+ restore
+ mov 1, %o4
+ stw %o4, [%o3]
+1: _SYSCALL(sigaction)
+ retl
+ nop
+_SYSEND(sigaction)
+
+ .comm sigcode_installed, 4, 4
diff --git a/lib/libc/sparc64/sys/sigcode.S b/lib/libc/sparc64/sys/sigcode.S
new file mode 100644
index 0000000..be3cb45
--- /dev/null
+++ b/lib/libc/sparc64/sys/sigcode.S
@@ -0,0 +1,40 @@
+/*-
+ * Copyright (c) 2002 Jake Burkholder.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+__FBSDID("$FreeBSD$");
+
+#include "assym.s"
+
+ENTRY(__sigtramp)
+ call %o4
+ nop
+ call sigreturn
+ add %sp, SPOFF + CCFSZ + SF_UC, %o0
+ call exit
+ mov 1, %o0
+ illtrap
+END(__sigtramp)
diff --git a/lib/libc/stdio/Makefile.inc b/lib/libc/stdio/Makefile.inc
new file mode 100644
index 0000000..c3b60f6
--- /dev/null
+++ b/lib/libc/stdio/Makefile.inc
@@ -0,0 +1,76 @@
+# @(#)Makefile.inc 8.3 (Berkeley) 4/17/94
+# $FreeBSD$
+
+# stdio sources
+.PATH: ${.CURDIR}/stdio
+
+SRCS+= _flock_stub.c asprintf.c clrerr.c dprintf.c \
+ fclose.c fcloseall.c fdopen.c \
+ feof.c ferror.c fflush.c fgetc.c fgetln.c fgetpos.c fgets.c fgetwc.c \
+ fgetwln.c fgetws.c \
+ fileno.c findfp.c flags.c fopen.c fprintf.c fpurge.c fputc.c fputs.c \
+ fputwc.c fputws.c fread.c freopen.c fscanf.c fseek.c fsetpos.c \
+ ftell.c funopen.c fvwrite.c fwalk.c fwide.c fwprintf.c fwscanf.c \
+ fwrite.c getc.c getchar.c getdelim.c getline.c \
+ gets.c getw.c getwc.c getwchar.c makebuf.c mktemp.c \
+ perror.c printf.c printf-pos.c putc.c putchar.c \
+ puts.c putw.c putwc.c putwchar.c \
+ refill.c remove.c rewind.c rget.c scanf.c setbuf.c setbuffer.c \
+ setvbuf.c snprintf.c sprintf.c sscanf.c stdio.c swprintf.c swscanf.c \
+ tempnam.c tmpfile.c \
+ tmpnam.c ungetc.c ungetwc.c vasprintf.c vdprintf.c vfprintf.c \
+ vfscanf.c \
+ vfwprintf.c vfwscanf.c vprintf.c vscanf.c vsnprintf.c vsprintf.c \
+ vsscanf.c \
+ vswprintf.c vswscanf.c vwprintf.c vwscanf.c wbuf.c wprintf.c wscanf.c \
+ wsetup.c
+
+SRCS+= xprintf.c xprintf_float.c xprintf_int.c xprintf_str.c
+SRCS+= xprintf_errno.c xprintf_hexdump.c xprintf_quote.c
+SRCS+= xprintf_time.c xprintf_vis.c
+
+SYM_MAPS+= ${.CURDIR}/stdio/Symbol.map
+
+MAN+= fclose.3 ferror.3 fflush.3 fgetln.3 fgets.3 fgetwln.3 fgetws.3 \
+ flockfile.3 \
+ fopen.3 fputs.3 \
+ fputws.3 fread.3 fseek.3 funopen.3 fwide.3 getc.3 \
+ getline.3 getwc.3 mktemp.3 \
+ printf.3 putc.3 putwc.3 remove.3 scanf.3 setbuf.3 stdio.3 tmpnam.3 \
+ ungetc.3 ungetwc.3 wprintf.3 wscanf.3
+
+MLINKS+=fclose.3 fcloseall.3
+MLINKS+=ferror.3 ferror_unlocked.3 \
+ ferror.3 clearerr.3 ferror.3 clearerr_unlocked.3 \
+ ferror.3 feof.3 ferror.3 feof_unlocked.3 \
+ ferror.3 fileno.3 ferror.3 fileno_unlocked.3
+MLINKS+=fflush.3 fpurge.3
+MLINKS+=fgets.3 gets.3
+MLINKS+=flockfile.3 ftrylockfile.3 flockfile.3 funlockfile.3
+MLINKS+=fopen.3 fdopen.3 fopen.3 freopen.3
+MLINKS+=fputs.3 puts.3
+MLINKS+=fread.3 fwrite.3
+MLINKS+=fseek.3 fgetpos.3 fseek.3 fseeko.3 fseek.3 fsetpos.3 fseek.3 ftell.3 \
+ fseek.3 ftello.3 fseek.3 rewind.3
+MLINKS+=funopen.3 fropen.3 funopen.3 fwopen.3
+MLINKS+=getc.3 fgetc.3 getc.3 getc_unlocked.3 getc.3 getchar.3 \
+ getc.3 getchar_unlocked.3 getc.3 getw.3
+MLINKS+=getline.3 getdelim.3
+MLINKS+=getwc.3 fgetwc.3 getwc.3 getwchar.3
+MLINKS+=mktemp.3 mkdtemp.3 mktemp.3 mkstemp.3 mktemp.3 mkstemps.3
+MLINKS+=printf.3 asprintf.3 printf.3 dprintf.3 printf.3 fprintf.3 \
+ printf.3 snprintf.3 printf.3 sprintf.3 \
+ printf.3 vasprintf.3 printf.3 vdprintf.3 \
+ printf.3 vfprintf.3 printf.3 vprintf.3 printf.3 vsnprintf.3 \
+ printf.3 vsprintf.3
+MLINKS+=putc.3 fputc.3 putc.3 putc_unlocked.3 putc.3 putchar.3 \
+ putc.3 putchar_unlocked.3 putc.3 putw.3
+MLINKS+=putwc.3 fputwc.3 putwc.3 putwchar.3
+MLINKS+=scanf.3 fscanf.3 scanf.3 sscanf.3 scanf.3 vfscanf.3 scanf.3 vscanf.3 \
+ scanf.3 vsscanf.3
+MLINKS+=setbuf.3 setbuffer.3 setbuf.3 setlinebuf.3 setbuf.3 setvbuf.3
+MLINKS+=tmpnam.3 tempnam.3 tmpnam.3 tmpfile.3
+MLINKS+=wprintf.3 fwprintf.3 wprintf.3 swprintf.3 \
+ wprintf.3 vwprintf.3 wprintf.3 vfwprintf.3 wprintf.3 vswprintf.3
+MLINKS+=wscanf.3 fwscanf.3 wscanf.3 swscanf.3 wscanf.3 vwscanf.3 \
+ wscanf.3 vswscanf.3 wscanf.3 vfwscanf.3
diff --git a/lib/libc/stdio/Symbol.map b/lib/libc/stdio/Symbol.map
new file mode 100644
index 0000000..cafb0c6
--- /dev/null
+++ b/lib/libc/stdio/Symbol.map
@@ -0,0 +1,198 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ flockfile;
+ ftrylockfile;
+ funlockfile;
+ asprintf;
+ clearerr;
+ fclose;
+ fcloseall;
+ fdopen;
+ feof;
+ ferror;
+ fflush;
+ fgetc;
+ fgetln;
+ fgetpos;
+ fgets;
+ fgetwc;
+ fgetwln;
+ fgetws;
+ fileno;
+ __sF;
+ __stdinp;
+ __stdoutp;
+ __stderrp;
+ f_prealloc; /* deprecated??? */
+ fopen;
+ fprintf;
+ fpurge;
+ fputc;
+ fputs;
+ fputwc;
+ fputws;
+ fread;
+ freopen;
+ fscanf;
+ fseek;
+ fseeko;
+ fsetpos;
+ ftell;
+ ftello;
+ funopen;
+ fwide;
+ fwprintf;
+ fwrite;
+ fwscanf;
+ getc;
+ getchar;
+ gets;
+ getw;
+ getwc;
+ getwchar;
+ mkstemps;
+ mkstemp;
+ mkdtemp;
+ mktemp;
+ perror;
+ printf;
+ putc;
+ putchar;
+ puts;
+ putw;
+ putwc;
+ putwchar;
+ remove;
+ rewind;
+ __srget;
+ scanf;
+ setbuf;
+ setbuffer;
+ setlinebuf;
+ setvbuf;
+ snprintf;
+ sprintf;
+ sscanf;
+ swprintf;
+ swscanf;
+ tempnam;
+ tmpfile;
+ tmpnam;
+ ungetc;
+ ungetwc;
+ getchar_unlocked;
+ getc_unlocked;
+ putchar_unlocked;
+ putc_unlocked;
+ feof_unlocked;
+ ferror_unlocked;
+ clearerr_unlocked;
+ fileno_unlocked;
+ vasprintf;
+ vfprintf;
+ vfscanf;
+ vfwprintf;
+ vfwscanf;
+ vprintf;
+ vscanf;
+ vsnprintf;
+ vsprintf;
+ vsscanf;
+ vswprintf;
+ vswscanf;
+ vwprintf;
+ vwscanf;
+ __swbuf;
+ wprintf;
+ wscanf;
+};
+
+FBSD_1.1 {
+ dprintf;
+ getdelim;
+ getline;
+ vdprintf;
+};
+
+FBSD_1.3 {
+ asprintf_l;
+ fprintf_l;
+ fwprintf_l;
+ printf_l;
+ snprintf_l;
+ sprintf_l;
+ swprintf_l;
+ vasprintf_l;
+ vfprintf_l;
+ vfwprintf_l;
+ vprintf_l;
+ vsnprintf_l;
+ vsprintf_l;
+ vswprintf_l;
+ vwprintf_l;
+ wprintf_l;
+ fgetwc_l;
+ fputwc_l;
+ ungetwc_l;
+ vfwscanf_l;
+ vswscanf_l;
+ fscanf_l;
+ fwscanf_l;
+ scanf_l;
+ sscanf_l;
+ swscanf_l;
+ vfscanf_l;
+ vscanf_l;
+ vsscanf_l;
+ vwscanf_l;
+ wscanf_l;
+ fgetws_l;
+ fputws_l;
+ getwc_l;
+ getwchar_l;
+ putwc_l;
+ putwchar_l;
+};
+
+FBSDprivate_1.0 {
+ _flockfile;
+ _flockfile_debug_stub;
+ _flockfile_debug;
+ _ftrylockfile;
+ _funlockfile;
+ __vfscanf;
+
+ /*
+ * xprintf support
+ */
+ __use_xprintf;
+ __lowercase_hex;
+ __uppercase_hex;
+ __printf_flush;
+ __printf_puts;
+ __printf_pad;
+ __printf_out;
+ __xvprintf;
+ register_printf_function;
+ register_printf_render;
+ register_printf_render_std;
+ __printf_arginfo_float;
+ __printf_render_float;
+ __printf_arginfo_hexdump;
+ __printf_render_hexdump;
+ __printf_arginfo_int;
+ __printf_render_int;
+ __printf_arginfo_ptr;
+ __printf_render_ptr;
+ __printf_arginfo_str;
+ __printf_render_str;
+ __printf_arginfo_chr;
+ __printf_render_chr;
+ __printf_arginfo_time;
+ __printf_render_time;
+ __printf_arginfo_vis;
+ __printf_render_vis;
+};
diff --git a/lib/libc/stdio/_flock_stub.c b/lib/libc/stdio/_flock_stub.c
new file mode 100644
index 0000000..0b61315
--- /dev/null
+++ b/lib/libc/stdio/_flock_stub.c
@@ -0,0 +1,136 @@
+/*
+ * Copyright (c) 1998 John Birrell <jb@cimlogic.com.au>.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of any co-contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JOHN BIRRELL AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * POSIX stdio FILE locking functions. These assume that the locking
+ * is only required at FILE structure level, not at file descriptor
+ * level too.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include "un-namespace.h"
+
+#include "local.h"
+
+
+/*
+ * Weak symbols for externally visible functions in this file:
+ */
+__weak_reference(_flockfile, flockfile);
+__weak_reference(_flockfile_debug_stub, _flockfile_debug);
+__weak_reference(_ftrylockfile, ftrylockfile);
+__weak_reference(_funlockfile, funlockfile);
+
+void
+_flockfile(FILE *fp)
+{
+ pthread_t curthread = _pthread_self();
+
+ if (fp->_fl_owner == curthread)
+ fp->_fl_count++;
+ else {
+ /*
+ * Make sure this mutex is treated as a private
+ * internal mutex:
+ */
+ _pthread_mutex_lock(&fp->_fl_mutex);
+ fp->_fl_owner = curthread;
+ fp->_fl_count = 1;
+ }
+}
+
+/*
+ * This can be overriden by the threads library if it is linked in.
+ */
+void
+_flockfile_debug_stub(FILE *fp, char *fname, int lineno)
+{
+ _flockfile(fp);
+}
+
+int
+_ftrylockfile(FILE *fp)
+{
+ pthread_t curthread = _pthread_self();
+ int ret = 0;
+
+ if (fp->_fl_owner == curthread)
+ fp->_fl_count++;
+ /*
+ * Make sure this mutex is treated as a private
+ * internal mutex:
+ */
+ else if (_pthread_mutex_trylock(&fp->_fl_mutex) == 0) {
+ fp->_fl_owner = curthread;
+ fp->_fl_count = 1;
+ }
+ else
+ ret = -1;
+ return (ret);
+}
+
+void
+_funlockfile(FILE *fp)
+{
+ pthread_t curthread = _pthread_self();
+
+ /*
+ * Check if this file is owned by the current thread:
+ */
+ if (fp->_fl_owner == curthread) {
+ /*
+ * Check if this thread has locked the FILE
+ * more than once:
+ */
+ if (fp->_fl_count > 1)
+ /*
+ * Decrement the count of the number of
+ * times the running thread has locked this
+ * file:
+ */
+ fp->_fl_count--;
+ else {
+ /*
+ * The running thread will release the
+ * lock now:
+ */
+ fp->_fl_count = 0;
+ fp->_fl_owner = NULL;
+ _pthread_mutex_unlock(&fp->_fl_mutex);
+ }
+ }
+}
diff --git a/lib/libc/stdio/asprintf.c b/lib/libc/stdio/asprintf.c
new file mode 100644
index 0000000..cd475cd
--- /dev/null
+++ b/lib/libc/stdio/asprintf.c
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <xlocale.h>
+
+int
+asprintf(char ** __restrict s, char const * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vasprintf(s, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
+int
+asprintf_l(char ** __restrict s, locale_t locale, char const * __restrict fmt,
+ ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vasprintf_l(s, locale, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
diff --git a/lib/libc/stdio/clrerr.c b/lib/libc/stdio/clrerr.c
new file mode 100644
index 0000000..1b318e6
--- /dev/null
+++ b/lib/libc/stdio/clrerr.c
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)clrerr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+#undef clearerr
+#undef clearerr_unlocked
+
+void
+clearerr(fp)
+ FILE *fp;
+{
+ FLOCKFILE(fp);
+ __sclearerr(fp);
+ FUNLOCKFILE(fp);
+}
+
+void
+clearerr_unlocked(FILE *fp)
+{
+
+ __sclearerr(fp);
+}
diff --git a/lib/libc/stdio/dprintf.c b/lib/libc/stdio/dprintf.c
new file mode 100644
index 0000000..7f883dd
--- /dev/null
+++ b/lib/libc/stdio/dprintf.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define _WITH_DPRINTF
+#include "namespace.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include "un-namespace.h"
+
+int
+dprintf(int fd, const char * __restrict fmt, ...)
+{
+ va_list ap;
+ int ret;
+
+ va_start(ap, fmt);
+ ret = vdprintf(fd, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
diff --git a/lib/libc/stdio/fclose.3 b/lib/libc/stdio/fclose.3
new file mode 100644
index 0000000..883aa10
--- /dev/null
+++ b/lib/libc/stdio/fclose.3
@@ -0,0 +1,111 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fclose.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd April 22, 2006
+.Dt FCLOSE 3
+.Os
+.Sh NAME
+.Nm fclose ,
+.Nm fcloseall
+.Nd close a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft int
+.Fn fclose "FILE *stream"
+.Ft void
+.Fn fcloseall void
+.Sh DESCRIPTION
+The
+.Fn fclose
+function
+dissociates the named
+.Fa stream
+from its underlying file or set of functions.
+If the stream was being used for output, any buffered data is written
+first, using
+.Xr fflush 3 .
+.Pp
+The
+.Fn fcloseall
+function calls
+.Fn fclose
+on all open streams.
+.Sh RETURN VALUES
+Upon successful completion 0 is returned.
+Otherwise,
+.Dv EOF
+is returned and the global variable
+.Va errno
+is set to indicate the error.
+In either case no further access to the stream is possible.
+.Sh ERRORS
+The
+.Fn fclose
+function
+may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr close 2
+or
+.Xr fflush 3 .
+.Sh NOTES
+The
+.Fn fclose
+function
+does not handle NULL arguments; they will result in a segmentation
+violation.
+This is intentional - it makes it easier to make sure programs written
+under
+.Fx
+are bug free.
+This behaviour is an implementation detail, and programs should not
+rely upon it.
+.Sh SEE ALSO
+.Xr close 2 ,
+.Xr fflush 3 ,
+.Xr fopen 3 ,
+.Xr setbuf 3
+.Sh STANDARDS
+The
+.Fn fclose
+function
+conforms to
+.St -isoC .
+.Pp
+The
+.Fn fcloseall
+function first appeared in
+.Fx 7.0 .
diff --git a/lib/libc/stdio/fclose.c b/lib/libc/stdio/fclose.c
new file mode 100644
index 0000000..3957b6a
--- /dev/null
+++ b/lib/libc/stdio/fclose.c
@@ -0,0 +1,85 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fclose.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+#include <spinlock.h>
+#include "libc_private.h"
+#include "local.h"
+
+int
+fclose(FILE *fp)
+{
+ int r;
+
+ if (fp->_flags == 0) { /* not open! */
+ errno = EBADF;
+ return (EOF);
+ }
+ FLOCKFILE(fp);
+ r = fp->_flags & __SWR ? __sflush(fp) : 0;
+ if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0)
+ r = EOF;
+ if (fp->_flags & __SMBF)
+ free((char *)fp->_bf._base);
+ if (HASUB(fp))
+ FREEUB(fp);
+ if (HASLB(fp))
+ FREELB(fp);
+ fp->_file = -1;
+ fp->_r = fp->_w = 0; /* Mess up if reaccessed. */
+
+ /*
+ * Lock the spinlock used to protect __sglue list walk in
+ * __sfp(). The __sfp() uses fp->_flags == 0 test as an
+ * indication of the unused FILE.
+ *
+ * Taking the lock prevents possible compiler or processor
+ * reordering of the writes performed before the final _flags
+ * cleanup, making sure that we are done with the FILE before
+ * it is considered available.
+ */
+ STDIO_THREAD_LOCK();
+ fp->_flags = 0; /* Release this FILE for reuse. */
+ STDIO_THREAD_UNLOCK();
+ FUNLOCKFILE(fp);
+ return (r);
+}
diff --git a/lib/libc/stdio/fcloseall.c b/lib/libc/stdio/fcloseall.c
new file mode 100644
index 0000000..8ee9a62
--- /dev/null
+++ b/lib/libc/stdio/fcloseall.c
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (C) 2006 Daniel M. Eischen. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include "local.h"
+
+__weak_reference(__fcloseall, fcloseall);
+
+void
+__fcloseall(void)
+{
+
+ (void)_fwalk(fclose);
+}
diff --git a/lib/libc/stdio/fdopen.c b/lib/libc/stdio/fdopen.c
new file mode 100644
index 0000000..26e2cd7
--- /dev/null
+++ b/lib/libc/stdio/fdopen.c
@@ -0,0 +1,98 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fdopen.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <limits.h>
+#include "un-namespace.h"
+#include "local.h"
+
+FILE *
+fdopen(fd, mode)
+ int fd;
+ const char *mode;
+{
+ FILE *fp;
+ int flags, oflags, fdflags, tmp;
+
+ /*
+ * File descriptors are a full int, but _file is only a short.
+ * If we get a valid file descriptor that is greater than
+ * SHRT_MAX, then the fd will get sign-extended into an
+ * invalid file descriptor. Handle this case by failing the
+ * open.
+ */
+ if (fd > SHRT_MAX) {
+ errno = EMFILE;
+ return (NULL);
+ }
+
+ if ((flags = __sflags(mode, &oflags)) == 0)
+ return (NULL);
+
+ /* Make sure the mode the user wants is a subset of the actual mode. */
+ if ((fdflags = _fcntl(fd, F_GETFL, 0)) < 0)
+ return (NULL);
+ tmp = fdflags & O_ACCMODE;
+ if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ if ((fp = __sfp()) == NULL)
+ return (NULL);
+ fp->_flags = flags;
+ /*
+ * If opened for appending, but underlying descriptor does not have
+ * O_APPEND bit set, assert __SAPP so that __swrite() caller
+ * will _sseek() to the end before write.
+ */
+ if ((oflags & O_APPEND) && !(fdflags & O_APPEND))
+ fp->_flags |= __SAPP;
+ fp->_file = fd;
+ fp->_cookie = fp;
+ fp->_read = __sread;
+ fp->_write = __swrite;
+ fp->_seek = __sseek;
+ fp->_close = __sclose;
+ return (fp);
+}
diff --git a/lib/libc/stdio/feof.c b/lib/libc/stdio/feof.c
new file mode 100644
index 0000000..502f1e5
--- /dev/null
+++ b/lib/libc/stdio/feof.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)feof.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+#undef feof
+#undef feof_unlocked
+
+int
+feof(FILE *fp)
+{
+ int ret;
+
+ FLOCKFILE(fp);
+ ret= __sfeof(fp);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
+
+int
+feof_unlocked(FILE *fp)
+{
+
+ return (__sfeof(fp));
+}
diff --git a/lib/libc/stdio/ferror.3 b/lib/libc/stdio/ferror.3
new file mode 100644
index 0000000..043b688
--- /dev/null
+++ b/lib/libc/stdio/ferror.3
@@ -0,0 +1,131 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)ferror.3 8.2 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd January 28, 2009
+.Dt FERROR 3
+.Os
+.Sh NAME
+.Nm clearerr ,
+.Nm clearerr_unlocked ,
+.Nm feof ,
+.Nm feof_unlocked ,
+.Nm ferror ,
+.Nm ferror_unlocked ,
+.Nm fileno ,
+.Nm fileno_unlocked
+.Nd check and reset stream status
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft void
+.Fn clearerr "FILE *stream"
+.Ft void
+.Fn clearerr_unlocked "FILE *stream"
+.Ft int
+.Fn feof "FILE *stream"
+.Ft int
+.Fn feof_unlocked "FILE *stream"
+.Ft int
+.Fn ferror "FILE *stream"
+.Ft int
+.Fn ferror_unlocked "FILE *stream"
+.Ft int
+.Fn fileno "FILE *stream"
+.Ft int
+.Fn fileno_unlocked "FILE *stream"
+.Sh DESCRIPTION
+The function
+.Fn clearerr
+clears the end-of-file and error indicators for the stream pointed
+to by
+.Fa stream .
+.Pp
+The function
+.Fn feof
+tests the end-of-file indicator for the stream pointed to by
+.Fa stream ,
+returning non-zero if it is set.
+The end-of-file indicator may be cleared by explicitly calling
+.Fn clearerr ,
+or as a side-effect of other operations, e.g.\&
+.Fn fseek .
+.Pp
+The function
+.Fn ferror
+tests the error indicator for the stream pointed to by
+.Fa stream ,
+returning non-zero if it is set.
+.Pp
+The function
+.Fn fileno
+examines the argument
+.Fa stream
+and returns its integer descriptor.
+.Pp
+The
+.Fn clearerr_unlocked ,
+.Fn feof_unlocked ,
+.Fn ferror_unlocked ,
+and
+.Fn fileno_unlocked
+functions are equivalent to
+.Fn clearerr ,
+.Fn feof ,
+.Fn ferror ,
+and
+.Fn fileno
+respectively, except that the caller is responsible for locking the stream
+with
+.Xr flockfile 3
+before calling them.
+These functions may be used to avoid the overhead of locking the stream
+and to prevent races when multiple threads are operating on the same stream.
+.Sh ERRORS
+These functions should not fail and do not set the external
+variable
+.Va errno .
+.Sh SEE ALSO
+.Xr open 2 ,
+.Xr fdopen 3 ,
+.Xr flockfile 3 ,
+.Xr stdio 3
+.Sh STANDARDS
+The functions
+.Fn clearerr ,
+.Fn feof ,
+and
+.Fn ferror
+conform to
+.St -isoC .
diff --git a/lib/libc/stdio/ferror.c b/lib/libc/stdio/ferror.c
new file mode 100644
index 0000000..d155ff0
--- /dev/null
+++ b/lib/libc/stdio/ferror.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ferror.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+#undef ferror
+#undef ferror_unlocked
+
+int
+ferror(FILE *fp)
+{
+ int ret;
+
+ FLOCKFILE(fp);
+ ret = __sferror(fp);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
+
+int
+ferror_unlocked(FILE *fp)
+{
+
+ return (__sferror(fp));
+}
diff --git a/lib/libc/stdio/fflush.3 b/lib/libc/stdio/fflush.3
new file mode 100644
index 0000000..1c04103
--- /dev/null
+++ b/lib/libc/stdio/fflush.3
@@ -0,0 +1,111 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fflush.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt FFLUSH 3
+.Os
+.Sh NAME
+.Nm fflush ,
+.Nm fpurge
+.Nd flush a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft int
+.Fn fflush "FILE *stream"
+.Ft int
+.Fn fpurge "FILE *stream"
+.Sh DESCRIPTION
+The function
+.Fn fflush
+forces a write of all buffered data for the given output or update
+.Fa stream
+via the stream's underlying write function.
+The open status of the stream is unaffected.
+.Pp
+If the
+.Fa stream
+argument is
+.Dv NULL ,
+.Fn fflush
+flushes
+.Em all
+open output streams.
+.Pp
+The function
+.Fn fpurge
+erases any input or output buffered in the given
+.Fa stream .
+For output streams this discards any unwritten output.
+For input streams this discards any input read from the underlying object
+but not yet obtained via
+.Xr getc 3 ;
+this includes any text pushed back via
+.Xr ungetc 3 .
+.Sh RETURN VALUES
+Upon successful completion 0 is returned.
+Otherwise,
+.Dv EOF
+is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa stream
+argument
+is not an open stream, or, in the case of
+.Fn fflush ,
+not a stream open for writing.
+.El
+.Pp
+The function
+.Fn fflush
+may also fail and set
+.Va errno
+for any of the errors specified for the routine
+.Xr write 2 .
+.Sh SEE ALSO
+.Xr write 2 ,
+.Xr fclose 3 ,
+.Xr fopen 3 ,
+.Xr setbuf 3
+.Sh STANDARDS
+The
+.Fn fflush
+function
+conforms to
+.St -isoC .
diff --git a/lib/libc/stdio/fflush.c b/lib/libc/stdio/fflush.c
new file mode 100644
index 0000000..c0237cf
--- /dev/null
+++ b/lib/libc/stdio/fflush.c
@@ -0,0 +1,141 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fflush.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <stdio.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+static int sflush_locked(FILE *);
+
+/*
+ * Flush a single file, or (if fp is NULL) all files.
+ * MT-safe version
+ */
+int
+fflush(FILE *fp)
+{
+ int retval;
+
+ if (fp == NULL)
+ return (_fwalk(sflush_locked));
+ FLOCKFILE(fp);
+
+ /*
+ * There is disagreement about the correct behaviour of fflush()
+ * when passed a file which is not open for reading. According to
+ * the ISO C standard, the behaviour is undefined.
+ * Under linux, such an fflush returns success and has no effect;
+ * under Windows, such an fflush is documented as behaving instead
+ * as fpurge().
+ * Given that applications may be written with the expectation of
+ * either of these two behaviours, the only safe (non-astonishing)
+ * option is to return EBADF and ask that applications be fixed.
+ */
+ if ((fp->_flags & (__SWR | __SRW)) == 0) {
+ errno = EBADF;
+ retval = EOF;
+ } else
+ retval = __sflush(fp);
+ FUNLOCKFILE(fp);
+ return (retval);
+}
+
+/*
+ * Flush a single file, or (if fp is NULL) all files.
+ * Non-MT-safe version
+ */
+int
+__fflush(FILE *fp)
+{
+ int retval;
+
+ if (fp == NULL)
+ return (_fwalk(sflush_locked));
+ if ((fp->_flags & (__SWR | __SRW)) == 0) {
+ errno = EBADF;
+ retval = EOF;
+ } else
+ retval = __sflush(fp);
+ return (retval);
+}
+
+int
+__sflush(FILE *fp)
+{
+ unsigned char *p;
+ int n, t;
+
+ t = fp->_flags;
+ if ((t & __SWR) == 0)
+ return (0);
+
+ if ((p = fp->_bf._base) == NULL)
+ return (0);
+
+ n = fp->_p - p; /* write this much */
+
+ /*
+ * Set these immediately to avoid problems with longjmp and to allow
+ * exchange buffering (via setvbuf) in user write function.
+ */
+ fp->_p = p;
+ fp->_w = t & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
+
+ for (; n > 0; n -= t, p += t) {
+ t = _swrite(fp, (char *)p, n);
+ if (t <= 0) {
+ fp->_flags |= __SERR;
+ return (EOF);
+ }
+ }
+ return (0);
+}
+
+static int
+sflush_locked(FILE *fp)
+{
+ int ret;
+
+ FLOCKFILE(fp);
+ ret = __sflush(fp);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
diff --git a/lib/libc/stdio/fgetc.c b/lib/libc/stdio/fgetc.c
new file mode 100644
index 0000000..8024df1
--- /dev/null
+++ b/lib/libc/stdio/fgetc.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fgetc.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+int
+fgetc(fp)
+ FILE *fp;
+{
+ int retval;
+ FLOCKFILE(fp);
+ /* Orientation set by __sgetc() when buffer is empty. */
+ /* ORIENT(fp, -1); */
+ retval = __sgetc(fp);
+ FUNLOCKFILE(fp);
+ return (retval);
+}
diff --git a/lib/libc/stdio/fgetln.3 b/lib/libc/stdio/fgetln.3
new file mode 100644
index 0000000..4b83664
--- /dev/null
+++ b/lib/libc/stdio/fgetln.3
@@ -0,0 +1,125 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fgetln.3 8.3 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd April 19, 1994
+.Dt FGETLN 3
+.Os
+.Sh NAME
+.Nm fgetln
+.Nd get a line from a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft char *
+.Fn fgetln "FILE *stream" "size_t *len"
+.Sh DESCRIPTION
+The
+.Fn fgetln
+function
+returns a pointer to the next line from the stream referenced by
+.Fa stream .
+This line is
+.Em not
+a C string as it does not end with a terminating
+.Dv NUL
+character.
+The length of the line, including the final newline,
+is stored in the memory location to which
+.Fa len
+points.
+(Note, however, that if the line is the last
+in a file that does not end in a newline,
+the returned text will not contain a newline.)
+.Sh RETURN VALUES
+Upon successful completion a pointer is returned;
+this pointer becomes invalid after the next
+.Tn I/O
+operation on
+.Fa stream
+(whether successful or not)
+or as soon as the stream is closed.
+Otherwise,
+.Dv NULL
+is returned.
+The
+.Fn fgetln
+function
+does not distinguish between end-of-file and error; the routines
+.Xr feof 3
+and
+.Xr ferror 3
+must be used
+to determine which occurred.
+If an error occurs, the global variable
+.Va errno
+is set to indicate the error.
+The end-of-file condition is remembered, even on a terminal, and all
+subsequent attempts to read will return
+.Dv NULL
+until the condition is
+cleared with
+.Xr clearerr 3 .
+.Pp
+The text to which the returned pointer points may be modified,
+provided that no changes are made beyond the returned size.
+These changes are lost as soon as the pointer becomes invalid.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBADF
+The argument
+.Fa stream
+is not a stream open for reading.
+.El
+.Pp
+The
+.Fn fgetln
+function
+may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr fflush 3 ,
+.Xr malloc 3 ,
+.Xr read 2 ,
+.Xr stat 2 ,
+or
+.Xr realloc 3 .
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr fgets 3 ,
+.Xr fgetwln 3 ,
+.Xr fopen 3 ,
+.Xr getline 3 ,
+.Xr putc 3
+.Sh HISTORY
+The
+.Fn fgetln
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/stdio/fgetln.c b/lib/libc/stdio/fgetln.c
new file mode 100644
index 0000000..7cb2854
--- /dev/null
+++ b/lib/libc/stdio/fgetln.c
@@ -0,0 +1,164 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fgetln.c 8.2 (Berkeley) 1/2/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+/*
+ * Expand the line buffer. Return -1 on error.
+#ifdef notdef
+ * The `new size' does not account for a terminating '\0',
+ * so we add 1 here.
+#endif
+ */
+int
+__slbexpand(FILE *fp, size_t newsize)
+{
+ void *p;
+
+#ifdef notdef
+ ++newsize;
+#endif
+ if (fp->_lb._size >= newsize)
+ return (0);
+ if ((p = realloc(fp->_lb._base, newsize)) == NULL)
+ return (-1);
+ fp->_lb._base = p;
+ fp->_lb._size = newsize;
+ return (0);
+}
+
+/*
+ * Get an input line. The returned pointer often (but not always)
+ * points into a stdio buffer. Fgetln does not alter the text of
+ * the returned line (which is thus not a C string because it will
+ * not necessarily end with '\0'), but does allow callers to modify
+ * it if they wish. Thus, we set __SMOD in case the caller does.
+ */
+char *
+fgetln(FILE *fp, size_t *lenp)
+{
+ unsigned char *p;
+ size_t len;
+ size_t off;
+
+ FLOCKFILE(fp);
+ ORIENT(fp, -1);
+ /* make sure there is input */
+ if (fp->_r <= 0 && __srefill(fp)) {
+ *lenp = 0;
+ FUNLOCKFILE(fp);
+ return (NULL);
+ }
+
+ /* look for a newline in the input */
+ if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) != NULL) {
+ char *ret;
+
+ /*
+ * Found one. Flag buffer as modified to keep fseek from
+ * `optimising' a backward seek, in case the user stomps on
+ * the text.
+ */
+ p++; /* advance over it */
+ ret = (char *)fp->_p;
+ *lenp = len = p - fp->_p;
+ fp->_flags |= __SMOD;
+ fp->_r -= len;
+ fp->_p = p;
+ FUNLOCKFILE(fp);
+ return (ret);
+ }
+
+ /*
+ * We have to copy the current buffered data to the line buffer.
+ * As a bonus, though, we can leave off the __SMOD.
+ *
+ * OPTIMISTIC is length that we (optimistically) expect will
+ * accomodate the `rest' of the string, on each trip through the
+ * loop below.
+ */
+#define OPTIMISTIC 80
+
+ for (len = fp->_r, off = 0;; len += fp->_r) {
+ size_t diff;
+
+ /*
+ * Make sure there is room for more bytes. Copy data from
+ * file buffer to line buffer, refill file and look for
+ * newline. The loop stops only when we find a newline.
+ */
+ if (__slbexpand(fp, len + OPTIMISTIC))
+ goto error;
+ (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
+ len - off);
+ off = len;
+ if (__srefill(fp))
+ break; /* EOF or error: return partial line */
+ if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) == NULL)
+ continue;
+
+ /* got it: finish up the line (like code above) */
+ p++;
+ diff = p - fp->_p;
+ len += diff;
+ if (__slbexpand(fp, len))
+ goto error;
+ (void)memcpy((void *)(fp->_lb._base + off), (void *)fp->_p,
+ diff);
+ fp->_r -= diff;
+ fp->_p = p;
+ break;
+ }
+ *lenp = len;
+#ifdef notdef
+ fp->_lb._base[len] = 0;
+#endif
+ FUNLOCKFILE(fp);
+ return ((char *)fp->_lb._base);
+
+error:
+ *lenp = 0; /* ??? */
+ FUNLOCKFILE(fp);
+ return (NULL); /* ??? */
+}
diff --git a/lib/libc/stdio/fgetpos.c b/lib/libc/stdio/fgetpos.c
new file mode 100644
index 0000000..9053be8
--- /dev/null
+++ b/lib/libc/stdio/fgetpos.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fgetpos.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+
+int
+fgetpos(FILE * __restrict fp, fpos_t * __restrict pos)
+{
+ /*
+ * ftello is thread-safe; no need to lock fp.
+ */
+ if ((*pos = ftello(fp)) == (fpos_t)-1)
+ return (-1);
+ else
+ return (0);
+}
diff --git a/lib/libc/stdio/fgets.3 b/lib/libc/stdio/fgets.3
new file mode 100644
index 0000000..fba7353
--- /dev/null
+++ b/lib/libc/stdio/fgets.3
@@ -0,0 +1,158 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fgets.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt FGETS 3
+.Os
+.Sh NAME
+.Nm fgets ,
+.Nm gets
+.Nd get a line from a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft char *
+.Fn fgets "char * restrict str" "int size" "FILE * restrict stream"
+.Ft char *
+.Fn gets "char *str"
+.Sh DESCRIPTION
+The
+.Fn fgets
+function
+reads at most one less than the number of characters specified by
+.Fa size
+from the given
+.Fa stream
+and stores them in the string
+.Fa str .
+Reading stops when a newline character is found,
+at end-of-file or error.
+The newline, if any, is retained.
+If any characters are read and there is no error, a
+.Ql \e0
+character is appended to end the string.
+.Pp
+The
+.Fn gets
+function
+is equivalent to
+.Fn fgets
+with an infinite
+.Fa size
+and a
+.Fa stream
+of
+.Dv stdin ,
+except that the newline character (if any) is not stored in the string.
+It is the caller's responsibility to ensure that the input line,
+if any, is sufficiently short to fit in the string.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn fgets
+and
+.Fn gets
+return
+a pointer to the string.
+If end-of-file occurs before any characters are read,
+they return
+.Dv NULL
+and the buffer contents remain unchanged.
+If an error occurs,
+they return
+.Dv NULL
+and the buffer contents are indeterminate.
+The
+.Fn fgets
+and
+.Fn gets
+functions
+do not distinguish between end-of-file and error, and callers must use
+.Xr feof 3
+and
+.Xr ferror 3
+to determine which occurred.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBADF
+The given
+.Fa stream
+is not a readable stream.
+.El
+.Pp
+The function
+.Fn fgets
+may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr fflush 3 ,
+.Xr fstat 2 ,
+.Xr read 2 ,
+or
+.Xr malloc 3 .
+.Pp
+The function
+.Fn gets
+may also fail and set
+.Va errno
+for any of the errors specified for the routine
+.Xr getchar 3 .
+.Sh SEE ALSO
+.Xr feof 3 ,
+.Xr ferror 3 ,
+.Xr fgetln 3 ,
+.Xr fgetws 3 ,
+.Xr getline 3
+.Sh STANDARDS
+The functions
+.Fn fgets
+and
+.Fn gets
+conform to
+.St -isoC-99 .
+.Sh SECURITY CONSIDERATIONS
+The
+.Fn gets
+function cannot be used securely.
+Because of its lack of bounds checking,
+and the inability for the calling program
+to reliably determine the length of the next incoming line,
+the use of this function enables malicious users
+to arbitrarily change a running program's functionality through
+a buffer overflow attack.
+It is strongly suggested that the
+.Fn fgets
+function be used in all cases.
+(See
+the FSA.)
diff --git a/lib/libc/stdio/fgets.c b/lib/libc/stdio/fgets.c
new file mode 100644
index 0000000..a0cc724
--- /dev/null
+++ b/lib/libc/stdio/fgets.c
@@ -0,0 +1,112 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fgets.c 8.2 (Berkeley) 12/22/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "local.h"
+#include "libc_private.h"
+
+/*
+ * Read at most n-1 characters from the given file.
+ * Stop when a newline has been read, or the count runs out.
+ * Return first argument, or NULL if no characters were read.
+ */
+char *
+fgets(buf, n, fp)
+ char *buf;
+ int n;
+ FILE *fp;
+{
+ size_t len;
+ char *s;
+ unsigned char *p, *t;
+
+ if (n <= 0) /* sanity check */
+ return (NULL);
+
+ FLOCKFILE(fp);
+ ORIENT(fp, -1);
+ s = buf;
+ n--; /* leave space for NUL */
+ while (n != 0) {
+ /*
+ * If the buffer is empty, refill it.
+ */
+ if ((len = fp->_r) <= 0) {
+ if (__srefill(fp)) {
+ /* EOF/error: stop with partial or no line */
+ if (s == buf) {
+ FUNLOCKFILE(fp);
+ return (NULL);
+ }
+ break;
+ }
+ len = fp->_r;
+ }
+ p = fp->_p;
+
+ /*
+ * Scan through at most n bytes of the current buffer,
+ * looking for '\n'. If found, copy up to and including
+ * newline, and stop. Otherwise, copy entire chunk
+ * and loop.
+ */
+ if (len > n)
+ len = n;
+ t = memchr((void *)p, '\n', len);
+ if (t != NULL) {
+ len = ++t - p;
+ fp->_r -= len;
+ fp->_p = t;
+ (void)memcpy((void *)s, (void *)p, len);
+ s[len] = 0;
+ FUNLOCKFILE(fp);
+ return (buf);
+ }
+ fp->_r -= len;
+ fp->_p += len;
+ (void)memcpy((void *)s, (void *)p, len);
+ s += len;
+ n -= len;
+ }
+ *s = 0;
+ FUNLOCKFILE(fp);
+ return (buf);
+}
diff --git a/lib/libc/stdio/fgetwc.c b/lib/libc/stdio/fgetwc.c
new file mode 100644
index 0000000..0e87753
--- /dev/null
+++ b/lib/libc/stdio/fgetwc.c
@@ -0,0 +1,109 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+#include "mblocal.h"
+#include "xlocale_private.h"
+
+/*
+ * MT-safe version.
+ */
+wint_t
+fgetwc_l(FILE *fp, locale_t locale)
+{
+ wint_t r;
+ FIX_LOCALE(locale);
+
+ FLOCKFILE(fp);
+ ORIENT(fp, 1);
+ r = __fgetwc(fp, locale);
+ FUNLOCKFILE(fp);
+
+ return (r);
+}
+wint_t
+fgetwc(FILE *fp)
+{
+ return fgetwc_l(fp, __get_locale());
+}
+
+/*
+ * Non-MT-safe version.
+ */
+wint_t
+__fgetwc(FILE *fp, locale_t locale)
+{
+ wchar_t wc;
+ size_t nconv;
+ struct xlocale_ctype *l = XLOCALE_CTYPE(locale);
+
+ if (fp->_r <= 0 && __srefill(fp))
+ return (WEOF);
+ if (MB_CUR_MAX == 1) {
+ /* Fast path for single-byte encodings. */
+ wc = *fp->_p++;
+ fp->_r--;
+ return (wc);
+ }
+ do {
+ nconv = l->__mbrtowc(&wc, fp->_p, fp->_r, &fp->_mbstate);
+ if (nconv == (size_t)-1)
+ break;
+ else if (nconv == (size_t)-2)
+ continue;
+ else if (nconv == 0) {
+ /*
+ * Assume that the only valid representation of
+ * the null wide character is a single null byte.
+ */
+ fp->_p++;
+ fp->_r--;
+ return (L'\0');
+ } else {
+ fp->_p += nconv;
+ fp->_r -= nconv;
+ return (wc);
+ }
+ } while (__srefill(fp) == 0);
+ fp->_flags |= __SERR;
+ errno = EILSEQ;
+ return (WEOF);
+}
diff --git a/lib/libc/stdio/fgetwln.3 b/lib/libc/stdio/fgetwln.3
new file mode 100644
index 0000000..b1594e2
--- /dev/null
+++ b/lib/libc/stdio/fgetwln.3
@@ -0,0 +1,116 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fgetln.3 8.3 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd July 16, 2004
+.Dt FGETWLN 3
+.Os
+.Sh NAME
+.Nm fgetwln
+.Nd get a line of wide characters from a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.In wchar.h
+.Ft wchar_t *
+.Fn fgetwln "FILE * restrict stream" "size_t * restrict len"
+.Sh DESCRIPTION
+The
+.Fn fgetwln
+function
+returns a pointer to the next line from the stream referenced by
+.Fa stream .
+This line is
+.Em not
+a standard wide character string as it does not end with a terminating
+null wide character.
+The length of the line, including the final newline,
+is stored in the memory location to which
+.Fa len
+points.
+(Note, however, that if the line is the last
+in a file that does not end in a newline,
+the returned text will not contain a newline.)
+.Sh RETURN VALUES
+Upon successful completion a pointer is returned;
+this pointer becomes invalid after the next
+.Tn I/O
+operation on
+.Fa stream
+(whether successful or not)
+or as soon as the stream is closed.
+Otherwise,
+.Dv NULL
+is returned.
+The
+.Fn fgetwln
+function
+does not distinguish between end-of-file and error; the routines
+.Xr feof 3
+and
+.Xr ferror 3
+must be used
+to determine which occurred.
+If an error occurs, the global variable
+.Va errno
+is set to indicate the error.
+The end-of-file condition is remembered, even on a terminal, and all
+subsequent attempts to read will return
+.Dv NULL
+until the condition is
+cleared with
+.Xr clearerr 3 .
+.Pp
+The text to which the returned pointer points may be modified,
+provided that no changes are made beyond the returned size.
+These changes are lost as soon as the pointer becomes invalid.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBADF
+The argument
+.Fa stream
+is not a stream open for reading.
+.El
+.Pp
+The
+.Fn fgetwln
+function
+may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr mbrtowc 3 ,
+.Xr realloc 3 ,
+or
+.Xr read 2 .
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr fgetln 3 ,
+.Xr fgetws 3 ,
+.Xr fopen 3
diff --git a/lib/libc/stdio/fgetwln.c b/lib/libc/stdio/fgetwln.c
new file mode 100644
index 0000000..6d9087b
--- /dev/null
+++ b/lib/libc/stdio/fgetwln.c
@@ -0,0 +1,79 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <wchar.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+#include "xlocale_private.h"
+
+wchar_t *
+fgetwln_l(FILE * __restrict fp, size_t *lenp, locale_t locale)
+{
+ wint_t wc;
+ size_t len;
+ FIX_LOCALE(locale);
+
+ FLOCKFILE(fp);
+ ORIENT(fp, 1);
+
+ len = 0;
+ while ((wc = __fgetwc(fp, locale)) != WEOF) {
+#define GROW 512
+ if (len * sizeof(wchar_t) >= fp->_lb._size &&
+ __slbexpand(fp, (len + GROW) * sizeof(wchar_t)))
+ goto error;
+ *((wchar_t *)fp->_lb._base + len++) = wc;
+ if (wc == L'\n')
+ break;
+ }
+ if (len == 0)
+ goto error;
+
+ FUNLOCKFILE(fp);
+ *lenp = len;
+ return ((wchar_t *)fp->_lb._base);
+
+error:
+ FUNLOCKFILE(fp);
+ *lenp = 0;
+ return (NULL);
+}
+wchar_t *
+fgetwln(FILE * __restrict fp, size_t *lenp)
+{
+ return fgetwln_l(fp, lenp, __get_locale());
+}
diff --git a/lib/libc/stdio/fgetws.3 b/lib/libc/stdio/fgetws.3
new file mode 100644
index 0000000..5397a10
--- /dev/null
+++ b/lib/libc/stdio/fgetws.3
@@ -0,0 +1,121 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fgets.3 8.1 (Berkeley) 6/4/93
+.\" FreeBSD: src/lib/libc/stdio/fgets.3,v 1.16 2002/05/31 05:01:17 archie Exp
+.\" $FreeBSD$
+.\"
+.Dd August 6, 2002
+.Dt FGETWS 3
+.Os
+.Sh NAME
+.Nm fgetws
+.Nd get a line of wide characters from a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.In wchar.h
+.Ft "wchar_t *"
+.Fn fgetws "wchar_t * restrict ws" "int n" "FILE * restrict fp"
+.Sh DESCRIPTION
+The
+.Fn fgetws
+function
+reads at most one less than the number of characters specified by
+.Fa n
+from the given
+.Fa fp
+and stores them in the wide character string
+.Fa ws .
+Reading stops when a newline character is found,
+at end-of-file or error.
+The newline, if any, is retained.
+If any characters are read and there is no error, a
+.Ql \e0
+character is appended to end the string.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn fgetws
+returns
+.Fa ws .
+If end-of-file occurs before any characters are read,
+.Fn fgetws
+returns
+.Dv NULL
+and the buffer contents remain unchanged.
+If an error occurs,
+.Fn fgetws
+returns
+.Dv NULL
+and the buffer contents are indeterminate.
+The
+.Fn fgetws
+function
+does not distinguish between end-of-file and error, and callers must use
+.Xr feof 3
+and
+.Xr ferror 3
+to determine which occurred.
+.Sh ERRORS
+The
+.Fn fgetws
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The given
+.Fa fp
+argument is not a readable stream.
+.It Bq Er EILSEQ
+The data obtained from the input stream does not form a valid
+multibyte character.
+.El
+.Pp
+The function
+.Fn fgetws
+may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr fflush 3 ,
+.Xr fstat 2 ,
+.Xr read 2 ,
+or
+.Xr malloc 3 .
+.Sh SEE ALSO
+.Xr feof 3 ,
+.Xr ferror 3 ,
+.Xr fgets 3
+.Sh STANDARDS
+The
+.Fn fgetws
+function
+conforms to
+.St -p1003.1-2001 .
diff --git a/lib/libc/stdio/fgetws.c b/lib/libc/stdio/fgetws.c
new file mode 100644
index 0000000..f7a63fe
--- /dev/null
+++ b/lib/libc/stdio/fgetws.c
@@ -0,0 +1,112 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <wchar.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+#include "mblocal.h"
+
+wchar_t *
+fgetws_l(wchar_t * __restrict ws, int n, FILE * __restrict fp, locale_t locale)
+{
+ wchar_t *wsp;
+ size_t nconv;
+ const char *src;
+ unsigned char *nl;
+ FIX_LOCALE(locale);
+ struct xlocale_ctype *l = XLOCALE_CTYPE(locale);
+
+ FLOCKFILE(fp);
+ ORIENT(fp, 1);
+
+ if (n <= 0) {
+ errno = EINVAL;
+ goto error;
+ }
+
+ if (fp->_r <= 0 && __srefill(fp))
+ /* EOF */
+ goto error;
+ wsp = ws;
+ do {
+ src = fp->_p;
+ nl = memchr(fp->_p, '\n', fp->_r);
+ nconv = l->__mbsnrtowcs(wsp, &src,
+ nl != NULL ? (nl - fp->_p + 1) : fp->_r,
+ n - 1, &fp->_mbstate);
+ if (nconv == (size_t)-1)
+ /* Conversion error */
+ goto error;
+ if (src == NULL) {
+ /*
+ * We hit a null byte. Increment the character count,
+ * since mbsnrtowcs()'s return value doesn't include
+ * the terminating null, then resume conversion
+ * after the null.
+ */
+ nconv++;
+ src = memchr(fp->_p, '\0', fp->_r);
+ src++;
+ }
+ fp->_r -= (unsigned char *)src - fp->_p;
+ fp->_p = (unsigned char *)src;
+ n -= nconv;
+ wsp += nconv;
+ } while (wsp[-1] != L'\n' && n > 1 && (fp->_r > 0 ||
+ __srefill(fp) == 0));
+ if (wsp == ws)
+ /* EOF */
+ goto error;
+ if (!l->__mbsinit(&fp->_mbstate))
+ /* Incomplete character */
+ goto error;
+ *wsp = L'\0';
+ FUNLOCKFILE(fp);
+
+ return (ws);
+
+error:
+ FUNLOCKFILE(fp);
+ return (NULL);
+}
+wchar_t *
+fgetws(wchar_t * __restrict ws, int n, FILE * __restrict fp)
+{
+ return fgetws_l(ws, n, fp, __get_locale());
+}
diff --git a/lib/libc/stdio/fileno.c b/lib/libc/stdio/fileno.c
new file mode 100644
index 0000000..1962bb7
--- /dev/null
+++ b/lib/libc/stdio/fileno.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fileno.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+#undef fileno
+#undef fileno_unlocked
+
+int
+fileno(FILE *fp)
+{
+ int fd;
+
+ FLOCKFILE(fp);
+ fd = __sfileno(fp);
+ FUNLOCKFILE(fp);
+
+ return (fd);
+}
+
+int
+fileno_unlocked(FILE *fp)
+{
+
+ return (__sfileno(fp));
+}
diff --git a/lib/libc/stdio/findfp.c b/lib/libc/stdio/findfp.c
new file mode 100644
index 0000000..6d0b673
--- /dev/null
+++ b/lib/libc/stdio/findfp.c
@@ -0,0 +1,215 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)findfp.c 8.2 (Berkeley) 1/4/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <machine/atomic.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <spinlock.h>
+
+#include "libc_private.h"
+#include "local.h"
+#include "glue.h"
+
+int __sdidinit;
+
+#define NDYNAMIC 10 /* add ten more whenever necessary */
+
+#define std(flags, file) { \
+ ._flags = (flags), \
+ ._file = (file), \
+ ._cookie = __sF + (file), \
+ ._close = __sclose, \
+ ._read = __sread, \
+ ._seek = __sseek, \
+ ._write = __swrite, \
+ ._fl_mutex = PTHREAD_MUTEX_INITIALIZER, \
+}
+ /* the usual - (stdin + stdout + stderr) */
+static FILE usual[FOPEN_MAX - 3];
+static struct glue uglue = { NULL, FOPEN_MAX - 3, usual };
+
+static FILE __sF[3] = {
+ std(__SRD, STDIN_FILENO),
+ std(__SWR, STDOUT_FILENO),
+ std(__SWR|__SNBF, STDERR_FILENO)
+};
+
+FILE *__stdinp = &__sF[0];
+FILE *__stdoutp = &__sF[1];
+FILE *__stderrp = &__sF[2];
+
+struct glue __sglue = { &uglue, 3, __sF };
+static struct glue *lastglue = &uglue;
+
+static struct glue * moreglue(int);
+
+spinlock_t __stdio_thread_lock = _SPINLOCK_INITIALIZER;
+
+#if NOT_YET
+#define SET_GLUE_PTR(ptr, val) atomic_set_rel_ptr(&(ptr), (uintptr_t)(val))
+#else
+#define SET_GLUE_PTR(ptr, val) ptr = val
+#endif
+
+static struct glue *
+moreglue(n)
+ int n;
+{
+ struct glue *g;
+ static FILE empty = { ._fl_mutex = PTHREAD_MUTEX_INITIALIZER };
+ FILE *p;
+
+ g = (struct glue *)malloc(sizeof(*g) + ALIGNBYTES + n * sizeof(FILE));
+ if (g == NULL)
+ return (NULL);
+ p = (FILE *)ALIGN(g + 1);
+ g->next = NULL;
+ g->niobs = n;
+ g->iobs = p;
+ while (--n >= 0)
+ *p++ = empty;
+ return (g);
+}
+
+/*
+ * Find a free FILE for fopen et al.
+ */
+FILE *
+__sfp()
+{
+ FILE *fp;
+ int n;
+ struct glue *g;
+
+ if (!__sdidinit)
+ __sinit();
+ /*
+ * The list must be locked because a FILE may be updated.
+ */
+ STDIO_THREAD_LOCK();
+ for (g = &__sglue; g != NULL; g = g->next) {
+ for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
+ if (fp->_flags == 0)
+ goto found;
+ }
+ STDIO_THREAD_UNLOCK(); /* don't hold lock while malloc()ing. */
+ if ((g = moreglue(NDYNAMIC)) == NULL)
+ return (NULL);
+ STDIO_THREAD_LOCK(); /* reacquire the lock */
+ SET_GLUE_PTR(lastglue->next, g); /* atomically append glue to list */
+ lastglue = g; /* not atomic; only accessed when locked */
+ fp = g->iobs;
+found:
+ fp->_flags = 1; /* reserve this slot; caller sets real flags */
+ STDIO_THREAD_UNLOCK();
+ fp->_p = NULL; /* no current pointer */
+ fp->_w = 0; /* nothing to read or write */
+ fp->_r = 0;
+ fp->_bf._base = NULL; /* no buffer */
+ fp->_bf._size = 0;
+ fp->_lbfsize = 0; /* not line buffered */
+ fp->_file = -1; /* no file */
+/* fp->_cookie = <any>; */ /* caller sets cookie, _read/_write etc */
+ fp->_ub._base = NULL; /* no ungetc buffer */
+ fp->_ub._size = 0;
+ fp->_lb._base = NULL; /* no line buffer */
+ fp->_lb._size = 0;
+/* fp->_fl_mutex = NULL; */ /* once set always set (reused) */
+ fp->_orientation = 0;
+ memset(&fp->_mbstate, 0, sizeof(mbstate_t));
+ return (fp);
+}
+
+/*
+ * XXX. Force immediate allocation of internal memory. Not used by stdio,
+ * but documented historically for certain applications. Bad applications.
+ */
+__warn_references(f_prealloc,
+ "warning: this program uses f_prealloc(), which is not recommended.");
+
+void
+f_prealloc(void)
+{
+ struct glue *g;
+ int n;
+
+ n = getdtablesize() - FOPEN_MAX + 20; /* 20 for slop. */
+ /*
+ * It should be safe to walk the list without locking it;
+ * new nodes are only added to the end and none are ever
+ * removed.
+ */
+ for (g = &__sglue; (n -= g->niobs) > 0 && g->next; g = g->next)
+ /* void */;
+ if ((n > 0) && ((g = moreglue(n)) != NULL)) {
+ STDIO_THREAD_LOCK();
+ SET_GLUE_PTR(lastglue->next, g);
+ lastglue = g;
+ STDIO_THREAD_UNLOCK();
+ }
+}
+
+/*
+ * exit() calls _cleanup() through *__cleanup, set whenever we
+ * open or buffer a file. This chicanery is done so that programs
+ * that do not use stdio need not link it all in.
+ *
+ * The name `_cleanup' is, alas, fairly well known outside stdio.
+ */
+void
+_cleanup()
+{
+ /* (void) _fwalk(fclose); */
+ (void) _fwalk(__sflush); /* `cheating' */
+}
+
+/*
+ * __sinit() is called whenever stdio's internal variables must be set up.
+ */
+void
+__sinit()
+{
+
+ /* Make sure we clean up on exit. */
+ __cleanup = _cleanup; /* conservative */
+ __sdidinit = 1;
+}
diff --git a/lib/libc/stdio/flags.c b/lib/libc/stdio/flags.c
new file mode 100644
index 0000000..0b6b075
--- /dev/null
+++ b/lib/libc/stdio/flags.c
@@ -0,0 +1,109 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)flags.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/file.h>
+#include <stdio.h>
+#include <errno.h>
+
+#include "local.h"
+
+/*
+ * Return the (stdio) flags for a given mode. Store the flags
+ * to be passed to an _open() syscall through *optr.
+ * Return 0 on error.
+ */
+int
+__sflags(mode, optr)
+ const char *mode;
+ int *optr;
+{
+ int ret, m, o;
+
+ switch (*mode++) {
+
+ case 'r': /* open for reading */
+ ret = __SRD;
+ m = O_RDONLY;
+ o = 0;
+ break;
+
+ case 'w': /* open for writing */
+ ret = __SWR;
+ m = O_WRONLY;
+ o = O_CREAT | O_TRUNC;
+ break;
+
+ case 'a': /* open for appending */
+ ret = __SWR;
+ m = O_WRONLY;
+ o = O_CREAT | O_APPEND;
+ break;
+
+ default: /* illegal mode */
+ errno = EINVAL;
+ return (0);
+ }
+
+ /* 'b' (binary) is ignored */
+ if (*mode == 'b')
+ mode++;
+
+ /* [rwa][b]\+ means read and write */
+ if (*mode == '+') {
+ mode++;
+ ret = __SRW;
+ m = O_RDWR;
+ }
+
+ /* 'b' (binary) can appear here, too -- and is ignored again */
+ if (*mode == 'b')
+ mode++;
+
+ /* 'x' means exclusive (fail if the file exists) */
+ if (*mode == 'x') {
+ if (m == O_RDONLY) {
+ errno = EINVAL;
+ return (0);
+ }
+ o |= O_EXCL;
+ }
+
+ *optr = m | o;
+ return (ret);
+}
diff --git a/lib/libc/stdio/floatio.h b/lib/libc/stdio/floatio.h
new file mode 100644
index 0000000..09d24b8
--- /dev/null
+++ b/lib/libc/stdio/floatio.h
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)floatio.h 8.1 (Berkeley) 6/4/93
+ * $FreeBSD$
+ */
+
+/*
+ * Floating point scanf/printf (input/output) definitions.
+ */
+
+/*
+ * MAXEXPDIG is the maximum number of decimal digits needed to store a
+ * floating point exponent in the largest supported format. It should
+ * be ceil(log10(LDBL_MAX_10_EXP)) or, if hexadecimal floating point
+ * conversions are supported, ceil(log10(LDBL_MAX_EXP)). But since it
+ * is presently never greater than 5 in practice, we fudge it.
+ */
+#define MAXEXPDIG 6
+#if LDBL_MAX_EXP > 999999
+#error "floating point buffers too small"
+#endif
+
+char *__hdtoa(double, const char *, int, int *, int *, char **);
+char *__hldtoa(long double, const char *, int, int *, int *, char **);
+char *__ldtoa(long double *, int, int, int *, int *, char **);
diff --git a/lib/libc/stdio/flockfile.3 b/lib/libc/stdio/flockfile.3
new file mode 100644
index 0000000..a895a0a
--- /dev/null
+++ b/lib/libc/stdio/flockfile.3
@@ -0,0 +1,104 @@
+.\" Copyright (c) 2003 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd January 10, 2003
+.Dt FLOCKFILE 3
+.Os
+.Sh NAME
+.Nm flockfile ,
+.Nm ftrylockfile ,
+.Nm funlockfile
+.Nd "stdio locking functions"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft void
+.Fn flockfile "FILE *stream"
+.Ft int
+.Fn ftrylockfile "FILE *stream"
+.Ft void
+.Fn funlockfile "FILE *stream"
+.Sh DESCRIPTION
+These functions provide explicit application-level locking of stdio streams.
+They can be used to avoid output from multiple threads being interspersed,
+input being dispersed among multiple readers, and to avoid the overhead
+of locking the stream for each operation.
+.Pp
+The
+.Fn flockfile
+function acquires an exclusive lock on the specified stream.
+If another thread has already locked the stream,
+.Fn flockfile
+will block until the lock is released.
+.Pp
+The
+.Fn ftrylockfile
+function is a non-blocking version of
+.Fn flockfile ;
+if the lock cannot be acquired immediately,
+.Fn ftrylockfile
+returns non-zero instead of blocking.
+.Pp
+The
+.Fn funlockfile
+function releases the lock on a stream acquired by an earlier call to
+.Fn flockfile
+or
+.Fn ftrylockfile .
+.Pp
+These functions behave as if there is a lock count associated
+with each stream.
+Each time
+.Fn flockfile
+is called on the stream, the count is incremented,
+and each time
+.Fn funlockfile
+is called on the stream, the count is decremented.
+The lock is only actually released when the count reaches zero.
+.Sh RETURN VALUES
+The
+.Fn flockfile
+and
+.Fn funlockfile
+functions return no value.
+.Pp
+The
+.Fn ftrylockfile
+function
+returns zero if the stream was successfully locked,
+non-zero otherwise.
+.Sh SEE ALSO
+.Xr getc_unlocked 3 ,
+.Xr putc_unlocked 3
+.Sh STANDARDS
+The
+.Fn flockfile ,
+.Fn ftrylockfile
+and
+.Fn funlockfile
+functions conform to
+.St -p1003.1-2001 .
diff --git a/lib/libc/stdio/fopen.3 b/lib/libc/stdio/fopen.3
new file mode 100644
index 0000000..64d033e
--- /dev/null
+++ b/lib/libc/stdio/fopen.3
@@ -0,0 +1,275 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fopen.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd October 17, 2011
+.Dt FOPEN 3
+.Os
+.Sh NAME
+.Nm fopen ,
+.Nm fdopen ,
+.Nm freopen
+.Nd stream open functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft FILE *
+.Fn fopen "const char * restrict path" "const char * restrict mode"
+.Ft FILE *
+.Fn fdopen "int fildes" "const char *mode"
+.Ft FILE *
+.Fn freopen "const char *path" "const char *mode" "FILE *stream"
+.Sh DESCRIPTION
+The
+.Fn fopen
+function
+opens the file whose name is the string pointed to by
+.Fa path
+and associates a stream with it.
+.Pp
+The argument
+.Fa mode
+points to a string beginning with one of the following letters:
+.Bl -tag -width indent
+.It Dq Li r
+Open for reading.
+The stream is positioned at the beginning of the file.
+Fail if the file does not exist.
+.It Dq Li w
+Open for writing.
+The stream is positioned at the beginning of the file.
+Create the file if it does not exist.
+.It Dq Li a
+Open for writing.
+The stream is positioned at the end of the file.
+Subsequent writes to the file will always end up at the then current
+end of file, irrespective of any intervening
+.Xr fseek 3
+or similar.
+Create the file if it does not exist.
+.El
+.Pp
+An optional
+.Dq Li +
+following
+.Dq Li r ,
+.Dq Li w ,
+or
+.Dq Li a
+opens the file for both reading and writing.
+An optional
+.Dq Li x
+following
+.Dq Li w
+or
+.Dq Li w+
+causes the
+.Fn fopen
+call to fail if the file already exists.
+.Pp
+The
+.Fa mode
+string can also include the letter
+.Dq Li b
+after either the
+.Dq Li +
+or the first letter.
+This is strictly for compatibility with
+.St -isoC
+and has no effect; the ``b'' is ignored.
+.Pp
+Any created files will have mode
+.Do Dv S_IRUSR
+\&|
+.Dv S_IWUSR
+\&|
+.Dv S_IRGRP
+\&|
+.Dv S_IWGRP
+\&|
+.Dv S_IROTH
+\&|
+.Dv S_IWOTH Dc
+.Pq Li 0666 ,
+as modified by the process'
+umask value (see
+.Xr umask 2 ) .
+.Pp
+Reads and writes may be intermixed on read/write streams in any order,
+and do not require an intermediate seek as in previous versions of
+.Em stdio .
+This is not portable to other systems, however;
+.Tn ANSI C
+requires that
+a file positioning function intervene between output and input, unless
+an input operation encounters end-of-file.
+.Pp
+The
+.Fn fdopen
+function associates a stream with the existing file descriptor,
+.Fa fildes .
+The mode
+of the stream must be compatible with the mode of the file descriptor.
+The
+.Dq Li x
+mode option is ignored.
+When the stream is closed via
+.Xr fclose 3 ,
+.Fa fildes
+is closed also.
+.Pp
+The
+.Fn freopen
+function
+opens the file whose name is the string pointed to by
+.Fa path
+and associates the stream pointed to by
+.Fa stream
+with it.
+The original stream (if it exists) is closed.
+The
+.Fa mode
+argument is used just as in the
+.Fn fopen
+function.
+.Pp
+If the
+.Fa path
+argument is
+.Dv NULL ,
+.Fn freopen
+attempts to re-open the file associated with
+.Fa stream
+with a new mode.
+The new mode must be compatible with the mode that the stream was originally
+opened with:
+Streams open for reading can only be re-opened for reading,
+streams open for writing can only be re-opened for writing,
+and streams open for reading and writing can be re-opened in any mode.
+The
+.Dq Li x
+mode option is not meaningful in this context.
+.Pp
+The primary use of the
+.Fn freopen
+function
+is to change the file associated with a
+standard text stream
+.Dv ( stderr , stdin ,
+or
+.Dv stdout ) .
+.Sh RETURN VALUES
+Upon successful completion
+.Fn fopen ,
+.Fn fdopen
+and
+.Fn freopen
+return a
+.Tn FILE
+pointer.
+Otherwise,
+.Dv NULL
+is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa mode
+argument
+to
+.Fn fopen ,
+.Fn fdopen ,
+or
+.Fn freopen
+was invalid.
+.El
+.Pp
+The
+.Fn fopen ,
+.Fn fdopen
+and
+.Fn freopen
+functions
+may also fail and set
+.Va errno
+for any of the errors specified for the routine
+.Xr malloc 3 .
+.Pp
+The
+.Fn fopen
+function
+may also fail and set
+.Va errno
+for any of the errors specified for the routine
+.Xr open 2 .
+.Pp
+The
+.Fn fdopen
+function
+may also fail and set
+.Va errno
+for any of the errors specified for the routine
+.Xr fcntl 2 .
+.Pp
+The
+.Fn freopen
+function
+may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr open 2 ,
+.Xr fclose 3
+and
+.Xr fflush 3 .
+.Sh SEE ALSO
+.Xr open 2 ,
+.Xr fclose 3 ,
+.Xr fileno 3 ,
+.Xr fseek 3 ,
+.Xr funopen 3
+.Sh STANDARDS
+The
+.Fn fopen
+and
+.Fn freopen
+functions
+conform to
+.St -isoC .
+The
+.Fn fdopen
+function
+conforms to
+.St -p1003.1-88 .
diff --git a/lib/libc/stdio/fopen.c b/lib/libc/stdio/fopen.c
new file mode 100644
index 0000000..6fe536a
--- /dev/null
+++ b/lib/libc/stdio/fopen.c
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fopen.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <limits.h>
+#include "un-namespace.h"
+
+#include "local.h"
+
+FILE *
+fopen(file, mode)
+ const char * __restrict file;
+ const char * __restrict mode;
+{
+ FILE *fp;
+ int f;
+ int flags, oflags;
+
+ if ((flags = __sflags(mode, &oflags)) == 0)
+ return (NULL);
+ if ((fp = __sfp()) == NULL)
+ return (NULL);
+ if ((f = _open(file, oflags, DEFFILEMODE)) < 0) {
+ fp->_flags = 0; /* release */
+ return (NULL);
+ }
+ /*
+ * File descriptors are a full int, but _file is only a short.
+ * If we get a valid file descriptor that is greater than
+ * SHRT_MAX, then the fd will get sign-extended into an
+ * invalid file descriptor. Handle this case by failing the
+ * open.
+ */
+ if (f > SHRT_MAX) {
+ fp->_flags = 0; /* release */
+ _close(f);
+ errno = EMFILE;
+ return (NULL);
+ }
+ fp->_file = f;
+ fp->_flags = flags;
+ fp->_cookie = fp;
+ fp->_read = __sread;
+ fp->_write = __swrite;
+ fp->_seek = __sseek;
+ fp->_close = __sclose;
+ /*
+ * When opening in append mode, even though we use O_APPEND,
+ * we need to seek to the end so that ftell() gets the right
+ * answer. If the user then alters the seek pointer, or
+ * the file extends, this will fail, but there is not much
+ * we can do about this. (We could set __SAPP and check in
+ * fseek and ftell.)
+ */
+ if (oflags & O_APPEND)
+ (void)_sseek(fp, (fpos_t)0, SEEK_END);
+ return (fp);
+}
diff --git a/lib/libc/stdio/fprintf.c b/lib/libc/stdio/fprintf.c
new file mode 100644
index 0000000..169532d
--- /dev/null
+++ b/lib/libc/stdio/fprintf.c
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fprintf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <stdarg.h>
+#include "xlocale_private.h"
+
+int
+fprintf(FILE * __restrict fp, const char * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vfprintf_l(fp, __get_locale(), fmt, ap);
+ va_end(ap);
+ return (ret);
+}
+int
+fprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+ FIX_LOCALE(locale);
+
+ va_start(ap, fmt);
+ ret = vfprintf_l(fp, locale, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
diff --git a/lib/libc/stdio/fpurge.c b/lib/libc/stdio/fpurge.c
new file mode 100644
index 0000000..6a2c70c
--- /dev/null
+++ b/lib/libc/stdio/fpurge.c
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fpurge.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+#include "local.h"
+#include "libc_private.h"
+
+/*
+ * fpurge: like fflush, but without writing anything: leave the
+ * given FILE's buffer empty.
+ */
+int
+fpurge(fp)
+ FILE *fp;
+{
+ int retval;
+ FLOCKFILE(fp);
+ if (!fp->_flags) {
+ errno = EBADF;
+ retval = EOF;
+ } else {
+ if (HASUB(fp))
+ FREEUB(fp);
+ fp->_p = fp->_bf._base;
+ fp->_r = 0;
+ fp->_w = fp->_flags & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
+ retval = 0;
+ }
+ FUNLOCKFILE(fp);
+ return (retval);
+}
diff --git a/lib/libc/stdio/fputc.c b/lib/libc/stdio/fputc.c
new file mode 100644
index 0000000..66d9a2f
--- /dev/null
+++ b/lib/libc/stdio/fputc.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fputc.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "local.h"
+#include "libc_private.h"
+
+int
+fputc(c, fp)
+ int c;
+ FILE *fp;
+{
+ int retval;
+ FLOCKFILE(fp);
+ /* Orientation set by __sputc() when buffer is full. */
+ /* ORIENT(fp, -1); */
+ retval = __sputc(c, fp);
+ FUNLOCKFILE(fp);
+ return (retval);
+}
diff --git a/lib/libc/stdio/fputs.3 b/lib/libc/stdio/fputs.3
new file mode 100644
index 0000000..8e8bbd1
--- /dev/null
+++ b/lib/libc/stdio/fputs.3
@@ -0,0 +1,104 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fputs.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt FPUTS 3
+.Os
+.Sh NAME
+.Nm fputs ,
+.Nm puts
+.Nd output a line to a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft int
+.Fn fputs "const char *str" "FILE *stream"
+.Ft int
+.Fn puts "const char *str"
+.Sh DESCRIPTION
+The function
+.Fn fputs
+writes the string pointed to by
+.Fa str
+to the stream pointed to by
+.Fa stream .
+.\" The terminating
+.\" .Dv NUL
+.\" character is not written.
+.Pp
+The function
+.Fn puts
+writes the string
+.Fa str ,
+and a terminating newline character,
+to the stream
+.Dv stdout .
+.Sh RETURN VALUES
+The functions
+.Fn fputs
+and
+.Fn puts
+return a nonnegative integer on success and
+.Dv EOF
+on error.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa stream
+argument
+is not a writable stream.
+.El
+.Pp
+The functions
+.Fn fputs
+and
+.Fn puts
+may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr write 2 .
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr fputws 3 ,
+.Xr putc 3 ,
+.Xr stdio 3
+.Sh STANDARDS
+The functions
+.Fn fputs
+and
+.Fn puts
+conform to
+.St -isoC .
diff --git a/lib/libc/stdio/fputs.c b/lib/libc/stdio/fputs.c
new file mode 100644
index 0000000..eb20f9e
--- /dev/null
+++ b/lib/libc/stdio/fputs.c
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fputs.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "fvwrite.h"
+#include "libc_private.h"
+#include "local.h"
+
+/*
+ * Write the given string to the given file.
+ */
+int
+fputs(s, fp)
+ const char * __restrict s;
+ FILE * __restrict fp;
+{
+ int retval;
+ struct __suio uio;
+ struct __siov iov;
+
+ iov.iov_base = (void *)s;
+ iov.iov_len = uio.uio_resid = strlen(s);
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ FLOCKFILE(fp);
+ ORIENT(fp, -1);
+ retval = __sfvwrite(fp, &uio);
+ FUNLOCKFILE(fp);
+ return (retval);
+}
diff --git a/lib/libc/stdio/fputwc.c b/lib/libc/stdio/fputwc.c
new file mode 100644
index 0000000..7b05d4a
--- /dev/null
+++ b/lib/libc/stdio/fputwc.c
@@ -0,0 +1,98 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+#include "mblocal.h"
+
+/*
+ * Non-MT-safe version.
+ */
+wint_t
+__fputwc(wchar_t wc, FILE *fp, locale_t locale)
+{
+ char buf[MB_LEN_MAX];
+ size_t i, len;
+ struct xlocale_ctype *l = XLOCALE_CTYPE(locale);
+
+ if (MB_CUR_MAX == 1 && wc > 0 && wc <= UCHAR_MAX) {
+ /*
+ * Assume single-byte locale with no special encoding.
+ * A more careful test would be to check
+ * _CurrentRuneLocale->encoding.
+ */
+ *buf = (unsigned char)wc;
+ len = 1;
+ } else {
+ if ((len = l->__wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) {
+ fp->_flags |= __SERR;
+ return (WEOF);
+ }
+ }
+
+ for (i = 0; i < len; i++)
+ if (__sputc((unsigned char)buf[i], fp) == EOF)
+ return (WEOF);
+
+ return ((wint_t)wc);
+}
+
+/*
+ * MT-safe version.
+ */
+wint_t
+fputwc_l(wchar_t wc, FILE *fp, locale_t locale)
+{
+ wint_t r;
+ FIX_LOCALE(locale);
+
+ FLOCKFILE(fp);
+ ORIENT(fp, 1);
+ r = __fputwc(wc, fp, locale);
+ FUNLOCKFILE(fp);
+
+ return (r);
+}
+wint_t
+fputwc(wchar_t wc, FILE *fp)
+{
+ return fputwc_l(wc, fp, __get_locale());
+}
diff --git a/lib/libc/stdio/fputws.3 b/lib/libc/stdio/fputws.3
new file mode 100644
index 0000000..ff62057
--- /dev/null
+++ b/lib/libc/stdio/fputws.3
@@ -0,0 +1,88 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fputs.3 8.1 (Berkeley) 6/4/93
+.\" FreeBSD: src/lib/libc/stdio/fputs.3,v 1.8 2001/10/01 16:08:59 ru Exp
+.\" $FreeBSD$
+.\"
+.Dd August 6, 2002
+.Dt FPUTWS 3
+.Os
+.Sh NAME
+.Nm fputws
+.Nd output a line of wide characters to a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.In wchar.h
+.Ft int
+.Fn fputws "const wchar_t * restrict ws" "FILE * restrict fp"
+.Sh DESCRIPTION
+The
+.Fn fputws
+function writes the wide character string pointed to by
+.Fa ws
+to the stream pointed to by
+.Fa fp .
+.Sh RETURN VALUES
+The
+.Fn fputws
+function
+returns 0 on success and \-1 on error.
+.Sh ERRORS
+The
+.Fn fputws
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa fp
+argument supplied
+is not a writable stream.
+.El
+.Pp
+The
+.Fn fputws
+function may also fail and set
+.Va errno
+for any of the errors specified for the routine
+.Xr write 2 .
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr fputs 3 ,
+.Xr putwc 3 ,
+.Xr stdio 3
+.Sh STANDARDS
+The
+.Fn fputws
+function conforms to
+.St -p1003.1-2001 .
diff --git a/lib/libc/stdio/fputws.c b/lib/libc/stdio/fputws.c
new file mode 100644
index 0000000..fa8d317
--- /dev/null
+++ b/lib/libc/stdio/fputws.c
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <wchar.h>
+#include "un-namespace.h"
+#include "fvwrite.h"
+#include "libc_private.h"
+#include "local.h"
+#include "mblocal.h"
+
+int
+fputws_l(const wchar_t * __restrict ws, FILE * __restrict fp, locale_t locale)
+{
+ size_t nbytes;
+ char buf[BUFSIZ];
+ struct __suio uio;
+ struct __siov iov;
+ const wchar_t *wsp;
+ FIX_LOCALE(locale);
+ struct xlocale_ctype *l = XLOCALE_CTYPE(locale);
+
+ FLOCKFILE(fp);
+ ORIENT(fp, 1);
+ if (prepwrite(fp) != 0)
+ goto error;
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ iov.iov_base = buf;
+ wsp = ws;
+ do {
+ nbytes = l->__wcsnrtombs(buf, &wsp, SIZE_T_MAX, sizeof(buf),
+ &fp->_mbstate);
+ if (nbytes == (size_t)-1)
+ goto error;
+ iov.iov_len = uio.uio_resid = nbytes;
+ if (__sfvwrite(fp, &uio) != 0)
+ goto error;
+ } while (wsp != NULL);
+ FUNLOCKFILE(fp);
+ return (0);
+
+error:
+ FUNLOCKFILE(fp);
+ return (-1);
+}
+
+int
+fputws(const wchar_t * __restrict ws, FILE * __restrict fp)
+{
+ return fputws_l(ws, fp, __get_locale());
+}
diff --git a/lib/libc/stdio/fread.3 b/lib/libc/stdio/fread.3
new file mode 100644
index 0000000..14541bb
--- /dev/null
+++ b/lib/libc/stdio/fread.3
@@ -0,0 +1,105 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fread.3 8.2 (Berkeley) 3/8/94
+.\" $FreeBSD$
+.\"
+.Dd March 8, 1994
+.Dt FREAD 3
+.Os
+.Sh NAME
+.Nm fread ,
+.Nm fwrite
+.Nd binary stream input/output
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft size_t
+.Fn fread "void * restrict ptr" "size_t size" "size_t nmemb" "FILE * restrict stream"
+.Ft size_t
+.Fn fwrite "const void * restrict ptr" "size_t size" "size_t nmemb" "FILE * restrict stream"
+.Sh DESCRIPTION
+The function
+.Fn fread
+reads
+.Fa nmemb
+objects, each
+.Fa size
+bytes long, from the stream pointed to by
+.Fa stream ,
+storing them at the location given by
+.Fa ptr .
+.Pp
+The function
+.Fn fwrite
+writes
+.Fa nmemb
+objects, each
+.Fa size
+bytes long, to the stream pointed to by
+.Fa stream ,
+obtaining them from the location given by
+.Fa ptr .
+.Sh RETURN VALUES
+The functions
+.Fn fread
+and
+.Fn fwrite
+advance the file position indicator for the stream
+by the number of bytes read or written.
+They return the number of objects read or written.
+If an error occurs, or the end-of-file is reached,
+the return value is a short object count (or zero).
+.Pp
+The function
+.Fn fread
+does not distinguish between end-of-file and error, and callers
+must use
+.Xr feof 3
+and
+.Xr ferror 3
+to determine which occurred.
+The function
+.Fn fwrite
+returns a value less than
+.Fa nmemb
+only if a write error has occurred.
+.Sh SEE ALSO
+.Xr read 2 ,
+.Xr write 2
+.Sh STANDARDS
+The functions
+.Fn fread
+and
+.Fn fwrite
+conform to
+.St -isoC .
diff --git a/lib/libc/stdio/fread.c b/lib/libc/stdio/fread.c
new file mode 100644
index 0000000..ad3ea29
--- /dev/null
+++ b/lib/libc/stdio/fread.c
@@ -0,0 +1,115 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fread.c 8.2 (Berkeley) 12/11/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "local.h"
+#include "libc_private.h"
+
+/*
+ * MT-safe version
+ */
+
+size_t
+fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
+{
+ size_t ret;
+
+ FLOCKFILE(fp);
+ ret = __fread(buf, size, count, fp);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
+
+size_t
+__fread(void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
+{
+ size_t resid;
+ char *p;
+ int r;
+ size_t total;
+
+ /*
+ * ANSI and SUSv2 require a return value of 0 if size or count are 0.
+ */
+ if ((count == 0) || (size == 0))
+ return (0);
+
+ /*
+ * Check for integer overflow. As an optimization, first check that
+ * at least one of {count, size} is at least 2^16, since if both
+ * values are less than that, their product can't possible overflow
+ * (size_t is always at least 32 bits on FreeBSD).
+ */
+ if (((count | size) > 0xFFFF) &&
+ (count > SIZE_MAX / size)) {
+ errno = EINVAL;
+ fp->_flags |= __SERR;
+ return (0);
+ }
+
+ /*
+ * Compute the (now required to not overflow) number of bytes to
+ * read and actually do the work.
+ */
+ resid = count * size;
+ ORIENT(fp, -1);
+ if (fp->_r < 0)
+ fp->_r = 0;
+ total = resid;
+ p = buf;
+ while (resid > (r = fp->_r)) {
+ (void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
+ fp->_p += r;
+ /* fp->_r = 0 ... done in __srefill */
+ p += r;
+ resid -= r;
+ if (__srefill(fp)) {
+ /* no more input: return partial result */
+ return ((total - resid) / size);
+ }
+ }
+ (void)memcpy((void *)p, (void *)fp->_p, resid);
+ fp->_r -= resid;
+ fp->_p += resid;
+ return (count);
+}
diff --git a/lib/libc/stdio/freopen.c b/lib/libc/stdio/freopen.c
new file mode 100644
index 0000000..be7bc8a
--- /dev/null
+++ b/lib/libc/stdio/freopen.c
@@ -0,0 +1,237 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)freopen.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <limits.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+/*
+ * Re-direct an existing, open (probably) file to some other file.
+ * ANSI is written such that the original file gets closed if at
+ * all possible, no matter what.
+ */
+FILE *
+freopen(file, mode, fp)
+ const char * __restrict file;
+ const char * __restrict mode;
+ FILE *fp;
+{
+ int f;
+ int dflags, flags, isopen, oflags, sverrno, wantfd;
+
+ if ((flags = __sflags(mode, &oflags)) == 0) {
+ sverrno = errno;
+ (void) fclose(fp);
+ errno = sverrno;
+ return (NULL);
+ }
+
+ FLOCKFILE(fp);
+
+ if (!__sdidinit)
+ __sinit();
+
+ /*
+ * If the filename is a NULL pointer, the caller is asking us to
+ * re-open the same file with a different mode. We allow this only
+ * if the modes are compatible.
+ */
+ if (file == NULL) {
+ /* See comment below regarding freopen() of closed files. */
+ if (fp->_flags == 0) {
+ FUNLOCKFILE(fp);
+ errno = EINVAL;
+ return (NULL);
+ }
+ if ((dflags = _fcntl(fp->_file, F_GETFL)) < 0) {
+ sverrno = errno;
+ fclose(fp);
+ FUNLOCKFILE(fp);
+ errno = sverrno;
+ return (NULL);
+ }
+ if ((dflags & O_ACCMODE) != O_RDWR && (dflags & O_ACCMODE) !=
+ (oflags & O_ACCMODE)) {
+ fclose(fp);
+ FUNLOCKFILE(fp);
+ errno = EINVAL;
+ return (NULL);
+ }
+ if (fp->_flags & __SWR)
+ (void) __sflush(fp);
+ if ((oflags ^ dflags) & O_APPEND) {
+ dflags &= ~O_APPEND;
+ dflags |= oflags & O_APPEND;
+ if (_fcntl(fp->_file, F_SETFL, dflags) < 0) {
+ sverrno = errno;
+ fclose(fp);
+ FUNLOCKFILE(fp);
+ errno = sverrno;
+ return (NULL);
+ }
+ }
+ if (oflags & O_TRUNC)
+ (void) ftruncate(fp->_file, (off_t)0);
+ if (!(oflags & O_APPEND))
+ (void) _sseek(fp, (fpos_t)0, SEEK_SET);
+ f = fp->_file;
+ isopen = 0;
+ wantfd = -1;
+ goto finish;
+ }
+
+ /*
+ * There are actually programs that depend on being able to "freopen"
+ * descriptors that weren't originally open. Keep this from breaking.
+ * Remember whether the stream was open to begin with, and which file
+ * descriptor (if any) was associated with it. If it was attached to
+ * a descriptor, defer closing it; freopen("/dev/stdin", "r", stdin)
+ * should work. This is unnecessary if it was not a Unix file.
+ */
+ if (fp->_flags == 0) {
+ fp->_flags = __SEOF; /* hold on to it */
+ isopen = 0;
+ wantfd = -1;
+ } else {
+ /* flush the stream; ANSI doesn't require this. */
+ if (fp->_flags & __SWR)
+ (void) __sflush(fp);
+ /* if close is NULL, closing is a no-op, hence pointless */
+ isopen = fp->_close != NULL;
+ if ((wantfd = fp->_file) < 0 && isopen) {
+ (void) (*fp->_close)(fp->_cookie);
+ isopen = 0;
+ }
+ }
+
+ /* Get a new descriptor to refer to the new file. */
+ f = _open(file, oflags, DEFFILEMODE);
+ sverrno = errno;
+
+finish:
+ /*
+ * Finish closing fp. Even if the open succeeded above, we cannot
+ * keep fp->_base: it may be the wrong size. This loses the effect
+ * of any setbuffer calls, but stdio has always done this before.
+ *
+ * Leave the existing file descriptor open until dup2() is called
+ * below to avoid races where a concurrent open() in another thread
+ * could claim the existing descriptor.
+ */
+ if (fp->_flags & __SMBF)
+ free((char *)fp->_bf._base);
+ fp->_w = 0;
+ fp->_r = 0;
+ fp->_p = NULL;
+ fp->_bf._base = NULL;
+ fp->_bf._size = 0;
+ fp->_lbfsize = 0;
+ if (HASUB(fp))
+ FREEUB(fp);
+ fp->_ub._size = 0;
+ if (HASLB(fp))
+ FREELB(fp);
+ fp->_lb._size = 0;
+ fp->_orientation = 0;
+ memset(&fp->_mbstate, 0, sizeof(mbstate_t));
+
+ if (f < 0) { /* did not get it after all */
+ if (isopen)
+ (void) (*fp->_close)(fp->_cookie);
+ fp->_flags = 0; /* set it free */
+ FUNLOCKFILE(fp);
+ errno = sverrno; /* restore in case _close clobbered */
+ return (NULL);
+ }
+
+ /*
+ * If reopening something that was open before on a real file, try
+ * to maintain the descriptor. Various C library routines (perror)
+ * assume stderr is always fd STDERR_FILENO, even if being freopen'd.
+ */
+ if (wantfd >= 0) {
+ if (_dup2(f, wantfd) >= 0) {
+ (void)_close(f);
+ f = wantfd;
+ } else
+ (void)_close(fp->_file);
+ }
+
+ /*
+ * File descriptors are a full int, but _file is only a short.
+ * If we get a valid file descriptor that is greater than
+ * SHRT_MAX, then the fd will get sign-extended into an
+ * invalid file descriptor. Handle this case by failing the
+ * open.
+ */
+ if (f > SHRT_MAX) {
+ fp->_flags = 0; /* set it free */
+ FUNLOCKFILE(fp);
+ errno = EMFILE;
+ return (NULL);
+ }
+
+ fp->_flags = flags;
+ fp->_file = f;
+ fp->_cookie = fp;
+ fp->_read = __sread;
+ fp->_write = __swrite;
+ fp->_seek = __sseek;
+ fp->_close = __sclose;
+ /*
+ * When opening in append mode, even though we use O_APPEND,
+ * we need to seek to the end so that ftell() gets the right
+ * answer. If the user then alters the seek pointer, or
+ * the file extends, this will fail, but there is not much
+ * we can do about this. (We could set __SAPP and check in
+ * fseek and ftell.)
+ */
+ if (oflags & O_APPEND)
+ (void) _sseek(fp, (fpos_t)0, SEEK_END);
+ FUNLOCKFILE(fp);
+ return (fp);
+}
diff --git a/lib/libc/stdio/fscanf.c b/lib/libc/stdio/fscanf.c
new file mode 100644
index 0000000..c5fa85f
--- /dev/null
+++ b/lib/libc/stdio/fscanf.c
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fscanf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+#include "xlocale_private.h"
+
+int
+fscanf(FILE * __restrict fp, char const * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ FLOCKFILE(fp);
+ ret = __svfscanf(fp, __get_locale(), fmt, ap);
+ va_end(ap);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
+int
+fscanf_l(FILE * __restrict fp, locale_t locale, char const * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+ FIX_LOCALE(locale);
+
+ va_start(ap, fmt);
+ FLOCKFILE(fp);
+ ret = __svfscanf(fp, locale, fmt, ap);
+ va_end(ap);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
diff --git a/lib/libc/stdio/fseek.3 b/lib/libc/stdio/fseek.3
new file mode 100644
index 0000000..3f45e31
--- /dev/null
+++ b/lib/libc/stdio/fseek.3
@@ -0,0 +1,269 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)fseek.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd March 19, 2004
+.Dt FSEEK 3
+.Os
+.Sh NAME
+.Nm fgetpos ,
+.Nm fseek ,
+.Nm fseeko ,
+.Nm fsetpos ,
+.Nm ftell ,
+.Nm ftello ,
+.Nm rewind
+.Nd reposition a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft int
+.Fn fseek "FILE *stream" "long offset" "int whence"
+.Ft long
+.Fn ftell "FILE *stream"
+.Ft void
+.Fn rewind "FILE *stream"
+.Ft int
+.Fn fgetpos "FILE * restrict stream" "fpos_t * restrict pos"
+.Ft int
+.Fn fsetpos "FILE *stream" "const fpos_t *pos"
+.In sys/types.h
+.Ft int
+.Fn fseeko "FILE *stream" "off_t offset" "int whence"
+.Ft off_t
+.Fn ftello "FILE *stream"
+.Sh DESCRIPTION
+The
+.Fn fseek
+function sets the file position indicator for the stream pointed
+to by
+.Fa stream .
+The new position, measured in bytes, is obtained by adding
+.Fa offset
+bytes to the position specified by
+.Fa whence .
+If
+.Fa whence
+is set to
+.Dv SEEK_SET ,
+.Dv SEEK_CUR ,
+or
+.Dv SEEK_END ,
+the offset is relative to the
+start of the file, the current position indicator, or end-of-file,
+respectively.
+A successful call to the
+.Fn fseek
+function clears the end-of-file indicator for the stream and undoes
+any effects of the
+.Xr ungetc 3
+and
+.Xr ungetwc 3
+functions on the same stream.
+.Pp
+The
+.Fn ftell
+function
+obtains the current value of the file position indicator for the
+stream pointed to by
+.Fa stream .
+.Pp
+The
+.Fn rewind
+function sets the file position indicator for the stream pointed
+to by
+.Fa stream
+to the beginning of the file.
+It is equivalent to:
+.Pp
+.Dl (void)fseek(stream, 0L, SEEK_SET)
+.Pp
+except that the error indicator for the stream is also cleared
+(see
+.Xr clearerr 3 ) .
+.Pp
+Since
+.Fn rewind
+does not return a value,
+an application wishing to detect errors should clear
+.Va errno ,
+then call
+.Fn rewind ,
+and if
+.Va errno
+is non-zero, assume an error has occurred.
+.Pp
+The
+.Fn fseeko
+function is identical to
+.Fn fseek ,
+except it takes an
+.Fa off_t
+argument
+instead of a
+.Fa long .
+Likewise, the
+.Fn ftello
+function is identical to
+.Fn ftell ,
+except it returns an
+.Fa off_t .
+.Pp
+The
+.Fn fgetpos
+and
+.Fn fsetpos
+functions
+are alternate interfaces for retrieving and setting the current position in
+the file, similar to
+.Fn ftell
+and
+.Fn fseek ,
+except that the current position is stored in an opaque object of
+type
+.Vt fpos_t
+pointed to by
+.Fa pos .
+These functions provide a portable way to seek to offsets larger than
+those that can be represented by a
+.Vt long int .
+They may also store additional state information in the
+.Vt fpos_t
+object to facilitate seeking within files containing multibyte
+characters with state-dependent encodings.
+Although
+.Vt fpos_t
+has traditionally been an integral type,
+applications cannot assume that it is;
+in particular, they must not perform arithmetic on objects
+of this type.
+.Pp
+If the stream is a wide character stream (see
+.Xr fwide 3 ) ,
+the position specified by the combination of
+.Fa offset
+and
+.Fa whence
+must contain the first byte of a multibyte sequence.
+.Sh RETURN VALUES
+The
+.Fn rewind
+function
+returns no value.
+.Pp
+.Rv -std fgetpos fseek fseeko fsetpos
+.Pp
+Upon successful completion,
+.Fn ftell
+and
+.Fn ftello
+return the current offset.
+Otherwise, \-1 is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa stream
+argument
+is not a seekable stream.
+.It Bq Er EINVAL
+The
+.Fa whence
+argument is invalid or
+the resulting file-position
+indicator would be set to a negative value.
+.It Bq Er EOVERFLOW
+The resulting file offset would be a value which
+cannot be represented correctly in an object of type
+.Fa off_t
+for
+.Fn fseeko
+and
+.Fn ftello
+or
+.Fa long
+for
+.Fn fseek
+and
+.Fn ftell .
+.It Bq Er ESPIPE
+The file descriptor underlying stream is associated with a pipe or FIFO
+or file-position indicator value is unspecified
+(see
+.Xr ungetc 3 ) .
+.El
+.Pp
+The functions
+.Fn fgetpos ,
+.Fn fseek ,
+.Fn fseeko ,
+.Fn fsetpos ,
+.Fn ftell ,
+.Fn ftello ,
+and
+.Fn rewind
+may also fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr fflush 3 ,
+.Xr fstat 2 ,
+.Xr lseek 2 ,
+and
+.Xr malloc 3 .
+.Sh SEE ALSO
+.Xr lseek 2 ,
+.Xr clearerr 3 ,
+.Xr fwide 3 ,
+.Xr ungetc 3 ,
+.Xr ungetwc 3
+.Sh STANDARDS
+The
+.Fn fgetpos ,
+.Fn fsetpos ,
+.Fn fseek ,
+.Fn ftell ,
+and
+.Fn rewind
+functions
+conform to
+.St -isoC .
+.Pp
+The
+.Fn fseeko
+and
+.Fn ftello
+functions conform to
+.St -p1003.1-2001 .
diff --git a/lib/libc/stdio/fseek.c b/lib/libc/stdio/fseek.c
new file mode 100644
index 0000000..c934349
--- /dev/null
+++ b/lib/libc/stdio/fseek.c
@@ -0,0 +1,311 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fseek.c 8.3 (Berkeley) 1/2/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+#include "local.h"
+#include "libc_private.h"
+
+#define POS_ERR (-(fpos_t)1)
+
+int
+fseek(fp, offset, whence)
+ FILE *fp;
+ long offset;
+ int whence;
+{
+ int ret;
+ int serrno = errno;
+
+ /* make sure stdio is set up */
+ if (!__sdidinit)
+ __sinit();
+
+ FLOCKFILE(fp);
+ ret = _fseeko(fp, (off_t)offset, whence, 1);
+ FUNLOCKFILE(fp);
+ if (ret == 0)
+ errno = serrno;
+ return (ret);
+}
+
+int
+fseeko(fp, offset, whence)
+ FILE *fp;
+ off_t offset;
+ int whence;
+{
+ int ret;
+ int serrno = errno;
+
+ /* make sure stdio is set up */
+ if (!__sdidinit)
+ __sinit();
+
+ FLOCKFILE(fp);
+ ret = _fseeko(fp, offset, whence, 0);
+ FUNLOCKFILE(fp);
+ if (ret == 0)
+ errno = serrno;
+ return (ret);
+}
+
+/*
+ * Seek the given file to the given offset.
+ * `Whence' must be one of the three SEEK_* macros.
+ */
+int
+_fseeko(fp, offset, whence, ltest)
+ FILE *fp;
+ off_t offset;
+ int whence;
+ int ltest;
+{
+ fpos_t (*seekfn)(void *, fpos_t, int);
+ fpos_t target, curoff, ret;
+ size_t n;
+ struct stat st;
+ int havepos;
+
+ /*
+ * Have to be able to seek.
+ */
+ if ((seekfn = fp->_seek) == NULL) {
+ errno = ESPIPE; /* historic practice */
+ return (-1);
+ }
+
+ /*
+ * Change any SEEK_CUR to SEEK_SET, and check `whence' argument.
+ * After this, whence is either SEEK_SET or SEEK_END.
+ */
+ switch (whence) {
+
+ case SEEK_CUR:
+ /*
+ * In order to seek relative to the current stream offset,
+ * we have to first find the current stream offset via
+ * ftell (see ftell for details).
+ */
+ if (_ftello(fp, &curoff))
+ return (-1);
+ if (curoff < 0) {
+ /* Unspecified position because of ungetc() at 0 */
+ errno = ESPIPE;
+ return (-1);
+ }
+ if (offset > 0 && curoff > OFF_MAX - offset) {
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ offset += curoff;
+ if (offset < 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (ltest && offset > LONG_MAX) {
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ whence = SEEK_SET;
+ havepos = 1;
+ break;
+
+ case SEEK_SET:
+ if (offset < 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+ case SEEK_END:
+ curoff = 0; /* XXX just to keep gcc quiet */
+ havepos = 0;
+ break;
+
+ default:
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /*
+ * Can only optimise if:
+ * reading (and not reading-and-writing);
+ * not unbuffered; and
+ * this is a `regular' Unix file (and hence seekfn==__sseek).
+ * We must check __NBF first, because it is possible to have __NBF
+ * and __SOPT both set.
+ */
+ if (fp->_bf._base == NULL)
+ __smakebuf(fp);
+ if (fp->_flags & (__SWR | __SRW | __SNBF | __SNPT))
+ goto dumb;
+ if ((fp->_flags & __SOPT) == 0) {
+ if (seekfn != __sseek ||
+ fp->_file < 0 || _fstat(fp->_file, &st) ||
+ (st.st_mode & S_IFMT) != S_IFREG) {
+ fp->_flags |= __SNPT;
+ goto dumb;
+ }
+ fp->_blksize = st.st_blksize;
+ fp->_flags |= __SOPT;
+ }
+
+ /*
+ * We are reading; we can try to optimise.
+ * Figure out where we are going and where we are now.
+ */
+ if (whence == SEEK_SET)
+ target = offset;
+ else {
+ if (_fstat(fp->_file, &st))
+ goto dumb;
+ if (offset > 0 && st.st_size > OFF_MAX - offset) {
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ target = st.st_size + offset;
+ if ((off_t)target < 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (ltest && (off_t)target > LONG_MAX) {
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ }
+
+ if (!havepos && _ftello(fp, &curoff))
+ goto dumb;
+
+ /*
+ * (If the buffer was modified, we have to
+ * skip this; see fgetln.c.)
+ */
+ if (fp->_flags & __SMOD)
+ goto abspos;
+
+ /*
+ * Compute the number of bytes in the input buffer (pretending
+ * that any ungetc() input has been discarded). Adjust current
+ * offset backwards by this count so that it represents the
+ * file offset for the first byte in the current input buffer.
+ */
+ if (HASUB(fp)) {
+ curoff += fp->_r; /* kill off ungetc */
+ n = fp->_up - fp->_bf._base;
+ curoff -= n;
+ n += fp->_ur;
+ } else {
+ n = fp->_p - fp->_bf._base;
+ curoff -= n;
+ n += fp->_r;
+ }
+
+ /*
+ * If the target offset is within the current buffer,
+ * simply adjust the pointers, clear EOF, undo ungetc(),
+ * and return.
+ */
+ if (target >= curoff && target < curoff + n) {
+ size_t o = target - curoff;
+
+ fp->_p = fp->_bf._base + o;
+ fp->_r = n - o;
+ if (HASUB(fp))
+ FREEUB(fp);
+ fp->_flags &= ~__SEOF;
+ memset(&fp->_mbstate, 0, sizeof(mbstate_t));
+ return (0);
+ }
+
+abspos:
+ /*
+ * The place we want to get to is not within the current buffer,
+ * but we can still be kind to the kernel copyout mechanism.
+ * By aligning the file offset to a block boundary, we can let
+ * the kernel use the VM hardware to map pages instead of
+ * copying bytes laboriously. Using a block boundary also
+ * ensures that we only read one block, rather than two.
+ */
+ curoff = target & ~(fp->_blksize - 1);
+ if (_sseek(fp, curoff, SEEK_SET) == POS_ERR)
+ goto dumb;
+ fp->_r = 0;
+ fp->_p = fp->_bf._base;
+ if (HASUB(fp))
+ FREEUB(fp);
+ n = target - curoff;
+ if (n) {
+ if (__srefill(fp) || fp->_r < n)
+ goto dumb;
+ fp->_p += n;
+ fp->_r -= n;
+ }
+ fp->_flags &= ~__SEOF;
+ memset(&fp->_mbstate, 0, sizeof(mbstate_t));
+ return (0);
+
+ /*
+ * We get here if we cannot optimise the seek ... just
+ * do it. Allow the seek function to change fp->_bf._base.
+ */
+dumb:
+ if (__sflush(fp) ||
+ (ret = _sseek(fp, (fpos_t)offset, whence)) == POS_ERR)
+ return (-1);
+ if (ltest && ret > LONG_MAX) {
+ fp->_flags |= __SERR;
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ /* success: clear EOF indicator and discard ungetc() data */
+ if (HASUB(fp))
+ FREEUB(fp);
+ fp->_p = fp->_bf._base;
+ fp->_r = 0;
+ /* fp->_w = 0; */ /* unnecessary (I think...) */
+ fp->_flags &= ~__SEOF;
+ memset(&fp->_mbstate, 0, sizeof(mbstate_t));
+ return (0);
+}
diff --git a/lib/libc/stdio/fsetpos.c b/lib/libc/stdio/fsetpos.c
new file mode 100644
index 0000000..f9a742e
--- /dev/null
+++ b/lib/libc/stdio/fsetpos.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fsetpos.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <stdio.h>
+
+/*
+ * fsetpos: like fseek.
+ */
+int
+fsetpos(iop, pos)
+ FILE *iop;
+ const fpos_t *pos;
+{
+ return (fseeko(iop, (off_t)*pos, SEEK_SET));
+}
diff --git a/lib/libc/stdio/ftell.c b/lib/libc/stdio/ftell.c
new file mode 100644
index 0000000..a9ff6ed
--- /dev/null
+++ b/lib/libc/stdio/ftell.c
@@ -0,0 +1,139 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ftell.c 8.2 (Berkeley) 5/4/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include "un-namespace.h"
+#include "local.h"
+#include "libc_private.h"
+
+/*
+ * standard ftell function.
+ */
+long
+ftell(fp)
+ FILE *fp;
+{
+ off_t rv;
+
+ rv = ftello(fp);
+ if (rv > LONG_MAX) {
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ return (rv);
+}
+
+/*
+ * ftello: return current offset.
+ */
+off_t
+ftello(fp)
+ FILE *fp;
+{
+ fpos_t rv;
+ int ret;
+
+ FLOCKFILE(fp);
+ ret = _ftello(fp, &rv);
+ FUNLOCKFILE(fp);
+ if (ret)
+ return (-1);
+ if (rv < 0) { /* Unspecified value because of ungetc() at 0 */
+ errno = ESPIPE;
+ return (-1);
+ }
+ return (rv);
+}
+
+int
+_ftello(fp, offset)
+ FILE *fp;
+ fpos_t *offset;
+{
+ fpos_t pos;
+ size_t n;
+
+ if (fp->_seek == NULL) {
+ errno = ESPIPE; /* historic practice */
+ return (1);
+ }
+
+ /*
+ * Find offset of underlying I/O object, then
+ * adjust for buffered bytes.
+ */
+ if (fp->_flags & __SOFF)
+ pos = fp->_offset;
+ else {
+ pos = _sseek(fp, (fpos_t)0, SEEK_CUR);
+ if (pos == -1)
+ return (1);
+ }
+ if (fp->_flags & __SRD) {
+ /*
+ * Reading. Any unread characters (including
+ * those from ungetc) cause the position to be
+ * smaller than that in the underlying object.
+ */
+ if ((pos -= (HASUB(fp) ? fp->_ur : fp->_r)) < 0) {
+ fp->_flags |= __SERR;
+ errno = EIO;
+ return (1);
+ }
+ if (HASUB(fp))
+ pos -= fp->_r; /* Can be negative at this point. */
+ } else if ((fp->_flags & __SWR) && fp->_p != NULL) {
+ /*
+ * Writing. Any buffered characters cause the
+ * position to be greater than that in the
+ * underlying object.
+ */
+ n = fp->_p - fp->_bf._base;
+ if (pos > OFF_MAX - n) {
+ errno = EOVERFLOW;
+ return (1);
+ }
+ pos += n;
+ }
+ *offset = pos;
+ return (0);
+}
diff --git a/lib/libc/stdio/funopen.3 b/lib/libc/stdio/funopen.3
new file mode 100644
index 0000000..ef7c8f9
--- /dev/null
+++ b/lib/libc/stdio/funopen.3
@@ -0,0 +1,176 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)funopen.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd March 19, 2004
+.Dt FUNOPEN 3
+.Os
+.Sh NAME
+.Nm funopen ,
+.Nm fropen ,
+.Nm fwopen
+.Nd open a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft FILE *
+.Fn funopen "const void *cookie" "int (*readfn)(void *, char *, int)" "int (*writefn)(void *, const char *, int)" "fpos_t (*seekfn)(void *, fpos_t, int)" "int (*closefn)(void *)"
+.Ft FILE *
+.Fn fropen "void *cookie" "int (*readfn)(void *, char *, int)"
+.Ft FILE *
+.Fn fwopen "void *cookie" "int (*writefn)(void *, const char *, int)"
+.Sh DESCRIPTION
+The
+.Fn funopen
+function
+associates a stream with up to four
+.Dq Tn I/O No functions .
+Either
+.Fa readfn
+or
+.Fa writefn
+must be specified;
+the others can be given as an appropriately-typed
+.Dv NULL
+pointer.
+These
+.Tn I/O
+functions will be used to read, write, seek and
+close the new stream.
+.Pp
+In general, omitting a function means that any attempt to perform the
+associated operation on the resulting stream will fail.
+If the close function is omitted, closing the stream will flush
+any buffered output and then succeed.
+.Pp
+The calling conventions of
+.Fa readfn ,
+.Fa writefn ,
+.Fa seekfn
+and
+.Fa closefn
+must match those, respectively, of
+.Xr read 2 ,
+.Xr write 2 ,
+.Xr lseek 2 ,
+and
+.Xr close 2
+with the single exception that they are passed the
+.Fa cookie
+argument specified to
+.Fn funopen
+in place of the traditional file descriptor argument.
+.Pp
+Read and write
+.Tn I/O
+functions are allowed to change the underlying buffer
+on fully buffered or line buffered streams by calling
+.Xr setvbuf 3 .
+They are also not required to completely fill or empty the buffer.
+They are not, however, allowed to change streams from unbuffered to buffered
+or to change the state of the line buffering flag.
+They must also be prepared to have read or write calls occur on buffers other
+than the one most recently specified.
+.Pp
+All user
+.Tn I/O
+functions can report an error by returning \-1.
+Additionally, all of the functions should set the external variable
+.Va errno
+appropriately if an error occurs.
+.Pp
+An error on
+.Fn closefn
+does not keep the stream open.
+.Pp
+As a convenience, the include file
+.In stdio.h
+defines the macros
+.Fn fropen
+and
+.Fn fwopen
+as calls to
+.Fn funopen
+with only a read or write function specified.
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn funopen
+returns a
+.Dv FILE
+pointer.
+Otherwise,
+.Dv NULL
+is returned and the global variable
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fn funopen
+function
+was called without either a read or write function.
+The
+.Fn funopen
+function
+may also fail and set
+.Va errno
+for any of the errors
+specified for the routine
+.Xr malloc 3 .
+.El
+.Sh SEE ALSO
+.Xr fcntl 2 ,
+.Xr open 2 ,
+.Xr fclose 3 ,
+.Xr fopen 3 ,
+.Xr fseek 3 ,
+.Xr setbuf 3
+.Sh HISTORY
+The
+.Fn funopen
+functions first appeared in
+.Bx 4.4 .
+.Sh BUGS
+The
+.Fn funopen
+function
+may not be portable to systems other than
+.Bx .
+.Pp
+The
+.Fn funopen
+interface erroneously assumes that
+.Vt fpos_t
+is an integral type; see
+.Xr fseek 3
+for a discussion of this issue.
diff --git a/lib/libc/stdio/funopen.c b/lib/libc/stdio/funopen.c
new file mode 100644
index 0000000..573589f
--- /dev/null
+++ b/lib/libc/stdio/funopen.c
@@ -0,0 +1,76 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)funopen.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <errno.h>
+
+#include "local.h"
+
+FILE *
+funopen(const void *cookie,
+ int (*readfn)(void *, char *, int),
+ int (*writefn)(void *, const char *, int),
+ fpos_t (*seekfn)(void *, fpos_t, int),
+ int (*closefn)(void *))
+{
+ FILE *fp;
+ int flags;
+
+ if (readfn == NULL) {
+ if (writefn == NULL) { /* illegal */
+ errno = EINVAL;
+ return (NULL);
+ } else
+ flags = __SWR; /* write only */
+ } else {
+ if (writefn == NULL)
+ flags = __SRD; /* read only */
+ else
+ flags = __SRW; /* read-write */
+ }
+ if ((fp = __sfp()) == NULL)
+ return (NULL);
+ fp->_flags = flags;
+ fp->_file = -1;
+ fp->_cookie = (void *)cookie;
+ fp->_read = readfn;
+ fp->_write = writefn;
+ fp->_seek = seekfn;
+ fp->_close = closefn;
+ return (fp);
+}
diff --git a/lib/libc/stdio/fvwrite.c b/lib/libc/stdio/fvwrite.c
new file mode 100644
index 0000000..7206676
--- /dev/null
+++ b/lib/libc/stdio/fvwrite.c
@@ -0,0 +1,207 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fvwrite.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "local.h"
+#include "fvwrite.h"
+
+/*
+ * Write some memory regions. Return zero on success, EOF on error.
+ *
+ * This routine is large and unsightly, but most of the ugliness due
+ * to the three different kinds of output buffering is handled here.
+ */
+int
+__sfvwrite(fp, uio)
+ FILE *fp;
+ struct __suio *uio;
+{
+ size_t len;
+ char *p;
+ struct __siov *iov;
+ int w, s;
+ char *nl;
+ int nlknown, nldist;
+
+ if (uio->uio_resid == 0)
+ return (0);
+ /* make sure we can write */
+ if (prepwrite(fp) != 0)
+ return (EOF);
+
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#define COPY(n) (void)memcpy((void *)fp->_p, (void *)p, (size_t)(n))
+
+ iov = uio->uio_iov;
+ p = iov->iov_base;
+ len = iov->iov_len;
+ iov++;
+#define GETIOV(extra_work) \
+ while (len == 0) { \
+ extra_work; \
+ p = iov->iov_base; \
+ len = iov->iov_len; \
+ iov++; \
+ }
+ if (fp->_flags & __SNBF) {
+ /*
+ * Unbuffered: write up to BUFSIZ bytes at a time.
+ */
+ do {
+ GETIOV(;);
+ w = _swrite(fp, p, MIN(len, BUFSIZ));
+ if (w <= 0)
+ goto err;
+ p += w;
+ len -= w;
+ } while ((uio->uio_resid -= w) != 0);
+ } else if ((fp->_flags & __SLBF) == 0) {
+ /*
+ * Fully buffered: fill partially full buffer, if any,
+ * and then flush. If there is no partial buffer, write
+ * one _bf._size byte chunk directly (without copying).
+ *
+ * String output is a special case: write as many bytes
+ * as fit, but pretend we wrote everything. This makes
+ * snprintf() return the number of bytes needed, rather
+ * than the number used, and avoids its write function
+ * (so that the write function can be invalid).
+ */
+ do {
+ GETIOV(;);
+ if ((fp->_flags & (__SALC | __SSTR)) ==
+ (__SALC | __SSTR) && fp->_w < len) {
+ size_t blen = fp->_p - fp->_bf._base;
+
+ /*
+ * Alloc an extra 128 bytes (+ 1 for NULL)
+ * so we don't call realloc(3) so often.
+ */
+ fp->_w = len + 128;
+ fp->_bf._size = blen + len + 128;
+ fp->_bf._base =
+ reallocf(fp->_bf._base, fp->_bf._size + 1);
+ if (fp->_bf._base == NULL)
+ goto err;
+ fp->_p = fp->_bf._base + blen;
+ }
+ w = fp->_w;
+ if (fp->_flags & __SSTR) {
+ if (len < w)
+ w = len;
+ if (w > 0) {
+ COPY(w); /* copy MIN(fp->_w,len), */
+ fp->_w -= w;
+ fp->_p += w;
+ }
+ w = len; /* but pretend copied all */
+ } else if (fp->_p > fp->_bf._base && len > w) {
+ /* fill and flush */
+ COPY(w);
+ /* fp->_w -= w; */ /* unneeded */
+ fp->_p += w;
+ if (__fflush(fp))
+ goto err;
+ } else if (len >= (w = fp->_bf._size)) {
+ /* write directly */
+ w = _swrite(fp, p, w);
+ if (w <= 0)
+ goto err;
+ } else {
+ /* fill and done */
+ w = len;
+ COPY(w);
+ fp->_w -= w;
+ fp->_p += w;
+ }
+ p += w;
+ len -= w;
+ } while ((uio->uio_resid -= w) != 0);
+ } else {
+ /*
+ * Line buffered: like fully buffered, but we
+ * must check for newlines. Compute the distance
+ * to the first newline (including the newline),
+ * or `infinity' if there is none, then pretend
+ * that the amount to write is MIN(len,nldist).
+ */
+ nlknown = 0;
+ nldist = 0; /* XXX just to keep gcc happy */
+ do {
+ GETIOV(nlknown = 0);
+ if (!nlknown) {
+ nl = memchr((void *)p, '\n', len);
+ nldist = nl ? nl + 1 - p : len + 1;
+ nlknown = 1;
+ }
+ s = MIN(len, nldist);
+ w = fp->_w + fp->_bf._size;
+ if (fp->_p > fp->_bf._base && s > w) {
+ COPY(w);
+ /* fp->_w -= w; */
+ fp->_p += w;
+ if (__fflush(fp))
+ goto err;
+ } else if (s >= (w = fp->_bf._size)) {
+ w = _swrite(fp, p, w);
+ if (w <= 0)
+ goto err;
+ } else {
+ w = s;
+ COPY(w);
+ fp->_w -= w;
+ fp->_p += w;
+ }
+ if ((nldist -= w) == 0) {
+ /* copied the newline: flush and forget */
+ if (__fflush(fp))
+ goto err;
+ nlknown = 0;
+ }
+ p += w;
+ len -= w;
+ } while ((uio->uio_resid -= w) != 0);
+ }
+ return (0);
+
+err:
+ fp->_flags |= __SERR;
+ return (EOF);
+}
diff --git a/lib/libc/stdio/fvwrite.h b/lib/libc/stdio/fvwrite.h
new file mode 100644
index 0000000..a4da743
--- /dev/null
+++ b/lib/libc/stdio/fvwrite.h
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)fvwrite.h 8.1 (Berkeley) 6/4/93
+ * $FreeBSD$
+ */
+
+/*
+ * I/O descriptors for __sfvwrite().
+ */
+struct __siov {
+ void *iov_base;
+ size_t iov_len;
+};
+struct __suio {
+ struct __siov *uio_iov;
+ int uio_iovcnt;
+ int uio_resid;
+};
+
+extern int __sfvwrite(FILE *, struct __suio *);
diff --git a/lib/libc/stdio/fwalk.c b/lib/libc/stdio/fwalk.c
new file mode 100644
index 0000000..e5ce49f
--- /dev/null
+++ b/lib/libc/stdio/fwalk.c
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fwalk.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <machine/atomic.h>
+#include <stdio.h>
+#include "local.h"
+#include "glue.h"
+
+int
+_fwalk(function)
+ int (*function)(FILE *);
+{
+ FILE *fp;
+ int n, ret;
+ struct glue *g;
+
+ ret = 0;
+ /*
+ * It should be safe to walk the list without locking it;
+ * new nodes are only added to the end and none are ever
+ * removed.
+ *
+ * Avoid locking this list while walking it or else you will
+ * introduce a potential deadlock in [at least] refill.c.
+ */
+ for (g = &__sglue; g != NULL; g = g->next)
+ for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
+ if ((fp->_flags != 0) && ((fp->_flags & __SIGN) == 0))
+ ret |= (*function)(fp);
+ return (ret);
+}
diff --git a/lib/libc/stdio/fwide.3 b/lib/libc/stdio/fwide.3
new file mode 100644
index 0000000..6ff8d92
--- /dev/null
+++ b/lib/libc/stdio/fwide.3
@@ -0,0 +1,97 @@
+.\" $NetBSD: fwide.3,v 1.3 2002/02/07 07:00:25 ross Exp $
+.\"
+.\" Copyright (c)2001 Citrus Project,
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $Citrus: xpg4dl/FreeBSD/lib/libc/stdio/fwide.3,v 1.2 2001/12/07 04:47:08 yamt Exp $
+.\" $FreeBSD$
+.\"
+.Dd October 24, 2001
+.Dt FWIDE 3
+.Os
+.Sh NAME
+.Nm fwide
+.Nd get/set orientation of a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.In wchar.h
+.Ft int
+.Fn fwide "FILE *stream" "int mode"
+.Sh DESCRIPTION
+The
+.Fn fwide
+function
+determines the orientation of the stream pointed at by
+.Fa stream .
+.Pp
+If the orientation of
+.Fa stream
+has already been determined,
+.Fn fwide
+leaves it unchanged.
+Otherwise,
+.Fn fwide
+sets the orientation of
+.Fa stream
+according to
+.Fa mode .
+.Pp
+If
+.Fa mode
+is less than zero,
+.Fa stream
+is set to byte-oriented.
+If it is greater than zero,
+.Fa stream
+is set to wide-oriented.
+Otherwise,
+.Fa mode
+is zero, and
+.Fa stream
+is unchanged.
+.Sh RETURN VALUES
+The
+.Fn fwide
+function
+returns a value according to orientation after the call of
+.Fn fwide ;
+a value less than zero if byte-oriented, a value greater than zero
+if wide-oriented, and zero if the stream has no orientation.
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr fgetc 3 ,
+.Xr fgetwc 3 ,
+.Xr fopen 3 ,
+.Xr fputc 3 ,
+.Xr fputwc 3 ,
+.Xr freopen 3 ,
+.Xr stdio 3
+.Sh STANDARDS
+The
+.Fn fwide
+function
+conforms to
+.St -isoC-99 .
diff --git a/lib/libc/stdio/fwide.c b/lib/libc/stdio/fwide.c
new file mode 100644
index 0000000..c94ffe6
--- /dev/null
+++ b/lib/libc/stdio/fwide.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <stdio.h>
+#include <wchar.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+int
+fwide(FILE *fp, int mode)
+{
+ int m;
+
+ FLOCKFILE(fp);
+ /* Only change the orientation if the stream is not oriented yet. */
+ if (mode != 0 && fp->_orientation == 0)
+ fp->_orientation = mode > 0 ? 1 : -1;
+ m = fp->_orientation;
+ FUNLOCKFILE(fp);
+
+ return (m);
+}
diff --git a/lib/libc/stdio/fwprintf.c b/lib/libc/stdio/fwprintf.c
new file mode 100644
index 0000000..f4342ab
--- /dev/null
+++ b/lib/libc/stdio/fwprintf.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <xlocale.h>
+
+int
+fwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vfwprintf(fp, fmt, ap);
+ va_end(ap);
+
+ return (ret);
+}
+int
+fwprintf_l(FILE * __restrict fp, locale_t locale, const wchar_t * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vfwprintf_l(fp, locale, fmt, ap);
+ va_end(ap);
+
+ return (ret);
+}
diff --git a/lib/libc/stdio/fwrite.c b/lib/libc/stdio/fwrite.c
new file mode 100644
index 0000000..acac943
--- /dev/null
+++ b/lib/libc/stdio/fwrite.c
@@ -0,0 +1,99 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fwrite.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <stdint.h>
+#include <stdio.h>
+#include "un-namespace.h"
+#include "local.h"
+#include "fvwrite.h"
+#include "libc_private.h"
+
+/*
+ * Write `count' objects (each size `size') from memory to the given file.
+ * Return the number of whole objects written.
+ */
+size_t
+fwrite(buf, size, count, fp)
+ const void * __restrict buf;
+ size_t size, count;
+ FILE * __restrict fp;
+{
+ size_t n;
+ struct __suio uio;
+ struct __siov iov;
+
+ /*
+ * ANSI and SUSv2 require a return value of 0 if size or count are 0.
+ */
+ if ((count == 0) || (size == 0))
+ return (0);
+
+ /*
+ * Check for integer overflow. As an optimization, first check that
+ * at least one of {count, size} is at least 2^16, since if both
+ * values are less than that, their product can't possible overflow
+ * (size_t is always at least 32 bits on FreeBSD).
+ */
+ if (((count | size) > 0xFFFF) &&
+ (count > SIZE_MAX / size)) {
+ errno = EINVAL;
+ fp->_flags |= __SERR;
+ return (0);
+ }
+
+ n = count * size;
+
+ iov.iov_base = (void *)buf;
+ uio.uio_resid = iov.iov_len = n;
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+
+ FLOCKFILE(fp);
+ ORIENT(fp, -1);
+ /*
+ * The usual case is success (__sfvwrite returns 0);
+ * skip the divide if this happens, since divides are
+ * generally slow and since this occurs whenever size==0.
+ */
+ if (__sfvwrite(fp, &uio) != 0)
+ count = (n - uio.uio_resid) / size;
+ FUNLOCKFILE(fp);
+ return (count);
+}
diff --git a/lib/libc/stdio/fwscanf.c b/lib/libc/stdio/fwscanf.c
new file mode 100644
index 0000000..1756077
--- /dev/null
+++ b/lib/libc/stdio/fwscanf.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <xlocale.h>
+
+int
+fwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, ...)
+{
+ va_list ap;
+ int r;
+
+ va_start(ap, fmt);
+ r = vfwscanf(fp, fmt, ap);
+ va_end(ap);
+
+ return (r);
+}
+int
+fwscanf_l(FILE * __restrict fp, locale_t locale, const wchar_t * __restrict fmt, ...)
+{
+ va_list ap;
+ int r;
+
+ va_start(ap, fmt);
+ r = vfwscanf_l(fp, locale, fmt, ap);
+ va_end(ap);
+
+ return (r);
+}
diff --git a/lib/libc/stdio/getc.3 b/lib/libc/stdio/getc.3
new file mode 100644
index 0000000..d0f3c15
--- /dev/null
+++ b/lib/libc/stdio/getc.3
@@ -0,0 +1,169 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getc.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd January 10, 2003
+.Dt GETC 3
+.Os
+.Sh NAME
+.Nm fgetc ,
+.Nm getc ,
+.Nm getc_unlocked ,
+.Nm getchar ,
+.Nm getchar_unlocked ,
+.Nm getw
+.Nd get next character or word from input stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft int
+.Fn fgetc "FILE *stream"
+.Ft int
+.Fn getc "FILE *stream"
+.Ft int
+.Fn getc_unlocked "FILE *stream"
+.Ft int
+.Fn getchar void
+.Ft int
+.Fn getchar_unlocked void
+.Ft int
+.Fn getw "FILE *stream"
+.Sh DESCRIPTION
+The
+.Fn fgetc
+function
+obtains the next input character (if present) from the stream pointed at by
+.Fa stream ,
+or the next character pushed back on the stream via
+.Xr ungetc 3 .
+.Pp
+The
+.Fn getc
+function
+acts essentially identically to
+.Fn fgetc ,
+but is a macro that expands in-line.
+.Pp
+The
+.Fn getchar
+function
+is equivalent to
+.Fn getc stdin .
+.Pp
+The
+.Fn getw
+function
+obtains the next
+.Vt int
+(if present)
+from the stream pointed at by
+.Fa stream .
+.Pp
+The
+.Fn getc_unlocked
+and
+.Fn getchar_unlocked
+functions are equivalent to
+.Fn getc
+and
+.Fn getchar
+respectively,
+except that the caller is responsible for locking the stream
+with
+.Xr flockfile 3
+before calling them.
+These functions may be used to avoid the overhead of locking the stream
+for each character, and to avoid input being dispersed among multiple
+threads reading from the same stream.
+.Sh RETURN VALUES
+If successful, these routines return the next requested object
+from the
+.Fa stream .
+Character values are returned as an
+.Vt "unsigned char"
+converted to an
+.Vt int .
+If the stream is at end-of-file or a read error occurs,
+the routines return
+.Dv EOF .
+The routines
+.Xr feof 3
+and
+.Xr ferror 3
+must be used to distinguish between end-of-file and error.
+If an error occurs, the global variable
+.Va errno
+is set to indicate the error.
+The end-of-file condition is remembered, even on a terminal, and all
+subsequent attempts to read will return
+.Dv EOF
+until the condition is cleared with
+.Xr clearerr 3 .
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr flockfile 3 ,
+.Xr fopen 3 ,
+.Xr fread 3 ,
+.Xr getwc 3 ,
+.Xr putc 3 ,
+.Xr ungetc 3
+.Sh STANDARDS
+The
+.Fn fgetc ,
+.Fn getc ,
+and
+.Fn getchar
+functions
+conform to
+.St -isoC .
+The
+.Fn getc_unlocked
+and
+.Fn getchar_unlocked
+functions conform to
+.St -p1003.1-2001 .
+.Sh BUGS
+Since
+.Dv EOF
+is a valid integer value,
+.Xr feof 3
+and
+.Xr ferror 3
+must be used to check for failure after calling
+.Fn getw .
+The size and byte order of an
+.Vt int
+varies from one machine to another, and
+.Fn getw
+is not recommended for portable applications.
diff --git a/lib/libc/stdio/getc.c b/lib/libc/stdio/getc.c
new file mode 100644
index 0000000..5c94e60
--- /dev/null
+++ b/lib/libc/stdio/getc.c
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getc.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+#undef getc
+#undef getc_unlocked
+
+int
+getc(FILE *fp)
+{
+ int retval;
+ FLOCKFILE(fp);
+ /* Orientation set by __sgetc() when buffer is empty. */
+ /* ORIENT(fp, -1); */
+ retval = __sgetc(fp);
+ FUNLOCKFILE(fp);
+ return (retval);
+}
+
+int
+getc_unlocked(FILE *fp)
+{
+
+ return (__sgetc(fp));
+}
diff --git a/lib/libc/stdio/getchar.c b/lib/libc/stdio/getchar.c
new file mode 100644
index 0000000..90c84ab
--- /dev/null
+++ b/lib/libc/stdio/getchar.c
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getchar.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * A subroutine version of the macro getchar.
+ */
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "local.h"
+#include "libc_private.h"
+
+#undef getchar
+#undef getchar_unlocked
+
+int
+getchar()
+{
+ int retval;
+ FLOCKFILE(stdin);
+ /* Orientation set by __sgetc() when buffer is empty. */
+ /* ORIENT(stdin, -1); */
+ retval = __sgetc(stdin);
+ FUNLOCKFILE(stdin);
+ return (retval);
+}
+
+int
+getchar_unlocked(void)
+{
+
+ return (__sgetc(stdin));
+}
diff --git a/lib/libc/stdio/getdelim.c b/lib/libc/stdio/getdelim.c
new file mode 100644
index 0000000..d7d5627
--- /dev/null
+++ b/lib/libc/stdio/getdelim.c
@@ -0,0 +1,160 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+#include "local.h"
+
+static inline size_t
+p2roundup(size_t n)
+{
+
+ if (!powerof2(n)) {
+ n--;
+ n |= n >> 1;
+ n |= n >> 2;
+ n |= n >> 4;
+ n |= n >> 8;
+ n |= n >> 16;
+#if SIZE_T_MAX > 0xffffffffU
+ n |= n >> 32;
+#endif
+ n++;
+ }
+ return (n);
+}
+
+/*
+ * Expand *linep to hold len bytes (up to SSIZE_MAX + 1).
+ */
+static inline int
+expandtofit(char ** __restrict linep, size_t len, size_t * __restrict capp)
+{
+ char *newline;
+ size_t newcap;
+
+ if (len > (size_t)SSIZE_MAX + 1) {
+ errno = EOVERFLOW;
+ return (-1);
+ }
+ if (len > *capp) {
+ if (len == (size_t)SSIZE_MAX + 1) /* avoid overflow */
+ newcap = (size_t)SSIZE_MAX + 1;
+ else
+ newcap = p2roundup(len);
+ newline = realloc(*linep, newcap);
+ if (newline == NULL)
+ return (-1);
+ *capp = newcap;
+ *linep = newline;
+ }
+ return (0);
+}
+
+/*
+ * Append the src buffer to the *dstp buffer. The buffers are of
+ * length srclen and *dstlenp, respectively, and dst has space for
+ * *dstlenp bytes. After the call, *dstlenp and *dstcapp are updated
+ * appropriately, and *dstp is reallocated if needed. Returns 0 on
+ * success, -1 on allocation failure.
+ */
+static int
+sappend(char ** __restrict dstp, size_t * __restrict dstlenp,
+ size_t * __restrict dstcapp, char * __restrict src, size_t srclen)
+{
+
+ /* ensure room for srclen + dstlen + terminating NUL */
+ if (expandtofit(dstp, srclen + *dstlenp + 1, dstcapp))
+ return (-1);
+ memcpy(*dstp + *dstlenp, src, srclen);
+ *dstlenp += srclen;
+ return (0);
+}
+
+ssize_t
+getdelim(char ** __restrict linep, size_t * __restrict linecapp, int delim,
+ FILE * __restrict fp)
+{
+ u_char *endp;
+ size_t linelen;
+
+ FLOCKFILE(fp);
+ ORIENT(fp, -1);
+
+ if (linep == NULL || linecapp == NULL) {
+ errno = EINVAL;
+ goto error;
+ }
+
+ if (*linep == NULL)
+ *linecapp = 0;
+
+ if (fp->_r <= 0 && __srefill(fp)) {
+ /* If fp is at EOF already, we just need space for the NUL. */
+ if (__sferror(fp) || expandtofit(linep, 1, linecapp))
+ goto error;
+ FUNLOCKFILE(fp);
+ (*linep)[0] = '\0';
+ return (-1);
+ }
+
+ linelen = 0;
+ while ((endp = memchr(fp->_p, delim, fp->_r)) == NULL) {
+ if (sappend(linep, &linelen, linecapp, fp->_p, fp->_r))
+ goto error;
+ if (__srefill(fp)) {
+ if (__sferror(fp))
+ goto error;
+ goto done; /* hit EOF */
+ }
+ }
+ endp++; /* snarf the delimiter, too */
+ if (sappend(linep, &linelen, linecapp, fp->_p, endp - fp->_p))
+ goto error;
+ fp->_r -= endp - fp->_p;
+ fp->_p = endp;
+done:
+ /* Invariant: *linep has space for at least linelen+1 bytes. */
+ (*linep)[linelen] = '\0';
+ FUNLOCKFILE(fp);
+ return (linelen);
+
+error:
+ fp->_flags |= __SERR;
+ FUNLOCKFILE(fp);
+ return (-1);
+}
diff --git a/lib/libc/stdio/getline.3 b/lib/libc/stdio/getline.3
new file mode 100644
index 0000000..6061bfc
--- /dev/null
+++ b/lib/libc/stdio/getline.3
@@ -0,0 +1,165 @@
+.\" Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 30, 2010
+.Dt GETLINE 3
+.Os
+.Sh NAME
+.Nm getdelim ,
+.Nm getline
+.Nd get a line from a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd "#define _WITH_GETLINE"
+.In stdio.h
+.Ft ssize_t
+.Fn getdelim "char ** restrict linep" "size_t * restrict linecapp" "int delimiter" " FILE * restrict stream"
+.Ft ssize_t
+.Fn getline "char ** restrict linep" "size_t * restrict linecapp" " FILE * restrict stream"
+.Sh DESCRIPTION
+The
+.Fn getdelim
+function reads a line from
+.Fa stream ,
+delimited by the character
+.Fa delimiter .
+The
+.Fn getline
+function is equivalent to
+.Fn getdelim
+with the newline character as the delimiter.
+The delimiter character is included as part of the line, unless
+the end of the file is reached.
+.Pp
+The caller may provide a pointer to a malloced buffer for the line in
+.Fa *linep ,
+and the capacity of that buffer in
+.Fa *linecapp .
+These functions expand the buffer as needed, as if via
+.Fn realloc .
+If
+.Fa linep
+points to a
+.Dv NULL
+pointer, a new buffer will be allocated.
+In either case,
+.Fa *linep
+and
+.Fa *linecapp
+will be updated accordingly.
+.Sh RETURN VALUES
+The
+.Fn getdelim
+and
+.Fn getline
+functions return the number of characters written, excluding the
+terminating
+.Dv NUL
+character.
+The value \-1 is returned if an error occurs, or if end-of-file is reached.
+.Sh EXAMPLES
+The following code fragment reads lines from a file and
+writes them to standard output.
+The
+.Fn fwrite
+function is used in case the line contains embedded
+.Dv NUL
+characters.
+.Bd -literal -offset indent
+char *line = NULL;
+size_t linecap = 0;
+ssize_t linelen;
+while ((linelen = getline(&line, &linecap, fp)) > 0)
+ fwrite(line, linelen, 1, stdout);
+.Ed
+.Sh COMPATIBILITY
+Many application writers used the name
+.Va getline
+before the
+.Fn getline
+function was introduced in
+.St -p1003.1 ,
+so a prototype is not provided by default in order to avoid
+compatibility problems.
+Applications that wish to use the
+.Fn getline
+function described herein should either request a strict
+.St -p1003.1-2008
+environment by defining the macro
+.Dv _POSIX_C_SOURCE
+to the value 200809 or greater, or by defining the macro
+.Dv _WITH_GETLINE ,
+prior to the inclusion of
+.In stdio.h .
+For compatibility with GNU libc, defining either
+.Dv _BSD_SOURCE
+or
+.Dv _GNU_SOURCE
+prior to the inclusion of
+.In stdio.h
+will also make
+.Fn getline
+available.
+.Sh ERRORS
+These functions may fail if:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+Either
+.Fa linep
+or
+.Fa linecapp
+is
+.Dv NULL .
+.It Bq Er EOVERFLOW
+No delimiter was found in the first
+.Dv SSIZE_MAX
+characters.
+.El
+.Pp
+These functions may also fail due to any of the errors specified for
+.Fn fgets
+and
+.Fn malloc .
+.Sh SEE ALSO
+.Xr fgetln 3 ,
+.Xr fgets 3 ,
+.Xr malloc 3
+.Sh STANDARDS
+The
+.Fn getdelim
+and
+.Fn getline
+functions conform to
+.St -p1003.1-2008 .
+.Sh HISTORY
+These routines first appeared in
+.Fx 8.0 .
+.Sh BUGS
+There are no wide character versions of
+.Fn getdelim
+or
+.Fn getline .
diff --git a/lib/libc/stdio/getline.c b/lib/libc/stdio/getline.c
new file mode 100644
index 0000000..3f35520
--- /dev/null
+++ b/lib/libc/stdio/getline.c
@@ -0,0 +1,39 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define _WITH_GETLINE
+#include <stdio.h>
+
+ssize_t
+getline(char ** __restrict linep, size_t * __restrict linecapp,
+ FILE * __restrict fp)
+{
+
+ return (getdelim(linep, linecapp, '\n', fp));
+}
diff --git a/lib/libc/stdio/gets.c b/lib/libc/stdio/gets.c
new file mode 100644
index 0000000..6a617ce
--- /dev/null
+++ b/lib/libc/stdio/gets.c
@@ -0,0 +1,77 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)gets.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <unistd.h>
+#include <stdio.h>
+#include <sys/cdefs.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+__warn_references(gets, "warning: this program uses gets(), which is unsafe.");
+
+char *
+gets(buf)
+ char *buf;
+{
+ int c;
+ char *s;
+ static int warned;
+ static char w[] =
+ "warning: this program uses gets(), which is unsafe.\n";
+
+ FLOCKFILE(stdin);
+ ORIENT(stdin, -1);
+ if (!warned) {
+ (void) _write(STDERR_FILENO, w, sizeof(w) - 1);
+ warned = 1;
+ }
+ for (s = buf; (c = __sgetc(stdin)) != '\n';)
+ if (c == EOF)
+ if (s == buf) {
+ FUNLOCKFILE(stdin);
+ return (NULL);
+ } else
+ break;
+ else
+ *s++ = c;
+ *s = 0;
+ FUNLOCKFILE(stdin);
+ return (buf);
+}
diff --git a/lib/libc/stdio/getw.c b/lib/libc/stdio/getw.c
new file mode 100644
index 0000000..d2c6942
--- /dev/null
+++ b/lib/libc/stdio/getw.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getw.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+
+int
+getw(fp)
+ FILE *fp;
+{
+ int x;
+
+ return (fread((void *)&x, sizeof(x), 1, fp) == 1 ? x : EOF);
+}
diff --git a/lib/libc/stdio/getwc.3 b/lib/libc/stdio/getwc.3
new file mode 100644
index 0000000..bc4218a
--- /dev/null
+++ b/lib/libc/stdio/getwc.3
@@ -0,0 +1,114 @@
+.\" $NetBSD: getwc.3,v 1.3 2002/02/07 07:00:26 ross Exp $
+.\"
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getc.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd March 3, 2004
+.Dt GETWC 3
+.Os
+.Sh NAME
+.Nm fgetwc ,
+.Nm getwc ,
+.Nm getwchar
+.Nd get next wide character from input stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.In wchar.h
+.Ft wint_t
+.Fn fgetwc "FILE *stream"
+.Ft wint_t
+.Fn getwc "FILE *stream"
+.Ft wint_t
+.Fn getwchar void
+.Sh DESCRIPTION
+The
+.Fn fgetwc
+function
+obtains the next input wide character (if present) from the stream pointed at by
+.Fa stream ,
+or the next character pushed back on the stream via
+.Xr ungetwc 3 .
+.Pp
+The
+.Fn getwc
+function
+acts essentially identically to
+.Fn fgetwc .
+.Pp
+The
+.Fn getwchar
+function
+is equivalent to
+.Fn getwc
+with the argument
+.Dv stdin .
+.Sh RETURN VALUES
+If successful, these routines return the next wide character
+from the
+.Fa stream .
+If the stream is at end-of-file or a read error occurs,
+the routines return
+.Dv WEOF .
+The routines
+.Xr feof 3
+and
+.Xr ferror 3
+must be used to distinguish between end-of-file and error.
+If an error occurs, the global variable
+.Va errno
+is set to indicate the error.
+The end-of-file condition is remembered, even on a terminal, and all
+subsequent attempts to read will return
+.Dv WEOF
+until the condition is cleared with
+.Xr clearerr 3 .
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr fopen 3 ,
+.Xr fread 3 ,
+.Xr getc 3 ,
+.Xr putwc 3 ,
+.Xr stdio 3 ,
+.Xr ungetwc 3
+.Sh STANDARDS
+The
+.Fn fgetwc ,
+.Fn getwc
+and
+.Fn getwchar
+functions
+conform to
+.St -isoC-99 .
diff --git a/lib/libc/stdio/getwc.c b/lib/libc/stdio/getwc.c
new file mode 100644
index 0000000..666350b
--- /dev/null
+++ b/lib/libc/stdio/getwc.c
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <wchar.h>
+#include <xlocale.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+#undef getwc
+
+/*
+ * Synonym for fgetwc(). The only difference is that getwc(), if it is a
+ * macro, may evaluate `fp' more than once.
+ */
+wint_t
+getwc(FILE *fp)
+{
+
+ return (fgetwc(fp));
+}
+wint_t
+getwc_l(FILE *fp, locale_t locale)
+{
+
+ return (fgetwc_l(fp, locale));
+}
diff --git a/lib/libc/stdio/getwchar.c b/lib/libc/stdio/getwchar.c
new file mode 100644
index 0000000..bc3b8a6
--- /dev/null
+++ b/lib/libc/stdio/getwchar.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <wchar.h>
+#include <xlocale.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+#undef getwchar
+
+/*
+ * Synonym for fgetwc(stdin).
+ */
+wint_t
+getwchar(void)
+{
+ return (fgetwc(stdin));
+}
+wint_t
+getwchar_l(locale_t locale)
+{
+ return (fgetwc_l(stdin, locale));
+}
diff --git a/lib/libc/stdio/glue.h b/lib/libc/stdio/glue.h
new file mode 100644
index 0000000..1fef140
--- /dev/null
+++ b/lib/libc/stdio/glue.h
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)glue.h 8.1 (Berkeley) 6/4/93
+ * $FreeBSD$
+ */
+
+/*
+ * The first few FILEs are statically allocated; others are dynamically
+ * allocated and linked in via this glue structure.
+ */
+struct glue {
+ struct glue *next;
+ int niobs;
+ FILE *iobs;
+};
+extern struct glue __sglue;
diff --git a/lib/libc/stdio/local.h b/lib/libc/stdio/local.h
new file mode 100644
index 0000000..8b37f0d
--- /dev/null
+++ b/lib/libc/stdio/local.h
@@ -0,0 +1,133 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)local.h 8.3 (Berkeley) 7/3/94
+ * $FreeBSD$
+ */
+
+#include <sys/types.h> /* for off_t */
+#include <pthread.h>
+#include <string.h>
+#include <wchar.h>
+#include <locale.h>
+
+/*
+ * Information local to this implementation of stdio,
+ * in particular, macros and private variables.
+ */
+
+extern int _sread(FILE *, char *, int);
+extern int _swrite(FILE *, char const *, int);
+extern fpos_t _sseek(FILE *, fpos_t, int);
+extern int _ftello(FILE *, fpos_t *);
+extern int _fseeko(FILE *, off_t, int, int);
+extern int __fflush(FILE *fp);
+extern void __fcloseall(void);
+extern wint_t __fgetwc(FILE *, locale_t);
+extern wint_t __fputwc(wchar_t, FILE *, locale_t);
+extern int __sflush(FILE *);
+extern FILE *__sfp(void);
+extern int __slbexpand(FILE *, size_t);
+extern int __srefill(FILE *);
+extern int __sread(void *, char *, int);
+extern int __swrite(void *, char const *, int);
+extern fpos_t __sseek(void *, fpos_t, int);
+extern int __sclose(void *);
+extern void __sinit(void);
+extern void _cleanup(void);
+extern void __smakebuf(FILE *);
+extern int __swhatbuf(FILE *, size_t *, int *);
+extern int _fwalk(int (*)(FILE *));
+extern int __svfscanf(FILE *, locale_t, const char *, __va_list);
+extern int __swsetup(FILE *);
+extern int __sflags(const char *, int *);
+extern int __ungetc(int, FILE *);
+extern wint_t __ungetwc(wint_t, FILE *, locale_t);
+extern int __vfprintf(FILE *, locale_t, const char *, __va_list);
+extern int __vfscanf(FILE *, const char *, __va_list);
+extern int __vfwprintf(FILE *, locale_t, const wchar_t *, __va_list);
+extern int __vfwscanf(FILE * __restrict, locale_t, const wchar_t * __restrict,
+ __va_list);
+extern size_t __fread(void * __restrict buf, size_t size, size_t count,
+ FILE * __restrict fp);
+extern int __sdidinit;
+
+
+/*
+ * Prepare the given FILE for writing, and return 0 iff it
+ * can be written now. Otherwise, return EOF and set errno.
+ */
+#define prepwrite(fp) \
+ ((((fp)->_flags & __SWR) == 0 || \
+ ((fp)->_bf._base == NULL && ((fp)->_flags & __SSTR) == 0)) && \
+ __swsetup(fp))
+
+/*
+ * Test whether the given stdio file has an active ungetc buffer;
+ * release such a buffer, without restoring ordinary unread data.
+ */
+#define HASUB(fp) ((fp)->_ub._base != NULL)
+#define FREEUB(fp) { \
+ if ((fp)->_ub._base != (fp)->_ubuf) \
+ free((char *)(fp)->_ub._base); \
+ (fp)->_ub._base = NULL; \
+}
+
+/*
+ * test for an fgetln() buffer.
+ */
+#define HASLB(fp) ((fp)->_lb._base != NULL)
+#define FREELB(fp) { \
+ free((char *)(fp)->_lb._base); \
+ (fp)->_lb._base = NULL; \
+}
+
+/*
+ * Structure initializations for 'fake' FILE objects.
+ */
+#define FAKE_FILE { \
+ ._file = -1, \
+ ._fl_mutex = PTHREAD_MUTEX_INITIALIZER, \
+}
+
+/*
+ * Set the orientation for a stream. If o > 0, the stream has wide-
+ * orientation. If o < 0, the stream has byte-orientation.
+ */
+#define ORIENT(fp, o) do { \
+ if ((fp)->_orientation == 0) \
+ (fp)->_orientation = (o); \
+} while (0)
diff --git a/lib/libc/stdio/makebuf.c b/lib/libc/stdio/makebuf.c
new file mode 100644
index 0000000..92e6c4b
--- /dev/null
+++ b/lib/libc/stdio/makebuf.c
@@ -0,0 +1,120 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)makebuf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+#include "local.h"
+
+/*
+ * Allocate a file buffer, or switch to unbuffered I/O.
+ * Per the ANSI C standard, ALL tty devices default to line buffered.
+ *
+ * As a side effect, we set __SOPT or __SNPT (en/dis-able fseek
+ * optimisation) right after the _fstat() that finds the buffer size.
+ */
+void
+__smakebuf(fp)
+ FILE *fp;
+{
+ void *p;
+ int flags;
+ size_t size;
+ int couldbetty;
+
+ if (fp->_flags & __SNBF) {
+ fp->_bf._base = fp->_p = fp->_nbuf;
+ fp->_bf._size = 1;
+ return;
+ }
+ flags = __swhatbuf(fp, &size, &couldbetty);
+ if ((p = malloc(size)) == NULL) {
+ fp->_flags |= __SNBF;
+ fp->_bf._base = fp->_p = fp->_nbuf;
+ fp->_bf._size = 1;
+ return;
+ }
+ __cleanup = _cleanup;
+ flags |= __SMBF;
+ fp->_bf._base = fp->_p = p;
+ fp->_bf._size = size;
+ if (couldbetty && isatty(fp->_file))
+ flags |= __SLBF;
+ fp->_flags |= flags;
+}
+
+/*
+ * Internal routine to determine `proper' buffering for a file.
+ */
+int
+__swhatbuf(fp, bufsize, couldbetty)
+ FILE *fp;
+ size_t *bufsize;
+ int *couldbetty;
+{
+ struct stat st;
+
+ if (fp->_file < 0 || _fstat(fp->_file, &st) < 0) {
+ *couldbetty = 0;
+ *bufsize = BUFSIZ;
+ return (__SNPT);
+ }
+
+ /* could be a tty iff it is a character device */
+ *couldbetty = (st.st_mode & S_IFMT) == S_IFCHR;
+ if (st.st_blksize <= 0) {
+ *bufsize = BUFSIZ;
+ return (__SNPT);
+ }
+
+ /*
+ * Optimise fseek() only if it is a regular file. (The test for
+ * __sseek is mainly paranoia.) It is safe to set _blksize
+ * unconditionally; it will only be used if __SOPT is also set.
+ */
+ *bufsize = st.st_blksize;
+ fp->_blksize = st.st_blksize;
+ return ((st.st_mode & S_IFMT) == S_IFREG && fp->_seek == __sseek ?
+ __SOPT : __SNPT);
+}
diff --git a/lib/libc/stdio/mktemp.3 b/lib/libc/stdio/mktemp.3
new file mode 100644
index 0000000..b51a177
--- /dev/null
+++ b/lib/libc/stdio/mktemp.3
@@ -0,0 +1,238 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)mktemp.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd March 4, 2012
+.Dt MKTEMP 3
+.Os
+.Sh NAME
+.Nm mktemp
+.Nd make temporary file name (unique)
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft char *
+.Fn mktemp "char *template"
+.Ft int
+.Fn mkstemp "char *template"
+.Ft int
+.Fn mkstemps "char *template" "int suffixlen"
+.Ft char *
+.Fn mkdtemp "char *template"
+.Sh DESCRIPTION
+The
+.Fn mktemp
+function
+takes the given file name template and overwrites a portion of it
+to create a file name.
+This file name is guaranteed not to exist at the time of function invocation
+and is suitable for use
+by the application.
+The template may be any file name with some number of
+.Ql X Ns s
+appended
+to it, for example
+.Pa /tmp/temp.XXXXXX .
+The trailing
+.Ql X Ns s
+are replaced with a
+unique alphanumeric combination.
+The number of unique file names
+.Fn mktemp
+can return depends on the number of
+.Ql X Ns s
+provided; six
+.Ql X Ns s
+will
+result in
+.Fn mktemp
+selecting one of 56800235584 (62 ** 6) possible temporary file names.
+.Pp
+The
+.Fn mkstemp
+function
+makes the same replacement to the template and creates the template file,
+mode 0600, returning a file descriptor opened for reading and writing.
+This avoids the race between testing for a file's existence and opening it
+for use.
+.Pp
+The
+.Fn mkstemps
+function acts the same as
+.Fn mkstemp ,
+except it permits a suffix to exist in the template.
+The template should be of the form
+.Pa /tmp/tmpXXXXXXsuffix .
+The
+.Fn mkstemps
+function
+is told the length of the suffix string.
+.Pp
+The
+.Fn mkdtemp
+function makes the same replacement to the template as in
+.Fn mktemp
+and creates the template directory, mode 0700.
+.Sh RETURN VALUES
+The
+.Fn mktemp
+and
+.Fn mkdtemp
+functions return a pointer to the template on success and
+.Dv NULL
+on failure.
+The
+.Fn mkstemp
+and
+.Fn mkstemps
+functions
+return \-1 if no suitable file could be created.
+If either call fails an error code is placed in the global variable
+.Va errno .
+.Sh ERRORS
+The
+.Fn mkstemp ,
+.Fn mkstemps
+and
+.Fn mkdtemp
+functions
+may set
+.Va errno
+to one of the following values:
+.Bl -tag -width Er
+.It Bq Er ENOTDIR
+The pathname portion of the template is not an existing directory.
+.El
+.Pp
+The
+.Fn mkstemp ,
+.Fn mkstemps
+and
+.Fn mkdtemp
+functions
+may also set
+.Va errno
+to any value specified by the
+.Xr stat 2
+function.
+.Pp
+The
+.Fn mkstemp
+and
+.Fn mkstemps
+functions
+may also set
+.Va errno
+to any value specified by the
+.Xr open 2
+function.
+.Pp
+The
+.Fn mkdtemp
+function
+may also set
+.Va errno
+to any value specified by the
+.Xr mkdir 2
+function.
+.Sh NOTES
+A common problem that results in a core dump is that the programmer
+passes in a read-only string to
+.Fn mktemp ,
+.Fn mkstemp ,
+.Fn mkstemps
+or
+.Fn mkdtemp .
+This is common with programs that were developed before
+.St -isoC
+compilers were common.
+For example, calling
+.Fn mkstemp
+with an argument of
+.Qq /tmp/tempfile.XXXXXX
+will result in a core dump due to
+.Fn mkstemp
+attempting to modify the string constant that was given.
+.Sh SEE ALSO
+.Xr chmod 2 ,
+.Xr getpid 2 ,
+.Xr mkdir 2 ,
+.Xr open 2 ,
+.Xr stat 2
+.Sh HISTORY
+A
+.Fn mktemp
+function appeared in
+.At v7 .
+The
+.Fn mkstemp
+function appeared in
+.Bx 4.4 .
+The
+.Fn mkdtemp
+function first appeared in
+.Ox 2.2 ,
+and later in
+.Fx 3.2 .
+The
+.Fn mkstemps
+function first appeared in
+.Ox 2.4 ,
+and later in
+.Fx 3.4 .
+.Sh BUGS
+This family of functions produces filenames which can be guessed,
+though the risk is minimized when large numbers of
+.Ql X Ns s
+are used to
+increase the number of possible temporary filenames.
+This makes the race in
+.Fn mktemp ,
+between testing for a file's existence (in the
+.Fn mktemp
+function call)
+and opening it for use
+(later in the user application)
+particularly dangerous from a security perspective.
+Whenever it is possible,
+.Fn mkstemp
+should be used instead, since it does not have the race condition.
+If
+.Fn mkstemp
+cannot be used, the filename created by
+.Fn mktemp
+should be created using the
+.Dv O_EXCL
+flag to
+.Xr open 2
+and the return status of the call should be tested for failure.
+This will ensure that the program does not continue blindly
+in the event that an attacker has already created the file
+with the intention of manipulating or reading its contents.
diff --git a/lib/libc/stdio/mktemp.c b/lib/libc/stdio/mktemp.c
new file mode 100644
index 0000000..a30b930
--- /dev/null
+++ b/lib/libc/stdio/mktemp.c
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)mktemp.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+char *_mktemp(char *);
+
+static int _gettemp(char *, int *, int, int);
+
+static const unsigned char padchar[] =
+"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
+
+int
+mkstemps(path, slen)
+ char *path;
+ int slen;
+{
+ int fd;
+
+ return (_gettemp(path, &fd, 0, slen) ? fd : -1);
+}
+
+int
+mkstemp(path)
+ char *path;
+{
+ int fd;
+
+ return (_gettemp(path, &fd, 0, 0) ? fd : -1);
+}
+
+char *
+mkdtemp(path)
+ char *path;
+{
+ return (_gettemp(path, (int *)NULL, 1, 0) ? path : (char *)NULL);
+}
+
+char *
+_mktemp(path)
+ char *path;
+{
+ return (_gettemp(path, (int *)NULL, 0, 0) ? path : (char *)NULL);
+}
+
+__warn_references(mktemp,
+ "warning: mktemp() possibly used unsafely; consider using mkstemp()");
+
+char *
+mktemp(path)
+ char *path;
+{
+ return (_mktemp(path));
+}
+
+static int
+_gettemp(path, doopen, domkdir, slen)
+ char *path;
+ int *doopen;
+ int domkdir;
+ int slen;
+{
+ char *start, *trv, *suffp, *carryp;
+ char *pad;
+ struct stat sbuf;
+ int rval;
+ uint32_t rand;
+ char carrybuf[MAXPATHLEN];
+
+ if ((doopen != NULL && domkdir) || slen < 0) {
+ errno = EINVAL;
+ return (0);
+ }
+
+ for (trv = path; *trv != '\0'; ++trv)
+ ;
+ if (trv - path >= MAXPATHLEN) {
+ errno = ENAMETOOLONG;
+ return (0);
+ }
+ trv -= slen;
+ suffp = trv;
+ --trv;
+ if (trv < path || NULL != strchr(suffp, '/')) {
+ errno = EINVAL;
+ return (0);
+ }
+
+ /* Fill space with random characters */
+ while (trv >= path && *trv == 'X') {
+ rand = arc4random_uniform(sizeof(padchar) - 1);
+ *trv-- = padchar[rand];
+ }
+ start = trv + 1;
+
+ /* save first combination of random characters */
+ memcpy(carrybuf, start, suffp - start);
+
+ /*
+ * check the target directory.
+ */
+ if (doopen != NULL || domkdir) {
+ for (; trv > path; --trv) {
+ if (*trv == '/') {
+ *trv = '\0';
+ rval = stat(path, &sbuf);
+ *trv = '/';
+ if (rval != 0)
+ return (0);
+ if (!S_ISDIR(sbuf.st_mode)) {
+ errno = ENOTDIR;
+ return (0);
+ }
+ break;
+ }
+ }
+ }
+
+ for (;;) {
+ if (doopen) {
+ if ((*doopen =
+ _open(path, O_CREAT|O_EXCL|O_RDWR, 0600)) >= 0)
+ return (1);
+ if (errno != EEXIST)
+ return (0);
+ } else if (domkdir) {
+ if (mkdir(path, 0700) == 0)
+ return (1);
+ if (errno != EEXIST)
+ return (0);
+ } else if (lstat(path, &sbuf))
+ return (errno == ENOENT);
+
+ /* If we have a collision, cycle through the space of filenames */
+ for (trv = start, carryp = carrybuf;;) {
+ /* have we tried all possible permutations? */
+ if (trv == suffp)
+ return (0); /* yes - exit with EEXIST */
+ pad = strchr(padchar, *trv);
+ if (pad == NULL) {
+ /* this should never happen */
+ errno = EIO;
+ return (0);
+ }
+ /* increment character */
+ *trv = (*++pad == '\0') ? padchar[0] : *pad;
+ /* carry to next position? */
+ if (*trv == *carryp) {
+ /* increment position and loop */
+ ++trv;
+ ++carryp;
+ } else {
+ /* try with new name */
+ break;
+ }
+ }
+ }
+ /*NOTREACHED*/
+}
diff --git a/lib/libc/stdio/perror.c b/lib/libc/stdio/perror.c
new file mode 100644
index 0000000..9f18551
--- /dev/null
+++ b/lib/libc/stdio/perror.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)perror.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/uio.h>
+#include <unistd.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+void
+perror(s)
+ const char *s;
+{
+ char msgbuf[NL_TEXTMAX];
+ struct iovec *v;
+ struct iovec iov[4];
+
+ v = iov;
+ if (s != NULL && *s != '\0') {
+ v->iov_base = (char *)s;
+ v->iov_len = strlen(s);
+ v++;
+ v->iov_base = ": ";
+ v->iov_len = 2;
+ v++;
+ }
+ strerror_r(errno, msgbuf, sizeof(msgbuf));
+ v->iov_base = msgbuf;
+ v->iov_len = strlen(v->iov_base);
+ v++;
+ v->iov_base = "\n";
+ v->iov_len = 1;
+ FLOCKFILE(stderr);
+ __sflush(stderr);
+ (void)_writev(stderr->_file, iov, (v - iov) + 1);
+ stderr->_flags &= ~__SOFF;
+ FUNLOCKFILE(stderr);
+}
diff --git a/lib/libc/stdio/printf-pos.c b/lib/libc/stdio/printf-pos.c
new file mode 100644
index 0000000..c42bd85
--- /dev/null
+++ b/lib/libc/stdio/printf-pos.c
@@ -0,0 +1,752 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * This is the code responsible for handling positional arguments
+ * (%m$ and %m$.n$) for vfprintf() and vfwprintf().
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+
+#include "un-namespace.h"
+#include "printflocal.h"
+
+/*
+ * Type ids for argument type table.
+ */
+enum typeid {
+ T_UNUSED, TP_SHORT, T_INT, T_U_INT, TP_INT,
+ T_LONG, T_U_LONG, TP_LONG, T_LLONG, T_U_LLONG, TP_LLONG,
+ T_PTRDIFFT, TP_PTRDIFFT, T_SSIZET, T_SIZET, TP_SSIZET,
+ T_INTMAXT, T_UINTMAXT, TP_INTMAXT, TP_VOID, TP_CHAR, TP_SCHAR,
+ T_DOUBLE, T_LONG_DOUBLE, T_WINT, TP_WCHAR
+};
+
+/* An expandable array of types. */
+struct typetable {
+ enum typeid *table; /* table of types */
+ enum typeid stattable[STATIC_ARG_TBL_SIZE];
+ int tablesize; /* current size of type table */
+ int tablemax; /* largest used index in table */
+ int nextarg; /* 1-based argument index */
+};
+
+static int __grow_type_table(struct typetable *);
+static void build_arg_table (struct typetable *, va_list, union arg **);
+
+/*
+ * Initialize a struct typetable.
+ */
+static inline void
+inittypes(struct typetable *types)
+{
+ int n;
+
+ types->table = types->stattable;
+ types->tablesize = STATIC_ARG_TBL_SIZE;
+ types->tablemax = 0;
+ types->nextarg = 1;
+ for (n = 0; n < STATIC_ARG_TBL_SIZE; n++)
+ types->table[n] = T_UNUSED;
+}
+
+/*
+ * struct typetable destructor.
+ */
+static inline void
+freetypes(struct typetable *types)
+{
+
+ if (types->table != types->stattable)
+ free (types->table);
+}
+
+/*
+ * Ensure that there is space to add a new argument type to the type table.
+ * Expand the table if necessary. Returns 0 on success.
+ */
+static inline int
+_ensurespace(struct typetable *types)
+{
+
+ if (types->nextarg >= types->tablesize) {
+ if (__grow_type_table(types))
+ return (-1);
+ }
+ if (types->nextarg > types->tablemax)
+ types->tablemax = types->nextarg;
+ return (0);
+}
+
+/*
+ * Add an argument type to the table, expanding if necessary.
+ * Returns 0 on success.
+ */
+static inline int
+addtype(struct typetable *types, enum typeid type)
+{
+
+ if (_ensurespace(types))
+ return (-1);
+ types->table[types->nextarg++] = type;
+ return (0);
+}
+
+static inline int
+addsarg(struct typetable *types, int flags)
+{
+
+ if (_ensurespace(types))
+ return (-1);
+ if (flags & INTMAXT)
+ types->table[types->nextarg++] = T_INTMAXT;
+ else if (flags & SIZET)
+ types->table[types->nextarg++] = T_SSIZET;
+ else if (flags & PTRDIFFT)
+ types->table[types->nextarg++] = T_PTRDIFFT;
+ else if (flags & LLONGINT)
+ types->table[types->nextarg++] = T_LLONG;
+ else if (flags & LONGINT)
+ types->table[types->nextarg++] = T_LONG;
+ else
+ types->table[types->nextarg++] = T_INT;
+ return (0);
+}
+
+static inline int
+adduarg(struct typetable *types, int flags)
+{
+
+ if (_ensurespace(types))
+ return (-1);
+ if (flags & INTMAXT)
+ types->table[types->nextarg++] = T_UINTMAXT;
+ else if (flags & SIZET)
+ types->table[types->nextarg++] = T_SIZET;
+ else if (flags & PTRDIFFT)
+ types->table[types->nextarg++] = T_SIZET;
+ else if (flags & LLONGINT)
+ types->table[types->nextarg++] = T_U_LLONG;
+ else if (flags & LONGINT)
+ types->table[types->nextarg++] = T_U_LONG;
+ else
+ types->table[types->nextarg++] = T_U_INT;
+ return (0);
+}
+
+/*
+ * Add * arguments to the type array.
+ */
+static inline int
+addaster(struct typetable *types, char **fmtp)
+{
+ char *cp;
+ int n2;
+
+ n2 = 0;
+ cp = *fmtp;
+ while (is_digit(*cp)) {
+ n2 = 10 * n2 + to_digit(*cp);
+ cp++;
+ }
+ if (*cp == '$') {
+ int hold = types->nextarg;
+ types->nextarg = n2;
+ if (addtype(types, T_INT))
+ return (-1);
+ types->nextarg = hold;
+ *fmtp = ++cp;
+ } else {
+ if (addtype(types, T_INT))
+ return (-1);
+ }
+ return (0);
+}
+
+static inline int
+addwaster(struct typetable *types, wchar_t **fmtp)
+{
+ wchar_t *cp;
+ int n2;
+
+ n2 = 0;
+ cp = *fmtp;
+ while (is_digit(*cp)) {
+ n2 = 10 * n2 + to_digit(*cp);
+ cp++;
+ }
+ if (*cp == '$') {
+ int hold = types->nextarg;
+ types->nextarg = n2;
+ if (addtype(types, T_INT))
+ return (-1);
+ types->nextarg = hold;
+ *fmtp = ++cp;
+ } else {
+ if (addtype(types, T_INT))
+ return (-1);
+ }
+ return (0);
+}
+
+/*
+ * Find all arguments when a positional parameter is encountered. Returns a
+ * table, indexed by argument number, of pointers to each arguments. The
+ * initial argument table should be an array of STATIC_ARG_TBL_SIZE entries.
+ * It will be replaces with a malloc-ed one if it overflows.
+ * Returns 0 on success. On failure, returns nonzero and sets errno.
+ */
+int
+__find_arguments (const char *fmt0, va_list ap, union arg **argtable)
+{
+ char *fmt; /* format string */
+ int ch; /* character from fmt */
+ int n; /* handy integer (short term usage) */
+ int error;
+ int flags; /* flags as above */
+ struct typetable types; /* table of types */
+
+ fmt = (char *)fmt0;
+ inittypes(&types);
+ error = 0;
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ while ((ch = *fmt) != '\0' && ch != '%')
+ fmt++;
+ if (ch == '\0')
+ goto done;
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ case '#':
+ goto rflag;
+ case '*':
+ if ((error = addaster(&types, &fmt)))
+ goto error;
+ goto rflag;
+ case '-':
+ case '+':
+ case '\'':
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ if ((error = addaster(&types, &fmt)))
+ goto error;
+ goto rflag;
+ }
+ while (is_digit(ch)) {
+ ch = *fmt++;
+ }
+ goto reswitch;
+ case '0':
+ goto rflag;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ do {
+ n = 10 * n + to_digit(ch);
+ ch = *fmt++;
+ } while (is_digit(ch));
+ if (ch == '$') {
+ types.nextarg = n;
+ goto rflag;
+ }
+ goto reswitch;
+#ifndef NO_FLOATING_POINT
+ case 'L':
+ flags |= LONGDBL;
+ goto rflag;
+#endif
+ case 'h':
+ if (flags & SHORTINT) {
+ flags &= ~SHORTINT;
+ flags |= CHARINT;
+ } else
+ flags |= SHORTINT;
+ goto rflag;
+ case 'j':
+ flags |= INTMAXT;
+ goto rflag;
+ case 'l':
+ if (flags & LONGINT) {
+ flags &= ~LONGINT;
+ flags |= LLONGINT;
+ } else
+ flags |= LONGINT;
+ goto rflag;
+ case 'q':
+ flags |= LLONGINT; /* not necessarily */
+ goto rflag;
+ case 't':
+ flags |= PTRDIFFT;
+ goto rflag;
+ case 'z':
+ flags |= SIZET;
+ goto rflag;
+ case 'C':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'c':
+ error = addtype(&types,
+ (flags & LONGINT) ? T_WINT : T_INT);
+ if (error)
+ goto error;
+ break;
+ case 'D':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
+ if ((error = addsarg(&types, flags)))
+ goto error;
+ break;
+#ifndef NO_FLOATING_POINT
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ error = addtype(&types,
+ (flags & LONGDBL) ? T_LONG_DOUBLE : T_DOUBLE);
+ if (error)
+ goto error;
+ break;
+#endif /* !NO_FLOATING_POINT */
+ case 'n':
+ if (flags & INTMAXT)
+ error = addtype(&types, TP_INTMAXT);
+ else if (flags & PTRDIFFT)
+ error = addtype(&types, TP_PTRDIFFT);
+ else if (flags & SIZET)
+ error = addtype(&types, TP_SSIZET);
+ else if (flags & LLONGINT)
+ error = addtype(&types, TP_LLONG);
+ else if (flags & LONGINT)
+ error = addtype(&types, TP_LONG);
+ else if (flags & SHORTINT)
+ error = addtype(&types, TP_SHORT);
+ else if (flags & CHARINT)
+ error = addtype(&types, TP_SCHAR);
+ else
+ error = addtype(&types, TP_INT);
+ if (error)
+ goto error;
+ continue; /* no output */
+ case 'O':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'o':
+ if ((error = adduarg(&types, flags)))
+ goto error;
+ break;
+ case 'p':
+ if ((error = addtype(&types, TP_VOID)))
+ goto error;
+ break;
+ case 'S':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 's':
+ error = addtype(&types,
+ (flags & LONGINT) ? TP_WCHAR : TP_CHAR);
+ if (error)
+ goto error;
+ break;
+ case 'U':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'u':
+ case 'X':
+ case 'x':
+ if ((error = adduarg(&types, flags)))
+ goto error;
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ break;
+ }
+ }
+done:
+ build_arg_table(&types, ap, argtable);
+error:
+ freetypes(&types);
+ return (error || *argtable == NULL);
+}
+
+/* wchar version of __find_arguments. */
+int
+__find_warguments (const wchar_t *fmt0, va_list ap, union arg **argtable)
+{
+ wchar_t *fmt; /* format string */
+ wchar_t ch; /* character from fmt */
+ int n; /* handy integer (short term usage) */
+ int error;
+ int flags; /* flags as above */
+ struct typetable types; /* table of types */
+
+ fmt = (wchar_t *)fmt0;
+ inittypes(&types);
+ error = 0;
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ while ((ch = *fmt) != '\0' && ch != '%')
+ fmt++;
+ if (ch == '\0')
+ goto done;
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ case '#':
+ goto rflag;
+ case '*':
+ if ((error = addwaster(&types, &fmt)))
+ goto error;
+ goto rflag;
+ case '-':
+ case '+':
+ case '\'':
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ if ((error = addwaster(&types, &fmt)))
+ goto error;
+ goto rflag;
+ }
+ while (is_digit(ch)) {
+ ch = *fmt++;
+ }
+ goto reswitch;
+ case '0':
+ goto rflag;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ do {
+ n = 10 * n + to_digit(ch);
+ ch = *fmt++;
+ } while (is_digit(ch));
+ if (ch == '$') {
+ types.nextarg = n;
+ goto rflag;
+ }
+ goto reswitch;
+#ifndef NO_FLOATING_POINT
+ case 'L':
+ flags |= LONGDBL;
+ goto rflag;
+#endif
+ case 'h':
+ if (flags & SHORTINT) {
+ flags &= ~SHORTINT;
+ flags |= CHARINT;
+ } else
+ flags |= SHORTINT;
+ goto rflag;
+ case 'j':
+ flags |= INTMAXT;
+ goto rflag;
+ case 'l':
+ if (flags & LONGINT) {
+ flags &= ~LONGINT;
+ flags |= LLONGINT;
+ } else
+ flags |= LONGINT;
+ goto rflag;
+ case 'q':
+ flags |= LLONGINT; /* not necessarily */
+ goto rflag;
+ case 't':
+ flags |= PTRDIFFT;
+ goto rflag;
+ case 'z':
+ flags |= SIZET;
+ goto rflag;
+ case 'C':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'c':
+ error = addtype(&types,
+ (flags & LONGINT) ? T_WINT : T_INT);
+ if (error)
+ goto error;
+ break;
+ case 'D':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
+ if ((error = addsarg(&types, flags)))
+ goto error;
+ break;
+#ifndef NO_FLOATING_POINT
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'g':
+ case 'G':
+ error = addtype(&types,
+ (flags & LONGDBL) ? T_LONG_DOUBLE : T_DOUBLE);
+ if (error)
+ goto error;
+ break;
+#endif /* !NO_FLOATING_POINT */
+ case 'n':
+ if (flags & INTMAXT)
+ error = addtype(&types, TP_INTMAXT);
+ else if (flags & PTRDIFFT)
+ error = addtype(&types, TP_PTRDIFFT);
+ else if (flags & SIZET)
+ error = addtype(&types, TP_SSIZET);
+ else if (flags & LLONGINT)
+ error = addtype(&types, TP_LLONG);
+ else if (flags & LONGINT)
+ error = addtype(&types, TP_LONG);
+ else if (flags & SHORTINT)
+ error = addtype(&types, TP_SHORT);
+ else if (flags & CHARINT)
+ error = addtype(&types, TP_SCHAR);
+ else
+ error = addtype(&types, TP_INT);
+ if (error)
+ goto error;
+ continue; /* no output */
+ case 'O':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'o':
+ if ((error = adduarg(&types, flags)))
+ goto error;
+ break;
+ case 'p':
+ if ((error = addtype(&types, TP_VOID)))
+ goto error;
+ break;
+ case 'S':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 's':
+ error = addtype(&types,
+ (flags & LONGINT) ? TP_WCHAR : TP_CHAR);
+ if (error)
+ goto error;
+ break;
+ case 'U':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'u':
+ case 'X':
+ case 'x':
+ if ((error = adduarg(&types, flags)))
+ goto error;
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ break;
+ }
+ }
+done:
+ build_arg_table(&types, ap, argtable);
+error:
+ freetypes(&types);
+ return (error || *argtable == NULL);
+}
+
+/*
+ * Increase the size of the type table. Returns 0 on success.
+ */
+static int
+__grow_type_table(struct typetable *types)
+{
+ enum typeid *const oldtable = types->table;
+ const int oldsize = types->tablesize;
+ enum typeid *newtable;
+ int n, newsize = oldsize * 2;
+
+ if (newsize < types->nextarg + 1)
+ newsize = types->nextarg + 1;
+ if (oldsize == STATIC_ARG_TBL_SIZE) {
+ if ((newtable = malloc(newsize * sizeof(enum typeid))) == NULL)
+ return (-1);
+ bcopy(oldtable, newtable, oldsize * sizeof(enum typeid));
+ } else {
+ newtable = realloc(oldtable, newsize * sizeof(enum typeid));
+ if (newtable == NULL)
+ return (-1);
+ }
+ for (n = oldsize; n < newsize; n++)
+ newtable[n] = T_UNUSED;
+
+ types->table = newtable;
+ types->tablesize = newsize;
+
+ return (0);
+}
+
+/*
+ * Build the argument table from the completed type table.
+ * On malloc failure, *argtable is set to NULL.
+ */
+static void
+build_arg_table(struct typetable *types, va_list ap, union arg **argtable)
+{
+ int n;
+
+ if (types->tablemax >= STATIC_ARG_TBL_SIZE) {
+ *argtable = (union arg *)
+ malloc (sizeof (union arg) * (types->tablemax + 1));
+ if (*argtable == NULL)
+ return;
+ }
+
+ (*argtable) [0].intarg = 0;
+ for (n = 1; n <= types->tablemax; n++) {
+ switch (types->table[n]) {
+ case T_UNUSED: /* whoops! */
+ (*argtable) [n].intarg = va_arg (ap, int);
+ break;
+ case TP_SCHAR:
+ (*argtable) [n].pschararg = va_arg (ap, signed char *);
+ break;
+ case TP_SHORT:
+ (*argtable) [n].pshortarg = va_arg (ap, short *);
+ break;
+ case T_INT:
+ (*argtable) [n].intarg = va_arg (ap, int);
+ break;
+ case T_U_INT:
+ (*argtable) [n].uintarg = va_arg (ap, unsigned int);
+ break;
+ case TP_INT:
+ (*argtable) [n].pintarg = va_arg (ap, int *);
+ break;
+ case T_LONG:
+ (*argtable) [n].longarg = va_arg (ap, long);
+ break;
+ case T_U_LONG:
+ (*argtable) [n].ulongarg = va_arg (ap, unsigned long);
+ break;
+ case TP_LONG:
+ (*argtable) [n].plongarg = va_arg (ap, long *);
+ break;
+ case T_LLONG:
+ (*argtable) [n].longlongarg = va_arg (ap, long long);
+ break;
+ case T_U_LLONG:
+ (*argtable) [n].ulonglongarg = va_arg (ap, unsigned long long);
+ break;
+ case TP_LLONG:
+ (*argtable) [n].plonglongarg = va_arg (ap, long long *);
+ break;
+ case T_PTRDIFFT:
+ (*argtable) [n].ptrdiffarg = va_arg (ap, ptrdiff_t);
+ break;
+ case TP_PTRDIFFT:
+ (*argtable) [n].pptrdiffarg = va_arg (ap, ptrdiff_t *);
+ break;
+ case T_SIZET:
+ (*argtable) [n].sizearg = va_arg (ap, size_t);
+ break;
+ case T_SSIZET:
+ (*argtable) [n].sizearg = va_arg (ap, ssize_t);
+ break;
+ case TP_SSIZET:
+ (*argtable) [n].pssizearg = va_arg (ap, ssize_t *);
+ break;
+ case T_INTMAXT:
+ (*argtable) [n].intmaxarg = va_arg (ap, intmax_t);
+ break;
+ case T_UINTMAXT:
+ (*argtable) [n].uintmaxarg = va_arg (ap, uintmax_t);
+ break;
+ case TP_INTMAXT:
+ (*argtable) [n].pintmaxarg = va_arg (ap, intmax_t *);
+ break;
+ case T_DOUBLE:
+#ifndef NO_FLOATING_POINT
+ (*argtable) [n].doublearg = va_arg (ap, double);
+#endif
+ break;
+ case T_LONG_DOUBLE:
+#ifndef NO_FLOATING_POINT
+ (*argtable) [n].longdoublearg = va_arg (ap, long double);
+#endif
+ break;
+ case TP_CHAR:
+ (*argtable) [n].pchararg = va_arg (ap, char *);
+ break;
+ case TP_VOID:
+ (*argtable) [n].pvoidarg = va_arg (ap, void *);
+ break;
+ case T_WINT:
+ (*argtable) [n].wintarg = va_arg (ap, wint_t);
+ break;
+ case TP_WCHAR:
+ (*argtable) [n].pwchararg = va_arg (ap, wchar_t *);
+ break;
+ }
+ }
+}
diff --git a/lib/libc/stdio/printf.3 b/lib/libc/stdio/printf.3
new file mode 100644
index 0000000..0d9339e
--- /dev/null
+++ b/lib/libc/stdio/printf.3
@@ -0,0 +1,920 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)printf.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd December 2, 2009
+.Dt PRINTF 3
+.Os
+.Sh NAME
+.Nm printf , fprintf , sprintf , snprintf , asprintf , dprintf ,
+.Nm vprintf , vfprintf, vsprintf , vsnprintf , vasprintf, vdprintf
+.Nd formatted output conversion
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.Fd "#define _WITH_DPRINTF"
+.In stdio.h
+.Ft int
+.Fn printf "const char * restrict format" ...
+.Ft int
+.Fn fprintf "FILE * restrict stream" "const char * restrict format" ...
+.Ft int
+.Fn sprintf "char * restrict str" "const char * restrict format" ...
+.Ft int
+.Fn snprintf "char * restrict str" "size_t size" "const char * restrict format" ...
+.Ft int
+.Fn asprintf "char **ret" "const char *format" ...
+.Ft int
+.Fn dprintf "int fd" "const char * restrict format" ...
+.In stdarg.h
+.Ft int
+.Fn vprintf "const char * restrict format" "va_list ap"
+.Ft int
+.Fn vfprintf "FILE * restrict stream" "const char * restrict format" "va_list ap"
+.Ft int
+.Fn vsprintf "char * restrict str" "const char * restrict format" "va_list ap"
+.Ft int
+.Fn vsnprintf "char * restrict str" "size_t size" "const char * restrict format" "va_list ap"
+.Ft int
+.Fn vasprintf "char **ret" "const char *format" "va_list ap"
+.Ft int
+.Fn vdprintf "int fd" "const char * restrict format" "va_list ap"
+.Sh DESCRIPTION
+The
+.Fn printf
+family of functions produces output according to a
+.Fa format
+as described below.
+The
+.Fn printf
+and
+.Fn vprintf
+functions
+write output to
+.Dv stdout ,
+the standard output stream;
+.Fn fprintf
+and
+.Fn vfprintf
+write output to the given output
+.Fa stream ;
+.Fn dprintf
+and
+.Fn vdprintf
+write output to the given file descriptor;
+.Fn sprintf ,
+.Fn snprintf ,
+.Fn vsprintf ,
+and
+.Fn vsnprintf
+write to the character string
+.Fa str ;
+and
+.Fn asprintf
+and
+.Fn vasprintf
+dynamically allocate a new string with
+.Xr malloc 3 .
+.Pp
+These functions write the output under the control of a
+.Fa format
+string that specifies how subsequent arguments
+(or arguments accessed via the variable-length argument facilities of
+.Xr stdarg 3 )
+are converted for output.
+.Pp
+The
+.Fn asprintf
+and
+.Fn vasprintf
+functions
+set
+.Fa *ret
+to be a pointer to a buffer sufficiently large to hold the formatted string.
+This pointer should be passed to
+.Xr free 3
+to release the allocated storage when it is no longer needed.
+If sufficient space cannot be allocated,
+.Fn asprintf
+and
+.Fn vasprintf
+will return \-1 and set
+.Fa ret
+to be a
+.Dv NULL
+pointer.
+.Pp
+The
+.Fn snprintf
+and
+.Fn vsnprintf
+functions
+will write at most
+.Fa size Ns \-1
+of the characters printed into the output string
+(the
+.Fa size Ns 'th
+character then gets the terminating
+.Ql \e0 ) ;
+if the return value is greater than or equal to the
+.Fa size
+argument, the string was too short
+and some of the printed characters were discarded.
+The output is always null-terminated, unless
+.Fa size
+is 0.
+.Pp
+The
+.Fn sprintf
+and
+.Fn vsprintf
+functions
+effectively assume a
+.Fa size
+of
+.Dv INT_MAX + 1.
+.Pp
+The format string is composed of zero or more directives:
+ordinary
+.\" multibyte
+characters (not
+.Cm % ) ,
+which are copied unchanged to the output stream;
+and conversion specifications, each of which results
+in fetching zero or more subsequent arguments.
+Each conversion specification is introduced by
+the
+.Cm %
+character.
+The arguments must correspond properly (after type promotion)
+with the conversion specifier.
+After the
+.Cm % ,
+the following appear in sequence:
+.Bl -bullet
+.It
+An optional field, consisting of a decimal digit string followed by a
+.Cm $ ,
+specifying the next argument to access.
+If this field is not provided, the argument following the last
+argument accessed will be used.
+Arguments are numbered starting at
+.Cm 1 .
+If unaccessed arguments in the format string are interspersed with ones that
+are accessed the results will be indeterminate.
+.It
+Zero or more of the following flags:
+.Bl -tag -width ".So \ Sc (space)"
+.It Sq Cm #
+The value should be converted to an
+.Dq alternate form .
+For
+.Cm c , d , i , n , p , s ,
+and
+.Cm u
+conversions, this option has no effect.
+For
+.Cm o
+conversions, the precision of the number is increased to force the first
+character of the output string to a zero.
+For
+.Cm x
+and
+.Cm X
+conversions, a non-zero result has the string
+.Ql 0x
+(or
+.Ql 0X
+for
+.Cm X
+conversions) prepended to it.
+For
+.Cm a , A , e , E , f , F , g ,
+and
+.Cm G
+conversions, the result will always contain a decimal point, even if no
+digits follow it (normally, a decimal point appears in the results of
+those conversions only if a digit follows).
+For
+.Cm g
+and
+.Cm G
+conversions, trailing zeros are not removed from the result as they
+would otherwise be.
+.It So Cm 0 Sc (zero)
+Zero padding.
+For all conversions except
+.Cm n ,
+the converted value is padded on the left with zeros rather than blanks.
+If a precision is given with a numeric conversion
+.Cm ( d , i , o , u , i , x ,
+and
+.Cm X ) ,
+the
+.Cm 0
+flag is ignored.
+.It Sq Cm \-
+A negative field width flag;
+the converted value is to be left adjusted on the field boundary.
+Except for
+.Cm n
+conversions, the converted value is padded on the right with blanks,
+rather than on the left with blanks or zeros.
+A
+.Cm \-
+overrides a
+.Cm 0
+if both are given.
+.It So "\ " Sc (space)
+A blank should be left before a positive number
+produced by a signed conversion
+.Cm ( a , A , d , e , E , f , F , g , G ,
+or
+.Cm i ) .
+.It Sq Cm +
+A sign must always be placed before a
+number produced by a signed conversion.
+A
+.Cm +
+overrides a space if both are used.
+.It Sq Cm '
+Decimal conversions
+.Cm ( d , u ,
+or
+.Cm i )
+or the integral portion of a floating point conversion
+.Cm ( f
+or
+.Cm F )
+should be grouped and separated by thousands using
+the non-monetary separator returned by
+.Xr localeconv 3 .
+.El
+.It
+An optional decimal digit string specifying a minimum field width.
+If the converted value has fewer characters than the field width, it will
+be padded with spaces on the left (or right, if the left-adjustment
+flag has been given) to fill out
+the field width.
+.It
+An optional precision, in the form of a period
+.Cm \&.
+followed by an
+optional digit string.
+If the digit string is omitted, the precision is taken as zero.
+This gives the minimum number of digits to appear for
+.Cm d , i , o , u , x ,
+and
+.Cm X
+conversions, the number of digits to appear after the decimal-point for
+.Cm a , A , e , E , f ,
+and
+.Cm F
+conversions, the maximum number of significant digits for
+.Cm g
+and
+.Cm G
+conversions, or the maximum number of characters to be printed from a
+string for
+.Cm s
+conversions.
+.It
+An optional length modifier, that specifies the size of the argument.
+The following length modifiers are valid for the
+.Cm d , i , n , o , u , x ,
+or
+.Cm X
+conversion:
+.Bl -column ".Cm q Em (deprecated)" ".Vt signed char" ".Vt unsigned long long" ".Vt long long *"
+.It Sy Modifier Ta Cm d , i Ta Cm o , u , x , X Ta Cm n
+.It Cm hh Ta Vt "signed char" Ta Vt "unsigned char" Ta Vt "signed char *"
+.It Cm h Ta Vt short Ta Vt "unsigned short" Ta Vt "short *"
+.It Cm l No (ell) Ta Vt long Ta Vt "unsigned long" Ta Vt "long *"
+.It Cm ll No (ell ell) Ta Vt "long long" Ta Vt "unsigned long long" Ta Vt "long long *"
+.It Cm j Ta Vt intmax_t Ta Vt uintmax_t Ta Vt "intmax_t *"
+.It Cm t Ta Vt ptrdiff_t Ta (see note) Ta Vt "ptrdiff_t *"
+.It Cm z Ta (see note) Ta Vt size_t Ta (see note)
+.It Cm q Em (deprecated) Ta Vt quad_t Ta Vt u_quad_t Ta Vt "quad_t *"
+.El
+.Pp
+Note:
+the
+.Cm t
+modifier, when applied to a
+.Cm o , u , x ,
+or
+.Cm X
+conversion, indicates that the argument is of an unsigned type
+equivalent in size to a
+.Vt ptrdiff_t .
+The
+.Cm z
+modifier, when applied to a
+.Cm d
+or
+.Cm i
+conversion, indicates that the argument is of a signed type equivalent in
+size to a
+.Vt size_t .
+Similarly, when applied to an
+.Cm n
+conversion, it indicates that the argument is a pointer to a signed type
+equivalent in size to a
+.Vt size_t .
+.Pp
+The following length modifier is valid for the
+.Cm a , A , e , E , f , F , g ,
+or
+.Cm G
+conversion:
+.Bl -column ".Sy Modifier" ".Cm a , A , e , E , f , F , g , G"
+.It Sy Modifier Ta Cm a , A , e , E , f , F , g , G
+.It Cm l No (ell) Ta Vt double
+(ignored, same behavior as without it)
+.It Cm L Ta Vt "long double"
+.El
+.Pp
+The following length modifier is valid for the
+.Cm c
+or
+.Cm s
+conversion:
+.Bl -column ".Sy Modifier" ".Vt wint_t" ".Vt wchar_t *"
+.It Sy Modifier Ta Cm c Ta Cm s
+.It Cm l No (ell) Ta Vt wint_t Ta Vt "wchar_t *"
+.El
+.It
+A character that specifies the type of conversion to be applied.
+.El
+.Pp
+A field width or precision, or both, may be indicated by
+an asterisk
+.Ql *
+or an asterisk followed by one or more decimal digits and a
+.Ql $
+instead of a
+digit string.
+In this case, an
+.Vt int
+argument supplies the field width or precision.
+A negative field width is treated as a left adjustment flag followed by a
+positive field width; a negative precision is treated as though it were
+missing.
+If a single format directive mixes positional
+.Pq Li nn$
+and non-positional arguments, the results are undefined.
+.Pp
+The conversion specifiers and their meanings are:
+.Bl -tag -width ".Cm diouxX"
+.It Cm diouxX
+The
+.Vt int
+(or appropriate variant) argument is converted to signed decimal
+.Cm ( d
+and
+.Cm i ) ,
+unsigned octal
+.Pq Cm o ,
+unsigned decimal
+.Pq Cm u ,
+or unsigned hexadecimal
+.Cm ( x
+and
+.Cm X )
+notation.
+The letters
+.Dq Li abcdef
+are used for
+.Cm x
+conversions; the letters
+.Dq Li ABCDEF
+are used for
+.Cm X
+conversions.
+The precision, if any, gives the minimum number of digits that must
+appear; if the converted value requires fewer digits, it is padded on
+the left with zeros.
+.It Cm DOU
+The
+.Vt "long int"
+argument is converted to signed decimal, unsigned octal, or unsigned
+decimal, as if the format had been
+.Cm ld , lo ,
+or
+.Cm lu
+respectively.
+These conversion characters are deprecated, and will eventually disappear.
+.It Cm eE
+The
+.Vt double
+argument is rounded and converted in the style
+.Sm off
+.Oo \- Oc Ar d Li \&. Ar ddd Li e \(+- Ar dd
+.Sm on
+where there is one digit before the
+decimal-point character
+and the number of digits after it is equal to the precision;
+if the precision is missing,
+it is taken as 6; if the precision is
+zero, no decimal-point character appears.
+An
+.Cm E
+conversion uses the letter
+.Ql E
+(rather than
+.Ql e )
+to introduce the exponent.
+The exponent always contains at least two digits; if the value is zero,
+the exponent is 00.
+.Pp
+For
+.Cm a , A , e , E , f , F , g ,
+and
+.Cm G
+conversions, positive and negative infinity are represented as
+.Li inf
+and
+.Li -inf
+respectively when using the lowercase conversion character, and
+.Li INF
+and
+.Li -INF
+respectively when using the uppercase conversion character.
+Similarly, NaN is represented as
+.Li nan
+when using the lowercase conversion, and
+.Li NAN
+when using the uppercase conversion.
+.It Cm fF
+The
+.Vt double
+argument is rounded and converted to decimal notation in the style
+.Sm off
+.Oo \- Oc Ar ddd Li \&. Ar ddd ,
+.Sm on
+where the number of digits after the decimal-point character
+is equal to the precision specification.
+If the precision is missing, it is taken as 6; if the precision is
+explicitly zero, no decimal-point character appears.
+If a decimal point appears, at least one digit appears before it.
+.It Cm gG
+The
+.Vt double
+argument is converted in style
+.Cm f
+or
+.Cm e
+(or
+.Cm F
+or
+.Cm E
+for
+.Cm G
+conversions).
+The precision specifies the number of significant digits.
+If the precision is missing, 6 digits are given; if the precision is zero,
+it is treated as 1.
+Style
+.Cm e
+is used if the exponent from its conversion is less than \-4 or greater than
+or equal to the precision.
+Trailing zeros are removed from the fractional part of the result; a
+decimal point appears only if it is followed by at least one digit.
+.It Cm aA
+The
+.Vt double
+argument is rounded and converted to hexadecimal notation in the style
+.Sm off
+.Oo \- Oc Li 0x Ar h Li \&. Ar hhhp Oo \(+- Oc Ar d ,
+.Sm on
+where the number of digits after the hexadecimal-point character
+is equal to the precision specification.
+If the precision is missing, it is taken as enough to represent
+the floating-point number exactly, and no rounding occurs.
+If the precision is zero, no hexadecimal-point character appears.
+The
+.Cm p
+is a literal character
+.Ql p ,
+and the exponent consists of a positive or negative sign
+followed by a decimal number representing an exponent of 2.
+The
+.Cm A
+conversion uses the prefix
+.Dq Li 0X
+(rather than
+.Dq Li 0x ) ,
+the letters
+.Dq Li ABCDEF
+(rather than
+.Dq Li abcdef )
+to represent the hex digits, and the letter
+.Ql P
+(rather than
+.Ql p )
+to separate the mantissa and exponent.
+.Pp
+Note that there may be multiple valid ways to represent floating-point
+numbers in this hexadecimal format.
+For example,
+.Li 0x1.92p+1 , 0x3.24p+0 , 0x6.48p-1 ,
+and
+.Li 0xc.9p-2
+are all equivalent.
+.Fx 8.0
+and later always prints finite non-zero numbers using
+.Ql 1
+as the digit before the hexadecimal point.
+Zeroes are always represented with a mantissa of 0 (preceded by a
+.Ql -
+if appropriate) and an exponent of
+.Li +0 .
+.It Cm C
+Treated as
+.Cm c
+with the
+.Cm l
+(ell) modifier.
+.It Cm c
+The
+.Vt int
+argument is converted to an
+.Vt "unsigned char" ,
+and the resulting character is written.
+.Pp
+If the
+.Cm l
+(ell) modifier is used, the
+.Vt wint_t
+argument shall be converted to a
+.Vt wchar_t ,
+and the (potentially multi-byte) sequence representing the
+single wide character is written, including any shift sequences.
+If a shift sequence is used, the shift state is also restored
+to the original state after the character.
+.It Cm S
+Treated as
+.Cm s
+with the
+.Cm l
+(ell) modifier.
+.It Cm s
+The
+.Vt "char *"
+argument is expected to be a pointer to an array of character type (pointer
+to a string).
+Characters from the array are written up to (but not including)
+a terminating
+.Dv NUL
+character;
+if a precision is specified, no more than the number specified are
+written.
+If a precision is given, no null character
+need be present; if the precision is not specified, or is greater than
+the size of the array, the array must contain a terminating
+.Dv NUL
+character.
+.Pp
+If the
+.Cm l
+(ell) modifier is used, the
+.Vt "wchar_t *"
+argument is expected to be a pointer to an array of wide characters
+(pointer to a wide string).
+For each wide character in the string, the (potentially multi-byte)
+sequence representing the
+wide character is written, including any shift sequences.
+If any shift sequence is used, the shift state is also restored
+to the original state after the string.
+Wide characters from the array are written up to (but not including)
+a terminating wide
+.Dv NUL
+character;
+if a precision is specified, no more than the number of bytes specified are
+written (including shift sequences).
+Partial characters are never written.
+If a precision is given, no null character
+need be present; if the precision is not specified, or is greater than
+the number of bytes required to render the multibyte representation of
+the string, the array must contain a terminating wide
+.Dv NUL
+character.
+.It Cm p
+The
+.Vt "void *"
+pointer argument is printed in hexadecimal (as if by
+.Ql %#x
+or
+.Ql %#lx ) .
+.It Cm n
+The number of characters written so far is stored into the
+integer indicated by the
+.Vt "int *"
+(or variant) pointer argument.
+No argument is converted.
+.It Cm %
+A
+.Ql %
+is written.
+No argument is converted.
+The complete conversion specification
+is
+.Ql %% .
+.El
+.Pp
+The decimal point
+character is defined in the program's locale (category
+.Dv LC_NUMERIC ) .
+.Pp
+In no case does a non-existent or small field width cause truncation of
+a numeric field; if the result of a conversion is wider than the field
+width, the
+field is expanded to contain the conversion result.
+.Sh RETURN VALUES
+These functions return the number of characters printed
+(not including the trailing
+.Ql \e0
+used to end output to strings),
+except for
+.Fn snprintf
+and
+.Fn vsnprintf ,
+which return the number of characters that would have been printed if the
+.Fa size
+were unlimited
+(again, not including the final
+.Ql \e0 ) .
+These functions return a negative value if an error occurs.
+.Sh EXAMPLES
+To print a date and time in the form
+.Dq Li "Sunday, July 3, 10:02" ,
+where
+.Fa weekday
+and
+.Fa month
+are pointers to strings:
+.Bd -literal -offset indent
+#include <stdio.h>
+fprintf(stdout, "%s, %s %d, %.2d:%.2d\en",
+ weekday, month, day, hour, min);
+.Ed
+.Pp
+To print \*(Pi
+to five decimal places:
+.Bd -literal -offset indent
+#include <math.h>
+#include <stdio.h>
+fprintf(stdout, "pi = %.5f\en", 4 * atan(1.0));
+.Ed
+.Pp
+To allocate a 128 byte string and print into it:
+.Bd -literal -offset indent
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+char *newfmt(const char *fmt, ...)
+{
+ char *p;
+ va_list ap;
+ if ((p = malloc(128)) == NULL)
+ return (NULL);
+ va_start(ap, fmt);
+ (void) vsnprintf(p, 128, fmt, ap);
+ va_end(ap);
+ return (p);
+}
+.Ed
+.Sh COMPATIBILITY
+Many application writers used the name
+.Va dprintf
+before the
+.Fn dprintf
+function was introduced in
+.St -p1003.1 ,
+so a prototype is not provided by default in order to avoid
+compatibility problems.
+Applications that wish to use the
+.Fn dprintf
+function described herein should either request a strict
+.St -p1003.1-2008
+environment by defining the macro
+.Dv _POSIX_C_SOURCE
+to the value 200809 or greater, or by defining the macro
+.Dv _WITH_DPRINTF ,
+prior to the inclusion of
+.In stdio.h .
+For compatibility with GNU libc, defining either
+.Dv _BSD_SOURCE
+or
+.Dv _GNU_SOURCE
+prior to the inclusion of
+.In stdio.h
+will also make
+.Fn dprintf
+available.
+.Pp
+The conversion formats
+.Cm \&%D , \&%O ,
+and
+.Cm \&%U
+are not standard and
+are provided only for backward compatibility.
+The effect of padding the
+.Cm %p
+format with zeros (either by the
+.Cm 0
+flag or by specifying a precision), and the benign effect (i.e., none)
+of the
+.Cm #
+flag on
+.Cm %n
+and
+.Cm %p
+conversions, as well as other
+nonsensical combinations such as
+.Cm %Ld ,
+are not standard; such combinations
+should be avoided.
+.Sh ERRORS
+In addition to the errors documented for the
+.Xr write 2
+system call, the
+.Fn printf
+family of functions may fail if:
+.Bl -tag -width Er
+.It Bq Er EILSEQ
+An invalid wide character code was encountered.
+.It Bq Er ENOMEM
+Insufficient storage space is available.
+.It Bq Er EOVERFLOW
+The
+.Fa size
+argument exceeds
+.Dv INT_MAX + 1 ,
+or the return value would be too large to be represented by an
+.Vt int .
+.El
+.Sh SEE ALSO
+.Xr printf 1 ,
+.Xr fmtcheck 3 ,
+.Xr scanf 3 ,
+.Xr setlocale 3 ,
+.Xr wprintf 3
+.Sh STANDARDS
+Subject to the caveats noted in the
+.Sx BUGS
+section below, the
+.Fn fprintf ,
+.Fn printf ,
+.Fn sprintf ,
+.Fn vprintf ,
+.Fn vfprintf ,
+and
+.Fn vsprintf
+functions
+conform to
+.St -ansiC
+and
+.St -isoC-99 .
+With the same reservation, the
+.Fn snprintf
+and
+.Fn vsnprintf
+functions conform to
+.St -isoC-99 ,
+while
+.Fn dprintf
+and
+.Fn vdprintf
+conform to
+.St -p1003.1-2008 .
+.Sh HISTORY
+The functions
+.Fn asprintf
+and
+.Fn vasprintf
+first appeared in the
+.Tn GNU C
+library.
+These were implemented by
+.An Peter Wemm Aq peter@FreeBSD.org
+in
+.Fx 2.2 ,
+but were later replaced with a different implementation
+from
+.Ox 2.3
+by
+.An Todd C. Miller Aq Todd.Miller@courtesan.com .
+The
+.Fn dprintf
+and
+.Fn vdprintf
+functions were added in
+.Fx 8.0 .
+.Sh BUGS
+The
+.Nm
+family of functions do not correctly handle multibyte characters in the
+.Fa format
+argument.
+.Sh SECURITY CONSIDERATIONS
+The
+.Fn sprintf
+and
+.Fn vsprintf
+functions are easily misused in a manner which enables malicious users
+to arbitrarily change a running program's functionality through
+a buffer overflow attack.
+Because
+.Fn sprintf
+and
+.Fn vsprintf
+assume an infinitely long string,
+callers must be careful not to overflow the actual space;
+this is often hard to assure.
+For safety, programmers should use the
+.Fn snprintf
+interface instead.
+For example:
+.Bd -literal
+void
+foo(const char *arbitrary_string, const char *and_another)
+{
+ char onstack[8];
+
+#ifdef BAD
+ /*
+ * This first sprintf is bad behavior. Do not use sprintf!
+ */
+ sprintf(onstack, "%s, %s", arbitrary_string, and_another);
+#else
+ /*
+ * The following two lines demonstrate better use of
+ * snprintf().
+ */
+ snprintf(onstack, sizeof(onstack), "%s, %s", arbitrary_string,
+ and_another);
+#endif
+}
+.Ed
+.Pp
+The
+.Fn printf
+and
+.Fn sprintf
+family of functions are also easily misused in a manner
+allowing malicious users to arbitrarily change a running program's
+functionality by either causing the program
+to print potentially sensitive data
+.Dq "left on the stack" ,
+or causing it to generate a memory fault or bus error
+by dereferencing an invalid pointer.
+.Pp
+.Cm %n
+can be used to write arbitrary data to potentially carefully-selected
+addresses.
+Programmers are therefore strongly advised to never pass untrusted strings
+as the
+.Fa format
+argument, as an attacker can put format specifiers in the string
+to mangle your stack,
+leading to a possible security hole.
+This holds true even if the string was built using a function like
+.Fn snprintf ,
+as the resulting string may still contain user-supplied conversion specifiers
+for later interpolation by
+.Fn printf .
+.Pp
+Always use the proper secure idiom:
+.Pp
+.Dl "snprintf(buffer, sizeof(buffer), \*q%s\*q, string);"
diff --git a/lib/libc/stdio/printf.c b/lib/libc/stdio/printf.c
new file mode 100644
index 0000000..f623f2f
--- /dev/null
+++ b/lib/libc/stdio/printf.c
@@ -0,0 +1,69 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)printf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <xlocale.h>
+
+int
+printf(char const * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vfprintf(stdout, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
+int
+printf_l(locale_t locale, char const * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vfprintf_l(stdout, locale, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
diff --git a/lib/libc/stdio/printfcommon.h b/lib/libc/stdio/printfcommon.h
new file mode 100644
index 0000000..97acc53
--- /dev/null
+++ b/lib/libc/stdio/printfcommon.h
@@ -0,0 +1,307 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * This file defines common routines used by both printf and wprintf.
+ * You must define CHAR to either char or wchar_t prior to including this.
+ */
+
+
+#ifndef NO_FLOATING_POINT
+
+#define dtoa __dtoa
+#define freedtoa __freedtoa
+
+#include <float.h>
+#include <math.h>
+#include "floatio.h"
+#include "gdtoa.h"
+
+#define DEFPREC 6
+
+static int exponent(CHAR *, int, CHAR);
+
+#endif /* !NO_FLOATING_POINT */
+
+static CHAR *__ujtoa(uintmax_t, CHAR *, int, int, const char *);
+static CHAR *__ultoa(u_long, CHAR *, int, int, const char *);
+
+#define NIOV 8
+struct io_state {
+ FILE *fp;
+ struct __suio uio; /* output information: summary */
+ struct __siov iov[NIOV];/* ... and individual io vectors */
+};
+
+static inline void
+io_init(struct io_state *iop, FILE *fp)
+{
+
+ iop->uio.uio_iov = iop->iov;
+ iop->uio.uio_resid = 0;
+ iop->uio.uio_iovcnt = 0;
+ iop->fp = fp;
+}
+
+/*
+ * WARNING: The buffer passed to io_print() is not copied immediately; it must
+ * remain valid until io_flush() is called.
+ */
+static inline int
+io_print(struct io_state *iop, const CHAR * __restrict ptr, int len, locale_t locale)
+{
+
+ iop->iov[iop->uio.uio_iovcnt].iov_base = (char *)ptr;
+ iop->iov[iop->uio.uio_iovcnt].iov_len = len;
+ iop->uio.uio_resid += len;
+ if (++iop->uio.uio_iovcnt >= NIOV)
+ return (__sprint(iop->fp, &iop->uio, locale));
+ else
+ return (0);
+}
+
+/*
+ * Choose PADSIZE to trade efficiency vs. size. If larger printf
+ * fields occur frequently, increase PADSIZE and make the initialisers
+ * below longer.
+ */
+#define PADSIZE 16 /* pad chunk size */
+static const CHAR blanks[PADSIZE] =
+{' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
+static const CHAR zeroes[PADSIZE] =
+{'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
+
+/*
+ * Pad with blanks or zeroes. 'with' should point to either the blanks array
+ * or the zeroes array.
+ */
+static inline int
+io_pad(struct io_state *iop, int howmany, const CHAR * __restrict with,
+ locale_t locale)
+{
+ int n;
+
+ while (howmany > 0) {
+ n = (howmany >= PADSIZE) ? PADSIZE : howmany;
+ if (io_print(iop, with, n, locale))
+ return (-1);
+ howmany -= n;
+ }
+ return (0);
+}
+
+/*
+ * Print exactly len characters of the string spanning p to ep, truncating
+ * or padding with 'with' as necessary.
+ */
+static inline int
+io_printandpad(struct io_state *iop, const CHAR *p, const CHAR *ep,
+ int len, const CHAR * __restrict with, locale_t locale)
+{
+ int p_len;
+
+ p_len = ep - p;
+ if (p_len > len)
+ p_len = len;
+ if (p_len > 0) {
+ if (io_print(iop, p, p_len, locale))
+ return (-1);
+ } else {
+ p_len = 0;
+ }
+ return (io_pad(iop, len - p_len, with, locale));
+}
+
+static inline int
+io_flush(struct io_state *iop, locale_t locale)
+{
+
+ return (__sprint(iop->fp, &iop->uio, locale));
+}
+
+/*
+ * Convert an unsigned long to ASCII for printf purposes, returning
+ * a pointer to the first character of the string representation.
+ * Octal numbers can be forced to have a leading zero; hex numbers
+ * use the given digits.
+ */
+static CHAR *
+__ultoa(u_long val, CHAR *endp, int base, int octzero, const char *xdigs)
+{
+ CHAR *cp = endp;
+ long sval;
+
+ /*
+ * Handle the three cases separately, in the hope of getting
+ * better/faster code.
+ */
+ switch (base) {
+ case 10:
+ if (val < 10) { /* many numbers are 1 digit */
+ *--cp = to_char(val);
+ return (cp);
+ }
+ /*
+ * On many machines, unsigned arithmetic is harder than
+ * signed arithmetic, so we do at most one unsigned mod and
+ * divide; this is sufficient to reduce the range of
+ * the incoming value to where signed arithmetic works.
+ */
+ if (val > LONG_MAX) {
+ *--cp = to_char(val % 10);
+ sval = val / 10;
+ } else
+ sval = val;
+ do {
+ *--cp = to_char(sval % 10);
+ sval /= 10;
+ } while (sval != 0);
+ break;
+
+ case 8:
+ do {
+ *--cp = to_char(val & 7);
+ val >>= 3;
+ } while (val);
+ if (octzero && *cp != '0')
+ *--cp = '0';
+ break;
+
+ case 16:
+ do {
+ *--cp = xdigs[val & 15];
+ val >>= 4;
+ } while (val);
+ break;
+
+ default: /* oops */
+ abort();
+ }
+ return (cp);
+}
+
+/* Identical to __ultoa, but for intmax_t. */
+static CHAR *
+__ujtoa(uintmax_t val, CHAR *endp, int base, int octzero, const char *xdigs)
+{
+ CHAR *cp = endp;
+ intmax_t sval;
+
+ /* quick test for small values; __ultoa is typically much faster */
+ /* (perhaps instead we should run until small, then call __ultoa?) */
+ if (val <= ULONG_MAX)
+ return (__ultoa((u_long)val, endp, base, octzero, xdigs));
+ switch (base) {
+ case 10:
+ if (val < 10) {
+ *--cp = to_char(val % 10);
+ return (cp);
+ }
+ if (val > INTMAX_MAX) {
+ *--cp = to_char(val % 10);
+ sval = val / 10;
+ } else
+ sval = val;
+ do {
+ *--cp = to_char(sval % 10);
+ sval /= 10;
+ } while (sval != 0);
+ break;
+
+ case 8:
+ do {
+ *--cp = to_char(val & 7);
+ val >>= 3;
+ } while (val);
+ if (octzero && *cp != '0')
+ *--cp = '0';
+ break;
+
+ case 16:
+ do {
+ *--cp = xdigs[val & 15];
+ val >>= 4;
+ } while (val);
+ break;
+
+ default:
+ abort();
+ }
+ return (cp);
+}
+
+#ifndef NO_FLOATING_POINT
+
+static int
+exponent(CHAR *p0, int exp, CHAR fmtch)
+{
+ CHAR *p, *t;
+ CHAR expbuf[MAXEXPDIG];
+
+ p = p0;
+ *p++ = fmtch;
+ if (exp < 0) {
+ exp = -exp;
+ *p++ = '-';
+ }
+ else
+ *p++ = '+';
+ t = expbuf + MAXEXPDIG;
+ if (exp > 9) {
+ do {
+ *--t = to_char(exp % 10);
+ } while ((exp /= 10) > 9);
+ *--t = to_char(exp);
+ for (; t < expbuf + MAXEXPDIG; *p++ = *t++);
+ }
+ else {
+ /*
+ * Exponents for decimal floating point conversions
+ * (%[eEgG]) must be at least two characters long,
+ * whereas exponents for hexadecimal conversions can
+ * be only one character long.
+ */
+ if (fmtch == 'e' || fmtch == 'E')
+ *p++ = '0';
+ *p++ = to_char(exp);
+ }
+ return (p - p0);
+}
+
+#endif /* !NO_FLOATING_POINT */
diff --git a/lib/libc/stdio/printflocal.h b/lib/libc/stdio/printflocal.h
new file mode 100644
index 0000000..3cef7bd
--- /dev/null
+++ b/lib/libc/stdio/printflocal.h
@@ -0,0 +1,94 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+/*
+ * Flags used during conversion.
+ */
+#define ALT 0x001 /* alternate form */
+#define LADJUST 0x004 /* left adjustment */
+#define LONGDBL 0x008 /* long double */
+#define LONGINT 0x010 /* long integer */
+#define LLONGINT 0x020 /* long long integer */
+#define SHORTINT 0x040 /* short integer */
+#define ZEROPAD 0x080 /* zero (as opposed to blank) pad */
+#define FPT 0x100 /* Floating point number */
+#define GROUPING 0x200 /* use grouping ("'" flag) */
+ /* C99 additional size modifiers: */
+#define SIZET 0x400 /* size_t */
+#define PTRDIFFT 0x800 /* ptrdiff_t */
+#define INTMAXT 0x1000 /* intmax_t */
+#define CHARINT 0x2000 /* print char using int format */
+
+/*
+ * Macros for converting digits to letters and vice versa
+ */
+#define to_digit(c) ((c) - '0')
+#define is_digit(c) ((unsigned)to_digit(c) <= 9)
+#define to_char(n) ((n) + '0')
+
+/* Size of the static argument table. */
+#define STATIC_ARG_TBL_SIZE 8
+
+union arg {
+ int intarg;
+ u_int uintarg;
+ long longarg;
+ u_long ulongarg;
+ long long longlongarg;
+ unsigned long long ulonglongarg;
+ ptrdiff_t ptrdiffarg;
+ size_t sizearg;
+ intmax_t intmaxarg;
+ uintmax_t uintmaxarg;
+ void *pvoidarg;
+ char *pchararg;
+ signed char *pschararg;
+ short *pshortarg;
+ int *pintarg;
+ long *plongarg;
+ long long *plonglongarg;
+ ptrdiff_t *pptrdiffarg;
+ ssize_t *pssizearg;
+ intmax_t *pintmaxarg;
+#ifndef NO_FLOATING_POINT
+ double doublearg;
+ long double longdoublearg;
+#endif
+ wint_t wintarg;
+ wchar_t *pwchararg;
+};
+
+/* Handle positional parameters. */
+int __find_arguments(const char *, va_list, union arg **);
+int __find_warguments(const wchar_t *, va_list, union arg **);
diff --git a/lib/libc/stdio/putc.3 b/lib/libc/stdio/putc.3
new file mode 100644
index 0000000..a9fea5e
--- /dev/null
+++ b/lib/libc/stdio/putc.3
@@ -0,0 +1,165 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)putc.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd January 10, 2003
+.Dt PUTC 3
+.Os
+.Sh NAME
+.Nm fputc ,
+.Nm putc ,
+.Nm putc_unlocked ,
+.Nm putchar ,
+.Nm putchar_unlocked ,
+.Nm putw
+.Nd output a character or word to a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft int
+.Fn fputc "int c" "FILE *stream"
+.Ft int
+.Fn putc "int c" "FILE *stream"
+.Ft int
+.Fn putc_unlocked "int c" "FILE *stream"
+.Ft int
+.Fn putchar "int c"
+.Ft int
+.Fn putchar_unlocked "int c"
+.Ft int
+.Fn putw "int w" "FILE *stream"
+.Sh DESCRIPTION
+The
+.Fn fputc
+function
+writes the character
+.Fa c
+(converted to an ``unsigned char'')
+to the output stream pointed to by
+.Fa stream .
+.Pp
+The
+.Fn putc
+macro acts essentially identically to
+.Fn fputc ,
+but is a macro that expands in-line.
+It may evaluate
+.Fa stream
+more than once, so arguments given to
+.Fn putc
+should not be expressions with potential side effects.
+.Pp
+The
+.Fn putchar
+function
+is identical to
+.Fn putc
+with an output stream of
+.Dv stdout .
+.Pp
+The
+.Fn putw
+function
+writes the specified
+.Vt int
+to the named output
+.Fa stream .
+.Pp
+The
+.Fn putc_unlocked
+and
+.Fn putchar_unlocked
+functions are equivalent to
+.Fn putc
+and
+.Fn putchar
+respectively,
+except that the caller is responsible for locking the stream
+with
+.Xr flockfile 3
+before calling them.
+These functions may be used to avoid the overhead of locking the stream
+for each character, and to avoid output being interspersed from multiple
+threads writing to the same stream.
+.Sh RETURN VALUES
+The functions,
+.Fn fputc ,
+.Fn putc ,
+.Fn putchar ,
+.Fn putc_unlocked
+and
+.Fn putchar_unlocked
+return the character written.
+If an error occurs, the value
+.Dv EOF
+is returned.
+The
+.Fn putw
+function
+returns 0 on success;
+.Dv EOF
+is returned if
+a write error occurs,
+or if an attempt is made to write a read-only stream.
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr flockfile 3 ,
+.Xr fopen 3 ,
+.Xr getc 3 ,
+.Xr putwc 3 ,
+.Xr stdio 3
+.Sh STANDARDS
+The functions
+.Fn fputc ,
+.Fn putc ,
+and
+.Fn putchar ,
+conform to
+.St -isoC .
+The
+.Fn putc_unlocked
+and
+.Fn putchar_unlocked
+functions conform to
+.St -p1003.1-2001 .
+A function
+.Fn putw
+function appeared in
+.At v6 .
+.Sh BUGS
+The size and byte order of an
+.Vt int
+varies from one machine to another, and
+.Fn putw
+is not recommended for portable applications.
diff --git a/lib/libc/stdio/putc.c b/lib/libc/stdio/putc.c
new file mode 100644
index 0000000..d0882f0
--- /dev/null
+++ b/lib/libc/stdio/putc.c
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)putc.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "local.h"
+#include "libc_private.h"
+
+#undef putc
+#undef putc_unlocked
+
+int
+putc(c, fp)
+ int c;
+ FILE *fp;
+{
+ int retval;
+ FLOCKFILE(fp);
+ /* Orientation set by __sputc() when buffer is full. */
+ /* ORIENT(fp, -1); */
+ retval = __sputc(c, fp);
+ FUNLOCKFILE(fp);
+ return (retval);
+}
+
+int
+putc_unlocked(int ch, FILE *fp)
+{
+
+ return (__sputc(ch, fp));
+}
diff --git a/lib/libc/stdio/putchar.c b/lib/libc/stdio/putchar.c
new file mode 100644
index 0000000..d263970
--- /dev/null
+++ b/lib/libc/stdio/putchar.c
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)putchar.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "local.h"
+#include "libc_private.h"
+
+#undef putchar
+#undef putchar_unlocked
+
+/*
+ * A subroutine version of the macro putchar
+ */
+int
+putchar(c)
+ int c;
+{
+ int retval;
+ FILE *so = stdout;
+
+ FLOCKFILE(so);
+ /* Orientation set by __sputc() when buffer is full. */
+ /* ORIENT(so, -1); */
+ retval = __sputc(c, so);
+ FUNLOCKFILE(so);
+ return (retval);
+}
+
+int
+putchar_unlocked(int ch)
+{
+
+ return (__sputc(ch, stdout));
+}
diff --git a/lib/libc/stdio/puts.c b/lib/libc/stdio/puts.c
new file mode 100644
index 0000000..2dc945b
--- /dev/null
+++ b/lib/libc/stdio/puts.c
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)puts.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "fvwrite.h"
+#include "libc_private.h"
+#include "local.h"
+
+/*
+ * Write the given string to stdout, appending a newline.
+ */
+int
+puts(s)
+ char const *s;
+{
+ int retval;
+ size_t c = strlen(s);
+ struct __suio uio;
+ struct __siov iov[2];
+
+ iov[0].iov_base = (void *)s;
+ iov[0].iov_len = c;
+ iov[1].iov_base = "\n";
+ iov[1].iov_len = 1;
+ uio.uio_resid = c + 1;
+ uio.uio_iov = &iov[0];
+ uio.uio_iovcnt = 2;
+ FLOCKFILE(stdout);
+ ORIENT(stdout, -1);
+ retval = __sfvwrite(stdout, &uio) ? EOF : '\n';
+ FUNLOCKFILE(stdout);
+ return (retval);
+}
diff --git a/lib/libc/stdio/putw.c b/lib/libc/stdio/putw.c
new file mode 100644
index 0000000..8fc1b4d
--- /dev/null
+++ b/lib/libc/stdio/putw.c
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)putw.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "fvwrite.h"
+#include "libc_private.h"
+
+int
+putw(w, fp)
+ int w;
+ FILE *fp;
+{
+ int retval;
+ struct __suio uio;
+ struct __siov iov;
+
+ iov.iov_base = &w;
+ iov.iov_len = uio.uio_resid = sizeof(w);
+ uio.uio_iov = &iov;
+ uio.uio_iovcnt = 1;
+ FLOCKFILE(fp);
+ retval = __sfvwrite(fp, &uio);
+ FUNLOCKFILE(fp);
+ return (retval);
+}
diff --git a/lib/libc/stdio/putwc.3 b/lib/libc/stdio/putwc.3
new file mode 100644
index 0000000..a661c77
--- /dev/null
+++ b/lib/libc/stdio/putwc.3
@@ -0,0 +1,103 @@
+.\" $NetBSD: putwc.3,v 1.2 2002/02/07 07:00:26 ross Exp $
+.\"
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)putc.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd March 3, 2004
+.Dt PUTWC 3
+.Os
+.Sh NAME
+.Nm fputwc ,
+.Nm putwc ,
+.Nm putwchar
+.Nd output a wide character to a stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.In wchar.h
+.Ft wint_t
+.Fn fputwc "wchar_t wc" "FILE *stream"
+.Ft wint_t
+.Fn putwc "wchar_t wc" "FILE *stream"
+.Ft wint_t
+.Fn putwchar "wchar_t wc"
+.Sh DESCRIPTION
+The
+.Fn fputwc
+function
+writes the wide character
+.Fa wc
+to the output stream pointed to by
+.Fa stream .
+.Pp
+The
+.Fn putwc
+function
+acts essentially identically to
+.Fn fputwc .
+.Pp
+The
+.Fn putwchar
+function
+is identical to
+.Fn putwc
+with an output stream of
+.Dv stdout .
+.Sh RETURN VALUES
+The
+.Fn fputwc ,
+.Fn putwc ,
+and
+.Fn putwchar
+functions
+return the wide character written.
+If an error occurs, the value
+.Dv WEOF
+is returned.
+.Sh SEE ALSO
+.Xr ferror 3 ,
+.Xr fopen 3 ,
+.Xr getwc 3 ,
+.Xr putc 3 ,
+.Xr stdio 3
+.Sh STANDARDS
+The
+.Fn fputwc ,
+.Fn putwc ,
+and
+.Fn putwchar
+functions
+conform to
+.St -isoC-99 .
diff --git a/lib/libc/stdio/putwc.c b/lib/libc/stdio/putwc.c
new file mode 100644
index 0000000..56acf50
--- /dev/null
+++ b/lib/libc/stdio/putwc.c
@@ -0,0 +1,59 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <wchar.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+#include "xlocale_private.h"
+
+#undef putwc
+
+/*
+ * Synonym for fputwc(). The only difference is that putwc(), if it is a
+ * macro, may evaluate `fp' more than once.
+ */
+wint_t
+putwc_l(wchar_t wc, FILE *fp, locale_t locale)
+{
+ FIX_LOCALE(locale);
+ return (fputwc_l(wc, fp, locale));
+}
+wint_t
+putwc(wchar_t wc, FILE *fp)
+{
+ return putwc_l(wc, fp, __get_locale());
+}
diff --git a/lib/libc/stdio/putwchar.c b/lib/libc/stdio/putwchar.c
new file mode 100644
index 0000000..8673bd5
--- /dev/null
+++ b/lib/libc/stdio/putwchar.c
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <wchar.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+#include "xlocale_private.h"
+
+#undef putwchar
+
+/*
+ * Synonym for fputwc(wc, stdout).
+ */
+wint_t
+putwchar_l(wchar_t wc, locale_t locale)
+{
+ FIX_LOCALE(locale);
+ return (fputwc_l(wc, stdout, locale));
+}
+wint_t
+putwchar(wchar_t wc)
+{
+ return putwchar_l(wc, __get_locale());
+}
diff --git a/lib/libc/stdio/refill.c b/lib/libc/stdio/refill.c
new file mode 100644
index 0000000..f2a1f16
--- /dev/null
+++ b/lib/libc/stdio/refill.c
@@ -0,0 +1,146 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)refill.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+#include "local.h"
+
+static int lflush(FILE *);
+
+static int
+lflush(FILE *fp)
+{
+ int ret = 0;
+
+ if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR)) {
+ FLOCKFILE(fp);
+ ret = __sflush(fp);
+ FUNLOCKFILE(fp);
+ }
+ return (ret);
+}
+
+/*
+ * Refill a stdio buffer.
+ * Return EOF on eof or error, 0 otherwise.
+ */
+int
+__srefill(FILE *fp)
+{
+
+ /* make sure stdio is set up */
+ if (!__sdidinit)
+ __sinit();
+
+ ORIENT(fp, -1);
+
+ fp->_r = 0; /* largely a convenience for callers */
+
+ /* SysV does not make this test; take it out for compatibility */
+ if (fp->_flags & __SEOF)
+ return (EOF);
+
+ /* if not already reading, have to be reading and writing */
+ if ((fp->_flags & __SRD) == 0) {
+ if ((fp->_flags & __SRW) == 0) {
+ errno = EBADF;
+ fp->_flags |= __SERR;
+ return (EOF);
+ }
+ /* switch to reading */
+ if (fp->_flags & __SWR) {
+ if (__sflush(fp))
+ return (EOF);
+ fp->_flags &= ~__SWR;
+ fp->_w = 0;
+ fp->_lbfsize = 0;
+ }
+ fp->_flags |= __SRD;
+ } else {
+ /*
+ * We were reading. If there is an ungetc buffer,
+ * we must have been reading from that. Drop it,
+ * restoring the previous buffer (if any). If there
+ * is anything in that buffer, return.
+ */
+ if (HASUB(fp)) {
+ FREEUB(fp);
+ if ((fp->_r = fp->_ur) != 0) {
+ fp->_p = fp->_up;
+ return (0);
+ }
+ }
+ }
+
+ if (fp->_bf._base == NULL)
+ __smakebuf(fp);
+
+ /*
+ * Before reading from a line buffered or unbuffered file,
+ * flush all line buffered output files, per the ANSI C
+ * standard.
+ */
+ if (fp->_flags & (__SLBF|__SNBF)) {
+ /* Ignore this file in _fwalk to avoid potential deadlock. */
+ fp->_flags |= __SIGN;
+ (void) _fwalk(lflush);
+ fp->_flags &= ~__SIGN;
+
+ /* Now flush this file without locking it. */
+ if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
+ __sflush(fp);
+ }
+ fp->_p = fp->_bf._base;
+ fp->_r = _sread(fp, (char *)fp->_p, fp->_bf._size);
+ fp->_flags &= ~__SMOD; /* buffer contents are again pristine */
+ if (fp->_r <= 0) {
+ if (fp->_r == 0)
+ fp->_flags |= __SEOF;
+ else {
+ fp->_r = 0;
+ fp->_flags |= __SERR;
+ }
+ return (EOF);
+ }
+ return (0);
+}
diff --git a/lib/libc/stdio/remove.3 b/lib/libc/stdio/remove.3
new file mode 100644
index 0000000..e7a57fe
--- /dev/null
+++ b/lib/libc/stdio/remove.3
@@ -0,0 +1,83 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)remove.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt REMOVE 3
+.Os
+.Sh NAME
+.Nm remove
+.Nd remove directory entry
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft int
+.Fn remove "const char *path"
+.Sh DESCRIPTION
+The
+.Fn remove
+function removes the file or directory specified by
+.Fa path .
+.Pp
+If
+.Fa path
+specifies a directory,
+.Fn remove "path"
+is the equivalent of
+.Fn rmdir "path" .
+Otherwise, it is the equivalent of
+.Fn unlink "path" .
+.Sh RETURN VALUES
+.Rv -std remove
+.Sh ERRORS
+The
+.Fn remove
+function
+may fail and set
+.Va errno
+for any of the errors specified for the routines
+.Xr lstat 2 ,
+.Xr rmdir 2
+or
+.Xr unlink 2 .
+.Sh SEE ALSO
+.Xr rmdir 2 ,
+.Xr unlink 2
+.Sh STANDARDS
+The
+.Fn remove
+function conforms to
+.St -isoC
+and
+.St -xpg4.2 .
diff --git a/lib/libc/stdio/remove.c b/lib/libc/stdio/remove.c
new file mode 100644
index 0000000..f08e47c
--- /dev/null
+++ b/lib/libc/stdio/remove.c
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)remove.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
+
+int
+remove(file)
+ const char *file;
+{
+ struct stat sb;
+
+ if (lstat(file, &sb) < 0)
+ return (-1);
+ if (S_ISDIR(sb.st_mode))
+ return (rmdir(file));
+ return (unlink(file));
+}
diff --git a/lib/libc/stdio/rewind.c b/lib/libc/stdio/rewind.c
new file mode 100644
index 0000000..73ef2c6
--- /dev/null
+++ b/lib/libc/stdio/rewind.c
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rewind.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <stdio.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+
+void
+rewind(FILE *fp)
+{
+ int serrno = errno;
+
+ /* make sure stdio is set up */
+ if (!__sdidinit)
+ __sinit();
+
+ FLOCKFILE(fp);
+ if (_fseeko(fp, (off_t)0, SEEK_SET, 1) == 0) {
+ clearerr_unlocked(fp);
+ errno = serrno;
+ }
+ FUNLOCKFILE(fp);
+}
diff --git a/lib/libc/stdio/rget.c b/lib/libc/stdio/rget.c
new file mode 100644
index 0000000..71c75e0
--- /dev/null
+++ b/lib/libc/stdio/rget.c
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rget.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include "local.h"
+
+/*
+ * Handle getc() when the buffer ran out:
+ * Refill, then return the first character
+ * in the newly-filled buffer.
+ */
+int
+__srget(FILE *fp)
+{
+ if (__srefill(fp) == 0) {
+ fp->_r--;
+ return (*fp->_p++);
+ }
+ return (EOF);
+}
diff --git a/lib/libc/stdio/scanf.3 b/lib/libc/stdio/scanf.3
new file mode 100644
index 0000000..319455a
--- /dev/null
+++ b/lib/libc/stdio/scanf.3
@@ -0,0 +1,513 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)scanf.3 8.2 (Berkeley) 12/11/93
+.\" $FreeBSD$
+.\"
+.Dd January 4, 2003
+.Dt SCANF 3
+.Os
+.Sh NAME
+.Nm scanf ,
+.Nm fscanf ,
+.Nm sscanf ,
+.Nm vscanf ,
+.Nm vsscanf ,
+.Nm vfscanf
+.Nd input format conversion
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft int
+.Fn scanf "const char * restrict format" ...
+.Ft int
+.Fn fscanf "FILE * restrict stream" "const char * restrict format" ...
+.Ft int
+.Fn sscanf "const char * restrict str" "const char * restrict format" ...
+.In stdarg.h
+.Ft int
+.Fn vscanf "const char * restrict format" "va_list ap"
+.Ft int
+.Fn vsscanf "const char * restrict str" "const char * restrict format" "va_list ap"
+.Ft int
+.Fn vfscanf "FILE * restrict stream" "const char * restrict format" "va_list ap"
+.Sh DESCRIPTION
+The
+.Fn scanf
+family of functions scans input according to a
+.Fa format
+as described below.
+This format may contain
+.Em conversion specifiers ;
+the results from such conversions, if any,
+are stored through the
+.Em pointer
+arguments.
+The
+.Fn scanf
+function
+reads input from the standard input stream
+.Dv stdin ,
+.Fn fscanf
+reads input from the stream pointer
+.Fa stream ,
+and
+.Fn sscanf
+reads its input from the character string pointed to by
+.Fa str .
+The
+.Fn vfscanf
+function
+is analogous to
+.Xr vfprintf 3
+and reads input from the stream pointer
+.Fa stream
+using a variable argument list of pointers (see
+.Xr stdarg 3 ) .
+The
+.Fn vscanf
+function scans a variable argument list from the standard input and
+the
+.Fn vsscanf
+function scans it from a string;
+these are analogous to
+the
+.Fn vprintf
+and
+.Fn vsprintf
+functions respectively.
+Each successive
+.Em pointer
+argument must correspond properly with
+each successive conversion specifier
+(but see the
+.Cm *
+conversion below).
+All conversions are introduced by the
+.Cm %
+(percent sign) character.
+The
+.Fa format
+string
+may also contain other characters.
+White space (such as blanks, tabs, or newlines) in the
+.Fa format
+string match any amount of white space, including none, in the input.
+Everything else
+matches only itself.
+Scanning stops
+when an input character does not match such a format character.
+Scanning also stops
+when an input conversion cannot be made (see below).
+.Sh CONVERSIONS
+Following the
+.Cm %
+character introducing a conversion
+there may be a number of
+.Em flag
+characters, as follows:
+.Bl -tag -width ".Cm l No (ell)"
+.It Cm *
+Suppresses assignment.
+The conversion that follows occurs as usual, but no pointer is used;
+the result of the conversion is simply discarded.
+.It Cm hh
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt char
+(rather than
+.Vt int ) .
+.It Cm h
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt "short int"
+(rather than
+.Vt int ) .
+.It Cm l No (ell)
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt "long int"
+(rather than
+.Vt int ) ,
+that the conversion will be one of
+.Cm a , e , f ,
+or
+.Cm g
+and the next pointer is a pointer to
+.Vt double
+(rather than
+.Vt float ) ,
+or that the conversion will be one of
+.Cm c ,
+.Cm s
+or
+.Cm \&[
+and the next pointer is a pointer to an array of
+.Vt wchar_t
+(rather than
+.Vt char ) .
+.It Cm ll No (ell ell)
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt "long long int"
+(rather than
+.Vt int ) .
+.It Cm L
+Indicates that the conversion will be one of
+.Cm a , e , f ,
+or
+.Cm g
+and the next pointer is a pointer to
+.Vt "long double" .
+.It Cm j
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt intmax_t
+(rather than
+.Vt int ) .
+.It Cm t
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt ptrdiff_t
+(rather than
+.Vt int ) .
+.It Cm z
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt size_t
+(rather than
+.Vt int ) .
+.It Cm q
+(deprecated.)
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt "long long int"
+(rather than
+.Vt int ) .
+.El
+.Pp
+In addition to these flags,
+there may be an optional maximum field width,
+expressed as a decimal integer,
+between the
+.Cm %
+and the conversion.
+If no width is given,
+a default of
+.Dq infinity
+is used (with one exception, below);
+otherwise at most this many bytes are scanned
+in processing the conversion.
+In the case of the
+.Cm lc ,
+.Cm ls
+and
+.Cm l[
+conversions, the field width specifies the maximum number
+of multibyte characters that will be scanned.
+Before conversion begins,
+most conversions skip white space;
+this white space is not counted against the field width.
+.Pp
+The following conversions are available:
+.Bl -tag -width XXXX
+.It Cm %
+Matches a literal
+.Ql % .
+That is,
+.Dq Li %%
+in the format string
+matches a single input
+.Ql %
+character.
+No conversion is done, and assignment does not occur.
+.It Cm d
+Matches an optionally signed decimal integer;
+the next pointer must be a pointer to
+.Vt int .
+.It Cm i
+Matches an optionally signed integer;
+the next pointer must be a pointer to
+.Vt int .
+The integer is read in base 16 if it begins
+with
+.Ql 0x
+or
+.Ql 0X ,
+in base 8 if it begins with
+.Ql 0 ,
+and in base 10 otherwise.
+Only characters that correspond to the base are used.
+.It Cm o
+Matches an octal integer;
+the next pointer must be a pointer to
+.Vt "unsigned int" .
+.It Cm u
+Matches an optionally signed decimal integer;
+the next pointer must be a pointer to
+.Vt "unsigned int" .
+.It Cm x , X
+Matches an optionally signed hexadecimal integer;
+the next pointer must be a pointer to
+.Vt "unsigned int" .
+.It Cm a , A , e , E , f , F , g , G
+Matches a floating-point number in the style of
+.Xr strtod 3 .
+The next pointer must be a pointer to
+.Vt float
+(unless
+.Cm l
+or
+.Cm L
+is specified.)
+.It Cm s
+Matches a sequence of non-white-space characters;
+the next pointer must be a pointer to
+.Vt char ,
+and the array must be large enough to accept all the sequence and the
+terminating
+.Dv NUL
+character.
+The input string stops at white space
+or at the maximum field width, whichever occurs first.
+.Pp
+If an
+.Cm l
+qualifier is present, the next pointer must be a pointer to
+.Vt wchar_t ,
+into which the input will be placed after conversion by
+.Xr mbrtowc 3 .
+.It Cm S
+The same as
+.Cm ls .
+.It Cm c
+Matches a sequence of
+.Em width
+count
+characters (default 1);
+the next pointer must be a pointer to
+.Vt char ,
+and there must be enough room for all the characters
+(no terminating
+.Dv NUL
+is added).
+The usual skip of leading white space is suppressed.
+To skip white space first, use an explicit space in the format.
+.Pp
+If an
+.Cm l
+qualifier is present, the next pointer must be a pointer to
+.Vt wchar_t ,
+into which the input will be placed after conversion by
+.Xr mbrtowc 3 .
+.It Cm C
+The same as
+.Cm lc .
+.It Cm \&[
+Matches a nonempty sequence of characters from the specified set
+of accepted characters;
+the next pointer must be a pointer to
+.Vt char ,
+and there must be enough room for all the characters in the string,
+plus a terminating
+.Dv NUL
+character.
+The usual skip of leading white space is suppressed.
+The string is to be made up of characters in
+(or not in)
+a particular set;
+the set is defined by the characters between the open bracket
+.Cm [
+character
+and a close bracket
+.Cm ]
+character.
+The set
+.Em excludes
+those characters
+if the first character after the open bracket is a circumflex
+.Cm ^ .
+To include a close bracket in the set,
+make it the first character after the open bracket
+or the circumflex;
+any other position will end the set.
+The hyphen character
+.Cm -
+is also special;
+when placed between two other characters,
+it adds all intervening characters to the set.
+To include a hyphen,
+make it the last character before the final close bracket.
+For instance,
+.Ql [^]0-9-]
+means the set
+.Dq "everything except close bracket, zero through nine, and hyphen" .
+The string ends with the appearance of a character not in the
+(or, with a circumflex, in) set
+or when the field width runs out.
+.Pp
+If an
+.Cm l
+qualifier is present, the next pointer must be a pointer to
+.Vt wchar_t ,
+into which the input will be placed after conversion by
+.Xr mbrtowc 3 .
+.It Cm p
+Matches a pointer value (as printed by
+.Ql %p
+in
+.Xr printf 3 ) ;
+the next pointer must be a pointer to
+.Vt void .
+.It Cm n
+Nothing is expected;
+instead, the number of characters consumed thus far from the input
+is stored through the next pointer,
+which must be a pointer to
+.Vt int .
+This is
+.Em not
+a conversion, although it can be suppressed with the
+.Cm *
+flag.
+.El
+.Pp
+The decimal point
+character is defined in the program's locale (category
+.Dv LC_NUMERIC ) .
+.Pp
+For backwards compatibility, a
+.Dq conversion
+of
+.Ql %\e0
+causes an immediate return of
+.Dv EOF .
+.Sh RETURN VALUES
+These
+functions
+return
+the number of input items assigned, which can be fewer than provided
+for, or even zero, in the event of a matching failure.
+Zero
+indicates that, while there was input available,
+no conversions were assigned;
+typically this is due to an invalid input character,
+such as an alphabetic character for a
+.Ql %d
+conversion.
+The value
+.Dv EOF
+is returned if an input failure occurs before any conversion such as an
+end-of-file occurs.
+If an error or end-of-file occurs after conversion
+has begun,
+the number of conversions which were successfully completed is returned.
+.Sh SEE ALSO
+.Xr getc 3 ,
+.Xr mbrtowc 3 ,
+.Xr printf 3 ,
+.Xr strtod 3 ,
+.Xr strtol 3 ,
+.Xr strtoul 3 ,
+.Xr wscanf 3
+.Sh STANDARDS
+The functions
+.Fn fscanf ,
+.Fn scanf ,
+.Fn sscanf ,
+.Fn vfscanf ,
+.Fn vscanf
+and
+.Fn vsscanf
+conform to
+.St -isoC-99 .
+.Sh BUGS
+Earlier implementations of
+.Nm
+treated
+.Cm \&%D , \&%E , \&%F , \&%O
+and
+.Cm \&%X
+as their lowercase equivalents with an
+.Cm l
+modifier.
+In addition,
+.Nm
+treated an unknown conversion character as
+.Cm \&%d
+or
+.Cm \&%D ,
+depending on its case.
+This functionality has been removed.
+.Pp
+Numerical strings are truncated to 512 characters; for example,
+.Cm %f
+and
+.Cm %d
+are implicitly
+.Cm %512f
+and
+.Cm %512d .
+.Pp
+The
+.Cm %n$
+modifiers for positional arguments are not implemented.
+.Pp
+The
+.Nm
+family of functions do not correctly handle multibyte characters in the
+.Fa format
+argument.
diff --git a/lib/libc/stdio/scanf.c b/lib/libc/stdio/scanf.c
new file mode 100644
index 0000000..ba33caa
--- /dev/null
+++ b/lib/libc/stdio/scanf.c
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)scanf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <stdarg.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+#include "xlocale_private.h"
+
+int
+scanf(char const * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ FLOCKFILE(stdin);
+ ret = __svfscanf(stdin, __get_locale(), fmt, ap);
+ FUNLOCKFILE(stdin);
+ va_end(ap);
+ return (ret);
+}
+int
+scanf_l(locale_t locale, char const * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+ FIX_LOCALE(locale);
+
+ va_start(ap, fmt);
+ FLOCKFILE(stdin);
+ ret = __svfscanf(stdin, locale, fmt, ap);
+ FUNLOCKFILE(stdin);
+ va_end(ap);
+ return (ret);
+}
diff --git a/lib/libc/stdio/setbuf.3 b/lib/libc/stdio/setbuf.3
new file mode 100644
index 0000000..be88034
--- /dev/null
+++ b/lib/libc/stdio/setbuf.3
@@ -0,0 +1,209 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)setbuf.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt SETBUF 3
+.Os
+.Sh NAME
+.Nm setbuf ,
+.Nm setbuffer ,
+.Nm setlinebuf ,
+.Nm setvbuf
+.Nd stream buffering operations
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft void
+.Fn setbuf "FILE * restrict stream" "char * restrict buf"
+.Ft void
+.Fn setbuffer "FILE *stream" "char *buf" "int size"
+.Ft int
+.Fn setlinebuf "FILE *stream"
+.Ft int
+.Fn setvbuf "FILE * restrict stream" "char * restrict buf" "int mode" "size_t size"
+.Sh DESCRIPTION
+The three types of buffering available are unbuffered, block buffered,
+and line buffered.
+When an output stream is unbuffered, information appears on the
+destination file or terminal as soon as written;
+when it is block buffered many characters are saved up and written as a block;
+when it is line buffered characters are saved up until a newline is
+output or input is read from any stream attached to a terminal device
+(typically
+.Dv stdin ) .
+The function
+.Xr fflush 3
+may be used to force the block out early.
+(See
+.Xr fclose 3 . )
+.Pp
+Normally all files are block buffered.
+When the first
+.Tn I/O
+operation occurs on a file,
+.Xr malloc 3
+is called,
+and an optimally-sized buffer is obtained.
+If a stream refers to a terminal
+(as
+.Dv stdout
+normally does) it is line buffered.
+The standard error stream
+.Dv stderr
+is always unbuffered.
+.Pp
+The
+.Fn setvbuf
+function
+may be used to alter the buffering behavior of a stream.
+The
+.Fa mode
+argument must be one of the following three macros:
+.Bl -tag -width _IOFBF -offset indent
+.It Dv _IONBF
+unbuffered
+.It Dv _IOLBF
+line buffered
+.It Dv _IOFBF
+fully buffered
+.El
+.Pp
+The
+.Fa size
+argument may be given as zero
+to obtain deferred optimal-size buffer allocation as usual.
+If it is not zero,
+then except for unbuffered files, the
+.Fa buf
+argument should point to a buffer at least
+.Fa size
+bytes long;
+this buffer will be used instead of the current buffer.
+If
+.Fa buf
+is not
+.Dv NULL ,
+it is the caller's responsibility to
+.Xr free 3
+this buffer after closing the stream.
+(If the
+.Fa size
+argument
+is not zero but
+.Fa buf
+is
+.Dv NULL ,
+a buffer of the given size will be allocated immediately,
+and released on close.
+This is an extension to ANSI C;
+portable code should use a size of 0 with any
+.Dv NULL
+buffer.)
+.Pp
+The
+.Fn setvbuf
+function may be used at any time,
+but may have peculiar side effects
+(such as discarding input or flushing output)
+if the stream is ``active''.
+Portable applications should call it only once on any given stream,
+and before any
+.Tn I/O
+is performed.
+.Pp
+The other three calls are, in effect, simply aliases for calls to
+.Fn setvbuf .
+Except for the lack of a return value, the
+.Fn setbuf
+function is exactly equivalent to the call
+.Pp
+.Dl "setvbuf(stream, buf, buf ? _IOFBF : _IONBF, BUFSIZ);"
+.Pp
+The
+.Fn setbuffer
+function
+is the same, except that the size of the buffer is up to the caller,
+rather than being determined by the default
+.Dv BUFSIZ .
+The
+.Fn setlinebuf
+function
+is exactly equivalent to the call:
+.Pp
+.Dl "setvbuf(stream, (char *)NULL, _IOLBF, 0);"
+.Sh RETURN VALUES
+The
+.Fn setvbuf
+function returns 0 on success, or
+.Dv EOF
+if the request cannot be honored
+(note that the stream is still functional in this case).
+.Pp
+The
+.Fn setlinebuf
+function returns what the equivalent
+.Fn setvbuf
+would have returned.
+.Sh SEE ALSO
+.Xr fclose 3 ,
+.Xr fopen 3 ,
+.Xr fread 3 ,
+.Xr malloc 3 ,
+.Xr printf 3 ,
+.Xr puts 3
+.Sh STANDARDS
+The
+.Fn setbuf
+and
+.Fn setvbuf
+functions
+conform to
+.St -isoC .
+.Sh BUGS
+The
+.Fn setbuffer
+and
+.Fn setlinebuf
+functions are not portable to versions of
+.Bx
+before
+.Bx 4.2 .
+On
+.Bx 4.2
+and
+.Bx 4.3
+systems,
+.Fn setbuf
+always uses a suboptimal buffer size and should be avoided.
diff --git a/lib/libc/stdio/setbuf.c b/lib/libc/stdio/setbuf.c
new file mode 100644
index 0000000..0daef54
--- /dev/null
+++ b/lib/libc/stdio/setbuf.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setbuf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include "local.h"
+
+void
+setbuf(FILE * __restrict fp, char * __restrict buf)
+{
+ (void) setvbuf(fp, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
+}
diff --git a/lib/libc/stdio/setbuffer.c b/lib/libc/stdio/setbuffer.c
new file mode 100644
index 0000000..dd1caa0
--- /dev/null
+++ b/lib/libc/stdio/setbuffer.c
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setbuffer.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+
+void
+setbuffer(fp, buf, size)
+ FILE *fp;
+ char *buf;
+ int size;
+{
+
+ (void)setvbuf(fp, buf, buf ? _IOFBF : _IONBF, (size_t)size);
+}
+
+/*
+ * set line buffering
+ */
+int
+setlinebuf(fp)
+ FILE *fp;
+{
+
+ return (setvbuf(fp, (char *)NULL, _IOLBF, (size_t)0));
+}
diff --git a/lib/libc/stdio/setvbuf.c b/lib/libc/stdio/setvbuf.c
new file mode 100644
index 0000000..d897925
--- /dev/null
+++ b/lib/libc/stdio/setvbuf.c
@@ -0,0 +1,161 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setvbuf.c 8.2 (Berkeley) 11/16/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+#include "local.h"
+#include "libc_private.h"
+
+/*
+ * Set one of the three kinds of buffering, optionally including
+ * a buffer.
+ */
+int
+setvbuf(FILE * __restrict fp, char * __restrict buf, int mode, size_t size)
+{
+ int ret, flags;
+ size_t iosize;
+ int ttyflag;
+
+ /*
+ * Verify arguments. The `int' limit on `size' is due to this
+ * particular implementation. Note, buf and size are ignored
+ * when setting _IONBF.
+ */
+ if (mode != _IONBF)
+ if ((mode != _IOFBF && mode != _IOLBF) || (int)size < 0)
+ return (EOF);
+
+ FLOCKFILE(fp);
+ /*
+ * Write current buffer, if any. Discard unread input (including
+ * ungetc data), cancel line buffering, and free old buffer if
+ * malloc()ed. We also clear any eof condition, as if this were
+ * a seek.
+ */
+ ret = 0;
+ (void)__sflush(fp);
+ if (HASUB(fp))
+ FREEUB(fp);
+ fp->_r = fp->_lbfsize = 0;
+ flags = fp->_flags;
+ if (flags & __SMBF)
+ free((void *)fp->_bf._base);
+ flags &= ~(__SLBF | __SNBF | __SMBF | __SOPT | __SOFF | __SNPT | __SEOF);
+
+ /* If setting unbuffered mode, skip all the hard work. */
+ if (mode == _IONBF)
+ goto nbf;
+
+ /*
+ * Find optimal I/O size for seek optimization. This also returns
+ * a `tty flag' to suggest that we check isatty(fd), but we do not
+ * care since our caller told us how to buffer.
+ */
+ flags |= __swhatbuf(fp, &iosize, &ttyflag);
+ if (size == 0) {
+ buf = NULL; /* force local allocation */
+ size = iosize;
+ }
+
+ /* Allocate buffer if needed. */
+ if (buf == NULL) {
+ if ((buf = malloc(size)) == NULL) {
+ /*
+ * Unable to honor user's request. We will return
+ * failure, but try again with file system size.
+ */
+ ret = EOF;
+ if (size != iosize) {
+ size = iosize;
+ buf = malloc(size);
+ }
+ }
+ if (buf == NULL) {
+ /* No luck; switch to unbuffered I/O. */
+nbf:
+ fp->_flags = flags | __SNBF;
+ fp->_w = 0;
+ fp->_bf._base = fp->_p = fp->_nbuf;
+ fp->_bf._size = 1;
+ FUNLOCKFILE(fp);
+ return (ret);
+ }
+ flags |= __SMBF;
+ }
+
+ /*
+ * Kill any seek optimization if the buffer is not the
+ * right size.
+ *
+ * SHOULD WE ALLOW MULTIPLES HERE (i.e., ok iff (size % iosize) == 0)?
+ */
+ if (size != iosize)
+ flags |= __SNPT;
+
+ /*
+ * Fix up the FILE fields, and set __cleanup for output flush on
+ * exit (since we are buffered in some way).
+ */
+ if (mode == _IOLBF)
+ flags |= __SLBF;
+ fp->_flags = flags;
+ fp->_bf._base = fp->_p = (unsigned char *)buf;
+ fp->_bf._size = size;
+ /* fp->_lbfsize is still 0 */
+ if (flags & __SWR) {
+ /*
+ * Begin or continue writing: see __swsetup(). Note
+ * that __SNBF is impossible (it was handled earlier).
+ */
+ if (flags & __SLBF) {
+ fp->_w = 0;
+ fp->_lbfsize = -fp->_bf._size;
+ } else
+ fp->_w = size;
+ } else {
+ /* begin/continue reading, or stay in intermediate state */
+ fp->_w = 0;
+ }
+ __cleanup = _cleanup;
+
+ FUNLOCKFILE(fp);
+ return (ret);
+}
diff --git a/lib/libc/stdio/snprintf.c b/lib/libc/stdio/snprintf.c
new file mode 100644
index 0000000..d0ae5a6
--- /dev/null
+++ b/lib/libc/stdio/snprintf.c
@@ -0,0 +1,105 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)snprintf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include "xlocale_private.h"
+
+#include "local.h"
+
+int
+snprintf(char * __restrict str, size_t n, char const * __restrict fmt, ...)
+{
+ size_t on;
+ int ret;
+ va_list ap;
+ FILE f = FAKE_FILE;
+
+ on = n;
+ if (n != 0)
+ n--;
+ if (n > INT_MAX) {
+ errno = EOVERFLOW;
+ *str = '\0';
+ return (EOF);
+ }
+ va_start(ap, fmt);
+ f._flags = __SWR | __SSTR;
+ f._bf._base = f._p = (unsigned char *)str;
+ f._bf._size = f._w = n;
+ ret = __vfprintf(&f, __get_locale(), fmt, ap);
+ if (on > 0)
+ *f._p = '\0';
+ va_end(ap);
+ return (ret);
+}
+int
+snprintf_l(char * __restrict str, size_t n, locale_t locale,
+ char const * __restrict fmt, ...)
+{
+ size_t on;
+ int ret;
+ va_list ap;
+ FILE f = FAKE_FILE;
+ FIX_LOCALE(locale);
+
+ on = n;
+ if (n != 0)
+ n--;
+ if (n > INT_MAX) {
+ errno = EOVERFLOW;
+ *str = '\0';
+ return (EOF);
+ }
+ va_start(ap, fmt);
+ f._flags = __SWR | __SSTR;
+ f._bf._base = f._p = (unsigned char *)str;
+ f._bf._size = f._w = n;
+ ret = __vfprintf(&f, locale, fmt, ap);
+ if (on > 0)
+ *f._p = '\0';
+ va_end(ap);
+ return (ret);
+}
diff --git a/lib/libc/stdio/sprintf.c b/lib/libc/stdio/sprintf.c
new file mode 100644
index 0000000..6e20e04
--- /dev/null
+++ b/lib/libc/stdio/sprintf.c
@@ -0,0 +1,73 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)sprintf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <limits.h>
+#include "local.h"
+#include "xlocale_private.h"
+
+int
+sprintf(char * __restrict str, char const * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vsprintf(str, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
+int
+sprintf_l(char * __restrict str, locale_t locale, char const * __restrict fmt,
+ ...)
+{
+ int ret;
+ va_list ap;
+ FIX_LOCALE(locale);
+
+ va_start(ap, fmt);
+ ret = vsprintf_l(str, locale, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
diff --git a/lib/libc/stdio/sscanf.c b/lib/libc/stdio/sscanf.c
new file mode 100644
index 0000000..1c339eb
--- /dev/null
+++ b/lib/libc/stdio/sscanf.c
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)sscanf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <xlocale.h>
+#include "local.h"
+
+int
+sscanf(const char * __restrict str, char const * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vsscanf(str, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
+int
+sscanf_l(const char * __restrict str, locale_t locale,
+ char const * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vsscanf_l(str, locale, fmt, ap);
+ va_end(ap);
+ return (ret);
+}
diff --git a/lib/libc/stdio/stdio.3 b/lib/libc/stdio/stdio.3
new file mode 100644
index 0000000..53320b5
--- /dev/null
+++ b/lib/libc/stdio/stdio.3
@@ -0,0 +1,333 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)stdio.3 8.7 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd March 3, 2009
+.Dt STDIO 3
+.Os
+.Sh NAME
+.Nm stdio
+.Nd standard input/output library functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Vt FILE *stdin ;
+.Vt FILE *stdout ;
+.Vt FILE *stderr ;
+.Sh DESCRIPTION
+The standard
+.Tn I/O
+library provides a simple and efficient buffered stream
+.Tn I/O
+interface.
+Input and output is mapped into logical data streams
+and the physical
+.Tn I/O
+characteristics are concealed.
+The functions and macros are listed
+below; more information is available from the individual man pages.
+.Pp
+A stream is associated with an external file (which may be a physical
+device) by
+.Em opening
+a file, which may involve creating a new file.
+Creating an
+existing file causes its former contents to be discarded.
+If a file can support positioning requests (such as a disk file, as opposed
+to a terminal) then a
+.Em file position indicator
+associated with the stream is positioned at the start of the file (byte
+zero), unless the file is opened with append mode.
+If append mode
+is used, the position indicator will be placed at the end-of-file.
+The position indicator is maintained by subsequent reads, writes
+and positioning requests.
+All input occurs as if the characters
+were read by successive calls to the
+.Xr fgetc 3
+function; all output takes place as if all characters were
+written by successive calls to the
+.Xr fputc 3
+function.
+.Pp
+A file is disassociated from a stream by
+.Em closing
+the file.
+Output streams are flushed (any unwritten buffer contents are transferred
+to the host environment) before the stream is disassociated from the file.
+The value of a pointer to a
+.Dv FILE
+object is indeterminate (garbage) after a file is closed.
+.Pp
+A file may be subsequently reopened, by the same or another program
+execution, and its contents reclaimed or modified (if it can be repositioned
+at the start).
+If the main function returns to its original caller, or
+the
+.Xr exit 3
+function is called, all open files are closed (hence all output
+streams are flushed) before program termination.
+Other methods
+of program termination may not close files properly and hence
+buffered output may be lost.
+In particular,
+.Xr _exit 2
+does not flush stdio files.
+Neither does an exit due to a signal.
+Buffers are flushed by
+.Xr abort 3
+as required by POSIX, although previous implementations did not.
+.Pp
+This implementation makes no distinction between
+.Dq text
+and
+.Dq binary
+streams.
+In effect, all streams are binary.
+No translation is performed and no extra padding appears on any stream.
+.Pp
+At program startup, three streams are predefined and need not be
+opened explicitly:
+.Bl -bullet -compact -offset indent
+.It
+.Em standard input
+(for reading conventional input),
+.It
+.Em standard output
+(for writing conventional output), and
+.It
+.Em standard error
+(for writing diagnostic output).
+.El
+These streams are abbreviated
+.Dv stdin , stdout
+and
+.Dv stderr .
+Initially, the standard error stream
+is unbuffered; the standard input and output streams are
+fully buffered if and only if the streams do not refer to
+an interactive or
+.Dq terminal
+device, as determined by the
+.Xr isatty 3
+function.
+In fact,
+.Em all
+freshly-opened streams that refer to terminal devices
+default to line buffering, and
+pending output to such streams is written automatically
+whenever such an input stream is read.
+Note that this applies only to
+.Dq "true reads" ;
+if the read request can be satisfied by existing buffered data,
+no automatic flush will occur.
+In these cases,
+or when a large amount of computation is done after printing
+part of a line on an output terminal, it is necessary to
+.Xr fflush 3
+the standard output before going off and computing so that the output
+will appear.
+Alternatively, these defaults may be modified via the
+.Xr setvbuf 3
+function.
+.Pp
+The
+.Nm
+library is a part of the library
+.Nm libc
+and routines are automatically loaded as needed by the C compiler.
+The
+.Tn SYNOPSIS
+sections of the following manual pages indicate which include files
+are to be used, what the compiler declaration for the function
+looks like and which external variables are of interest.
+.Pp
+The following are defined as macros;
+these names may not be re-used
+without first removing their current definitions with
+.Ic #undef :
+.Dv BUFSIZ ,
+.Dv EOF ,
+.Dv FILENAME_MAX ,
+.Dv FOPEN_MAX ,
+.Dv L_ctermid ,
+.Dv L_cuserid ,
+.Dv L_tmpnam ,
+.Dv NULL ,
+.Dv P_tmpdir ,
+.Dv SEEK_CUR ,
+.Dv SEEK_END ,
+.Dv SEEK_SET ,
+.Dv TMP_MAX ,
+.Dv clearerr ,
+.Dv clearerr_unlocked ,
+.Dv feof ,
+.Dv feof_unlocked ,
+.Dv ferror ,
+.Dv ferror_unlocked ,
+.Dv fileno ,
+.Dv fileno_unlocked ,
+.Dv fropen ,
+.Dv fwopen ,
+.Dv getc ,
+.Dv getc_unlocked ,
+.Dv getchar ,
+.Dv getchar_unlocked ,
+.Dv putc ,
+.Dv putc_unlocked ,
+.Dv putchar ,
+.Dv putchar_unlocked ,
+.Dv stderr ,
+.Dv stdin
+and
+.Dv stdout .
+Function versions of the macro functions
+.Dv clearerr ,
+.Dv clearerr_unlocked ,
+.Dv feof ,
+.Dv feof_unlocked ,
+.Dv ferror ,
+.Dv ferror_unlocked ,
+.Dv fileno ,
+.Dv fileno_unlocked ,
+.Dv getc ,
+.Dv getc_unlocked ,
+.Dv getchar ,
+.Dv getchar_unlocked ,
+.Dv putc ,
+.Dv putc_unlocked ,
+.Dv putchar ,
+and
+.Dv putchar_unlocked
+exist and will be used if the macro
+definitions are explicitly removed.
+.Sh SEE ALSO
+.Xr close 2 ,
+.Xr open 2 ,
+.Xr read 2 ,
+.Xr write 2
+.Sh STANDARDS
+The
+.Nm
+library conforms to
+.St -isoC-99 .
+.Sh LIST OF FUNCTIONS
+.Bl -column "Description"
+.It Sy "Function Description"
+.It "asprintf formatted output conversion"
+.It "clearerr check and reset stream status"
+.It "dprintf formatted output conversion"
+.It "fclose close a stream"
+.It "fdopen stream open functions"
+.It "feof check and reset stream status"
+.It "ferror check and reset stream status"
+.It "fflush flush a stream"
+.It "fgetc get next character or word from input stream"
+.It "fgetln get a line from a stream"
+.It "fgetpos reposition a stream"
+.It "fgets get a line from a stream"
+.It "fgetwc get next wide character from input stream"
+.It "fgetws get a line of wide characters from a stream"
+.It "fileno check and reset stream status"
+.It "fopen stream open functions"
+.It "fprintf formatted output conversion"
+.It "fpurge flush a stream"
+.It "fputc output a character or word to a stream"
+.It "fputs output a line to a stream"
+.It "fputwc output a wide character to a stream"
+.It "fputws output a line of wide characters to a stream"
+.It "fread binary stream input/output"
+.It "freopen stream open functions"
+.It "fropen open a stream"
+.It "fscanf input format conversion"
+.It "fseek reposition a stream"
+.It "fsetpos reposition a stream"
+.It "ftell reposition a stream"
+.It "funopen open a stream"
+.It "fwide set/get orientation of stream"
+.It "fwopen open a stream"
+.It "fwprintf formatted wide character output conversion"
+.It "fwrite binary stream input/output"
+.It "getc get next character or word from input stream"
+.It "getchar get next character or word from input stream"
+.It "getdelim get a line from a stream"
+.It "getline get a line from a stream"
+.It "gets get a line from a stream"
+.It "getw get next character or word from input stream"
+.It "getwc get next wide character from input stream"
+.It "getwchar get next wide character from input stream"
+.It "mkdtemp create unique temporary directory"
+.It "mkstemp create unique temporary file"
+.It "mktemp create unique temporary file"
+.It "perror system error messages"
+.It "printf formatted output conversion"
+.It "putc output a character or word to a stream"
+.It "putchar output a character or word to a stream"
+.It "puts output a line to a stream"
+.It "putw output a character or word to a stream"
+.It "putwc output a wide character to a stream"
+.It "putwchar output a wide character to a stream"
+.It "remove remove directory entry"
+.It "rewind reposition a stream"
+.It "scanf input format conversion"
+.It "setbuf stream buffering operations"
+.It "setbuffer stream buffering operations"
+.It "setlinebuf stream buffering operations"
+.It "setvbuf stream buffering operations"
+.It "snprintf formatted output conversion"
+.It "sprintf formatted output conversion"
+.It "sscanf input format conversion"
+.It "strerror system error messages"
+.It "swprintf formatted wide character output conversion"
+.It "sys_errlist system error messages"
+.It "sys_nerr system error messages"
+.It "tempnam temporary file routines"
+.It "tmpfile temporary file routines"
+.It "tmpnam temporary file routines"
+.It "ungetc un-get character from input stream"
+.It "ungetwc un-get wide character from input stream"
+.It "vasprintf formatted output conversion"
+.It "vdprintf formatted output conversion"
+.It "vfprintf formatted output conversion"
+.It "vfscanf input format conversion"
+.It "vfwprintf formatted wide character output conversion"
+.It "vprintf formatted output conversion"
+.It "vscanf input format conversion"
+.It "vsnprintf formatted output conversion"
+.It "vsprintf formatted output conversion"
+.It "vsscanf input format conversion"
+.It "vswprintf formatted wide character output conversion"
+.It "vwprintf formatted wide character output conversion"
+.It "wprintf formatted wide character output conversion"
+.El
+.Sh BUGS
+The standard buffered functions do not interact well with certain other
+library and system functions, especially
+.Xr vfork 2 .
diff --git a/lib/libc/stdio/stdio.c b/lib/libc/stdio/stdio.c
new file mode 100644
index 0000000..2447d18
--- /dev/null
+++ b/lib/libc/stdio/stdio.c
@@ -0,0 +1,187 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)stdio.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include "un-namespace.h"
+#include "local.h"
+
+/*
+ * Small standard I/O/seek/close functions.
+ */
+int
+__sread(cookie, buf, n)
+ void *cookie;
+ char *buf;
+ int n;
+{
+ FILE *fp = cookie;
+
+ return(_read(fp->_file, buf, (size_t)n));
+}
+
+int
+__swrite(cookie, buf, n)
+ void *cookie;
+ char const *buf;
+ int n;
+{
+ FILE *fp = cookie;
+
+ return (_write(fp->_file, buf, (size_t)n));
+}
+
+fpos_t
+__sseek(cookie, offset, whence)
+ void *cookie;
+ fpos_t offset;
+ int whence;
+{
+ FILE *fp = cookie;
+
+ return (lseek(fp->_file, (off_t)offset, whence));
+}
+
+int
+__sclose(cookie)
+ void *cookie;
+{
+
+ return (_close(((FILE *)cookie)->_file));
+}
+
+/*
+ * Higher level wrappers.
+ */
+int
+_sread(fp, buf, n)
+ FILE *fp;
+ char *buf;
+ int n;
+{
+ int ret;
+
+ ret = (*fp->_read)(fp->_cookie, buf, n);
+ if (ret > 0) {
+ if (fp->_flags & __SOFF) {
+ if (fp->_offset <= OFF_MAX - ret)
+ fp->_offset += ret;
+ else
+ fp->_flags &= ~__SOFF;
+ }
+ } else if (ret < 0)
+ fp->_flags &= ~__SOFF;
+ return (ret);
+}
+
+int
+_swrite(fp, buf, n)
+ FILE *fp;
+ char const *buf;
+ int n;
+{
+ int ret;
+ int serrno;
+
+ if (fp->_flags & __SAPP) {
+ serrno = errno;
+ if (_sseek(fp, (fpos_t)0, SEEK_END) == -1 &&
+ (fp->_flags & __SOPT))
+ return (-1);
+ errno = serrno;
+ }
+ ret = (*fp->_write)(fp->_cookie, buf, n);
+ /* __SOFF removed even on success in case O_APPEND mode is set. */
+ if (ret >= 0) {
+ if ((fp->_flags & (__SAPP|__SOFF)) == (__SAPP|__SOFF) &&
+ fp->_offset <= OFF_MAX - ret)
+ fp->_offset += ret;
+ else
+ fp->_flags &= ~__SOFF;
+
+ } else if (ret < 0)
+ fp->_flags &= ~__SOFF;
+ return (ret);
+}
+
+fpos_t
+_sseek(fp, offset, whence)
+ FILE *fp;
+ fpos_t offset;
+ int whence;
+{
+ fpos_t ret;
+ int serrno, errret;
+
+ serrno = errno;
+ errno = 0;
+ ret = (*fp->_seek)(fp->_cookie, offset, whence);
+ errret = errno;
+ if (errno == 0)
+ errno = serrno;
+ /*
+ * Disallow negative seeks per POSIX.
+ * It is needed here to help upper level caller
+ * in the cases it can't detect.
+ */
+ if (ret < 0) {
+ if (errret == 0) {
+ if (offset != 0 || whence != SEEK_CUR) {
+ if (HASUB(fp))
+ FREEUB(fp);
+ fp->_p = fp->_bf._base;
+ fp->_r = 0;
+ fp->_flags &= ~__SEOF;
+ }
+ fp->_flags |= __SERR;
+ errno = EINVAL;
+ } else if (errret == ESPIPE)
+ fp->_flags &= ~__SAPP;
+ fp->_flags &= ~__SOFF;
+ ret = -1;
+ } else if (fp->_flags & __SOPT) {
+ fp->_flags |= __SOFF;
+ fp->_offset = ret;
+ }
+ return (ret);
+}
diff --git a/lib/libc/stdio/swprintf.c b/lib/libc/stdio/swprintf.c
new file mode 100644
index 0000000..1f6ecc6
--- /dev/null
+++ b/lib/libc/stdio/swprintf.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <xlocale.h>
+
+int
+swprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vswprintf(s, n, fmt, ap);
+ va_end(ap);
+
+ return (ret);
+}
+int
+swprintf_l(wchar_t * __restrict s, size_t n, locale_t locale,
+ const wchar_t * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vswprintf_l(s, n, locale, fmt, ap);
+ va_end(ap);
+
+ return (ret);
+}
diff --git a/lib/libc/stdio/swscanf.c b/lib/libc/stdio/swscanf.c
new file mode 100644
index 0000000..c305ac1
--- /dev/null
+++ b/lib/libc/stdio/swscanf.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <xlocale.h>
+
+int
+swscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt, ...)
+{
+ va_list ap;
+ int r;
+
+ va_start(ap, fmt);
+ r = vswscanf(str, fmt, ap);
+ va_end(ap);
+
+ return (r);
+}
+int
+swscanf_l(const wchar_t * __restrict str, locale_t locale,
+ const wchar_t * __restrict fmt, ...)
+{
+ va_list ap;
+ int r;
+
+ va_start(ap, fmt);
+ r = vswscanf_l(str, locale, fmt, ap);
+ va_end(ap);
+
+ return (r);
+}
diff --git a/lib/libc/stdio/tempnam.c b/lib/libc/stdio/tempnam.c
new file mode 100644
index 0000000..ea4a2c8
--- /dev/null
+++ b/lib/libc/stdio/tempnam.c
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tempnam.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <paths.h>
+
+__warn_references(tempnam,
+ "warning: tempnam() possibly used unsafely; consider using mkstemp()");
+
+extern char *_mktemp(char *);
+
+char *
+tempnam(dir, pfx)
+ const char *dir, *pfx;
+{
+ int sverrno;
+ char *f, *name;
+
+ if (!(name = malloc(MAXPATHLEN)))
+ return(NULL);
+
+ if (!pfx)
+ pfx = "tmp.";
+
+ if (issetugid() == 0 && (f = getenv("TMPDIR"))) {
+ (void)snprintf(name, MAXPATHLEN, "%s%s%sXXXXXX", f,
+ *(f + strlen(f) - 1) == '/'? "": "/", pfx);
+ if ((f = _mktemp(name)))
+ return(f);
+ }
+
+ if ((f = (char *)dir)) {
+ (void)snprintf(name, MAXPATHLEN, "%s%s%sXXXXXX", f,
+ *(f + strlen(f) - 1) == '/'? "": "/", pfx);
+ if ((f = _mktemp(name)))
+ return(f);
+ }
+
+ f = P_tmpdir;
+ (void)snprintf(name, MAXPATHLEN, "%s%sXXXXXX", f, pfx);
+ if ((f = _mktemp(name)))
+ return(f);
+
+ f = _PATH_TMP;
+ (void)snprintf(name, MAXPATHLEN, "%s%sXXXXXX", f, pfx);
+ if ((f = _mktemp(name)))
+ return(f);
+
+ sverrno = errno;
+ free(name);
+ errno = sverrno;
+ return(NULL);
+}
diff --git a/lib/libc/stdio/tmpfile.c b/lib/libc/stdio/tmpfile.c
new file mode 100644
index 0000000..7ff297f
--- /dev/null
+++ b/lib/libc/stdio/tmpfile.c
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tmpfile.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <signal.h>
+#include <unistd.h>
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <paths.h>
+#include "un-namespace.h"
+
+FILE *
+tmpfile()
+{
+ sigset_t set, oset;
+ FILE *fp;
+ int fd, sverrno;
+#define TRAILER "tmp.XXXXXX"
+ char *buf;
+ const char *tmpdir;
+
+ tmpdir = NULL;
+ if (issetugid() == 0)
+ tmpdir = getenv("TMPDIR");
+ if (tmpdir == NULL)
+ tmpdir = _PATH_TMP;
+
+ (void)asprintf(&buf, "%s%s%s", tmpdir,
+ (tmpdir[strlen(tmpdir) - 1] == '/') ? "" : "/", TRAILER);
+ if (buf == NULL)
+ return (NULL);
+
+ sigfillset(&set);
+ (void)_sigprocmask(SIG_BLOCK, &set, &oset);
+
+ fd = mkstemp(buf);
+ if (fd != -1)
+ (void)unlink(buf);
+
+ free(buf);
+
+ (void)_sigprocmask(SIG_SETMASK, &oset, NULL);
+
+ if (fd == -1)
+ return (NULL);
+
+ if ((fp = fdopen(fd, "w+")) == NULL) {
+ sverrno = errno;
+ (void)_close(fd);
+ errno = sverrno;
+ return (NULL);
+ }
+ return (fp);
+}
diff --git a/lib/libc/stdio/tmpnam.3 b/lib/libc/stdio/tmpnam.3
new file mode 100644
index 0000000..937068f
--- /dev/null
+++ b/lib/libc/stdio/tmpnam.3
@@ -0,0 +1,248 @@
+.\" Copyright (c) 1988, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)tmpnam.3 8.2 (Berkeley) 11/17/93
+.\" $FreeBSD$
+.\"
+.Dd March 18, 2007
+.Dt TMPFILE 3
+.Os
+.Sh NAME
+.Nm tempnam ,
+.Nm tmpfile ,
+.Nm tmpnam
+.Nd temporary file routines
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft FILE *
+.Fn tmpfile void
+.Ft char *
+.Fn tmpnam "char *str"
+.Ft char *
+.Fn tempnam "const char *tmpdir" "const char *prefix"
+.Sh DESCRIPTION
+The
+.Fn tmpfile
+function
+returns a pointer to a stream associated with a file descriptor returned
+by the routine
+.Xr mkstemp 3 .
+The created file is unlinked before
+.Fn tmpfile
+returns, causing the file to be automatically deleted when the last
+reference to it is closed.
+The file is opened with the access value
+.Ql w+ .
+The file is created in the directory determined by the environment variable
+.Ev TMPDIR
+if set.
+The default location if
+.Ev TMPDIR
+is not set is
+.Pa /tmp .
+.Pp
+The
+.Fn tmpnam
+function
+returns a pointer to a file name, in the
+.Dv P_tmpdir
+directory, which
+did not reference an existing file at some indeterminate point in the
+past.
+.Dv P_tmpdir
+is defined in the include file
+.In stdio.h .
+If the argument
+.Fa str
+is
+.Pf non- Dv NULL ,
+the file name is copied to the buffer it references.
+Otherwise, the file name is copied to a static buffer.
+In either case,
+.Fn tmpnam
+returns a pointer to the file name.
+.Pp
+The buffer referenced by
+.Fa str
+is expected to be at least
+.Dv L_tmpnam
+bytes in length.
+.Dv L_tmpnam
+is defined in the include file
+.In stdio.h .
+.Pp
+The
+.Fn tempnam
+function
+is similar to
+.Fn tmpnam ,
+but provides the ability to specify the directory which will
+contain the temporary file and the file name prefix.
+.Pp
+The environment variable
+.Ev TMPDIR
+(if set), the argument
+.Fa tmpdir
+(if
+.Pf non- Dv NULL ) ,
+the directory
+.Dv P_tmpdir ,
+and the directory
+.Pa /tmp
+are tried, in the listed order, as directories in which to store the
+temporary file.
+.Pp
+The argument
+.Fa prefix ,
+if
+.Pf non- Dv NULL ,
+is used to specify a file name prefix, which will be the
+first part of the created file name.
+The
+.Fn tempnam
+function
+allocates memory in which to store the file name; the returned pointer
+may be used as a subsequent argument to
+.Xr free 3 .
+.Sh RETURN VALUES
+The
+.Fn tmpfile
+function
+returns a pointer to an open file stream on success, and a
+.Dv NULL
+pointer
+on error.
+.Pp
+The
+.Fn tmpnam
+and
+.Fn tempfile
+functions
+return a pointer to a file name on success, and a
+.Dv NULL
+pointer
+on error.
+.Sh ENVIRONMENT
+.Bl -tag -width Ds
+.It Ev TMPDIR
+.Pf [ Fn tempnam
+only]
+If set,
+the directory in which the temporary file is stored.
+.Ev TMPDIR
+is ignored for processes
+for which
+.Xr issetugid 2
+is true.
+.El
+.Sh COMPATIBILITY
+These interfaces are provided from System V and
+.Tn ANSI
+compatibility only.
+.Pp
+Most historic implementations of these functions provide
+only a limited number of possible temporary file names
+(usually 26)
+before file names will start being recycled.
+System V implementations of these functions
+(and of
+.Xr mktemp 3 )
+use the
+.Xr access 2
+system call to determine whether or not the temporary file
+may be created.
+This has obvious ramifications for setuid or setgid programs,
+complicating the portable use of these interfaces in such programs.
+.Pp
+The
+.Fn tmpfile
+interface should not be used in software expected to be used on other systems
+if there is any possibility that the user does not wish the temporary file to
+be publicly readable and writable.
+.Sh ERRORS
+The
+.Fn tmpfile
+function
+may fail and set the global variable
+.Va errno
+for any of the errors specified for the library functions
+.Xr fdopen 3
+or
+.Xr mkstemp 3 .
+.Pp
+The
+.Fn tmpnam
+function
+may fail and set
+.Va errno
+for any of the errors specified for the library function
+.Xr mktemp 3 .
+.Pp
+The
+.Fn tempnam
+function
+may fail and set
+.Va errno
+for any of the errors specified for the library functions
+.Xr malloc 3
+or
+.Xr mktemp 3 .
+.Sh SEE ALSO
+.Xr mkstemp 3 ,
+.Xr mktemp 3
+.Sh STANDARDS
+The
+.Fn tmpfile
+and
+.Fn tmpnam
+functions
+conform to
+.St -isoC .
+.Sh SECURITY CONSIDERATIONS
+The
+.Fn tmpnam
+and
+.Fn tempnam
+functions are susceptible to a race condition
+occurring between the selection of the file name
+and the creation of the file,
+which allows malicious users
+to potentially overwrite arbitrary files in the system,
+depending on the level of privilege of the running program.
+Additionally, there is no means by which
+file permissions may be specified.
+It is strongly suggested that
+.Xr mkstemp 3
+be used in place of these functions.
+(See
+the FSA.)
diff --git a/lib/libc/stdio/tmpnam.c b/lib/libc/stdio/tmpnam.c
new file mode 100644
index 0000000..05bcb5b
--- /dev/null
+++ b/lib/libc/stdio/tmpnam.c
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tmpnam.c 8.3 (Berkeley) 3/28/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <stdio.h>
+#include <unistd.h>
+
+__warn_references(tmpnam,
+ "warning: tmpnam() possibly used unsafely; consider using mkstemp()");
+
+extern char *_mktemp(char *);
+
+char *
+tmpnam(s)
+ char *s;
+{
+ static u_long tmpcount;
+ static char buf[L_tmpnam];
+
+ if (s == NULL)
+ s = buf;
+ (void)snprintf(s, L_tmpnam, "%stmp.%lu.XXXXXX", P_tmpdir, tmpcount);
+ ++tmpcount;
+ return (_mktemp(s));
+}
diff --git a/lib/libc/stdio/ungetc.3 b/lib/libc/stdio/ungetc.3
new file mode 100644
index 0000000..86566b3
--- /dev/null
+++ b/lib/libc/stdio/ungetc.3
@@ -0,0 +1,98 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)ungetc.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt UNGETC 3
+.Os
+.Sh NAME
+.Nm ungetc
+.Nd un-get character from input stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft int
+.Fn ungetc "int c" "FILE *stream"
+.Sh DESCRIPTION
+The
+.Fn ungetc
+function pushes the character
+.Fa c
+(converted to an unsigned char)
+back onto the input stream pointed to by
+.Fa stream .
+The pushed-back characters will be returned by subsequent reads on the
+stream (in reverse order).
+A successful intervening call,
+using the same stream,
+to one of the file positioning functions
+.Xr ( fseek 3 ,
+.Xr fsetpos 3 ,
+or
+.Xr rewind 3 )
+will discard the pushed back characters.
+.Pp
+One character of push-back is guaranteed,
+but as long as there is sufficient memory,
+an effectively infinite amount of pushback is allowed.
+.Pp
+If a character is successfully pushed-back,
+the end-of-file indicator for the stream is cleared.
+The file-position indicator is decremented
+by each successful call to
+.Fn ungetc ;
+if its value was 0 before a call, its value is unspecified after
+the call.
+.Sh RETURN VALUES
+The
+.Fn ungetc
+function returns the character pushed-back after the conversion,
+or
+.Dv EOF
+if the operation fails.
+If the value of the argument
+.Fa c
+character equals
+.Dv EOF ,
+the operation will fail and the stream will remain unchanged.
+.Sh SEE ALSO
+.Xr fseek 3 ,
+.Xr getc 3 ,
+.Xr setvbuf 3 ,
+.Xr ungetwc 3
+.Sh STANDARDS
+The
+.Fn ungetc
+function conforms to
+.St -isoC .
diff --git a/lib/libc/stdio/ungetc.c b/lib/libc/stdio/ungetc.c
new file mode 100644
index 0000000..1353b7e
--- /dev/null
+++ b/lib/libc/stdio/ungetc.c
@@ -0,0 +1,168 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ungetc.c 8.2 (Berkeley) 11/3/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "un-namespace.h"
+#include "local.h"
+#include "libc_private.h"
+
+static int __submore(FILE *);
+
+/*
+ * Expand the ungetc buffer `in place'. That is, adjust fp->_p when
+ * the buffer moves, so that it points the same distance from the end,
+ * and move the bytes in the buffer around as necessary so that they
+ * are all at the end (stack-style).
+ */
+static int
+__submore(FILE *fp)
+{
+ int i;
+ unsigned char *p;
+
+ if (fp->_ub._base == fp->_ubuf) {
+ /*
+ * Get a new buffer (rather than expanding the old one).
+ */
+ if ((p = malloc((size_t)BUFSIZ)) == NULL)
+ return (EOF);
+ fp->_ub._base = p;
+ fp->_ub._size = BUFSIZ;
+ p += BUFSIZ - sizeof(fp->_ubuf);
+ for (i = sizeof(fp->_ubuf); --i >= 0;)
+ p[i] = fp->_ubuf[i];
+ fp->_p = p;
+ return (0);
+ }
+ i = fp->_ub._size;
+ p = realloc(fp->_ub._base, (size_t)(i << 1));
+ if (p == NULL)
+ return (EOF);
+ /* no overlap (hence can use memcpy) because we doubled the size */
+ (void)memcpy((void *)(p + i), (void *)p, (size_t)i);
+ fp->_p = p + i;
+ fp->_ub._base = p;
+ fp->_ub._size = i << 1;
+ return (0);
+}
+
+/*
+ * MT-safe version
+ */
+int
+ungetc(int c, FILE *fp)
+{
+ int ret;
+
+ if (!__sdidinit)
+ __sinit();
+ FLOCKFILE(fp);
+ ORIENT(fp, -1);
+ ret = __ungetc(c, fp);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
+
+/*
+ * Non-MT-safe version
+ */
+int
+__ungetc(int c, FILE *fp)
+{
+
+ if (c == EOF)
+ return (EOF);
+ if ((fp->_flags & __SRD) == 0) {
+ /*
+ * Not already reading: no good unless reading-and-writing.
+ * Otherwise, flush any current write stuff.
+ */
+ if ((fp->_flags & __SRW) == 0)
+ return (EOF);
+ if (fp->_flags & __SWR) {
+ if (__sflush(fp))
+ return (EOF);
+ fp->_flags &= ~__SWR;
+ fp->_w = 0;
+ fp->_lbfsize = 0;
+ }
+ fp->_flags |= __SRD;
+ }
+ c = (unsigned char)c;
+
+ /*
+ * If we are in the middle of ungetc'ing, just continue.
+ * This may require expanding the current ungetc buffer.
+ */
+ if (HASUB(fp)) {
+ if (fp->_r >= fp->_ub._size && __submore(fp))
+ return (EOF);
+ *--fp->_p = c;
+ fp->_r++;
+ return (c);
+ }
+ fp->_flags &= ~__SEOF;
+
+ /*
+ * If we can handle this by simply backing up, do so,
+ * but never replace the original character.
+ * (This makes sscanf() work when scanning `const' data.)
+ */
+ if (fp->_bf._base != NULL && fp->_p > fp->_bf._base &&
+ fp->_p[-1] == c) {
+ fp->_p--;
+ fp->_r++;
+ return (c);
+ }
+
+ /*
+ * Create an ungetc buffer.
+ * Initially, we will use the `reserve' buffer.
+ */
+ fp->_ur = fp->_r;
+ fp->_up = fp->_p;
+ fp->_ub._base = fp->_ubuf;
+ fp->_ub._size = sizeof(fp->_ubuf);
+ fp->_ubuf[sizeof(fp->_ubuf) - 1] = c;
+ fp->_p = &fp->_ubuf[sizeof(fp->_ubuf) - 1];
+ fp->_r = 1;
+ return (c);
+}
diff --git a/lib/libc/stdio/ungetwc.3 b/lib/libc/stdio/ungetwc.3
new file mode 100644
index 0000000..2cdfbe9
--- /dev/null
+++ b/lib/libc/stdio/ungetwc.3
@@ -0,0 +1,95 @@
+.\" $NetBSD: ungetwc.3,v 1.3 2002/02/07 07:00:27 ross Exp $
+.\"
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)ungetc.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd March 3, 2004
+.Dt UNGETWC 3
+.Os
+.Sh NAME
+.Nm ungetwc
+.Nd un-get wide character from input stream
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.In wchar.h
+.Ft wint_t
+.Fn ungetwc "wint_t wc" "FILE *stream"
+.Sh DESCRIPTION
+The
+.Fn ungetwc
+function pushes the wide character
+.Fa wc
+(converted to an
+.Vt wchar_t )
+back onto the input stream pointed to by
+.Fa stream .
+The pushed-backed wide characters will be returned by subsequent reads on the
+stream (in reverse order).
+A successful intervening call, using the same stream, to one of the file
+positioning functions
+.Xr fseek 3 ,
+.Xr fsetpos 3 ,
+or
+.Xr rewind 3
+will discard the pushed back wide characters.
+.Pp
+One wide character of push-back is guaranteed,
+but as long as there is
+sufficient memory, an effectively infinite amount of pushback is allowed.
+.Pp
+If a character is successfully pushed-back,
+the end-of-file indicator for the stream is cleared.
+.Sh RETURN VALUES
+The
+.Fn ungetwc
+function
+returns
+the wide character pushed-back after the conversion, or
+.Dv WEOF
+if the operation fails.
+If the value of the argument
+.Fa c
+character equals
+.Dv WEOF ,
+the operation will fail and the stream will remain unchanged.
+.Sh SEE ALSO
+.Xr fseek 3 ,
+.Xr getwc 3
+.Sh STANDARDS
+The
+.Fn ungetwc
+function conforms to
+.St -isoC-99 .
diff --git a/lib/libc/stdio/ungetwc.c b/lib/libc/stdio/ungetwc.c
new file mode 100644
index 0000000..78bc38d
--- /dev/null
+++ b/lib/libc/stdio/ungetwc.c
@@ -0,0 +1,90 @@
+/*-
+ * Copyright (c) 2002-2004 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+#include "mblocal.h"
+#include "xlocale_private.h"
+
+/*
+ * Non-MT-safe version.
+ */
+wint_t
+__ungetwc(wint_t wc, FILE *fp, locale_t locale)
+{
+ char buf[MB_LEN_MAX];
+ size_t len;
+ struct xlocale_ctype *l = XLOCALE_CTYPE(locale);
+
+ if (wc == WEOF)
+ return (WEOF);
+ if ((len = l->__wcrtomb(buf, wc, &fp->_mbstate)) == (size_t)-1) {
+ fp->_flags |= __SERR;
+ return (WEOF);
+ }
+ while (len-- != 0)
+ if (__ungetc((unsigned char)buf[len], fp) == EOF)
+ return (WEOF);
+
+ return (wc);
+}
+
+/*
+ * MT-safe version.
+ */
+wint_t
+ungetwc_l(wint_t wc, FILE *fp, locale_t locale)
+{
+ wint_t r;
+ FIX_LOCALE(locale);
+
+ FLOCKFILE(fp);
+ ORIENT(fp, 1);
+ r = __ungetwc(wc, fp, locale);
+ FUNLOCKFILE(fp);
+
+ return (r);
+}
+wint_t
+ungetwc(wint_t wc, FILE *fp)
+{
+ return ungetwc_l(wc, fp, __get_locale());
+}
diff --git a/lib/libc/stdio/vasprintf.c b/lib/libc/stdio/vasprintf.c
new file mode 100644
index 0000000..8feb23d
--- /dev/null
+++ b/lib/libc/stdio/vasprintf.c
@@ -0,0 +1,74 @@
+/* $OpenBSD: vasprintf.c,v 1.4 1998/06/21 22:13:47 millert Exp $ */
+
+/*
+ * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+#include "xlocale_private.h"
+#include "local.h"
+
+int
+vasprintf_l(char **str, locale_t locale, const char *fmt, __va_list ap)
+{
+ FILE f = FAKE_FILE;
+ int ret;
+ FIX_LOCALE(locale);
+
+ f._flags = __SWR | __SSTR | __SALC;
+ f._bf._base = f._p = malloc(128);
+ if (f._bf._base == NULL) {
+ *str = NULL;
+ errno = ENOMEM;
+ return (-1);
+ }
+ f._bf._size = f._w = 127; /* Leave room for the NUL */
+ ret = __vfprintf(&f, locale, fmt, ap);
+ if (ret < 0) {
+ free(f._bf._base);
+ *str = NULL;
+ errno = ENOMEM;
+ return (-1);
+ }
+ *f._p = '\0';
+ *str = (char *)f._bf._base;
+ return (ret);
+}
+int
+vasprintf(char **str, const char *fmt, __va_list ap)
+{
+ return vasprintf_l(str, __get_locale(), fmt, ap);
+}
diff --git a/lib/libc/stdio/vdprintf.c b/lib/libc/stdio/vdprintf.c
new file mode 100644
index 0000000..454b0f9
--- /dev/null
+++ b/lib/libc/stdio/vdprintf.c
@@ -0,0 +1,70 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include "un-namespace.h"
+
+#include "local.h"
+#include "xlocale_private.h"
+
+int
+vdprintf(int fd, const char * __restrict fmt, va_list ap)
+{
+ FILE f = FAKE_FILE;
+ unsigned char buf[BUFSIZ];
+ int ret;
+
+ if (fd > SHRT_MAX) {
+ errno = EMFILE;
+ return (EOF);
+ }
+
+ f._p = buf;
+ f._w = sizeof(buf);
+ f._flags = __SWR;
+ f._file = fd;
+ f._cookie = &f;
+ f._write = __swrite;
+ f._bf._base = buf;
+ f._bf._size = sizeof(buf);
+
+ if ((ret = __vfprintf(&f, __get_locale(), fmt, ap)) < 0)
+ return (ret);
+
+ return (__fflush(&f) ? EOF : ret);
+}
diff --git a/lib/libc/stdio/vfprintf.c b/lib/libc/stdio/vfprintf.c
new file mode 100644
index 0000000..4ad0ee1
--- /dev/null
+++ b/lib/libc/stdio/vfprintf.c
@@ -0,0 +1,1037 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Actual printf innards.
+ *
+ * This code is large and complicated...
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <printf.h>
+
+#include <stdarg.h>
+#include "xlocale_private.h"
+#include "un-namespace.h"
+
+#include "libc_private.h"
+#include "local.h"
+#include "fvwrite.h"
+#include "printflocal.h"
+
+static int __sprint(FILE *, struct __suio *, locale_t);
+static int __sbprintf(FILE *, locale_t, const char *, va_list) __printflike(3, 0)
+ __noinline;
+static char *__wcsconv(wchar_t *, int);
+
+#define CHAR char
+#include "printfcommon.h"
+
+struct grouping_state {
+ char *thousands_sep; /* locale-specific thousands separator */
+ int thousep_len; /* length of thousands_sep */
+ const char *grouping; /* locale-specific numeric grouping rules */
+ int lead; /* sig figs before decimal or group sep */
+ int nseps; /* number of group separators with ' */
+ int nrepeats; /* number of repeats of the last group */
+};
+
+/*
+ * Initialize the thousands' grouping state in preparation to print a
+ * number with ndigits digits. This routine returns the total number
+ * of bytes that will be needed.
+ */
+static int
+grouping_init(struct grouping_state *gs, int ndigits, locale_t loc)
+{
+ struct lconv *locale;
+
+ locale = localeconv_l(loc);
+ gs->grouping = locale->grouping;
+ gs->thousands_sep = locale->thousands_sep;
+ gs->thousep_len = strlen(gs->thousands_sep);
+
+ gs->nseps = gs->nrepeats = 0;
+ gs->lead = ndigits;
+ while (*gs->grouping != CHAR_MAX) {
+ if (gs->lead <= *gs->grouping)
+ break;
+ gs->lead -= *gs->grouping;
+ if (*(gs->grouping+1)) {
+ gs->nseps++;
+ gs->grouping++;
+ } else
+ gs->nrepeats++;
+ }
+ return ((gs->nseps + gs->nrepeats) * gs->thousep_len);
+}
+
+/*
+ * Print a number with thousands' separators.
+ */
+static int
+grouping_print(struct grouping_state *gs, struct io_state *iop,
+ const CHAR *cp, const CHAR *ep, locale_t locale)
+{
+ const CHAR *cp0 = cp;
+
+ if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale))
+ return (-1);
+ cp += gs->lead;
+ while (gs->nseps > 0 || gs->nrepeats > 0) {
+ if (gs->nrepeats > 0)
+ gs->nrepeats--;
+ else {
+ gs->grouping--;
+ gs->nseps--;
+ }
+ if (io_print(iop, gs->thousands_sep, gs->thousep_len, locale))
+ return (-1);
+ if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale))
+ return (-1);
+ cp += *gs->grouping;
+ }
+ if (cp > ep)
+ cp = ep;
+ return (cp - cp0);
+}
+
+/*
+ * Flush out all the vectors defined by the given uio,
+ * then reset it so that it can be reused.
+ */
+static int
+__sprint(FILE *fp, struct __suio *uio, locale_t locale)
+{
+ int err;
+
+ if (uio->uio_resid == 0) {
+ uio->uio_iovcnt = 0;
+ return (0);
+ }
+ err = __sfvwrite(fp, uio);
+ uio->uio_resid = 0;
+ uio->uio_iovcnt = 0;
+ return (err);
+}
+
+/*
+ * Helper function for `fprintf to unbuffered unix file': creates a
+ * temporary buffer. We only work on write-only files; this avoids
+ * worries about ungetc buffers and so forth.
+ */
+static int
+__sbprintf(FILE *fp, locale_t locale, const char *fmt, va_list ap)
+{
+ int ret;
+ FILE fake = FAKE_FILE;
+ unsigned char buf[BUFSIZ];
+
+ /* XXX This is probably not needed. */
+ if (prepwrite(fp) != 0)
+ return (EOF);
+
+ /* copy the important variables */
+ fake._flags = fp->_flags & ~__SNBF;
+ fake._file = fp->_file;
+ fake._cookie = fp->_cookie;
+ fake._write = fp->_write;
+ fake._orientation = fp->_orientation;
+ fake._mbstate = fp->_mbstate;
+
+ /* set up the buffer */
+ fake._bf._base = fake._p = buf;
+ fake._bf._size = fake._w = sizeof(buf);
+ fake._lbfsize = 0; /* not actually used, but Just In Case */
+
+ /* do the work, then copy any error status */
+ ret = __vfprintf(&fake, locale, fmt, ap);
+ if (ret >= 0 && __fflush(&fake))
+ ret = EOF;
+ if (fake._flags & __SERR)
+ fp->_flags |= __SERR;
+ return (ret);
+}
+
+/*
+ * Convert a wide character string argument for the %ls format to a multibyte
+ * string representation. If not -1, prec specifies the maximum number of
+ * bytes to output, and also means that we can't assume that the wide char.
+ * string ends is null-terminated.
+ */
+static char *
+__wcsconv(wchar_t *wcsarg, int prec)
+{
+ static const mbstate_t initial;
+ mbstate_t mbs;
+ char buf[MB_LEN_MAX];
+ wchar_t *p;
+ char *convbuf;
+ size_t clen, nbytes;
+
+ /* Allocate space for the maximum number of bytes we could output. */
+ if (prec < 0) {
+ p = wcsarg;
+ mbs = initial;
+ nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
+ if (nbytes == (size_t)-1)
+ return (NULL);
+ } else {
+ /*
+ * Optimisation: if the output precision is small enough,
+ * just allocate enough memory for the maximum instead of
+ * scanning the string.
+ */
+ if (prec < 128)
+ nbytes = prec;
+ else {
+ nbytes = 0;
+ p = wcsarg;
+ mbs = initial;
+ for (;;) {
+ clen = wcrtomb(buf, *p++, &mbs);
+ if (clen == 0 || clen == (size_t)-1 ||
+ nbytes + clen > prec)
+ break;
+ nbytes += clen;
+ }
+ }
+ }
+ if ((convbuf = malloc(nbytes + 1)) == NULL)
+ return (NULL);
+
+ /* Fill the output buffer. */
+ p = wcsarg;
+ mbs = initial;
+ if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
+ nbytes, &mbs)) == (size_t)-1) {
+ free(convbuf);
+ return (NULL);
+ }
+ convbuf[nbytes] = '\0';
+ return (convbuf);
+}
+
+/*
+ * MT-safe version
+ */
+int
+vfprintf_l(FILE * __restrict fp, locale_t locale, const char * __restrict fmt0,
+ va_list ap)
+{
+ int ret;
+ FIX_LOCALE(locale);
+
+ FLOCKFILE(fp);
+ /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+ fp->_file >= 0)
+ ret = __sbprintf(fp, locale, fmt0, ap);
+ else
+ ret = __vfprintf(fp, locale, fmt0, ap);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
+int
+vfprintf(FILE * __restrict fp, const char * __restrict fmt0, va_list ap)
+{
+ return vfprintf_l(fp, __get_locale(), fmt0, ap);
+}
+
+/*
+ * The size of the buffer we use as scratch space for integer
+ * conversions, among other things. We need enough space to
+ * write a uintmax_t in octal (plus one byte).
+ */
+#if UINTMAX_MAX <= UINT64_MAX
+#define BUF 32
+#else
+#error "BUF must be large enough to format a uintmax_t"
+#endif
+
+/*
+ * Non-MT-safe version
+ */
+int
+__vfprintf(FILE *fp, locale_t locale, const char *fmt0, va_list ap)
+{
+ char *fmt; /* format string */
+ int ch; /* character from fmt */
+ int n, n2; /* handy integer (short term usage) */
+ char *cp; /* handy char pointer (short term usage) */
+ int flags; /* flags as above */
+ int ret; /* return value accumulator */
+ int width; /* width from format (%8d), or 0 */
+ int prec; /* precision from format; <0 for N/A */
+ char sign; /* sign prefix (' ', '+', '-', or \0) */
+ struct grouping_state gs; /* thousands' grouping info */
+
+#ifndef NO_FLOATING_POINT
+ /*
+ * We can decompose the printed representation of floating
+ * point numbers into several parts, some of which may be empty:
+ *
+ * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
+ * A B ---C--- D E F
+ *
+ * A: 'sign' holds this value if present; '\0' otherwise
+ * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
+ * C: cp points to the string MMMNNN. Leading and trailing
+ * zeros are not in the string and must be added.
+ * D: expchar holds this character; '\0' if no exponent, e.g. %f
+ * F: at least two digits for decimal, at least one digit for hex
+ */
+ char *decimal_point; /* locale specific decimal point */
+ int decpt_len; /* length of decimal_point */
+ int signflag; /* true if float is negative */
+ union { /* floating point arguments %[aAeEfFgG] */
+ double dbl;
+ long double ldbl;
+ } fparg;
+ int expt; /* integer value of exponent */
+ char expchar; /* exponent character: [eEpP\0] */
+ char *dtoaend; /* pointer to end of converted digits */
+ int expsize; /* character count for expstr */
+ int ndig; /* actual number of digits returned by dtoa */
+ char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
+ char *dtoaresult; /* buffer allocated by dtoa */
+#endif
+ u_long ulval; /* integer arguments %[diouxX] */
+ uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
+ int base; /* base for [diouxX] conversion */
+ int dprec; /* a copy of prec if [diouxX], 0 otherwise */
+ int realsz; /* field size expanded by dprec, sign, etc */
+ int size; /* size of converted field or string */
+ int prsize; /* max size of printed field */
+ const char *xdigs; /* digits for %[xX] conversion */
+ struct io_state io; /* I/O buffering state */
+ char buf[BUF]; /* buffer with space for digits of uintmax_t */
+ char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */
+ union arg *argtable; /* args, built due to positional arg */
+ union arg statargtable [STATIC_ARG_TBL_SIZE];
+ int nextarg; /* 1-based argument index */
+ va_list orgap; /* original argument pointer */
+ char *convbuf; /* wide to multibyte conversion result */
+
+ static const char xdigs_lower[16] = "0123456789abcdef";
+ static const char xdigs_upper[16] = "0123456789ABCDEF";
+
+ /* BEWARE, these `goto error' on error. */
+#define PRINT(ptr, len) { \
+ if (io_print(&io, (ptr), (len), locale)) \
+ goto error; \
+}
+#define PAD(howmany, with) { \
+ if (io_pad(&io, (howmany), (with), locale)) \
+ goto error; \
+}
+#define PRINTANDPAD(p, ep, len, with) { \
+ if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \
+ goto error; \
+}
+#define FLUSH() { \
+ if (io_flush(&io, locale)) \
+ goto error; \
+}
+
+ /*
+ * Get the argument indexed by nextarg. If the argument table is
+ * built, use it to get the argument. If its not, get the next
+ * argument (and arguments must be gotten sequentially).
+ */
+#define GETARG(type) \
+ ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
+ (nextarg++, va_arg(ap, type)))
+
+ /*
+ * To extend shorts properly, we need both signed and unsigned
+ * argument extraction methods.
+ */
+#define SARG() \
+ (flags&LONGINT ? GETARG(long) : \
+ flags&SHORTINT ? (long)(short)GETARG(int) : \
+ flags&CHARINT ? (long)(signed char)GETARG(int) : \
+ (long)GETARG(int))
+#define UARG() \
+ (flags&LONGINT ? GETARG(u_long) : \
+ flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
+ flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
+ (u_long)GETARG(u_int))
+#define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
+#define SJARG() \
+ (flags&INTMAXT ? GETARG(intmax_t) : \
+ flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
+ flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
+ (intmax_t)GETARG(long long))
+#define UJARG() \
+ (flags&INTMAXT ? GETARG(uintmax_t) : \
+ flags&SIZET ? (uintmax_t)GETARG(size_t) : \
+ flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
+ (uintmax_t)GETARG(unsigned long long))
+
+ /*
+ * Get * arguments, including the form *nn$. Preserve the nextarg
+ * that the argument can be gotten once the type is determined.
+ */
+#define GETASTER(val) \
+ n2 = 0; \
+ cp = fmt; \
+ while (is_digit(*cp)) { \
+ n2 = 10 * n2 + to_digit(*cp); \
+ cp++; \
+ } \
+ if (*cp == '$') { \
+ int hold = nextarg; \
+ if (argtable == NULL) { \
+ argtable = statargtable; \
+ if (__find_arguments (fmt0, orgap, &argtable)) { \
+ ret = EOF; \
+ goto error; \
+ } \
+ } \
+ nextarg = n2; \
+ val = GETARG (int); \
+ nextarg = hold; \
+ fmt = ++cp; \
+ } else { \
+ val = GETARG (int); \
+ }
+
+ if (__use_xprintf == 0 && getenv("USE_XPRINTF"))
+ __use_xprintf = 1;
+ if (__use_xprintf > 0)
+ return (__xvprintf(fp, fmt0, ap));
+
+ /* sorry, fprintf(read_only_file, "") returns EOF, not 0 */
+ if (prepwrite(fp) != 0)
+ return (EOF);
+
+ convbuf = NULL;
+ fmt = (char *)fmt0;
+ argtable = NULL;
+ nextarg = 1;
+ va_copy(orgap, ap);
+ io_init(&io, fp);
+ ret = 0;
+#ifndef NO_FLOATING_POINT
+ dtoaresult = NULL;
+ decimal_point = localeconv_l(locale)->decimal_point;
+ /* The overwhelmingly common case is decpt_len == 1. */
+ decpt_len = (decimal_point[1] == '\0' ? 1 : strlen(decimal_point));
+#endif
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
+ /* void */;
+ if ((n = fmt - cp) != 0) {
+ if ((unsigned)ret + n > INT_MAX) {
+ ret = EOF;
+ errno = EOVERFLOW;
+ goto error;
+ }
+ PRINT(cp, n);
+ ret += n;
+ }
+ if (ch == '\0')
+ goto done;
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+ dprec = 0;
+ width = 0;
+ prec = -1;
+ gs.grouping = NULL;
+ sign = '\0';
+ ox[1] = '\0';
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ /*-
+ * ``If the space and + flags both appear, the space
+ * flag will be ignored.''
+ * -- ANSI X3J11
+ */
+ if (!sign)
+ sign = ' ';
+ goto rflag;
+ case '#':
+ flags |= ALT;
+ goto rflag;
+ case '*':
+ /*-
+ * ``A negative field width argument is taken as a
+ * - flag followed by a positive field width.''
+ * -- ANSI X3J11
+ * They don't exclude field widths read from args.
+ */
+ GETASTER (width);
+ if (width >= 0)
+ goto rflag;
+ width = -width;
+ /* FALLTHROUGH */
+ case '-':
+ flags |= LADJUST;
+ goto rflag;
+ case '+':
+ sign = '+';
+ goto rflag;
+ case '\'':
+ flags |= GROUPING;
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ GETASTER (prec);
+ goto rflag;
+ }
+ prec = 0;
+ while (is_digit(ch)) {
+ prec = 10 * prec + to_digit(ch);
+ ch = *fmt++;
+ }
+ goto reswitch;
+ case '0':
+ /*-
+ * ``Note that 0 is taken as a flag, not as the
+ * beginning of a field width.''
+ * -- ANSI X3J11
+ */
+ flags |= ZEROPAD;
+ goto rflag;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ do {
+ n = 10 * n + to_digit(ch);
+ ch = *fmt++;
+ } while (is_digit(ch));
+ if (ch == '$') {
+ nextarg = n;
+ if (argtable == NULL) {
+ argtable = statargtable;
+ if (__find_arguments (fmt0, orgap,
+ &argtable)) {
+ ret = EOF;
+ goto error;
+ }
+ }
+ goto rflag;
+ }
+ width = n;
+ goto reswitch;
+#ifndef NO_FLOATING_POINT
+ case 'L':
+ flags |= LONGDBL;
+ goto rflag;
+#endif
+ case 'h':
+ if (flags & SHORTINT) {
+ flags &= ~SHORTINT;
+ flags |= CHARINT;
+ } else
+ flags |= SHORTINT;
+ goto rflag;
+ case 'j':
+ flags |= INTMAXT;
+ goto rflag;
+ case 'l':
+ if (flags & LONGINT) {
+ flags &= ~LONGINT;
+ flags |= LLONGINT;
+ } else
+ flags |= LONGINT;
+ goto rflag;
+ case 'q':
+ flags |= LLONGINT; /* not necessarily */
+ goto rflag;
+ case 't':
+ flags |= PTRDIFFT;
+ goto rflag;
+ case 'z':
+ flags |= SIZET;
+ goto rflag;
+ case 'C':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'c':
+ if (flags & LONGINT) {
+ static const mbstate_t initial;
+ mbstate_t mbs;
+ size_t mbseqlen;
+
+ mbs = initial;
+ mbseqlen = wcrtomb(cp = buf,
+ (wchar_t)GETARG(wint_t), &mbs);
+ if (mbseqlen == (size_t)-1) {
+ fp->_flags |= __SERR;
+ goto error;
+ }
+ size = (int)mbseqlen;
+ } else {
+ *(cp = buf) = GETARG(int);
+ size = 1;
+ }
+ sign = '\0';
+ break;
+ case 'D':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
+ if (flags & INTMAX_SIZE) {
+ ujval = SJARG();
+ if ((intmax_t)ujval < 0) {
+ ujval = -ujval;
+ sign = '-';
+ }
+ } else {
+ ulval = SARG();
+ if ((long)ulval < 0) {
+ ulval = -ulval;
+ sign = '-';
+ }
+ }
+ base = 10;
+ goto number;
+#ifndef NO_FLOATING_POINT
+ case 'a':
+ case 'A':
+ if (ch == 'a') {
+ ox[1] = 'x';
+ xdigs = xdigs_lower;
+ expchar = 'p';
+ } else {
+ ox[1] = 'X';
+ xdigs = xdigs_upper;
+ expchar = 'P';
+ }
+ if (prec >= 0)
+ prec++;
+ if (dtoaresult != NULL)
+ freedtoa(dtoaresult);
+ if (flags & LONGDBL) {
+ fparg.ldbl = GETARG(long double);
+ dtoaresult = cp =
+ __hldtoa(fparg.ldbl, xdigs, prec,
+ &expt, &signflag, &dtoaend);
+ } else {
+ fparg.dbl = GETARG(double);
+ dtoaresult = cp =
+ __hdtoa(fparg.dbl, xdigs, prec,
+ &expt, &signflag, &dtoaend);
+ }
+ if (prec < 0)
+ prec = dtoaend - cp;
+ if (expt == INT_MAX)
+ ox[1] = '\0';
+ goto fp_common;
+ case 'e':
+ case 'E':
+ expchar = ch;
+ if (prec < 0) /* account for digit before decpt */
+ prec = DEFPREC + 1;
+ else
+ prec++;
+ goto fp_begin;
+ case 'f':
+ case 'F':
+ expchar = '\0';
+ goto fp_begin;
+ case 'g':
+ case 'G':
+ expchar = ch - ('g' - 'e');
+ if (prec == 0)
+ prec = 1;
+fp_begin:
+ if (prec < 0)
+ prec = DEFPREC;
+ if (dtoaresult != NULL)
+ freedtoa(dtoaresult);
+ if (flags & LONGDBL) {
+ fparg.ldbl = GETARG(long double);
+ dtoaresult = cp =
+ __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
+ &expt, &signflag, &dtoaend);
+ } else {
+ fparg.dbl = GETARG(double);
+ dtoaresult = cp =
+ dtoa(fparg.dbl, expchar ? 2 : 3, prec,
+ &expt, &signflag, &dtoaend);
+ if (expt == 9999)
+ expt = INT_MAX;
+ }
+fp_common:
+ if (signflag)
+ sign = '-';
+ if (expt == INT_MAX) { /* inf or nan */
+ if (*cp == 'N') {
+ cp = (ch >= 'a') ? "nan" : "NAN";
+ sign = '\0';
+ } else
+ cp = (ch >= 'a') ? "inf" : "INF";
+ size = 3;
+ flags &= ~ZEROPAD;
+ break;
+ }
+ flags |= FPT;
+ ndig = dtoaend - cp;
+ if (ch == 'g' || ch == 'G') {
+ if (expt > -4 && expt <= prec) {
+ /* Make %[gG] smell like %[fF] */
+ expchar = '\0';
+ if (flags & ALT)
+ prec -= expt;
+ else
+ prec = ndig - expt;
+ if (prec < 0)
+ prec = 0;
+ } else {
+ /*
+ * Make %[gG] smell like %[eE], but
+ * trim trailing zeroes if no # flag.
+ */
+ if (!(flags & ALT))
+ prec = ndig;
+ }
+ }
+ if (expchar) {
+ expsize = exponent(expstr, expt - 1, expchar);
+ size = expsize + prec;
+ if (prec > 1 || flags & ALT)
+ size += decpt_len;
+ } else {
+ /* space for digits before decimal point */
+ if (expt > 0)
+ size = expt;
+ else /* "0" */
+ size = 1;
+ /* space for decimal pt and following digits */
+ if (prec || flags & ALT)
+ size += prec + decpt_len;
+ if ((flags & GROUPING) && expt > 0)
+ size += grouping_init(&gs, expt, locale);
+ }
+ break;
+#endif /* !NO_FLOATING_POINT */
+ case 'n':
+ /*
+ * Assignment-like behavior is specified if the
+ * value overflows or is otherwise unrepresentable.
+ * C99 says to use `signed char' for %hhn conversions.
+ */
+ if (flags & LLONGINT)
+ *GETARG(long long *) = ret;
+ else if (flags & SIZET)
+ *GETARG(ssize_t *) = (ssize_t)ret;
+ else if (flags & PTRDIFFT)
+ *GETARG(ptrdiff_t *) = ret;
+ else if (flags & INTMAXT)
+ *GETARG(intmax_t *) = ret;
+ else if (flags & LONGINT)
+ *GETARG(long *) = ret;
+ else if (flags & SHORTINT)
+ *GETARG(short *) = ret;
+ else if (flags & CHARINT)
+ *GETARG(signed char *) = ret;
+ else
+ *GETARG(int *) = ret;
+ continue; /* no output */
+ case 'O':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'o':
+ if (flags & INTMAX_SIZE)
+ ujval = UJARG();
+ else
+ ulval = UARG();
+ base = 8;
+ goto nosign;
+ case 'p':
+ /*-
+ * ``The argument shall be a pointer to void. The
+ * value of the pointer is converted to a sequence
+ * of printable characters, in an implementation-
+ * defined manner.''
+ * -- ANSI X3J11
+ */
+ ujval = (uintmax_t)(uintptr_t)GETARG(void *);
+ base = 16;
+ xdigs = xdigs_lower;
+ flags = flags | INTMAXT;
+ ox[1] = 'x';
+ goto nosign;
+ case 'S':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 's':
+ if (flags & LONGINT) {
+ wchar_t *wcp;
+
+ if (convbuf != NULL)
+ free(convbuf);
+ if ((wcp = GETARG(wchar_t *)) == NULL)
+ cp = "(null)";
+ else {
+ convbuf = __wcsconv(wcp, prec);
+ if (convbuf == NULL) {
+ fp->_flags |= __SERR;
+ goto error;
+ }
+ cp = convbuf;
+ }
+ } else if ((cp = GETARG(char *)) == NULL)
+ cp = "(null)";
+ size = (prec >= 0) ? strnlen(cp, prec) : strlen(cp);
+ sign = '\0';
+ break;
+ case 'U':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'u':
+ if (flags & INTMAX_SIZE)
+ ujval = UJARG();
+ else
+ ulval = UARG();
+ base = 10;
+ goto nosign;
+ case 'X':
+ xdigs = xdigs_upper;
+ goto hex;
+ case 'x':
+ xdigs = xdigs_lower;
+hex:
+ if (flags & INTMAX_SIZE)
+ ujval = UJARG();
+ else
+ ulval = UARG();
+ base = 16;
+ /* leading 0x/X only if non-zero */
+ if (flags & ALT &&
+ (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
+ ox[1] = ch;
+
+ flags &= ~GROUPING;
+ /* unsigned conversions */
+nosign: sign = '\0';
+ /*-
+ * ``... diouXx conversions ... if a precision is
+ * specified, the 0 flag will be ignored.''
+ * -- ANSI X3J11
+ */
+number: if ((dprec = prec) >= 0)
+ flags &= ~ZEROPAD;
+
+ /*-
+ * ``The result of converting a zero value with an
+ * explicit precision of zero is no characters.''
+ * -- ANSI X3J11
+ *
+ * ``The C Standard is clear enough as is. The call
+ * printf("%#.0o", 0) should print 0.''
+ * -- Defect Report #151
+ */
+ cp = buf + BUF;
+ if (flags & INTMAX_SIZE) {
+ if (ujval != 0 || prec != 0 ||
+ (flags & ALT && base == 8))
+ cp = __ujtoa(ujval, cp, base,
+ flags & ALT, xdigs);
+ } else {
+ if (ulval != 0 || prec != 0 ||
+ (flags & ALT && base == 8))
+ cp = __ultoa(ulval, cp, base,
+ flags & ALT, xdigs);
+ }
+ size = buf + BUF - cp;
+ if (size > BUF) /* should never happen */
+ abort();
+ if ((flags & GROUPING) && size != 0)
+ size += grouping_init(&gs, size, locale);
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ /* pretend it was %c with argument ch */
+ cp = buf;
+ *cp = ch;
+ size = 1;
+ sign = '\0';
+ break;
+ }
+
+ /*
+ * All reasonable formats wind up here. At this point, `cp'
+ * points to a string which (if not flags&LADJUST) should be
+ * padded out to `width' places. If flags&ZEROPAD, it should
+ * first be prefixed by any sign or other prefix; otherwise,
+ * it should be blank padded before the prefix is emitted.
+ * After any left-hand padding and prefixing, emit zeroes
+ * required by a decimal [diouxX] precision, then print the
+ * string proper, then emit zeroes required by any leftover
+ * floating precision; finally, if LADJUST, pad with blanks.
+ *
+ * Compute actual size, so we know how much to pad.
+ * size excludes decimal prec; realsz includes it.
+ */
+ realsz = dprec > size ? dprec : size;
+ if (sign)
+ realsz++;
+ if (ox[1])
+ realsz += 2;
+
+ prsize = width > realsz ? width : realsz;
+ if ((unsigned)ret + prsize > INT_MAX) {
+ ret = EOF;
+ errno = EOVERFLOW;
+ goto error;
+ }
+
+ /* right-adjusting blank padding */
+ if ((flags & (LADJUST|ZEROPAD)) == 0)
+ PAD(width - realsz, blanks);
+
+ /* prefix */
+ if (sign)
+ PRINT(&sign, 1);
+
+ if (ox[1]) { /* ox[1] is either x, X, or \0 */
+ ox[0] = '0';
+ PRINT(ox, 2);
+ }
+
+ /* right-adjusting zero padding */
+ if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
+ PAD(width - realsz, zeroes);
+
+ /* the string or number proper */
+#ifndef NO_FLOATING_POINT
+ if ((flags & FPT) == 0) {
+#endif
+ /* leading zeroes from decimal precision */
+ PAD(dprec - size, zeroes);
+ if (gs.grouping) {
+ if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0)
+ goto error;
+ } else {
+ PRINT(cp, size);
+ }
+#ifndef NO_FLOATING_POINT
+ } else { /* glue together f_p fragments */
+ if (!expchar) { /* %[fF] or sufficiently short %[gG] */
+ if (expt <= 0) {
+ PRINT(zeroes, 1);
+ if (prec || flags & ALT)
+ PRINT(decimal_point,decpt_len);
+ PAD(-expt, zeroes);
+ /* already handled initial 0's */
+ prec += expt;
+ } else {
+ if (gs.grouping) {
+ n = grouping_print(&gs, &io,
+ cp, dtoaend, locale);
+ if (n < 0)
+ goto error;
+ cp += n;
+ } else {
+ PRINTANDPAD(cp, dtoaend,
+ expt, zeroes);
+ cp += expt;
+ }
+ if (prec || flags & ALT)
+ PRINT(decimal_point,decpt_len);
+ }
+ PRINTANDPAD(cp, dtoaend, prec, zeroes);
+ } else { /* %[eE] or sufficiently long %[gG] */
+ if (prec > 1 || flags & ALT) {
+ PRINT(cp++, 1);
+ PRINT(decimal_point, decpt_len);
+ PRINT(cp, ndig-1);
+ PAD(prec - ndig, zeroes);
+ } else /* XeYYY */
+ PRINT(cp, 1);
+ PRINT(expstr, expsize);
+ }
+ }
+#endif
+ /* left-adjusting padding (always blank) */
+ if (flags & LADJUST)
+ PAD(width - realsz, blanks);
+
+ /* finally, adjust ret */
+ ret += prsize;
+
+ FLUSH(); /* copy out the I/O vectors */
+ }
+done:
+ FLUSH();
+error:
+ va_end(orgap);
+#ifndef NO_FLOATING_POINT
+ if (dtoaresult != NULL)
+ freedtoa(dtoaresult);
+#endif
+ if (convbuf != NULL)
+ free(convbuf);
+ if (__sferror(fp))
+ ret = EOF;
+ if ((argtable != NULL) && (argtable != statargtable))
+ free (argtable);
+ return (ret);
+ /* NOTREACHED */
+}
+
diff --git a/lib/libc/stdio/vfscanf.c b/lib/libc/stdio/vfscanf.c
new file mode 100644
index 0000000..6a6b19c
--- /dev/null
+++ b/lib/libc/stdio/vfscanf.c
@@ -0,0 +1,1174 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <ctype.h>
+#include <inttypes.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "un-namespace.h"
+
+#include "collate.h"
+#include "libc_private.h"
+#include "local.h"
+#include "xlocale_private.h"
+
+#ifndef NO_FLOATING_POINT
+#include <locale.h>
+#endif
+
+#define BUF 513 /* Maximum length of numeric string. */
+
+/*
+ * Flags used during conversion.
+ */
+#define LONG 0x01 /* l: long or double */
+#define LONGDBL 0x02 /* L: long double */
+#define SHORT 0x04 /* h: short */
+#define SUPPRESS 0x08 /* *: suppress assignment */
+#define POINTER 0x10 /* p: void * (as hex) */
+#define NOSKIP 0x20 /* [ or c: do not skip blanks */
+#define LONGLONG 0x400 /* ll: long long (+ deprecated q: quad) */
+#define INTMAXT 0x800 /* j: intmax_t */
+#define PTRDIFFT 0x1000 /* t: ptrdiff_t */
+#define SIZET 0x2000 /* z: size_t */
+#define SHORTSHORT 0x4000 /* hh: char */
+#define UNSIGNED 0x8000 /* %[oupxX] conversions */
+
+/*
+ * The following are used in integral conversions only:
+ * SIGNOK, NDIGITS, PFXOK, and NZDIGITS
+ */
+#define SIGNOK 0x40 /* +/- is (still) legal */
+#define NDIGITS 0x80 /* no digits detected */
+#define PFXOK 0x100 /* 0x prefix is (still) legal */
+#define NZDIGITS 0x200 /* no zero digits detected */
+#define HAVESIGN 0x10000 /* sign detected */
+
+/*
+ * Conversion types.
+ */
+#define CT_CHAR 0 /* %c conversion */
+#define CT_CCL 1 /* %[...] conversion */
+#define CT_STRING 2 /* %s conversion */
+#define CT_INT 3 /* %[dioupxX] conversion */
+#define CT_FLOAT 4 /* %[efgEFG] conversion */
+
+static const u_char *__sccl(char *, const u_char *);
+#ifndef NO_FLOATING_POINT
+static int parsefloat(FILE *, char *, char *, locale_t);
+#endif
+
+__weak_reference(__vfscanf, vfscanf);
+
+/*
+ * Conversion functions are passed a pointer to this object instead of
+ * a real parameter to indicate that the assignment-suppression (*)
+ * flag was specified. We could use a NULL pointer to indicate this,
+ * but that would mask bugs in applications that call scanf() with a
+ * NULL pointer.
+ */
+static const int suppress;
+#define SUPPRESS_PTR ((void *)&suppress)
+
+static const mbstate_t initial_mbs;
+
+/*
+ * The following conversion functions return the number of characters consumed,
+ * or -1 on input failure. Character class conversion returns 0 on match
+ * failure.
+ */
+
+static __inline int
+convert_char(FILE *fp, char * __restrict p, int width)
+{
+ int n, nread;
+
+ nread = 0;
+ if (p == SUPPRESS_PTR) {
+ size_t sum = 0;
+ for (;;) {
+ if ((n = fp->_r) < width) {
+ sum += n;
+ width -= n;
+ fp->_p += n;
+ if (__srefill(fp)) {
+ if (sum == 0)
+ return (-1);
+ break;
+ }
+ } else {
+ sum += width;
+ fp->_r -= width;
+ fp->_p += width;
+ break;
+ }
+ }
+ nread += sum;
+ } else {
+ size_t r = __fread(p, 1, width, fp);
+
+ if (r == 0)
+ return (-1);
+ nread += r;
+ }
+ return (nread);
+}
+
+static __inline int
+convert_wchar(FILE *fp, wchar_t *wcp, int width)
+{
+ mbstate_t mbs;
+ size_t nconv;
+ int n, nread;
+ char buf[MB_CUR_MAX];
+
+ nread = 0;
+ n = 0;
+ while (width != 0) {
+ if (n == MB_CUR_MAX) {
+ fp->_flags |= __SERR;
+ return (-1);
+ }
+ buf[n++] = *fp->_p;
+ fp->_p++;
+ fp->_r--;
+ mbs = initial_mbs;
+ nconv = mbrtowc(wcp, buf, n, &mbs);
+ if (nconv == (size_t)-1) {
+ fp->_flags |= __SERR;
+ return (-1);
+ }
+ if (nconv == 0 && wcp != SUPPRESS_PTR)
+ *wcp = L'\0';
+ if (nconv != (size_t)-2) {
+ nread += n;
+ width--;
+ if (wcp != SUPPRESS_PTR)
+ wcp++;
+ n = 0;
+ }
+ if (fp->_r <= 0 && __srefill(fp)) {
+ if (n != 0) {
+ fp->_flags |= __SERR;
+ return (-1);
+ }
+ break;
+ }
+ }
+ return (nread);
+}
+
+static __inline int
+convert_ccl(FILE *fp, char * __restrict p, int width, const char *ccltab)
+{
+ char *p0;
+ int n;
+
+ if (p == SUPPRESS_PTR) {
+ n = 0;
+ while (ccltab[*fp->_p]) {
+ n++, fp->_r--, fp->_p++;
+ if (--width == 0)
+ break;
+ if (fp->_r <= 0 && __srefill(fp)) {
+ if (n == 0)
+ return (-1);
+ break;
+ }
+ }
+ } else {
+ p0 = p;
+ while (ccltab[*fp->_p]) {
+ fp->_r--;
+ *p++ = *fp->_p++;
+ if (--width == 0)
+ break;
+ if (fp->_r <= 0 && __srefill(fp)) {
+ if (p == p0)
+ return (-1);
+ break;
+ }
+ }
+ n = p - p0;
+ if (n == 0)
+ return (0);
+ *p = 0;
+ }
+ return (n);
+}
+
+static __inline int
+convert_wccl(FILE *fp, wchar_t *wcp, int width, const char *ccltab)
+{
+ mbstate_t mbs;
+ wchar_t twc;
+ int n, nchars, nconv;
+ char buf[MB_CUR_MAX];
+
+ if (wcp == SUPPRESS_PTR)
+ wcp = &twc;
+ n = 0;
+ nchars = 0;
+ while (width != 0) {
+ if (n == MB_CUR_MAX) {
+ fp->_flags |= __SERR;
+ return (-1);
+ }
+ buf[n++] = *fp->_p;
+ fp->_p++;
+ fp->_r--;
+ mbs = initial_mbs;
+ nconv = mbrtowc(wcp, buf, n, &mbs);
+ if (nconv == (size_t)-1) {
+ fp->_flags |= __SERR;
+ return (-1);
+ }
+ if (nconv == 0)
+ *wcp = L'\0';
+ if (nconv != (size_t)-2) {
+ if (wctob(*wcp) != EOF && !ccltab[wctob(*wcp)]) {
+ while (n != 0) {
+ n--;
+ __ungetc(buf[n], fp);
+ }
+ break;
+ }
+ width--;
+ if (wcp != &twc)
+ wcp++;
+ nchars++;
+ n = 0;
+ }
+ if (fp->_r <= 0 && __srefill(fp)) {
+ if (n != 0) {
+ fp->_flags |= __SERR;
+ return (-1);
+ }
+ break;
+ }
+ }
+ if (n != 0) {
+ fp->_flags |= __SERR;
+ return (-1);
+ }
+ if (nchars == 0)
+ return (0);
+ *wcp = L'\0';
+ return (nchars);
+}
+
+static __inline int
+convert_string(FILE *fp, char * __restrict p, int width)
+{
+ char *p0;
+ int n;
+
+ if (p == SUPPRESS_PTR) {
+ n = 0;
+ while (!isspace(*fp->_p)) {
+ n++, fp->_r--, fp->_p++;
+ if (--width == 0)
+ break;
+ if (fp->_r <= 0 && __srefill(fp))
+ break;
+ }
+ } else {
+ p0 = p;
+ while (!isspace(*fp->_p)) {
+ fp->_r--;
+ *p++ = *fp->_p++;
+ if (--width == 0)
+ break;
+ if (fp->_r <= 0 && __srefill(fp))
+ break;
+ }
+ *p = 0;
+ n = p - p0;
+ }
+ return (n);
+}
+
+static __inline int
+convert_wstring(FILE *fp, wchar_t *wcp, int width)
+{
+ mbstate_t mbs;
+ wchar_t twc;
+ int n, nconv, nread;
+ char buf[MB_CUR_MAX];
+
+ if (wcp == SUPPRESS_PTR)
+ wcp = &twc;
+ n = nread = 0;
+ while (!isspace(*fp->_p) && width != 0) {
+ if (n == MB_CUR_MAX) {
+ fp->_flags |= __SERR;
+ return (-1);
+ }
+ buf[n++] = *fp->_p;
+ fp->_p++;
+ fp->_r--;
+ mbs = initial_mbs;
+ nconv = mbrtowc(wcp, buf, n, &mbs);
+ if (nconv == (size_t)-1) {
+ fp->_flags |= __SERR;
+ return (-1);
+ }
+ if (nconv == 0)
+ *wcp = L'\0';
+ if (nconv != (size_t)-2) {
+ if (iswspace(*wcp)) {
+ while (n != 0) {
+ n--;
+ __ungetc(buf[n], fp);
+ }
+ break;
+ }
+ nread += n;
+ width--;
+ if (wcp != &twc)
+ wcp++;
+ n = 0;
+ }
+ if (fp->_r <= 0 && __srefill(fp)) {
+ if (n != 0) {
+ fp->_flags |= __SERR;
+ return (-1);
+ }
+ break;
+ }
+ }
+ *wcp = L'\0';
+ return (nread);
+}
+
+/*
+ * Read an integer, storing it in buf. The only relevant bit in the
+ * flags argument is PFXOK.
+ *
+ * Return 0 on a match failure, and the number of characters read
+ * otherwise.
+ */
+static __inline int
+parseint(FILE *fp, char * __restrict buf, int width, int base, int flags)
+{
+ /* `basefix' is used to avoid `if' tests */
+ static const short basefix[17] =
+ { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+ char *p;
+ int c;
+
+ flags |= SIGNOK | NDIGITS | NZDIGITS;
+ for (p = buf; width; width--) {
+ c = *fp->_p;
+ /*
+ * Switch on the character; `goto ok' if we accept it
+ * as a part of number.
+ */
+ switch (c) {
+
+ /*
+ * The digit 0 is always legal, but is special. For
+ * %i conversions, if no digits (zero or nonzero) have
+ * been scanned (only signs), we will have base==0.
+ * In that case, we should set it to 8 and enable 0x
+ * prefixing. Also, if we have not scanned zero
+ * digits before this, do not turn off prefixing
+ * (someone else will turn it off if we have scanned
+ * any nonzero digits).
+ */
+ case '0':
+ if (base == 0) {
+ base = 8;
+ flags |= PFXOK;
+ }
+ if (flags & NZDIGITS)
+ flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
+ else
+ flags &= ~(SIGNOK|PFXOK|NDIGITS);
+ goto ok;
+
+ /* 1 through 7 always legal */
+ case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ base = basefix[base];
+ flags &= ~(SIGNOK | PFXOK | NDIGITS);
+ goto ok;
+
+ /* digits 8 and 9 ok iff decimal or hex */
+ case '8': case '9':
+ base = basefix[base];
+ if (base <= 8)
+ break; /* not legal here */
+ flags &= ~(SIGNOK | PFXOK | NDIGITS);
+ goto ok;
+
+ /* letters ok iff hex */
+ case 'A': case 'B': case 'C':
+ case 'D': case 'E': case 'F':
+ case 'a': case 'b': case 'c':
+ case 'd': case 'e': case 'f':
+ /* no need to fix base here */
+ if (base <= 10)
+ break; /* not legal here */
+ flags &= ~(SIGNOK | PFXOK | NDIGITS);
+ goto ok;
+
+ /* sign ok only as first character */
+ case '+': case '-':
+ if (flags & SIGNOK) {
+ flags &= ~SIGNOK;
+ flags |= HAVESIGN;
+ goto ok;
+ }
+ break;
+
+ /*
+ * x ok iff flag still set & 2nd char (or 3rd char if
+ * we have a sign).
+ */
+ case 'x': case 'X':
+ if (flags & PFXOK && p ==
+ buf + 1 + !!(flags & HAVESIGN)) {
+ base = 16; /* if %i */
+ flags &= ~PFXOK;
+ goto ok;
+ }
+ break;
+ }
+
+ /*
+ * If we got here, c is not a legal character for a
+ * number. Stop accumulating digits.
+ */
+ break;
+ ok:
+ /*
+ * c is legal: store it and look at the next.
+ */
+ *p++ = c;
+ if (--fp->_r > 0)
+ fp->_p++;
+ else if (__srefill(fp))
+ break; /* EOF */
+ }
+ /*
+ * If we had only a sign, it is no good; push back the sign.
+ * If the number ends in `x', it was [sign] '0' 'x', so push
+ * back the x and treat it as [sign] '0'.
+ */
+ if (flags & NDIGITS) {
+ if (p > buf)
+ (void) __ungetc(*(u_char *)--p, fp);
+ return (0);
+ }
+ c = ((u_char *)p)[-1];
+ if (c == 'x' || c == 'X') {
+ --p;
+ (void) __ungetc(c, fp);
+ }
+ return (p - buf);
+}
+
+/*
+ * __vfscanf - MT-safe version
+ */
+int
+__vfscanf(FILE *fp, char const *fmt0, va_list ap)
+{
+ int ret;
+
+ FLOCKFILE(fp);
+ ret = __svfscanf(fp, __get_locale(), fmt0, ap);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
+int
+vfscanf_l(FILE *fp, locale_t locale, char const *fmt0, va_list ap)
+{
+ int ret;
+ FIX_LOCALE(locale);
+
+ FLOCKFILE(fp);
+ ret = __svfscanf(fp, locale, fmt0, ap);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
+
+/*
+ * __svfscanf - non-MT-safe version of __vfscanf
+ */
+int
+__svfscanf(FILE *fp, locale_t locale, const char *fmt0, va_list ap)
+{
+#define GETARG(type) ((flags & SUPPRESS) ? SUPPRESS_PTR : va_arg(ap, type))
+ const u_char *fmt = (const u_char *)fmt0;
+ int c; /* character from format, or conversion */
+ size_t width; /* field width, or 0 */
+ int flags; /* flags as defined above */
+ int nassigned; /* number of fields assigned */
+ int nconversions; /* number of conversions */
+ int nr; /* characters read by the current conversion */
+ int nread; /* number of characters consumed from fp */
+ int base; /* base argument to conversion function */
+ char ccltab[256]; /* character class table for %[...] */
+ char buf[BUF]; /* buffer for numeric conversions */
+
+ ORIENT(fp, -1);
+
+ nassigned = 0;
+ nconversions = 0;
+ nread = 0;
+ for (;;) {
+ c = *fmt++;
+ if (c == 0)
+ return (nassigned);
+ if (isspace(c)) {
+ while ((fp->_r > 0 || __srefill(fp) == 0) && isspace(*fp->_p))
+ nread++, fp->_r--, fp->_p++;
+ continue;
+ }
+ if (c != '%')
+ goto literal;
+ width = 0;
+ flags = 0;
+ /*
+ * switch on the format. continue if done;
+ * break once format type is derived.
+ */
+again: c = *fmt++;
+ switch (c) {
+ case '%':
+literal:
+ if (fp->_r <= 0 && __srefill(fp))
+ goto input_failure;
+ if (*fp->_p != c)
+ goto match_failure;
+ fp->_r--, fp->_p++;
+ nread++;
+ continue;
+
+ case '*':
+ flags |= SUPPRESS;
+ goto again;
+ case 'j':
+ flags |= INTMAXT;
+ goto again;
+ case 'l':
+ if (flags & LONG) {
+ flags &= ~LONG;
+ flags |= LONGLONG;
+ } else
+ flags |= LONG;
+ goto again;
+ case 'q':
+ flags |= LONGLONG; /* not quite */
+ goto again;
+ case 't':
+ flags |= PTRDIFFT;
+ goto again;
+ case 'z':
+ flags |= SIZET;
+ goto again;
+ case 'L':
+ flags |= LONGDBL;
+ goto again;
+ case 'h':
+ if (flags & SHORT) {
+ flags &= ~SHORT;
+ flags |= SHORTSHORT;
+ } else
+ flags |= SHORT;
+ goto again;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ width = width * 10 + c - '0';
+ goto again;
+
+ /*
+ * Conversions.
+ */
+ case 'd':
+ c = CT_INT;
+ base = 10;
+ break;
+
+ case 'i':
+ c = CT_INT;
+ base = 0;
+ break;
+
+ case 'o':
+ c = CT_INT;
+ flags |= UNSIGNED;
+ base = 8;
+ break;
+
+ case 'u':
+ c = CT_INT;
+ flags |= UNSIGNED;
+ base = 10;
+ break;
+
+ case 'X':
+ case 'x':
+ flags |= PFXOK; /* enable 0x prefixing */
+ c = CT_INT;
+ flags |= UNSIGNED;
+ base = 16;
+ break;
+
+#ifndef NO_FLOATING_POINT
+ case 'A': case 'E': case 'F': case 'G':
+ case 'a': case 'e': case 'f': case 'g':
+ c = CT_FLOAT;
+ break;
+#endif
+
+ case 'S':
+ flags |= LONG;
+ /* FALLTHROUGH */
+ case 's':
+ c = CT_STRING;
+ break;
+
+ case '[':
+ fmt = __sccl(ccltab, fmt);
+ flags |= NOSKIP;
+ c = CT_CCL;
+ break;
+
+ case 'C':
+ flags |= LONG;
+ /* FALLTHROUGH */
+ case 'c':
+ flags |= NOSKIP;
+ c = CT_CHAR;
+ break;
+
+ case 'p': /* pointer format is like hex */
+ flags |= POINTER | PFXOK;
+ c = CT_INT; /* assumes sizeof(uintmax_t) */
+ flags |= UNSIGNED; /* >= sizeof(uintptr_t) */
+ base = 16;
+ break;
+
+ case 'n':
+ if (flags & SUPPRESS) /* ??? */
+ continue;
+ if (flags & SHORTSHORT)
+ *va_arg(ap, char *) = nread;
+ else if (flags & SHORT)
+ *va_arg(ap, short *) = nread;
+ else if (flags & LONG)
+ *va_arg(ap, long *) = nread;
+ else if (flags & LONGLONG)
+ *va_arg(ap, long long *) = nread;
+ else if (flags & INTMAXT)
+ *va_arg(ap, intmax_t *) = nread;
+ else if (flags & SIZET)
+ *va_arg(ap, size_t *) = nread;
+ else if (flags & PTRDIFFT)
+ *va_arg(ap, ptrdiff_t *) = nread;
+ else
+ *va_arg(ap, int *) = nread;
+ continue;
+
+ default:
+ goto match_failure;
+
+ /*
+ * Disgusting backwards compatibility hack. XXX
+ */
+ case '\0': /* compat */
+ return (EOF);
+ }
+
+ /*
+ * We have a conversion that requires input.
+ */
+ if (fp->_r <= 0 && __srefill(fp))
+ goto input_failure;
+
+ /*
+ * Consume leading white space, except for formats
+ * that suppress this.
+ */
+ if ((flags & NOSKIP) == 0) {
+ while (isspace(*fp->_p)) {
+ nread++;
+ if (--fp->_r > 0)
+ fp->_p++;
+ else if (__srefill(fp))
+ goto input_failure;
+ }
+ /*
+ * Note that there is at least one character in
+ * the buffer, so conversions that do not set NOSKIP
+ * ca no longer result in an input failure.
+ */
+ }
+
+ /*
+ * Do the conversion.
+ */
+ switch (c) {
+
+ case CT_CHAR:
+ /* scan arbitrary characters (sets NOSKIP) */
+ if (width == 0)
+ width = 1;
+ if (flags & LONG) {
+ nr = convert_wchar(fp, GETARG(wchar_t *),
+ width);
+ } else {
+ nr = convert_char(fp, GETARG(char *), width);
+ }
+ if (nr < 0)
+ goto input_failure;
+ break;
+
+ case CT_CCL:
+ /* scan a (nonempty) character class (sets NOSKIP) */
+ if (width == 0)
+ width = (size_t)~0; /* `infinity' */
+ if (flags & LONG) {
+ nr = convert_wccl(fp, GETARG(wchar_t *), width,
+ ccltab);
+ } else {
+ nr = convert_ccl(fp, GETARG(char *), width,
+ ccltab);
+ }
+ if (nr <= 0) {
+ if (nr < 0)
+ goto input_failure;
+ else /* nr == 0 */
+ goto match_failure;
+ }
+ break;
+
+ case CT_STRING:
+ /* like CCL, but zero-length string OK, & no NOSKIP */
+ if (width == 0)
+ width = (size_t)~0;
+ if (flags & LONG) {
+ nr = convert_wstring(fp, GETARG(wchar_t *),
+ width);
+ } else {
+ nr = convert_string(fp, GETARG(char *), width);
+ }
+ if (nr < 0)
+ goto input_failure;
+ break;
+
+ case CT_INT:
+ /* scan an integer as if by the conversion function */
+#ifdef hardway
+ if (width == 0 || width > sizeof(buf) - 1)
+ width = sizeof(buf) - 1;
+#else
+ /* size_t is unsigned, hence this optimisation */
+ if (--width > sizeof(buf) - 2)
+ width = sizeof(buf) - 2;
+ width++;
+#endif
+ nr = parseint(fp, buf, width, base, flags);
+ if (nr == 0)
+ goto match_failure;
+ if ((flags & SUPPRESS) == 0) {
+ uintmax_t res;
+
+ buf[nr] = '\0';
+ if ((flags & UNSIGNED) == 0)
+ res = strtoimax_l(buf, (char **)NULL, base, locale);
+ else
+ res = strtoumax_l(buf, (char **)NULL, base, locale);
+ if (flags & POINTER)
+ *va_arg(ap, void **) =
+ (void *)(uintptr_t)res;
+ else if (flags & SHORTSHORT)
+ *va_arg(ap, char *) = res;
+ else if (flags & SHORT)
+ *va_arg(ap, short *) = res;
+ else if (flags & LONG)
+ *va_arg(ap, long *) = res;
+ else if (flags & LONGLONG)
+ *va_arg(ap, long long *) = res;
+ else if (flags & INTMAXT)
+ *va_arg(ap, intmax_t *) = res;
+ else if (flags & PTRDIFFT)
+ *va_arg(ap, ptrdiff_t *) = res;
+ else if (flags & SIZET)
+ *va_arg(ap, size_t *) = res;
+ else
+ *va_arg(ap, int *) = res;
+ }
+ break;
+
+#ifndef NO_FLOATING_POINT
+ case CT_FLOAT:
+ /* scan a floating point number as if by strtod */
+ if (width == 0 || width > sizeof(buf) - 1)
+ width = sizeof(buf) - 1;
+ nr = parsefloat(fp, buf, buf + width, locale);
+ if (nr == 0)
+ goto match_failure;
+ if ((flags & SUPPRESS) == 0) {
+ if (flags & LONGDBL) {
+ long double res = strtold_l(buf, NULL,
+ locale);
+ *va_arg(ap, long double *) = res;
+ } else if (flags & LONG) {
+ double res = strtod_l(buf, NULL,
+ locale);
+ *va_arg(ap, double *) = res;
+ } else {
+ float res = strtof_l(buf, NULL, locale);
+ *va_arg(ap, float *) = res;
+ }
+ }
+ break;
+#endif /* !NO_FLOATING_POINT */
+ }
+ if (!(flags & SUPPRESS))
+ nassigned++;
+ nread += nr;
+ nconversions++;
+ }
+input_failure:
+ return (nconversions != 0 ? nassigned : EOF);
+match_failure:
+ return (nassigned);
+}
+
+/*
+ * Fill in the given table from the scanset at the given format
+ * (just after `['). Return a pointer to the character past the
+ * closing `]'. The table has a 1 wherever characters should be
+ * considered part of the scanset.
+ */
+static const u_char *
+__sccl(tab, fmt)
+ char *tab;
+ const u_char *fmt;
+{
+ int c, n, v, i;
+ struct xlocale_collate *table =
+ (struct xlocale_collate*)__get_locale()->components[XLC_COLLATE];
+
+ /* first `clear' the whole table */
+ c = *fmt++; /* first char hat => negated scanset */
+ if (c == '^') {
+ v = 1; /* default => accept */
+ c = *fmt++; /* get new first char */
+ } else
+ v = 0; /* default => reject */
+
+ /* XXX: Will not work if sizeof(tab*) > sizeof(char) */
+ (void) memset(tab, v, 256);
+
+ if (c == 0)
+ return (fmt - 1);/* format ended before closing ] */
+
+ /*
+ * Now set the entries corresponding to the actual scanset
+ * to the opposite of the above.
+ *
+ * The first character may be ']' (or '-') without being special;
+ * the last character may be '-'.
+ */
+ v = 1 - v;
+ for (;;) {
+ tab[c] = v; /* take character c */
+doswitch:
+ n = *fmt++; /* and examine the next */
+ switch (n) {
+
+ case 0: /* format ended too soon */
+ return (fmt - 1);
+
+ case '-':
+ /*
+ * A scanset of the form
+ * [01+-]
+ * is defined as `the digit 0, the digit 1,
+ * the character +, the character -', but
+ * the effect of a scanset such as
+ * [a-zA-Z0-9]
+ * is implementation defined. The V7 Unix
+ * scanf treats `a-z' as `the letters a through
+ * z', but treats `a-a' as `the letter a, the
+ * character -, and the letter a'.
+ *
+ * For compatibility, the `-' is not considerd
+ * to define a range if the character following
+ * it is either a close bracket (required by ANSI)
+ * or is not numerically greater than the character
+ * we just stored in the table (c).
+ */
+ n = *fmt;
+ if (n == ']'
+ || (table->__collate_load_error ? n < c :
+ __collate_range_cmp (table, n, c) < 0
+ )
+ ) {
+ c = '-';
+ break; /* resume the for(;;) */
+ }
+ fmt++;
+ /* fill in the range */
+ if (table->__collate_load_error) {
+ do {
+ tab[++c] = v;
+ } while (c < n);
+ } else {
+ for (i = 0; i < 256; i ++)
+ if ( __collate_range_cmp (table, c, i) < 0
+ && __collate_range_cmp (table, i, n) <= 0
+ )
+ tab[i] = v;
+ }
+#if 1 /* XXX another disgusting compatibility hack */
+ c = n;
+ /*
+ * Alas, the V7 Unix scanf also treats formats
+ * such as [a-c-e] as `the letters a through e'.
+ * This too is permitted by the standard....
+ */
+ goto doswitch;
+#else
+ c = *fmt++;
+ if (c == 0)
+ return (fmt - 1);
+ if (c == ']')
+ return (fmt);
+#endif
+ break;
+
+ case ']': /* end of scanset */
+ return (fmt);
+
+ default: /* just another character */
+ c = n;
+ break;
+ }
+ }
+ /* NOTREACHED */
+}
+
+#ifndef NO_FLOATING_POINT
+static int
+parsefloat(FILE *fp, char *buf, char *end, locale_t locale)
+{
+ char *commit, *p;
+ int infnanpos = 0, decptpos = 0;
+ enum {
+ S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX,
+ S_DIGITS, S_DECPT, S_FRAC, S_EXP, S_EXPDIGITS
+ } state = S_START;
+ unsigned char c;
+ const char *decpt = localeconv_l(locale)->decimal_point;
+ _Bool gotmantdig = 0, ishex = 0;
+
+ /*
+ * We set commit = p whenever the string we have read so far
+ * constitutes a valid representation of a floating point
+ * number by itself. At some point, the parse will complete
+ * or fail, and we will ungetc() back to the last commit point.
+ * To ensure that the file offset gets updated properly, it is
+ * always necessary to read at least one character that doesn't
+ * match; thus, we can't short-circuit "infinity" or "nan(...)".
+ */
+ commit = buf - 1;
+ for (p = buf; p < end; ) {
+ c = *fp->_p;
+reswitch:
+ switch (state) {
+ case S_START:
+ state = S_GOTSIGN;
+ if (c == '-' || c == '+')
+ break;
+ else
+ goto reswitch;
+ case S_GOTSIGN:
+ switch (c) {
+ case '0':
+ state = S_MAYBEHEX;
+ commit = p;
+ break;
+ case 'I':
+ case 'i':
+ state = S_INF;
+ break;
+ case 'N':
+ case 'n':
+ state = S_NAN;
+ break;
+ default:
+ state = S_DIGITS;
+ goto reswitch;
+ }
+ break;
+ case S_INF:
+ if (infnanpos > 6 ||
+ (c != "nfinity"[infnanpos] &&
+ c != "NFINITY"[infnanpos]))
+ goto parsedone;
+ if (infnanpos == 1 || infnanpos == 6)
+ commit = p; /* inf or infinity */
+ infnanpos++;
+ break;
+ case S_NAN:
+ switch (infnanpos) {
+ case 0:
+ if (c != 'A' && c != 'a')
+ goto parsedone;
+ break;
+ case 1:
+ if (c != 'N' && c != 'n')
+ goto parsedone;
+ else
+ commit = p;
+ break;
+ case 2:
+ if (c != '(')
+ goto parsedone;
+ break;
+ default:
+ if (c == ')') {
+ commit = p;
+ state = S_DONE;
+ } else if (!isalnum(c) && c != '_')
+ goto parsedone;
+ break;
+ }
+ infnanpos++;
+ break;
+ case S_DONE:
+ goto parsedone;
+ case S_MAYBEHEX:
+ state = S_DIGITS;
+ if (c == 'X' || c == 'x') {
+ ishex = 1;
+ break;
+ } else { /* we saw a '0', but no 'x' */
+ gotmantdig = 1;
+ goto reswitch;
+ }
+ case S_DIGITS:
+ if ((ishex && isxdigit(c)) || isdigit(c)) {
+ gotmantdig = 1;
+ commit = p;
+ break;
+ } else {
+ state = S_DECPT;
+ goto reswitch;
+ }
+ case S_DECPT:
+ if (c == decpt[decptpos]) {
+ if (decpt[++decptpos] == '\0') {
+ /* We read the complete decpt seq. */
+ state = S_FRAC;
+ if (gotmantdig)
+ commit = p;
+ }
+ break;
+ } else if (!decptpos) {
+ /* We didn't read any decpt characters. */
+ state = S_FRAC;
+ goto reswitch;
+ } else {
+ /*
+ * We read part of a multibyte decimal point,
+ * but the rest is invalid, so bail.
+ */
+ goto parsedone;
+ }
+ case S_FRAC:
+ if (((c == 'E' || c == 'e') && !ishex) ||
+ ((c == 'P' || c == 'p') && ishex)) {
+ if (!gotmantdig)
+ goto parsedone;
+ else
+ state = S_EXP;
+ } else if ((ishex && isxdigit(c)) || isdigit(c)) {
+ commit = p;
+ gotmantdig = 1;
+ } else
+ goto parsedone;
+ break;
+ case S_EXP:
+ state = S_EXPDIGITS;
+ if (c == '-' || c == '+')
+ break;
+ else
+ goto reswitch;
+ case S_EXPDIGITS:
+ if (isdigit(c))
+ commit = p;
+ else
+ goto parsedone;
+ break;
+ default:
+ abort();
+ }
+ *p++ = c;
+ if (--fp->_r > 0)
+ fp->_p++;
+ else if (__srefill(fp))
+ break; /* EOF */
+ }
+
+parsedone:
+ while (commit < --p)
+ __ungetc(*(u_char *)p, fp);
+ *++commit = '\0';
+ return (commit - buf);
+}
+#endif
diff --git a/lib/libc/stdio/vfwprintf.c b/lib/libc/stdio/vfwprintf.c
new file mode 100644
index 0000000..cc96b63
--- /dev/null
+++ b/lib/libc/stdio/vfwprintf.c
@@ -0,0 +1,1101 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vfprintf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Actual wprintf innards.
+ *
+ * Avoid making gratuitous changes to this source file; it should be kept
+ * as close as possible to vfprintf.c for ease of maintenance.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdarg.h>
+#include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+#include "local.h"
+#include "fvwrite.h"
+#include "printflocal.h"
+#include "xlocale_private.h"
+
+static int __sprint(FILE *, struct __suio *, locale_t);
+static int __sbprintf(FILE *, locale_t, const wchar_t *, va_list) __noinline;
+static wint_t __xfputwc(wchar_t, FILE *, locale_t);
+static wchar_t *__mbsconv(char *, int);
+
+#define CHAR wchar_t
+#include "printfcommon.h"
+
+struct grouping_state {
+ wchar_t thousands_sep; /* locale-specific thousands separator */
+ const char *grouping; /* locale-specific numeric grouping rules */
+ int lead; /* sig figs before decimal or group sep */
+ int nseps; /* number of group separators with ' */
+ int nrepeats; /* number of repeats of the last group */
+};
+
+static const mbstate_t initial_mbs;
+
+static inline wchar_t
+get_decpt(locale_t locale)
+{
+ mbstate_t mbs;
+ wchar_t decpt;
+ int nconv;
+
+ mbs = initial_mbs;
+ nconv = mbrtowc(&decpt, localeconv_l(locale)->decimal_point, MB_CUR_MAX, &mbs);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ decpt = '.'; /* failsafe */
+ return (decpt);
+}
+
+static inline wchar_t
+get_thousep(locale_t locale)
+{
+ mbstate_t mbs;
+ wchar_t thousep;
+ int nconv;
+
+ mbs = initial_mbs;
+ nconv = mbrtowc(&thousep, localeconv_l(locale)->thousands_sep,
+ MB_CUR_MAX, &mbs);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ thousep = '\0'; /* failsafe */
+ return (thousep);
+}
+
+/*
+ * Initialize the thousands' grouping state in preparation to print a
+ * number with ndigits digits. This routine returns the total number
+ * of wide characters that will be printed.
+ */
+static int
+grouping_init(struct grouping_state *gs, int ndigits, locale_t locale)
+{
+
+ gs->grouping = localeconv_l(locale)->grouping;
+ gs->thousands_sep = get_thousep(locale);
+
+ gs->nseps = gs->nrepeats = 0;
+ gs->lead = ndigits;
+ while (*gs->grouping != CHAR_MAX) {
+ if (gs->lead <= *gs->grouping)
+ break;
+ gs->lead -= *gs->grouping;
+ if (*(gs->grouping+1)) {
+ gs->nseps++;
+ gs->grouping++;
+ } else
+ gs->nrepeats++;
+ }
+ return (gs->nseps + gs->nrepeats);
+}
+
+/*
+ * Print a number with thousands' separators.
+ */
+static int
+grouping_print(struct grouping_state *gs, struct io_state *iop,
+ const CHAR *cp, const CHAR *ep, locale_t locale)
+{
+ const CHAR *cp0 = cp;
+
+ if (io_printandpad(iop, cp, ep, gs->lead, zeroes, locale))
+ return (-1);
+ cp += gs->lead;
+ while (gs->nseps > 0 || gs->nrepeats > 0) {
+ if (gs->nrepeats > 0)
+ gs->nrepeats--;
+ else {
+ gs->grouping--;
+ gs->nseps--;
+ }
+ if (io_print(iop, &gs->thousands_sep, 1, locale))
+ return (-1);
+ if (io_printandpad(iop, cp, ep, *gs->grouping, zeroes, locale))
+ return (-1);
+ cp += *gs->grouping;
+ }
+ if (cp > ep)
+ cp = ep;
+ return (cp - cp0);
+}
+
+
+/*
+ * Flush out all the vectors defined by the given uio,
+ * then reset it so that it can be reused.
+ *
+ * XXX The fact that we do this a character at a time and convert to a
+ * multibyte character sequence even if the destination is a wide
+ * string eclipses the benefits of buffering.
+ */
+static int
+__sprint(FILE *fp, struct __suio *uio, locale_t locale)
+{
+ struct __siov *iov;
+ wchar_t *p;
+ int i, len;
+
+ iov = uio->uio_iov;
+ for (; uio->uio_resid != 0; uio->uio_resid -= len, iov++) {
+ p = (wchar_t *)iov->iov_base;
+ len = iov->iov_len;
+ for (i = 0; i < len; i++) {
+ if (__xfputwc(p[i], fp, locale) == WEOF)
+ return (-1);
+ }
+ }
+ uio->uio_iovcnt = 0;
+ return (0);
+}
+
+/*
+ * Helper function for `fprintf to unbuffered unix file': creates a
+ * temporary buffer. We only work on write-only files; this avoids
+ * worries about ungetc buffers and so forth.
+ */
+static int
+__sbprintf(FILE *fp, locale_t locale, const wchar_t *fmt, va_list ap)
+{
+ int ret;
+ FILE fake;
+ unsigned char buf[BUFSIZ];
+
+ /* XXX This is probably not needed. */
+ if (prepwrite(fp) != 0)
+ return (EOF);
+
+ /* copy the important variables */
+ fake._flags = fp->_flags & ~__SNBF;
+ fake._file = fp->_file;
+ fake._cookie = fp->_cookie;
+ fake._write = fp->_write;
+ fake._orientation = fp->_orientation;
+ fake._mbstate = fp->_mbstate;
+
+ /* set up the buffer */
+ fake._bf._base = fake._p = buf;
+ fake._bf._size = fake._w = sizeof(buf);
+ fake._lbfsize = 0; /* not actually used, but Just In Case */
+
+ /* do the work, then copy any error status */
+ ret = __vfwprintf(&fake, locale, fmt, ap);
+ if (ret >= 0 && __fflush(&fake))
+ ret = WEOF;
+ if (fake._flags & __SERR)
+ fp->_flags |= __SERR;
+ return (ret);
+}
+
+/*
+ * Like __fputwc, but handles fake string (__SSTR) files properly.
+ * File must already be locked.
+ */
+static wint_t
+__xfputwc(wchar_t wc, FILE *fp, locale_t locale)
+{
+ mbstate_t mbs;
+ char buf[MB_LEN_MAX];
+ struct __suio uio;
+ struct __siov iov;
+ size_t len;
+
+ if ((fp->_flags & __SSTR) == 0)
+ return (__fputwc(wc, fp, locale));
+
+ mbs = initial_mbs;
+ if ((len = wcrtomb(buf, wc, &mbs)) == (size_t)-1) {
+ fp->_flags |= __SERR;
+ return (WEOF);
+ }
+ uio.uio_iov = &iov;
+ uio.uio_resid = len;
+ uio.uio_iovcnt = 1;
+ iov.iov_base = buf;
+ iov.iov_len = len;
+ return (__sfvwrite(fp, &uio) != EOF ? (wint_t)wc : WEOF);
+}
+
+/*
+ * Convert a multibyte character string argument for the %s format to a wide
+ * string representation. ``prec'' specifies the maximum number of bytes
+ * to output. If ``prec'' is greater than or equal to zero, we can't assume
+ * that the multibyte char. string ends in a null character.
+ */
+static wchar_t *
+__mbsconv(char *mbsarg, int prec)
+{
+ mbstate_t mbs;
+ wchar_t *convbuf, *wcp;
+ const char *p;
+ size_t insize, nchars, nconv;
+
+ if (mbsarg == NULL)
+ return (NULL);
+
+ /*
+ * Supplied argument is a multibyte string; convert it to wide
+ * characters first.
+ */
+ if (prec >= 0) {
+ /*
+ * String is not guaranteed to be NUL-terminated. Find the
+ * number of characters to print.
+ */
+ p = mbsarg;
+ insize = nchars = nconv = 0;
+ mbs = initial_mbs;
+ while (nchars != (size_t)prec) {
+ nconv = mbrlen(p, MB_CUR_MAX, &mbs);
+ if (nconv == 0 || nconv == (size_t)-1 ||
+ nconv == (size_t)-2)
+ break;
+ p += nconv;
+ nchars++;
+ insize += nconv;
+ }
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ return (NULL);
+ } else {
+ insize = strlen(mbsarg);
+ nconv = 0;
+ }
+
+ /*
+ * Allocate buffer for the result and perform the conversion,
+ * converting at most `size' bytes of the input multibyte string to
+ * wide characters for printing.
+ */
+ convbuf = malloc((insize + 1) * sizeof(*convbuf));
+ if (convbuf == NULL)
+ return (NULL);
+ wcp = convbuf;
+ p = mbsarg;
+ mbs = initial_mbs;
+ while (insize != 0) {
+ nconv = mbrtowc(wcp, p, insize, &mbs);
+ if (nconv == 0 || nconv == (size_t)-1 || nconv == (size_t)-2)
+ break;
+ wcp++;
+ p += nconv;
+ insize -= nconv;
+ }
+ if (nconv == (size_t)-1 || nconv == (size_t)-2) {
+ free(convbuf);
+ return (NULL);
+ }
+ *wcp = L'\0';
+
+ return (convbuf);
+}
+
+/*
+ * MT-safe version
+ */
+int
+vfwprintf_l(FILE * __restrict fp, locale_t locale,
+ const wchar_t * __restrict fmt0, va_list ap)
+
+{
+ int ret;
+ FIX_LOCALE(locale);
+ FLOCKFILE(fp);
+ /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+ fp->_file >= 0)
+ ret = __sbprintf(fp, locale, fmt0, ap);
+ else
+ ret = __vfwprintf(fp, locale, fmt0, ap);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
+int
+vfwprintf(FILE * __restrict fp, const wchar_t * __restrict fmt0, va_list ap)
+{
+ return vfwprintf_l(fp, __get_locale(), fmt0, ap);
+}
+
+/*
+ * The size of the buffer we use as scratch space for integer
+ * conversions, among other things. We need enough space to
+ * write a uintmax_t in octal (plus one byte).
+ */
+#if UINTMAX_MAX <= UINT64_MAX
+#define BUF 32
+#else
+#error "BUF must be large enough to format a uintmax_t"
+#endif
+
+/*
+ * Non-MT-safe version
+ */
+int
+__vfwprintf(FILE *fp, locale_t locale, const wchar_t *fmt0, va_list ap)
+{
+ wchar_t *fmt; /* format string */
+ wchar_t ch; /* character from fmt */
+ int n, n2; /* handy integer (short term usage) */
+ wchar_t *cp; /* handy char pointer (short term usage) */
+ int flags; /* flags as above */
+ int ret; /* return value accumulator */
+ int width; /* width from format (%8d), or 0 */
+ int prec; /* precision from format; <0 for N/A */
+ wchar_t sign; /* sign prefix (' ', '+', '-', or \0) */
+ struct grouping_state gs; /* thousands' grouping info */
+#ifndef NO_FLOATING_POINT
+ /*
+ * We can decompose the printed representation of floating
+ * point numbers into several parts, some of which may be empty:
+ *
+ * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
+ * A B ---C--- D E F
+ *
+ * A: 'sign' holds this value if present; '\0' otherwise
+ * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
+ * C: cp points to the string MMMNNN. Leading and trailing
+ * zeros are not in the string and must be added.
+ * D: expchar holds this character; '\0' if no exponent, e.g. %f
+ * F: at least two digits for decimal, at least one digit for hex
+ */
+ wchar_t decimal_point; /* locale specific decimal point */
+ int signflag; /* true if float is negative */
+ union { /* floating point arguments %[aAeEfFgG] */
+ double dbl;
+ long double ldbl;
+ } fparg;
+ int expt; /* integer value of exponent */
+ char expchar; /* exponent character: [eEpP\0] */
+ char *dtoaend; /* pointer to end of converted digits */
+ int expsize; /* character count for expstr */
+ int ndig; /* actual number of digits returned by dtoa */
+ wchar_t expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
+ char *dtoaresult; /* buffer allocated by dtoa */
+#endif
+ u_long ulval; /* integer arguments %[diouxX] */
+ uintmax_t ujval; /* %j, %ll, %q, %t, %z integers */
+ int base; /* base for [diouxX] conversion */
+ int dprec; /* a copy of prec if [diouxX], 0 otherwise */
+ int realsz; /* field size expanded by dprec, sign, etc */
+ int size; /* size of converted field or string */
+ int prsize; /* max size of printed field */
+ const char *xdigs; /* digits for [xX] conversion */
+ struct io_state io; /* I/O buffering state */
+ wchar_t buf[BUF]; /* buffer with space for digits of uintmax_t */
+ wchar_t ox[2]; /* space for 0x hex-prefix */
+ union arg *argtable; /* args, built due to positional arg */
+ union arg statargtable [STATIC_ARG_TBL_SIZE];
+ int nextarg; /* 1-based argument index */
+ va_list orgap; /* original argument pointer */
+ wchar_t *convbuf; /* multibyte to wide conversion result */
+
+ static const char xdigs_lower[16] = "0123456789abcdef";
+ static const char xdigs_upper[16] = "0123456789ABCDEF";
+
+ /* BEWARE, these `goto error' on error. */
+#define PRINT(ptr, len) do { \
+ if (io_print(&io, (ptr), (len), locale)) \
+ goto error; \
+} while (0)
+#define PAD(howmany, with) { \
+ if (io_pad(&io, (howmany), (with), locale)) \
+ goto error; \
+}
+#define PRINTANDPAD(p, ep, len, with) { \
+ if (io_printandpad(&io, (p), (ep), (len), (with), locale)) \
+ goto error; \
+}
+#define FLUSH() { \
+ if (io_flush(&io, locale)) \
+ goto error; \
+}
+
+ /*
+ * Get the argument indexed by nextarg. If the argument table is
+ * built, use it to get the argument. If its not, get the next
+ * argument (and arguments must be gotten sequentially).
+ */
+#define GETARG(type) \
+ ((argtable != NULL) ? *((type*)(&argtable[nextarg++])) : \
+ (nextarg++, va_arg(ap, type)))
+
+ /*
+ * To extend shorts properly, we need both signed and unsigned
+ * argument extraction methods.
+ */
+#define SARG() \
+ (flags&LONGINT ? GETARG(long) : \
+ flags&SHORTINT ? (long)(short)GETARG(int) : \
+ flags&CHARINT ? (long)(signed char)GETARG(int) : \
+ (long)GETARG(int))
+#define UARG() \
+ (flags&LONGINT ? GETARG(u_long) : \
+ flags&SHORTINT ? (u_long)(u_short)GETARG(int) : \
+ flags&CHARINT ? (u_long)(u_char)GETARG(int) : \
+ (u_long)GETARG(u_int))
+#define INTMAX_SIZE (INTMAXT|SIZET|PTRDIFFT|LLONGINT)
+#define SJARG() \
+ (flags&INTMAXT ? GETARG(intmax_t) : \
+ flags&SIZET ? (intmax_t)GETARG(ssize_t) : \
+ flags&PTRDIFFT ? (intmax_t)GETARG(ptrdiff_t) : \
+ (intmax_t)GETARG(long long))
+#define UJARG() \
+ (flags&INTMAXT ? GETARG(uintmax_t) : \
+ flags&SIZET ? (uintmax_t)GETARG(size_t) : \
+ flags&PTRDIFFT ? (uintmax_t)GETARG(ptrdiff_t) : \
+ (uintmax_t)GETARG(unsigned long long))
+
+ /*
+ * Get * arguments, including the form *nn$. Preserve the nextarg
+ * that the argument can be gotten once the type is determined.
+ */
+#define GETASTER(val) \
+ n2 = 0; \
+ cp = fmt; \
+ while (is_digit(*cp)) { \
+ n2 = 10 * n2 + to_digit(*cp); \
+ cp++; \
+ } \
+ if (*cp == '$') { \
+ int hold = nextarg; \
+ if (argtable == NULL) { \
+ argtable = statargtable; \
+ if (__find_warguments (fmt0, orgap, &argtable)) { \
+ ret = EOF; \
+ goto error; \
+ } \
+ } \
+ nextarg = n2; \
+ val = GETARG (int); \
+ nextarg = hold; \
+ fmt = ++cp; \
+ } else { \
+ val = GETARG (int); \
+ }
+
+
+ /* sorry, fwprintf(read_only_file, L"") returns WEOF, not 0 */
+ if (prepwrite(fp) != 0)
+ return (EOF);
+
+ convbuf = NULL;
+ fmt = (wchar_t *)fmt0;
+ argtable = NULL;
+ nextarg = 1;
+ va_copy(orgap, ap);
+ io_init(&io, fp);
+ ret = 0;
+#ifndef NO_FLOATING_POINT
+ decimal_point = get_decpt(locale);
+#endif
+
+ /*
+ * Scan the format for conversions (`%' character).
+ */
+ for (;;) {
+ for (cp = fmt; (ch = *fmt) != '\0' && ch != '%'; fmt++)
+ /* void */;
+ if ((n = fmt - cp) != 0) {
+ if ((unsigned)ret + n > INT_MAX) {
+ ret = EOF;
+ errno = EOVERFLOW;
+ goto error;
+ }
+ PRINT(cp, n);
+ ret += n;
+ }
+ if (ch == '\0')
+ goto done;
+ fmt++; /* skip over '%' */
+
+ flags = 0;
+ dprec = 0;
+ width = 0;
+ prec = -1;
+ gs.grouping = NULL;
+ sign = '\0';
+ ox[1] = '\0';
+
+rflag: ch = *fmt++;
+reswitch: switch (ch) {
+ case ' ':
+ /*-
+ * ``If the space and + flags both appear, the space
+ * flag will be ignored.''
+ * -- ANSI X3J11
+ */
+ if (!sign)
+ sign = ' ';
+ goto rflag;
+ case '#':
+ flags |= ALT;
+ goto rflag;
+ case '*':
+ /*-
+ * ``A negative field width argument is taken as a
+ * - flag followed by a positive field width.''
+ * -- ANSI X3J11
+ * They don't exclude field widths read from args.
+ */
+ GETASTER (width);
+ if (width >= 0)
+ goto rflag;
+ width = -width;
+ /* FALLTHROUGH */
+ case '-':
+ flags |= LADJUST;
+ goto rflag;
+ case '+':
+ sign = '+';
+ goto rflag;
+ case '\'':
+ flags |= GROUPING;
+ goto rflag;
+ case '.':
+ if ((ch = *fmt++) == '*') {
+ GETASTER (prec);
+ goto rflag;
+ }
+ prec = 0;
+ while (is_digit(ch)) {
+ prec = 10 * prec + to_digit(ch);
+ ch = *fmt++;
+ }
+ goto reswitch;
+ case '0':
+ /*-
+ * ``Note that 0 is taken as a flag, not as the
+ * beginning of a field width.''
+ * -- ANSI X3J11
+ */
+ flags |= ZEROPAD;
+ goto rflag;
+ case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ n = 0;
+ do {
+ n = 10 * n + to_digit(ch);
+ ch = *fmt++;
+ } while (is_digit(ch));
+ if (ch == '$') {
+ nextarg = n;
+ if (argtable == NULL) {
+ argtable = statargtable;
+ if (__find_warguments (fmt0, orgap,
+ &argtable)) {
+ ret = EOF;
+ goto error;
+ }
+ }
+ goto rflag;
+ }
+ width = n;
+ goto reswitch;
+#ifndef NO_FLOATING_POINT
+ case 'L':
+ flags |= LONGDBL;
+ goto rflag;
+#endif
+ case 'h':
+ if (flags & SHORTINT) {
+ flags &= ~SHORTINT;
+ flags |= CHARINT;
+ } else
+ flags |= SHORTINT;
+ goto rflag;
+ case 'j':
+ flags |= INTMAXT;
+ goto rflag;
+ case 'l':
+ if (flags & LONGINT) {
+ flags &= ~LONGINT;
+ flags |= LLONGINT;
+ } else
+ flags |= LONGINT;
+ goto rflag;
+ case 'q':
+ flags |= LLONGINT; /* not necessarily */
+ goto rflag;
+ case 't':
+ flags |= PTRDIFFT;
+ goto rflag;
+ case 'z':
+ flags |= SIZET;
+ goto rflag;
+ case 'C':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'c':
+ if (flags & LONGINT)
+ *(cp = buf) = (wchar_t)GETARG(wint_t);
+ else
+ *(cp = buf) = (wchar_t)btowc(GETARG(int));
+ size = 1;
+ sign = '\0';
+ break;
+ case 'D':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'd':
+ case 'i':
+ if (flags & INTMAX_SIZE) {
+ ujval = SJARG();
+ if ((intmax_t)ujval < 0) {
+ ujval = -ujval;
+ sign = '-';
+ }
+ } else {
+ ulval = SARG();
+ if ((long)ulval < 0) {
+ ulval = -ulval;
+ sign = '-';
+ }
+ }
+ base = 10;
+ goto number;
+#ifndef NO_FLOATING_POINT
+ case 'a':
+ case 'A':
+ if (ch == 'a') {
+ ox[1] = 'x';
+ xdigs = xdigs_lower;
+ expchar = 'p';
+ } else {
+ ox[1] = 'X';
+ xdigs = xdigs_upper;
+ expchar = 'P';
+ }
+ if (prec >= 0)
+ prec++;
+ if (flags & LONGDBL) {
+ fparg.ldbl = GETARG(long double);
+ dtoaresult =
+ __hldtoa(fparg.ldbl, xdigs, prec,
+ &expt, &signflag, &dtoaend);
+ } else {
+ fparg.dbl = GETARG(double);
+ dtoaresult =
+ __hdtoa(fparg.dbl, xdigs, prec,
+ &expt, &signflag, &dtoaend);
+ }
+ if (prec < 0)
+ prec = dtoaend - dtoaresult;
+ if (expt == INT_MAX)
+ ox[1] = '\0';
+ if (convbuf != NULL)
+ free(convbuf);
+ ndig = dtoaend - dtoaresult;
+ cp = convbuf = __mbsconv(dtoaresult, -1);
+ freedtoa(dtoaresult);
+ goto fp_common;
+ case 'e':
+ case 'E':
+ expchar = ch;
+ if (prec < 0) /* account for digit before decpt */
+ prec = DEFPREC + 1;
+ else
+ prec++;
+ goto fp_begin;
+ case 'f':
+ case 'F':
+ expchar = '\0';
+ goto fp_begin;
+ case 'g':
+ case 'G':
+ expchar = ch - ('g' - 'e');
+ if (prec == 0)
+ prec = 1;
+fp_begin:
+ if (prec < 0)
+ prec = DEFPREC;
+ if (convbuf != NULL)
+ free(convbuf);
+ if (flags & LONGDBL) {
+ fparg.ldbl = GETARG(long double);
+ dtoaresult =
+ __ldtoa(&fparg.ldbl, expchar ? 2 : 3, prec,
+ &expt, &signflag, &dtoaend);
+ } else {
+ fparg.dbl = GETARG(double);
+ dtoaresult =
+ dtoa(fparg.dbl, expchar ? 2 : 3, prec,
+ &expt, &signflag, &dtoaend);
+ if (expt == 9999)
+ expt = INT_MAX;
+ }
+ ndig = dtoaend - dtoaresult;
+ cp = convbuf = __mbsconv(dtoaresult, -1);
+ freedtoa(dtoaresult);
+fp_common:
+ if (signflag)
+ sign = '-';
+ if (expt == INT_MAX) { /* inf or nan */
+ if (*cp == 'N') {
+ cp = (ch >= 'a') ? L"nan" : L"NAN";
+ sign = '\0';
+ } else
+ cp = (ch >= 'a') ? L"inf" : L"INF";
+ size = 3;
+ flags &= ~ZEROPAD;
+ break;
+ }
+ flags |= FPT;
+ if (ch == 'g' || ch == 'G') {
+ if (expt > -4 && expt <= prec) {
+ /* Make %[gG] smell like %[fF] */
+ expchar = '\0';
+ if (flags & ALT)
+ prec -= expt;
+ else
+ prec = ndig - expt;
+ if (prec < 0)
+ prec = 0;
+ } else {
+ /*
+ * Make %[gG] smell like %[eE], but
+ * trim trailing zeroes if no # flag.
+ */
+ if (!(flags & ALT))
+ prec = ndig;
+ }
+ }
+ if (expchar) {
+ expsize = exponent(expstr, expt - 1, expchar);
+ size = expsize + prec;
+ if (prec > 1 || flags & ALT)
+ ++size;
+ } else {
+ /* space for digits before decimal point */
+ if (expt > 0)
+ size = expt;
+ else /* "0" */
+ size = 1;
+ /* space for decimal pt and following digits */
+ if (prec || flags & ALT)
+ size += prec + 1;
+ if ((flags & GROUPING) && expt > 0)
+ size += grouping_init(&gs, expt, locale);
+ }
+ break;
+#endif /* !NO_FLOATING_POINT */
+ case 'n':
+ /*
+ * Assignment-like behavior is specified if the
+ * value overflows or is otherwise unrepresentable.
+ * C99 says to use `signed char' for %hhn conversions.
+ */
+ if (flags & LLONGINT)
+ *GETARG(long long *) = ret;
+ else if (flags & SIZET)
+ *GETARG(ssize_t *) = (ssize_t)ret;
+ else if (flags & PTRDIFFT)
+ *GETARG(ptrdiff_t *) = ret;
+ else if (flags & INTMAXT)
+ *GETARG(intmax_t *) = ret;
+ else if (flags & LONGINT)
+ *GETARG(long *) = ret;
+ else if (flags & SHORTINT)
+ *GETARG(short *) = ret;
+ else if (flags & CHARINT)
+ *GETARG(signed char *) = ret;
+ else
+ *GETARG(int *) = ret;
+ continue; /* no output */
+ case 'O':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'o':
+ if (flags & INTMAX_SIZE)
+ ujval = UJARG();
+ else
+ ulval = UARG();
+ base = 8;
+ goto nosign;
+ case 'p':
+ /*-
+ * ``The argument shall be a pointer to void. The
+ * value of the pointer is converted to a sequence
+ * of printable characters, in an implementation-
+ * defined manner.''
+ * -- ANSI X3J11
+ */
+ ujval = (uintmax_t)(uintptr_t)GETARG(void *);
+ base = 16;
+ xdigs = xdigs_lower;
+ flags = flags | INTMAXT;
+ ox[1] = 'x';
+ goto nosign;
+ case 'S':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 's':
+ if (flags & LONGINT) {
+ if ((cp = GETARG(wchar_t *)) == NULL)
+ cp = L"(null)";
+ } else {
+ char *mbp;
+
+ if (convbuf != NULL)
+ free(convbuf);
+ if ((mbp = GETARG(char *)) == NULL)
+ cp = L"(null)";
+ else {
+ convbuf = __mbsconv(mbp, prec);
+ if (convbuf == NULL) {
+ fp->_flags |= __SERR;
+ goto error;
+ }
+ cp = convbuf;
+ }
+ }
+ size = (prec >= 0) ? wcsnlen(cp, prec) : wcslen(cp);
+ sign = '\0';
+ break;
+ case 'U':
+ flags |= LONGINT;
+ /*FALLTHROUGH*/
+ case 'u':
+ if (flags & INTMAX_SIZE)
+ ujval = UJARG();
+ else
+ ulval = UARG();
+ base = 10;
+ goto nosign;
+ case 'X':
+ xdigs = xdigs_upper;
+ goto hex;
+ case 'x':
+ xdigs = xdigs_lower;
+hex:
+ if (flags & INTMAX_SIZE)
+ ujval = UJARG();
+ else
+ ulval = UARG();
+ base = 16;
+ /* leading 0x/X only if non-zero */
+ if (flags & ALT &&
+ (flags & INTMAX_SIZE ? ujval != 0 : ulval != 0))
+ ox[1] = ch;
+
+ flags &= ~GROUPING;
+ /* unsigned conversions */
+nosign: sign = '\0';
+ /*-
+ * ``... diouXx conversions ... if a precision is
+ * specified, the 0 flag will be ignored.''
+ * -- ANSI X3J11
+ */
+number: if ((dprec = prec) >= 0)
+ flags &= ~ZEROPAD;
+
+ /*-
+ * ``The result of converting a zero value with an
+ * explicit precision of zero is no characters.''
+ * -- ANSI X3J11
+ *
+ * ``The C Standard is clear enough as is. The call
+ * printf("%#.0o", 0) should print 0.''
+ * -- Defect Report #151
+ */
+ cp = buf + BUF;
+ if (flags & INTMAX_SIZE) {
+ if (ujval != 0 || prec != 0 ||
+ (flags & ALT && base == 8))
+ cp = __ujtoa(ujval, cp, base,
+ flags & ALT, xdigs);
+ } else {
+ if (ulval != 0 || prec != 0 ||
+ (flags & ALT && base == 8))
+ cp = __ultoa(ulval, cp, base,
+ flags & ALT, xdigs);
+ }
+ size = buf + BUF - cp;
+ if (size > BUF) /* should never happen */
+ abort();
+ if ((flags & GROUPING) && size != 0)
+ size += grouping_init(&gs, size, locale);
+ break;
+ default: /* "%?" prints ?, unless ? is NUL */
+ if (ch == '\0')
+ goto done;
+ /* pretend it was %c with argument ch */
+ cp = buf;
+ *cp = ch;
+ size = 1;
+ sign = '\0';
+ break;
+ }
+
+ /*
+ * All reasonable formats wind up here. At this point, `cp'
+ * points to a string which (if not flags&LADJUST) should be
+ * padded out to `width' places. If flags&ZEROPAD, it should
+ * first be prefixed by any sign or other prefix; otherwise,
+ * it should be blank padded before the prefix is emitted.
+ * After any left-hand padding and prefixing, emit zeroes
+ * required by a decimal [diouxX] precision, then print the
+ * string proper, then emit zeroes required by any leftover
+ * floating precision; finally, if LADJUST, pad with blanks.
+ *
+ * Compute actual size, so we know how much to pad.
+ * size excludes decimal prec; realsz includes it.
+ */
+ realsz = dprec > size ? dprec : size;
+ if (sign)
+ realsz++;
+ if (ox[1])
+ realsz += 2;
+
+ prsize = width > realsz ? width : realsz;
+ if ((unsigned)ret + prsize > INT_MAX) {
+ ret = EOF;
+ errno = EOVERFLOW;
+ goto error;
+ }
+
+ /* right-adjusting blank padding */
+ if ((flags & (LADJUST|ZEROPAD)) == 0)
+ PAD(width - realsz, blanks);
+
+ /* prefix */
+ if (sign)
+ PRINT(&sign, 1);
+
+ if (ox[1]) { /* ox[1] is either x, X, or \0 */
+ ox[0] = '0';
+ PRINT(ox, 2);
+ }
+
+ /* right-adjusting zero padding */
+ if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD)
+ PAD(width - realsz, zeroes);
+
+ /* the string or number proper */
+#ifndef NO_FLOATING_POINT
+ if ((flags & FPT) == 0) {
+#endif
+ /* leading zeroes from decimal precision */
+ PAD(dprec - size, zeroes);
+ if (gs.grouping) {
+ if (grouping_print(&gs, &io, cp, buf+BUF, locale) < 0)
+ goto error;
+ } else {
+ PRINT(cp, size);
+ }
+#ifndef NO_FLOATING_POINT
+ } else { /* glue together f_p fragments */
+ if (!expchar) { /* %[fF] or sufficiently short %[gG] */
+ if (expt <= 0) {
+ PRINT(zeroes, 1);
+ if (prec || flags & ALT)
+ PRINT(&decimal_point, 1);
+ PAD(-expt, zeroes);
+ /* already handled initial 0's */
+ prec += expt;
+ } else {
+ if (gs.grouping) {
+ n = grouping_print(&gs, &io,
+ cp, convbuf + ndig, locale);
+ if (n < 0)
+ goto error;
+ cp += n;
+ } else {
+ PRINTANDPAD(cp, convbuf + ndig,
+ expt, zeroes);
+ cp += expt;
+ }
+ if (prec || flags & ALT)
+ PRINT(&decimal_point, 1);
+ }
+ PRINTANDPAD(cp, convbuf + ndig, prec, zeroes);
+ } else { /* %[eE] or sufficiently long %[gG] */
+ if (prec > 1 || flags & ALT) {
+ buf[0] = *cp++;
+ buf[1] = decimal_point;
+ PRINT(buf, 2);
+ PRINT(cp, ndig-1);
+ PAD(prec - ndig, zeroes);
+ } else /* XeYYY */
+ PRINT(cp, 1);
+ PRINT(expstr, expsize);
+ }
+ }
+#endif
+ /* left-adjusting padding (always blank) */
+ if (flags & LADJUST)
+ PAD(width - realsz, blanks);
+
+ /* finally, adjust ret */
+ ret += prsize;
+
+ FLUSH(); /* copy out the I/O vectors */
+ }
+done:
+ FLUSH();
+error:
+ va_end(orgap);
+ if (convbuf != NULL)
+ free(convbuf);
+ if (__sferror(fp))
+ ret = EOF;
+ if ((argtable != NULL) && (argtable != statargtable))
+ free (argtable);
+ return (ret);
+ /* NOTREACHED */
+}
diff --git a/lib/libc/stdio/vfwscanf.c b/lib/libc/stdio/vfwscanf.c
new file mode 100644
index 0000000..6b4d8c5
--- /dev/null
+++ b/lib/libc/stdio/vfwscanf.c
@@ -0,0 +1,983 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vfscanf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <ctype.h>
+#include <inttypes.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <stdarg.h>
+#include <string.h>
+#include <wchar.h>
+#include <wctype.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+#include "local.h"
+#include "xlocale_private.h"
+
+#define BUF 513 /* Maximum length of numeric string. */
+
+/*
+ * Flags used during conversion.
+ */
+#define LONG 0x01 /* l: long or double */
+#define LONGDBL 0x02 /* L: long double */
+#define SHORT 0x04 /* h: short */
+#define SUPPRESS 0x08 /* *: suppress assignment */
+#define POINTER 0x10 /* p: void * (as hex) */
+#define NOSKIP 0x20 /* [ or c: do not skip blanks */
+#define LONGLONG 0x400 /* ll: long long (+ deprecated q: quad) */
+#define INTMAXT 0x800 /* j: intmax_t */
+#define PTRDIFFT 0x1000 /* t: ptrdiff_t */
+#define SIZET 0x2000 /* z: size_t */
+#define SHORTSHORT 0x4000 /* hh: char */
+#define UNSIGNED 0x8000 /* %[oupxX] conversions */
+
+/*
+ * The following are used in integral conversions only:
+ * SIGNOK, NDIGITS, PFXOK, and NZDIGITS
+ */
+#define SIGNOK 0x40 /* +/- is (still) legal */
+#define NDIGITS 0x80 /* no digits detected */
+#define PFXOK 0x100 /* 0x prefix is (still) legal */
+#define NZDIGITS 0x200 /* no zero digits detected */
+#define HAVESIGN 0x10000 /* sign detected */
+
+/*
+ * Conversion types.
+ */
+#define CT_CHAR 0 /* %c conversion */
+#define CT_CCL 1 /* %[...] conversion */
+#define CT_STRING 2 /* %s conversion */
+#define CT_INT 3 /* %[dioupxX] conversion */
+#define CT_FLOAT 4 /* %[efgEFG] conversion */
+
+#ifndef NO_FLOATING_POINT
+static int parsefloat(FILE *, wchar_t *, wchar_t *, locale_t);
+#endif
+
+struct ccl {
+ const wchar_t *start; /* character class start */
+ const wchar_t *end; /* character class end */
+ int compl; /* ccl is complemented? */
+};
+
+static __inline int
+inccl(const struct ccl *ccl, wint_t wi)
+{
+
+ if (ccl->compl) {
+ return (wmemchr(ccl->start, wi, ccl->end - ccl->start)
+ == NULL);
+ } else {
+ return (wmemchr(ccl->start, wi, ccl->end - ccl->start) != NULL);
+ }
+}
+
+/*
+ * Conversion functions are passed a pointer to this object instead of
+ * a real parameter to indicate that the assignment-suppression (*)
+ * flag was specified. We could use a NULL pointer to indicate this,
+ * but that would mask bugs in applications that call scanf() with a
+ * NULL pointer.
+ */
+static const int suppress;
+#define SUPPRESS_PTR ((void *)&suppress)
+
+static const mbstate_t initial_mbs;
+
+/*
+ * The following conversion functions return the number of characters consumed,
+ * or -1 on input failure. Character class conversion returns 0 on match
+ * failure.
+ */
+
+static __inline int
+convert_char(FILE *fp, char * __restrict mbp, int width, locale_t locale)
+{
+ mbstate_t mbs;
+ size_t nconv;
+ wint_t wi;
+ int n;
+ char mbbuf[MB_LEN_MAX];
+
+ n = 0;
+ mbs = initial_mbs;
+ while (width != 0 && (wi = __fgetwc(fp, locale)) != WEOF) {
+ if (width >= MB_CUR_MAX && mbp != SUPPRESS_PTR) {
+ nconv = wcrtomb(mbp, wi, &mbs);
+ if (nconv == (size_t)-1)
+ return (-1);
+ } else {
+ nconv = wcrtomb(mbbuf, wi, &mbs);
+ if (nconv == (size_t)-1)
+ return (-1);
+ if (nconv > width) {
+ __ungetwc(wi, fp, locale);
+ break;
+ }
+ if (mbp != SUPPRESS_PTR)
+ memcpy(mbp, mbbuf, nconv);
+ }
+ if (mbp != SUPPRESS_PTR)
+ mbp += nconv;
+ width -= nconv;
+ n++;
+ }
+ if (n == 0)
+ return (-1);
+ return (n);
+}
+
+static __inline int
+convert_wchar(FILE *fp, wchar_t *wcp, int width, locale_t locale)
+{
+ wint_t wi;
+ int n;
+
+ n = 0;
+ while (width-- != 0 && (wi = __fgetwc(fp, locale)) != WEOF) {
+ if (wcp != SUPPRESS_PTR)
+ *wcp++ = (wchar_t)wi;
+ n++;
+ }
+ if (n == 0)
+ return (-1);
+ return (n);
+}
+
+static __inline int
+convert_ccl(FILE *fp, char * __restrict mbp, int width, const struct ccl *ccl,
+ locale_t locale)
+{
+ mbstate_t mbs;
+ size_t nconv;
+ wint_t wi;
+ int n;
+ char mbbuf[MB_LEN_MAX];
+
+ n = 0;
+ mbs = initial_mbs;
+ while ((wi = __fgetwc(fp, locale)) != WEOF &&
+ width != 0 && inccl(ccl, wi)) {
+ if (width >= MB_CUR_MAX && mbp != SUPPRESS_PTR) {
+ nconv = wcrtomb(mbp, wi, &mbs);
+ if (nconv == (size_t)-1)
+ return (-1);
+ } else {
+ nconv = wcrtomb(mbbuf, wi, &mbs);
+ if (nconv == (size_t)-1)
+ return (-1);
+ if (nconv > width)
+ break;
+ if (mbp != SUPPRESS_PTR)
+ memcpy(mbp, mbbuf, nconv);
+ }
+ if (mbp != SUPPRESS_PTR)
+ mbp += nconv;
+ width -= nconv;
+ n++;
+ }
+ if (wi != WEOF)
+ __ungetwc(wi, fp, locale);
+ if (mbp != SUPPRESS_PTR)
+ *mbp = 0;
+ return (n);
+}
+
+static __inline int
+convert_wccl(FILE *fp, wchar_t *wcp, int width, const struct ccl *ccl,
+ locale_t locale)
+{
+ wchar_t *wcp0;
+ wint_t wi;
+ int n;
+
+ if (wcp == SUPPRESS_PTR) {
+ n = 0;
+ while ((wi = __fgetwc(fp, locale)) != WEOF &&
+ width-- != 0 && inccl(ccl, wi))
+ n++;
+ if (wi != WEOF)
+ __ungetwc(wi, fp, locale);
+ } else {
+ wcp0 = wcp;
+ while ((wi = __fgetwc(fp, locale)) != WEOF &&
+ width-- != 0 && inccl(ccl, wi))
+ *wcp++ = (wchar_t)wi;
+ if (wi != WEOF)
+ __ungetwc(wi, fp, locale);
+ n = wcp - wcp0;
+ if (n == 0)
+ return (0);
+ *wcp = 0;
+ }
+ return (n);
+}
+
+static __inline int
+convert_string(FILE *fp, char * __restrict mbp, int width, locale_t locale)
+{
+ mbstate_t mbs;
+ size_t nconv;
+ wint_t wi;
+ int nread;
+ char mbbuf[MB_LEN_MAX];
+
+ mbs = initial_mbs;
+ nread = 0;
+ while ((wi = __fgetwc(fp, locale)) != WEOF && width != 0 &&
+ !iswspace(wi)) {
+ if (width >= MB_CUR_MAX && mbp != SUPPRESS_PTR) {
+ nconv = wcrtomb(mbp, wi, &mbs);
+ if (nconv == (size_t)-1)
+ return (-1);
+ } else {
+ nconv = wcrtomb(mbbuf, wi, &mbs);
+ if (nconv == (size_t)-1)
+ return (-1);
+ if (nconv > width)
+ break;
+ if (mbp != SUPPRESS_PTR)
+ memcpy(mbp, mbbuf, nconv);
+ }
+ if (mbp != SUPPRESS_PTR)
+ mbp += nconv;
+ width -= nconv;
+ nread++;
+ }
+ if (wi != WEOF)
+ __ungetwc(wi, fp, locale);
+ if (mbp != SUPPRESS_PTR)
+ *mbp = 0;
+ return (nread);
+}
+
+static __inline int
+convert_wstring(FILE *fp, wchar_t *wcp, int width, locale_t locale)
+{
+ wchar_t *wcp0;
+ wint_t wi;
+ int nread;
+
+ nread = 0;
+ if (wcp == SUPPRESS_PTR) {
+ while ((wi = __fgetwc(fp, locale)) != WEOF &&
+ width-- != 0 && !iswspace(wi))
+ nread++;
+ if (wi != WEOF)
+ __ungetwc(wi, fp, locale);
+ } else {
+ wcp0 = wcp;
+ while ((wi = __fgetwc(fp, locale)) != WEOF &&
+ width-- != 0 && !iswspace(wi)) {
+ *wcp++ = (wchar_t)wi;
+ nread++;
+ }
+ if (wi != WEOF)
+ __ungetwc(wi, fp, locale);
+ *wcp = '\0';
+ }
+ return (nread);
+}
+
+/*
+ * Read an integer, storing it in buf. The only relevant bit in the
+ * flags argument is PFXOK.
+ *
+ * Return 0 on a match failure, and the number of characters read
+ * otherwise.
+ */
+static __inline int
+parseint(FILE *fp, wchar_t *buf, int width, int base, int flags,
+ locale_t locale)
+{
+ /* `basefix' is used to avoid `if' tests */
+ static const short basefix[17] =
+ { 10, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16 };
+ wchar_t *wcp;
+ int c;
+
+ flags |= SIGNOK | NDIGITS | NZDIGITS;
+ for (wcp = buf; width; width--) {
+ c = __fgetwc(fp, locale);
+ /*
+ * Switch on the character; `goto ok' if we accept it
+ * as a part of number.
+ */
+ switch (c) {
+
+ /*
+ * The digit 0 is always legal, but is special. For
+ * %i conversions, if no digits (zero or nonzero) have
+ * been scanned (only signs), we will have base==0.
+ * In that case, we should set it to 8 and enable 0x
+ * prefixing. Also, if we have not scanned zero
+ * digits before this, do not turn off prefixing
+ * (someone else will turn it off if we have scanned
+ * any nonzero digits).
+ */
+ case '0':
+ if (base == 0) {
+ base = 8;
+ flags |= PFXOK;
+ }
+ if (flags & NZDIGITS)
+ flags &= ~(SIGNOK|NZDIGITS|NDIGITS);
+ else
+ flags &= ~(SIGNOK|PFXOK|NDIGITS);
+ goto ok;
+
+ /* 1 through 7 always legal */
+ case '1': case '2': case '3':
+ case '4': case '5': case '6': case '7':
+ base = basefix[base];
+ flags &= ~(SIGNOK | PFXOK | NDIGITS);
+ goto ok;
+
+ /* digits 8 and 9 ok iff decimal or hex */
+ case '8': case '9':
+ base = basefix[base];
+ if (base <= 8)
+ break; /* not legal here */
+ flags &= ~(SIGNOK | PFXOK | NDIGITS);
+ goto ok;
+
+ /* letters ok iff hex */
+ case 'A': case 'B': case 'C':
+ case 'D': case 'E': case 'F':
+ case 'a': case 'b': case 'c':
+ case 'd': case 'e': case 'f':
+ /* no need to fix base here */
+ if (base <= 10)
+ break; /* not legal here */
+ flags &= ~(SIGNOK | PFXOK | NDIGITS);
+ goto ok;
+
+ /* sign ok only as first character */
+ case '+': case '-':
+ if (flags & SIGNOK) {
+ flags &= ~SIGNOK;
+ flags |= HAVESIGN;
+ goto ok;
+ }
+ break;
+
+ /*
+ * x ok iff flag still set & 2nd char (or 3rd char if
+ * we have a sign).
+ */
+ case 'x': case 'X':
+ if (flags & PFXOK && wcp ==
+ buf + 1 + !!(flags & HAVESIGN)) {
+ base = 16; /* if %i */
+ flags &= ~PFXOK;
+ goto ok;
+ }
+ break;
+ }
+
+ /*
+ * If we got here, c is not a legal character for a
+ * number. Stop accumulating digits.
+ */
+ if (c != WEOF)
+ __ungetwc(c, fp, locale);
+ break;
+ ok:
+ /*
+ * c is legal: store it and look at the next.
+ */
+ *wcp++ = (wchar_t)c;
+ }
+ /*
+ * If we had only a sign, it is no good; push back the sign.
+ * If the number ends in `x', it was [sign] '0' 'x', so push
+ * back the x and treat it as [sign] '0'.
+ */
+ if (flags & NDIGITS) {
+ if (wcp > buf)
+ __ungetwc(*--wcp, fp, locale);
+ return (0);
+ }
+ c = wcp[-1];
+ if (c == 'x' || c == 'X') {
+ --wcp;
+ __ungetwc(c, fp, locale);
+ }
+ return (wcp - buf);
+}
+
+/*
+ * MT-safe version.
+ */
+int
+vfwscanf_l(FILE * __restrict fp, locale_t locale,
+ const wchar_t * __restrict fmt, va_list ap)
+{
+ int ret;
+ FIX_LOCALE(locale);
+
+ FLOCKFILE(fp);
+ ORIENT(fp, 1);
+ ret = __vfwscanf(fp, locale, fmt, ap);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
+int
+vfwscanf(FILE * __restrict fp, const wchar_t * __restrict fmt, va_list ap)
+{
+ return vfwscanf_l(fp, __get_locale(), fmt, ap);
+}
+
+/*
+ * Non-MT-safe version.
+ */
+int
+__vfwscanf(FILE * __restrict fp, locale_t locale,
+ const wchar_t * __restrict fmt, va_list ap)
+{
+#define GETARG(type) ((flags & SUPPRESS) ? SUPPRESS_PTR : va_arg(ap, type))
+ wint_t c; /* character from format, or conversion */
+ size_t width; /* field width, or 0 */
+ int flags; /* flags as defined above */
+ int nassigned; /* number of fields assigned */
+ int nconversions; /* number of conversions */
+ int nr; /* characters read by the current conversion */
+ int nread; /* number of characters consumed from fp */
+ int base; /* base argument to conversion function */
+ struct ccl ccl; /* character class info */
+ wchar_t buf[BUF]; /* buffer for numeric conversions */
+ wint_t wi; /* handy wint_t */
+
+ nassigned = 0;
+ nconversions = 0;
+ nread = 0;
+ ccl.start = ccl.end = NULL;
+ for (;;) {
+ c = *fmt++;
+ if (c == 0)
+ return (nassigned);
+ if (iswspace(c)) {
+ while ((c = __fgetwc(fp, locale)) != WEOF &&
+ iswspace_l(c, locale))
+ nread++;
+ if (c != WEOF)
+ __ungetwc(c, fp, locale);
+ continue;
+ }
+ if (c != '%')
+ goto literal;
+ width = 0;
+ flags = 0;
+ /*
+ * switch on the format. continue if done;
+ * break once format type is derived.
+ */
+again: c = *fmt++;
+ switch (c) {
+ case '%':
+literal:
+ if ((wi = __fgetwc(fp, locale)) == WEOF)
+ goto input_failure;
+ if (wi != c) {
+ __ungetwc(wi, fp, locale);
+ goto input_failure;
+ }
+ nread++;
+ continue;
+
+ case '*':
+ flags |= SUPPRESS;
+ goto again;
+ case 'j':
+ flags |= INTMAXT;
+ goto again;
+ case 'l':
+ if (flags & LONG) {
+ flags &= ~LONG;
+ flags |= LONGLONG;
+ } else
+ flags |= LONG;
+ goto again;
+ case 'q':
+ flags |= LONGLONG; /* not quite */
+ goto again;
+ case 't':
+ flags |= PTRDIFFT;
+ goto again;
+ case 'z':
+ flags |= SIZET;
+ goto again;
+ case 'L':
+ flags |= LONGDBL;
+ goto again;
+ case 'h':
+ if (flags & SHORT) {
+ flags &= ~SHORT;
+ flags |= SHORTSHORT;
+ } else
+ flags |= SHORT;
+ goto again;
+
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ width = width * 10 + c - '0';
+ goto again;
+
+ /*
+ * Conversions.
+ */
+ case 'd':
+ c = CT_INT;
+ base = 10;
+ break;
+
+ case 'i':
+ c = CT_INT;
+ base = 0;
+ break;
+
+ case 'o':
+ c = CT_INT;
+ flags |= UNSIGNED;
+ base = 8;
+ break;
+
+ case 'u':
+ c = CT_INT;
+ flags |= UNSIGNED;
+ base = 10;
+ break;
+
+ case 'X':
+ case 'x':
+ flags |= PFXOK; /* enable 0x prefixing */
+ c = CT_INT;
+ flags |= UNSIGNED;
+ base = 16;
+ break;
+
+#ifndef NO_FLOATING_POINT
+ case 'A': case 'E': case 'F': case 'G':
+ case 'a': case 'e': case 'f': case 'g':
+ c = CT_FLOAT;
+ break;
+#endif
+
+ case 'S':
+ flags |= LONG;
+ /* FALLTHROUGH */
+ case 's':
+ c = CT_STRING;
+ break;
+
+ case '[':
+ ccl.start = fmt;
+ if (*fmt == '^') {
+ ccl.compl = 1;
+ fmt++;
+ } else
+ ccl.compl = 0;
+ if (*fmt == ']')
+ fmt++;
+ while (*fmt != '\0' && *fmt != ']')
+ fmt++;
+ ccl.end = fmt;
+ fmt++;
+ flags |= NOSKIP;
+ c = CT_CCL;
+ break;
+
+ case 'C':
+ flags |= LONG;
+ /* FALLTHROUGH */
+ case 'c':
+ flags |= NOSKIP;
+ c = CT_CHAR;
+ break;
+
+ case 'p': /* pointer format is like hex */
+ flags |= POINTER | PFXOK;
+ c = CT_INT; /* assumes sizeof(uintmax_t) */
+ flags |= UNSIGNED; /* >= sizeof(uintptr_t) */
+ base = 16;
+ break;
+
+ case 'n':
+ if (flags & SUPPRESS) /* ??? */
+ continue;
+ if (flags & SHORTSHORT)
+ *va_arg(ap, char *) = nread;
+ else if (flags & SHORT)
+ *va_arg(ap, short *) = nread;
+ else if (flags & LONG)
+ *va_arg(ap, long *) = nread;
+ else if (flags & LONGLONG)
+ *va_arg(ap, long long *) = nread;
+ else if (flags & INTMAXT)
+ *va_arg(ap, intmax_t *) = nread;
+ else if (flags & SIZET)
+ *va_arg(ap, size_t *) = nread;
+ else if (flags & PTRDIFFT)
+ *va_arg(ap, ptrdiff_t *) = nread;
+ else
+ *va_arg(ap, int *) = nread;
+ continue;
+
+ default:
+ goto match_failure;
+
+ /*
+ * Disgusting backwards compatibility hack. XXX
+ */
+ case '\0': /* compat */
+ return (EOF);
+ }
+
+ /*
+ * Consume leading white space, except for formats
+ * that suppress this.
+ */
+ if ((flags & NOSKIP) == 0) {
+ while ((wi = __fgetwc(fp, locale)) != WEOF && iswspace(wi))
+ nread++;
+ if (wi == WEOF)
+ goto input_failure;
+ __ungetwc(wi, fp, locale);
+ }
+
+ /*
+ * Do the conversion.
+ */
+ switch (c) {
+
+ case CT_CHAR:
+ /* scan arbitrary characters (sets NOSKIP) */
+ if (width == 0)
+ width = 1;
+ if (flags & LONG) {
+ nr = convert_wchar(fp, GETARG(wchar_t *), width,
+ locale);
+ } else {
+ nr = convert_char(fp, GETARG(char *), width,
+ locale);
+ }
+ if (nr < 0)
+ goto input_failure;
+ break;
+
+ case CT_CCL:
+ /* scan a (nonempty) character class (sets NOSKIP) */
+ if (width == 0)
+ width = (size_t)~0; /* `infinity' */
+ /* take only those things in the class */
+ if (flags & LONG) {
+ nr = convert_wccl(fp, GETARG(wchar_t *), width,
+ &ccl, locale);
+ } else {
+ nr = convert_ccl(fp, GETARG(char *), width,
+ &ccl, locale);
+ }
+ if (nr <= 0) {
+ if (nr < 0)
+ goto input_failure;
+ else /* nr == 0 */
+ goto match_failure;
+ }
+ break;
+
+ case CT_STRING:
+ /* like CCL, but zero-length string OK, & no NOSKIP */
+ if (width == 0)
+ width = (size_t)~0;
+ if (flags & LONG) {
+ nr = convert_wstring(fp, GETARG(wchar_t *),
+ width, locale);
+ } else {
+ nr = convert_string(fp, GETARG(char *), width,
+ locale);
+ }
+ if (nr < 0)
+ goto input_failure;
+ break;
+
+ case CT_INT:
+ /* scan an integer as if by the conversion function */
+ if (width == 0 || width > sizeof(buf) /
+ sizeof(*buf) - 1)
+ width = sizeof(buf) / sizeof(*buf) - 1;
+
+ nr = parseint(fp, buf, width, base, flags, locale);
+ if (nr == 0)
+ goto match_failure;
+ if ((flags & SUPPRESS) == 0) {
+ uintmax_t res;
+
+ buf[nr] = L'\0';
+ if ((flags & UNSIGNED) == 0)
+ res = wcstoimax(buf, NULL, base);
+ else
+ res = wcstoumax(buf, NULL, base);
+ if (flags & POINTER)
+ *va_arg(ap, void **) =
+ (void *)(uintptr_t)res;
+ else if (flags & SHORTSHORT)
+ *va_arg(ap, char *) = res;
+ else if (flags & SHORT)
+ *va_arg(ap, short *) = res;
+ else if (flags & LONG)
+ *va_arg(ap, long *) = res;
+ else if (flags & LONGLONG)
+ *va_arg(ap, long long *) = res;
+ else if (flags & INTMAXT)
+ *va_arg(ap, intmax_t *) = res;
+ else if (flags & PTRDIFFT)
+ *va_arg(ap, ptrdiff_t *) = res;
+ else if (flags & SIZET)
+ *va_arg(ap, size_t *) = res;
+ else
+ *va_arg(ap, int *) = res;
+ }
+ break;
+
+#ifndef NO_FLOATING_POINT
+ case CT_FLOAT:
+ /* scan a floating point number as if by strtod */
+ if (width == 0 || width > sizeof(buf) /
+ sizeof(*buf) - 1)
+ width = sizeof(buf) / sizeof(*buf) - 1;
+ nr = parsefloat(fp, buf, buf + width, locale);
+ if (nr == 0)
+ goto match_failure;
+ if ((flags & SUPPRESS) == 0) {
+ if (flags & LONGDBL) {
+ long double res = wcstold(buf, NULL);
+ *va_arg(ap, long double *) = res;
+ } else if (flags & LONG) {
+ double res = wcstod(buf, NULL);
+ *va_arg(ap, double *) = res;
+ } else {
+ float res = wcstof(buf, NULL);
+ *va_arg(ap, float *) = res;
+ }
+ }
+ break;
+#endif /* !NO_FLOATING_POINT */
+ }
+ if (!(flags & SUPPRESS))
+ nassigned++;
+ nread += nr;
+ nconversions++;
+ }
+input_failure:
+ return (nconversions != 0 ? nassigned : EOF);
+match_failure:
+ return (nassigned);
+}
+
+#ifndef NO_FLOATING_POINT
+static int
+parsefloat(FILE *fp, wchar_t *buf, wchar_t *end, locale_t locale)
+{
+ mbstate_t mbs;
+ size_t nconv;
+ wchar_t *commit, *p;
+ int infnanpos = 0;
+ enum {
+ S_START, S_GOTSIGN, S_INF, S_NAN, S_DONE, S_MAYBEHEX,
+ S_DIGITS, S_FRAC, S_EXP, S_EXPDIGITS
+ } state = S_START;
+ wchar_t c;
+ wchar_t decpt;
+ _Bool gotmantdig = 0, ishex = 0;
+
+ mbs = initial_mbs;
+ nconv = mbrtowc(&decpt, localeconv()->decimal_point, MB_CUR_MAX, &mbs);
+ if (nconv == (size_t)-1 || nconv == (size_t)-2)
+ decpt = '.'; /* failsafe */
+
+ /*
+ * We set commit = p whenever the string we have read so far
+ * constitutes a valid representation of a floating point
+ * number by itself. At some point, the parse will complete
+ * or fail, and we will ungetc() back to the last commit point.
+ * To ensure that the file offset gets updated properly, it is
+ * always necessary to read at least one character that doesn't
+ * match; thus, we can't short-circuit "infinity" or "nan(...)".
+ */
+ commit = buf - 1;
+ c = WEOF;
+ for (p = buf; p < end; ) {
+ if ((c = __fgetwc(fp, locale)) == WEOF)
+ break;
+reswitch:
+ switch (state) {
+ case S_START:
+ state = S_GOTSIGN;
+ if (c == '-' || c == '+')
+ break;
+ else
+ goto reswitch;
+ case S_GOTSIGN:
+ switch (c) {
+ case '0':
+ state = S_MAYBEHEX;
+ commit = p;
+ break;
+ case 'I':
+ case 'i':
+ state = S_INF;
+ break;
+ case 'N':
+ case 'n':
+ state = S_NAN;
+ break;
+ default:
+ state = S_DIGITS;
+ goto reswitch;
+ }
+ break;
+ case S_INF:
+ if (infnanpos > 6 ||
+ (c != "nfinity"[infnanpos] &&
+ c != "NFINITY"[infnanpos]))
+ goto parsedone;
+ if (infnanpos == 1 || infnanpos == 6)
+ commit = p; /* inf or infinity */
+ infnanpos++;
+ break;
+ case S_NAN:
+ switch (infnanpos) {
+ case 0:
+ if (c != 'A' && c != 'a')
+ goto parsedone;
+ break;
+ case 1:
+ if (c != 'N' && c != 'n')
+ goto parsedone;
+ else
+ commit = p;
+ break;
+ case 2:
+ if (c != '(')
+ goto parsedone;
+ break;
+ default:
+ if (c == ')') {
+ commit = p;
+ state = S_DONE;
+ } else if (!iswalnum(c) && c != '_')
+ goto parsedone;
+ break;
+ }
+ infnanpos++;
+ break;
+ case S_DONE:
+ goto parsedone;
+ case S_MAYBEHEX:
+ state = S_DIGITS;
+ if (c == 'X' || c == 'x') {
+ ishex = 1;
+ break;
+ } else { /* we saw a '0', but no 'x' */
+ gotmantdig = 1;
+ goto reswitch;
+ }
+ case S_DIGITS:
+ if ((ishex && iswxdigit(c)) || iswdigit(c))
+ gotmantdig = 1;
+ else {
+ state = S_FRAC;
+ if (c != decpt)
+ goto reswitch;
+ }
+ if (gotmantdig)
+ commit = p;
+ break;
+ case S_FRAC:
+ if (((c == 'E' || c == 'e') && !ishex) ||
+ ((c == 'P' || c == 'p') && ishex)) {
+ if (!gotmantdig)
+ goto parsedone;
+ else
+ state = S_EXP;
+ } else if ((ishex && iswxdigit(c)) || iswdigit(c)) {
+ commit = p;
+ gotmantdig = 1;
+ } else
+ goto parsedone;
+ break;
+ case S_EXP:
+ state = S_EXPDIGITS;
+ if (c == '-' || c == '+')
+ break;
+ else
+ goto reswitch;
+ case S_EXPDIGITS:
+ if (iswdigit(c))
+ commit = p;
+ else
+ goto parsedone;
+ break;
+ default:
+ abort();
+ }
+ *p++ = c;
+ c = WEOF;
+ }
+
+parsedone:
+ if (c != WEOF)
+ __ungetwc(c, fp, locale);
+ while (commit < --p)
+ __ungetwc(*p, fp, locale);
+ *++commit = '\0';
+ return (commit - buf);
+}
+#endif
diff --git a/lib/libc/stdio/vprintf.c b/lib/libc/stdio/vprintf.c
new file mode 100644
index 0000000..c15ef4d
--- /dev/null
+++ b/lib/libc/stdio/vprintf.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vprintf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <xlocale.h>
+
+int
+vprintf(const char * __restrict fmt, __va_list ap)
+{
+ return (vfprintf(stdout, fmt, ap));
+}
+int
+vprintf_l(locale_t locale, const char * __restrict fmt, __va_list ap)
+{
+ return (vfprintf_l(stdout, locale, fmt, ap));
+}
diff --git a/lib/libc/stdio/vscanf.c b/lib/libc/stdio/vscanf.c
new file mode 100644
index 0000000..d56bb3b
--- /dev/null
+++ b/lib/libc/stdio/vscanf.c
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Donn Seeley at UUNET Technologies, Inc.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vscanf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "local.h"
+#include "xlocale_private.h"
+
+int
+vscanf_l(locale, fmt, ap)
+ locale_t locale;
+ const char * __restrict fmt;
+ __va_list ap;
+{
+ int retval;
+ FIX_LOCALE(locale);
+
+ FLOCKFILE(stdin);
+ retval = __svfscanf(stdin, locale, fmt, ap);
+ FUNLOCKFILE(stdin);
+ return (retval);
+}
+int
+vscanf(fmt, ap)
+ const char * __restrict fmt;
+ __va_list ap;
+{
+ return vscanf_l(__get_locale(), fmt, ap);
+}
diff --git a/lib/libc/stdio/vsnprintf.c b/lib/libc/stdio/vsnprintf.c
new file mode 100644
index 0000000..82959d1
--- /dev/null
+++ b/lib/libc/stdio/vsnprintf.c
@@ -0,0 +1,88 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vsnprintf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include "local.h"
+#include "xlocale_private.h"
+
+int
+vsnprintf_l(char * __restrict str, size_t n, locale_t locale,
+ const char * __restrict fmt, __va_list ap)
+{
+ size_t on;
+ int ret;
+ char dummy[2];
+ FILE f = FAKE_FILE;
+ FIX_LOCALE(locale);
+
+ on = n;
+ if (n != 0)
+ n--;
+ if (n > INT_MAX) {
+ errno = EOVERFLOW;
+ *str = '\0';
+ return (EOF);
+ }
+ /* Stdio internals do not deal correctly with zero length buffer */
+ if (n == 0) {
+ if (on > 0)
+ *str = '\0';
+ str = dummy;
+ n = 1;
+ }
+ f._flags = __SWR | __SSTR;
+ f._bf._base = f._p = (unsigned char *)str;
+ f._bf._size = f._w = n;
+ ret = __vfprintf(&f, locale, fmt, ap);
+ if (on > 0)
+ *f._p = '\0';
+ return (ret);
+}
+int
+vsnprintf(char * __restrict str, size_t n, const char * __restrict fmt,
+ __va_list ap)
+{
+ return vsnprintf_l(str, n, __get_locale(), fmt, ap);
+}
diff --git a/lib/libc/stdio/vsprintf.c b/lib/libc/stdio/vsprintf.c
new file mode 100644
index 0000000..04f2df3
--- /dev/null
+++ b/lib/libc/stdio/vsprintf.c
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vsprintf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <limits.h>
+#include "local.h"
+#include "xlocale_private.h"
+
+int
+vsprintf_l(char * __restrict str, locale_t locale,
+ const char * __restrict fmt, __va_list ap)
+{
+ int ret;
+ FILE f = FAKE_FILE;
+ FIX_LOCALE(locale);
+
+ f._flags = __SWR | __SSTR;
+ f._bf._base = f._p = (unsigned char *)str;
+ f._bf._size = f._w = INT_MAX;
+ ret = __vfprintf(&f, locale, fmt, ap);
+ *f._p = 0;
+ return (ret);
+}
+int
+vsprintf(char * __restrict str, const char * __restrict fmt, __va_list ap)
+{
+ return vsprintf_l(str, __get_locale(), fmt, ap);
+}
diff --git a/lib/libc/stdio/vsscanf.c b/lib/libc/stdio/vsscanf.c
new file mode 100644
index 0000000..5668ab5
--- /dev/null
+++ b/lib/libc/stdio/vsscanf.c
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Donn Seeley at UUNET Technologies, Inc.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vsscanf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include <string.h>
+#include "local.h"
+#include "xlocale_private.h"
+
+static int
+eofread(void *, char *, int);
+
+/* ARGSUSED */
+static int
+eofread(void *cookie, char *buf, int len)
+{
+
+ return (0);
+}
+
+int
+vsscanf_l(const char * __restrict str, locale_t locale,
+ const char * __restrict fmt, __va_list ap)
+{
+ FILE f = FAKE_FILE;
+ FIX_LOCALE(locale);
+
+ f._flags = __SRD;
+ f._bf._base = f._p = (unsigned char *)str;
+ f._bf._size = f._r = strlen(str);
+ f._read = eofread;
+ return (__svfscanf(&f, locale, fmt, ap));
+}
+int
+vsscanf(const char * __restrict str, const char * __restrict fmt,
+ __va_list ap)
+{
+ return vsscanf_l(str, __get_locale(), fmt, ap);
+}
diff --git a/lib/libc/stdio/vswprintf.c b/lib/libc/stdio/vswprintf.c
new file mode 100644
index 0000000..2585888
--- /dev/null
+++ b/lib/libc/stdio/vswprintf.c
@@ -0,0 +1,114 @@
+/* $OpenBSD: vasprintf.c,v 1.4 1998/06/21 22:13:47 millert Exp $ */
+
+/*
+ * Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("FreeBSD: src/lib/libc/stdio/vasprintf.c,v 1.16 2002/08/21 16:19:57 mike Exp ");
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include "local.h"
+#include "xlocale_private.h"
+
+int
+vswprintf_l(wchar_t * __restrict s, size_t n, locale_t locale,
+ const wchar_t * __restrict fmt, __va_list ap)
+{
+ static const mbstate_t initial;
+ mbstate_t mbs;
+ FILE f = FAKE_FILE;
+ char *mbp;
+ int ret, sverrno;
+ size_t nwc;
+ FIX_LOCALE(locale);
+
+ if (n == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+ if (n - 1 > INT_MAX) {
+ errno = EOVERFLOW;
+ *s = L'\0';
+ return (-1);
+ }
+
+ f._flags = __SWR | __SSTR | __SALC;
+ f._bf._base = f._p = (unsigned char *)malloc(128);
+ if (f._bf._base == NULL) {
+ errno = ENOMEM;
+ *s = L'\0';
+ return (-1);
+ }
+ f._bf._size = f._w = 127; /* Leave room for the NUL */
+ ret = __vfwprintf(&f, locale, fmt, ap);
+ if (ret < 0) {
+ sverrno = errno;
+ free(f._bf._base);
+ errno = sverrno;
+ *s = L'\0';
+ return (-1);
+ }
+ *f._p = '\0';
+ mbp = f._bf._base;
+ /*
+ * XXX Undo the conversion from wide characters to multibyte that
+ * fputwc() did in __vfwprintf().
+ */
+ mbs = initial;
+ nwc = mbsrtowcs_l(s, (const char **)&mbp, n, &mbs, locale);
+ free(f._bf._base);
+ if (nwc == (size_t)-1) {
+ errno = EILSEQ;
+ *s = L'\0';
+ return (-1);
+ }
+ if (nwc == n) {
+ s[n - 1] = L'\0';
+ errno = EOVERFLOW;
+ return (-1);
+ }
+
+ return (ret);
+}
+int
+vswprintf(wchar_t * __restrict s, size_t n, const wchar_t * __restrict fmt,
+ __va_list ap)
+{
+ return vswprintf_l(s, n, __get_locale(), fmt, ap);
+}
diff --git a/lib/libc/stdio/vswscanf.c b/lib/libc/stdio/vswscanf.c
new file mode 100644
index 0000000..f646e85
--- /dev/null
+++ b/lib/libc/stdio/vswscanf.c
@@ -0,0 +1,104 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Donn Seeley at UUNET Technologies, Inc.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)vsscanf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+__FBSDID("FreeBSD: src/lib/libc/stdio/vsscanf.c,v 1.11 2002/08/21 16:19:57 mike Exp ");
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "local.h"
+#include "xlocale_private.h"
+
+static int eofread(void *, char *, int);
+
+static int
+eofread(void *cookie, char *buf, int len)
+{
+
+ return (0);
+}
+
+int
+vswscanf_l(const wchar_t * __restrict str, locale_t locale,
+ const wchar_t * __restrict fmt, va_list ap)
+{
+ static const mbstate_t initial;
+ mbstate_t mbs;
+ FILE f = FAKE_FILE;
+ char *mbstr;
+ size_t mlen;
+ int r;
+ const wchar_t *strp;
+ FIX_LOCALE(locale);
+
+ /*
+ * XXX Convert the wide character string to multibyte, which
+ * __vfwscanf() will convert back to wide characters.
+ */
+ if ((mbstr = malloc(wcslen(str) * MB_CUR_MAX + 1)) == NULL)
+ return (EOF);
+ mbs = initial;
+ strp = str;
+ if ((mlen = wcsrtombs_l(mbstr, &strp, SIZE_T_MAX, &mbs, locale)) == (size_t)-1) {
+ free(mbstr);
+ return (EOF);
+ }
+ f._flags = __SRD;
+ f._bf._base = f._p = (unsigned char *)mbstr;
+ f._bf._size = f._r = mlen;
+ f._read = eofread;
+ r = __vfwscanf(&f, locale, fmt, ap);
+ free(mbstr);
+
+ return (r);
+}
+int
+vswscanf(const wchar_t * __restrict str, const wchar_t * __restrict fmt,
+ va_list ap)
+{
+ return vswscanf_l(str, __get_locale(), fmt, ap);
+}
diff --git a/lib/libc/stdio/vwprintf.c b/lib/libc/stdio/vwprintf.c
new file mode 100644
index 0000000..e09a30e
--- /dev/null
+++ b/lib/libc/stdio/vwprintf.c
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <xlocale.h>
+
+int
+vwprintf(const wchar_t * __restrict fmt, va_list ap)
+{
+ return (vfwprintf(stdout, fmt, ap));
+}
+int
+vwprintf_l(locale_t locale, const wchar_t * __restrict fmt, va_list ap)
+{
+ return (vfwprintf_l(stdout, locale, fmt, ap));
+}
diff --git a/lib/libc/stdio/vwscanf.c b/lib/libc/stdio/vwscanf.c
new file mode 100644
index 0000000..730beee
--- /dev/null
+++ b/lib/libc/stdio/vwscanf.c
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <xlocale.h>
+
+int
+vwscanf(const wchar_t * __restrict fmt, va_list ap)
+{
+ return (vfwscanf(stdin, fmt, ap));
+}
+int
+vwscanf_l(locale_t locale, const wchar_t * __restrict fmt, va_list ap)
+{
+ return (vfwscanf_l(stdin, locale, fmt, ap));
+}
diff --git a/lib/libc/stdio/wbuf.c b/lib/libc/stdio/wbuf.c
new file mode 100644
index 0000000..58e2da5
--- /dev/null
+++ b/lib/libc/stdio/wbuf.c
@@ -0,0 +1,91 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)wbuf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdio.h>
+#include "local.h"
+
+/*
+ * Write the given character into the (probably full) buffer for
+ * the given file. Flush the buffer out if it is or becomes full,
+ * or if c=='\n' and the file is line buffered.
+ *
+ * Non-MT-safe
+ */
+int
+__swbuf(c, fp)
+ int c;
+ FILE *fp;
+{
+ int n;
+
+ /*
+ * In case we cannot write, or longjmp takes us out early,
+ * make sure _w is 0 (if fully- or un-buffered) or -_bf._size
+ * (if line buffered) so that we will get called again.
+ * If we did not do this, a sufficient number of putc()
+ * calls might wrap _w from negative to positive.
+ */
+ fp->_w = fp->_lbfsize;
+ if (prepwrite(fp) != 0)
+ return (EOF);
+ c = (unsigned char)c;
+
+ ORIENT(fp, -1);
+
+ /*
+ * If it is completely full, flush it out. Then, in any case,
+ * stuff c into the buffer. If this causes the buffer to fill
+ * completely, or if c is '\n' and the file is line buffered,
+ * flush it (perhaps a second time). The second flush will always
+ * happen on unbuffered streams, where _bf._size==1; fflush()
+ * guarantees that putc() will always call wbuf() by setting _w
+ * to 0, so we need not do anything else.
+ */
+ n = fp->_p - fp->_bf._base;
+ if (n >= fp->_bf._size) {
+ if (__fflush(fp))
+ return (EOF);
+ n = 0;
+ }
+ fp->_w--;
+ *fp->_p++ = c;
+ if (++n == fp->_bf._size || (fp->_flags & __SLBF && c == '\n'))
+ if (__fflush(fp))
+ return (EOF);
+ return (c);
+}
diff --git a/lib/libc/stdio/wprintf.3 b/lib/libc/stdio/wprintf.3
new file mode 100644
index 0000000..fecb586
--- /dev/null
+++ b/lib/libc/stdio/wprintf.3
@@ -0,0 +1,618 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)printf.3 8.1 (Berkeley) 6/4/93
+.\" FreeBSD: src/lib/libc/stdio/printf.3,v 1.47 2002/09/06 11:23:55 tjr Exp
+.\" $FreeBSD$
+.\"
+.Dd July 5, 2003
+.Dt WPRINTF 3
+.Os
+.Sh NAME
+.Nm wprintf , fwprintf , swprintf ,
+.Nm vwprintf , vfwprintf , vswprintf
+.Nd formatted wide character output conversion
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.In wchar.h
+.Ft int
+.Fn fwprintf "FILE * restrict stream" "const wchar_t * restrict format" ...
+.Ft int
+.Fn swprintf "wchar_t * restrict ws" "size_t n" "const wchar_t * restrict format" ...
+.Ft int
+.Fn wprintf "const wchar_t * restrict format" ...
+.In stdarg.h
+.Ft int
+.Fn vfwprintf "FILE * restrict stream" "const wchar_t * restrict" "va_list ap"
+.Ft int
+.Fn vswprintf "wchar_t * restrict ws" "size_t n" "const wchar_t *restrict format" "va_list ap"
+.Ft int
+.Fn vwprintf "const wchar_t * restrict format" "va_list ap"
+.Sh DESCRIPTION
+The
+.Fn wprintf
+family of functions produces output according to a
+.Fa format
+as described below.
+The
+.Fn wprintf
+and
+.Fn vwprintf
+functions
+write output to
+.Dv stdout ,
+the standard output stream;
+.Fn fwprintf
+and
+.Fn vfwprintf
+write output to the given output
+.Fa stream ;
+.Fn swprintf
+and
+.Fn vswprintf
+write to the wide character string
+.Fa ws .
+.Pp
+These functions write the output under the control of a
+.Fa format
+string that specifies how subsequent arguments
+(or arguments accessed via the variable-length argument facilities of
+.Xr stdarg 3 )
+are converted for output.
+.Pp
+These functions return the number of characters printed
+(not including the trailing
+.Ql \e0
+used to end output to strings).
+.Pp
+The
+.Fn swprintf
+and
+.Fn vswprintf
+functions will fail if
+.Fa n
+or more wide characters were requested to be written,
+.Pp
+The format string is composed of zero or more directives:
+ordinary
+characters (not
+.Cm % ) ,
+which are copied unchanged to the output stream;
+and conversion specifications, each of which results
+in fetching zero or more subsequent arguments.
+Each conversion specification is introduced by
+the
+.Cm %
+character.
+The arguments must correspond properly (after type promotion)
+with the conversion specifier.
+After the
+.Cm % ,
+the following appear in sequence:
+.Bl -bullet
+.It
+An optional field, consisting of a decimal digit string followed by a
+.Cm $ ,
+specifying the next argument to access.
+If this field is not provided, the argument following the last
+argument accessed will be used.
+Arguments are numbered starting at
+.Cm 1 .
+If unaccessed arguments in the format string are interspersed with ones that
+are accessed the results will be indeterminate.
+.It
+Zero or more of the following flags:
+.Bl -tag -width ".So \ Sc (space)"
+.It Sq Cm #
+The value should be converted to an
+.Dq alternate form .
+For
+.Cm c , d , i , n , p , s ,
+and
+.Cm u
+conversions, this option has no effect.
+For
+.Cm o
+conversions, the precision of the number is increased to force the first
+character of the output string to a zero (except if a zero value is printed
+with an explicit precision of zero).
+For
+.Cm x
+and
+.Cm X
+conversions, a non-zero result has the string
+.Ql 0x
+(or
+.Ql 0X
+for
+.Cm X
+conversions) prepended to it.
+For
+.Cm a , A , e , E , f , F , g ,
+and
+.Cm G
+conversions, the result will always contain a decimal point, even if no
+digits follow it (normally, a decimal point appears in the results of
+those conversions only if a digit follows).
+For
+.Cm g
+and
+.Cm G
+conversions, trailing zeros are not removed from the result as they
+would otherwise be.
+.It So Cm 0 Sc (zero)
+Zero padding.
+For all conversions except
+.Cm n ,
+the converted value is padded on the left with zeros rather than blanks.
+If a precision is given with a numeric conversion
+.Cm ( d , i , o , u , i , x ,
+and
+.Cm X ) ,
+the
+.Cm 0
+flag is ignored.
+.It Sq Cm \-
+A negative field width flag;
+the converted value is to be left adjusted on the field boundary.
+Except for
+.Cm n
+conversions, the converted value is padded on the right with blanks,
+rather than on the left with blanks or zeros.
+A
+.Cm \-
+overrides a
+.Cm 0
+if both are given.
+.It So "\ " Sc (space)
+A blank should be left before a positive number
+produced by a signed conversion
+.Cm ( a , A , d , e , E , f , F , g , G ,
+or
+.Cm i ) .
+.It Sq Cm +
+A sign must always be placed before a
+number produced by a signed conversion.
+A
+.Cm +
+overrides a space if both are used.
+.It Sq Cm '
+Decimal conversions
+.Cm ( d , u ,
+or
+.Cm i )
+or the integral portion of a floating point conversion
+.Cm ( f
+or
+.Cm F )
+should be grouped and separated by thousands using
+the non-monetary separator returned by
+.Xr localeconv 3 .
+.El
+.It
+An optional decimal digit string specifying a minimum field width.
+If the converted value has fewer characters than the field width, it will
+be padded with spaces on the left (or right, if the left-adjustment
+flag has been given) to fill out
+the field width.
+.It
+An optional precision, in the form of a period
+.Cm \&.
+followed by an
+optional digit string.
+If the digit string is omitted, the precision is taken as zero.
+This gives the minimum number of digits to appear for
+.Cm d , i , o , u , x ,
+and
+.Cm X
+conversions, the number of digits to appear after the decimal-point for
+.Cm a , A , e , E , f ,
+and
+.Cm F
+conversions, the maximum number of significant digits for
+.Cm g
+and
+.Cm G
+conversions, or the maximum number of characters to be printed from a
+string for
+.Cm s
+conversions.
+.It
+An optional length modifier, that specifies the size of the argument.
+The following length modifiers are valid for the
+.Cm d , i , n , o , u , x ,
+or
+.Cm X
+conversion:
+.Bl -column ".Cm q Em (deprecated)" ".Vt signed char" ".Vt unsigned long long" ".Vt long long *"
+.It Sy Modifier Ta Cm d , i Ta Cm o , u , x , X Ta Cm n
+.It Cm hh Ta Vt "signed char" Ta Vt "unsigned char" Ta Vt "signed char *"
+.It Cm h Ta Vt short Ta Vt "unsigned short" Ta Vt "short *"
+.It Cm l No (ell) Ta Vt long Ta Vt "unsigned long" Ta Vt "long *"
+.It Cm ll No (ell ell) Ta Vt "long long" Ta Vt "unsigned long long" Ta Vt "long long *"
+.It Cm j Ta Vt intmax_t Ta Vt uintmax_t Ta Vt "intmax_t *"
+.It Cm t Ta Vt ptrdiff_t Ta (see note) Ta Vt "ptrdiff_t *"
+.It Cm z Ta (see note) Ta Vt size_t Ta (see note)
+.It Cm q Em (deprecated) Ta Vt quad_t Ta Vt u_quad_t Ta Vt "quad_t *"
+.El
+.Pp
+Note:
+the
+.Cm t
+modifier, when applied to a
+.Cm o , u , x ,
+or
+.Cm X
+conversion, indicates that the argument is of an unsigned type
+equivalent in size to a
+.Vt ptrdiff_t .
+The
+.Cm z
+modifier, when applied to a
+.Cm d
+or
+.Cm i
+conversion, indicates that the argument is of a signed type equivalent in
+size to a
+.Vt size_t .
+Similarly, when applied to an
+.Cm n
+conversion, it indicates that the argument is a pointer to a signed type
+equivalent in size to a
+.Vt size_t .
+.Pp
+The following length modifier is valid for the
+.Cm a , A , e , E , f , F , g ,
+or
+.Cm G
+conversion:
+.Bl -column ".Sy Modifier" ".Cm a , A , e , E , f , F , g , G"
+.It Sy Modifier Ta Cm a , A , e , E , f , F , g , G
+.It Cm L Ta Vt "long double"
+.El
+.Pp
+The following length modifier is valid for the
+.Cm c
+or
+.Cm s
+conversion:
+.Bl -column ".Sy Modifier" ".Vt wint_t" ".Vt wchar_t *"
+.It Sy Modifier Ta Cm c Ta Cm s
+.It Cm l No (ell) Ta Vt wint_t Ta Vt "wchar_t *"
+.El
+.It
+A character that specifies the type of conversion to be applied.
+.El
+.Pp
+A field width or precision, or both, may be indicated by
+an asterisk
+.Ql *
+or an asterisk followed by one or more decimal digits and a
+.Ql $
+instead of a
+digit string.
+In this case, an
+.Vt int
+argument supplies the field width or precision.
+A negative field width is treated as a left adjustment flag followed by a
+positive field width; a negative precision is treated as though it were
+missing.
+If a single format directive mixes positional
+.Pq Li nn$
+and non-positional arguments, the results are undefined.
+.Pp
+The conversion specifiers and their meanings are:
+.Bl -tag -width ".Cm diouxX"
+.It Cm diouxX
+The
+.Vt int
+(or appropriate variant) argument is converted to signed decimal
+.Cm ( d
+and
+.Cm i ) ,
+unsigned octal
+.Pq Cm o ,
+unsigned decimal
+.Pq Cm u ,
+or unsigned hexadecimal
+.Cm ( x
+and
+.Cm X )
+notation.
+The letters
+.Dq Li abcdef
+are used for
+.Cm x
+conversions; the letters
+.Dq Li ABCDEF
+are used for
+.Cm X
+conversions.
+The precision, if any, gives the minimum number of digits that must
+appear; if the converted value requires fewer digits, it is padded on
+the left with zeros.
+.It Cm DOU
+The
+.Vt "long int"
+argument is converted to signed decimal, unsigned octal, or unsigned
+decimal, as if the format had been
+.Cm ld , lo ,
+or
+.Cm lu
+respectively.
+These conversion characters are deprecated, and will eventually disappear.
+.It Cm eE
+The
+.Vt double
+argument is rounded and converted in the style
+.Sm off
+.Oo \- Oc Ar d Li \&. Ar ddd Li e \(+- Ar dd
+.Sm on
+where there is one digit before the
+decimal-point character
+and the number of digits after it is equal to the precision;
+if the precision is missing,
+it is taken as 6; if the precision is
+zero, no decimal-point character appears.
+An
+.Cm E
+conversion uses the letter
+.Ql E
+(rather than
+.Ql e )
+to introduce the exponent.
+The exponent always contains at least two digits; if the value is zero,
+the exponent is 00.
+.Pp
+For
+.Cm a , A , e , E , f , F , g ,
+and
+.Cm G
+conversions, positive and negative infinity are represented as
+.Li inf
+and
+.Li -inf
+respectively when using the lowercase conversion character, and
+.Li INF
+and
+.Li -INF
+respectively when using the uppercase conversion character.
+Similarly, NaN is represented as
+.Li nan
+when using the lowercase conversion, and
+.Li NAN
+when using the uppercase conversion.
+.It Cm fF
+The
+.Vt double
+argument is rounded and converted to decimal notation in the style
+.Sm off
+.Oo \- Oc Ar ddd Li \&. Ar ddd ,
+.Sm on
+where the number of digits after the decimal-point character
+is equal to the precision specification.
+If the precision is missing, it is taken as 6; if the precision is
+explicitly zero, no decimal-point character appears.
+If a decimal point appears, at least one digit appears before it.
+.It Cm gG
+The
+.Vt double
+argument is converted in style
+.Cm f
+or
+.Cm e
+(or
+.Cm F
+or
+.Cm E
+for
+.Cm G
+conversions).
+The precision specifies the number of significant digits.
+If the precision is missing, 6 digits are given; if the precision is zero,
+it is treated as 1.
+Style
+.Cm e
+is used if the exponent from its conversion is less than \-4 or greater than
+or equal to the precision.
+Trailing zeros are removed from the fractional part of the result; a
+decimal point appears only if it is followed by at least one digit.
+.It Cm aA
+The
+.Vt double
+argument is converted to hexadecimal notation in the style
+.Sm off
+.Oo \- Oc Li 0x Ar h Li \&. Ar hhhp Oo \(+- Oc Ar d ,
+.Sm on
+where the number of digits after the hexadecimal-point character
+is equal to the precision specification.
+If the precision is missing, it is taken as enough to exactly
+represent the floating-point number; if the precision is
+explicitly zero, no hexadecimal-point character appears.
+This is an exact conversion of the mantissa+exponent internal
+floating point representation; the
+.Sm off
+.Oo \- Oc Li 0x Ar h Li \&. Ar hhh
+.Sm on
+portion represents exactly the mantissa; only denormalized
+mantissas have a zero value to the left of the hexadecimal
+point.
+The
+.Cm p
+is a literal character
+.Ql p ;
+the exponent is preceded by a positive or negative sign
+and is represented in decimal, using only enough characters
+to represent the exponent.
+The
+.Cm A
+conversion uses the prefix
+.Dq Li 0X
+(rather than
+.Dq Li 0x ) ,
+the letters
+.Dq Li ABCDEF
+(rather than
+.Dq Li abcdef )
+to represent the hex digits, and the letter
+.Ql P
+(rather than
+.Ql p )
+to separate the mantissa and exponent.
+.It Cm C
+Treated as
+.Cm c
+with the
+.Cm l
+(ell) modifier.
+.It Cm c
+The
+.Vt int
+argument is converted to an
+.Vt "unsigned char" ,
+then to a
+.Vt wchar_t
+as if by
+.Xr btowc 3 ,
+and the resulting character is written.
+.Pp
+If the
+.Cm l
+(ell) modifier is used, the
+.Vt wint_t
+argument is converted to a
+.Vt wchar_t
+and written.
+.It Cm S
+Treated as
+.Cm s
+with the
+.Cm l
+(ell) modifier.
+.It Cm s
+The
+.Vt "char *"
+argument is expected to be a pointer to an array of character type (pointer
+to a string) containing a multibyte sequence.
+Characters from the array are converted to wide characters and written up to
+(but not including)
+a terminating
+.Dv NUL
+character;
+if a precision is specified, no more than the number specified are
+written.
+If a precision is given, no null character
+need be present; if the precision is not specified, or is greater than
+the size of the array, the array must contain a terminating
+.Dv NUL
+character.
+.Pp
+If the
+.Cm l
+(ell) modifier is used, the
+.Vt "wchar_t *"
+argument is expected to be a pointer to an array of wide characters
+(pointer to a wide string).
+Each wide character in the string
+is written.
+Wide characters from the array are written up to (but not including)
+a terminating wide
+.Dv NUL
+character;
+if a precision is specified, no more than the number specified are
+written (including shift sequences).
+If a precision is given, no null character
+need be present; if the precision is not specified, or is greater than
+the number of characters in
+the string, the array must contain a terminating wide
+.Dv NUL
+character.
+.It Cm p
+The
+.Vt "void *"
+pointer argument is printed in hexadecimal (as if by
+.Ql %#x
+or
+.Ql %#lx ) .
+.It Cm n
+The number of characters written so far is stored into the
+integer indicated by the
+.Vt "int *"
+(or variant) pointer argument.
+No argument is converted.
+.It Cm %
+A
+.Ql %
+is written.
+No argument is converted.
+The complete conversion specification
+is
+.Ql %% .
+.El
+.Pp
+The decimal point
+character is defined in the program's locale (category
+.Dv LC_NUMERIC ) .
+.Pp
+In no case does a non-existent or small field width cause truncation of
+a numeric field; if the result of a conversion is wider than the field
+width, the
+field is expanded to contain the conversion result.
+.Sh SEE ALSO
+.Xr btowc 3 ,
+.Xr fputws 3 ,
+.Xr printf 3 ,
+.Xr putwc 3 ,
+.Xr setlocale 3 ,
+.Xr wcsrtombs 3 ,
+.Xr wscanf 3
+.Sh STANDARDS
+Subject to the caveats noted in the
+.Sx BUGS
+section
+of
+.Xr printf 3 ,
+the
+.Fn wprintf ,
+.Fn fwprintf ,
+.Fn swprintf ,
+.Fn vwprintf ,
+.Fn vfwprintf
+and
+.Fn vswprintf
+functions
+conform to
+.St -isoC-99 .
+.Sh SECURITY CONSIDERATIONS
+Refer to
+.Xr printf 3 .
diff --git a/lib/libc/stdio/wprintf.c b/lib/libc/stdio/wprintf.c
new file mode 100644
index 0000000..fdffa86
--- /dev/null
+++ b/lib/libc/stdio/wprintf.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <xlocale.h>
+
+int
+wprintf(const wchar_t * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vfwprintf(stdout, fmt, ap);
+ va_end(ap);
+
+ return (ret);
+}
+int
+wprintf_l(locale_t locale, const wchar_t * __restrict fmt, ...)
+{
+ int ret;
+ va_list ap;
+
+ va_start(ap, fmt);
+ ret = vfwprintf_l(stdout, locale, fmt, ap);
+ va_end(ap);
+
+ return (ret);
+}
diff --git a/lib/libc/stdio/wscanf.3 b/lib/libc/stdio/wscanf.3
new file mode 100644
index 0000000..f696d3d
--- /dev/null
+++ b/lib/libc/stdio/wscanf.3
@@ -0,0 +1,479 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)scanf.3 8.2 (Berkeley) 12/11/93
+.\" FreeBSD: src/lib/libc/stdio/scanf.3,v 1.24 2003/06/28 09:03:25 das Exp
+.\" $FreeBSD$
+.\"
+.Dd July 5, 2003
+.Dt WSCANF 3
+.Os
+.Sh NAME
+.Nm wscanf ,
+.Nm fwscanf ,
+.Nm swscanf ,
+.Nm vwscanf ,
+.Nm vswscanf ,
+.Nm vfwscanf
+.Nd wide character input format conversion
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.In wchar.h
+.Ft int
+.Fn wscanf "const wchar_t * restrict format" ...
+.Ft int
+.Fn fwscanf "FILE * restrict stream" "const wchar_t * restrict format" ...
+.Ft int
+.Fn swscanf "const wchar_t * restrict str" "const wchar_t * restrict format" ...
+.In stdarg.h
+.Ft int
+.Fn vwscanf "const wchar_t * restrict format" "va_list ap"
+.Ft int
+.Fn vswscanf "const wchar_t * restrict str" "const wchar_t * restrict format" "va_list ap"
+.Ft int
+.Fn vfwscanf "FILE * restrict stream" "const wchar_t * restrict format" "va_list ap"
+.Sh DESCRIPTION
+The
+.Fn wscanf
+family of functions scans input according to a
+.Fa format
+as described below.
+This format may contain
+.Em conversion specifiers ;
+the results from such conversions, if any,
+are stored through the
+.Em pointer
+arguments.
+The
+.Fn wscanf
+function
+reads input from the standard input stream
+.Dv stdin ,
+.Fn fwscanf
+reads input from the stream pointer
+.Fa stream ,
+and
+.Fn swscanf
+reads its input from the wide character string pointed to by
+.Fa str .
+The
+.Fn vfwscanf
+function
+is analogous to
+.Xr vfwprintf 3
+and reads input from the stream pointer
+.Fa stream
+using a variable argument list of pointers (see
+.Xr stdarg 3 ) .
+The
+.Fn vwscanf
+function scans a variable argument list from the standard input and
+the
+.Fn vswscanf
+function scans it from a wide character string;
+these are analogous to
+the
+.Fn vwprintf
+and
+.Fn vswprintf
+functions respectively.
+Each successive
+.Em pointer
+argument must correspond properly with
+each successive conversion specifier
+(but see the
+.Cm *
+conversion below).
+All conversions are introduced by the
+.Cm %
+(percent sign) character.
+The
+.Fa format
+string
+may also contain other characters.
+White space (such as blanks, tabs, or newlines) in the
+.Fa format
+string match any amount of white space, including none, in the input.
+Everything else
+matches only itself.
+Scanning stops
+when an input character does not match such a format character.
+Scanning also stops
+when an input conversion cannot be made (see below).
+.Sh CONVERSIONS
+Following the
+.Cm %
+character introducing a conversion
+there may be a number of
+.Em flag
+characters, as follows:
+.Bl -tag -width ".Cm l No (ell)"
+.It Cm *
+Suppresses assignment.
+The conversion that follows occurs as usual, but no pointer is used;
+the result of the conversion is simply discarded.
+.It Cm hh
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt char
+(rather than
+.Vt int ) .
+.It Cm h
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt "short int"
+(rather than
+.Vt int ) .
+.It Cm l No (ell)
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt "long int"
+(rather than
+.Vt int ) ,
+that the conversion will be one of
+.Cm a , e , f ,
+or
+.Cm g
+and the next pointer is a pointer to
+.Vt double
+(rather than
+.Vt float ) ,
+or that the conversion will be one of
+.Cm c
+or
+.Cm s
+and the next pointer is a pointer to an array of
+.Vt wchar_t
+(rather than
+.Vt char ) .
+.It Cm ll No (ell ell)
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt "long long int"
+(rather than
+.Vt int ) .
+.It Cm L
+Indicates that the conversion will be one of
+.Cm a , e , f ,
+or
+.Cm g
+and the next pointer is a pointer to
+.Vt "long double" .
+.It Cm j
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt intmax_t
+(rather than
+.Vt int ) .
+.It Cm t
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt ptrdiff_t
+(rather than
+.Vt int ) .
+.It Cm z
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt size_t
+(rather than
+.Vt int ) .
+.It Cm q
+(deprecated.)
+Indicates that the conversion will be one of
+.Cm dioux
+or
+.Cm n
+and the next pointer is a pointer to a
+.Vt "long long int"
+(rather than
+.Vt int ) .
+.El
+.Pp
+In addition to these flags,
+there may be an optional maximum field width,
+expressed as a decimal integer,
+between the
+.Cm %
+and the conversion.
+If no width is given,
+a default of
+.Dq infinity
+is used (with one exception, below);
+otherwise at most this many characters are scanned
+in processing the conversion.
+Before conversion begins,
+most conversions skip white space;
+this white space is not counted against the field width.
+.Pp
+The following conversions are available:
+.Bl -tag -width XXXX
+.It Cm %
+Matches a literal
+.Ql % .
+That is,
+.Dq Li %%
+in the format string
+matches a single input
+.Ql %
+character.
+No conversion is done, and assignment does not occur.
+.It Cm d
+Matches an optionally signed decimal integer;
+the next pointer must be a pointer to
+.Vt int .
+.It Cm i
+Matches an optionally signed integer;
+the next pointer must be a pointer to
+.Vt int .
+The integer is read in base 16 if it begins
+with
+.Ql 0x
+or
+.Ql 0X ,
+in base 8 if it begins with
+.Ql 0 ,
+and in base 10 otherwise.
+Only characters that correspond to the base are used.
+.It Cm o
+Matches an octal integer;
+the next pointer must be a pointer to
+.Vt "unsigned int" .
+.It Cm u
+Matches an optionally signed decimal integer;
+the next pointer must be a pointer to
+.Vt "unsigned int" .
+.It Cm x , X
+Matches an optionally signed hexadecimal integer;
+the next pointer must be a pointer to
+.Vt "unsigned int" .
+.It Cm a , A , e , E , f , F , g , G
+Matches a floating-point number in the style of
+.Xr wcstod 3 .
+The next pointer must be a pointer to
+.Vt float
+(unless
+.Cm l
+or
+.Cm L
+is specified.)
+.It Cm s
+Matches a sequence of non-white-space wide characters;
+the next pointer must be a pointer to
+.Vt char ,
+and the array must be large enough to accept the multibyte representation
+of all the sequence and the
+terminating
+.Dv NUL
+character.
+The input string stops at white space
+or at the maximum field width, whichever occurs first.
+.Pp
+If an
+.Cm l
+qualifier is present, the next pointer must be a pointer to
+.Vt wchar_t ,
+into which the input will be placed.
+.It Cm S
+The same as
+.Cm ls .
+.It Cm c
+Matches a sequence of
+.Em width
+count
+wide characters (default 1);
+the next pointer must be a pointer to
+.Vt char ,
+and there must be enough room for the multibyte representation
+of all the characters
+(no terminating
+.Dv NUL
+is added).
+The usual skip of leading white space is suppressed.
+To skip white space first, use an explicit space in the format.
+.Pp
+If an
+.Cm l
+qualifier is present, the next pointer must be a pointer to
+.Vt wchar_t ,
+into which the input will be placed.
+.It Cm C
+The same as
+.Cm lc .
+.It Cm \&[
+Matches a nonempty sequence of characters from the specified set
+of accepted characters;
+the next pointer must be a pointer to
+.Vt char ,
+and there must be enough room for the multibyte representation of
+all the characters in the string,
+plus a terminating
+.Dv NUL
+character.
+The usual skip of leading white space is suppressed.
+The string is to be made up of characters in
+(or not in)
+a particular set;
+the set is defined by the characters between the open bracket
+.Cm [
+character
+and a close bracket
+.Cm ]
+character.
+The set
+.Em excludes
+those characters
+if the first character after the open bracket is a circumflex
+.Cm ^ .
+To include a close bracket in the set,
+make it the first character after the open bracket
+or the circumflex;
+any other position will end the set.
+To include a hyphen in the set,
+make it the last character before the final close bracket;
+some implementations of
+.Fn wscanf
+use
+.Dq Li A-Z
+to represent the range of characters between
+.Ql A
+and
+.Ql Z .
+The string ends with the appearance of a character not in the
+(or, with a circumflex, in) set
+or when the field width runs out.
+.Pp
+If an
+.Cm l
+qualifier is present, the next pointer must be a pointer to
+.Vt wchar_t ,
+into which the input will be placed.
+.It Cm p
+Matches a pointer value (as printed by
+.Ql %p
+in
+.Xr wprintf 3 ) ;
+the next pointer must be a pointer to
+.Vt void .
+.It Cm n
+Nothing is expected;
+instead, the number of characters consumed thus far from the input
+is stored through the next pointer,
+which must be a pointer to
+.Vt int .
+This is
+.Em not
+a conversion, although it can be suppressed with the
+.Cm *
+flag.
+.El
+.Pp
+The decimal point
+character is defined in the program's locale (category
+.Dv LC_NUMERIC ) .
+.Pp
+For backwards compatibility, a
+.Dq conversion
+of
+.Ql %\e0
+causes an immediate return of
+.Dv EOF .
+.Sh RETURN VALUES
+These
+functions
+return
+the number of input items assigned, which can be fewer than provided
+for, or even zero, in the event of a matching failure.
+Zero
+indicates that, while there was input available,
+no conversions were assigned;
+typically this is due to an invalid input character,
+such as an alphabetic character for a
+.Ql %d
+conversion.
+The value
+.Dv EOF
+is returned if an input failure occurs before any conversion such as an
+end-of-file occurs.
+If an error or end-of-file occurs after conversion
+has begun,
+the number of conversions which were successfully completed is returned.
+.Sh SEE ALSO
+.Xr fgetwc 3 ,
+.Xr scanf 3 ,
+.Xr wcrtomb 3 ,
+.Xr wcstod 3 ,
+.Xr wcstol 3 ,
+.Xr wcstoul 3 ,
+.Xr wprintf 3
+.Sh STANDARDS
+The
+.Fn fwscanf ,
+.Fn wscanf ,
+.Fn swscanf ,
+.Fn vfwscanf ,
+.Fn vwscanf
+and
+.Fn vswscanf
+functions
+conform to
+.St -isoC-99 .
+.Sh BUGS
+In addition to the bugs documented in
+.Xr scanf 3 ,
+.Fn wscanf
+does not support the
+.Dq Li A-Z
+notation for specifying character ranges with the character
+class conversion
+.Pq Sq Cm %[ .
diff --git a/lib/libc/stdio/wscanf.c b/lib/libc/stdio/wscanf.c
new file mode 100644
index 0000000..22ce9bd
--- /dev/null
+++ b/lib/libc/stdio/wscanf.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <xlocale.h>
+
+int
+wscanf(const wchar_t * __restrict fmt, ...)
+{
+ va_list ap;
+ int r;
+
+ va_start(ap, fmt);
+ r = vfwscanf(stdin, fmt, ap);
+ va_end(ap);
+
+ return (r);
+}
+int
+wscanf_l(locale_t locale, const wchar_t * __restrict fmt, ...)
+{
+ va_list ap;
+ int r;
+
+ va_start(ap, fmt);
+ r = vfwscanf_l(stdin, locale, fmt, ap);
+ va_end(ap);
+
+ return (r);
+}
diff --git a/lib/libc/stdio/wsetup.c b/lib/libc/stdio/wsetup.c
new file mode 100644
index 0000000..37bfc58
--- /dev/null
+++ b/lib/libc/stdio/wsetup.c
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)wsetup.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include "local.h"
+
+/*
+ * Various output routines call wsetup to be sure it is safe to write,
+ * because either _flags does not include __SWR, or _buf is NULL.
+ * _wsetup returns 0 if OK to write; otherwise, it returns EOF and sets errno.
+ */
+int
+__swsetup(fp)
+ FILE *fp;
+{
+ /* make sure stdio is set up */
+ if (!__sdidinit)
+ __sinit();
+
+ /*
+ * If we are not writing, we had better be reading and writing.
+ */
+ if ((fp->_flags & __SWR) == 0) {
+ if ((fp->_flags & __SRW) == 0) {
+ errno = EBADF;
+ fp->_flags |= __SERR;
+ return (EOF);
+ }
+ if (fp->_flags & __SRD) {
+ /* clobber any ungetc data */
+ if (HASUB(fp))
+ FREEUB(fp);
+ fp->_flags &= ~(__SRD|__SEOF);
+ fp->_r = 0;
+ fp->_p = fp->_bf._base;
+ }
+ fp->_flags |= __SWR;
+ }
+
+ /*
+ * Make a buffer if necessary, then set _w.
+ */
+ if (fp->_bf._base == NULL)
+ __smakebuf(fp);
+ if (fp->_flags & __SLBF) {
+ /*
+ * It is line buffered, so make _lbfsize be -_bufsize
+ * for the putc() macro. We will change _lbfsize back
+ * to 0 whenever we turn off __SWR.
+ */
+ fp->_w = 0;
+ fp->_lbfsize = -fp->_bf._size;
+ } else
+ fp->_w = fp->_flags & __SNBF ? 0 : fp->_bf._size;
+ return (0);
+}
diff --git a/lib/libc/stdio/xprintf.c b/lib/libc/stdio/xprintf.c
new file mode 100644
index 0000000..0cc8571
--- /dev/null
+++ b/lib/libc/stdio/xprintf.c
@@ -0,0 +1,690 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include "namespace.h"
+#include <err.h>
+#include <sys/types.h>
+#include <stdio.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <locale.h>
+#include <stdint.h>
+#include <assert.h>
+#include <stdarg.h>
+#include <namespace.h>
+#include <string.h>
+#include <wchar.h>
+#include "un-namespace.h"
+
+#include "local.h"
+#include "printf.h"
+#include "fvwrite.h"
+
+int __use_xprintf = -1;
+
+/* private stuff -----------------------------------------------------*/
+
+union arg {
+ int intarg;
+ long longarg;
+ intmax_t intmaxarg;
+#ifndef NO_FLOATING_POINT
+ double doublearg;
+ long double longdoublearg;
+#endif
+ wint_t wintarg;
+ char *pchararg;
+ wchar_t *pwchararg;
+ void *pvoidarg;
+};
+
+/*
+ * Macros for converting digits to letters and vice versa
+ */
+#define to_digit(c) ((c) - '0')
+#define is_digit(c) (((unsigned)to_digit(c)) <= 9)
+
+/* various globals ---------------------------------------------------*/
+
+const char __lowercase_hex[17] = "0123456789abcdef?"; /*lint !e784 */
+const char __uppercase_hex[17] = "0123456789ABCDEF?"; /*lint !e784 */
+
+#define PADSIZE 16
+static char blanks[PADSIZE] =
+ {' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' '};
+static char zeroes[PADSIZE] =
+ {'0','0','0','0','0','0','0','0','0','0','0','0','0','0','0','0'};
+
+/* printing and padding functions ------------------------------------*/
+
+#define NIOV 8
+
+struct __printf_io {
+ FILE *fp;
+ struct __suio uio;
+ struct __siov iov[NIOV];
+ struct __siov *iovp;
+};
+
+static void
+__printf_init(struct __printf_io *io)
+{
+
+ io->uio.uio_iov = io->iovp = &io->iov[0];
+ io->uio.uio_resid = 0;
+ io->uio.uio_iovcnt = 0;
+}
+
+void
+__printf_flush(struct __printf_io *io)
+{
+
+ __sfvwrite(io->fp, &io->uio);
+ __printf_init(io);
+}
+
+int
+__printf_puts(struct __printf_io *io, const void *ptr, int len)
+{
+
+
+ if (io->fp->_flags & __SERR)
+ return (0);
+ if (len == 0)
+ return (0);
+ io->iovp->iov_base = __DECONST(void *, ptr);
+ io->iovp->iov_len = len;
+ io->uio.uio_resid += len;
+ io->iovp++;
+ io->uio.uio_iovcnt++;
+ if (io->uio.uio_iovcnt >= NIOV)
+ __printf_flush(io);
+ return (len);
+}
+
+int
+__printf_pad(struct __printf_io *io, int howmany, int zero)
+{
+ int n;
+ const char *with;
+ int ret = 0;
+
+ if (zero)
+ with = zeroes;
+ else
+ with = blanks;
+
+ if ((n = (howmany)) > 0) {
+ while (n > PADSIZE) {
+ ret += __printf_puts(io, with, PADSIZE);
+ n -= PADSIZE;
+ }
+ ret += __printf_puts(io, with, n);
+ }
+ return (ret);
+}
+
+int
+__printf_out(struct __printf_io *io, const struct printf_info *pi, const void *ptr, int len)
+{
+ int ret = 0;
+
+ if ((!pi->left) && pi->width > len)
+ ret += __printf_pad(io, pi->width - len, pi->pad == '0');
+ ret += __printf_puts(io, ptr, len);
+ if (pi->left && pi->width > len)
+ ret += __printf_pad(io, pi->width - len, pi->pad == '0');
+ return (ret);
+}
+
+
+/* percent handling -------------------------------------------------*/
+
+static int
+__printf_arginfo_pct(const struct printf_info *pi __unused, size_t n __unused, int *argt __unused)
+{
+
+ return (0);
+}
+
+static int
+__printf_render_pct(struct __printf_io *io, const struct printf_info *pi __unused, const void *const *arg __unused)
+{
+
+ return (__printf_puts(io, "%", 1));
+}
+
+/* 'n' ---------------------------------------------------------------*/
+
+static int
+__printf_arginfo_n(const struct printf_info *pi, size_t n, int *argt)
+{
+
+ assert(n >= 1);
+ argt[0] = PA_POINTER;
+ return (1);
+}
+
+/*
+ * This is a printf_render so that all output has been flushed before it
+ * gets called.
+ */
+
+static int
+__printf_render_n(FILE *io __unused, const struct printf_info *pi, const void *const *arg)
+{
+
+ if (pi->is_char)
+ **((signed char **)arg[0]) = (signed char)pi->sofar;
+ else if (pi->is_short)
+ **((short **)arg[0]) = (short)pi->sofar;
+ else if (pi->is_long)
+ **((long **)arg[0]) = pi->sofar;
+ else if (pi->is_long_double)
+ **((long long **)arg[0]) = pi->sofar;
+ else if (pi->is_intmax)
+ **((intmax_t **)arg[0]) = pi->sofar;
+ else if (pi->is_ptrdiff)
+ **((ptrdiff_t **)arg[0]) = pi->sofar;
+ else if (pi->is_quad)
+ **((quad_t **)arg[0]) = pi->sofar;
+ else if (pi->is_size)
+ **((size_t **)arg[0]) = pi->sofar;
+ else
+ **((int **)arg[0]) = pi->sofar;
+
+ return (0);
+}
+
+/* table -------------------------------------------------------------*/
+
+/*lint -esym(785, printf_tbl) */
+static struct {
+ printf_arginfo_function *arginfo;
+ printf_function *gnurender;
+ printf_render *render;
+} printf_tbl[256] = {
+ ['%'] = { __printf_arginfo_pct, NULL, __printf_render_pct },
+ ['A'] = { __printf_arginfo_float, NULL, __printf_render_float },
+ ['C'] = { __printf_arginfo_chr, NULL, __printf_render_chr },
+ ['E'] = { __printf_arginfo_float, NULL, __printf_render_float },
+ ['F'] = { __printf_arginfo_float, NULL, __printf_render_float },
+ ['G'] = { __printf_arginfo_float, NULL, __printf_render_float },
+ ['S'] = { __printf_arginfo_str, NULL, __printf_render_str },
+ ['X'] = { __printf_arginfo_int, NULL, __printf_render_int },
+ ['a'] = { __printf_arginfo_float, NULL, __printf_render_float },
+ ['c'] = { __printf_arginfo_chr, NULL, __printf_render_chr },
+ ['d'] = { __printf_arginfo_int, NULL, __printf_render_int },
+ ['e'] = { __printf_arginfo_float, NULL, __printf_render_float },
+ ['f'] = { __printf_arginfo_float, NULL, __printf_render_float },
+ ['g'] = { __printf_arginfo_float, NULL, __printf_render_float },
+ ['i'] = { __printf_arginfo_int, NULL, __printf_render_int },
+ ['n'] = { __printf_arginfo_n, __printf_render_n, NULL },
+ ['o'] = { __printf_arginfo_int, NULL, __printf_render_int },
+ ['p'] = { __printf_arginfo_ptr, NULL, __printf_render_ptr },
+ ['q'] = { __printf_arginfo_int, NULL, __printf_render_int },
+ ['s'] = { __printf_arginfo_str, NULL, __printf_render_str },
+ ['u'] = { __printf_arginfo_int, NULL, __printf_render_int },
+ ['x'] = { __printf_arginfo_int, NULL, __printf_render_int },
+};
+
+
+static int
+__v2printf(FILE *fp, const char *fmt0, unsigned pct, va_list ap)
+{
+ struct printf_info *pi, *pil;
+ const char *fmt;
+ int ch;
+ struct printf_info pia[pct + 10];
+ int argt[pct + 10];
+ union arg args[pct + 10];
+ int nextarg;
+ int maxarg;
+ int ret = 0;
+ int n;
+ struct __printf_io io;
+
+ __printf_init(&io);
+ io.fp = fp;
+
+ fmt = fmt0;
+ maxarg = 0;
+ nextarg = 1;
+ memset(argt, 0, sizeof argt);
+ for (pi = pia; ; pi++) {
+ memset(pi, 0, sizeof *pi);
+ pil = pi;
+ if (*fmt == '\0')
+ break;
+ pil = pi + 1;
+ pi->prec = -1;
+ pi->pad = ' ';
+ pi->begin = pi->end = fmt;
+ while (*fmt != '\0' && *fmt != '%')
+ pi->end = ++fmt;
+ if (*fmt == '\0')
+ break;
+ fmt++;
+ for (;;) {
+ pi->spec = *fmt;
+ switch (pi->spec) {
+ case ' ':
+ /*-
+ * ``If the space and + flags both appear, the space
+ * flag will be ignored.''
+ * -- ANSI X3J11
+ */
+ if (pi->showsign == 0)
+ pi->showsign = ' ';
+ fmt++;
+ continue;
+ case '#':
+ pi->alt = 1;
+ fmt++;
+ continue;
+ case '.':
+ pi->prec = 0;
+ fmt++;
+ if (*fmt == '*') {
+ fmt++;
+ pi->get_prec = nextarg;
+ argt[nextarg++] = PA_INT;
+ continue;
+ }
+ while (*fmt != '\0' && is_digit(*fmt)) {
+ pi->prec *= 10;
+ pi->prec += to_digit(*fmt);
+ fmt++;
+ }
+ continue;
+ case '-':
+ pi->left = 1;
+ fmt++;
+ continue;
+ case '+':
+ pi->showsign = '+';
+ fmt++;
+ continue;
+ case '*':
+ fmt++;
+ pi->get_width = nextarg;
+ argt[nextarg++] = PA_INT;
+ continue;
+ case '%':
+ fmt++;
+ break;
+ case '\'':
+ pi->group = 1;
+ fmt++;
+ continue;
+ case '0':
+ /*-
+ * ``Note that 0 is taken as a flag, not as the
+ * beginning of a field width.''
+ * -- ANSI X3J11
+ */
+ pi->pad = '0';
+ fmt++;
+ continue;
+ case '1': case '2': case '3':
+ case '4': case '5': case '6':
+ case '7': case '8': case '9':
+ n = 0;
+ while (*fmt != '\0' && is_digit(*fmt)) {
+ n *= 10;
+ n += to_digit(*fmt);
+ fmt++;
+ }
+ if (*fmt == '$') {
+ if (nextarg > maxarg)
+ maxarg = nextarg;
+ nextarg = n;
+ fmt++;
+ } else
+ pi->width = n;
+ continue;
+ case 'D':
+ case 'O':
+ case 'U':
+ pi->spec += ('a' - 'A');
+ pi->is_intmax = 0;
+ if (pi->is_long_double || pi->is_quad) {
+ pi->is_long = 0;
+ pi->is_long_double = 1;
+ } else {
+ pi->is_long = 1;
+ pi->is_long_double = 0;
+ }
+ fmt++;
+ break;
+ case 'j':
+ pi->is_intmax = 1;
+ fmt++;
+ continue;
+ case 'q':
+ pi->is_long = 0;
+ pi->is_quad = 1;
+ fmt++;
+ continue;
+ case 'L':
+ pi->is_long_double = 1;
+ fmt++;
+ continue;
+ case 'h':
+ fmt++;
+ if (*fmt == 'h') {
+ fmt++;
+ pi->is_char = 1;
+ } else {
+ pi->is_short = 1;
+ }
+ continue;
+ case 'l':
+ fmt++;
+ if (*fmt == 'l') {
+ fmt++;
+ pi->is_long_double = 1;
+ pi->is_quad = 0;
+ } else {
+ pi->is_quad = 0;
+ pi->is_long = 1;
+ }
+ continue;
+ case 't':
+ pi->is_ptrdiff = 1;
+ fmt++;
+ continue;
+ case 'z':
+ pi->is_size = 1;
+ fmt++;
+ continue;
+ default:
+ fmt++;
+ break;
+ }
+ if (printf_tbl[pi->spec].arginfo == NULL)
+ errx(1, "arginfo[%c] = NULL", pi->spec);
+ ch = printf_tbl[pi->spec].arginfo(
+ pi, __PRINTFMAXARG, &argt[nextarg]);
+ if (ch > 0)
+ pi->arg[0] = &args[nextarg];
+ if (ch > 1)
+ pi->arg[1] = &args[nextarg + 1];
+ nextarg += ch;
+ break;
+ }
+ }
+ if (nextarg > maxarg)
+ maxarg = nextarg;
+#if 0
+ fprintf(stderr, "fmt0 <%s>\n", fmt0);
+ fprintf(stderr, "pil %p\n", pil);
+#endif
+ for (ch = 1; ch < maxarg; ch++) {
+#if 0
+ fprintf(stderr, "arg %d %x\n", ch, argt[ch]);
+#endif
+ switch(argt[ch]) {
+ case PA_CHAR:
+ args[ch].intarg = (char)va_arg (ap, int);
+ break;
+ case PA_INT:
+ args[ch].intarg = va_arg (ap, int);
+ break;
+ case PA_INT | PA_FLAG_SHORT:
+ args[ch].intarg = (short)va_arg (ap, int);
+ break;
+ case PA_INT | PA_FLAG_LONG:
+ args[ch].longarg = va_arg (ap, long);
+ break;
+ case PA_INT | PA_FLAG_INTMAX:
+ args[ch].intmaxarg = va_arg (ap, intmax_t);
+ break;
+ case PA_INT | PA_FLAG_QUAD:
+ args[ch].intmaxarg = va_arg (ap, quad_t);
+ break;
+ case PA_INT | PA_FLAG_LONG_LONG:
+ args[ch].intmaxarg = va_arg (ap, long long);
+ break;
+ case PA_INT | PA_FLAG_SIZE:
+ args[ch].intmaxarg = va_arg (ap, size_t);
+ break;
+ case PA_INT | PA_FLAG_PTRDIFF:
+ args[ch].intmaxarg = va_arg (ap, ptrdiff_t);
+ break;
+ case PA_WCHAR:
+ args[ch].wintarg = va_arg (ap, wint_t);
+ break;
+ case PA_POINTER:
+ args[ch].pvoidarg = va_arg (ap, void *);
+ break;
+ case PA_STRING:
+ args[ch].pchararg = va_arg (ap, char *);
+ break;
+ case PA_WSTRING:
+ args[ch].pwchararg = va_arg (ap, wchar_t *);
+ break;
+ case PA_DOUBLE:
+#ifndef NO_FLOATING_POINT
+ args[ch].doublearg = va_arg (ap, double);
+#endif
+ break;
+ case PA_DOUBLE | PA_FLAG_LONG_DOUBLE:
+#ifndef NO_FLOATING_POINT
+ args[ch].longdoublearg = va_arg (ap, long double);
+#endif
+ break;
+ default:
+ errx(1, "argtype = %x (fmt = \"%s\")\n",
+ argt[ch], fmt0);
+ }
+ }
+ for (pi = pia; pi < pil; pi++) {
+#if 0
+ fprintf(stderr, "pi %p", pi);
+ fprintf(stderr, " spec '%c'", pi->spec);
+ fprintf(stderr, " args %d",
+ ((uintptr_t)pi->arg[0] - (uintptr_t)args) / sizeof args[0]);
+ if (pi->width) fprintf(stderr, " width %d", pi->width);
+ if (pi->pad) fprintf(stderr, " pad 0x%x", pi->pad);
+ if (pi->left) fprintf(stderr, " left");
+ if (pi->showsign) fprintf(stderr, " showsign");
+ if (pi->prec != -1) fprintf(stderr, " prec %d", pi->prec);
+ if (pi->is_char) fprintf(stderr, " char");
+ if (pi->is_short) fprintf(stderr, " short");
+ if (pi->is_long) fprintf(stderr, " long");
+ if (pi->is_long_double) fprintf(stderr, " long_double");
+ fprintf(stderr, "\n");
+ fprintf(stderr, "\t\"%.*s\"\n", pi->end - pi->begin, pi->begin);
+#endif
+ if (pi->get_width) {
+ pi->width = args[pi->get_width].intarg;
+ /*-
+ * ``A negative field width argument is taken as a
+ * - flag followed by a positive field width.''
+ * -- ANSI X3J11
+ * They don't exclude field widths read from args.
+ */
+ if (pi->width < 0) {
+ pi->left = 1;
+ pi->width = -pi->width;
+ }
+ }
+ if (pi->get_prec)
+ pi->prec = args[pi->get_prec].intarg;
+ ret += __printf_puts(&io, pi->begin, pi->end - pi->begin);
+ if (printf_tbl[pi->spec].gnurender != NULL) {
+ __printf_flush(&io);
+ pi->sofar = ret;
+ ret += printf_tbl[pi->spec].gnurender(
+ fp, pi, (const void *)pi->arg);
+ } else if (printf_tbl[pi->spec].render != NULL) {
+ pi->sofar = ret;
+ n = printf_tbl[pi->spec].render(
+ &io, pi, (const void *)pi->arg);
+ if (n < 0)
+ io.fp->_flags |= __SERR;
+ else
+ ret += n;
+ } else if (pi->begin == pi->end)
+ errx(1, "render[%c] = NULL", *fmt);
+ }
+ __printf_flush(&io);
+ return (ret);
+}
+
+extern int __fflush(FILE *fp);
+
+/*
+ * Helper function for `fprintf to unbuffered unix file': creates a
+ * temporary buffer. We only work on write-only files; this avoids
+ * worries about ungetc buffers and so forth.
+ */
+static int
+__v3printf(FILE *fp, const char *fmt, int pct, va_list ap)
+{
+ int ret;
+ FILE fake = FAKE_FILE;
+ unsigned char buf[BUFSIZ];
+
+ /* copy the important variables */
+ fake._flags = fp->_flags & ~__SNBF;
+ fake._file = fp->_file;
+ fake._cookie = fp->_cookie;
+ fake._write = fp->_write;
+ fake._orientation = fp->_orientation;
+ fake._mbstate = fp->_mbstate;
+
+ /* set up the buffer */
+ fake._bf._base = fake._p = buf;
+ fake._bf._size = fake._w = sizeof(buf);
+ fake._lbfsize = 0; /* not actually used, but Just In Case */
+
+ /* do the work, then copy any error status */
+ ret = __v2printf(&fake, fmt, pct, ap);
+ if (ret >= 0 && __fflush(&fake))
+ ret = EOF;
+ if (fake._flags & __SERR)
+ fp->_flags |= __SERR;
+ return (ret);
+}
+
+int
+__xvprintf(FILE *fp, const char *fmt0, va_list ap)
+{
+ unsigned u;
+ const char *p;
+
+ /* Count number of '%' signs handling double '%' signs */
+ for (p = fmt0, u = 0; *p; p++) {
+ if (*p != '%')
+ continue;
+ u++;
+ if (p[1] == '%')
+ p++;
+ }
+
+ /* optimise fprintf(stderr) (and other unbuffered Unix files) */
+ if ((fp->_flags & (__SNBF|__SWR|__SRW)) == (__SNBF|__SWR) &&
+ fp->_file >= 0)
+ return (__v3printf(fp, fmt0, u, ap));
+ else
+ return (__v2printf(fp, fmt0, u, ap));
+}
+
+/* extending ---------------------------------------------------------*/
+
+int
+register_printf_function(int spec, printf_function *render, printf_arginfo_function *arginfo)
+{
+
+ if (spec > 255 || spec < 0)
+ return (-1);
+ printf_tbl[spec].gnurender = render;
+ printf_tbl[spec].arginfo = arginfo;
+ __use_xprintf = 1;
+ return (0);
+}
+
+int
+register_printf_render(int spec, printf_render *render, printf_arginfo_function *arginfo)
+{
+
+ if (spec > 255 || spec < 0)
+ return (-1);
+ printf_tbl[spec].render = render;
+ printf_tbl[spec].arginfo = arginfo;
+ __use_xprintf = 1;
+ return (0);
+}
+
+int
+register_printf_render_std(const unsigned char *specs)
+{
+
+ for (; *specs != '\0'; specs++) {
+ switch (*specs) {
+ case 'H':
+ register_printf_render(*specs,
+ __printf_render_hexdump,
+ __printf_arginfo_hexdump);
+ break;
+ case 'M':
+ register_printf_render(*specs,
+ __printf_render_errno,
+ __printf_arginfo_errno);
+ break;
+ case 'Q':
+ register_printf_render(*specs,
+ __printf_render_quote,
+ __printf_arginfo_quote);
+ break;
+ case 'T':
+ register_printf_render(*specs,
+ __printf_render_time,
+ __printf_arginfo_time);
+ break;
+ case 'V':
+ register_printf_render(*specs,
+ __printf_render_vis,
+ __printf_arginfo_vis);
+ break;
+ default:
+ return (-1);
+ }
+ }
+ return (0);
+}
+
diff --git a/lib/libc/stdio/xprintf_errno.c b/lib/libc/stdio/xprintf_errno.c
new file mode 100644
index 0000000..0c2be46
--- /dev/null
+++ b/lib/libc/stdio/xprintf_errno.c
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <namespace.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <vis.h>
+#include <assert.h>
+#include <sys/time.h>
+#include "printf.h"
+
+int
+__printf_arginfo_errno(const struct printf_info *pi __unused, size_t n, int *argt)
+{
+
+ assert(n >= 1);
+ argt[0] = PA_INT;
+ return (1);
+}
+
+int
+__printf_render_errno(struct __printf_io *io, const struct printf_info *pi __unused, const void *const *arg)
+{
+ int ret, error;
+ char buf[64];
+ const char *p;
+
+ ret = 0;
+ error = *((const int *)arg[0]);
+ if (error >= 0 && error < sys_nerr) {
+ p = strerror(error);
+ return (__printf_out(io, pi, p, strlen(p)));
+ }
+ sprintf(buf, "errno=%d/0x%x", error, error);
+ ret += __printf_out(io, pi, buf, strlen(buf));
+ __printf_flush(io);
+ return(ret);
+}
diff --git a/lib/libc/stdio/xprintf_float.c b/lib/libc/stdio/xprintf_float.c
new file mode 100644
index 0000000..b719aac
--- /dev/null
+++ b/lib/libc/stdio/xprintf_float.c
@@ -0,0 +1,425 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <namespace.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <assert.h>
+#include <locale.h>
+#include <limits.h>
+
+#define dtoa __dtoa
+#define freedtoa __freedtoa
+
+#include <float.h>
+#include <math.h>
+#include "gdtoa.h"
+#include "floatio.h"
+#include "printf.h"
+#include <un-namespace.h>
+
+/*
+ * The size of the buffer we use as scratch space for integer
+ * conversions, among other things. Technically, we would need the
+ * most space for base 10 conversions with thousands' grouping
+ * characters between each pair of digits. 100 bytes is a
+ * conservative overestimate even for a 128-bit uintmax_t.
+ */
+#define BUF 100
+
+#define DEFPREC 6 /* Default FP precision */
+
+
+/* various globals ---------------------------------------------------*/
+
+
+/* padding function---------------------------------------------------*/
+
+#define PRINTANDPAD(p, ep, len, with) do { \
+ n2 = (ep) - (p); \
+ if (n2 > (len)) \
+ n2 = (len); \
+ if (n2 > 0) \
+ ret += __printf_puts(io, (p), n2); \
+ ret += __printf_pad(io, (len) - (n2 > 0 ? n2 : 0), (with)); \
+} while(0)
+
+/* misc --------------------------------------------------------------*/
+
+#define to_char(n) ((n) + '0')
+
+static int
+exponent(char *p0, int expo, int fmtch)
+{
+ char *p, *t;
+ char expbuf[MAXEXPDIG];
+
+ p = p0;
+ *p++ = fmtch;
+ if (expo < 0) {
+ expo = -expo;
+ *p++ = '-';
+ }
+ else
+ *p++ = '+';
+ t = expbuf + MAXEXPDIG;
+ if (expo > 9) {
+ do {
+ *--t = to_char(expo % 10);
+ } while ((expo /= 10) > 9);
+ *--t = to_char(expo);
+ for (; t < expbuf + MAXEXPDIG; *p++ = *t++)
+ ;
+ }
+ else {
+ /*
+ * Exponents for decimal floating point conversions
+ * (%[eEgG]) must be at least two characters long,
+ * whereas exponents for hexadecimal conversions can
+ * be only one character long.
+ */
+ if (fmtch == 'e' || fmtch == 'E')
+ *p++ = '0';
+ *p++ = to_char(expo);
+ }
+ return (p - p0);
+}
+
+/* 'f' ---------------------------------------------------------------*/
+
+int
+__printf_arginfo_float(const struct printf_info *pi, size_t n, int *argt)
+{
+ assert (n > 0);
+ argt[0] = PA_DOUBLE;
+ if (pi->is_long_double)
+ argt[0] |= PA_FLAG_LONG_DOUBLE;
+ return (1);
+}
+
+/*
+ * We can decompose the printed representation of floating
+ * point numbers into several parts, some of which may be empty:
+ *
+ * [+|-| ] [0x|0X] MMM . NNN [e|E|p|P] [+|-] ZZ
+ * A B ---C--- D E F
+ *
+ * A: 'sign' holds this value if present; '\0' otherwise
+ * B: ox[1] holds the 'x' or 'X'; '\0' if not hexadecimal
+ * C: cp points to the string MMMNNN. Leading and trailing
+ * zeros are not in the string and must be added.
+ * D: expchar holds this character; '\0' if no exponent, e.g. %f
+ * F: at least two digits for decimal, at least one digit for hex
+ */
+
+int
+__printf_render_float(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
+{
+ int prec; /* precision from format; <0 for N/A */
+ char *dtoaresult; /* buffer allocated by dtoa */
+ char expchar; /* exponent character: [eEpP\0] */
+ char *cp;
+ int expt; /* integer value of exponent */
+ int signflag; /* true if float is negative */
+ char *dtoaend; /* pointer to end of converted digits */
+ char sign; /* sign prefix (' ', '+', '-', or \0) */
+ int size; /* size of converted field or string */
+ int ndig; /* actual number of digits returned by dtoa */
+ int expsize; /* character count for expstr */
+ char expstr[MAXEXPDIG+2]; /* buffer for exponent string: e+ZZZ */
+ int nseps; /* number of group separators with ' */
+ int nrepeats; /* number of repeats of the last group */
+ const char *grouping; /* locale specific numeric grouping rules */
+ int lead; /* sig figs before decimal or group sep */
+ long double ld;
+ double d;
+ int realsz; /* field size expanded by dprec, sign, etc */
+ int dprec; /* a copy of prec if [diouxX], 0 otherwise */
+ char ox[2]; /* space for 0x; ox[1] is either x, X, or \0 */
+ int prsize; /* max size of printed field */
+ int ret; /* return value accumulator */
+ char *decimal_point; /* locale specific decimal point */
+ int n2; /* XXX: for PRINTANDPAD */
+ char thousands_sep; /* locale specific thousands separator */
+ char buf[BUF]; /* buffer with space for digits of uintmax_t */
+ const char *xdigs;
+ int flag;
+
+ prec = pi->prec;
+ ox[1] = '\0';
+ sign = pi->showsign;
+ flag = 0;
+ ret = 0;
+
+ thousands_sep = *(localeconv()->thousands_sep);
+ grouping = NULL;
+ if (pi->alt)
+ grouping = localeconv()->grouping;
+ decimal_point = localeconv()->decimal_point;
+ dprec = -1;
+
+ switch(pi->spec) {
+ case 'a':
+ case 'A':
+ if (pi->spec == 'a') {
+ ox[1] = 'x';
+ xdigs = __lowercase_hex;
+ expchar = 'p';
+ } else {
+ ox[1] = 'X';
+ xdigs = __uppercase_hex;
+ expchar = 'P';
+ }
+ if (prec >= 0)
+ prec++;
+ if (pi->is_long_double) {
+ ld = *((long double *)arg[0]);
+ dtoaresult = cp =
+ __hldtoa(ld, xdigs, prec,
+ &expt, &signflag, &dtoaend);
+ } else {
+ d = *((double *)arg[0]);
+ dtoaresult = cp =
+ __hdtoa(d, xdigs, prec,
+ &expt, &signflag, &dtoaend);
+ }
+ if (prec < 0)
+ prec = dtoaend - cp;
+ if (expt == INT_MAX)
+ ox[1] = '\0';
+ goto fp_common;
+ case 'e':
+ case 'E':
+ expchar = pi->spec;
+ if (prec < 0) /* account for digit before decpt */
+ prec = DEFPREC + 1;
+ else
+ prec++;
+ break;
+ case 'f':
+ case 'F':
+ expchar = '\0';
+ break;
+ case 'g':
+ case 'G':
+ expchar = pi->spec - ('g' - 'e');
+ if (prec == 0)
+ prec = 1;
+ break;
+ default:
+ assert(pi->spec == 'f');
+ }
+
+ if (prec < 0)
+ prec = DEFPREC;
+ if (pi->is_long_double) {
+ ld = *((long double *)arg[0]);
+ dtoaresult = cp =
+ __ldtoa(&ld, expchar ? 2 : 3, prec,
+ &expt, &signflag, &dtoaend);
+ } else {
+ d = *((double *)arg[0]);
+ dtoaresult = cp =
+ dtoa(d, expchar ? 2 : 3, prec,
+ &expt, &signflag, &dtoaend);
+ if (expt == 9999)
+ expt = INT_MAX;
+ }
+fp_common:
+ if (signflag)
+ sign = '-';
+ if (expt == INT_MAX) { /* inf or nan */
+ if (*cp == 'N') {
+ cp = (pi->spec >= 'a') ? "nan" : "NAN";
+ sign = '\0';
+ } else
+ cp = (pi->spec >= 'a') ? "inf" : "INF";
+ size = 3;
+ flag = 1;
+ goto here;
+ }
+ ndig = dtoaend - cp;
+ if (pi->spec == 'g' || pi->spec == 'G') {
+ if (expt > -4 && expt <= prec) {
+ /* Make %[gG] smell like %[fF] */
+ expchar = '\0';
+ if (pi->alt)
+ prec -= expt;
+ else
+ prec = ndig - expt;
+ if (prec < 0)
+ prec = 0;
+ } else {
+ /*
+ * Make %[gG] smell like %[eE], but
+ * trim trailing zeroes if no # flag.
+ */
+ if (!pi->alt)
+ prec = ndig;
+ }
+ }
+ if (expchar) {
+ expsize = exponent(expstr, expt - 1, expchar);
+ size = expsize + prec;
+ if (prec > 1 || pi->alt)
+ ++size;
+ } else {
+ /* space for digits before decimal point */
+ if (expt > 0)
+ size = expt;
+ else /* "0" */
+ size = 1;
+ /* space for decimal pt and following digits */
+ if (prec || pi->alt)
+ size += prec + 1;
+ if (grouping && expt > 0) {
+ /* space for thousands' grouping */
+ nseps = nrepeats = 0;
+ lead = expt;
+ while (*grouping != CHAR_MAX) {
+ if (lead <= *grouping)
+ break;
+ lead -= *grouping;
+ if (*(grouping+1)) {
+ nseps++;
+ grouping++;
+ } else
+ nrepeats++;
+ }
+ size += nseps + nrepeats;
+ } else
+ lead = expt;
+ }
+
+here:
+ /*
+ * All reasonable formats wind up here. At this point, `cp'
+ * points to a string which (if not flags&LADJUST) should be
+ * padded out to `width' places. If flags&ZEROPAD, it should
+ * first be prefixed by any sign or other prefix; otherwise,
+ * it should be blank padded before the prefix is emitted.
+ * After any left-hand padding and prefixing, emit zeroes
+ * required by a decimal [diouxX] precision, then print the
+ * string proper, then emit zeroes required by any leftover
+ * floating precision; finally, if LADJUST, pad with blanks.
+ *
+ * Compute actual size, so we know how much to pad.
+ * size excludes decimal prec; realsz includes it.
+ */
+ realsz = dprec > size ? dprec : size;
+ if (sign)
+ realsz++;
+ if (ox[1])
+ realsz += 2;
+
+ prsize = pi->width > realsz ? pi->width : realsz;
+
+ /* right-adjusting blank padding */
+ if (pi->pad != '0' && pi->left == 0)
+ ret += __printf_pad(io, pi->width - realsz, 0);
+
+ /* prefix */
+ if (sign)
+ ret += __printf_puts(io, &sign, 1);
+
+ if (ox[1]) { /* ox[1] is either x, X, or \0 */
+ ox[0] = '0';
+ ret += __printf_puts(io, ox, 2);
+ }
+
+ /* right-adjusting zero padding */
+ if (pi->pad == '0' && pi->left == 0)
+ ret += __printf_pad(io, pi->width - realsz, 1);
+
+ /* leading zeroes from decimal precision */
+ ret += __printf_pad(io, dprec - size, 1);
+
+ if (flag)
+ ret += __printf_puts(io, cp, size);
+ else {
+ /* glue together f_p fragments */
+ if (!expchar) { /* %[fF] or sufficiently short %[gG] */
+ if (expt <= 0) {
+ ret += __printf_puts(io, "0", 1);
+ if (prec || pi->alt)
+ ret += __printf_puts(io, decimal_point, 1);
+ ret += __printf_pad(io, -expt, 1);
+ /* already handled initial 0's */
+ prec += expt;
+ } else {
+ PRINTANDPAD(cp, dtoaend, lead, 1);
+ cp += lead;
+ if (grouping) {
+ while (nseps>0 || nrepeats>0) {
+ if (nrepeats > 0)
+ nrepeats--;
+ else {
+ grouping--;
+ nseps--;
+ }
+ ret += __printf_puts(io, &thousands_sep, 1);
+ PRINTANDPAD(cp,dtoaend,
+ *grouping, 1);
+ cp += *grouping;
+ }
+ if (cp > dtoaend)
+ cp = dtoaend;
+ }
+ if (prec || pi->alt)
+ ret += __printf_puts(io, decimal_point,1);
+ }
+ PRINTANDPAD(cp, dtoaend, prec, 1);
+ } else { /* %[eE] or sufficiently long %[gG] */
+ if (prec > 1 || pi->alt) {
+ buf[0] = *cp++;
+ buf[1] = *decimal_point;
+ ret += __printf_puts(io, buf, 2);
+ ret += __printf_puts(io, cp, ndig-1);
+ ret += __printf_pad(io, prec - ndig, 1);
+ } else /* XeYYY */
+ ret += __printf_puts(io, cp, 1);
+ ret += __printf_puts(io, expstr, expsize);
+ }
+ }
+ /* left-adjusting padding (always blank) */
+ if (pi->left)
+ ret += __printf_pad(io, pi->width - realsz, 0);
+
+ __printf_flush(io);
+ if (dtoaresult != NULL)
+ freedtoa(dtoaresult);
+
+ return (ret);
+}
diff --git a/lib/libc/stdio/xprintf_hexdump.c b/lib/libc/stdio/xprintf_hexdump.c
new file mode 100644
index 0000000..a2956ba
--- /dev/null
+++ b/lib/libc/stdio/xprintf_hexdump.c
@@ -0,0 +1,97 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <namespace.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <stdint.h>
+#include <assert.h>
+#include <sys/time.h>
+#include "printf.h"
+
+int
+__printf_arginfo_hexdump(const struct printf_info *pi, size_t n, int *argt)
+{
+
+ assert(n >= 2);
+ argt[0] = PA_POINTER;
+ argt[1] = PA_INT;
+ return (2);
+}
+
+int
+__printf_render_hexdump(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
+{
+ unsigned char *p;
+ unsigned u, l, j, a;
+ char buf[100], *q;
+ int ret;
+
+ if (pi->width > 0 && pi->width < 16)
+ l = pi->width;
+ else
+ l = 16;
+ p = *((unsigned char **)arg[0]);
+ u = *((unsigned *)arg[1]);
+
+ ret = 0;
+ a = 0;
+ while (u > 0) {
+ q = buf;
+ if (pi->showsign)
+ q += sprintf(q, " %04x", a);
+ for (j = 0; j < l && j < u; j++)
+ q += sprintf(q, " %02x", p[j]);
+ if (pi->alt) {
+ for (; j < l; j++)
+ q += sprintf(q, " ");
+ q += sprintf(q, " |");
+ for (j = 0; j < l && j < u; j++) {
+ if (p[j] < ' ' || p[j] > '~')
+ *q++ = '.';
+ else
+ *q++ = p[j];
+ }
+ for (; j < l; j++)
+ *q++ = ' ';
+ *q++ = '|';
+ }
+ if (l < u)
+ j = l;
+ else
+ j = u;
+ p += j;
+ u -= j;
+ a += j;
+ if (u > 0)
+ *q++ = '\n';
+ ret += __printf_puts(io, buf + 1, q - (buf + 1));
+ __printf_flush(io);
+ }
+ return (ret);
+}
diff --git a/lib/libc/stdio/xprintf_int.c b/lib/libc/stdio/xprintf_int.c
new file mode 100644
index 0000000..f006b54
--- /dev/null
+++ b/lib/libc/stdio/xprintf_int.c
@@ -0,0 +1,471 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <namespace.h>
+#include <err.h>
+#include <sys/types.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <limits.h>
+#include <locale.h>
+#include <stdint.h>
+#include <assert.h>
+#include <namespace.h>
+#include <string.h>
+#include <wchar.h>
+#include <un-namespace.h>
+
+#include "printf.h"
+
+/* private stuff -----------------------------------------------------*/
+
+union arg {
+ int intarg;
+ u_int uintarg;
+ long longarg;
+ u_long ulongarg;
+ intmax_t intmaxarg;
+ uintmax_t uintmaxarg;
+};
+
+/*
+ * Macros for converting digits to letters and vice versa
+ */
+#define to_char(n) ((n) + '0')
+
+/* various globals ---------------------------------------------------*/
+
+/*
+ * The size of the buffer we use for integer conversions.
+ * Technically, we would need the most space for base 10
+ * conversions with thousands' grouping characters between
+ * each pair of digits: 60 digits for 128 bit intmax_t.
+ * Use a bit more for better alignment of stuff.
+ */
+#define BUF 64
+
+/* misc --------------------------------------------------------------*/
+
+/*
+ * Convert an unsigned long to ASCII for printf purposes, returning
+ * a pointer to the first character of the string representation.
+ * Octal numbers can be forced to have a leading zero; hex numbers
+ * use the given digits.
+ */
+static char *
+__ultoa(u_long val, char *endp, int base, const char *xdigs,
+ int needgrp, char thousep, const char *grp)
+{
+ char *cp = endp;
+ long sval;
+ int ndig;
+
+ /*
+ * Handle the three cases separately, in the hope of getting
+ * better/faster code.
+ */
+ switch (base) {
+ case 10:
+ if (val < 10) { /* many numbers are 1 digit */
+ *--cp = to_char(val);
+ return (cp);
+ }
+ ndig = 0;
+ /*
+ * On many machines, unsigned arithmetic is harder than
+ * signed arithmetic, so we do at most one unsigned mod and
+ * divide; this is sufficient to reduce the range of
+ * the incoming value to where signed arithmetic works.
+ */
+ if (val > LONG_MAX) {
+ *--cp = to_char(val % 10);
+ ndig++;
+ sval = val / 10;
+ } else
+ sval = val;
+ do {
+ *--cp = to_char(sval % 10);
+ ndig++;
+ /*
+ * If (*grp == CHAR_MAX) then no more grouping
+ * should be performed.
+ */
+ if (needgrp && ndig == *grp && *grp != CHAR_MAX
+ && sval > 9) {
+ *--cp = thousep;
+ ndig = 0;
+ /*
+ * If (*(grp+1) == '\0') then we have to
+ * use *grp character (last grouping rule)
+ * for all next cases
+ */
+ if (*(grp+1) != '\0')
+ grp++;
+ }
+ sval /= 10;
+ } while (sval != 0);
+ break;
+
+ case 8:
+ do {
+ *--cp = to_char(val & 7);
+ val >>= 3;
+ } while (val);
+ break;
+
+ case 16:
+ do {
+ *--cp = xdigs[val & 15];
+ val >>= 4;
+ } while (val);
+ break;
+
+ default: /* oops */
+ assert(base == 16);
+ }
+ return (cp);
+}
+
+
+/* Identical to __ultoa, but for intmax_t. */
+static char *
+__ujtoa(uintmax_t val, char *endp, int base, const char *xdigs,
+ int needgrp, char thousep, const char *grp)
+{
+ char *cp = endp;
+ intmax_t sval;
+ int ndig;
+
+ switch (base) {
+ case 10:
+ if (val < 10) {
+ *--cp = to_char(val % 10);
+ return (cp);
+ }
+ ndig = 0;
+ if (val > INTMAX_MAX) {
+ *--cp = to_char(val % 10);
+ ndig++;
+ sval = val / 10;
+ } else
+ sval = val;
+ do {
+ *--cp = to_char(sval % 10);
+ ndig++;
+ /*
+ * If (*grp == CHAR_MAX) then no more grouping
+ * should be performed.
+ */
+ if (needgrp && *grp != CHAR_MAX && ndig == *grp
+ && sval > 9) {
+ *--cp = thousep;
+ ndig = 0;
+ /*
+ * If (*(grp+1) == '\0') then we have to
+ * use *grp character (last grouping rule)
+ * for all next cases
+ */
+ if (*(grp+1) != '\0')
+ grp++;
+ }
+ sval /= 10;
+ } while (sval != 0);
+ break;
+
+ case 8:
+ do {
+ *--cp = to_char(val & 7);
+ val >>= 3;
+ } while (val);
+ break;
+
+ case 16:
+ do {
+ *--cp = xdigs[val & 15];
+ val >>= 4;
+ } while (val);
+ break;
+
+ default:
+ abort();
+ }
+ return (cp);
+}
+
+
+/* 'd' ---------------------------------------------------------------*/
+
+int
+__printf_arginfo_int(const struct printf_info *pi, size_t n, int *argt)
+{
+ assert (n > 0);
+ argt[0] = PA_INT;
+ if (pi->is_ptrdiff)
+ argt[0] |= PA_FLAG_PTRDIFF;
+ else if (pi->is_size)
+ argt[0] |= PA_FLAG_SIZE;
+ else if (pi->is_long)
+ argt[0] |= PA_FLAG_LONG;
+ else if (pi->is_intmax)
+ argt[0] |= PA_FLAG_INTMAX;
+ else if (pi->is_quad)
+ argt[0] |= PA_FLAG_QUAD;
+ else if (pi->is_long_double)
+ argt[0] |= PA_FLAG_LONG_LONG;
+ else if (pi->is_short)
+ argt[0] |= PA_FLAG_SHORT;
+ else if (pi->is_char)
+ argt[0] = PA_CHAR;
+ return (1);
+}
+
+int
+__printf_render_int(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
+{
+ const union arg *argp;
+ char buf[BUF];
+ char *p, *pe;
+ char ns, l;
+ int rdx, sign, zext, ngrp;
+ const char *nalt, *digit;
+ char thousands_sep; /* locale specific thousands separator */
+ const char *grouping; /* locale specific numeric grouping rules */
+ uintmax_t uu;
+ int ret;
+
+ ret = 0;
+ nalt = NULL;
+ digit = __lowercase_hex;
+ ns = '\0';
+ pe = buf + sizeof buf - 1;
+
+ if (pi->group) {
+ thousands_sep = *(localeconv()->thousands_sep);
+ grouping = localeconv()->grouping;
+ ngrp = 1;
+ } else {
+ thousands_sep = 0;
+ grouping = NULL;
+ ngrp = 0;
+ }
+
+ switch(pi->spec) {
+ case 'd':
+ case 'i':
+ rdx = 10;
+ sign = 1;
+ break;
+ case 'X':
+ digit = __uppercase_hex;
+ /*FALLTHOUGH*/
+ case 'x':
+ rdx = 16;
+ sign = 0;
+ break;
+ case 'u':
+ case 'U':
+ rdx = 10;
+ sign = 0;
+ break;
+ case 'o':
+ case 'O':
+ rdx = 8;
+ sign = 0;
+ break;
+ default:
+ fprintf(stderr, "pi->spec = '%c'\n", pi->spec);
+ assert(1 == 0);
+ }
+ argp = arg[0];
+
+ if (sign)
+ ns = pi->showsign;
+
+ if (pi->is_long_double || pi->is_quad || pi->is_intmax ||
+ pi->is_size || pi->is_ptrdiff) {
+ if (sign && argp->intmaxarg < 0) {
+ uu = -argp->intmaxarg;
+ ns = '-';
+ } else
+ uu = argp->uintmaxarg;
+ } else if (pi->is_long) {
+ if (sign && argp->longarg < 0) {
+ uu = (u_long)-argp->longarg;
+ ns = '-';
+ } else
+ uu = argp->ulongarg;
+ } else if (pi->is_short) {
+ if (sign && (short)argp->intarg < 0) {
+ uu = -(short)argp->intarg;
+ ns = '-';
+ } else
+ uu = (unsigned short)argp->uintarg;
+ } else if (pi->is_char) {
+ if (sign && (signed char)argp->intarg < 0) {
+ uu = -(signed char)argp->intarg;
+ ns = '-';
+ } else
+ uu = (unsigned char)argp->uintarg;
+ } else {
+ if (sign && argp->intarg < 0) {
+ uu = (unsigned)-argp->intarg;
+ ns = '-';
+ } else
+ uu = argp->uintarg;
+ }
+ if (uu <= ULONG_MAX)
+ p = __ultoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
+ else
+ p = __ujtoa(uu, pe, rdx, digit, ngrp, thousands_sep, grouping);
+
+ l = 0;
+ if (uu == 0) {
+ /*-
+ * ``The result of converting a zero value with an
+ * explicit precision of zero is no characters.''
+ * -- ANSI X3J11
+ *
+ * ``The C Standard is clear enough as is. The call
+ * printf("%#.0o", 0) should print 0.''
+ * -- Defect Report #151
+ */
+ ;
+ if (pi->prec == 0 && !(pi->alt && rdx == 8))
+ p = pe;
+ } else if (pi->alt) {
+ if (rdx == 8)
+ *--p = '0';
+ if (rdx == 16) {
+ if (pi->spec == 'x')
+ nalt = "0x";
+ else
+ nalt = "0X";
+ l += 2;
+ }
+ }
+ l += pe - p;
+ if (ns)
+ l++;
+
+ /*-
+ * ``... diouXx conversions ... if a precision is
+ * specified, the 0 flag will be ignored.''
+ * -- ANSI X3J11
+ */
+ if (pi->prec > (pe - p))
+ zext = pi->prec - (pe - p);
+ else if (pi->prec != -1)
+ zext = 0;
+ else if (pi->pad == '0' && pi->width > l && !pi->left)
+ zext = pi->width - l;
+ else
+ zext = 0;
+
+ l += zext;
+
+ while (zext > 0 && p > buf) {
+ *--p = '0';
+ zext--;
+ }
+
+ if (l < BUF) {
+ if (ns) {
+ *--p = ns;
+ } else if (nalt != NULL) {
+ *--p = nalt[1];
+ *--p = nalt[0];
+ }
+ if (pi->width > (pe - p) && !pi->left) {
+ l = pi->width - (pe - p);
+ while (l > 0 && p > buf) {
+ *--p = ' ';
+ l--;
+ }
+ if (l)
+ ret += __printf_pad(io, l, 0);
+ }
+ } else {
+ if (!pi->left && pi->width > l)
+ ret += __printf_pad(io, pi->width - l, 0);
+ if (ns != '\0')
+ ret += __printf_puts(io, &ns, 1);
+ else if (nalt != NULL)
+ ret += __printf_puts(io, nalt, 2);
+ if (zext > 0)
+ ret += __printf_pad(io, zext, 1);
+ }
+
+ ret += __printf_puts(io, p, pe - p);
+ if (pi->width > ret && pi->left)
+ ret += __printf_pad(io, pi->width - ret, 0);
+ __printf_flush(io);
+ return (ret);
+}
+
+/* 'p' ---------------------------------------------------------------*/
+
+int
+__printf_arginfo_ptr(const struct printf_info *pi __unused, size_t n, int *argt)
+{
+
+ assert (n > 0);
+ argt[0] = PA_POINTER;
+ return (1);
+}
+
+int
+__printf_render_ptr(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
+{
+ struct printf_info p2;
+ uintmax_t u;
+ const void *p;
+
+ /*-
+ * ``The argument shall be a pointer to void. The
+ * value of the pointer is converted to a sequence
+ * of printable characters, in an implementation-
+ * defined manner.''
+ * -- ANSI X3J11
+ */
+ u = (uintmax_t)(uintptr_t) *((void **)arg[0]);
+ p2 = *pi;
+
+ p2.spec = 'x';
+ p2.alt = 1;
+ p2.is_long_double = 1;
+ p = &u;
+ return (__printf_render_int(io, &p2, &p));
+}
diff --git a/lib/libc/stdio/xprintf_quote.c b/lib/libc/stdio/xprintf_quote.c
new file mode 100644
index 0000000..0edcd30
--- /dev/null
+++ b/lib/libc/stdio/xprintf_quote.c
@@ -0,0 +1,98 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <namespace.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include <wchar.h>
+#include <vis.h>
+#include <assert.h>
+#include <sys/time.h>
+#include "printf.h"
+
+int
+__printf_arginfo_quote(const struct printf_info *pi __unused, size_t n, int *argt)
+{
+
+ assert(n >= 1);
+ argt[0] = PA_POINTER;
+ return (1);
+}
+
+int
+__printf_render_quote(struct __printf_io *io, const struct printf_info *pi __unused, const void *const *arg)
+{
+ const char *str, *p, *t, *o;
+ char r[5];
+ int i, ret;
+
+ str = *((const char *const *)arg[0]);
+ if (str == NULL)
+ return (__printf_out(io, pi, "\"(null)\"", 8));
+ if (*str == '\0')
+ return (__printf_out(io, pi, "\"\"", 2));
+
+ for (i = 0, p = str; *p; p++)
+ if (isspace(*p) || *p == '\\' || *p == '"')
+ i++;
+ if (!i)
+ return (__printf_out(io, pi, str, strlen(str)));
+
+ ret = __printf_out(io, pi, "\"", 1);
+ for (t = p = str; *p; p++) {
+ o = NULL;
+ if (*p == '\\')
+ o = "\\\\";
+ else if (*p == '\n')
+ o = "\\n";
+ else if (*p == '\r')
+ o = "\\r";
+ else if (*p == '\t')
+ o = "\\t";
+ else if (*p == ' ')
+ o = " ";
+ else if (*p == '"')
+ o = "\\\"";
+ else if (isspace(*p)) {
+ sprintf(r, "\\%03o", *p);
+ o = r;
+ } else
+ continue;
+ if (p != t)
+ ret += __printf_out(io, pi, t, p - t);
+ ret += __printf_out(io, pi, o, strlen(o));
+ t = p + 1;
+ }
+ if (p != t)
+ ret += __printf_out(io, pi, t, p - t);
+ ret += __printf_out(io, pi, "\"", 1);
+ __printf_flush(io);
+ return(ret);
+}
diff --git a/lib/libc/stdio/xprintf_str.c b/lib/libc/stdio/xprintf_str.c
new file mode 100644
index 0000000..d46fa85
--- /dev/null
+++ b/lib/libc/stdio/xprintf_str.c
@@ -0,0 +1,187 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <namespace.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+#include <stdint.h>
+#include <assert.h>
+#include <wchar.h>
+#include "printf.h"
+
+/*
+ * Convert a wide character string argument for the %ls format to a multibyte
+ * string representation. If not -1, prec specifies the maximum number of
+ * bytes to output, and also means that we can't assume that the wide char.
+ * string ends is null-terminated.
+ */
+static char *
+__wcsconv(wchar_t *wcsarg, int prec)
+{
+ static const mbstate_t initial;
+ mbstate_t mbs;
+ char buf[MB_LEN_MAX];
+ wchar_t *p;
+ char *convbuf;
+ size_t clen, nbytes;
+
+ /* Allocate space for the maximum number of bytes we could output. */
+ if (prec < 0) {
+ p = wcsarg;
+ mbs = initial;
+ nbytes = wcsrtombs(NULL, (const wchar_t **)&p, 0, &mbs);
+ if (nbytes == (size_t)-1)
+ return (NULL);
+ } else {
+ /*
+ * Optimisation: if the output precision is small enough,
+ * just allocate enough memory for the maximum instead of
+ * scanning the string.
+ */
+ if (prec < 128)
+ nbytes = prec;
+ else {
+ nbytes = 0;
+ p = wcsarg;
+ mbs = initial;
+ for (;;) {
+ clen = wcrtomb(buf, *p++, &mbs);
+ if (clen == 0 || clen == (size_t)-1 ||
+ (int)(nbytes + clen) > prec)
+ break;
+ nbytes += clen;
+ }
+ }
+ }
+ if ((convbuf = malloc(nbytes + 1)) == NULL)
+ return (NULL);
+
+ /* Fill the output buffer. */
+ p = wcsarg;
+ mbs = initial;
+ if ((nbytes = wcsrtombs(convbuf, (const wchar_t **)&p,
+ nbytes, &mbs)) == (size_t)-1) {
+ free(convbuf);
+ return (NULL);
+ }
+ convbuf[nbytes] = '\0';
+ return (convbuf);
+}
+
+
+/* 's' ---------------------------------------------------------------*/
+
+int
+__printf_arginfo_str(const struct printf_info *pi, size_t n, int *argt)
+{
+
+ assert (n > 0);
+ if (pi->is_long || pi->spec == 'C')
+ argt[0] = PA_WSTRING;
+ else
+ argt[0] = PA_STRING;
+ return (1);
+}
+
+int
+__printf_render_str(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
+{
+ const char *p;
+ wchar_t *wcp;
+ char *convbuf;
+ int l;
+
+ if (pi->is_long || pi->spec == 'S') {
+ wcp = *((wint_t **)arg[0]);
+ if (wcp == NULL)
+ return (__printf_out(io, pi, "(null)", 6));
+ convbuf = __wcsconv(wcp, pi->prec);
+ if (convbuf == NULL)
+ return (-1);
+ l = __printf_out(io, pi, convbuf, strlen(convbuf));
+ free(convbuf);
+ return (l);
+ }
+ p = *((char **)arg[0]);
+ if (p == NULL)
+ return (__printf_out(io, pi, "(null)", 6));
+ l = strlen(p);
+ if (pi->prec >= 0 && pi->prec < l)
+ l = pi->prec;
+ return (__printf_out(io, pi, p, l));
+}
+
+/* 'c' ---------------------------------------------------------------*/
+
+int
+__printf_arginfo_chr(const struct printf_info *pi, size_t n, int *argt)
+{
+
+ assert (n > 0);
+ if (pi->is_long || pi->spec == 'C')
+ argt[0] = PA_WCHAR;
+ else
+ argt[0] = PA_INT;
+ return (1);
+}
+
+int
+__printf_render_chr(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
+{
+ int i;
+ wint_t ii;
+ unsigned char c;
+ static const mbstate_t initial; /* XXX: this is bogus! */
+ mbstate_t mbs;
+ size_t mbseqlen;
+ char buf[MB_CUR_MAX];
+
+ if (pi->is_long || pi->spec == 'C') {
+ ii = *((wint_t *)arg[0]);
+
+ mbs = initial;
+ mbseqlen = wcrtomb(buf, (wchar_t)ii, &mbs);
+ if (mbseqlen == (size_t) -1)
+ return (-1);
+ return (__printf_out(io, pi, buf, mbseqlen));
+ }
+ i = *((int *)arg[0]);
+ c = i;
+ i = __printf_out(io, pi, &c, 1);
+ __printf_flush(io);
+ return (i);
+}
diff --git a/lib/libc/stdio/xprintf_time.c b/lib/libc/stdio/xprintf_time.c
new file mode 100644
index 0000000..debfac5
--- /dev/null
+++ b/lib/libc/stdio/xprintf_time.c
@@ -0,0 +1,122 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+#include <namespace.h>
+#include <stdio.h>
+#include <wchar.h>
+#include <stdint.h>
+#include <assert.h>
+#include <sys/time.h>
+#include "printf.h"
+
+int
+__printf_arginfo_time(const struct printf_info *pi, size_t n, int *argt)
+{
+
+ assert(n >= 1);
+ argt[0] = PA_POINTER;
+ return (1);
+}
+#define MINUTE 60
+#define HOUR (60 * MINUTE)
+#define DAY (24 * HOUR)
+#define YEAR (365 * DAY)
+
+int
+__printf_render_time(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
+{
+ char buf[100];
+ char *p;
+ struct timeval *tv;
+ struct timespec *ts;
+ time_t *tp;
+ intmax_t t, tx;
+ int i, prec, nsec, ret;
+
+ if (pi->is_long) {
+ tv = *((struct timeval **)arg[0]);
+ t = tv->tv_sec;
+ nsec = tv->tv_usec * 1000;
+ prec = 6;
+ } else if (pi->is_long_double) {
+ ts = *((struct timespec **)arg[0]);
+ t = ts->tv_sec;
+ nsec = ts->tv_nsec;
+ prec = 9;
+ } else {
+ tp = *((time_t **)arg[0]);
+ t = *tp;
+ nsec = 0;
+ prec = 0;
+ }
+ if (pi->is_long || pi->is_long_double) {
+ if (pi->prec >= 0)
+ prec = pi->prec;
+ if (prec == 0)
+ nsec = 0;
+ }
+
+ p = buf;
+ if (pi->alt) {
+ tx = t;
+ if (t >= YEAR) {
+ p += sprintf(p, "%jdy", t / YEAR);
+ t %= YEAR;
+ }
+ if (tx >= DAY && (t != 0 || prec != 0)) {
+ p += sprintf(p, "%jdd", t / DAY);
+ t %= DAY;
+ }
+ if (tx >= HOUR && (t != 0 || prec != 0)) {
+ p += sprintf(p, "%jdh", t / HOUR);
+ t %= HOUR;
+ }
+ if (tx >= MINUTE && (t != 0 || prec != 0)) {
+ p += sprintf(p, "%jdm", t / MINUTE);
+ t %= MINUTE;
+ }
+ if (t != 0 || tx == 0 || prec != 0)
+ p += sprintf(p, "%jds", t);
+ } else {
+ p += sprintf(p, "%jd", (intmax_t)t);
+ }
+ if (prec != 0) {
+ for (i = prec; i < 9; i++)
+ nsec /= 10;
+ p += sprintf(p, ".%.*d", prec, nsec);
+ }
+ ret = __printf_out(io, pi, buf, p - buf);
+ __printf_flush(io);
+ return (ret);
+}
diff --git a/lib/libc/stdio/xprintf_vis.c b/lib/libc/stdio/xprintf_vis.c
new file mode 100644
index 0000000..819f09f
--- /dev/null
+++ b/lib/libc/stdio/xprintf_vis.c
@@ -0,0 +1,78 @@
+/*-
+ * Copyright (c) 2005 Poul-Henning Kamp
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <namespace.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <wchar.h>
+#include <vis.h>
+#include <assert.h>
+#include <sys/time.h>
+#include "printf.h"
+
+int
+__printf_arginfo_vis(const struct printf_info *pi, size_t n, int *argt)
+{
+
+ assert(n >= 1);
+ argt[0] = PA_POINTER;
+ return (1);
+}
+
+int
+__printf_render_vis(struct __printf_io *io, const struct printf_info *pi, const void *const *arg)
+{
+ char *p, *buf;
+ unsigned l;
+ int ret;
+
+ ret = 0;
+ p = *((char **)arg[0]);
+ if (p == NULL)
+ return (__printf_out(io, pi, "(null)", 6));
+ if (pi->prec >= 0)
+ l = pi->prec;
+ else
+ l = strlen(p);
+ buf = malloc(l * 4 + 1);
+ if (buf == NULL)
+ return (-1);
+ if (pi->showsign)
+ ret = strvisx(buf, p, l, VIS_WHITE | VIS_HTTPSTYLE);
+ else if (pi->pad == '0')
+ ret = strvisx(buf, p, l, VIS_WHITE | VIS_OCTAL);
+ else if (pi->alt)
+ ret = strvisx(buf, p, l, VIS_WHITE);
+ else
+ ret = strvisx(buf, p, l, VIS_WHITE | VIS_CSTYLE | VIS_OCTAL);
+ ret += __printf_out(io, pi, buf, ret);
+ __printf_flush(io);
+ free(buf);
+ return(ret);
+}
diff --git a/lib/libc/stdlib/Makefile.inc b/lib/libc/stdlib/Makefile.inc
new file mode 100644
index 0000000..7fdb6e4
--- /dev/null
+++ b/lib/libc/stdlib/Makefile.inc
@@ -0,0 +1,48 @@
+# from @(#)Makefile.inc 8.3 (Berkeley) 2/4/95
+# $FreeBSD$
+
+# machine-independent stdlib sources
+.PATH: ${.CURDIR}/${LIBC_ARCH}/stdlib ${.CURDIR}/stdlib
+
+MISRCS+=_Exit.c a64l.c abort.c abs.c atexit.c atof.c atoi.c atol.c atoll.c \
+ bsearch.c div.c exit.c getenv.c getopt.c getopt_long.c \
+ getsubopt.c hcreate.c heapsort.c imaxabs.c imaxdiv.c \
+ insque.c l64a.c labs.c ldiv.c llabs.c lldiv.c lsearch.c \
+ merge.c ptsname.c qsort.c qsort_r.c quick_exit.c radixsort.c rand.c \
+ random.c reallocf.c realpath.c remque.c strfmon.c strtoimax.c \
+ strtol.c strtoll.c strtoq.c strtoul.c strtonum.c strtoull.c \
+ strtoumax.c strtouq.c system.c tdelete.c tfind.c tsearch.c twalk.c
+
+SYM_MAPS+= ${.CURDIR}/stdlib/Symbol.map
+
+# machine-dependent stdlib sources
+.sinclude "${.CURDIR}/${LIBC_ARCH}/stdlib/Makefile.inc"
+
+MAN+= a64l.3 abort.3 abs.3 alloca.3 atexit.3 atof.3 \
+ atoi.3 atol.3 at_quick_exit.3 bsearch.3 \
+ div.3 exit.3 getenv.3 getopt.3 getopt_long.3 getsubopt.3 \
+ hcreate.3 imaxabs.3 imaxdiv.3 insque.3 labs.3 ldiv.3 llabs.3 lldiv.3 \
+ lsearch.3 memory.3 ptsname.3 qsort.3 \
+ quick_exit.3 \
+ radixsort.3 rand.3 random.3 reallocf.3 \
+ realpath.3 strfmon.3 strtod.3 strtol.3 strtonum.3 strtoul.3 system.3 \
+ tsearch.3
+
+MLINKS+=a64l.3 l64a.3 a64l.3 l64a_r.3
+MLINKS+=atol.3 atoll.3
+MLINKS+=exit.3 _Exit.3
+MLINKS+=getenv.3 putenv.3 getenv.3 setenv.3 getenv.3 unsetenv.3
+MLINKS+=getopt_long.3 getopt_long_only.3
+MLINKS+=hcreate.3 hdestroy.3 hcreate.3 hsearch.3
+MLINKS+=insque.3 remque.3
+MLINKS+=lsearch.3 lfind.3
+MLINKS+=ptsname.3 grantpt.3 ptsname.3 unlockpt.3
+MLINKS+=qsort.3 heapsort.3 qsort.3 mergesort.3 qsort.3 qsort_r.3
+MLINKS+=rand.3 rand_r.3 rand.3 srand.3 rand.3 sranddev.3
+MLINKS+=random.3 initstate.3 random.3 setstate.3 random.3 srandom.3 \
+ random.3 srandomdev.3
+MLINKS+=radixsort.3 sradixsort.3
+MLINKS+=strtod.3 strtof.3 strtod.3 strtold.3
+MLINKS+=strtol.3 strtoll.3 strtol.3 strtoq.3 strtol.3 strtoimax.3
+MLINKS+=strtoul.3 strtoull.3 strtoul.3 strtouq.3 strtoul.3 strtoumax.3
+MLINKS+=tsearch.3 tdelete.3 tsearch.3 tfind.3 tsearch.3 twalk.3
diff --git a/lib/libc/stdlib/Symbol.map b/lib/libc/stdlib/Symbol.map
new file mode 100644
index 0000000..6a1798f
--- /dev/null
+++ b/lib/libc/stdlib/Symbol.map
@@ -0,0 +1,110 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ _Exit;
+ a64l;
+ abort;
+ abs;
+ atexit;
+ __cxa_atexit;
+ __cxa_finalize;
+ atof;
+ atoi;
+ atol;
+ atoll;
+ bsearch;
+ div;
+ __isthreaded;
+ exit;
+ getenv;
+ opterr;
+ optind;
+ optopt;
+ optreset;
+ optarg;
+ getopt;
+ getopt_long;
+ getopt_long_only;
+ suboptarg;
+ getsubopt;
+ grantpt;
+ ptsname;
+ unlockpt;
+ hcreate;
+ hdestroy;
+ hsearch;
+ heapsort;
+ imaxabs;
+ imaxdiv;
+ insque;
+ l64a;
+ l64a_r;
+ labs;
+ ldiv;
+ llabs;
+ lldiv;
+ lsearch;
+ lfind;
+ mergesort;
+ putenv;
+ qsort_r;
+ qsort;
+ radixsort;
+ sradixsort;
+ rand_r;
+ rand;
+ srand;
+ sranddev;
+ srandom;
+ srandomdev;
+ initstate;
+ setstate;
+ random;
+ reallocf;
+ realpath;
+ remque;
+ setenv;
+ unsetenv;
+ strfmon;
+ strtoimax;
+ strtol;
+ strtoll;
+ strtonum;
+ strtoq;
+ strtoul;
+ strtoull;
+ strtoumax;
+ strtouq;
+ system;
+ tdelete;
+ tfind;
+ tsearch;
+ twalk;
+};
+
+FBSD_1.3 {
+ at_quick_exit;
+ atof_l;
+ atoi_l;
+ atol_l;
+ atoll_l;
+ quick_exit;
+ strtod_l;
+ strtof_l;
+ strtoimax_l;
+ strtol_l;
+ strtold_l;
+ strtoll_l;
+ strtoq_l;
+ strtoul_l;
+ strtoull_l;
+ strtoumax_l;
+ strtouq_l;
+};
+
+FBSDprivate_1.0 {
+ __system;
+ _system;
+};
diff --git a/lib/libc/stdlib/_Exit.c b/lib/libc/stdlib/_Exit.c
new file mode 100644
index 0000000..e7f0f51
--- /dev/null
+++ b/lib/libc/stdlib/_Exit.c
@@ -0,0 +1,22 @@
+/*
+ * This file is in the public domain. Written by Garrett A. Wollman,
+ * 2002-09-07.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdlib.h>
+#include <unistd.h>
+
+/*
+ * ISO C99 added this function to provide for Standard C applications
+ * which needed something like POSIX _exit(). A new interface was created
+ * in case it turned out that _exit() was insufficient to meet the
+ * requirements of ISO C. (That's probably not the case, but here
+ * is where you would put the extra code if it were.)
+ */
+void
+_Exit(int code)
+{
+ _exit(code);
+}
diff --git a/lib/libc/stdlib/a64l.3 b/lib/libc/stdlib/a64l.3
new file mode 100644
index 0000000..61fbffd
--- /dev/null
+++ b/lib/libc/stdlib/a64l.3
@@ -0,0 +1,187 @@
+.\" Copyright (c) 2005 Tom Rhodes
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" Portions of this text are reprinted and reproduced in electronic form
+.\" from IEEE Std 1003.1, 2004 Edition, Standard for Information Technology --
+.\" Portable Operating System Interface (POSIX), The Open Group Base
+.\" Specifications Issue 6, Copyright (C) 2001-2004 by the Institute of
+.\" Electrical and Electronics Engineers, Inc and The Open Group. In the
+.\" event of any discrepancy between this version and the original IEEE and
+.\" The Open Group Standard, the original IEEE and The Open Group Standard is
+.\" the referee document. The original Standard can be obtained online at
+.\" http://www.opengroup.org/unix/online.html.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 20, 2005
+.Dt A64L 3
+.Os
+.Sh NAME
+.Nm a64l ,
+.Nm l64a ,
+.Nm l64a_r
+.Nd "convert between a long integer and a base-64 ASCII string"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft long
+.Fn a64l "const char *s"
+.Ft char *
+.Fn l64a "long int l"
+.Ft int
+.Fn l64a_r "long int l" "char *buffer" "int buflen"
+.Sh DESCRIPTION
+These functions are used to maintain numbers stored in radix-64
+.Tn ASCII
+characters.
+This is a notation by which 32-bit integers can be represented by
+up to six characters; each character represents a digit in
+radix-64 notation.
+If the type long contains more than 32 bits, only the low-order
+32 bits are used for these operations.
+.Pp
+The characters used to represent
+.Dq digits
+are
+.Ql .\&
+for 0,
+.Ql /
+for 1,
+.Ql 0
+-
+.Ql 9
+for 2 - 11,
+.Ql A
+-
+.Ql Z
+for 12 - 37, and
+.Ql a
+-
+.Ql z
+for 38 - 63.
+.Pp
+The
+.Fn a64l
+function takes a pointer to a radix-64 representation, in which the first
+digit is the least significant, and returns a corresponding
+.Vt long
+value.
+If the string pointed to by
+.Fa s
+contains more than six characters,
+.Fn a64l
+uses the first six.
+If the first six characters of the string contain a null terminator,
+.Fn a64l
+uses only characters preceding the null terminator.
+The
+.Fn a64l
+function scans the character string from left to right with the least
+significant digit on the left, decoding each character as a 6-bit
+radix-64 number.
+If the type long contains more than 32 bits, the resulting value is
+sign-extended.
+The behavior of
+.Fn a64l
+is unspecified if
+.Fa s
+is a null pointer or the string pointed to by
+.Fa s
+was not generated by a previous call to
+.Fn l64a .
+.Pp
+The
+.Fn l64a
+function takes a
+.Vt long
+argument and returns a pointer to the corresponding
+radix-64 representation.
+The behavior of
+.Fn l64a
+is unspecified if value is negative.
+.Pp
+The value returned by
+.Fn l64a
+is a pointer into a static buffer.
+Subsequent calls to
+.Fn l64a
+may overwrite the buffer.
+.Pp
+The
+.Fn l64a_r
+function performs a conversion identical to that of
+.Fn l64a
+and stores the resulting representation in the memory area pointed to by
+.Fa buffer ,
+consuming at most
+.Fa buflen
+characters including the terminating
+.Dv NUL
+character.
+.Sh RETURN VALUES
+On successful completion,
+.Fn a64l
+returns the
+.Vt long
+value resulting from conversion of the input string.
+If a string pointed to by
+.Fa s
+is an empty string,
+.Fn a64l
+returns 0.
+.Pp
+The
+.Fn l64a
+function returns a pointer to the radix-64 representation.
+If value is 0,
+.Fn l64a
+returns a pointer to an empty string.
+.Sh SEE ALSO
+.Xr strtoul 3
+.Sh HISTORY
+The
+.Fn a64l ,
+.Fn l64a ,
+and
+.Fn l64a_r
+functions are derived from
+.Nx
+with modifications.
+They appeared in
+.Fx 6.1 .
+.Sh AUTHORS
+The
+.Fn a64l ,
+.Fn l64a ,
+and
+.Fn l64a_r
+functions
+were added to
+.Fx
+by
+.An Tom Rhodes Aq trhodes@FreeBSD.org .
+Almost all of this manual page came from the
+.Tn POSIX
+standard.
diff --git a/lib/libc/stdlib/a64l.c b/lib/libc/stdlib/a64l.c
new file mode 100644
index 0000000..a130dcb
--- /dev/null
+++ b/lib/libc/stdlib/a64l.c
@@ -0,0 +1,46 @@
+/*-
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: a64l.c,v 1.8 2000/01/22 22:19:19 mycroft Exp $");
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <inttypes.h>
+
+#define ADOT 46 /* ASCII '.' */
+#define ASLASH 47 /* ASCII '/' */
+#define A0 48 /* ASCII '0' */
+#define AA 65 /* ASCII 'A' */
+#define Aa 97 /* ASCII 'a' */
+
+long
+a64l(const char *s)
+{
+ long shift;
+ int digit, i, value;
+
+ value = 0;
+ shift = 0;
+ for (i = 0; *s != '\0' && i < 6; i++, s++) {
+ if (*s <= ASLASH)
+ digit = *s - ASLASH + 1;
+ else if (*s <= A0 + 9)
+ digit = *s - A0 + 2;
+ else if (*s <= AA + 25)
+ digit = *s - AA + 12;
+ else
+ digit = *s - Aa + 38;
+
+ value |= digit << shift;
+ shift += 6;
+ }
+ return (value);
+}
diff --git a/lib/libc/stdlib/abort.3 b/lib/libc/stdlib/abort.3
new file mode 100644
index 0000000..b939e9c2
--- /dev/null
+++ b/lib/libc/stdlib/abort.3
@@ -0,0 +1,79 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)abort.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt ABORT 3
+.Os
+.Sh NAME
+.Nm abort
+.Nd cause abnormal program termination
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft void
+.Fn abort void
+.Sh DESCRIPTION
+The
+.Fn abort
+function causes abnormal program termination to occur, unless the
+signal
+.Dv SIGABRT
+is being caught and the signal handler does not return.
+.Pp
+Any open streams are flushed and closed.
+.Sh IMPLEMENTATION NOTES
+The
+.Fn abort
+function is thread-safe.
+It is unknown if it is async-cancel-safe.
+.Sh RETURN VALUES
+The
+.Fn abort
+function
+never returns.
+.Sh SEE ALSO
+.Xr sigaction 2 ,
+.Xr exit 3
+.Sh STANDARDS
+The
+.Fn abort
+function
+conforms to
+.St -p1003.1-90 .
+The
+.Fn abort
+function also conforms to
+.St -isoC-99
+with the implementation specific details as noted above.
diff --git a/lib/libc/stdlib/abort.c b/lib/libc/stdlib/abort.c
new file mode 100644
index 0000000..eba53e5
--- /dev/null
+++ b/lib/libc/stdlib/abort.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)abort.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <signal.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <pthread.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+void
+abort()
+{
+ struct sigaction act;
+
+ /*
+ * POSIX requires we flush stdio buffers on abort.
+ * XXX ISO C requires that abort() be async-signal-safe.
+ */
+ if (__cleanup)
+ (*__cleanup)();
+
+ sigfillset(&act.sa_mask);
+ /*
+ * Don't block SIGABRT to give any handler a chance; we ignore
+ * any errors -- ISO C doesn't allow abort to return anyway.
+ */
+ sigdelset(&act.sa_mask, SIGABRT);
+ (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
+ (void)raise(SIGABRT);
+
+ /*
+ * If SIGABRT was ignored, or caught and the handler returns, do
+ * it again, only harder.
+ */
+ act.sa_handler = SIG_DFL;
+ act.sa_flags = 0;
+ sigfillset(&act.sa_mask);
+ (void)_sigaction(SIGABRT, &act, NULL);
+ sigdelset(&act.sa_mask, SIGABRT);
+ (void)_sigprocmask(SIG_SETMASK, &act.sa_mask, NULL);
+ (void)raise(SIGABRT);
+ exit(1);
+}
diff --git a/lib/libc/stdlib/abs.3 b/lib/libc/stdlib/abs.3
new file mode 100644
index 0000000..4f02122
--- /dev/null
+++ b/lib/libc/stdlib/abs.3
@@ -0,0 +1,75 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)abs.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd November 14, 2001
+.Dt ABS 3
+.Os
+.Sh NAME
+.Nm abs
+.Nd integer absolute value function
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fn abs "int j"
+.Sh DESCRIPTION
+The
+.Fn abs
+function
+computes
+the absolute value of the integer
+.Fa j .
+.Sh RETURN VALUES
+The
+.Fn abs
+function
+returns
+the absolute value.
+.Sh SEE ALSO
+.Xr cabs 3 ,
+.Xr fabs 3 ,
+.Xr floor 3 ,
+.Xr hypot 3 ,
+.Xr imaxabs 3 ,
+.Xr labs 3 ,
+.Xr llabs 3 ,
+.Xr math 3
+.Sh STANDARDS
+The
+.Fn abs
+function conforms to
+.St -isoC-99 .
+.Sh BUGS
+The absolute value of the most negative integer remains negative.
diff --git a/lib/libc/stdlib/abs.c b/lib/libc/stdlib/abs.c
new file mode 100644
index 0000000..5ca9596
--- /dev/null
+++ b/lib/libc/stdlib/abs.c
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)abs.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+
+int
+abs(j)
+ int j;
+{
+ return(j < 0 ? -j : j);
+}
diff --git a/lib/libc/stdlib/alloca.3 b/lib/libc/stdlib/alloca.3
new file mode 100644
index 0000000..9559444
--- /dev/null
+++ b/lib/libc/stdlib/alloca.3
@@ -0,0 +1,88 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)alloca.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd September 5, 2006
+.Dt ALLOCA 3
+.Os
+.Sh NAME
+.Nm alloca
+.Nd memory allocator
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft void *
+.Fn alloca "size_t size"
+.Sh DESCRIPTION
+The
+.Fn alloca
+function
+allocates
+.Fa size
+bytes of space in the stack frame of the caller.
+This temporary space is automatically freed on
+return.
+.Sh RETURN VALUES
+The
+.Fn alloca
+function returns a pointer to the beginning of the allocated space.
+.Sh SEE ALSO
+.Xr brk 2 ,
+.Xr calloc 3 ,
+.Xr getpagesize 3 ,
+.Xr malloc 3 ,
+.Xr realloc 3
+.Sh HISTORY
+The
+.Fn alloca
+function appeared in
+.At 32v .
+.\" .Bx ?? .
+.\" The function appeared in 32v, pwb and pwb.2 and in 3bsd 4bsd
+.\" The first man page (or link to a man page that I can find at the
+.\" moment is 4.3...
+.Sh BUGS
+The
+.Fn alloca
+function
+is machine and compiler dependent;
+its use is discouraged.
+.Pp
+The
+.Fn alloca
+function is slightly unsafe because it cannot ensure that the pointer
+returned points to a valid and usable block of memory.
+The allocation made may exceed the bounds of the stack, or even go
+further into other objects in memory, and
+.Fn alloca
+cannot determine such an error.
+Avoid
+.Fn alloca
+with large unbounded allocations.
diff --git a/lib/libc/stdlib/at_quick_exit.3 b/lib/libc/stdlib/at_quick_exit.3
new file mode 100644
index 0000000..a75c0c0
--- /dev/null
+++ b/lib/libc/stdlib/at_quick_exit.3
@@ -0,0 +1,61 @@
+.\" Copyright (c) 2011 David Chisnall
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 7, 2011
+.Dt AT_QUICK_EXIT 3
+.Os
+.Sh NAME
+.Nm at_quick_exit
+.Nd registers a cleanup function to run on quick exit
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fn at_quick_exit "void (*func)(void)"
+.Sh DESCRIPTION
+The
+.Fn at_quick_exit
+function registers a cleanup function to be called when the program exits as a
+result of calling
+.Xr quick_exit 3 .
+The cleanup functions are called in the reverse order and will not be called if
+the program exits by calling
+.Xr exit 3 ,
+.Xr _Exit 3 ,
+or
+.Xr abort 3 .
+.Sh RETURN VALUES
+The
+.Fn at_quick_exit
+function returns the value 0 if successful and a non-zero value on failure.
+.Sh SEE ALSO
+.Xr exit 3 ,
+.Xr quick_exit 3
+.Sh STANDARDS
+The
+.Fn at_quick_exit
+function conforms to the C1x draft specification.
diff --git a/lib/libc/stdlib/atexit.3 b/lib/libc/stdlib/atexit.3
new file mode 100644
index 0000000..3a514b9
--- /dev/null
+++ b/lib/libc/stdlib/atexit.3
@@ -0,0 +1,89 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)atexit.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd September 6, 2002
+.Dt ATEXIT 3
+.Os
+.Sh NAME
+.Nm atexit
+.Nd register a function to be called on exit
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fn atexit "void (*function)(void)"
+.Sh DESCRIPTION
+The
+.Fn atexit
+function
+registers the given
+.Fa function
+to be called at program exit, whether via
+.Xr exit 3
+or via return from the program's
+.Fn main .
+Functions so registered are called in reverse order;
+no arguments are passed.
+.Pp
+These functions must not call
+.Fn exit ;
+if it should be necessary to terminate the process while in such a
+function, the
+.Xr _exit 2
+function should be used.
+(Alternatively, the function may cause abnormal
+process termination, for example by calling
+.Xr abort 3 . )
+.Pp
+At least 32 functions can always be registered,
+and more are allowed as long as sufficient memory can be allocated.
+.\" XXX {ATEXIT_MAX} is not implemented yet
+.Sh RETURN VALUES
+.Rv -std atexit
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+No memory was available to add the function to the list.
+The existing list of functions is unmodified.
+.El
+.Sh SEE ALSO
+.Xr at_quick_exit 3
+.Xr exit 3
+.Sh STANDARDS
+The
+.Fn atexit
+function
+conforms to
+.St -isoC .
diff --git a/lib/libc/stdlib/atexit.c b/lib/libc/stdlib/atexit.c
new file mode 100644
index 0000000..511172a
--- /dev/null
+++ b/lib/libc/stdlib/atexit.c
@@ -0,0 +1,205 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)atexit.c 8.2 (Berkeley) 7/3/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <link.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <pthread.h>
+#include "atexit.h"
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+#define ATEXIT_FN_EMPTY 0
+#define ATEXIT_FN_STD 1
+#define ATEXIT_FN_CXA 2
+
+static pthread_mutex_t atexit_mutex = PTHREAD_MUTEX_INITIALIZER;
+
+#define _MUTEX_LOCK(x) if (__isthreaded) _pthread_mutex_lock(x)
+#define _MUTEX_UNLOCK(x) if (__isthreaded) _pthread_mutex_unlock(x)
+#define _MUTEX_DESTROY(x) if (__isthreaded) _pthread_mutex_destroy(x)
+
+struct atexit {
+ struct atexit *next; /* next in list */
+ int ind; /* next index in this table */
+ struct atexit_fn {
+ int fn_type; /* ATEXIT_? from above */
+ union {
+ void (*std_func)(void);
+ void (*cxa_func)(void *);
+ } fn_ptr; /* function pointer */
+ void *fn_arg; /* argument for CXA callback */
+ void *fn_dso; /* shared module handle */
+ } fns[ATEXIT_SIZE]; /* the table itself */
+};
+
+static struct atexit *__atexit; /* points to head of LIFO stack */
+
+/*
+ * Register the function described by 'fptr' to be called at application
+ * exit or owning shared object unload time. This is a helper function
+ * for atexit and __cxa_atexit.
+ */
+static int
+atexit_register(struct atexit_fn *fptr)
+{
+ static struct atexit __atexit0; /* one guaranteed table */
+ struct atexit *p;
+
+ _MUTEX_LOCK(&atexit_mutex);
+ if ((p = __atexit) == NULL)
+ __atexit = p = &__atexit0;
+ else while (p->ind >= ATEXIT_SIZE) {
+ struct atexit *old__atexit;
+ old__atexit = __atexit;
+ _MUTEX_UNLOCK(&atexit_mutex);
+ if ((p = (struct atexit *)malloc(sizeof(*p))) == NULL)
+ return (-1);
+ _MUTEX_LOCK(&atexit_mutex);
+ if (old__atexit != __atexit) {
+ /* Lost race, retry operation */
+ _MUTEX_UNLOCK(&atexit_mutex);
+ free(p);
+ _MUTEX_LOCK(&atexit_mutex);
+ p = __atexit;
+ continue;
+ }
+ p->ind = 0;
+ p->next = __atexit;
+ __atexit = p;
+ }
+ p->fns[p->ind++] = *fptr;
+ _MUTEX_UNLOCK(&atexit_mutex);
+ return 0;
+}
+
+/*
+ * Register a function to be performed at exit.
+ */
+int
+atexit(void (*func)(void))
+{
+ struct atexit_fn fn;
+ int error;
+
+ fn.fn_type = ATEXIT_FN_STD;
+ fn.fn_ptr.std_func = func;
+ fn.fn_arg = NULL;
+ fn.fn_dso = NULL;
+
+ error = atexit_register(&fn);
+ return (error);
+}
+
+/*
+ * Register a function to be performed at exit or when an shared object
+ * with given dso handle is unloaded dynamically.
+ */
+int
+__cxa_atexit(void (*func)(void *), void *arg, void *dso)
+{
+ struct atexit_fn fn;
+ int error;
+
+ fn.fn_type = ATEXIT_FN_CXA;
+ fn.fn_ptr.cxa_func = func;
+ fn.fn_arg = arg;
+ fn.fn_dso = dso;
+
+ error = atexit_register(&fn);
+ return (error);
+}
+
+#pragma weak __pthread_cxa_finalize
+void __pthread_cxa_finalize(const struct dl_phdr_info *);
+
+/*
+ * Call all handlers registered with __cxa_atexit for the shared
+ * object owning 'dso'. Note: if 'dso' is NULL, then all remaining
+ * handlers are called.
+ */
+void
+__cxa_finalize(void *dso)
+{
+ struct dl_phdr_info phdr_info;
+ struct atexit *p;
+ struct atexit_fn fn;
+ int n, has_phdr;
+
+ if (dso != NULL)
+ has_phdr = _rtld_addr_phdr(dso, &phdr_info);
+ else
+ has_phdr = 0;
+
+ _MUTEX_LOCK(&atexit_mutex);
+ for (p = __atexit; p; p = p->next) {
+ for (n = p->ind; --n >= 0;) {
+ if (p->fns[n].fn_type == ATEXIT_FN_EMPTY)
+ continue; /* already been called */
+ fn = p->fns[n];
+ if (dso != NULL && dso != fn.fn_dso) {
+ /* wrong DSO ? */
+ if (!has_phdr || !__elf_phdr_match_addr(
+ &phdr_info, fn.fn_ptr.cxa_func))
+ continue;
+ }
+ /*
+ Mark entry to indicate that this particular handler
+ has already been called.
+ */
+ p->fns[n].fn_type = ATEXIT_FN_EMPTY;
+ _MUTEX_UNLOCK(&atexit_mutex);
+
+ /* Call the function of correct type. */
+ if (fn.fn_type == ATEXIT_FN_CXA)
+ fn.fn_ptr.cxa_func(fn.fn_arg);
+ else if (fn.fn_type == ATEXIT_FN_STD)
+ fn.fn_ptr.std_func();
+ _MUTEX_LOCK(&atexit_mutex);
+ }
+ }
+ _MUTEX_UNLOCK(&atexit_mutex);
+ if (dso == NULL)
+ _MUTEX_DESTROY(&atexit_mutex);
+
+ if (has_phdr && &__pthread_cxa_finalize != NULL)
+ __pthread_cxa_finalize(&phdr_info);
+}
diff --git a/lib/libc/stdlib/atexit.h b/lib/libc/stdlib/atexit.h
new file mode 100644
index 0000000..f34194f
--- /dev/null
+++ b/lib/libc/stdlib/atexit.h
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)atexit.h 8.2 (Berkeley) 7/3/94
+ * $FreeBSD$
+ */
+
+/* must be at least 32 to guarantee ANSI conformance */
+#define ATEXIT_SIZE 32
+
+void __cxa_finalize(void *dso);
diff --git a/lib/libc/stdlib/atof.3 b/lib/libc/stdlib/atof.3
new file mode 100644
index 0000000..abf5b7c
--- /dev/null
+++ b/lib/libc/stdlib/atof.3
@@ -0,0 +1,95 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)atof.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt ATOF 3
+.Os
+.Sh NAME
+.Nm atof
+.Nd convert
+.Tn ASCII
+string to double
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft double
+.Fn atof "const char *nptr"
+.Sh DESCRIPTION
+The
+.Fn atof
+function converts the initial portion of the string pointed to by
+.Fa nptr
+to
+.Vt double
+representation.
+.Pp
+It is equivalent to:
+.Bd -literal -offset indent
+strtod(nptr, (char **)NULL);
+.Ed
+.Pp
+The decimal point
+character is defined in the program's locale (category
+.Dv LC_NUMERIC ) .
+.Sh IMPLEMENTATION NOTES
+The
+.Fn atof
+function is not thread-safe and also not async-cancel-safe.
+.Pp
+The
+.Fn atof
+function has been deprecated by
+.Fn strtod
+and should not be used in new code.
+.Sh ERRORS
+The function
+.Fn atof
+need not affect the value of
+.Va errno
+on an error.
+.Sh SEE ALSO
+.Xr atoi 3 ,
+.Xr atol 3 ,
+.Xr strtod 3 ,
+.Xr strtol 3 ,
+.Xr strtoul 3
+.Sh STANDARDS
+The
+.Fn atof
+function conforms to
+.St -p1003.1-90 ,
+.St -isoC ,
+and
+.St -isoC-99 .
diff --git a/lib/libc/stdlib/atof.c b/lib/libc/stdlib/atof.c
new file mode 100644
index 0000000..746ceac
--- /dev/null
+++ b/lib/libc/stdlib/atof.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)atof.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <xlocale.h>
+
+double
+atof(ascii)
+ const char *ascii;
+{
+ return strtod(ascii, (char **)NULL);
+}
+
+double
+atof_l(ascii, locale)
+ const char *ascii;
+ locale_t locale;
+{
+ return strtod_l(ascii, (char **)NULL, locale);
+}
diff --git a/lib/libc/stdlib/atoi.3 b/lib/libc/stdlib/atoi.3
new file mode 100644
index 0000000..b0d1d38
--- /dev/null
+++ b/lib/libc/stdlib/atoi.3
@@ -0,0 +1,87 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)atoi.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt ATOI 3
+.Os
+.Sh NAME
+.Nm atoi
+.Nd convert
+.Tn ASCII
+string to integer
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fn atoi "const char *nptr"
+.Sh DESCRIPTION
+The
+.Fn atoi
+function converts the initial portion of the string pointed to by
+.Fa nptr
+to
+.Vt int
+representation.
+.Pp
+It is equivalent to:
+.Bd -literal -offset indent
+(int)strtol(nptr, (char **)NULL, 10);
+.Ed
+.Pp
+The
+.Fn atoi
+function has been deprecated by
+.Fn strtol
+and should not be used in new code.
+.Sh ERRORS
+The function
+.Fn atoi
+need not affect the value of
+.Va errno
+on an error.
+.Sh SEE ALSO
+.Xr atof 3 ,
+.Xr atol 3 ,
+.Xr strtod 3 ,
+.Xr strtol 3 ,
+.Xr strtoul 3
+.Sh STANDARDS
+The
+.Fn atoi
+function conforms to
+.St -p1003.1-90 ,
+.St -isoC ,
+and
+.St -isoC-99 .
diff --git a/lib/libc/stdlib/atoi.c b/lib/libc/stdlib/atoi.c
new file mode 100644
index 0000000..31a8676
--- /dev/null
+++ b/lib/libc/stdlib/atoi.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)atoi.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <xlocale.h>
+
+int
+atoi(str)
+ const char *str;
+{
+ return (int)strtol(str, (char **)NULL, 10);
+}
+
+int
+atoi_l(str, locale)
+ const char *str;
+ locale_t locale;
+{
+ return (int)strtol_l(str, (char **)NULL, 10, locale);
+}
diff --git a/lib/libc/stdlib/atol.3 b/lib/libc/stdlib/atol.3
new file mode 100644
index 0000000..cc49fe2
--- /dev/null
+++ b/lib/libc/stdlib/atol.3
@@ -0,0 +1,135 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)atol.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd February 1, 2009
+.Dt ATOL 3
+.Os
+.Sh NAME
+.Nm atol , atoll
+.Nd convert
+.Tn ASCII
+string to
+.Vt long
+or
+.Vt "long long"
+integer
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft long
+.Fn atol "const char *nptr"
+.Ft "long long"
+.Fn atoll "const char *nptr"
+.Sh DESCRIPTION
+The
+.Fn atol
+function converts the initial portion of the string pointed to by
+.Fa nptr
+to
+.Vt long
+integer
+representation.
+.Pp
+It is equivalent to:
+.Pp
+.Dl "strtol(nptr, (char **)NULL, 10);"
+.Pp
+The
+.Fn atoll
+function converts the initial portion of the string pointed to by
+.Fa nptr
+to
+.Vt "long long"
+integer
+representation.
+.Pp
+It is equivalent to:
+.Pp
+.Dl "strtoll(nptr, (char **)NULL, 10);"
+.Sh COMPATIBILITY
+The
+.Fx
+implementations of the
+.Fn atol
+and
+.Fn atoll
+functions are thin wrappers around
+.Fn strtol
+and
+.Fn stroll
+respectively, so these functions will affect the value of
+.Va errno
+in the same way that the
+.Fn strtol
+and
+.Fn stroll
+functions are able to.
+This behavior of
+.Fn atol
+and
+.Fn atoll
+is not required by
+.St -isoC
+or
+.St -isoC-99 ,
+but it is allowed by all of
+.St -isoC , St -isoC-99
+and
+.St -p1003.1-2001 .
+.Sh ERRORS
+The functions
+.Fn atol
+and
+.Fn atoll
+may affect the value of
+.Va errno
+on an error.
+.Sh SEE ALSO
+.Xr atof 3 ,
+.Xr atoi 3 ,
+.Xr strtod 3 ,
+.Xr strtol 3 ,
+.Xr strtoul 3
+.Sh STANDARDS
+The
+.Fn atol
+function
+conforms to
+.St -isoC .
+The
+.Fn atoll
+function
+conforms to
+.St -isoC-99 .
diff --git a/lib/libc/stdlib/atol.c b/lib/libc/stdlib/atol.c
new file mode 100644
index 0000000..7ebbe01
--- /dev/null
+++ b/lib/libc/stdlib/atol.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)atol.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <xlocale.h>
+
+long
+atol(str)
+ const char *str;
+{
+ return strtol(str, (char **)NULL, 10);
+}
+
+long
+atol_l(str, locale)
+ const char *str;
+ locale_t locale;
+{
+ return strtol_l(str, (char **)NULL, 10, locale);
+}
diff --git a/lib/libc/stdlib/atoll.c b/lib/libc/stdlib/atoll.c
new file mode 100644
index 0000000..cbb5459
--- /dev/null
+++ b/lib/libc/stdlib/atoll.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <xlocale.h>
+
+long long
+atoll(str)
+ const char *str;
+{
+ return strtoll(str, (char **)NULL, 10);
+}
+
+long long
+atoll_l(str, locale)
+ const char *str;
+ locale_t locale;
+{
+ return strtoll_l(str, (char **)NULL, 10, locale);
+}
diff --git a/lib/libc/stdlib/bsearch.3 b/lib/libc/stdlib/bsearch.3
new file mode 100644
index 0000000..b3591f8e
--- /dev/null
+++ b/lib/libc/stdlib/bsearch.3
@@ -0,0 +1,89 @@
+.\" Copyright (c) 1990, 1991, 1993, 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)bsearch.3 8.3 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd April 19, 1994
+.Dt BSEARCH 3
+.Os
+.Sh NAME
+.Nm bsearch
+.Nd binary search of a sorted table
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft void *
+.Fn bsearch "const void *key" "const void *base" "size_t nmemb" "size_t size" "int (*compar) (const void *, const void *)"
+.Sh DESCRIPTION
+The
+.Fn bsearch
+function searches an array of
+.Fa nmemb
+objects, the initial member of which is
+pointed to by
+.Fa base ,
+for a member that matches the object pointed to by
+.Fa key .
+The size of each member of the array is specified by
+.Fa size .
+.Pp
+The contents of the array should be in ascending sorted order according
+to the comparison function referenced by
+.Fa compar .
+The
+.Fa compar
+routine
+is expected to have
+two arguments which point to the
+.Fa key
+object and to an array member, in that order, and should return an integer
+less than, equal to, or greater than zero if the
+.Fa key
+object is found, respectively, to be less than, to match, or be
+greater than the array member.
+.Sh RETURN VALUES
+The
+.Fn bsearch
+function returns a pointer to a matching member of the array, or a null
+pointer if no match is found.
+If two members compare as equal, which member is matched is unspecified.
+.Sh SEE ALSO
+.Xr db 3 ,
+.Xr lsearch 3 ,
+.Xr qsort 3
+.\" .Xr tsearch 3
+.Sh STANDARDS
+The
+.Fn bsearch
+function conforms to
+.St -isoC .
diff --git a/lib/libc/stdlib/bsearch.c b/lib/libc/stdlib/bsearch.c
new file mode 100644
index 0000000..ff02168
--- /dev/null
+++ b/lib/libc/stdlib/bsearch.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bsearch.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stddef.h>
+#include <stdlib.h>
+
+/*
+ * Perform a binary search.
+ *
+ * The code below is a bit sneaky. After a comparison fails, we
+ * divide the work in half by moving either left or right. If lim
+ * is odd, moving left simply involves halving lim: e.g., when lim
+ * is 5 we look at item 2, so we change lim to 2 so that we will
+ * look at items 0 & 1. If lim is even, the same applies. If lim
+ * is odd, moving right again involes halving lim, this time moving
+ * the base up one item past p: e.g., when lim is 5 we change base
+ * to item 3 and make lim 2 so that we will look at items 3 and 4.
+ * If lim is even, however, we have to shrink it by one before
+ * halving: e.g., when lim is 4, we still looked at item 2, so we
+ * have to make lim 3, then halve, obtaining 1, so that we will only
+ * look at item 3.
+ */
+void *
+bsearch(key, base0, nmemb, size, compar)
+ const void *key;
+ const void *base0;
+ size_t nmemb;
+ size_t size;
+ int (*compar)(const void *, const void *);
+{
+ const char *base = base0;
+ size_t lim;
+ int cmp;
+ const void *p;
+
+ for (lim = nmemb; lim != 0; lim >>= 1) {
+ p = base + (lim >> 1) * size;
+ cmp = (*compar)(key, p);
+ if (cmp == 0)
+ return ((void *)p);
+ if (cmp > 0) { /* key > p: move right */
+ base = (char *)p + size;
+ lim--;
+ } /* else move left */
+ }
+ return (NULL);
+}
diff --git a/lib/libc/stdlib/div.3 b/lib/libc/stdlib/div.3
new file mode 100644
index 0000000..46a145f
--- /dev/null
+++ b/lib/libc/stdlib/div.3
@@ -0,0 +1,68 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)div.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd November 14, 2001
+.Dt DIV 3
+.Os
+.Sh NAME
+.Nm div
+.Nd return quotient and remainder from division
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft div_t
+.Fn div "int num" "int denom"
+.Sh DESCRIPTION
+The
+.Fn div
+function
+computes the value
+.Fa num/denom
+and returns the quotient and remainder in a structure named
+.Fa div_t
+that contains two
+.Vt int
+members named
+.Va quot
+and
+.Va rem .
+.Sh SEE ALSO
+.Xr imaxdiv 3 ,
+.Xr ldiv 3 ,
+.Xr lldiv 3
+.Sh STANDARDS
+The
+.Fn div
+function
+conforms to
+.St -isoC-99 .
diff --git a/lib/libc/stdlib/div.c b/lib/libc/stdlib/div.c
new file mode 100644
index 0000000..ef93d73
--- /dev/null
+++ b/lib/libc/stdlib/div.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)div.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h> /* div_t */
+
+div_t
+div(num, denom)
+ int num, denom;
+{
+ div_t r;
+
+ r.quot = num / denom;
+ r.rem = num % denom;
+ /*
+ * The ANSI standard says that |r.quot| <= |n/d|, where
+ * n/d is to be computed in infinite precision. In other
+ * words, we should always truncate the quotient towards
+ * 0, never -infinity.
+ *
+ * Machine division and remainer may work either way when
+ * one or both of n or d is negative. If only one is
+ * negative and r.quot has been truncated towards -inf,
+ * r.rem will have the same sign as denom and the opposite
+ * sign of num; if both are negative and r.quot has been
+ * truncated towards -inf, r.rem will be positive (will
+ * have the opposite sign of num). These are considered
+ * `wrong'.
+ *
+ * If both are num and denom are positive, r will always
+ * be positive.
+ *
+ * This all boils down to:
+ * if num >= 0, but r.rem < 0, we got the wrong answer.
+ * In that case, to get the right answer, add 1 to r.quot and
+ * subtract denom from r.rem.
+ */
+ if (num >= 0 && r.rem < 0) {
+ r.quot++;
+ r.rem -= denom;
+ }
+ return (r);
+}
diff --git a/lib/libc/stdlib/exit.3 b/lib/libc/stdlib/exit.3
new file mode 100644
index 0000000..4547efe
--- /dev/null
+++ b/lib/libc/stdlib/exit.3
@@ -0,0 +1,132 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)exit.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd September 9, 2002
+.Dt EXIT 3
+.Os
+.Sh NAME
+.Nm exit , _Exit
+.Nd perform normal program termination
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft void
+.Fn exit "int status"
+.Ft void
+.Fn _Exit "int status"
+.Sh DESCRIPTION
+The
+.Fn exit
+and
+.Fn _Exit
+functions terminate a process.
+.Pp
+Before termination,
+.Fn exit
+performs the following functions in the order listed:
+.Bl -enum -offset indent
+.It
+Call the functions registered with the
+.Xr atexit 3
+function, in the reverse order of their registration.
+.It
+Flush all open output streams.
+.It
+Close all open streams.
+.It
+Unlink all files created with the
+.Xr tmpfile 3
+function.
+.El
+.Pp
+The
+.Fn _Exit
+function terminates without calling the functions registered with the
+.Xr atexit 3
+function, and may or may not perform the other actions listed.
+Both functions make the low-order eight bits of the
+.Fa status
+argument available to a parent process which has called a
+.Xr wait 2 Ns -family
+function.
+.Pp
+The C Standard
+.Pq St -isoC-99
+defines the values
+.Li 0 ,
+.Dv EXIT_SUCCESS ,
+and
+.Dv EXIT_FAILURE
+as possible values of
+.Fa status .
+Cooperating processes may use other values;
+in a program which might be called by a mail transfer agent, the
+values described in
+.Xr sysexits 3
+may be used to provide more information to the parent process.
+.Pp
+Note that
+.Fn exit
+does nothing to prevent bottomless recursion should a function registered
+using
+.Xr atexit 3
+itself call
+.Fn exit .
+Such functions must call
+.Fn _Exit
+instead (although this has other effects as well which may not be desired).
+.Sh RETURN VALUES
+The
+.Fn exit
+and
+.Fn _Exit
+functions
+never return.
+.Sh SEE ALSO
+.Xr _exit 2 ,
+.Xr wait 2 ,
+.Xr atexit 3 ,
+.Xr at_quick_exit 3 ,
+.Xr intro 3 ,
+.Xr quick_exit 3 ,
+.Xr sysexits 3 ,
+.Xr tmpfile 3
+.Sh STANDARDS
+The
+.Fn exit
+and
+.Fn _Exit
+functions conform to
+.St -isoC-99 .
diff --git a/lib/libc/stdlib/exit.c b/lib/libc/stdlib/exit.c
new file mode 100644
index 0000000..26c346a
--- /dev/null
+++ b/lib/libc/stdlib/exit.c
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)exit.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdlib.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "atexit.h"
+#include "libc_private.h"
+
+void (*__cleanup)(void);
+
+/*
+ * This variable is zero until a process has created a thread.
+ * It is used to avoid calling locking functions in libc when they
+ * are not required. By default, libc is intended to be(come)
+ * thread-safe, but without a (significant) penalty to non-threaded
+ * processes.
+ */
+int __isthreaded = 0;
+
+/*
+ * Exit, flushing stdio buffers if necessary.
+ */
+void
+exit(status)
+ int status;
+{
+ /* Ensure that the auto-initialization routine is linked in: */
+ extern int _thread_autoinit_dummy_decl;
+
+ _thread_autoinit_dummy_decl = 1;
+
+ __cxa_finalize(NULL);
+ if (__cleanup)
+ (*__cleanup)();
+ _exit(status);
+}
diff --git a/lib/libc/stdlib/getenv.3 b/lib/libc/stdlib/getenv.3
new file mode 100644
index 0000000..bc87b9d
--- /dev/null
+++ b/lib/libc/stdlib/getenv.3
@@ -0,0 +1,229 @@
+.\" Copyright (c) 1988, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getenv.3 8.2 (Berkeley) 12/11/93
+.\" $FreeBSD$
+.\"
+.Dd June 20, 2007
+.Dt GETENV 3
+.Os
+.Sh NAME
+.Nm getenv ,
+.Nm putenv ,
+.Nm setenv ,
+.Nm unsetenv
+.Nd environment variable functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft char *
+.Fn getenv "const char *name"
+.Ft int
+.Fn setenv "const char *name" "const char *value" "int overwrite"
+.Ft int
+.Fn putenv "char *string"
+.Ft int
+.Fn unsetenv "const char *name"
+.Sh DESCRIPTION
+These functions set, unset and fetch environment variables from the
+host
+.Em environment list .
+.Pp
+The
+.Fn getenv
+function obtains the current value of the environment variable,
+.Fa name .
+The application should not modify the string pointed
+to by the
+.Fn getenv
+function.
+.Pp
+The
+.Fn setenv
+function inserts or resets the environment variable
+.Fa name
+in the current environment list.
+If the variable
+.Fa name
+does not exist in the list,
+it is inserted with the given
+.Fa value .
+If the variable does exist, the argument
+.Fa overwrite
+is tested; if
+.Fa overwrite
+is zero, the
+variable is not reset, otherwise it is reset
+to the given
+.Fa value .
+.Pp
+The
+.Fn putenv
+function takes an argument of the form ``name=value'' and
+puts it directly into the current environment,
+so altering the argument shall change the environment.
+If the variable
+.Fa name
+does not exist in the list,
+it is inserted with the given
+.Fa value .
+If the variable
+.Fa name
+does exist, it is reset to the given
+.Fa value .
+.Pp
+The
+.Fn unsetenv
+function
+deletes all instances of the variable name pointed to by
+.Fa name
+from the list.
+.Pp
+If corruption (e.g., a name without a value) is detected while making a copy of
+environ for internal usage, then
+.Fn setenv ,
+.Fn unsetenv
+and
+.Fn putenv
+will output a warning to stderr about the issue, drop the corrupt entry and
+complete the task without error.
+.Sh RETURN VALUES
+The
+.Fn getenv
+function returns the value of the environment variable as a
+.Dv NUL Ns
+-terminated string.
+If the variable
+.Fa name
+is not in the current environment,
+.Dv NULL
+is returned.
+.Pp
+.Rv -std setenv putenv unsetenv
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The function
+.Fn getenv ,
+.Fn setenv
+or
+.Fn unsetenv
+failed because the
+.Fa name
+is a
+.Dv NULL
+pointer, points to an empty string, or points to a string containing an
+.Dq Li \&=
+character.
+.Pp
+The function
+.Fn putenv
+failed because
+.Fa string
+is a
+.Dv NULL
+pointer,
+.Fa string is without an
+.Dq Li \&=
+character or
+.Dq Li \&=
+is the first character in
+.Fa string .
+This does not follow the
+.Tn POSIX
+specification.
+.It Bq Er ENOMEM
+The function
+.Fn setenv ,
+.Fn unsetenv
+or
+.Fn putenv
+failed because they were unable to allocate memory for the environment.
+.El
+.Sh SEE ALSO
+.Xr csh 1 ,
+.Xr sh 1 ,
+.Xr execve 2 ,
+.Xr environ 7
+.Sh STANDARDS
+The
+.Fn getenv
+function conforms to
+.St -isoC .
+The
+.Fn setenv ,
+.Fn putenv
+and
+.Fn unsetenv
+functions conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The functions
+.Fn setenv
+and
+.Fn unsetenv
+appeared in
+.At v7 .
+The
+.Fn putenv
+function appeared in
+.Bx 4.3 Reno .
+.Pp
+Until
+.Fx 7.0 ,
+.Fn putenv
+would make a copy of
+.Fa string
+and insert it into the environment using
+.Fn setenv .
+This was changed to use
+.Fa string
+as the memory location of the ``name=value'' pair to follow the
+.Tn POSIX
+specification.
+.Sh BUGS
+Successive calls to
+.Fn setenv
+that assign a larger-sized
+.Fa value
+than any previous value to the same
+.Fa name
+will result in a memory leak.
+The
+.Fx
+semantics for this function
+(namely, that the contents of
+.Fa value
+are copied and that old values remain accessible indefinitely) make this
+bug unavoidable.
+Future versions may eliminate one or both of these
+semantic guarantees in order to fix the bug.
diff --git a/lib/libc/stdlib/getenv.c b/lib/libc/stdlib/getenv.c
new file mode 100644
index 0000000..b7826d7
--- /dev/null
+++ b/lib/libc/stdlib/getenv.c
@@ -0,0 +1,686 @@
+/*-
+ * Copyright (c) 2007-2009 Sean C. Farley <scf@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer,
+ * without modification, immediately at the beginning of the file.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <errno.h>
+#include <stdbool.h>
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+
+static const char CorruptEnvFindMsg[] = "environment corrupt; unable to find ";
+static const char CorruptEnvValueMsg[] =
+ "environment corrupt; missing value for ";
+
+
+/*
+ * Standard environ. environ variable is exposed to entire process.
+ *
+ * origEnviron: Upon cleanup on unloading of library or failure, this
+ * allows environ to return to as it was before.
+ * environSize: Number of variables environ can hold. Can only
+ * increase.
+ * intEnviron: Internally-built environ. Exposed via environ during
+ * (re)builds of the environment.
+ */
+extern char **environ;
+static char **origEnviron;
+static char **intEnviron = NULL;
+static int environSize = 0;
+
+/*
+ * Array of environment variables built from environ. Each element records:
+ * name: Pointer to name=value string
+ * name length: Length of name not counting '=' character
+ * value: Pointer to value within same string as name
+ * value size: Size (not length) of space for value not counting the
+ * nul character
+ * active state: true/false value to signify whether variable is active.
+ * Useful since multiple variables with the same name can
+ * co-exist. At most, one variable can be active at any
+ * one time.
+ * putenv: Created from putenv() call. This memory must not be
+ * reused.
+ */
+static struct envVars {
+ size_t nameLen;
+ size_t valueSize;
+ char *name;
+ char *value;
+ bool active;
+ bool putenv;
+} *envVars = NULL;
+
+/*
+ * Environment array information.
+ *
+ * envActive: Number of active variables in array.
+ * envVarsSize: Size of array.
+ * envVarsTotal: Number of total variables in array (active or not).
+ */
+static int envActive = 0;
+static int envVarsSize = 0;
+static int envVarsTotal = 0;
+
+
+/* Deinitialization of new environment. */
+static void __attribute__ ((destructor)) __clean_env_destructor(void);
+
+
+/*
+ * A simple version of warnx() to avoid the bloat of including stdio in static
+ * binaries.
+ */
+static void
+__env_warnx(const char *msg, const char *name, size_t nameLen)
+{
+ static const char nl[] = "\n";
+ static const char progSep[] = ": ";
+
+ _write(STDERR_FILENO, _getprogname(), strlen(_getprogname()));
+ _write(STDERR_FILENO, progSep, sizeof(progSep) - 1);
+ _write(STDERR_FILENO, msg, strlen(msg));
+ _write(STDERR_FILENO, name, nameLen);
+ _write(STDERR_FILENO, nl, sizeof(nl) - 1);
+
+ return;
+}
+
+
+/*
+ * Inline strlen() for performance. Also, perform check for an equals sign.
+ * Cheaper here than peforming a strchr() later.
+ */
+static inline size_t
+__strleneq(const char *str)
+{
+ const char *s;
+
+ for (s = str; *s != '\0'; ++s)
+ if (*s == '=')
+ return (0);
+
+ return (s - str);
+}
+
+
+/*
+ * Comparison of an environment name=value to a name.
+ */
+static inline bool
+strncmpeq(const char *nameValue, const char *name, size_t nameLen)
+{
+ if (strncmp(nameValue, name, nameLen) == 0 && nameValue[nameLen] == '=')
+ return (true);
+
+ return (false);
+}
+
+
+/*
+ * Using environment, returns pointer to value associated with name, if any,
+ * else NULL. If the onlyActive flag is set to true, only variables that are
+ * active are returned else all are.
+ */
+static inline char *
+__findenv(const char *name, size_t nameLen, int *envNdx, bool onlyActive)
+{
+ int ndx;
+
+ /*
+ * Find environment variable from end of array (more likely to be
+ * active). A variable created by putenv is always active, or it is not
+ * tracked in the array.
+ */
+ for (ndx = *envNdx; ndx >= 0; ndx--)
+ if (envVars[ndx].putenv) {
+ if (strncmpeq(envVars[ndx].name, name, nameLen)) {
+ *envNdx = ndx;
+ return (envVars[ndx].name + nameLen +
+ sizeof ("=") - 1);
+ }
+ } else if ((!onlyActive || envVars[ndx].active) &&
+ (envVars[ndx].nameLen == nameLen &&
+ strncmpeq(envVars[ndx].name, name, nameLen))) {
+ *envNdx = ndx;
+ return (envVars[ndx].value);
+ }
+
+ return (NULL);
+}
+
+
+/*
+ * Using environ, returns pointer to value associated with name, if any, else
+ * NULL. Used on the original environ passed into the program.
+ */
+static char *
+__findenv_environ(const char *name, size_t nameLen)
+{
+ int envNdx;
+
+ /* Find variable within environ. */
+ for (envNdx = 0; environ[envNdx] != NULL; envNdx++)
+ if (strncmpeq(environ[envNdx], name, nameLen))
+ return (&(environ[envNdx][nameLen + sizeof("=") - 1]));
+
+ return (NULL);
+}
+
+
+/*
+ * Remove variable added by putenv() from variable tracking array.
+ */
+static void
+__remove_putenv(int envNdx)
+{
+ envVarsTotal--;
+ if (envVarsTotal > envNdx)
+ memmove(&(envVars[envNdx]), &(envVars[envNdx + 1]),
+ (envVarsTotal - envNdx) * sizeof (*envVars));
+ memset(&(envVars[envVarsTotal]), 0, sizeof (*envVars));
+
+ return;
+}
+
+
+/*
+ * Deallocate the environment built from environ as well as environ then set
+ * both to NULL. Eases debugging of memory leaks.
+ */
+static void
+__clean_env(bool freeVars)
+{
+ int envNdx;
+
+ /* Deallocate environment and environ if created by *env(). */
+ if (envVars != NULL) {
+ for (envNdx = envVarsTotal - 1; envNdx >= 0; envNdx--)
+ /* Free variables or deactivate them. */
+ if (envVars[envNdx].putenv) {
+ if (!freeVars)
+ __remove_putenv(envNdx);
+ } else {
+ if (freeVars)
+ free(envVars[envNdx].name);
+ else
+ envVars[envNdx].active = false;
+ }
+ if (freeVars) {
+ free(envVars);
+ envVars = NULL;
+ } else
+ envActive = 0;
+
+ /* Restore original environ if it has not updated by program. */
+ if (origEnviron != NULL) {
+ if (environ == intEnviron)
+ environ = origEnviron;
+ free(intEnviron);
+ intEnviron = NULL;
+ environSize = 0;
+ }
+ }
+
+ return;
+}
+
+
+/*
+ * Using the environment, rebuild the environ array for use by other C library
+ * calls that depend upon it.
+ */
+static int
+__rebuild_environ(int newEnvironSize)
+{
+ char **tmpEnviron;
+ int envNdx;
+ int environNdx;
+ int tmpEnvironSize;
+
+ /* Resize environ. */
+ if (newEnvironSize > environSize) {
+ tmpEnvironSize = newEnvironSize * 2;
+ tmpEnviron = realloc(intEnviron, sizeof (*intEnviron) *
+ (tmpEnvironSize + 1));
+ if (tmpEnviron == NULL)
+ return (-1);
+ environSize = tmpEnvironSize;
+ intEnviron = tmpEnviron;
+ }
+ envActive = newEnvironSize;
+
+ /* Assign active variables to environ. */
+ for (envNdx = envVarsTotal - 1, environNdx = 0; envNdx >= 0; envNdx--)
+ if (envVars[envNdx].active)
+ intEnviron[environNdx++] = envVars[envNdx].name;
+ intEnviron[environNdx] = NULL;
+
+ /* Always set environ which may have been replaced by program. */
+ environ = intEnviron;
+
+ return (0);
+}
+
+
+/*
+ * Enlarge new environment.
+ */
+static inline bool
+__enlarge_env(void)
+{
+ int newEnvVarsSize;
+ struct envVars *tmpEnvVars;
+
+ envVarsTotal++;
+ if (envVarsTotal > envVarsSize) {
+ newEnvVarsSize = envVarsTotal * 2;
+ tmpEnvVars = realloc(envVars, sizeof (*envVars) *
+ newEnvVarsSize);
+ if (tmpEnvVars == NULL) {
+ envVarsTotal--;
+ return (false);
+ }
+ envVarsSize = newEnvVarsSize;
+ envVars = tmpEnvVars;
+ }
+
+ return (true);
+}
+
+
+/*
+ * Using environ, build an environment for use by standard C library calls.
+ */
+static int
+__build_env(void)
+{
+ char **env;
+ int activeNdx;
+ int envNdx;
+ int savedErrno;
+ size_t nameLen;
+
+ /* Check for non-existant environment. */
+ if (environ == NULL || environ[0] == NULL)
+ return (0);
+
+ /* Count environment variables. */
+ for (env = environ, envVarsTotal = 0; *env != NULL; env++)
+ envVarsTotal++;
+ envVarsSize = envVarsTotal * 2;
+
+ /* Create new environment. */
+ envVars = calloc(1, sizeof (*envVars) * envVarsSize);
+ if (envVars == NULL)
+ goto Failure;
+
+ /* Copy environ values and keep track of them. */
+ for (envNdx = envVarsTotal - 1; envNdx >= 0; envNdx--) {
+ envVars[envNdx].putenv = false;
+ envVars[envNdx].name =
+ strdup(environ[envVarsTotal - envNdx - 1]);
+ if (envVars[envNdx].name == NULL)
+ goto Failure;
+ envVars[envNdx].value = strchr(envVars[envNdx].name, '=');
+ if (envVars[envNdx].value != NULL) {
+ envVars[envNdx].value++;
+ envVars[envNdx].valueSize =
+ strlen(envVars[envNdx].value);
+ } else {
+ __env_warnx(CorruptEnvValueMsg, envVars[envNdx].name,
+ strlen(envVars[envNdx].name));
+ errno = EFAULT;
+ goto Failure;
+ }
+
+ /*
+ * Find most current version of variable to make active. This
+ * will prevent multiple active variables from being created
+ * during this initialization phase.
+ */
+ nameLen = envVars[envNdx].value - envVars[envNdx].name - 1;
+ envVars[envNdx].nameLen = nameLen;
+ activeNdx = envVarsTotal - 1;
+ if (__findenv(envVars[envNdx].name, nameLen, &activeNdx,
+ false) == NULL) {
+ __env_warnx(CorruptEnvFindMsg, envVars[envNdx].name,
+ nameLen);
+ errno = EFAULT;
+ goto Failure;
+ }
+ envVars[activeNdx].active = true;
+ }
+
+ /* Create a new environ. */
+ origEnviron = environ;
+ environ = NULL;
+ if (__rebuild_environ(envVarsTotal) == 0)
+ return (0);
+
+Failure:
+ savedErrno = errno;
+ __clean_env(true);
+ errno = savedErrno;
+
+ return (-1);
+}
+
+
+/*
+ * Destructor function with default argument to __clean_env().
+ */
+static void
+__clean_env_destructor(void)
+{
+ __clean_env(true);
+
+ return;
+}
+
+
+/*
+ * Returns the value of a variable or NULL if none are found.
+ */
+char *
+getenv(const char *name)
+{
+ int envNdx;
+ size_t nameLen;
+
+ /* Check for malformed name. */
+ if (name == NULL || (nameLen = __strleneq(name)) == 0) {
+ errno = EINVAL;
+ return (NULL);
+ }
+
+ /*
+ * Variable search order:
+ * 1. Check for an empty environ. This allows an application to clear
+ * the environment.
+ * 2. Search the external environ array.
+ * 3. Search the internal environment.
+ *
+ * Since malloc() depends upon getenv(), getenv() must never cause the
+ * internal environment storage to be generated.
+ */
+ if (environ == NULL || environ[0] == NULL)
+ return (NULL);
+ else if (envVars == NULL || environ != intEnviron)
+ return (__findenv_environ(name, nameLen));
+ else {
+ envNdx = envVarsTotal - 1;
+ return (__findenv(name, nameLen, &envNdx, true));
+ }
+}
+
+
+/*
+ * Set the value of a variable. Older settings are labeled as inactive. If an
+ * older setting has enough room to store the new value, it will be reused. No
+ * previous variables are ever freed here to avoid causing a segmentation fault
+ * in a user's code.
+ *
+ * The variables nameLen and valueLen are passed into here to allow the caller
+ * to calculate the length by means besides just strlen().
+ */
+static int
+__setenv(const char *name, size_t nameLen, const char *value, int overwrite)
+{
+ bool reuse;
+ char *env;
+ int envNdx;
+ int newEnvActive;
+ size_t valueLen;
+
+ /* Find existing environment variable large enough to use. */
+ envNdx = envVarsTotal - 1;
+ newEnvActive = envActive;
+ valueLen = strlen(value);
+ reuse = false;
+ if (__findenv(name, nameLen, &envNdx, false) != NULL) {
+ /* Deactivate entry if overwrite is allowed. */
+ if (envVars[envNdx].active) {
+ if (overwrite == 0)
+ return (0);
+ envVars[envNdx].active = false;
+ newEnvActive--;
+ }
+
+ /* putenv() created variable cannot be reused. */
+ if (envVars[envNdx].putenv)
+ __remove_putenv(envNdx);
+
+ /* Entry is large enough to reuse. */
+ else if (envVars[envNdx].valueSize >= valueLen)
+ reuse = true;
+ }
+
+ /* Create new variable if none was found of sufficient size. */
+ if (! reuse) {
+ /* Enlarge environment. */
+ envNdx = envVarsTotal;
+ if (!__enlarge_env())
+ return (-1);
+
+ /* Create environment entry. */
+ envVars[envNdx].name = malloc(nameLen + sizeof ("=") +
+ valueLen);
+ if (envVars[envNdx].name == NULL) {
+ envVarsTotal--;
+ return (-1);
+ }
+ envVars[envNdx].nameLen = nameLen;
+ envVars[envNdx].valueSize = valueLen;
+
+ /* Save name of name/value pair. */
+ env = stpcpy(envVars[envNdx].name, name);
+ if ((envVars[envNdx].name)[nameLen] != '=')
+ env = stpcpy(env, "=");
+ }
+ else
+ env = envVars[envNdx].value;
+
+ /* Save value of name/value pair. */
+ strcpy(env, value);
+ envVars[envNdx].value = env;
+ envVars[envNdx].active = true;
+ newEnvActive++;
+
+ /* No need to rebuild environ if an active variable was reused. */
+ if (reuse && newEnvActive == envActive)
+ return (0);
+ else
+ return (__rebuild_environ(newEnvActive));
+}
+
+
+/*
+ * If the program attempts to replace the array of environment variables
+ * (environ) environ or sets the first varible to NULL, then deactivate all
+ * variables and merge in the new list from environ.
+ */
+static int
+__merge_environ(void)
+{
+ char **env;
+ char *equals;
+
+ /*
+ * Internally-built environ has been replaced or cleared (detected by
+ * using the count of active variables against a NULL as the first value
+ * in environ). Clean up everything.
+ */
+ if (intEnviron != NULL && (environ != intEnviron || (envActive > 0 &&
+ environ[0] == NULL))) {
+ /* Deactivate all environment variables. */
+ if (envActive > 0) {
+ origEnviron = NULL;
+ __clean_env(false);
+ }
+
+ /*
+ * Insert new environ into existing, yet deactivated,
+ * environment array.
+ */
+ origEnviron = environ;
+ if (origEnviron != NULL)
+ for (env = origEnviron; *env != NULL; env++) {
+ if ((equals = strchr(*env, '=')) == NULL) {
+ __env_warnx(CorruptEnvValueMsg, *env,
+ strlen(*env));
+ errno = EFAULT;
+ return (-1);
+ }
+ if (__setenv(*env, equals - *env, equals + 1,
+ 1) == -1)
+ return (-1);
+ }
+ }
+
+ return (0);
+}
+
+
+/*
+ * The exposed setenv() that peforms a few tests before calling the function
+ * (__setenv()) that does the actual work of inserting a variable into the
+ * environment.
+ */
+int
+setenv(const char *name, const char *value, int overwrite)
+{
+ size_t nameLen;
+
+ /* Check for malformed name. */
+ if (name == NULL || (nameLen = __strleneq(name)) == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* Initialize environment. */
+ if (__merge_environ() == -1 || (envVars == NULL && __build_env() == -1))
+ return (-1);
+
+ return (__setenv(name, nameLen, value, overwrite));
+}
+
+
+/*
+ * Insert a "name=value" string into the environment. Special settings must be
+ * made to keep setenv() from reusing this memory block and unsetenv() from
+ * allowing it to be tracked.
+ */
+int
+putenv(char *string)
+{
+ char *equals;
+ int envNdx;
+ int newEnvActive;
+ size_t nameLen;
+
+ /* Check for malformed argument. */
+ if (string == NULL || (equals = strchr(string, '=')) == NULL ||
+ (nameLen = equals - string) == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* Initialize environment. */
+ if (__merge_environ() == -1 || (envVars == NULL && __build_env() == -1))
+ return (-1);
+
+ /* Deactivate previous environment variable. */
+ envNdx = envVarsTotal - 1;
+ newEnvActive = envActive;
+ if (__findenv(string, nameLen, &envNdx, true) != NULL) {
+ /* Reuse previous putenv slot. */
+ if (envVars[envNdx].putenv) {
+ envVars[envNdx].name = string;
+ return (__rebuild_environ(envActive));
+ } else {
+ newEnvActive--;
+ envVars[envNdx].active = false;
+ }
+ }
+
+ /* Enlarge environment. */
+ envNdx = envVarsTotal;
+ if (!__enlarge_env())
+ return (-1);
+
+ /* Create environment entry. */
+ envVars[envNdx].name = string;
+ envVars[envNdx].nameLen = -1;
+ envVars[envNdx].value = NULL;
+ envVars[envNdx].valueSize = -1;
+ envVars[envNdx].putenv = true;
+ envVars[envNdx].active = true;
+ newEnvActive++;
+
+ return (__rebuild_environ(newEnvActive));
+}
+
+
+/*
+ * Unset variable with the same name by flagging it as inactive. No variable is
+ * ever freed.
+ */
+int
+unsetenv(const char *name)
+{
+ int envNdx;
+ size_t nameLen;
+
+ /* Check for malformed name. */
+ if (name == NULL || (nameLen = __strleneq(name)) == 0) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ /* Initialize environment. */
+ if (__merge_environ() == -1 || (envVars == NULL && __build_env() == -1))
+ return (-1);
+
+ /* Deactivate specified variable. */
+ envNdx = envVarsTotal - 1;
+ if (__findenv(name, nameLen, &envNdx, true) != NULL) {
+ envVars[envNdx].active = false;
+ if (envVars[envNdx].putenv)
+ __remove_putenv(envNdx);
+ __rebuild_environ(envActive - 1);
+ }
+
+ return (0);
+}
diff --git a/lib/libc/stdlib/getopt.3 b/lib/libc/stdlib/getopt.3
new file mode 100644
index 0000000..3fe4453
--- /dev/null
+++ b/lib/libc/stdlib/getopt.3
@@ -0,0 +1,306 @@
+.\" $NetBSD: getopt.3,v 1.31 2003/09/23 10:26:54 wiz Exp $
+.\"
+.\" Copyright (c) 1988, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getopt.3 8.5 (Berkeley) 4/27/95
+.\" $FreeBSD$
+.\"
+.Dd April 27, 1995
+.Dt GETOPT 3
+.Os
+.Sh NAME
+.Nm getopt
+.Nd get option character from command line argument list
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Vt extern char *optarg ;
+.Vt extern int optind ;
+.Vt extern int optopt ;
+.Vt extern int opterr ;
+.Vt extern int optreset ;
+.Ft int
+.Fn getopt "int argc" "char * const argv[]" "const char *optstring"
+.Sh DESCRIPTION
+The
+.Fn getopt
+function incrementally parses a command line argument list
+.Fa argv
+and returns the next
+.Em known
+option character.
+An option character is
+.Em known
+if it has been specified in the string of accepted option characters,
+.Fa optstring .
+.Pp
+The option string
+.Fa optstring
+may contain the following elements: individual characters, and
+characters followed by a colon to indicate an option argument
+is to follow.
+For example, an option string
+.Li \&"x"
+recognizes an option
+.Dq Fl x ,
+and an option string
+.Li \&"x:"
+recognizes an option and argument
+.Dq Fl x Ar argument .
+It does not matter to
+.Fn getopt
+if a following argument has leading white space.
+.Pp
+On return from
+.Fn getopt ,
+.Va optarg
+points to an option argument, if it is anticipated,
+and the variable
+.Va optind
+contains the index to the next
+.Fa argv
+argument for a subsequent call
+to
+.Fn getopt .
+The variable
+.Va optopt
+saves the last
+.Em known
+option character returned by
+.Fn getopt .
+.Pp
+The variables
+.Va opterr
+and
+.Va optind
+are both initialized to 1.
+The
+.Va optind
+variable may be set to another value before a set of calls to
+.Fn getopt
+in order to skip over more or less argv entries.
+.Pp
+In order to use
+.Fn getopt
+to evaluate multiple sets of arguments, or to evaluate a single set of
+arguments multiple times,
+the variable
+.Va optreset
+must be set to 1 before the second and each additional set of calls to
+.Fn getopt ,
+and the variable
+.Va optind
+must be reinitialized.
+.Pp
+The
+.Fn getopt
+function returns \-1 when the argument list is exhausted.
+The interpretation of options in the argument list may be cancelled
+by the option
+.Ql --
+(double dash) which causes
+.Fn getopt
+to signal the end of argument processing and return \-1.
+When all options have been processed (i.e., up to the first non-option
+argument),
+.Fn getopt
+returns \-1.
+.Sh RETURN VALUES
+The
+.Fn getopt
+function returns the next known option character in
+.Fa optstring .
+If
+.Fn getopt
+encounters a character not found in
+.Fa optstring
+or if it detects a missing option argument,
+it returns
+.Ql \&?
+(question mark).
+If
+.Fa optstring
+has a leading
+.Ql \&:
+then a missing option argument causes
+.Ql \&:
+to be returned instead of
+.Ql \&? .
+In either case, the variable
+.Va optopt
+is set to the character that caused the error.
+The
+.Fn getopt
+function returns \-1 when the argument list is exhausted.
+.Sh EXAMPLES
+.Bd -literal -compact
+#include <unistd.h>
+int bflag, ch, fd;
+
+bflag = 0;
+while ((ch = getopt(argc, argv, "bf:")) != -1) {
+ switch (ch) {
+ case 'b':
+ bflag = 1;
+ break;
+ case 'f':
+ if ((fd = open(optarg, O_RDONLY, 0)) \*[Lt] 0) {
+ (void)fprintf(stderr,
+ "myname: %s: %s\en", optarg, strerror(errno));
+ exit(1);
+ }
+ break;
+ case '?':
+ default:
+ usage();
+ }
+}
+argc -= optind;
+argv += optind;
+.Ed
+.Sh DIAGNOSTICS
+If the
+.Fn getopt
+function encounters a character not found in the string
+.Fa optstring
+or detects
+a missing option argument it writes an error message to the
+.Dv stderr
+and returns
+.Ql \&? .
+Setting
+.Va opterr
+to a zero will disable these error messages.
+If
+.Fa optstring
+has a leading
+.Ql \&:
+then a missing option argument causes a
+.Ql \&:
+to be returned in addition to suppressing any error messages.
+.Pp
+Option arguments are allowed to begin with
+.Dq Li \- ;
+this is reasonable but reduces the amount of error checking possible.
+.Sh SEE ALSO
+.Xr getopt 1 ,
+.Xr getopt_long 3 ,
+.Xr getsubopt 3
+.Sh STANDARDS
+The
+.Va optreset
+variable was added to make it possible to call the
+.Fn getopt
+function multiple times.
+This is an extension to the
+.St -p1003.2
+specification.
+.Sh HISTORY
+The
+.Fn getopt
+function appeared in
+.Bx 4.3 .
+.Sh BUGS
+The
+.Fn getopt
+function was once specified to return
+.Dv EOF
+instead of \-1.
+This was changed by
+.St -p1003.2-92
+to decouple
+.Fn getopt
+from
+.In stdio.h .
+.Pp
+A single dash
+.Dq Li -
+may be specified as a character in
+.Fa optstring ,
+however it should
+.Em never
+have an argument associated with it.
+This allows
+.Fn getopt
+to be used with programs that expect
+.Dq Li -
+as an option flag.
+This practice is wrong, and should not be used in any current development.
+It is provided for backward compatibility
+.Em only .
+Care should be taken not to use
+.Ql \&-
+as the first character in
+.Fa optstring
+to avoid a semantic conflict with
+.Tn GNU
+.Fn getopt ,
+which assigns different meaning to an
+.Fa optstring
+that begins with a
+.Ql \&- .
+By default, a single dash causes
+.Fn getopt
+to return \-1.
+.Pp
+It is also possible to handle digits as option letters.
+This allows
+.Fn getopt
+to be used with programs that expect a number
+.Pq Dq Li \&-\&3
+as an option.
+This practice is wrong, and should not be used in any current development.
+It is provided for backward compatibility
+.Em only .
+The following code fragment works in most cases.
+.Bd -literal -offset indent
+int ch;
+long length;
+char *p, *ep;
+
+while ((ch = getopt(argc, argv, "0123456789")) != -1)
+ switch (ch) {
+ case '0': case '1': case '2': case '3': case '4':
+ case '5': case '6': case '7': case '8': case '9':
+ p = argv[optind - 1];
+ if (p[0] == '-' \*[Am]\*[Am] p[1] == ch \*[Am]\*[Am] !p[2]) {
+ length = ch - '0';
+ ep = "";
+ } else if (argv[optind] \*[Am]\*[Am] argv[optind][1] == ch) {
+ length = strtol((p = argv[optind] + 1),
+ \*[Am]ep, 10);
+ optind++;
+ optreset = 1;
+ } else
+ usage();
+ if (*ep != '\e0')
+ errx(EX_USAGE, "illegal number -- %s", p);
+ break;
+ }
+.Ed
diff --git a/lib/libc/stdlib/getopt.c b/lib/libc/stdlib/getopt.c
new file mode 100644
index 0000000..4d319a4
--- /dev/null
+++ b/lib/libc/stdlib/getopt.c
@@ -0,0 +1,135 @@
+/* $NetBSD: getopt.c,v 1.26 2003/08/07 16:43:40 agc Exp $ */
+
+/*
+ * Copyright (c) 1987, 1993, 1994
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getopt.c 8.3 (Berkeley) 4/27/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+#include "libc_private.h"
+
+int opterr = 1, /* if error message should be printed */
+ optind = 1, /* index into parent argv vector */
+ optopt, /* character checked for validity */
+ optreset; /* reset getopt */
+char *optarg; /* argument associated with option */
+
+#define BADCH (int)'?'
+#define BADARG (int)':'
+#define EMSG ""
+
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt(nargc, nargv, ostr)
+ int nargc;
+ char * const nargv[];
+ const char *ostr;
+{
+ static char *place = EMSG; /* option letter processing */
+ char *oli; /* option letter list index */
+
+ if (optreset || *place == 0) { /* update scanning pointer */
+ optreset = 0;
+ place = nargv[optind];
+ if (optind >= nargc || *place++ != '-') {
+ /* Argument is absent or is not an option */
+ place = EMSG;
+ return (-1);
+ }
+ optopt = *place++;
+ if (optopt == '-' && *place == 0) {
+ /* "--" => end of options */
+ ++optind;
+ place = EMSG;
+ return (-1);
+ }
+ if (optopt == 0) {
+ /* Solitary '-', treat as a '-' option
+ if the program (eg su) is looking for it. */
+ place = EMSG;
+ if (strchr(ostr, '-') == NULL)
+ return (-1);
+ optopt = '-';
+ }
+ } else
+ optopt = *place++;
+
+ /* See if option letter is one the caller wanted... */
+ if (optopt == ':' || (oli = strchr(ostr, optopt)) == NULL) {
+ if (*place == 0)
+ ++optind;
+ if (opterr && *ostr != ':')
+ (void)fprintf(stderr,
+ "%s: illegal option -- %c\n", _getprogname(),
+ optopt);
+ return (BADCH);
+ }
+
+ /* Does this option need an argument? */
+ if (oli[1] != ':') {
+ /* don't need argument */
+ optarg = NULL;
+ if (*place == 0)
+ ++optind;
+ } else {
+ /* Option-argument is either the rest of this argument or the
+ entire next argument. */
+ if (*place)
+ optarg = place;
+ else if (nargc > ++optind)
+ optarg = nargv[optind];
+ else {
+ /* option-argument absent */
+ place = EMSG;
+ if (*ostr == ':')
+ return (BADARG);
+ if (opterr)
+ (void)fprintf(stderr,
+ "%s: option requires an argument -- %c\n",
+ _getprogname(), optopt);
+ return (BADCH);
+ }
+ place = EMSG;
+ ++optind;
+ }
+ return (optopt); /* return option letter */
+}
diff --git a/lib/libc/stdlib/getopt_long.3 b/lib/libc/stdlib/getopt_long.3
new file mode 100644
index 0000000..06eadca
--- /dev/null
+++ b/lib/libc/stdlib/getopt_long.3
@@ -0,0 +1,507 @@
+.\" $OpenBSD: getopt_long.3,v 1.10 2004/01/06 23:44:28 fgsch Exp $
+.\" $NetBSD: getopt_long.3,v 1.14 2003/08/07 16:43:40 agc Exp $
+.\"
+.\" Copyright (c) 1988, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getopt.3 8.5 (Berkeley) 4/27/95
+.\" $FreeBSD$
+.\"
+.Dd December 25, 2011
+.Dt GETOPT_LONG 3
+.Os
+.Sh NAME
+.Nm getopt_long ,
+.Nm getopt_long_only
+.Nd get long options from command line argument list
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In getopt.h
+.Vt extern char *optarg ;
+.Vt extern int optind ;
+.Vt extern int optopt ;
+.Vt extern int opterr ;
+.Vt extern int optreset ;
+.Ft int
+.Fo getopt_long
+.Fa "int argc" "char * const *argv" "const char *optstring"
+.Fa "const struct option *longopts" "int *longindex"
+.Fc
+.Ft int
+.Fo getopt_long_only
+.Fa "int argc" "char * const *argv" "const char *optstring"
+.Fa "const struct option *longopts" "int *longindex"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn getopt_long
+function is similar to
+.Xr getopt 3
+but it accepts options in two forms: words and characters.
+The
+.Fn getopt_long
+function provides a superset of the functionality of
+.Xr getopt 3 .
+The
+.Fn getopt_long
+function
+can be used in two ways.
+In the first way, every long option understood
+by the program has a corresponding short option, and the option
+structure is only used to translate from long options to short
+options.
+When used in this fashion,
+.Fn getopt_long
+behaves identically to
+.Xr getopt 3 .
+This is a good way to add long option processing to an existing program
+with the minimum of rewriting.
+.Pp
+In the second mechanism, a long option sets a flag in the
+.Vt option
+structure passed, or will store a pointer to the command line argument
+in the
+.Vt option
+structure passed to it for options that take arguments.
+Additionally,
+the long option's argument may be specified as a single argument with
+an equal sign, e.g.,
+.Pp
+.Dl "myprogram --myoption=somevalue"
+.Pp
+When a long option is processed, the call to
+.Fn getopt_long
+will return 0.
+For this reason, long option processing without
+shortcuts is not backwards compatible with
+.Xr getopt 3 .
+.Pp
+It is possible to combine these methods, providing for long options
+processing with short option equivalents for some options.
+Less
+frequently used options would be processed as long options only.
+.Pp
+The
+.Fn getopt_long
+call requires a structure to be initialized describing the long
+options.
+The structure is:
+.Bd -literal -offset indent
+struct option {
+ char *name;
+ int has_arg;
+ int *flag;
+ int val;
+};
+.Ed
+.Pp
+The
+.Va name
+field should contain the option name without the leading double dash.
+.Pp
+The
+.Va has_arg
+field should be one of:
+.Pp
+.Bl -tag -width ".Dv optional_argument" -offset indent -compact
+.It Dv no_argument
+no argument to the option is expect
+.It Dv required_argument
+an argument to the option is required
+.It Dv optional_argument
+an argument to the option may be presented.
+.El
+.Pp
+If
+.Va flag
+is not
+.Dv NULL ,
+then the integer pointed to by it will be set to the
+value in the
+.Va val
+field.
+If the
+.Va flag
+field is
+.Dv NULL ,
+then the
+.Va val
+field will be returned.
+Setting
+.Va flag
+to
+.Dv NULL
+and setting
+.Va val
+to the corresponding short option will make this function act just
+like
+.Xr getopt 3 .
+.Pp
+If the
+.Fa longindex
+field is not
+.Dv NULL ,
+then the integer pointed to by it will be set to the index of the long
+option relative to
+.Fa longopts .
+.Pp
+The last element of the
+.Fa longopts
+array has to be filled with zeroes.
+.Pp
+The
+.Fn getopt_long_only
+function behaves identically to
+.Fn getopt_long
+with the exception that long options may start with
+.Ql -
+in addition to
+.Ql -- .
+If an option starting with
+.Ql -
+does not match a long option but does match a single-character option,
+the single-character option is returned.
+.Sh RETURN VALUES
+If the
+.Fa flag
+field in
+.Vt "struct option"
+is
+.Dv NULL ,
+.Fn getopt_long
+and
+.Fn getopt_long_only
+return the value specified in the
+.Fa val
+field, which is usually just the corresponding short option.
+If
+.Fa flag
+is not
+.Dv NULL ,
+these functions return 0 and store
+.Fa val
+in the location pointed to by
+.Fa flag .
+These functions return
+.Ql \&:
+if there was a missing option argument,
+.Ql \&?
+if the user specified an unknown or ambiguous option, and
+\-1 when the argument list has been exhausted.
+.Sh ENVIRONMENT
+.Bl -tag -width ".Ev POSIXLY_CORRECT"
+.It Ev POSIXLY_CORRECT
+If set, option processing stops when the first non-option is found and
+a leading
+.Ql -
+or
+.Ql +
+in the
+.Fa optstring
+is ignored.
+.El
+.Sh EXAMPLES
+.Bd -literal -compact
+int bflag, ch, fd;
+int daggerset;
+
+/* options descriptor */
+static struct option longopts[] = {
+ { "buffy", no_argument, NULL, 'b' },
+ { "fluoride", required_argument, NULL, 'f' },
+ { "daggerset", no_argument, \*[Am]daggerset, 1 },
+ { NULL, 0, NULL, 0 }
+};
+
+bflag = 0;
+while ((ch = getopt_long(argc, argv, "bf:", longopts, NULL)) != -1) {
+ switch (ch) {
+ case 'b':
+ bflag = 1;
+ break;
+ case 'f':
+ if ((fd = open(optarg, O_RDONLY, 0)) == -1)
+ err(1, "unable to open %s", optarg);
+ break;
+ case 0:
+ if (daggerset) {
+ fprintf(stderr,"Buffy will use her dagger to "
+ "apply fluoride to dracula's teeth\en");
+ }
+ break;
+ default:
+ usage();
+ }
+}
+argc -= optind;
+argv += optind;
+.Ed
+.Sh IMPLEMENTATION DIFFERENCES
+This section describes differences to the
+.Tn GNU
+implementation
+found in glibc-2.1.3:
+.Bl -bullet
+.\" .It
+.\" Handling of
+.\" .Ql -
+.\" as first char of option string in presence of
+.\" environment variable
+.\" .Ev POSIXLY_CORRECT :
+.\" .Bl -tag -width ".Bx"
+.\" .It Tn GNU
+.\" ignores
+.\" .Ev POSIXLY_CORRECT
+.\" and returns non-options as
+.\" arguments to option '\e1'.
+.\" .It Bx
+.\" honors
+.\" .Ev POSIXLY_CORRECT
+.\" and stops at the first non-option.
+.\" .El
+.\" .It
+.\" Handling of
+.\" .Ql -
+.\" within the option string (not the first character):
+.\" .Bl -tag -width ".Bx"
+.\" .It Tn GNU
+.\" treats a
+.\" .Ql -
+.\" on the command line as a non-argument.
+.\" .It Bx
+.\" a
+.\" .Ql -
+.\" within the option string matches a
+.\" .Ql -
+.\" (single dash) on the command line.
+.\" This functionality is provided for backward compatibility with
+.\" programs, such as
+.\" .Xr su 1 ,
+.\" that use
+.\" .Ql -
+.\" as an option flag.
+.\" This practice is wrong, and should not be used in any current development.
+.\" .El
+.\" .It
+.\" Handling of
+.\" .Ql ::
+.\" in options string in presence of
+.\" .Ev POSIXLY_CORRECT :
+.\" .Bl -tag -width ".Bx"
+.\" .It Both
+.\" .Tn GNU
+.\" and
+.\" .Bx
+.\" ignore
+.\" .Ev POSIXLY_CORRECT
+.\" here and take
+.\" .Ql ::
+.\" to
+.\" mean the preceding option takes an optional argument.
+.\" .El
+.\" .It
+.\" Return value in case of missing argument if first character
+.\" (after
+.\" .Ql +
+.\" or
+.\" .Ql - )
+.\" in option string is not
+.\" .Ql \&: :
+.\" .Bl -tag -width ".Bx"
+.\" .It Tn GNU
+.\" returns
+.\" .Ql \&?
+.\" .It Bx
+.\" returns
+.\" .Ql \&:
+.\" (since
+.\" .Bx Ns 's
+.\" .Fn getopt
+.\" does).
+.\" .El
+.\" .It
+.\" Handling of
+.\" .Ql --a
+.\" in getopt:
+.\" .Bl -tag -width ".Bx"
+.\" .It Tn GNU
+.\" parses this as option
+.\" .Ql - ,
+.\" option
+.\" .Ql a .
+.\" .It Bx
+.\" parses this as
+.\" .Ql -- ,
+.\" and returns \-1 (ignoring the
+.\" .Ql a ) .
+.\" (Because the original
+.\" .Fn getopt
+.\" does.)
+.\" .El
+.It
+Setting of
+.Va optopt
+for long options with
+.Va flag
+!=
+.Dv NULL :
+.Bl -tag -width ".Bx"
+.It Tn GNU
+sets
+.Va optopt
+to
+.Va val .
+.It Bx
+sets
+.Va optopt
+to 0 (since
+.Va val
+would never be returned).
+.El
+.\" .It
+.\" Handling of
+.\" .Ql -W
+.\" with
+.\" .Ql W;
+.\" in option string in
+.\" .Fn getopt
+.\" (not
+.\" .Fn getopt_long ) :
+.\" .Bl -tag -width ".Bx"
+.\" .It Tn GNU
+.\" causes a segfault.
+.\" .It Bx
+.\" no special handling is done;
+.\" .Ql W;
+.\" is interpreted as two separate options, neither of which take an argument.
+.\" .El
+.It
+Setting of
+.Va optarg
+for long options without an argument that are
+invoked via
+.Ql -W
+.Ql ( W;
+in option string):
+.Bl -tag -width ".Bx"
+.It Tn GNU
+sets
+.Va optarg
+to the option name (the argument of
+.Ql -W ) .
+.It Bx
+sets
+.Va optarg
+to
+.Dv NULL
+(the argument of the long option).
+.El
+.It
+Handling of
+.Ql -W
+with an argument that is not (a prefix to) a known
+long option
+.Ql ( W;
+in option string):
+.Bl -tag -width ".Bx"
+.It Tn GNU
+returns
+.Ql -W
+with
+.Va optarg
+set to the unknown option.
+.It Bx
+treats this as an error (unknown option) and returns
+.Ql \&?
+with
+.Va optopt
+set to 0 and
+.Va optarg
+set to
+.Dv NULL
+(as
+.Tn GNU Ns 's
+man page documents).
+.El
+.\" .It
+.\" The error messages are different.
+.It
+.Bx
+does not permute the argument vector at the same points in
+the calling sequence as
+.Tn GNU
+does.
+The aspects normally used by
+the caller (ordering after \-1 is returned, value of
+.Va optind
+relative
+to current positions) are the same, though.
+(We do fewer variable swaps.)
+.El
+.Sh SEE ALSO
+.Xr getopt 3
+.Sh HISTORY
+The
+.Fn getopt_long
+and
+.Fn getopt_long_only
+functions first appeared in the
+.Tn GNU
+libiberty library.
+The first
+.Bx
+implementation of
+.Fn getopt_long
+appeared in
+.Nx 1.5 ,
+the first
+.Bx
+implementation of
+.Fn getopt_long_only
+in
+.Ox 3.3 .
+.Fx
+first included
+.Fn getopt_long
+in
+.Fx 5.0 ,
+.Fn getopt_long_only
+in
+.Fx 5.2 .
+.Sh BUGS
+The
+.Fa argv
+argument is not really
+.Vt const
+as its elements may be permuted (unless
+.Ev POSIXLY_CORRECT
+is set).
+.Pp
+The implementation can completely replace
+.Xr getopt 3 ,
+but right now we are using separate code.
diff --git a/lib/libc/stdlib/getopt_long.c b/lib/libc/stdlib/getopt_long.c
new file mode 100644
index 0000000..bf7a04a
--- /dev/null
+++ b/lib/libc/stdlib/getopt_long.c
@@ -0,0 +1,625 @@
+/* $OpenBSD: getopt_long.c,v 1.21 2006/09/22 17:22:05 millert Exp $ */
+/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */
+
+/*
+ * Copyright (c) 2002 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Sponsored in part by the Defense Advanced Research Projects
+ * Agency (DARPA) and Air Force Research Laboratory, Air Force
+ * Materiel Command, USAF, under agreement number F39502-99-1-0512.
+ */
+/*-
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Dieter Baron and Thomas Klausner.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the NetBSD
+ * Foundation, Inc. and its contributors.
+ * 4. Neither the name of The NetBSD Foundation nor the names of its
+ * contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+ * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: getopt_long.c,v 1.16 2004/02/04 18:17:25 millert Exp $";
+#endif /* LIBC_SCCS and not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <err.h>
+#include <errno.h>
+#include <getopt.h>
+#include <stdlib.h>
+#include <string.h>
+
+#define GNU_COMPATIBLE /* Be more compatible, configure's use us! */
+
+#if 0 /* we prefer to keep our getopt(3) */
+#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */
+#endif
+
+#ifdef REPLACE_GETOPT
+int opterr = 1; /* if error message should be printed */
+int optind = 1; /* index into parent argv vector */
+int optopt = '?'; /* character checked for validity */
+int optreset; /* reset getopt */
+char *optarg; /* argument associated with option */
+#endif
+
+#define PRINT_ERROR ((opterr) && (*options != ':'))
+
+#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */
+#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */
+#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */
+
+/* return values */
+#define BADCH (int)'?'
+#define BADARG ((*options == ':') ? (int)':' : (int)'?')
+#define INORDER (int)1
+
+#define EMSG ""
+
+#ifdef GNU_COMPATIBLE
+#define NO_PREFIX (-1)
+#define D_PREFIX 0
+#define DD_PREFIX 1
+#define W_PREFIX 2
+#endif
+
+static int getopt_internal(int, char * const *, const char *,
+ const struct option *, int *, int);
+static int parse_long_options(char * const *, const char *,
+ const struct option *, int *, int, int);
+static int gcd(int, int);
+static void permute_args(int, int, int, char * const *);
+
+static char *place = EMSG; /* option letter processing */
+
+/* XXX: set optreset to 1 rather than these two */
+static int nonopt_start = -1; /* first non option argument (for permute) */
+static int nonopt_end = -1; /* first option after non options (for permute) */
+
+/* Error messages */
+static const char recargchar[] = "option requires an argument -- %c";
+static const char illoptchar[] = "illegal option -- %c"; /* From P1003.2 */
+#ifdef GNU_COMPATIBLE
+static int dash_prefix = NO_PREFIX;
+static const char gnuoptchar[] = "invalid option -- %c";
+
+static const char recargstring[] = "option `%s%s' requires an argument";
+static const char ambig[] = "option `%s%.*s' is ambiguous";
+static const char noarg[] = "option `%s%.*s' doesn't allow an argument";
+static const char illoptstring[] = "unrecognized option `%s%s'";
+#else
+static const char recargstring[] = "option requires an argument -- %s";
+static const char ambig[] = "ambiguous option -- %.*s";
+static const char noarg[] = "option doesn't take an argument -- %.*s";
+static const char illoptstring[] = "unknown option -- %s";
+#endif
+
+/*
+ * Compute the greatest common divisor of a and b.
+ */
+static int
+gcd(int a, int b)
+{
+ int c;
+
+ c = a % b;
+ while (c != 0) {
+ a = b;
+ b = c;
+ c = a % b;
+ }
+
+ return (b);
+}
+
+/*
+ * Exchange the block from nonopt_start to nonopt_end with the block
+ * from nonopt_end to opt_end (keeping the same order of arguments
+ * in each block).
+ */
+static void
+permute_args(int panonopt_start, int panonopt_end, int opt_end,
+ char * const *nargv)
+{
+ int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos;
+ char *swap;
+
+ /*
+ * compute lengths of blocks and number and size of cycles
+ */
+ nnonopts = panonopt_end - panonopt_start;
+ nopts = opt_end - panonopt_end;
+ ncycle = gcd(nnonopts, nopts);
+ cyclelen = (opt_end - panonopt_start) / ncycle;
+
+ for (i = 0; i < ncycle; i++) {
+ cstart = panonopt_end+i;
+ pos = cstart;
+ for (j = 0; j < cyclelen; j++) {
+ if (pos >= panonopt_end)
+ pos -= nnonopts;
+ else
+ pos += nopts;
+ swap = nargv[pos];
+ /* LINTED const cast */
+ ((char **) nargv)[pos] = nargv[cstart];
+ /* LINTED const cast */
+ ((char **)nargv)[cstart] = swap;
+ }
+ }
+}
+
+/*
+ * parse_long_options --
+ * Parse long options in argc/argv argument vector.
+ * Returns -1 if short_too is set and the option does not match long_options.
+ */
+static int
+parse_long_options(char * const *nargv, const char *options,
+ const struct option *long_options, int *idx, int short_too, int flags)
+{
+ char *current_argv, *has_equal;
+#ifdef GNU_COMPATIBLE
+ char *current_dash;
+#endif
+ size_t current_argv_len;
+ int i, match, exact_match, second_partial_match;
+
+ current_argv = place;
+#ifdef GNU_COMPATIBLE
+ switch (dash_prefix) {
+ case D_PREFIX:
+ current_dash = "-";
+ break;
+ case DD_PREFIX:
+ current_dash = "--";
+ break;
+ case W_PREFIX:
+ current_dash = "-W ";
+ break;
+ default:
+ current_dash = "";
+ break;
+ }
+#endif
+ match = -1;
+ exact_match = 0;
+ second_partial_match = 0;
+
+ optind++;
+
+ if ((has_equal = strchr(current_argv, '=')) != NULL) {
+ /* argument found (--option=arg) */
+ current_argv_len = has_equal - current_argv;
+ has_equal++;
+ } else
+ current_argv_len = strlen(current_argv);
+
+ for (i = 0; long_options[i].name; i++) {
+ /* find matching long option */
+ if (strncmp(current_argv, long_options[i].name,
+ current_argv_len))
+ continue;
+
+ if (strlen(long_options[i].name) == current_argv_len) {
+ /* exact match */
+ match = i;
+ exact_match = 1;
+ break;
+ }
+ /*
+ * If this is a known short option, don't allow
+ * a partial match of a single character.
+ */
+ if (short_too && current_argv_len == 1)
+ continue;
+
+ if (match == -1) /* first partial match */
+ match = i;
+ else if ((flags & FLAG_LONGONLY) ||
+ long_options[i].has_arg !=
+ long_options[match].has_arg ||
+ long_options[i].flag != long_options[match].flag ||
+ long_options[i].val != long_options[match].val)
+ second_partial_match = 1;
+ }
+ if (!exact_match && second_partial_match) {
+ /* ambiguous abbreviation */
+ if (PRINT_ERROR)
+ warnx(ambig,
+#ifdef GNU_COMPATIBLE
+ current_dash,
+#endif
+ (int)current_argv_len,
+ current_argv);
+ optopt = 0;
+ return (BADCH);
+ }
+ if (match != -1) { /* option found */
+ if (long_options[match].has_arg == no_argument
+ && has_equal) {
+ if (PRINT_ERROR)
+ warnx(noarg,
+#ifdef GNU_COMPATIBLE
+ current_dash,
+#endif
+ (int)current_argv_len,
+ current_argv);
+ /*
+ * XXX: GNU sets optopt to val regardless of flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+#ifdef GNU_COMPATIBLE
+ return (BADCH);
+#else
+ return (BADARG);
+#endif
+ }
+ if (long_options[match].has_arg == required_argument ||
+ long_options[match].has_arg == optional_argument) {
+ if (has_equal)
+ optarg = has_equal;
+ else if (long_options[match].has_arg ==
+ required_argument) {
+ /*
+ * optional argument doesn't use next nargv
+ */
+ optarg = nargv[optind++];
+ }
+ }
+ if ((long_options[match].has_arg == required_argument)
+ && (optarg == NULL)) {
+ /*
+ * Missing argument; leading ':' indicates no error
+ * should be generated.
+ */
+ if (PRINT_ERROR)
+ warnx(recargstring,
+#ifdef GNU_COMPATIBLE
+ current_dash,
+#endif
+ current_argv);
+ /*
+ * XXX: GNU sets optopt to val regardless of flag
+ */
+ if (long_options[match].flag == NULL)
+ optopt = long_options[match].val;
+ else
+ optopt = 0;
+ --optind;
+ return (BADARG);
+ }
+ } else { /* unknown option */
+ if (short_too) {
+ --optind;
+ return (-1);
+ }
+ if (PRINT_ERROR)
+ warnx(illoptstring,
+#ifdef GNU_COMPATIBLE
+ current_dash,
+#endif
+ current_argv);
+ optopt = 0;
+ return (BADCH);
+ }
+ if (idx)
+ *idx = match;
+ if (long_options[match].flag) {
+ *long_options[match].flag = long_options[match].val;
+ return (0);
+ } else
+ return (long_options[match].val);
+}
+
+/*
+ * getopt_internal --
+ * Parse argc/argv argument vector. Called by user level routines.
+ */
+static int
+getopt_internal(int nargc, char * const *nargv, const char *options,
+ const struct option *long_options, int *idx, int flags)
+{
+ char *oli; /* option letter list index */
+ int optchar, short_too;
+ int posixly_correct; /* no static, can be changed on the fly */
+
+ if (options == NULL)
+ return (-1);
+
+ /*
+ * Disable GNU extensions if POSIXLY_CORRECT is set or options
+ * string begins with a '+'.
+ */
+ posixly_correct = (getenv("POSIXLY_CORRECT") != NULL);
+#ifdef GNU_COMPATIBLE
+ if (*options == '-')
+ flags |= FLAG_ALLARGS;
+ else if (posixly_correct || *options == '+')
+ flags &= ~FLAG_PERMUTE;
+#else
+ if (posixly_correct || *options == '+')
+ flags &= ~FLAG_PERMUTE;
+ else if (*options == '-')
+ flags |= FLAG_ALLARGS;
+#endif
+ if (*options == '+' || *options == '-')
+ options++;
+
+ /*
+ * XXX Some GNU programs (like cvs) set optind to 0 instead of
+ * XXX using optreset. Work around this braindamage.
+ */
+ if (optind == 0)
+ optind = optreset = 1;
+
+ optarg = NULL;
+ if (optreset)
+ nonopt_start = nonopt_end = -1;
+start:
+ if (optreset || !*place) { /* update scanning pointer */
+ optreset = 0;
+ if (optind >= nargc) { /* end of argument vector */
+ place = EMSG;
+ if (nonopt_end != -1) {
+ /* do permutation, if we have to */
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ else if (nonopt_start != -1) {
+ /*
+ * If we skipped non-options, set optind
+ * to the first of them.
+ */
+ optind = nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return (-1);
+ }
+ if (*(place = nargv[optind]) != '-' ||
+#ifdef GNU_COMPATIBLE
+ place[1] == '\0') {
+#else
+ (place[1] == '\0' && strchr(options, '-') == NULL)) {
+#endif
+ place = EMSG; /* found non-option */
+ if (flags & FLAG_ALLARGS) {
+ /*
+ * GNU extension:
+ * return non-option as argument to option 1
+ */
+ optarg = nargv[optind++];
+ return (INORDER);
+ }
+ if (!(flags & FLAG_PERMUTE)) {
+ /*
+ * If no permutation wanted, stop parsing
+ * at first non-option.
+ */
+ return (-1);
+ }
+ /* do permutation */
+ if (nonopt_start == -1)
+ nonopt_start = optind;
+ else if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ nonopt_start = optind -
+ (nonopt_end - nonopt_start);
+ nonopt_end = -1;
+ }
+ optind++;
+ /* process next argument */
+ goto start;
+ }
+ if (nonopt_start != -1 && nonopt_end == -1)
+ nonopt_end = optind;
+
+ /*
+ * If we have "-" do nothing, if "--" we are done.
+ */
+ if (place[1] != '\0' && *++place == '-' && place[1] == '\0') {
+ optind++;
+ place = EMSG;
+ /*
+ * We found an option (--), so if we skipped
+ * non-options, we have to permute.
+ */
+ if (nonopt_end != -1) {
+ permute_args(nonopt_start, nonopt_end,
+ optind, nargv);
+ optind -= nonopt_end - nonopt_start;
+ }
+ nonopt_start = nonopt_end = -1;
+ return (-1);
+ }
+ }
+
+ /*
+ * Check long options if:
+ * 1) we were passed some
+ * 2) the arg is not just "-"
+ * 3) either the arg starts with -- we are getopt_long_only()
+ */
+ if (long_options != NULL && place != nargv[optind] &&
+ (*place == '-' || (flags & FLAG_LONGONLY))) {
+ short_too = 0;
+#ifdef GNU_COMPATIBLE
+ dash_prefix = D_PREFIX;
+#endif
+ if (*place == '-') {
+ place++; /* --foo long option */
+#ifdef GNU_COMPATIBLE
+ dash_prefix = DD_PREFIX;
+#endif
+ } else if (*place != ':' && strchr(options, *place) != NULL)
+ short_too = 1; /* could be short option too */
+
+ optchar = parse_long_options(nargv, options, long_options,
+ idx, short_too, flags);
+ if (optchar != -1) {
+ place = EMSG;
+ return (optchar);
+ }
+ }
+
+ if ((optchar = (int)*place++) == (int)':' ||
+ (optchar == (int)'-' && *place != '\0') ||
+ (oli = strchr(options, optchar)) == NULL) {
+ /*
+ * If the user specified "-" and '-' isn't listed in
+ * options, return -1 (non-option) as per POSIX.
+ * Otherwise, it is an unknown option character (or ':').
+ */
+ if (optchar == (int)'-' && *place == '\0')
+ return (-1);
+ if (!*place)
+ ++optind;
+#ifdef GNU_COMPATIBLE
+ if (PRINT_ERROR)
+ warnx(posixly_correct ? illoptchar : gnuoptchar,
+ optchar);
+#else
+ if (PRINT_ERROR)
+ warnx(illoptchar, optchar);
+#endif
+ optopt = optchar;
+ return (BADCH);
+ }
+ if (long_options != NULL && optchar == 'W' && oli[1] == ';') {
+ /* -W long-option */
+ if (*place) /* no space */
+ /* NOTHING */;
+ else if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+ if (PRINT_ERROR)
+ warnx(recargchar, optchar);
+ optopt = optchar;
+ return (BADARG);
+ } else /* white space */
+ place = nargv[optind];
+#ifdef GNU_COMPATIBLE
+ dash_prefix = W_PREFIX;
+#endif
+ optchar = parse_long_options(nargv, options, long_options,
+ idx, 0, flags);
+ place = EMSG;
+ return (optchar);
+ }
+ if (*++oli != ':') { /* doesn't take argument */
+ if (!*place)
+ ++optind;
+ } else { /* takes (optional) argument */
+ optarg = NULL;
+ if (*place) /* no white space */
+ optarg = place;
+ else if (oli[1] != ':') { /* arg not optional */
+ if (++optind >= nargc) { /* no arg */
+ place = EMSG;
+ if (PRINT_ERROR)
+ warnx(recargchar, optchar);
+ optopt = optchar;
+ return (BADARG);
+ } else
+ optarg = nargv[optind];
+ }
+ place = EMSG;
+ ++optind;
+ }
+ /* dump back option letter */
+ return (optchar);
+}
+
+#ifdef REPLACE_GETOPT
+/*
+ * getopt --
+ * Parse argc/argv argument vector.
+ *
+ * [eventually this will replace the BSD getopt]
+ */
+int
+getopt(int nargc, char * const *nargv, const char *options)
+{
+
+ /*
+ * We don't pass FLAG_PERMUTE to getopt_internal() since
+ * the BSD getopt(3) (unlike GNU) has never done this.
+ *
+ * Furthermore, since many privileged programs call getopt()
+ * before dropping privileges it makes sense to keep things
+ * as simple (and bug-free) as possible.
+ */
+ return (getopt_internal(nargc, nargv, options, NULL, NULL, 0));
+}
+#endif /* REPLACE_GETOPT */
+
+/*
+ * getopt_long --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt_long(int nargc, char * const *nargv, const char *options,
+ const struct option *long_options, int *idx)
+{
+
+ return (getopt_internal(nargc, nargv, options, long_options, idx,
+ FLAG_PERMUTE));
+}
+
+/*
+ * getopt_long_only --
+ * Parse argc/argv argument vector.
+ */
+int
+getopt_long_only(int nargc, char * const *nargv, const char *options,
+ const struct option *long_options, int *idx)
+{
+
+ return (getopt_internal(nargc, nargv, options, long_options, idx,
+ FLAG_PERMUTE|FLAG_LONGONLY));
+}
diff --git a/lib/libc/stdlib/getsubopt.3 b/lib/libc/stdlib/getsubopt.3
new file mode 100644
index 0000000..86894eb
--- /dev/null
+++ b/lib/libc/stdlib/getsubopt.3
@@ -0,0 +1,147 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)getsubopt.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd December 25, 2011
+.Dt GETSUBOPT 3
+.Os
+.Sh NAME
+.Nm getsubopt
+.Nd get sub options from an argument
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Vt extern char *suboptarg ;
+.Ft int
+.Fn getsubopt "char **optionp" "char * const *tokens" "char **valuep"
+.Sh DESCRIPTION
+The
+.Fn getsubopt
+function
+parses a string containing tokens delimited by one or more tab, space or
+comma
+.Pq Ql \&,
+characters.
+It is intended for use in parsing groups of option arguments provided
+as part of a utility command line.
+.Pp
+The argument
+.Fa optionp
+is a pointer to a pointer to the string.
+The argument
+.Fa tokens
+is a pointer to a
+.Dv NULL Ns -terminated
+array of pointers to strings.
+.Pp
+The
+.Fn getsubopt
+function
+returns the zero-based offset of the pointer in the
+.Fa tokens
+array referencing a string which matches the first token
+in the string, or, \-1 if the string contains no tokens or
+.Fa tokens
+does not contain a matching string.
+.Pp
+If the token is of the form ``name=value'', the location referenced by
+.Fa valuep
+will be set to point to the start of the ``value'' portion of the token.
+.Pp
+On return from
+.Fn getsubopt ,
+.Fa optionp
+will be set to point to the start of the next token in the string,
+or the null at the end of the string if no more tokens are present.
+The external variable
+.Fa suboptarg
+will be set to point to the start of the current token, or
+.Dv NULL
+if no
+tokens were present.
+The argument
+.Fa valuep
+will be set to point to the ``value'' portion of the token, or
+.Dv NULL
+if no ``value'' portion was present.
+.Sh EXAMPLES
+.Bd -literal -compact
+char *tokens[] = {
+ #define ONE 0
+ "one",
+ #define TWO 1
+ "two",
+ NULL
+};
+
+\&...
+
+extern char *optarg, *suboptarg;
+char *options, *value;
+
+while ((ch = getopt(argc, argv, "ab:")) != \-1) {
+ switch(ch) {
+ case 'a':
+ /* process ``a'' option */
+ break;
+ case 'b':
+ options = optarg;
+ while (*options) {
+ switch(getsubopt(&options, tokens, &value)) {
+ case ONE:
+ /* process ``one'' sub option */
+ break;
+ case TWO:
+ /* process ``two'' sub option */
+ if (!value)
+ error("no value for two");
+ i = atoi(value);
+ break;
+ case \-1:
+ if (suboptarg)
+ error("illegal sub option %s",
+ suboptarg);
+ else
+ error("missing sub option");
+ break;
+ }
+ }
+ break;
+ }
+}
+.Ed
+.Sh SEE ALSO
+.Xr getopt 3 ,
+.Xr strsep 3
+.Sh HISTORY
+The
+.Fn getsubopt
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/stdlib/getsubopt.c b/lib/libc/stdlib/getsubopt.c
new file mode 100644
index 0000000..6d0ab75
--- /dev/null
+++ b/lib/libc/stdlib/getsubopt.c
@@ -0,0 +1,97 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getsubopt.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * The SVID interface to getsubopt provides no way of figuring out which
+ * part of the suboptions list wasn't matched. This makes error messages
+ * tricky... The extern variable suboptarg is a pointer to the token
+ * which didn't match.
+ */
+char *suboptarg;
+
+int
+getsubopt(optionp, tokens, valuep)
+ char **optionp, **valuep;
+ char * const *tokens;
+{
+ int cnt;
+ char *p;
+
+ suboptarg = *valuep = NULL;
+
+ if (!optionp || !*optionp)
+ return(-1);
+
+ /* skip leading white-space, commas */
+ for (p = *optionp; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
+
+ if (!*p) {
+ *optionp = p;
+ return(-1);
+ }
+
+ /* save the start of the token, and skip the rest of the token. */
+ for (suboptarg = p;
+ *++p && *p != ',' && *p != '=' && *p != ' ' && *p != '\t';);
+
+ if (*p) {
+ /*
+ * If there's an equals sign, set the value pointer, and
+ * skip over the value part of the token. Terminate the
+ * token.
+ */
+ if (*p == '=') {
+ *p = '\0';
+ for (*valuep = ++p;
+ *p && *p != ',' && *p != ' ' && *p != '\t'; ++p);
+ if (*p)
+ *p++ = '\0';
+ } else
+ *p++ = '\0';
+ /* Skip any whitespace or commas after this token. */
+ for (; *p && (*p == ',' || *p == ' ' || *p == '\t'); ++p);
+ }
+
+ /* set optionp for next round. */
+ *optionp = p;
+
+ for (cnt = 0; *tokens; ++tokens, ++cnt)
+ if (!strcmp(suboptarg, *tokens))
+ return(cnt);
+ return(-1);
+}
diff --git a/lib/libc/stdlib/hcreate.3 b/lib/libc/stdlib/hcreate.3
new file mode 100644
index 0000000..2466c9f
--- /dev/null
+++ b/lib/libc/stdlib/hcreate.3
@@ -0,0 +1,258 @@
+.\"-
+.\" Copyright (c) 1999 The NetBSD Foundation, Inc.
+.\" All rights reserved.
+.\"
+.\" This code is derived from software contributed to The NetBSD Foundation
+.\" by Klaus Klein.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+.\" TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+.\" PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
+.\" BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+.\" CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+.\" SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+.\" INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+.\" CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+.\" ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+.\" POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 6, 2008
+.Dt HCREATE 3
+.Os
+.Sh NAME
+.Nm hcreate , hdestroy , hsearch
+.Nd manage hash search table
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In search.h
+.Ft int
+.Fn hcreate "size_t nel"
+.Ft void
+.Fn hdestroy void
+.Ft ENTRY *
+.Fn hsearch "ENTRY item" "ACTION action"
+.Sh DESCRIPTION
+The
+.Fn hcreate ,
+.Fn hdestroy ,
+and
+.Fn hsearch
+functions manage hash search tables.
+.Pp
+The
+.Fn hcreate
+function allocates sufficient space for the table, and the application should
+ensure it is called before
+.Fn hsearch
+is used.
+The
+.Fa nel
+argument is an estimate of the maximum
+number of entries that the table should contain.
+This number may be adjusted upward by the
+algorithm in order to obtain certain mathematically favorable circumstances.
+.Pp
+The
+.Fn hdestroy
+function disposes of the search table, and may be followed by another call to
+.Fn hcreate .
+After the call to
+.Fn hdestroy ,
+the data can no longer be considered accessible.
+The
+.Fn hdestroy
+function calls
+.Xr free 3
+for each comparison key in the search table
+but not the data item associated with the key.
+.Pp
+The
+.Fn hsearch
+function is a hash-table search routine.
+It returns a pointer into a hash table
+indicating the location at which an entry can be found.
+The
+.Fa item
+argument is a structure of type
+.Vt ENTRY
+(defined in the
+.In search.h
+header) containing two pointers:
+.Fa item.key
+points to the comparison key (a
+.Vt "char *" ) ,
+and
+.Fa item.data
+(a
+.Vt "void *" )
+points to any other data to be associated with
+that key.
+The comparison function used by
+.Fn hsearch
+is
+.Xr strcmp 3 .
+The
+.Fa action
+argument is a
+member of an enumeration type
+.Vt ACTION
+indicating the disposition of the entry if it cannot be
+found in the table.
+.Dv ENTER
+indicates that the
+.Fa item
+should be inserted in the table at an
+appropriate point.
+.Dv FIND
+indicates that no entry should be made.
+Unsuccessful resolution is
+indicated by the return of a
+.Dv NULL
+pointer.
+.Pp
+The comparison key (passed to
+.Fn hsearch
+as
+.Fa item.key )
+must be allocated using
+.Xr malloc 3
+if
+.Fa action
+is
+.Dv ENTER
+and
+.Fn hdestroy
+is called.
+.Sh RETURN VALUES
+The
+.Fn hcreate
+function returns 0 if the table creation failed and the global variable
+.Va errno
+is set to indicate the error;
+otherwise, a non-zero value is returned.
+.Pp
+The
+.Fn hdestroy
+function does not return a value.
+.Pp
+The
+.Fn hsearch
+function returns a
+.Dv NULL
+pointer if either the
+.Fa action
+is
+.Dv FIND
+and the
+.Fa item
+could not be found or the
+.Fa action
+is
+.Dv ENTER
+and the table is full.
+.Sh EXAMPLES
+The following example reads in strings followed by two numbers
+and stores them in a hash table, discarding duplicates.
+It then reads in strings and finds the matching entry in the hash
+table and prints it out.
+.Bd -literal
+#include <stdio.h>
+#include <search.h>
+#include <string.h>
+#include <stdlib.h>
+
+struct info { /* This is the info stored in the table */
+ int age, room; /* other than the key. */
+};
+
+#define NUM_EMPL 5000 /* # of elements in search table. */
+
+int
+main(void)
+{
+ char str[BUFSIZ]; /* Space to read string */
+ struct info info_space[NUM_EMPL]; /* Space to store employee info. */
+ struct info *info_ptr = info_space; /* Next space in info_space. */
+ ENTRY item;
+ ENTRY *found_item; /* Name to look for in table. */
+ char name_to_find[30];
+ int i = 0;
+
+ /* Create table; no error checking is performed. */
+ (void) hcreate(NUM_EMPL);
+
+ while (scanf("%s%d%d", str, &info_ptr->age,
+ &info_ptr->room) != EOF && i++ < NUM_EMPL) {
+ /* Put information in structure, and structure in item. */
+ item.key = strdup(str);
+ item.data = info_ptr;
+ info_ptr++;
+ /* Put item into table. */
+ (void) hsearch(item, ENTER);
+ }
+
+ /* Access table. */
+ item.key = name_to_find;
+ while (scanf("%s", item.key) != EOF) {
+ if ((found_item = hsearch(item, FIND)) != NULL) {
+ /* If item is in the table. */
+ (void)printf("found %s, age = %d, room = %d\en",
+ found_item->key,
+ ((struct info *)found_item->data)->age,
+ ((struct info *)found_item->data)->room);
+ } else
+ (void)printf("no such employee %s\en", name_to_find);
+ }
+ hdestroy();
+ return 0;
+}
+.Ed
+.Sh ERRORS
+The
+.Fn hcreate
+and
+.Fn hsearch
+functions may fail if:
+.Bl -tag -width Er
+.It Bq Er ENOMEM
+Insufficient storage space is available.
+.It Bq Er EINVAL
+A table already exists.
+.El
+.Sh SEE ALSO
+.Xr bsearch 3 ,
+.Xr lsearch 3 ,
+.Xr malloc 3 ,
+.Xr strcmp 3 ,
+.Xr tsearch 3
+.Sh STANDARDS
+The
+.Fn hcreate ,
+.Fn hdestroy ,
+and
+.Fn hsearch
+functions conform to
+.St -xpg4.2 .
+.Sh HISTORY
+The
+.Fn hcreate ,
+.Fn hdestroy ,
+and
+.Fn hsearch
+functions first appeared in
+.At V .
+.Sh BUGS
+The interface permits the use of only one hash table at a time.
diff --git a/lib/libc/stdlib/hcreate.c b/lib/libc/stdlib/hcreate.c
new file mode 100644
index 0000000..c68fe1b
--- /dev/null
+++ b/lib/libc/stdlib/hcreate.c
@@ -0,0 +1,185 @@
+/* $NetBSD: hcreate.c,v 1.2 2001/02/19 21:26:04 ross Exp $ */
+
+/*
+ * Copyright (c) 2001 Christopher G. Demetriou
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed for the
+ * NetBSD Project. See http://www.netbsd.org/ for
+ * information about NetBSD.
+ * 4. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * <<Id: LICENSE,v 1.2 2000/06/14 15:57:33 cgd Exp>>
+ */
+
+/*
+ * hcreate() / hsearch() / hdestroy()
+ *
+ * SysV/XPG4 hash table functions.
+ *
+ * Implementation done based on NetBSD manual page and Solaris manual page,
+ * plus my own personal experience about how they're supposed to work.
+ *
+ * I tried to look at Knuth (as cited by the Solaris manual page), but
+ * nobody had a copy in the office, so...
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: hcreate.c,v 1.2 2001/02/19 21:26:04 ross Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/queue.h>
+#include <errno.h>
+#include <search.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+ * DO NOT MAKE THIS STRUCTURE LARGER THAN 32 BYTES (4 ptrs on 64-bit
+ * ptr machine) without adjusting MAX_BUCKETS_LG2 below.
+ */
+struct internal_entry {
+ SLIST_ENTRY(internal_entry) link;
+ ENTRY ent;
+};
+SLIST_HEAD(internal_head, internal_entry);
+
+#define MIN_BUCKETS_LG2 4
+#define MIN_BUCKETS (1 << MIN_BUCKETS_LG2)
+
+/*
+ * max * sizeof internal_entry must fit into size_t.
+ * assumes internal_entry is <= 32 (2^5) bytes.
+ */
+#define MAX_BUCKETS_LG2 (sizeof (size_t) * 8 - 1 - 5)
+#define MAX_BUCKETS ((size_t)1 << MAX_BUCKETS_LG2)
+
+/* Default hash function, from db/hash/hash_func.c */
+extern u_int32_t (*__default_hash)(const void *, size_t);
+
+static struct internal_head *htable;
+static size_t htablesize;
+
+int
+hcreate(size_t nel)
+{
+ size_t idx;
+ unsigned int p2;
+
+ /* Make sure this is not called when a table already exists. */
+ if (htable != NULL) {
+ errno = EINVAL;
+ return 0;
+ }
+
+ /* If nel is too small, make it min sized. */
+ if (nel < MIN_BUCKETS)
+ nel = MIN_BUCKETS;
+
+ /* If it is too large, cap it. */
+ if (nel > MAX_BUCKETS)
+ nel = MAX_BUCKETS;
+
+ /* If it is not a power of two in size, round up. */
+ if ((nel & (nel - 1)) != 0) {
+ for (p2 = 0; nel != 0; p2++)
+ nel >>= 1;
+ nel = 1 << p2;
+ }
+
+ /* Allocate the table. */
+ htablesize = nel;
+ htable = malloc(htablesize * sizeof htable[0]);
+ if (htable == NULL) {
+ errno = ENOMEM;
+ return 0;
+ }
+
+ /* Initialize it. */
+ for (idx = 0; idx < htablesize; idx++)
+ SLIST_INIT(&htable[idx]);
+
+ return 1;
+}
+
+void
+hdestroy(void)
+{
+ struct internal_entry *ie;
+ size_t idx;
+
+ if (htable == NULL)
+ return;
+
+ for (idx = 0; idx < htablesize; idx++) {
+ while (!SLIST_EMPTY(&htable[idx])) {
+ ie = SLIST_FIRST(&htable[idx]);
+ SLIST_REMOVE_HEAD(&htable[idx], link);
+ free(ie->ent.key);
+ free(ie);
+ }
+ }
+ free(htable);
+ htable = NULL;
+}
+
+ENTRY *
+hsearch(ENTRY item, ACTION action)
+{
+ struct internal_head *head;
+ struct internal_entry *ie;
+ uint32_t hashval;
+ size_t len;
+
+ len = strlen(item.key);
+ hashval = (*__default_hash)(item.key, len);
+
+ head = &htable[hashval & (htablesize - 1)];
+ ie = SLIST_FIRST(head);
+ while (ie != NULL) {
+ if (strcmp(ie->ent.key, item.key) == 0)
+ break;
+ ie = SLIST_NEXT(ie, link);
+ }
+
+ if (ie != NULL)
+ return &ie->ent;
+ else if (action == FIND)
+ return NULL;
+
+ ie = malloc(sizeof *ie);
+ if (ie == NULL)
+ return NULL;
+ ie->ent.key = item.key;
+ ie->ent.data = item.data;
+
+ SLIST_INSERT_HEAD(head, ie, link);
+ return &ie->ent;
+}
diff --git a/lib/libc/stdlib/heapsort.c b/lib/libc/stdlib/heapsort.c
new file mode 100644
index 0000000..f656876
--- /dev/null
+++ b/lib/libc/stdlib/heapsort.c
@@ -0,0 +1,181 @@
+/*-
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Ronnie Kon at Mindcraft Inc., Kevin Lew and Elmer Yglesias.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)heapsort.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stddef.h>
+#include <stdlib.h>
+
+/*
+ * Swap two areas of size number of bytes. Although qsort(3) permits random
+ * blocks of memory to be sorted, sorting pointers is almost certainly the
+ * common case (and, were it not, could easily be made so). Regardless, it
+ * isn't worth optimizing; the SWAP's get sped up by the cache, and pointer
+ * arithmetic gets lost in the time required for comparison function calls.
+ */
+#define SWAP(a, b, count, size, tmp) { \
+ count = size; \
+ do { \
+ tmp = *a; \
+ *a++ = *b; \
+ *b++ = tmp; \
+ } while (--count); \
+}
+
+/* Copy one block of size size to another. */
+#define COPY(a, b, count, size, tmp1, tmp2) { \
+ count = size; \
+ tmp1 = a; \
+ tmp2 = b; \
+ do { \
+ *tmp1++ = *tmp2++; \
+ } while (--count); \
+}
+
+/*
+ * Build the list into a heap, where a heap is defined such that for
+ * the records K1 ... KN, Kj/2 >= Kj for 1 <= j/2 <= j <= N.
+ *
+ * There two cases. If j == nmemb, select largest of Ki and Kj. If
+ * j < nmemb, select largest of Ki, Kj and Kj+1.
+ */
+#define CREATE(initval, nmemb, par_i, child_i, par, child, size, count, tmp) { \
+ for (par_i = initval; (child_i = par_i * 2) <= nmemb; \
+ par_i = child_i) { \
+ child = base + child_i * size; \
+ if (child_i < nmemb && compar(child, child + size) < 0) { \
+ child += size; \
+ ++child_i; \
+ } \
+ par = base + par_i * size; \
+ if (compar(child, par) <= 0) \
+ break; \
+ SWAP(par, child, count, size, tmp); \
+ } \
+}
+
+/*
+ * Select the top of the heap and 'heapify'. Since by far the most expensive
+ * action is the call to the compar function, a considerable optimization
+ * in the average case can be achieved due to the fact that k, the displaced
+ * elememt, is ususally quite small, so it would be preferable to first
+ * heapify, always maintaining the invariant that the larger child is copied
+ * over its parent's record.
+ *
+ * Then, starting from the *bottom* of the heap, finding k's correct place,
+ * again maintianing the invariant. As a result of the invariant no element
+ * is 'lost' when k is assigned its correct place in the heap.
+ *
+ * The time savings from this optimization are on the order of 15-20% for the
+ * average case. See Knuth, Vol. 3, page 158, problem 18.
+ *
+ * XXX Don't break the #define SELECT line, below. Reiser cpp gets upset.
+ */
+#define SELECT(par_i, child_i, nmemb, par, child, size, k, count, tmp1, tmp2) { \
+ for (par_i = 1; (child_i = par_i * 2) <= nmemb; par_i = child_i) { \
+ child = base + child_i * size; \
+ if (child_i < nmemb && compar(child, child + size) < 0) { \
+ child += size; \
+ ++child_i; \
+ } \
+ par = base + par_i * size; \
+ COPY(par, child, count, size, tmp1, tmp2); \
+ } \
+ for (;;) { \
+ child_i = par_i; \
+ par_i = child_i / 2; \
+ child = base + child_i * size; \
+ par = base + par_i * size; \
+ if (child_i == 1 || compar(k, par) < 0) { \
+ COPY(child, k, count, size, tmp1, tmp2); \
+ break; \
+ } \
+ COPY(child, par, count, size, tmp1, tmp2); \
+ } \
+}
+
+/*
+ * Heapsort -- Knuth, Vol. 3, page 145. Runs in O (N lg N), both average
+ * and worst. While heapsort is faster than the worst case of quicksort,
+ * the BSD quicksort does median selection so that the chance of finding
+ * a data set that will trigger the worst case is nonexistent. Heapsort's
+ * only advantage over quicksort is that it requires little additional memory.
+ */
+int
+heapsort(vbase, nmemb, size, compar)
+ void *vbase;
+ size_t nmemb, size;
+ int (*compar)(const void *, const void *);
+{
+ size_t cnt, i, j, l;
+ char tmp, *tmp1, *tmp2;
+ char *base, *k, *p, *t;
+
+ if (nmemb <= 1)
+ return (0);
+
+ if (!size) {
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if ((k = malloc(size)) == NULL)
+ return (-1);
+
+ /*
+ * Items are numbered from 1 to nmemb, so offset from size bytes
+ * below the starting address.
+ */
+ base = (char *)vbase - size;
+
+ for (l = nmemb / 2 + 1; --l;)
+ CREATE(l, nmemb, i, j, t, p, size, cnt, tmp);
+
+ /*
+ * For each element of the heap, save the largest element into its
+ * final slot, save the displaced element (k), then recreate the
+ * heap.
+ */
+ while (nmemb > 1) {
+ COPY(k, base + nmemb * size, cnt, size, tmp1, tmp2);
+ COPY(base + nmemb * size, base + size, cnt, size, tmp1, tmp2);
+ --nmemb;
+ SELECT(i, j, nmemb, t, p, size, k, cnt, tmp1, tmp2);
+ }
+ free(k);
+ return (0);
+}
diff --git a/lib/libc/stdlib/imaxabs.3 b/lib/libc/stdlib/imaxabs.3
new file mode 100644
index 0000000..430f873
--- /dev/null
+++ b/lib/libc/stdlib/imaxabs.3
@@ -0,0 +1,62 @@
+.\" Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 14, 2001
+.Dt IMAXABS 3
+.Os
+.Sh NAME
+.Nm imaxabs
+.Nd returns absolute value
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In inttypes.h
+.Ft intmax_t
+.Fn imaxabs "intmax_t j"
+.Sh DESCRIPTION
+The
+.Fn imaxabs
+function returns the absolute value of
+.Fa j .
+.Sh SEE ALSO
+.Xr abs 3 ,
+.Xr fabs 3 ,
+.Xr hypot 3 ,
+.Xr labs 3 ,
+.Xr llabs 3 ,
+.Xr math 3
+.Sh STANDARDS
+The
+.Fn imaxabs
+function conforms to
+.St -isoC-99 .
+.Sh HISTORY
+The
+.Fn imaxabs
+function first appeared in
+.Fx 5.0 .
+.Sh BUGS
+The absolute value of the most negative integer remains negative.
diff --git a/lib/libc/stdlib/imaxabs.c b/lib/libc/stdlib/imaxabs.c
new file mode 100644
index 0000000..35e3dee
--- /dev/null
+++ b/lib/libc/stdlib/imaxabs.c
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <inttypes.h>
+
+intmax_t
+imaxabs(intmax_t j)
+{
+ return (j < 0 ? -j : j);
+}
diff --git a/lib/libc/stdlib/imaxdiv.3 b/lib/libc/stdlib/imaxdiv.3
new file mode 100644
index 0000000..0ee0971
--- /dev/null
+++ b/lib/libc/stdlib/imaxdiv.3
@@ -0,0 +1,73 @@
+.\" Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 14, 2001
+.Dt IMAXDIV 3
+.Os
+.Sh NAME
+.Nm imaxdiv
+.Nd returns quotient and remainder
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In inttypes.h
+.Ft imaxdiv_t
+.Fn imaxdiv "intmax_t numer" "intmax_t denom"
+.Sh DESCRIPTION
+The
+.Fn imaxdiv
+function computes the value of
+.Fa numer
+divided by
+.Fa denom
+and returns the stored result in the form of the
+.Vt imaxdiv_t
+type.
+.Pp
+The
+.Vt imaxdiv_t
+type is defined as:
+.Bd -literal -offset indent
+typedef struct {
+ intmax_t quot; /* Quotient. */
+ intmax_t rem; /* Remainder. */
+} imaxdiv_t;
+.Ed
+.Sh SEE ALSO
+.Xr div 3 ,
+.Xr ldiv 3 ,
+.Xr lldiv 3 ,
+.Xr math 3
+.Sh STANDARDS
+The
+.Fn imaxdiv
+function conforms to
+.St -isoC-99 .
+.Sh HISTORY
+The
+.Fn imaxdiv
+function first appeared in
+.Fx 5.0 .
diff --git a/lib/libc/stdlib/imaxdiv.c b/lib/libc/stdlib/imaxdiv.c
new file mode 100644
index 0000000..7dae467
--- /dev/null
+++ b/lib/libc/stdlib/imaxdiv.c
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <inttypes.h>
+
+/* See comments in div.c for implementation details. */
+imaxdiv_t
+imaxdiv(intmax_t numer, intmax_t denom)
+{
+ imaxdiv_t retval;
+
+ retval.quot = numer / denom;
+ retval.rem = numer % denom;
+ if (numer >= 0 && retval.rem < 0) {
+ retval.quot++;
+ retval.rem -= denom;
+ }
+ return (retval);
+}
diff --git a/lib/libc/stdlib/insque.3 b/lib/libc/stdlib/insque.3
new file mode 100644
index 0000000..a54434c
--- /dev/null
+++ b/lib/libc/stdlib/insque.3
@@ -0,0 +1,61 @@
+.\"
+.\" Initial implementation:
+.\" Copyright (c) 2002 Robert Drehmel
+.\" All rights reserved.
+.\"
+.\" As long as the above copyright statement and this notice remain
+.\" unchanged, you can do what ever you want with this file.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 10, 2002
+.Dt INSQUE 3
+.Os
+.Sh NAME
+.Nm insque ,
+.Nm remque
+.Nd doubly-linked list management
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In search.h
+.Ft void
+.Fn insque "void *element1" "void *pred"
+.Ft void
+.Fn remque "void *element"
+.Sh DESCRIPTION
+The
+.Fn insque
+and
+.Fn remque
+functions encapsulate the ever-repeating task of doing insertion and
+removal operations on doubly linked lists.
+The functions expect their
+arguments to point to a structure whose first and second members are
+pointers to the next and previous element, respectively.
+The
+.Fn insque
+function also allows the
+.Fa pred
+argument to be a
+.Dv NULL
+pointer for the initialization of a new list's
+head element.
+.Sh STANDARDS
+The
+.Fn insque
+and
+.Fn remque
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn insque
+and
+.Fn remque
+functions appeared in
+.Bx 4.2 .
+In
+.Fx 5.0 ,
+they reappeared conforming to
+.St -p1003.1-2001 .
diff --git a/lib/libc/stdlib/insque.c b/lib/libc/stdlib/insque.c
new file mode 100644
index 0000000..388e4d5
--- /dev/null
+++ b/lib/libc/stdlib/insque.c
@@ -0,0 +1,47 @@
+/*
+ * Initial implementation:
+ * Copyright (c) 2002 Robert Drehmel
+ * All rights reserved.
+ *
+ * As long as the above copyright statement and this notice remain
+ * unchanged, you can do what ever you want with this file.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define _SEARCH_PRIVATE
+#include <search.h>
+#ifdef DEBUG
+#include <stdio.h>
+#else
+#include <stdlib.h> /* for NULL */
+#endif
+
+void
+insque(void *element, void *pred)
+{
+ struct que_elem *prev, *next, *elem;
+
+ elem = (struct que_elem *)element;
+ prev = (struct que_elem *)pred;
+
+ if (prev == NULL) {
+ elem->prev = elem->next = NULL;
+ return;
+ }
+
+ next = prev->next;
+ if (next != NULL) {
+#ifdef DEBUG
+ if (next->prev != prev) {
+ fprintf(stderr, "insque: Inconsistency detected:"
+ " next(%p)->prev(%p) != prev(%p)\n",
+ next, next->prev, prev);
+ }
+#endif
+ next->prev = elem;
+ }
+ prev->next = elem;
+ elem->prev = prev;
+ elem->next = next;
+}
diff --git a/lib/libc/stdlib/jemalloc/Makefile.inc b/lib/libc/stdlib/jemalloc/Makefile.inc
new file mode 100644
index 0000000..9718676
--- /dev/null
+++ b/lib/libc/stdlib/jemalloc/Makefile.inc
@@ -0,0 +1,46 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/stdlib/jemalloc
+
+JEMALLOCSRCS:= jemalloc.c arena.c atomic.c base.c bitmap.c chunk.c \
+ chunk_dss.c chunk_mmap.c ckh.c ctl.c extent.c hash.c huge.c mb.c \
+ mutex.c prof.c quarantine.c rtree.c stats.c tcache.c util.c tsd.c
+
+SYM_MAPS+=${.CURDIR}/stdlib/jemalloc/Symbol.map
+
+CFLAGS+=-I${.CURDIR}/../../contrib/jemalloc/include
+
+.for src in ${JEMALLOCSRCS}
+MISRCS+=jemalloc_${src}
+CLEANFILES+=jemalloc_${src}
+jemalloc_${src}:
+ ln -sf ${.CURDIR}/../../contrib/jemalloc/src/${src} ${.TARGET}
+.endfor
+
+MAN+=jemalloc.3
+CLEANFILES+=jemalloc.3
+jemalloc.3:
+ ln -sf ${.CURDIR}/../../contrib/jemalloc/doc/jemalloc.3 ${.TARGET}
+
+MLINKS+= \
+ jemalloc.3 malloc.3 \
+ jemalloc.3 calloc.3 \
+ jemalloc.3 posix_memalign.3 \
+ jemalloc.3 aligned_alloc.3 \
+ jemalloc.3 realloc.3 \
+ jemalloc.3 free.3 \
+ jemalloc.3 malloc_usable_size.3 \
+ jemalloc.3 malloc_stats_print.3 \
+ jemalloc.3 mallctl.3 \
+ jemalloc.3 mallctlnametomib.3 \
+ jemalloc.3 mallctlbymib.3 \
+ jemalloc.3 allocm.3 \
+ jemalloc.3 rallocm.3 \
+ jemalloc.3 sallocm.3 \
+ jemalloc.3 dallocm.3 \
+ jemalloc.3 nallocm.3 \
+ jemalloc.3 malloc.conf.5
+
+.if defined(MALLOC_PRODUCTION)
+CFLAGS+= -DMALLOC_PRODUCTION
+.endif
diff --git a/lib/libc/stdlib/jemalloc/Symbol.map b/lib/libc/stdlib/jemalloc/Symbol.map
new file mode 100644
index 0000000..b98d37a
--- /dev/null
+++ b/lib/libc/stdlib/jemalloc/Symbol.map
@@ -0,0 +1,35 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ _malloc_options;
+ _malloc_message;
+ malloc;
+ posix_memalign;
+ calloc;
+ realloc;
+ free;
+ malloc_usable_size;
+};
+
+FBSD_1.3 {
+ malloc_conf;
+ malloc_message;
+ aligned_alloc;
+ malloc_stats_print;
+ mallctl;
+ mallctlnametomib;
+ mallctlbymib;
+ allocm;
+ rallocm;
+ sallocm;
+ dallocm;
+ nallocm;
+};
+
+FBSDprivate_1.0 {
+ _malloc_thread_cleanup;
+ _malloc_prefork;
+ _malloc_postfork;
+};
diff --git a/lib/libc/stdlib/l64a.c b/lib/libc/stdlib/l64a.c
new file mode 100644
index 0000000..bc10553
--- /dev/null
+++ b/lib/libc/stdlib/l64a.c
@@ -0,0 +1,52 @@
+/*
+ * Written by J.T. Conklin <jtc@NetBSD.org>.
+ * Public domain.
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: l64a.c,v 1.13 2003/07/26 19:24:54 salo Exp $");
+#endif /* not lint */
+#endif
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+
+#define ADOT 46 /* ASCII '.' */
+#define ASLASH ADOT + 1 /* ASCII '/' */
+#define A0 48 /* ASCII '0' */
+#define AA 65 /* ASCII 'A' */
+#define Aa 97 /* ASCII 'a' */
+
+char *
+l64a(long value)
+{
+ static char buf[8];
+
+ (void)l64a_r(value, buf, sizeof(buf));
+ return (buf);
+}
+
+int
+l64a_r(long value, char *buffer, int buflen)
+{
+ long v;
+ int digit;
+
+ v = value & (long)0xffffffff;
+ for (; v != 0 && buflen > 1; buffer++, buflen--) {
+ digit = v & 0x3f;
+ if (digit < 2)
+ *buffer = digit + ADOT;
+ else if (digit < 12)
+ *buffer = digit + A0 - 2;
+ else if (digit < 38)
+ *buffer = digit + AA - 12;
+ else
+ *buffer = digit + Aa - 38;
+ v >>= 6;
+ }
+ return (v == 0 ? 0 : -1);
+}
diff --git a/lib/libc/stdlib/labs.3 b/lib/libc/stdlib/labs.3
new file mode 100644
index 0000000..b714fe3
--- /dev/null
+++ b/lib/libc/stdlib/labs.3
@@ -0,0 +1,67 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)labs.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd November 14, 2001
+.Dt LABS 3
+.Os
+.Sh NAME
+.Nm labs
+.Nd return the absolute value of a long integer
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft long
+.Fn labs "long j"
+.Sh DESCRIPTION
+The
+.Fn labs
+function
+returns the absolute value of the long integer
+.Fa j .
+.Sh SEE ALSO
+.Xr abs 3 ,
+.Xr cabs 3 ,
+.Xr floor 3 ,
+.Xr imaxabs 3 ,
+.Xr llabs 3 ,
+.Xr math 3
+.Sh STANDARDS
+The
+.Fn labs
+function
+conforms to
+.St -isoC .
+.Sh BUGS
+The absolute value of the most negative integer remains negative.
diff --git a/lib/libc/stdlib/labs.c b/lib/libc/stdlib/labs.c
new file mode 100644
index 0000000..d22975e
--- /dev/null
+++ b/lib/libc/stdlib/labs.c
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)labs.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+
+long
+labs(j)
+ long j;
+{
+ return(j < 0 ? -j : j);
+}
diff --git a/lib/libc/stdlib/ldiv.3 b/lib/libc/stdlib/ldiv.3
new file mode 100644
index 0000000..221e68d
--- /dev/null
+++ b/lib/libc/stdlib/ldiv.3
@@ -0,0 +1,71 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)ldiv.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd November 14, 2001
+.Dt LDIV 3
+.Os
+.Sh NAME
+.Nm ldiv
+.Nd return quotient and remainder from division
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft ldiv_t
+.Fn ldiv "long num" "long denom"
+.Sh DESCRIPTION
+The
+.Fn ldiv
+function
+computes the value
+.Fa num Ns / Ns Fa denom
+and returns the quotient and remainder in a structure named
+.Vt ldiv_t
+that contains two
+.Vt long
+members named
+.Va quot
+and
+.Va rem .
+.Sh SEE ALSO
+.Xr div 3 ,
+.Xr imaxdiv 3 ,
+.Xr lldiv 3 ,
+.Xr math 3
+.Sh STANDARDS
+The
+.Fn ldiv
+function
+conforms to
+.St -isoC-99 .
diff --git a/lib/libc/stdlib/ldiv.c b/lib/libc/stdlib/ldiv.c
new file mode 100644
index 0000000..0311d06
--- /dev/null
+++ b/lib/libc/stdlib/ldiv.c
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ldiv.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h> /* ldiv_t */
+
+ldiv_t
+ldiv(num, denom)
+ long num, denom;
+{
+ ldiv_t r;
+
+ /* see div.c for comments */
+
+ r.quot = num / denom;
+ r.rem = num % denom;
+ if (num >= 0 && r.rem < 0) {
+ r.quot++;
+ r.rem -= denom;
+ }
+ return (r);
+}
diff --git a/lib/libc/stdlib/llabs.3 b/lib/libc/stdlib/llabs.3
new file mode 100644
index 0000000..8c031a9
--- /dev/null
+++ b/lib/libc/stdlib/llabs.3
@@ -0,0 +1,62 @@
+.\" Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 14, 2001
+.Dt LLABS 3
+.Os
+.Sh NAME
+.Nm llabs
+.Nd returns absolute value
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft "long long"
+.Fn llabs "long long j"
+.Sh DESCRIPTION
+The
+.Fn llabs
+function returns the absolute value of
+.Fa j .
+.Sh SEE ALSO
+.Xr abs 3 ,
+.Xr fabs 3 ,
+.Xr hypot 3 ,
+.Xr imaxabs 3 ,
+.Xr labs 3 ,
+.Xr math 3
+.Sh STANDARDS
+The
+.Fn llabs
+function conforms to
+.St -isoC-99 .
+.Sh HISTORY
+The
+.Fn llabs
+function first appeared in
+.Fx 5.0 .
+.Sh BUGS
+The absolute value of the most negative integer remains negative.
diff --git a/lib/libc/stdlib/llabs.c b/lib/libc/stdlib/llabs.c
new file mode 100644
index 0000000..2bfbada
--- /dev/null
+++ b/lib/libc/stdlib/llabs.c
@@ -0,0 +1,36 @@
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+
+long long
+llabs(long long j)
+{
+ return (j < 0 ? -j : j);
+}
diff --git a/lib/libc/stdlib/lldiv.3 b/lib/libc/stdlib/lldiv.3
new file mode 100644
index 0000000..976a997
--- /dev/null
+++ b/lib/libc/stdlib/lldiv.3
@@ -0,0 +1,73 @@
+.\" Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 14, 2001
+.Dt LLDIV 3
+.Os
+.Sh NAME
+.Nm lldiv
+.Nd returns quotient and remainder
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft lldiv_t
+.Fn lldiv "long long numer" "long long denom"
+.Sh DESCRIPTION
+The
+.Fn lldiv
+function computes the value of
+.Fa numer
+divided by
+.Fa denom
+and returns the stored result in the form of the
+.Vt lldiv_t
+type.
+.Pp
+The
+.Vt lldiv_t
+type is defined as:
+.Bd -literal -offset indent
+typedef struct {
+ long long quot; /* Quotient. */
+ long long rem; /* Remainder. */
+} lldiv_t;
+.Ed
+.Sh SEE ALSO
+.Xr div 3 ,
+.Xr imaxdiv 3 ,
+.Xr ldiv 3 ,
+.Xr math 3
+.Sh STANDARDS
+The
+.Fn lldiv
+function conforms to
+.St -isoC-99 .
+.Sh HISTORY
+The
+.Fn lldiv
+function first appeared in
+.Fx 5.0 .
diff --git a/lib/libc/stdlib/lldiv.c b/lib/libc/stdlib/lldiv.c
new file mode 100644
index 0000000..b34b65e
--- /dev/null
+++ b/lib/libc/stdlib/lldiv.c
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+
+/* See comments in div.c for implementation details. */
+lldiv_t
+lldiv(long long numer, long long denom)
+{
+ lldiv_t retval;
+
+ retval.quot = numer / denom;
+ retval.rem = numer % denom;
+ if (numer >= 0 && retval.rem < 0) {
+ retval.quot++;
+ retval.rem -= denom;
+ }
+ return (retval);
+}
diff --git a/lib/libc/stdlib/lsearch.3 b/lib/libc/stdlib/lsearch.3
new file mode 100644
index 0000000..5e76724
--- /dev/null
+++ b/lib/libc/stdlib/lsearch.3
@@ -0,0 +1,105 @@
+.\"
+.\" Initial implementation:
+.\" Copyright (c) 2002 Robert Drehmel
+.\" All rights reserved.
+.\"
+.\" As long as the above copyright statement and this notice remain
+.\" unchanged, you can do what ever you want with this file.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 11, 2002
+.Dt LSEARCH 3
+.Os
+.Sh NAME
+.Nm lsearch ,
+.Nm lfind
+.Nd linear search and append
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In search.h
+.Ft "void *"
+.Fo lsearch
+.Fa "const void *key" "void *base" "size_t *nelp" "size_t width"
+.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]"
+.Fc
+.Ft "void *"
+.Fo lfind
+.Fa "const void *key" "const void *base" "size_t *nelp" "size_t width"
+.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn lsearch
+and
+.Fn lfind
+functions walk linearly through an array and compare each element with
+the one to be sought using a supplied comparison function.
+.Pp
+The
+.Fa key
+argument
+points to an element that matches the one that is searched.
+The array's address in memory is denoted by the
+.Fa base
+argument.
+The width of one element (i.e., the size as returned by
+.Fn sizeof )
+is passed as the
+.Fa width
+argument.
+The number of valid elements contained in the array (not the number of
+elements the array has space reserved for) is given in the integer pointed
+to by
+.Fa nelp .
+The
+.Fa compar
+argument points to a function which compares its two arguments and returns
+zero if they are matching, and non-zero otherwise.
+.Pp
+If no matching element was found in the array,
+.Fn lsearch
+copies
+.Fa key
+into the position after the last element and increments the
+integer pointed to by
+.Fa nelp .
+.Sh RETURN VALUES
+The
+.Fn lsearch
+and
+.Fn lfind
+functions
+return a pointer to the first element found.
+If no element was found,
+.Fn lsearch
+returns a pointer to the newly added element, whereas
+.Fn lfind
+returns
+.Dv NULL .
+Both functions return
+.Dv NULL
+if an error occurs.
+.Sh SEE ALSO
+.Xr bsearch 3 ,
+.Xr hsearch 3 ,
+.Xr tsearch 3
+.Sh STANDARDS
+The
+.Fn lsearch
+and
+.Fn lfind
+functions conform to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn lsearch
+and
+.Fn lfind
+functions appeared in
+.Bx 4.2 .
+In
+.Fx 5.0 ,
+they reappeared conforming to
+.St -p1003.1-2001 .
diff --git a/lib/libc/stdlib/lsearch.c b/lib/libc/stdlib/lsearch.c
new file mode 100644
index 0000000..e4d1dd5
--- /dev/null
+++ b/lib/libc/stdlib/lsearch.c
@@ -0,0 +1,64 @@
+/*
+ * Initial implementation:
+ * Copyright (c) 2002 Robert Drehmel
+ * All rights reserved.
+ *
+ * As long as the above copyright statement and this notice remain
+ * unchanged, you can do what ever you want with this file.
+ */
+#include <sys/types.h>
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define _SEARCH_PRIVATE
+#include <search.h>
+#include <stdint.h> /* for uint8_t */
+#include <stdlib.h> /* for NULL */
+#include <string.h> /* for memcpy() prototype */
+
+static void *lwork(const void *, const void *, size_t *, size_t,
+ int (*)(const void *, const void *), int);
+
+void *lsearch(const void *key, void *base, size_t *nelp, size_t width,
+ int (*compar)(const void *, const void *))
+{
+
+ return (lwork(key, base, nelp, width, compar, 1));
+}
+
+void *lfind(const void *key, const void *base, size_t *nelp, size_t width,
+ int (*compar)(const void *, const void *))
+{
+
+ return (lwork(key, base, nelp, width, compar, 0));
+}
+
+static void *
+lwork(const void *key, const void *base, size_t *nelp, size_t width,
+ int (*compar)(const void *, const void *), int addelem)
+{
+ uint8_t *ep, *endp;
+
+ /*
+ * Cast to an integer value first to avoid the warning for removing
+ * 'const' via a cast.
+ */
+ ep = (uint8_t *)(uintptr_t)base;
+ for (endp = (uint8_t *)(ep + width * *nelp); ep < endp; ep += width) {
+ if (compar(key, ep) == 0)
+ return (ep);
+ }
+
+ /* lfind() shall return when the key was not found. */
+ if (!addelem)
+ return (NULL);
+
+ /*
+ * lsearch() adds the key to the end of the table and increments
+ * the number of elements.
+ */
+ memcpy(endp, key, width);
+ ++*nelp;
+
+ return (endp);
+}
diff --git a/lib/libc/stdlib/memory.3 b/lib/libc/stdlib/memory.3
new file mode 100644
index 0000000..9f42fa6
--- /dev/null
+++ b/lib/libc/stdlib/memory.3
@@ -0,0 +1,77 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)memory.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt MEMORY 3
+.Os
+.Sh NAME
+.Nm malloc ,
+.Nm free ,
+.Nm realloc ,
+.Nm calloc ,
+.Nm alloca ,
+.Nm mmap
+.Nd general memory allocation operations
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft void *
+.Fn malloc "size_t size"
+.Ft void
+.Fn free "void *ptr"
+.Ft void *
+.Fn realloc "void *ptr" "size_t size"
+.Ft void *
+.Fn calloc "size_t nelem" "size_t elsize"
+.Ft void *
+.Fn alloca "size_t size"
+.In sys/types.h
+.In sys/mman.h
+.Ft void *
+.Fn mmap "void * addr" "size_t len" "int prot" "int flags" "int fd" "off_t offset"
+.Sh DESCRIPTION
+These functions allocate and free memory for the calling process.
+They are described in the
+individual manual pages.
+.Sh SEE ALSO
+.Xr mmap 2 ,
+.Xr alloca 3 ,
+.Xr calloc 3 ,
+.Xr free 3 ,
+.Xr malloc 3 ,
+.Xr realloc 3
+.Sh STANDARDS
+These functions, with the exception of
+.Fn alloca
+and
+.Fn mmap
+conform to
+.St -isoC .
diff --git a/lib/libc/stdlib/merge.c b/lib/libc/stdlib/merge.c
new file mode 100644
index 0000000..e1078e7
--- /dev/null
+++ b/lib/libc/stdlib/merge.c
@@ -0,0 +1,351 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Peter McIlroy.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)merge.c 8.2 (Berkeley) 2/14/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Hybrid exponential search/linear search merge sort with hybrid
+ * natural/pairwise first pass. Requires about .3% more comparisons
+ * for random data than LSMS with pairwise first pass alone.
+ * It works for objects as small as two bytes.
+ */
+
+#define NATURAL
+#define THRESHOLD 16 /* Best choice for natural merge cut-off. */
+
+/* #define NATURAL to get hybrid natural merge.
+ * (The default is pairwise merging.)
+ */
+
+#include <sys/types.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+static void setup(u_char *, u_char *, size_t, size_t,
+ int (*)(const void *, const void *));
+static void insertionsort(u_char *, size_t, size_t,
+ int (*)(const void *, const void *));
+
+#define ISIZE sizeof(int)
+#define PSIZE sizeof(u_char *)
+#define ICOPY_LIST(src, dst, last) \
+ do \
+ *(int*)dst = *(int*)src, src += ISIZE, dst += ISIZE; \
+ while(src < last)
+#define ICOPY_ELT(src, dst, i) \
+ do \
+ *(int*) dst = *(int*) src, src += ISIZE, dst += ISIZE; \
+ while (i -= ISIZE)
+
+#define CCOPY_LIST(src, dst, last) \
+ do \
+ *dst++ = *src++; \
+ while (src < last)
+#define CCOPY_ELT(src, dst, i) \
+ do \
+ *dst++ = *src++; \
+ while (i -= 1)
+
+/*
+ * Find the next possible pointer head. (Trickery for forcing an array
+ * to do double duty as a linked list when objects do not align with word
+ * boundaries.
+ */
+/* Assumption: PSIZE is a power of 2. */
+#define EVAL(p) (u_char **) \
+ ((u_char *)0 + \
+ (((u_char *)p + PSIZE - 1 - (u_char *) 0) & ~(PSIZE - 1)))
+
+/*
+ * Arguments are as for qsort.
+ */
+int
+mergesort(base, nmemb, size, cmp)
+ void *base;
+ size_t nmemb;
+ size_t size;
+ int (*cmp)(const void *, const void *);
+{
+ size_t i;
+ int sense;
+ int big, iflag;
+ u_char *f1, *f2, *t, *b, *tp2, *q, *l1, *l2;
+ u_char *list2, *list1, *p2, *p, *last, **p1;
+
+ if (size < PSIZE / 2) { /* Pointers must fit into 2 * size. */
+ errno = EINVAL;
+ return (-1);
+ }
+
+ if (nmemb == 0)
+ return (0);
+
+ /*
+ * XXX
+ * Stupid subtraction for the Cray.
+ */
+ iflag = 0;
+ if (!(size % ISIZE) && !(((char *)base - (char *)0) % ISIZE))
+ iflag = 1;
+
+ if ((list2 = malloc(nmemb * size + PSIZE)) == NULL)
+ return (-1);
+
+ list1 = base;
+ setup(list1, list2, nmemb, size, cmp);
+ last = list2 + nmemb * size;
+ i = big = 0;
+ while (*EVAL(list2) != last) {
+ l2 = list1;
+ p1 = EVAL(list1);
+ for (tp2 = p2 = list2; p2 != last; p1 = EVAL(l2)) {
+ p2 = *EVAL(p2);
+ f1 = l2;
+ f2 = l1 = list1 + (p2 - list2);
+ if (p2 != last)
+ p2 = *EVAL(p2);
+ l2 = list1 + (p2 - list2);
+ while (f1 < l1 && f2 < l2) {
+ if ((*cmp)(f1, f2) <= 0) {
+ q = f2;
+ b = f1, t = l1;
+ sense = -1;
+ } else {
+ q = f1;
+ b = f2, t = l2;
+ sense = 0;
+ }
+ if (!big) { /* here i = 0 */
+ while ((b += size) < t && cmp(q, b) >sense)
+ if (++i == 6) {
+ big = 1;
+ goto EXPONENTIAL;
+ }
+ } else {
+EXPONENTIAL: for (i = size; ; i <<= 1)
+ if ((p = (b + i)) >= t) {
+ if ((p = t - size) > b &&
+ (*cmp)(q, p) <= sense)
+ t = p;
+ else
+ b = p;
+ break;
+ } else if ((*cmp)(q, p) <= sense) {
+ t = p;
+ if (i == size)
+ big = 0;
+ goto FASTCASE;
+ } else
+ b = p;
+ while (t > b+size) {
+ i = (((t - b) / size) >> 1) * size;
+ if ((*cmp)(q, p = b + i) <= sense)
+ t = p;
+ else
+ b = p;
+ }
+ goto COPY;
+FASTCASE: while (i > size)
+ if ((*cmp)(q,
+ p = b + (i >>= 1)) <= sense)
+ t = p;
+ else
+ b = p;
+COPY: b = t;
+ }
+ i = size;
+ if (q == f1) {
+ if (iflag) {
+ ICOPY_LIST(f2, tp2, b);
+ ICOPY_ELT(f1, tp2, i);
+ } else {
+ CCOPY_LIST(f2, tp2, b);
+ CCOPY_ELT(f1, tp2, i);
+ }
+ } else {
+ if (iflag) {
+ ICOPY_LIST(f1, tp2, b);
+ ICOPY_ELT(f2, tp2, i);
+ } else {
+ CCOPY_LIST(f1, tp2, b);
+ CCOPY_ELT(f2, tp2, i);
+ }
+ }
+ }
+ if (f2 < l2) {
+ if (iflag)
+ ICOPY_LIST(f2, tp2, l2);
+ else
+ CCOPY_LIST(f2, tp2, l2);
+ } else if (f1 < l1) {
+ if (iflag)
+ ICOPY_LIST(f1, tp2, l1);
+ else
+ CCOPY_LIST(f1, tp2, l1);
+ }
+ *p1 = l2;
+ }
+ tp2 = list1; /* swap list1, list2 */
+ list1 = list2;
+ list2 = tp2;
+ last = list2 + nmemb*size;
+ }
+ if (base == list2) {
+ memmove(list2, list1, nmemb*size);
+ list2 = list1;
+ }
+ free(list2);
+ return (0);
+}
+
+#define swap(a, b) { \
+ s = b; \
+ i = size; \
+ do { \
+ tmp = *a; *a++ = *s; *s++ = tmp; \
+ } while (--i); \
+ a -= size; \
+ }
+#define reverse(bot, top) { \
+ s = top; \
+ do { \
+ i = size; \
+ do { \
+ tmp = *bot; *bot++ = *s; *s++ = tmp; \
+ } while (--i); \
+ s -= size2; \
+ } while(bot < s); \
+}
+
+/*
+ * Optional hybrid natural/pairwise first pass. Eats up list1 in runs of
+ * increasing order, list2 in a corresponding linked list. Checks for runs
+ * when THRESHOLD/2 pairs compare with same sense. (Only used when NATURAL
+ * is defined. Otherwise simple pairwise merging is used.)
+ */
+void
+setup(list1, list2, n, size, cmp)
+ size_t n, size;
+ int (*cmp)(const void *, const void *);
+ u_char *list1, *list2;
+{
+ int i, length, size2, tmp, sense;
+ u_char *f1, *f2, *s, *l2, *last, *p2;
+
+ size2 = size*2;
+ if (n <= 5) {
+ insertionsort(list1, n, size, cmp);
+ *EVAL(list2) = (u_char*) list2 + n*size;
+ return;
+ }
+ /*
+ * Avoid running pointers out of bounds; limit n to evens
+ * for simplicity.
+ */
+ i = 4 + (n & 1);
+ insertionsort(list1 + (n - i) * size, i, size, cmp);
+ last = list1 + size * (n - i);
+ *EVAL(list2 + (last - list1)) = list2 + n * size;
+
+#ifdef NATURAL
+ p2 = list2;
+ f1 = list1;
+ sense = (cmp(f1, f1 + size) > 0);
+ for (; f1 < last; sense = !sense) {
+ length = 2;
+ /* Find pairs with same sense. */
+ for (f2 = f1 + size2; f2 < last; f2 += size2) {
+ if ((cmp(f2, f2+ size) > 0) != sense)
+ break;
+ length += 2;
+ }
+ if (length < THRESHOLD) { /* Pairwise merge */
+ do {
+ p2 = *EVAL(p2) = f1 + size2 - list1 + list2;
+ if (sense > 0)
+ swap (f1, f1 + size);
+ } while ((f1 += size2) < f2);
+ } else { /* Natural merge */
+ l2 = f2;
+ for (f2 = f1 + size2; f2 < l2; f2 += size2) {
+ if ((cmp(f2-size, f2) > 0) != sense) {
+ p2 = *EVAL(p2) = f2 - list1 + list2;
+ if (sense > 0)
+ reverse(f1, f2-size);
+ f1 = f2;
+ }
+ }
+ if (sense > 0)
+ reverse (f1, f2-size);
+ f1 = f2;
+ if (f2 < last || cmp(f2 - size, f2) > 0)
+ p2 = *EVAL(p2) = f2 - list1 + list2;
+ else
+ p2 = *EVAL(p2) = list2 + n*size;
+ }
+ }
+#else /* pairwise merge only. */
+ for (f1 = list1, p2 = list2; f1 < last; f1 += size2) {
+ p2 = *EVAL(p2) = p2 + size2;
+ if (cmp (f1, f1 + size) > 0)
+ swap(f1, f1 + size);
+ }
+#endif /* NATURAL */
+}
+
+/*
+ * This is to avoid out-of-bounds addresses in sorting the
+ * last 4 elements.
+ */
+static void
+insertionsort(a, n, size, cmp)
+ u_char *a;
+ size_t n, size;
+ int (*cmp)(const void *, const void *);
+{
+ u_char *ai, *s, *t, *u, tmp;
+ int i;
+
+ for (ai = a+size; --n >= 1; ai += size)
+ for (t = ai; t > a; t -= size) {
+ u = t - size;
+ if (cmp(u, t) <= 0)
+ break;
+ swap(u, t);
+ }
+}
diff --git a/lib/libc/stdlib/ptsname.3 b/lib/libc/stdlib/ptsname.3
new file mode 100644
index 0000000..48da3bd
--- /dev/null
+++ b/lib/libc/stdlib/ptsname.3
@@ -0,0 +1,160 @@
+.\"
+.\" Copyright (c) 2002 The FreeBSD Project, Inc.
+.\" All rights reserved.
+.\"
+.\" This software includes code contributed to the FreeBSD Project
+.\" by Ryan Younce of North Carolina State University.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the FreeBSD Project nor the names of its
+.\" contributors may be used to endorse or promote products derived from
+.\" this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE FREEBSD PROJECT AND CONTRIBUTORS
+.\" ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+.\" LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+.\" PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FREEBSD PROJECT
+.\" OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+.\" TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+.\" PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+.\" LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+.\" NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+.\" SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 20, 2008
+.Dt PTSNAME 3
+.Os
+.Sh NAME
+.Nm grantpt ,
+.Nm ptsname ,
+.Nm unlockpt
+.Nd pseudo-terminal access functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fn grantpt "int fildes"
+.Ft "char *"
+.Fn ptsname "int fildes"
+.Ft int
+.Fn unlockpt "int fildes"
+.Sh DESCRIPTION
+The
+.Fn grantpt ,
+.Fn ptsname ,
+and
+.Fn unlockpt
+functions allow access to pseudo-terminal devices.
+These three functions accept a file descriptor that references the
+master half of a pseudo-terminal pair.
+This file descriptor is created with
+.Xr posix_openpt 2 .
+.Pp
+The
+.Fn grantpt
+function is used to establish ownership and permissions
+of the slave device counterpart to the master device
+specified with
+.Fa fildes .
+The slave device's ownership is set to the real user ID
+of the calling process, and the permissions are set to
+user readable-writable and group writable.
+The group owner of the slave device is also set to the
+group
+.Dq Li tty .
+.Pp
+The
+.Fn ptsname
+function returns the full pathname of the slave device
+counterpart to the master device specified with
+.Fa fildes .
+This value can be used
+to subsequently open the appropriate slave after
+.Xr posix_openpt 2
+and
+.Fn grantpt
+have been called.
+.Pp
+The
+.Fn unlockpt
+function clears the lock held on the pseudo-terminal pair
+for the master device specified with
+.Fa fildes .
+.Sh RETURN VALUES
+.Rv -std grantpt unlockpt
+.Pp
+The
+.Fn ptsname
+function returns a pointer to the name
+of the slave device on success; otherwise a
+.Dv NULL
+pointer is returned.
+.Sh ERRORS
+The
+.Fn grantpt
+and
+.Fn unlockpt
+functions may fail and set
+.Va errno
+to:
+.Bl -tag -width Er
+.It Bq Er EBADF
+.Fa fildes
+is not a valid open file descriptor.
+.It Bq Er EINVAL
+.Fa fildes
+is not a master pseudo-terminal device.
+.El
+.Pp
+In addition, the
+.Fn grantpt
+function may set
+.Va errno
+to:
+.Bl -tag -width Er
+.It Bq Er EACCES
+The slave pseudo-terminal device could not be accessed.
+.El
+.Sh SEE ALSO
+.Xr posix_openpt 2 ,
+.Xr pts 4 ,
+.Xr tty 4
+.Sh STANDARDS
+The
+.Fn ptsname
+function conforms to
+.St -p1003.1-2008 .
+.Pp
+This implementation of
+.Fn grantpt
+and
+.Fn unlockpt
+does not conform to
+.St -p1003.1-2008 ,
+because it depends on
+.Xr posix_openpt 2
+to create the pseudo-terminal device with proper permissions in place.
+It only validates whether
+.Fa fildes
+is a valid pseudo-terminal master device.
+Future revisions of the specification will likely allow this behaviour,
+as stated by the Austin Group.
+.Sh HISTORY
+The
+.Fn grantpt ,
+.Fn ptsname
+and
+.Fn unlockpt
+functions appeared in
+.Fx 5.0 .
diff --git a/lib/libc/stdlib/ptsname.c b/lib/libc/stdlib/ptsname.c
new file mode 100644
index 0000000..40b140d
--- /dev/null
+++ b/lib/libc/stdlib/ptsname.c
@@ -0,0 +1,93 @@
+/*-
+ * Copyright (c) 2008 Ed Schouten <ed@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Portions of this software were developed under sponsorship from Snow
+ * B.V., the Netherlands.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+__FBSDID("$FreeBSD$");
+#endif /* not lint */
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/ioctl.h>
+
+#include <errno.h>
+#include <paths.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+
+/*
+ * __isptmaster(): return whether the file descriptor refers to a
+ * pseudo-terminal master device.
+ */
+static int
+__isptmaster(int fildes)
+{
+
+ if (_ioctl(fildes, TIOCPTMASTER) == 0)
+ return (0);
+
+ if (errno != EBADF)
+ errno = EINVAL;
+
+ return (-1);
+}
+
+/*
+ * In our implementation, grantpt() and unlockpt() don't actually have
+ * any use, because PTY's are created on the fly and already have proper
+ * permissions upon creation.
+ *
+ * Just make sure `fildes' actually points to a real PTY master device.
+ */
+__strong_reference(__isptmaster, grantpt);
+__strong_reference(__isptmaster, unlockpt);
+
+/*
+ * ptsname(): return the pathname of the slave pseudo-terminal device
+ * associated with the specified master.
+ */
+char *
+ptsname(int fildes)
+{
+ static char pt_slave[sizeof _PATH_DEV + SPECNAMELEN] = _PATH_DEV;
+ char *ret = NULL;
+ int sverrno = errno;
+
+ /* Make sure fildes points to a master device. */
+ if (__isptmaster(fildes) != 0)
+ goto done;
+
+ if (fdevname_r(fildes, pt_slave + (sizeof _PATH_DEV - 1),
+ sizeof pt_slave - (sizeof _PATH_DEV - 1)) != NULL)
+ ret = pt_slave;
+
+done: /* Make sure ptsname() does not overwrite errno. */
+ errno = sverrno;
+ return (ret);
+}
diff --git a/lib/libc/stdlib/qsort.3 b/lib/libc/stdlib/qsort.3
new file mode 100644
index 0000000..0f7ef73
--- /dev/null
+++ b/lib/libc/stdlib/qsort.3
@@ -0,0 +1,286 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)qsort.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd September 30, 2003
+.Dt QSORT 3
+.Os
+.Sh NAME
+.Nm qsort , qsort_r , heapsort , mergesort
+.Nd sort functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft void
+.Fo qsort
+.Fa "void *base"
+.Fa "size_t nmemb"
+.Fa "size_t size"
+.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]"
+.Fc
+.Ft void
+.Fo qsort_r
+.Fa "void *base"
+.Fa "size_t nmemb"
+.Fa "size_t size"
+.Fa "void *thunk"
+.Fa "int \*[lp]*compar\*[rp]\*[lp]void *, const void *, const void *\*[rp]"
+.Fc
+.Ft int
+.Fo heapsort
+.Fa "void *base"
+.Fa "size_t nmemb"
+.Fa "size_t size"
+.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]"
+.Fc
+.Ft int
+.Fo mergesort
+.Fa "void *base"
+.Fa "size_t nmemb"
+.Fa "size_t size"
+.Fa "int \*[lp]*compar\*[rp]\*[lp]const void *, const void *\*[rp]"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn qsort
+function is a modified partition-exchange sort, or quicksort.
+The
+.Fn heapsort
+function is a modified selection sort.
+The
+.Fn mergesort
+function is a modified merge sort with exponential search
+intended for sorting data with pre-existing order.
+.Pp
+The
+.Fn qsort
+and
+.Fn heapsort
+functions sort an array of
+.Fa nmemb
+objects, the initial member of which is pointed to by
+.Fa base .
+The size of each object is specified by
+.Fa size .
+The
+.Fn mergesort
+function
+behaves similarly, but
+.Em requires
+that
+.Fa size
+be greater than
+.Dq "sizeof(void *) / 2" .
+.Pp
+The contents of the array
+.Fa base
+are sorted in ascending order according to
+a comparison function pointed to by
+.Fa compar ,
+which requires two arguments pointing to the objects being
+compared.
+.Pp
+The comparison function must return an integer less than, equal to, or
+greater than zero if the first argument is considered to be respectively
+less than, equal to, or greater than the second.
+.Pp
+The
+.Fn qsort_r
+function behaves identically to
+.Fn qsort ,
+except that it takes an additional argument,
+.Fa thunk ,
+which is passed unchanged as the first argument to function pointed to
+.Fa compar .
+This allows the comparison function to access additional
+data without using global variables, and thus
+.Fn qsort_r
+is suitable for use in functions which must be reentrant.
+.Pp
+The algorithms implemented by
+.Fn qsort ,
+.Fn qsort_r ,
+and
+.Fn heapsort
+are
+.Em not
+stable, that is, if two members compare as equal, their order in
+the sorted array is undefined.
+The
+.Fn mergesort
+algorithm is stable.
+.Pp
+The
+.Fn qsort
+and
+.Fn qsort_r
+functions are an implementation of C.A.R.
+Hoare's
+.Dq quicksort
+algorithm,
+a variant of partition-exchange sorting; in particular, see
+.An D.E. Knuth Ns 's
+.%T "Algorithm Q" .
+.Sy Quicksort
+takes O N lg N average time.
+This implementation uses median selection to avoid its
+O N**2 worst-case behavior.
+.Pp
+The
+.Fn heapsort
+function is an implementation of
+.An "J.W.J. William" Ns 's
+.Dq heapsort
+algorithm,
+a variant of selection sorting; in particular, see
+.An "D.E. Knuth" Ns 's
+.%T "Algorithm H" .
+.Sy Heapsort
+takes O N lg N worst-case time.
+Its
+.Em only
+advantage over
+.Fn qsort
+is that it uses almost no additional memory; while
+.Fn qsort
+does not allocate memory, it is implemented using recursion.
+.Pp
+The function
+.Fn mergesort
+requires additional memory of size
+.Fa nmemb *
+.Fa size
+bytes; it should be used only when space is not at a premium.
+The
+.Fn mergesort
+function
+is optimized for data with pre-existing order; its worst case
+time is O N lg N; its best case is O N.
+.Pp
+Normally,
+.Fn qsort
+is faster than
+.Fn mergesort
+is faster than
+.Fn heapsort .
+Memory availability and pre-existing order in the data can make this
+untrue.
+.Sh RETURN VALUES
+The
+.Fn qsort
+and
+.Fn qsort_r
+functions
+return no value.
+.Pp
+.Rv -std heapsort mergesort
+.Sh COMPATIBILITY
+Previous versions of
+.Fn qsort
+did not permit the comparison routine itself to call
+.Fn qsort 3 .
+This is no longer true.
+.Sh ERRORS
+The
+.Fn heapsort
+and
+.Fn mergesort
+functions succeed unless:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The
+.Fa size
+argument is zero, or,
+the
+.Fa size
+argument to
+.Fn mergesort
+is less than
+.Dq "sizeof(void *) / 2" .
+.It Bq Er ENOMEM
+The
+.Fn heapsort
+or
+.Fn mergesort
+functions
+were unable to allocate memory.
+.El
+.Sh SEE ALSO
+.Xr sort 1 ,
+.Xr radixsort 3
+.Rs
+.%A Hoare, C.A.R.
+.%D 1962
+.%T "Quicksort"
+.%J "The Computer Journal"
+.%V 5:1
+.%P pp. 10-15
+.Re
+.Rs
+.%A Williams, J.W.J
+.%D 1964
+.%T "Heapsort"
+.%J "Communications of the ACM"
+.%V 7:1
+.%P pp. 347-348
+.Re
+.Rs
+.%A Knuth, D.E.
+.%D 1968
+.%B "The Art of Computer Programming"
+.%V Vol. 3
+.%T "Sorting and Searching"
+.%P pp. 114-123, 145-149
+.Re
+.Rs
+.%A McIlroy, P.M.
+.%T "Optimistic Sorting and Information Theoretic Complexity"
+.%J "Fourth Annual ACM-SIAM Symposium on Discrete Algorithms"
+.%V January 1992
+.Re
+.Rs
+.%A Bentley, J.L.
+.%A McIlroy, M.D.
+.%T "Engineering a Sort Function"
+.%J "Software--Practice and Experience"
+.%V Vol. 23(11)
+.%P pp. 1249-1265
+.%D November\ 1993
+.Re
+.Sh STANDARDS
+The
+.Fn qsort
+function
+conforms to
+.St -isoC .
diff --git a/lib/libc/stdlib/qsort.c b/lib/libc/stdlib/qsort.c
new file mode 100644
index 0000000..3687b05
--- /dev/null
+++ b/lib/libc/stdlib/qsort.c
@@ -0,0 +1,195 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+
+#ifdef I_AM_QSORT_R
+typedef int cmp_t(void *, const void *, const void *);
+#else
+typedef int cmp_t(const void *, const void *);
+#endif
+static inline char *med3(char *, char *, char *, cmp_t *, void *);
+static inline void swapfunc(char *, char *, int, int);
+
+#define min(a, b) (a) < (b) ? a : b
+
+/*
+ * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
+ */
+#define swapcode(TYPE, parmi, parmj, n) { \
+ long i = (n) / sizeof (TYPE); \
+ TYPE *pi = (TYPE *) (parmi); \
+ TYPE *pj = (TYPE *) (parmj); \
+ do { \
+ TYPE t = *pi; \
+ *pi++ = *pj; \
+ *pj++ = t; \
+ } while (--i > 0); \
+}
+
+#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
+ es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+
+static inline void
+swapfunc(a, b, n, swaptype)
+ char *a, *b;
+ int n, swaptype;
+{
+ if(swaptype <= 1)
+ swapcode(long, a, b, n)
+ else
+ swapcode(char, a, b, n)
+}
+
+#define swap(a, b) \
+ if (swaptype == 0) { \
+ long t = *(long *)(a); \
+ *(long *)(a) = *(long *)(b); \
+ *(long *)(b) = t; \
+ } else \
+ swapfunc(a, b, es, swaptype)
+
+#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
+
+#ifdef I_AM_QSORT_R
+#define CMP(t, x, y) (cmp((t), (x), (y)))
+#else
+#define CMP(t, x, y) (cmp((x), (y)))
+#endif
+
+static inline char *
+med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk
+#ifndef I_AM_QSORT_R
+__unused
+#endif
+)
+{
+ return CMP(thunk, a, b) < 0 ?
+ (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
+ :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
+}
+
+#ifdef I_AM_QSORT_R
+void
+qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp)
+#else
+#define thunk NULL
+void
+qsort(void *a, size_t n, size_t es, cmp_t *cmp)
+#endif
+{
+ char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+ size_t d, r;
+ int cmp_result;
+ int swaptype, swap_cnt;
+
+loop: SWAPINIT(a, es);
+ swap_cnt = 0;
+ if (n < 7) {
+ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+ for (pl = pm;
+ pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+ pm = (char *)a + (n / 2) * es;
+ if (n > 7) {
+ pl = a;
+ pn = (char *)a + (n - 1) * es;
+ if (n > 40) {
+ d = (n / 8) * es;
+ pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
+ pm = med3(pm - d, pm, pm + d, cmp, thunk);
+ pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
+ }
+ pm = med3(pl, pm, pn, cmp, thunk);
+ }
+ swap(a, pm);
+ pa = pb = (char *)a + es;
+
+ pc = pd = (char *)a + (n - 1) * es;
+ for (;;) {
+ while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) {
+ if (cmp_result == 0) {
+ swap_cnt = 1;
+ swap(pa, pb);
+ pa += es;
+ }
+ pb += es;
+ }
+ while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) {
+ if (cmp_result == 0) {
+ swap_cnt = 1;
+ swap(pc, pd);
+ pd -= es;
+ }
+ pc -= es;
+ }
+ if (pb > pc)
+ break;
+ swap(pb, pc);
+ swap_cnt = 1;
+ pb += es;
+ pc -= es;
+ }
+ if (swap_cnt == 0) { /* Switch to insertion sort */
+ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+ for (pl = pm;
+ pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+
+ pn = (char *)a + n * es;
+ r = min(pa - (char *)a, pb - pa);
+ vecswap(a, pb - r, r);
+ r = min(pd - pc, pn - pd - es);
+ vecswap(pb, pn - r, r);
+ if ((r = pb - pa) > es)
+#ifdef I_AM_QSORT_R
+ qsort_r(a, r / es, es, thunk, cmp);
+#else
+ qsort(a, r / es, es, cmp);
+#endif
+ if ((r = pd - pc) > es) {
+ /* Iterate rather than recurse to save stack space */
+ a = pn - r;
+ n = r / es;
+ goto loop;
+ }
+/* qsort(pn - r, r / es, es, cmp);*/
+}
diff --git a/lib/libc/stdlib/qsort_r.c b/lib/libc/stdlib/qsort_r.c
new file mode 100644
index 0000000..d868736
--- /dev/null
+++ b/lib/libc/stdlib/qsort_r.c
@@ -0,0 +1,8 @@
+/*
+ * This file is in the public domain. Originally written by Garrett
+ * A. Wollman.
+ *
+ * $FreeBSD$
+ */
+#define I_AM_QSORT_R
+#include "qsort.c"
diff --git a/lib/libc/stdlib/quick_exit.3 b/lib/libc/stdlib/quick_exit.3
new file mode 100644
index 0000000..06fde8b
--- /dev/null
+++ b/lib/libc/stdlib/quick_exit.3
@@ -0,0 +1,57 @@
+.\" Copyright (c) 2011 David Chisnall
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd December 7, 2011
+.Dt QUICK_EXIT 3
+.Os
+.Sh NAME
+.Nm quick_exit
+.Nd exits a program quickly, running minimal cleanup
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft _Noreturn void
+.Fn quick_exit "void"
+.Sh DESCRIPTION
+The
+.Fn quick_exit
+function exits the program quickly calling any cleanup functions registered
+with
+.Xr at_quick_exit 3
+but not any C++ destructors or cleanup code registered with
+.Xr atexit 3 .
+.Sh RETURN VALUES
+The
+.Fn quick_exit
+function does not return.
+.Sh SEE ALSO
+.Xr at_quick_exit 3 ,
+.Xr exit 3
+.Sh STANDARDS
+The
+.Fn quick_exit
+function conforms to the C1x draft specification.
diff --git a/lib/libc/stdlib/quick_exit.c b/lib/libc/stdlib/quick_exit.c
new file mode 100644
index 0000000..ef8cdb1
--- /dev/null
+++ b/lib/libc/stdlib/quick_exit.c
@@ -0,0 +1,80 @@
+/*-
+ * Copyright (c) 2011 David Chisnall
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdlib.h>
+#include <pthread.h>
+
+/**
+ * Linked list of quick exit handlers. This is simpler than the atexit()
+ * version, because it is not required to support C++ destructors or
+ * DSO-specific cleanups.
+ */
+struct quick_exit_handler {
+ struct quick_exit_handler *next;
+ void (*cleanup)(void);
+};
+
+/**
+ * Lock protecting the handlers list.
+ */
+static pthread_mutex_t atexit_mutex = PTHREAD_MUTEX_INITIALIZER;
+/**
+ * Stack of cleanup handlers. These will be invoked in reverse order when
+ */
+static struct quick_exit_handler *handlers;
+
+int
+at_quick_exit(void (*func)(void))
+{
+ struct quick_exit_handler *h;
+
+ h = malloc(sizeof(*h));
+
+ if (NULL == h)
+ return (1);
+ h->cleanup = func;
+ pthread_mutex_lock(&atexit_mutex);
+ h->next = handlers;
+ handlers = h;
+ pthread_mutex_unlock(&atexit_mutex);
+ return (0);
+}
+
+void
+quick_exit(int status)
+{
+ struct quick_exit_handler *h;
+
+ /*
+ * XXX: The C++ spec requires us to call std::terminate if there is an
+ * exception here.
+ */
+ for (h = handlers; NULL != h; h = h->next)
+ h->cleanup();
+ _Exit(status);
+}
diff --git a/lib/libc/stdlib/radixsort.3 b/lib/libc/stdlib/radixsort.3
new file mode 100644
index 0000000..dfa65f1
--- /dev/null
+++ b/lib/libc/stdlib/radixsort.3
@@ -0,0 +1,160 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)radixsort.3 8.2 (Berkeley) 1/27/94
+.\" $FreeBSD$
+.\"
+.Dd January 27, 1994
+.Dt RADIXSORT 3
+.Os
+.Sh NAME
+.Nm radixsort , sradixsort
+.Nd radix sort
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In limits.h
+.In stdlib.h
+.Ft int
+.Fn radixsort "const unsigned char **base" "int nmemb" "const unsigned char *table" "unsigned endbyte"
+.Ft int
+.Fn sradixsort "const unsigned char **base" "int nmemb" "const unsigned char *table" "unsigned endbyte"
+.Sh DESCRIPTION
+The
+.Fn radixsort
+and
+.Fn sradixsort
+functions
+are implementations of radix sort.
+.Pp
+These functions sort an array of pointers to byte strings, the initial
+member of which is referenced by
+.Fa base .
+The byte strings may contain any values; the end of each string
+is denoted by the user-specified value
+.Fa endbyte .
+.Pp
+Applications may specify a sort order by providing the
+.Fa table
+argument.
+If
+.Pf non- Dv NULL ,
+.Fa table
+must reference an array of
+.Dv UCHAR_MAX
++ 1 bytes which contains the sort
+weight of each possible byte value.
+The end-of-string byte must have a sort weight of 0 or 255
+(for sorting in reverse order).
+More than one byte may have the same sort weight.
+The
+.Fa table
+argument
+is useful for applications which wish to sort different characters
+equally, for example, providing a table with the same weights
+for A-Z as for a-z will result in a case-insensitive sort.
+If
+.Fa table
+is NULL, the contents of the array are sorted in ascending order
+according to the
+.Tn ASCII
+order of the byte strings they reference and
+.Fa endbyte
+has a sorting weight of 0.
+.Pp
+The
+.Fn sradixsort
+function is stable, that is, if two elements compare as equal, their
+order in the sorted array is unchanged.
+The
+.Fn sradixsort
+function uses additional memory sufficient to hold
+.Fa nmemb
+pointers.
+.Pp
+The
+.Fn radixsort
+function is not stable, but uses no additional memory.
+.Pp
+These functions are variants of most-significant-byte radix sorting; in
+particular, see
+.An "D.E. Knuth" Ns 's
+.%T "Algorithm R"
+and section 5.2.5, exercise 10.
+They take linear time relative to the number of bytes in the strings.
+.Sh RETURN VALUES
+.Rv -std radixsort
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value of the
+.Fa endbyte
+element of
+.Fa table
+is not 0 or 255.
+.El
+.Pp
+Additionally, the
+.Fn sradixsort
+function
+may fail and set
+.Va errno
+for any of the errors specified for the library routine
+.Xr malloc 3 .
+.Sh SEE ALSO
+.Xr sort 1 ,
+.Xr qsort 3
+.Pp
+.Rs
+.%A Knuth, D.E.
+.%D 1968
+.%B "The Art of Computer Programming"
+.%T "Sorting and Searching"
+.%V Vol. 3
+.%P pp. 170-178
+.Re
+.Rs
+.%A Paige, R.
+.%D 1987
+.%T "Three Partition Refinement Algorithms"
+.%J "SIAM J. Comput."
+.%V Vol. 16
+.%N No. 6
+.Re
+.Rs
+.%A McIlroy, P.
+.%D 1993
+.%B "Engineering Radix Sort"
+.%T "Computing Systems"
+.%V Vol. 6:1
+.%P pp. 5-27
+.Re
+.Sh HISTORY
+The
+.Fn radixsort
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/stdlib/radixsort.c b/lib/libc/stdlib/radixsort.c
new file mode 100644
index 0000000..82ff1bc
--- /dev/null
+++ b/lib/libc/stdlib/radixsort.c
@@ -0,0 +1,327 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Peter McIlroy and by Dan Bernstein at New York University,
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)radixsort.c 8.2 (Berkeley) 4/28/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Radixsort routines.
+ *
+ * Program r_sort_a() is unstable but uses O(logN) extra memory for a stack.
+ * Use radixsort(a, n, trace, endchar) for this case.
+ *
+ * For stable sorting (using N extra pointers) use sradixsort(), which calls
+ * r_sort_b().
+ *
+ * For a description of this code, see D. McIlroy, P. McIlroy, K. Bostic,
+ * "Engineering Radix Sort".
+ */
+
+#include <sys/types.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <errno.h>
+
+typedef struct {
+ const u_char **sa;
+ int sn, si;
+} stack;
+
+static inline void simplesort
+(const u_char **, int, int, const u_char *, u_int);
+static void r_sort_a(const u_char **, int, int, const u_char *, u_int);
+static void r_sort_b(const u_char **, const u_char **, int, int,
+ const u_char *, u_int);
+
+#define THRESHOLD 20 /* Divert to simplesort(). */
+#define SIZE 512 /* Default stack size. */
+
+#define SETUP { \
+ if (tab == NULL) { \
+ tr = tr0; \
+ for (c = 0; c < endch; c++) \
+ tr0[c] = c + 1; \
+ tr0[c] = 0; \
+ for (c++; c < 256; c++) \
+ tr0[c] = c; \
+ endch = 0; \
+ } else { \
+ endch = tab[endch]; \
+ tr = tab; \
+ if (endch != 0 && endch != 255) { \
+ errno = EINVAL; \
+ return (-1); \
+ } \
+ } \
+}
+
+int
+radixsort(a, n, tab, endch)
+ const u_char **a, *tab;
+ int n;
+ u_int endch;
+{
+ const u_char *tr;
+ int c;
+ u_char tr0[256];
+
+ SETUP;
+ r_sort_a(a, n, 0, tr, endch);
+ return (0);
+}
+
+int
+sradixsort(a, n, tab, endch)
+ const u_char **a, *tab;
+ int n;
+ u_int endch;
+{
+ const u_char *tr, **ta;
+ int c;
+ u_char tr0[256];
+
+ SETUP;
+ if (n < THRESHOLD)
+ simplesort(a, n, 0, tr, endch);
+ else {
+ if ((ta = malloc(n * sizeof(a))) == NULL)
+ return (-1);
+ r_sort_b(a, ta, n, 0, tr, endch);
+ free(ta);
+ }
+ return (0);
+}
+
+#define empty(s) (s >= sp)
+#define pop(a, n, i) a = (--sp)->sa, n = sp->sn, i = sp->si
+#define push(a, n, i) sp->sa = a, sp->sn = n, (sp++)->si = i
+#define swap(a, b, t) t = a, a = b, b = t
+
+/* Unstable, in-place sort. */
+static void
+r_sort_a(a, n, i, tr, endch)
+ const u_char **a;
+ int n, i;
+ const u_char *tr;
+ u_int endch;
+{
+ static int count[256], nc, bmin;
+ int c;
+ const u_char **ak, *r;
+ stack s[SIZE], *sp, *sp0, *sp1, temp;
+ int *cp, bigc;
+ const u_char **an, *t, **aj, **top[256];
+
+ /* Set up stack. */
+ sp = s;
+ push(a, n, i);
+ while (!empty(s)) {
+ pop(a, n, i);
+ if (n < THRESHOLD) {
+ simplesort(a, n, i, tr, endch);
+ continue;
+ }
+ an = a + n;
+
+ /* Make character histogram. */
+ if (nc == 0) {
+ bmin = 255; /* First occupied bin, excluding eos. */
+ for (ak = a; ak < an;) {
+ c = tr[(*ak++)[i]];
+ if (++count[c] == 1 && c != endch) {
+ if (c < bmin)
+ bmin = c;
+ nc++;
+ }
+ }
+ if (sp + nc > s + SIZE) { /* Get more stack. */
+ r_sort_a(a, n, i, tr, endch);
+ continue;
+ }
+ }
+
+ /*
+ * Special case: if all strings have the same
+ * character at position i, move on to the next
+ * character.
+ */
+ if (nc == 1 && count[bmin] == n) {
+ push(a, n, i+1);
+ nc = count[bmin] = 0;
+ continue;
+ }
+
+ /*
+ * Set top[]; push incompletely sorted bins onto stack.
+ * top[] = pointers to last out-of-place element in bins.
+ * count[] = counts of elements in bins.
+ * Before permuting: top[c-1] + count[c] = top[c];
+ * during deal: top[c] counts down to top[c-1].
+ */
+ sp0 = sp1 = sp; /* Stack position of biggest bin. */
+ bigc = 2; /* Size of biggest bin. */
+ if (endch == 0) /* Special case: set top[eos]. */
+ top[0] = ak = a + count[0];
+ else {
+ ak = a;
+ top[255] = an;
+ }
+ for (cp = count + bmin; nc > 0; cp++) {
+ while (*cp == 0) /* Find next non-empty pile. */
+ cp++;
+ if (*cp > 1) {
+ if (*cp > bigc) {
+ bigc = *cp;
+ sp1 = sp;
+ }
+ push(ak, *cp, i+1);
+ }
+ top[cp-count] = ak += *cp;
+ nc--;
+ }
+ swap(*sp0, *sp1, temp); /* Play it safe -- biggest bin last. */
+
+ /*
+ * Permute misplacements home. Already home: everything
+ * before aj, and in bin[c], items from top[c] on.
+ * Inner loop:
+ * r = next element to put in place;
+ * ak = top[r[i]] = location to put the next element.
+ * aj = bottom of 1st disordered bin.
+ * Outer loop:
+ * Once the 1st disordered bin is done, ie. aj >= ak,
+ * aj<-aj + count[c] connects the bins in a linked list;
+ * reset count[c].
+ */
+ for (aj = a; aj < an; *aj = r, aj += count[c], count[c] = 0)
+ for (r = *aj; aj < (ak = --top[c = tr[r[i]]]);)
+ swap(*ak, r, t);
+ }
+}
+
+/* Stable sort, requiring additional memory. */
+static void
+r_sort_b(a, ta, n, i, tr, endch)
+ const u_char **a, **ta;
+ int n, i;
+ const u_char *tr;
+ u_int endch;
+{
+ static int count[256], nc, bmin;
+ int c;
+ const u_char **ak, **ai;
+ stack s[512], *sp, *sp0, *sp1, temp;
+ const u_char **top[256];
+ int *cp, bigc;
+
+ sp = s;
+ push(a, n, i);
+ while (!empty(s)) {
+ pop(a, n, i);
+ if (n < THRESHOLD) {
+ simplesort(a, n, i, tr, endch);
+ continue;
+ }
+
+ if (nc == 0) {
+ bmin = 255;
+ for (ak = a + n; --ak >= a;) {
+ c = tr[(*ak)[i]];
+ if (++count[c] == 1 && c != endch) {
+ if (c < bmin)
+ bmin = c;
+ nc++;
+ }
+ }
+ if (sp + nc > s + SIZE) {
+ r_sort_b(a, ta, n, i, tr, endch);
+ continue;
+ }
+ }
+
+ sp0 = sp1 = sp;
+ bigc = 2;
+ if (endch == 0) {
+ top[0] = ak = a + count[0];
+ count[0] = 0;
+ } else {
+ ak = a;
+ top[255] = a + n;
+ count[255] = 0;
+ }
+ for (cp = count + bmin; nc > 0; cp++) {
+ while (*cp == 0)
+ cp++;
+ if ((c = *cp) > 1) {
+ if (c > bigc) {
+ bigc = c;
+ sp1 = sp;
+ }
+ push(ak, c, i+1);
+ }
+ top[cp-count] = ak += c;
+ *cp = 0; /* Reset count[]. */
+ nc--;
+ }
+ swap(*sp0, *sp1, temp);
+
+ for (ak = ta + n, ai = a+n; ak > ta;) /* Copy to temp. */
+ *--ak = *--ai;
+ for (ak = ta+n; --ak >= ta;) /* Deal to piles. */
+ *--top[tr[(*ak)[i]]] = *ak;
+ }
+}
+
+static inline void
+simplesort(a, n, b, tr, endch) /* insertion sort */
+ const u_char **a;
+ int n, b;
+ const u_char *tr;
+ u_int endch;
+{
+ u_char ch;
+ const u_char **ak, **ai, *s, *t;
+
+ for (ak = a+1; --n >= 1; ak++)
+ for (ai = ak; ai > a; ai--) {
+ for (s = ai[0] + b, t = ai[-1] + b;
+ (ch = tr[*s]) != endch; s++, t++)
+ if (ch != tr[*t])
+ break;
+ if (ch >= tr[*t])
+ break;
+ swap(ai[0], ai[-1], s);
+ }
+}
diff --git a/lib/libc/stdlib/rand.3 b/lib/libc/stdlib/rand.3
new file mode 100644
index 0000000..3eb1a1d
--- /dev/null
+++ b/lib/libc/stdlib/rand.3
@@ -0,0 +1,126 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)rand.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd October 6, 2010
+.Dt RAND 3
+.Os
+.Sh NAME
+.Nm rand ,
+.Nm srand ,
+.Nm sranddev ,
+.Nm rand_r
+.Nd bad random number generator
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft void
+.Fn srand "unsigned seed"
+.Ft void
+.Fn sranddev void
+.Ft int
+.Fn rand void
+.Ft int
+.Fn rand_r "unsigned *ctx"
+.Sh DESCRIPTION
+.Bf -symbolic
+These interfaces are obsoleted by
+.Xr random 3 .
+.Ef
+.Pp
+The
+.Fn rand
+function computes a sequence of pseudo-random integers in the range
+of 0 to
+.Dv RAND_MAX
+(as defined by the header file
+.In stdlib.h ) .
+.Pp
+The
+.Fn srand
+function sets its argument
+.Fa seed
+as the seed for a new sequence of
+pseudo-random numbers to be returned by
+.Fn rand .
+These sequences are repeatable by calling
+.Fn srand
+with the same seed value.
+.Pp
+If no
+.Fa seed
+value is provided, the functions are automatically
+seeded with a value of 1.
+.Pp
+The
+.Fn sranddev
+function initializes a seed using the
+.Xr random 4
+random number device which returns good random numbers.
+However, the
+.Fn rand
+function still remains unsuitable for cryptographic use.
+.Pp
+The
+.Fn rand_r
+function
+provides the same functionality as
+.Fn rand .
+A pointer to the context value
+.Fa ctx
+must be supplied by the caller.
+.Pp
+For better generator quality, use
+.Xr random 3
+or
+.Xr lrand48 3 .
+Applications requiring cryptographic quality randomness should use
+.Xr arc4random 3 .
+.Sh SEE ALSO
+.Xr arc4random 3 ,
+.Xr lrand48 3 ,
+.Xr random 3 ,
+.Xr random 4
+.Sh STANDARDS
+The
+.Fn rand
+and
+.Fn srand
+functions
+conform to
+.St -isoC .
+.Pp
+The
+.Fn rand_r
+function is as proposed in the POSIX.4a Draft #6 document.
diff --git a/lib/libc/stdlib/rand.c b/lib/libc/stdlib/rand.c
new file mode 100644
index 0000000..077c1ba
--- /dev/null
+++ b/lib/libc/stdlib/rand.c
@@ -0,0 +1,168 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * Posix rand_r function added May 1999 by Wes Peters <wes@softweyr.com>.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rand.c 8.1 (Berkeley) 6/14/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/time.h> /* for sranddev() */
+#include <sys/types.h>
+#include <fcntl.h> /* for sranddev() */
+#include <stdlib.h>
+#include <unistd.h> /* for sranddev() */
+#include "un-namespace.h"
+
+#ifdef TEST
+#include <stdio.h>
+#endif /* TEST */
+
+static int
+do_rand(unsigned long *ctx)
+{
+#ifdef USE_WEAK_SEEDING
+/*
+ * Historic implementation compatibility.
+ * The random sequences do not vary much with the seed,
+ * even with overflowing.
+ */
+ return ((*ctx = *ctx * 1103515245 + 12345) % ((u_long)RAND_MAX + 1));
+#else /* !USE_WEAK_SEEDING */
+/*
+ * Compute x = (7^5 * x) mod (2^31 - 1)
+ * without overflowing 31 bits:
+ * (2^31 - 1) = 127773 * (7^5) + 2836
+ * From "Random number generators: good ones are hard to find",
+ * Park and Miller, Communications of the ACM, vol. 31, no. 10,
+ * October 1988, p. 1195.
+ */
+ long hi, lo, x;
+
+ /* Can't be initialized with 0, so use another value. */
+ if (*ctx == 0)
+ *ctx = 123459876;
+ hi = *ctx / 127773;
+ lo = *ctx % 127773;
+ x = 16807 * lo - 2836 * hi;
+ if (x < 0)
+ x += 0x7fffffff;
+ return ((*ctx = x) % ((u_long)RAND_MAX + 1));
+#endif /* !USE_WEAK_SEEDING */
+}
+
+
+int
+rand_r(unsigned int *ctx)
+{
+ u_long val = (u_long) *ctx;
+ int r = do_rand(&val);
+
+ *ctx = (unsigned int) val;
+ return (r);
+}
+
+
+static u_long next = 1;
+
+int
+rand()
+{
+ return (do_rand(&next));
+}
+
+void
+srand(seed)
+u_int seed;
+{
+ next = seed;
+}
+
+
+/*
+ * sranddev:
+ *
+ * Many programs choose the seed value in a totally predictable manner.
+ * This often causes problems. We seed the generator using the much more
+ * secure random(4) interface.
+ */
+void
+sranddev()
+{
+ int fd, done;
+
+ done = 0;
+ fd = _open("/dev/random", O_RDONLY, 0);
+ if (fd >= 0) {
+ if (_read(fd, (void *) &next, sizeof(next)) == sizeof(next))
+ done = 1;
+ _close(fd);
+ }
+
+ if (!done) {
+ struct timeval tv;
+ unsigned long junk;
+
+ gettimeofday(&tv, NULL);
+ srand((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);
+ }
+}
+
+
+#ifdef TEST
+
+main()
+{
+ int i;
+ unsigned myseed;
+
+ printf("seeding rand with 0x19610910: \n");
+ srand(0x19610910);
+
+ printf("generating three pseudo-random numbers:\n");
+ for (i = 0; i < 3; i++)
+ {
+ printf("next random number = %d\n", rand());
+ }
+
+ printf("generating the same sequence with rand_r:\n");
+ myseed = 0x19610910;
+ for (i = 0; i < 3; i++)
+ {
+ printf("next random number = %d\n", rand_r(&myseed));
+ }
+
+ return 0;
+}
+
+#endif /* TEST */
+
diff --git a/lib/libc/stdlib/random.3 b/lib/libc/stdlib/random.3
new file mode 100644
index 0000000..c6502bf
--- /dev/null
+++ b/lib/libc/stdlib/random.3
@@ -0,0 +1,196 @@
+.\" Copyright (c) 1983, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)random.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt RANDOM 3
+.Os
+.Sh NAME
+.Nm random ,
+.Nm srandom ,
+.Nm srandomdev ,
+.Nm initstate ,
+.Nm setstate
+.Nd better random number generator; routines for changing generators
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft long
+.Fn random void
+.Ft void
+.Fn srandom "unsigned long seed"
+.Ft void
+.Fn srandomdev void
+.Ft char *
+.Fn initstate "unsigned long seed" "char *state" "long n"
+.Ft char *
+.Fn setstate "char *state"
+.Sh DESCRIPTION
+The
+.Fn random
+function
+uses a non-linear additive feedback random number generator employing a
+default table of size 31 long integers to return successive pseudo-random
+numbers in the range from 0 to
+.if t 2\u\s731\s10\d\(mi1.
+.if n (2**31)\(mi1.
+The period of this random number generator is very large, approximately
+.if t 16\(mu(2\u\s731\s10\d\(mi1).
+.if n 16*((2**31)\(mi1).
+.Pp
+The
+.Fn random
+and
+.Fn srandom
+functions have (almost) the same calling sequence and initialization properties as the
+.Xr rand 3
+and
+.Xr srand 3
+functions.
+The difference is that
+.Xr rand 3
+produces a much less random sequence \(em in fact, the low dozen bits
+generated by rand go through a cyclic pattern.
+All the bits generated by
+.Fn random
+are usable.
+For example,
+.Sq Li random()&01
+will produce a random binary
+value.
+.Pp
+Like
+.Xr rand 3 ,
+.Fn random
+will by default produce a sequence of numbers that can be duplicated
+by calling
+.Fn srandom
+with
+.Ql 1
+as the seed.
+.Pp
+The
+.Fn srandomdev
+routine initializes a state array using the
+.Xr random 4
+random number device which returns good random numbers,
+suitable for cryptographic use.
+Note that this particular seeding
+procedure can generate states which are impossible to reproduce by
+calling
+.Fn srandom
+with any value, since the succeeding terms in the
+state buffer are no longer derived from the LC algorithm applied to
+a fixed seed.
+.Pp
+The
+.Fn initstate
+routine allows a state array, passed in as an argument, to be initialized
+for future use.
+The size of the state array (in bytes) is used by
+.Fn initstate
+to decide how sophisticated a random number generator it should use \(em the
+more state, the better the random numbers will be.
+(Current "optimal" values for the amount of state information are
+8, 32, 64, 128, and 256 bytes; other amounts will be rounded down to
+the nearest known amount.
+Using less than 8 bytes will cause an error.)
+The seed for the initialization (which specifies a starting point for
+the random number sequence, and provides for restarting at the same
+point) is also an argument.
+The
+.Fn initstate
+function
+returns a pointer to the previous state information array.
+.Pp
+Once a state has been initialized, the
+.Fn setstate
+routine provides for rapid switching between states.
+The
+.Fn setstate
+function
+returns a pointer to the previous state array; its
+argument state array is used for further random number generation
+until the next call to
+.Fn initstate
+or
+.Fn setstate .
+.Pp
+Once a state array has been initialized, it may be restarted at a
+different point either by calling
+.Fn initstate
+(with the desired seed, the state array, and its size) or by calling
+both
+.Fn setstate
+(with the state array) and
+.Fn srandom
+(with the desired seed).
+The advantage of calling both
+.Fn setstate
+and
+.Fn srandom
+is that the size of the state array does not have to be remembered after
+it is initialized.
+.Pp
+With 256 bytes of state information, the period of the random number
+generator is greater than
+.if t 2\u\s769\s10\d,
+.if n 2**69
+which should be sufficient for most purposes.
+.Sh DIAGNOSTICS
+If
+.Fn initstate
+is called with less than 8 bytes of state information, or if
+.Fn setstate
+detects that the state information has been garbled, error
+messages are printed on the standard error output.
+.Sh SEE ALSO
+.Xr arc4random 3 ,
+.Xr lrand48 3 ,
+.Xr rand 3 ,
+.Xr srand 3 ,
+.Xr random 4
+.Sh HISTORY
+These
+functions appeared in
+.Bx 4.2 .
+.Sh AUTHORS
+.An Earl T. Cohen
+.Sh BUGS
+About 2/3 the speed of
+.Xr rand 3 .
+.Pp
+The historical implementation used to have a very weak seeding; the
+random sequence did not vary much with the seed.
+The current implementation employs a better pseudo-random number
+generator for the initial state calculation.
+.Pp
+Applications requiring cryptographic quality randomness should use
+.Xr arc4random 3 .
diff --git a/lib/libc/stdlib/random.c b/lib/libc/stdlib/random.c
new file mode 100644
index 0000000..f7be4a7
--- /dev/null
+++ b/lib/libc/stdlib/random.c
@@ -0,0 +1,502 @@
+/*
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)random.c 8.2 (Berkeley) 5/19/95";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/time.h> /* for srandomdev() */
+#include <fcntl.h> /* for srandomdev() */
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h> /* for srandomdev() */
+#include "un-namespace.h"
+
+/*
+ * random.c:
+ *
+ * An improved random number generation package. In addition to the standard
+ * rand()/srand() like interface, this package also has a special state info
+ * interface. The initstate() routine is called with a seed, an array of
+ * bytes, and a count of how many bytes are being passed in; this array is
+ * then initialized to contain information for random number generation with
+ * that much state information. Good sizes for the amount of state
+ * information are 32, 64, 128, and 256 bytes. The state can be switched by
+ * calling the setstate() routine with the same array as was initiallized
+ * with initstate(). By default, the package runs with 128 bytes of state
+ * information and generates far better random numbers than a linear
+ * congruential generator. If the amount of state information is less than
+ * 32 bytes, a simple linear congruential R.N.G. is used.
+ *
+ * Internally, the state information is treated as an array of uint32_t's; the
+ * zeroeth element of the array is the type of R.N.G. being used (small
+ * integer); the remainder of the array is the state information for the
+ * R.N.G. Thus, 32 bytes of state information will give 7 ints worth of
+ * state information, which will allow a degree seven polynomial. (Note:
+ * the zeroeth word of state information also has some other information
+ * stored in it -- see setstate() for details).
+ *
+ * The random number generation technique is a linear feedback shift register
+ * approach, employing trinomials (since there are fewer terms to sum up that
+ * way). In this approach, the least significant bit of all the numbers in
+ * the state table will act as a linear feedback shift register, and will
+ * have period 2^deg - 1 (where deg is the degree of the polynomial being
+ * used, assuming that the polynomial is irreducible and primitive). The
+ * higher order bits will have longer periods, since their values are also
+ * influenced by pseudo-random carries out of the lower bits. The total
+ * period of the generator is approximately deg*(2**deg - 1); thus doubling
+ * the amount of state information has a vast influence on the period of the
+ * generator. Note: the deg*(2**deg - 1) is an approximation only good for
+ * large deg, when the period of the shift is the dominant factor.
+ * With deg equal to seven, the period is actually much longer than the
+ * 7*(2**7 - 1) predicted by this formula.
+ *
+ * Modified 28 December 1994 by Jacob S. Rosenberg.
+ * The following changes have been made:
+ * All references to the type u_int have been changed to unsigned long.
+ * All references to type int have been changed to type long. Other
+ * cleanups have been made as well. A warning for both initstate and
+ * setstate has been inserted to the effect that on Sparc platforms
+ * the 'arg_state' variable must be forced to begin on word boundaries.
+ * This can be easily done by casting a long integer array to char *.
+ * The overall logic has been left STRICTLY alone. This software was
+ * tested on both a VAX and Sun SpacsStation with exactly the same
+ * results. The new version and the original give IDENTICAL results.
+ * The new version is somewhat faster than the original. As the
+ * documentation says: "By default, the package runs with 128 bytes of
+ * state information and generates far better random numbers than a linear
+ * congruential generator. If the amount of state information is less than
+ * 32 bytes, a simple linear congruential R.N.G. is used." For a buffer of
+ * 128 bytes, this new version runs about 19 percent faster and for a 16
+ * byte buffer it is about 5 percent faster.
+ */
+
+/*
+ * For each of the currently supported random number generators, we have a
+ * break value on the amount of state information (you need at least this
+ * many bytes of state info to support this random number generator), a degree
+ * for the polynomial (actually a trinomial) that the R.N.G. is based on, and
+ * the separation between the two lower order coefficients of the trinomial.
+ */
+#define TYPE_0 0 /* linear congruential */
+#define BREAK_0 8
+#define DEG_0 0
+#define SEP_0 0
+
+#define TYPE_1 1 /* x**7 + x**3 + 1 */
+#define BREAK_1 32
+#define DEG_1 7
+#define SEP_1 3
+
+#define TYPE_2 2 /* x**15 + x + 1 */
+#define BREAK_2 64
+#define DEG_2 15
+#define SEP_2 1
+
+#define TYPE_3 3 /* x**31 + x**3 + 1 */
+#define BREAK_3 128
+#define DEG_3 31
+#define SEP_3 3
+
+#define TYPE_4 4 /* x**63 + x + 1 */
+#define BREAK_4 256
+#define DEG_4 63
+#define SEP_4 1
+
+/*
+ * Array versions of the above information to make code run faster --
+ * relies on fact that TYPE_i == i.
+ */
+#define MAX_TYPES 5 /* max number of types above */
+
+#ifdef USE_WEAK_SEEDING
+#define NSHUFF 0
+#else /* !USE_WEAK_SEEDING */
+#define NSHUFF 50 /* to drop some "seed -> 1st value" linearity */
+#endif /* !USE_WEAK_SEEDING */
+
+static const int degrees[MAX_TYPES] = { DEG_0, DEG_1, DEG_2, DEG_3, DEG_4 };
+static const int seps [MAX_TYPES] = { SEP_0, SEP_1, SEP_2, SEP_3, SEP_4 };
+
+/*
+ * Initially, everything is set up as if from:
+ *
+ * initstate(1, randtbl, 128);
+ *
+ * Note that this initialization takes advantage of the fact that srandom()
+ * advances the front and rear pointers 10*rand_deg times, and hence the
+ * rear pointer which starts at 0 will also end up at zero; thus the zeroeth
+ * element of the state information, which contains info about the current
+ * position of the rear pointer is just
+ *
+ * MAX_TYPES * (rptr - state) + TYPE_3 == TYPE_3.
+ */
+
+static uint32_t randtbl[DEG_3 + 1] = {
+ TYPE_3,
+#ifdef USE_WEAK_SEEDING
+/* Historic implementation compatibility */
+/* The random sequences do not vary much with the seed */
+ 0x9a319039, 0x32d9c024, 0x9b663182, 0x5da1f342, 0xde3b81e0, 0xdf0a6fb5,
+ 0xf103bc02, 0x48f340fb, 0x7449e56b, 0xbeb1dbb0, 0xab5c5918, 0x946554fd,
+ 0x8c2e680f, 0xeb3d799f, 0xb11ee0b7, 0x2d436b86, 0xda672e2a, 0x1588ca88,
+ 0xe369735d, 0x904f35f7, 0xd7158fd6, 0x6fa6f051, 0x616e6b96, 0xac94efdc,
+ 0x36413f93, 0xc622c298, 0xf5a42ab8, 0x8a88d77b, 0xf5ad9d0e, 0x8999220b,
+ 0x27fb47b9,
+#else /* !USE_WEAK_SEEDING */
+ 0x991539b1, 0x16a5bce3, 0x6774a4cd, 0x3e01511e, 0x4e508aaa, 0x61048c05,
+ 0xf5500617, 0x846b7115, 0x6a19892c, 0x896a97af, 0xdb48f936, 0x14898454,
+ 0x37ffd106, 0xb58bff9c, 0x59e17104, 0xcf918a49, 0x09378c83, 0x52c7a471,
+ 0x8d293ea9, 0x1f4fc301, 0xc3db71be, 0x39b44e1c, 0xf8a44ef9, 0x4c8b80b1,
+ 0x19edc328, 0x87bf4bdd, 0xc9b240e5, 0xe9ee4b1b, 0x4382aee7, 0x535b6b41,
+ 0xf3bec5da
+#endif /* !USE_WEAK_SEEDING */
+};
+
+/*
+ * fptr and rptr are two pointers into the state info, a front and a rear
+ * pointer. These two pointers are always rand_sep places aparts, as they
+ * cycle cyclically through the state information. (Yes, this does mean we
+ * could get away with just one pointer, but the code for random() is more
+ * efficient this way). The pointers are left positioned as they would be
+ * from the call
+ *
+ * initstate(1, randtbl, 128);
+ *
+ * (The position of the rear pointer, rptr, is really 0 (as explained above
+ * in the initialization of randtbl) because the state table pointer is set
+ * to point to randtbl[1] (as explained below).
+ */
+static uint32_t *fptr = &randtbl[SEP_3 + 1];
+static uint32_t *rptr = &randtbl[1];
+
+/*
+ * The following things are the pointer to the state information table, the
+ * type of the current generator, the degree of the current polynomial being
+ * used, and the separation between the two pointers. Note that for efficiency
+ * of random(), we remember the first location of the state information, not
+ * the zeroeth. Hence it is valid to access state[-1], which is used to
+ * store the type of the R.N.G. Also, we remember the last location, since
+ * this is more efficient than indexing every time to find the address of
+ * the last element to see if the front and rear pointers have wrapped.
+ */
+static uint32_t *state = &randtbl[1];
+static int rand_type = TYPE_3;
+static int rand_deg = DEG_3;
+static int rand_sep = SEP_3;
+static uint32_t *end_ptr = &randtbl[DEG_3 + 1];
+
+static inline uint32_t good_rand(int32_t);
+
+static inline uint32_t good_rand (x)
+ int32_t x;
+{
+#ifdef USE_WEAK_SEEDING
+/*
+ * Historic implementation compatibility.
+ * The random sequences do not vary much with the seed,
+ * even with overflowing.
+ */
+ return (1103515245 * x + 12345);
+#else /* !USE_WEAK_SEEDING */
+/*
+ * Compute x = (7^5 * x) mod (2^31 - 1)
+ * wihout overflowing 31 bits:
+ * (2^31 - 1) = 127773 * (7^5) + 2836
+ * From "Random number generators: good ones are hard to find",
+ * Park and Miller, Communications of the ACM, vol. 31, no. 10,
+ * October 1988, p. 1195.
+ */
+ int32_t hi, lo;
+
+ /* Can't be initialized with 0, so use another value. */
+ if (x == 0)
+ x = 123459876;
+ hi = x / 127773;
+ lo = x % 127773;
+ x = 16807 * lo - 2836 * hi;
+ if (x < 0)
+ x += 0x7fffffff;
+ return (x);
+#endif /* !USE_WEAK_SEEDING */
+}
+
+/*
+ * srandom:
+ *
+ * Initialize the random number generator based on the given seed. If the
+ * type is the trivial no-state-information type, just remember the seed.
+ * Otherwise, initializes state[] based on the given "seed" via a linear
+ * congruential generator. Then, the pointers are set to known locations
+ * that are exactly rand_sep places apart. Lastly, it cycles the state
+ * information a given number of times to get rid of any initial dependencies
+ * introduced by the L.C.R.N.G. Note that the initialization of randtbl[]
+ * for default usage relies on values produced by this routine.
+ */
+void
+srandom(x)
+ unsigned long x;
+{
+ int i, lim;
+
+ state[0] = (uint32_t)x;
+ if (rand_type == TYPE_0)
+ lim = NSHUFF;
+ else {
+ for (i = 1; i < rand_deg; i++)
+ state[i] = good_rand(state[i - 1]);
+ fptr = &state[rand_sep];
+ rptr = &state[0];
+ lim = 10 * rand_deg;
+ }
+ for (i = 0; i < lim; i++)
+ (void)random();
+}
+
+/*
+ * srandomdev:
+ *
+ * Many programs choose the seed value in a totally predictable manner.
+ * This often causes problems. We seed the generator using the much more
+ * secure random(4) interface. Note that this particular seeding
+ * procedure can generate states which are impossible to reproduce by
+ * calling srandom() with any value, since the succeeding terms in the
+ * state buffer are no longer derived from the LC algorithm applied to
+ * a fixed seed.
+ */
+void
+srandomdev()
+{
+ int fd, done;
+ size_t len;
+
+ if (rand_type == TYPE_0)
+ len = sizeof state[0];
+ else
+ len = rand_deg * sizeof state[0];
+
+ done = 0;
+ fd = _open("/dev/random", O_RDONLY, 0);
+ if (fd >= 0) {
+ if (_read(fd, (void *) state, len) == (ssize_t) len)
+ done = 1;
+ _close(fd);
+ }
+
+ if (!done) {
+ struct timeval tv;
+ unsigned long junk;
+
+ gettimeofday(&tv, NULL);
+ srandom((getpid() << 16) ^ tv.tv_sec ^ tv.tv_usec ^ junk);
+ return;
+ }
+
+ if (rand_type != TYPE_0) {
+ fptr = &state[rand_sep];
+ rptr = &state[0];
+ }
+}
+
+/*
+ * initstate:
+ *
+ * Initialize the state information in the given array of n bytes for future
+ * random number generation. Based on the number of bytes we are given, and
+ * the break values for the different R.N.G.'s, we choose the best (largest)
+ * one we can and set things up for it. srandom() is then called to
+ * initialize the state information.
+ *
+ * Note that on return from srandom(), we set state[-1] to be the type
+ * multiplexed with the current value of the rear pointer; this is so
+ * successive calls to initstate() won't lose this information and will be
+ * able to restart with setstate().
+ *
+ * Note: the first thing we do is save the current state, if any, just like
+ * setstate() so that it doesn't matter when initstate is called.
+ *
+ * Returns a pointer to the old state.
+ *
+ * Note: The Sparc platform requires that arg_state begin on an int
+ * word boundary; otherwise a bus error will occur. Even so, lint will
+ * complain about mis-alignment, but you should disregard these messages.
+ */
+char *
+initstate(seed, arg_state, n)
+ unsigned long seed; /* seed for R.N.G. */
+ char *arg_state; /* pointer to state array */
+ long n; /* # bytes of state info */
+{
+ char *ostate = (char *)(&state[-1]);
+ uint32_t *int_arg_state = (uint32_t *)arg_state;
+
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+ if (n < BREAK_0) {
+ (void)fprintf(stderr,
+ "random: not enough state (%ld bytes); ignored.\n", n);
+ return(0);
+ }
+ if (n < BREAK_1) {
+ rand_type = TYPE_0;
+ rand_deg = DEG_0;
+ rand_sep = SEP_0;
+ } else if (n < BREAK_2) {
+ rand_type = TYPE_1;
+ rand_deg = DEG_1;
+ rand_sep = SEP_1;
+ } else if (n < BREAK_3) {
+ rand_type = TYPE_2;
+ rand_deg = DEG_2;
+ rand_sep = SEP_2;
+ } else if (n < BREAK_4) {
+ rand_type = TYPE_3;
+ rand_deg = DEG_3;
+ rand_sep = SEP_3;
+ } else {
+ rand_type = TYPE_4;
+ rand_deg = DEG_4;
+ rand_sep = SEP_4;
+ }
+ state = int_arg_state + 1; /* first location */
+ end_ptr = &state[rand_deg]; /* must set end_ptr before srandom */
+ srandom(seed);
+ if (rand_type == TYPE_0)
+ int_arg_state[0] = rand_type;
+ else
+ int_arg_state[0] = MAX_TYPES * (rptr - state) + rand_type;
+ return(ostate);
+}
+
+/*
+ * setstate:
+ *
+ * Restore the state from the given state array.
+ *
+ * Note: it is important that we also remember the locations of the pointers
+ * in the current state information, and restore the locations of the pointers
+ * from the old state information. This is done by multiplexing the pointer
+ * location into the zeroeth word of the state information.
+ *
+ * Note that due to the order in which things are done, it is OK to call
+ * setstate() with the same state as the current state.
+ *
+ * Returns a pointer to the old state information.
+ *
+ * Note: The Sparc platform requires that arg_state begin on an int
+ * word boundary; otherwise a bus error will occur. Even so, lint will
+ * complain about mis-alignment, but you should disregard these messages.
+ */
+char *
+setstate(arg_state)
+ char *arg_state; /* pointer to state array */
+{
+ uint32_t *new_state = (uint32_t *)arg_state;
+ uint32_t type = new_state[0] % MAX_TYPES;
+ uint32_t rear = new_state[0] / MAX_TYPES;
+ char *ostate = (char *)(&state[-1]);
+
+ if (rand_type == TYPE_0)
+ state[-1] = rand_type;
+ else
+ state[-1] = MAX_TYPES * (rptr - state) + rand_type;
+ switch(type) {
+ case TYPE_0:
+ case TYPE_1:
+ case TYPE_2:
+ case TYPE_3:
+ case TYPE_4:
+ rand_type = type;
+ rand_deg = degrees[type];
+ rand_sep = seps[type];
+ break;
+ default:
+ (void)fprintf(stderr,
+ "random: state info corrupted; not changed.\n");
+ }
+ state = new_state + 1;
+ if (rand_type != TYPE_0) {
+ rptr = &state[rear];
+ fptr = &state[(rear + rand_sep) % rand_deg];
+ }
+ end_ptr = &state[rand_deg]; /* set end_ptr too */
+ return(ostate);
+}
+
+/*
+ * random:
+ *
+ * If we are using the trivial TYPE_0 R.N.G., just do the old linear
+ * congruential bit. Otherwise, we do our fancy trinomial stuff, which is
+ * the same in all the other cases due to all the global variables that have
+ * been set up. The basic operation is to add the number at the rear pointer
+ * into the one at the front pointer. Then both pointers are advanced to
+ * the next location cyclically in the table. The value returned is the sum
+ * generated, reduced to 31 bits by throwing away the "least random" low bit.
+ *
+ * Note: the code takes advantage of the fact that both the front and
+ * rear pointers can't wrap on the same call by not testing the rear
+ * pointer if the front one has wrapped.
+ *
+ * Returns a 31-bit random number.
+ */
+long
+random()
+{
+ uint32_t i;
+ uint32_t *f, *r;
+
+ if (rand_type == TYPE_0) {
+ i = state[0];
+ state[0] = i = (good_rand(i)) & 0x7fffffff;
+ } else {
+ /*
+ * Use local variables rather than static variables for speed.
+ */
+ f = fptr; r = rptr;
+ *f += *r;
+ i = (*f >> 1) & 0x7fffffff; /* chucking least random bit */
+ if (++f >= end_ptr) {
+ f = state;
+ ++r;
+ }
+ else if (++r >= end_ptr) {
+ r = state;
+ }
+
+ fptr = f; rptr = r;
+ }
+ return((long)i);
+}
diff --git a/lib/libc/stdlib/reallocf.3 b/lib/libc/stdlib/reallocf.3
new file mode 100644
index 0000000..cc9ef3d
--- /dev/null
+++ b/lib/libc/stdlib/reallocf.3
@@ -0,0 +1,82 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)malloc.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd January 31, 2010
+.Dt MALLOC 3
+.Os
+.Sh NAME
+.Nm reallocf
+.Nd memory reallocation function
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft void *
+.Fn reallocf "void *ptr" "size_t size"
+.Sh DESCRIPTION
+The
+.Fn reallocf
+function is identical to the
+.Fn realloc
+function, except that it
+will free the passed pointer when the requested memory cannot be allocated.
+This is a
+.Fx
+specific API designed to ease the problems with traditional coding styles
+for
+.Fn realloc
+causing memory leaks in libraries.
+.Sh RETURN VALUES
+The
+.Fn reallocf
+function returns a pointer, possibly identical to
+.Fa ptr ,
+to the allocated memory
+if successful; otherwise a
+.Dv NULL
+pointer is returned, and
+.Va errno
+is set to
+.Er ENOMEM
+if the error was the result of an allocation failure.
+The
+.Fn reallocf
+function deletes the original buffer when an error occurs.
+.Sh SEE ALSO
+.Xr realloc 3
+.Sh HISTORY
+The
+.Fn reallocf
+function first appeared in
+.Fx 3.0 .
diff --git a/lib/libc/stdlib/reallocf.c b/lib/libc/stdlib/reallocf.c
new file mode 100644
index 0000000..a85b5a3
--- /dev/null
+++ b/lib/libc/stdlib/reallocf.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1998, M. Warner Losh <imp@freebsd.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+
+void *
+reallocf(void *ptr, size_t size)
+{
+ void *nptr;
+
+ nptr = realloc(ptr, size);
+
+ /*
+ * When the System V compatibility option (malloc "V" flag) is
+ * in effect, realloc(ptr, 0) frees the memory and returns NULL.
+ * So, to avoid double free, call free() only when size != 0.
+ * realloc(ptr, 0) can't fail when ptr != NULL.
+ */
+ if (!nptr && ptr && size != 0)
+ free(ptr);
+ return (nptr);
+}
diff --git a/lib/libc/stdlib/realpath.3 b/lib/libc/stdlib/realpath.3
new file mode 100644
index 0000000..fec5258
--- /dev/null
+++ b/lib/libc/stdlib/realpath.3
@@ -0,0 +1,135 @@
+.\" Copyright (c) 1994
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Jan-Simon Pendry.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)realpath.3 8.2 (Berkeley) 2/16/94
+.\" $FreeBSD$
+.\"
+.Dd April 19, 2010
+.Dt REALPATH 3
+.Os
+.Sh NAME
+.Nm realpath
+.Nd returns the canonicalized absolute pathname
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/param.h
+.In stdlib.h
+.Ft "char *"
+.Fn realpath "const char *pathname" "char *resolved_path"
+.Sh DESCRIPTION
+The
+.Fn realpath
+function resolves all symbolic links, extra
+.Dq /
+characters and references to
+.Pa /./
+and
+.Pa /../
+in
+.Fa pathname ,
+and copies the resulting absolute pathname into
+the memory pointed to by
+.Fa resolved_path .
+The
+.Fa resolved_path
+argument
+.Em must
+point to a buffer capable of storing at least
+.Dv PATH_MAX
+characters, or be
+.Dv NULL .
+.Pp
+The
+.Fn realpath
+function will resolve both absolute and relative paths
+and return the absolute pathname corresponding to
+.Fa pathname .
+All but the last component of
+.Fa pathname
+must exist when
+.Fn realpath
+is called.
+.Sh "RETURN VALUES"
+The
+.Fn realpath
+function returns
+.Fa resolved_path
+on success.
+If the function was supplied
+.Dv NULL
+as
+.Fa resolved_path ,
+and operation did not cause errors, the returned value is
+a null-terminated string in a buffer allocated by a call to
+.Fn malloc 3 .
+If an error occurs,
+.Fn realpath
+returns
+.Dv NULL ,
+and if
+.Fa resolved_path
+is not
+.Dv NULL ,
+the array that it points to contains the pathname which caused the problem.
+.Sh ERRORS
+The function
+.Fn realpath
+may fail and set the external variable
+.Va errno
+for any of the errors specified for the library functions
+.Xr lstat 2 ,
+.Xr readlink 2
+and
+.Xr getcwd 3 .
+.Sh SEE ALSO
+.Xr getcwd 3
+.\" .Sh STANDARDS
+.\" The
+.\" .Fn realpath
+.\" function conforms to
+.\" .St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn realpath
+function first appeared in
+.Bx 4.4 .
+.Sh CAVEATS
+This implementation of
+.Fn realpath
+differs slightly from the Solaris implementation.
+The
+.Bx 4.4
+version always returns absolute pathnames,
+whereas the Solaris implementation will,
+under certain circumstances, return a relative
+.Fa resolved_path
+when given a relative
+.Fa pathname .
diff --git a/lib/libc/stdlib/realpath.c b/lib/libc/stdlib/realpath.c
new file mode 100644
index 0000000..2c9562e
--- /dev/null
+++ b/lib/libc/stdlib/realpath.c
@@ -0,0 +1,235 @@
+/*
+ * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The names of the authors may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)realpath.c 8.1 (Berkeley) 2/16/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include "un-namespace.h"
+
+/*
+ * Find the real name of path, by removing all ".", ".." and symlink
+ * components. Returns (resolved) on success, or (NULL) on failure,
+ * in which case the path which caused trouble is left in (resolved).
+ */
+char *
+realpath(const char * __restrict path, char * __restrict resolved)
+{
+ struct stat sb;
+ char *p, *q, *s;
+ size_t left_len, resolved_len;
+ unsigned symlinks;
+ int m, serrno, slen;
+ char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
+
+ if (path == NULL) {
+ errno = EINVAL;
+ return (NULL);
+ }
+ if (path[0] == '\0') {
+ errno = ENOENT;
+ return (NULL);
+ }
+ serrno = errno;
+ if (resolved == NULL) {
+ resolved = malloc(PATH_MAX);
+ if (resolved == NULL)
+ return (NULL);
+ m = 1;
+ } else
+ m = 0;
+ symlinks = 0;
+ if (path[0] == '/') {
+ resolved[0] = '/';
+ resolved[1] = '\0';
+ if (path[1] == '\0')
+ return (resolved);
+ resolved_len = 1;
+ left_len = strlcpy(left, path + 1, sizeof(left));
+ } else {
+ if (getcwd(resolved, PATH_MAX) == NULL) {
+ if (m)
+ free(resolved);
+ else {
+ resolved[0] = '.';
+ resolved[1] = '\0';
+ }
+ return (NULL);
+ }
+ resolved_len = strlen(resolved);
+ left_len = strlcpy(left, path, sizeof(left));
+ }
+ if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
+ if (m)
+ free(resolved);
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+
+ /*
+ * Iterate over path components in `left'.
+ */
+ while (left_len != 0) {
+ /*
+ * Extract the next path component and adjust `left'
+ * and its length.
+ */
+ p = strchr(left, '/');
+ s = p ? p : left + left_len;
+ if (s - left >= sizeof(next_token)) {
+ if (m)
+ free(resolved);
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ memcpy(next_token, left, s - left);
+ next_token[s - left] = '\0';
+ left_len -= s - left;
+ if (p != NULL)
+ memmove(left, s + 1, left_len + 1);
+ if (resolved[resolved_len - 1] != '/') {
+ if (resolved_len + 1 >= PATH_MAX) {
+ if (m)
+ free(resolved);
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ resolved[resolved_len++] = '/';
+ resolved[resolved_len] = '\0';
+ }
+ if (next_token[0] == '\0')
+ continue;
+ else if (strcmp(next_token, ".") == 0)
+ continue;
+ else if (strcmp(next_token, "..") == 0) {
+ /*
+ * Strip the last path component except when we have
+ * single "/"
+ */
+ if (resolved_len > 1) {
+ resolved[resolved_len - 1] = '\0';
+ q = strrchr(resolved, '/') + 1;
+ *q = '\0';
+ resolved_len = q - resolved;
+ }
+ continue;
+ }
+
+ /*
+ * Append the next path component and lstat() it. If
+ * lstat() fails we still can return successfully if
+ * there are no more path components left.
+ */
+ resolved_len = strlcat(resolved, next_token, PATH_MAX);
+ if (resolved_len >= PATH_MAX) {
+ if (m)
+ free(resolved);
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ if (lstat(resolved, &sb) != 0) {
+ if (errno == ENOENT && p == NULL) {
+ errno = serrno;
+ return (resolved);
+ }
+ if (m)
+ free(resolved);
+ return (NULL);
+ }
+ if (S_ISLNK(sb.st_mode)) {
+ if (symlinks++ > MAXSYMLINKS) {
+ if (m)
+ free(resolved);
+ errno = ELOOP;
+ return (NULL);
+ }
+ slen = readlink(resolved, symlink, sizeof(symlink) - 1);
+ if (slen < 0) {
+ if (m)
+ free(resolved);
+ return (NULL);
+ }
+ symlink[slen] = '\0';
+ if (symlink[0] == '/') {
+ resolved[1] = 0;
+ resolved_len = 1;
+ } else if (resolved_len > 1) {
+ /* Strip the last path component. */
+ resolved[resolved_len - 1] = '\0';
+ q = strrchr(resolved, '/') + 1;
+ *q = '\0';
+ resolved_len = q - resolved;
+ }
+
+ /*
+ * If there are any path components left, then
+ * append them to symlink. The result is placed
+ * in `left'.
+ */
+ if (p != NULL) {
+ if (symlink[slen - 1] != '/') {
+ if (slen + 1 >= sizeof(symlink)) {
+ if (m)
+ free(resolved);
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ symlink[slen] = '/';
+ symlink[slen + 1] = 0;
+ }
+ left_len = strlcat(symlink, left,
+ sizeof(symlink));
+ if (left_len >= sizeof(left)) {
+ if (m)
+ free(resolved);
+ errno = ENAMETOOLONG;
+ return (NULL);
+ }
+ }
+ left_len = strlcpy(left, symlink, sizeof(left));
+ }
+ }
+
+ /*
+ * Remove trailing slash except when the resolved pathname
+ * is a single "/".
+ */
+ if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
+ resolved[resolved_len - 1] = '\0';
+ return (resolved);
+}
diff --git a/lib/libc/stdlib/remque.c b/lib/libc/stdlib/remque.c
new file mode 100644
index 0000000..0a2f28f
--- /dev/null
+++ b/lib/libc/stdlib/remque.c
@@ -0,0 +1,30 @@
+/*
+ * Initial implementation:
+ * Copyright (c) 2002 Robert Drehmel
+ * All rights reserved.
+ *
+ * As long as the above copyright statement and this notice remain
+ * unchanged, you can do what ever you want with this file.
+ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define _SEARCH_PRIVATE
+#include <search.h>
+#include <stdlib.h> /* for NULL */
+
+void
+remque(void *element)
+{
+ struct que_elem *prev, *next, *elem;
+
+ elem = (struct que_elem *)element;
+
+ prev = elem->prev;
+ next = elem->next;
+
+ if (prev != NULL)
+ prev->next = next;
+ if (next != NULL)
+ next->prev = prev;
+}
diff --git a/lib/libc/stdlib/strfmon.3 b/lib/libc/stdlib/strfmon.3
new file mode 100644
index 0000000..11b8e21
--- /dev/null
+++ b/lib/libc/stdlib/strfmon.3
@@ -0,0 +1,167 @@
+.\" Copyright (c) 2001 Jeroen Ruigrok van der Werven <asmodai@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 12, 2002
+.Dt STRFMON 3
+.Os
+.Sh NAME
+.Nm strfmon
+.Nd convert monetary value to string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In monetary.h
+.Ft ssize_t
+.Fn strfmon "char * restrict s" "size_t maxsize" "const char * restrict format" "..."
+.Sh DESCRIPTION
+The
+.Fn strfmon
+function places characters into the array pointed to by
+.Fa s
+as controlled by the string pointed to by
+.Fa format .
+No more than
+.Fa maxsize
+bytes are placed into the array.
+.Pp
+The format string is composed of zero or more directives:
+ordinary characters (not
+.Cm % ) ,
+which are copied unchanged to the output stream; and conversion
+specifications, each of which results in fetching zero or more subsequent
+arguments.
+Each conversion specification is introduced by the
+.Cm %
+character.
+After the
+.Cm % ,
+the following appear in sequence:
+.Bl -bullet
+.It
+Zero or more of the following flags:
+.Bl -tag -width "XXX"
+.It Cm = Ns Ar f
+A
+.Sq Cm =
+character followed by another character
+.Ar f
+which is used as the numeric fill character.
+.It Cm ^
+Do not use grouping characters, regardless of the current locale default.
+.It Cm +
+Represent positive values by prefixing them with a positive sign,
+and negative values by prefixing them with a negative sign.
+This is the default.
+.It Cm \&(
+Enclose negative values in parentheses.
+.It Cm \&!
+Do not include a currency symbol in the output.
+.It Cm \-
+Left justify the result.
+Only valid when a field width is specified.
+.El
+.It
+An optional minimum field width as a decimal number.
+By default, there is no minimum width.
+.It
+A
+.Sq Cm #
+sign followed by a decimal number specifying the maximum
+expected number of digits after the radix character.
+.It
+A
+.Sq Cm \&.
+character followed by a decimal number specifying the number
+the number of digits after the radix character.
+.It
+One of the following conversion specifiers:
+.Bl -tag -width "XXX"
+.It Cm i
+The
+.Vt double
+argument is formatted as an international monetary amount.
+.It Cm n
+The
+.Vt double
+argument is formatted as a national monetary amount.
+.It Cm %
+A
+.Sq Li %
+character is written.
+.El
+.El
+.Sh RETURN VALUES
+If the total number of resulting bytes including the terminating
+.Dv NULL
+byte is not more than
+.Fa maxsize ,
+.Fn strfmon
+returns the number of bytes placed into the array pointed to by
+.Fa s ,
+not including the terminating
+.Dv NULL
+byte.
+Otherwise, \-1 is returned,
+the contents of the array are indeterminate,
+and
+.Va errno
+is set to indicate the error.
+.Sh ERRORS
+The
+.Fn strfmon
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er E2BIG
+Conversion stopped due to lack of space in the buffer.
+.It Bq Er EINVAL
+The format string is invalid.
+.It Bq Er ENOMEM
+Not enough memory for temporary buffers.
+.El
+.Sh SEE ALSO
+.Xr localeconv 3
+.Sh STANDARDS
+The
+.Fn strfmon
+function
+conforms to
+.St -p1003.1-2001 .
+.Sh AUTHORS
+.An -nosplit
+The
+.Fn strfmon
+function was implemented by
+.An Alexey Zelkin Aq phantom@FreeBSD.org .
+.Pp
+This manual page was written by
+.An Jeroen Ruigrok van der Werven Aq asmodai@FreeBSD.org
+based on the standards' text.
+.Sh BUGS
+The
+.Fn strfmon
+function does not correctly handle multibyte characters in the
+.Fa format
+argument.
diff --git a/lib/libc/stdlib/strfmon.c b/lib/libc/stdlib/strfmon.c
new file mode 100644
index 0000000..b82797d
--- /dev/null
+++ b/lib/libc/stdlib/strfmon.c
@@ -0,0 +1,643 @@
+/*-
+ * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <ctype.h>
+#include <errno.h>
+#include <limits.h>
+#include <locale.h>
+#include <monetary.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "xlocale_private.h"
+
+/* internal flags */
+#define NEED_GROUPING 0x01 /* print digits grouped (default) */
+#define SIGN_POSN_USED 0x02 /* '+' or '(' usage flag */
+#define LOCALE_POSN 0x04 /* use locale defined +/- (default) */
+#define PARENTH_POSN 0x08 /* enclose negative amount in () */
+#define SUPRESS_CURR_SYMBOL 0x10 /* supress the currency from output */
+#define LEFT_JUSTIFY 0x20 /* left justify */
+#define USE_INTL_CURRENCY 0x40 /* use international currency symbol */
+#define IS_NEGATIVE 0x80 /* is argument value negative ? */
+
+/* internal macros */
+#define PRINT(CH) do { \
+ if (dst >= s + maxsize) \
+ goto e2big_error; \
+ *dst++ = CH; \
+} while (0)
+
+#define PRINTS(STR) do { \
+ char *tmps = STR; \
+ while (*tmps != '\0') \
+ PRINT(*tmps++); \
+} while (0)
+
+#define GET_NUMBER(VAR) do { \
+ VAR = 0; \
+ while (isdigit((unsigned char)*fmt)) { \
+ if (VAR > INT_MAX / 10) \
+ goto e2big_error; \
+ VAR *= 10; \
+ VAR += *fmt - '0'; \
+ if (VAR < 0) \
+ goto e2big_error; \
+ fmt++; \
+ } \
+} while (0)
+
+#define GRPCPY(howmany) do { \
+ int i = howmany; \
+ while (i-- > 0) { \
+ avalue_size--; \
+ *--bufend = *(avalue+avalue_size+padded); \
+ } \
+} while (0)
+
+#define GRPSEP do { \
+ *--bufend = thousands_sep; \
+ groups++; \
+} while (0)
+
+static void __setup_vars(int, char *, char *, char *, char **);
+static int __calc_left_pad(int, char *);
+static char *__format_grouped_double(double, int *, int, int, int);
+
+static ssize_t
+vstrfmon_l(char * __restrict s, size_t maxsize, locale_t loc,
+ const char * __restrict format, va_list ap)
+{
+ char *dst; /* output destination pointer */
+ const char *fmt; /* current format poistion pointer */
+ struct lconv *lc; /* pointer to lconv structure */
+ char *asciivalue; /* formatted double pointer */
+
+ int flags; /* formatting options */
+ int pad_char; /* padding character */
+ int pad_size; /* pad size */
+ int width; /* field width */
+ int left_prec; /* left precision */
+ int right_prec; /* right precision */
+ double value; /* just value */
+ char space_char = ' '; /* space after currency */
+
+ char cs_precedes, /* values gathered from struct lconv */
+ sep_by_space,
+ sign_posn,
+ *signstr,
+ *currency_symbol;
+
+ char *tmpptr; /* temporary vars */
+ int sverrno;
+ FIX_LOCALE(loc);
+
+
+ lc = localeconv_l(loc);
+ dst = s;
+ fmt = format;
+ asciivalue = NULL;
+ currency_symbol = NULL;
+ pad_size = 0;
+
+ while (*fmt) {
+ /* pass nonformating characters AS IS */
+ if (*fmt != '%')
+ goto literal;
+
+ /* '%' found ! */
+
+ /* "%%" mean just '%' */
+ if (*(fmt+1) == '%') {
+ fmt++;
+ literal:
+ PRINT(*fmt++);
+ continue;
+ }
+
+ /* set up initial values */
+ flags = (NEED_GROUPING|LOCALE_POSN);
+ pad_char = ' '; /* padding character is "space" */
+ left_prec = -1; /* no left precision specified */
+ right_prec = -1; /* no right precision specified */
+ width = -1; /* no width specified */
+ value = 0; /* we have no value to print now */
+
+ /* Flags */
+ while (1) {
+ switch (*++fmt) {
+ case '=': /* fill character */
+ pad_char = *++fmt;
+ if (pad_char == '\0')
+ goto format_error;
+ continue;
+ case '^': /* not group currency */
+ flags &= ~(NEED_GROUPING);
+ continue;
+ case '+': /* use locale defined signs */
+ if (flags & SIGN_POSN_USED)
+ goto format_error;
+ flags |= (SIGN_POSN_USED|LOCALE_POSN);
+ continue;
+ case '(': /* enclose negatives with () */
+ if (flags & SIGN_POSN_USED)
+ goto format_error;
+ flags |= (SIGN_POSN_USED|PARENTH_POSN);
+ continue;
+ case '!': /* suppress currency symbol */
+ flags |= SUPRESS_CURR_SYMBOL;
+ continue;
+ case '-': /* alignment (left) */
+ flags |= LEFT_JUSTIFY;
+ continue;
+ default:
+ break;
+ }
+ break;
+ }
+
+ /* field Width */
+ if (isdigit((unsigned char)*fmt)) {
+ GET_NUMBER(width);
+ /* Do we have enough space to put number with
+ * required width ?
+ */
+ if ((unsigned int)width >= maxsize - (dst - s))
+ goto e2big_error;
+ }
+
+ /* Left precision */
+ if (*fmt == '#') {
+ if (!isdigit((unsigned char)*++fmt))
+ goto format_error;
+ GET_NUMBER(left_prec);
+ if ((unsigned int)left_prec >= maxsize - (dst - s))
+ goto e2big_error;
+ }
+
+ /* Right precision */
+ if (*fmt == '.') {
+ if (!isdigit((unsigned char)*++fmt))
+ goto format_error;
+ GET_NUMBER(right_prec);
+ if ((unsigned int)right_prec >= maxsize - (dst - s) -
+ left_prec)
+ goto e2big_error;
+ }
+
+ /* Conversion Characters */
+ switch (*fmt++) {
+ case 'i': /* use internaltion currency format */
+ flags |= USE_INTL_CURRENCY;
+ break;
+ case 'n': /* use national currency format */
+ flags &= ~(USE_INTL_CURRENCY);
+ break;
+ default: /* required character is missing or
+ premature EOS */
+ goto format_error;
+ }
+
+ if (currency_symbol != NULL)
+ free(currency_symbol);
+ if (flags & USE_INTL_CURRENCY) {
+ currency_symbol = strdup(lc->int_curr_symbol);
+ if (currency_symbol != NULL)
+ space_char = *(currency_symbol+3);
+ } else
+ currency_symbol = strdup(lc->currency_symbol);
+
+ if (currency_symbol == NULL)
+ goto end_error; /* ENOMEM. */
+
+ /* value itself */
+ value = va_arg(ap, double);
+
+ /* detect sign */
+ if (value < 0) {
+ flags |= IS_NEGATIVE;
+ value = -value;
+ }
+
+ /* fill left_prec with amount of padding chars */
+ if (left_prec >= 0) {
+ pad_size = __calc_left_pad((flags ^ IS_NEGATIVE),
+ currency_symbol) -
+ __calc_left_pad(flags, currency_symbol);
+ if (pad_size < 0)
+ pad_size = 0;
+ }
+
+ if (asciivalue != NULL)
+ free(asciivalue);
+ asciivalue = __format_grouped_double(value, &flags,
+ left_prec, right_prec, pad_char);
+ if (asciivalue == NULL)
+ goto end_error; /* errno already set */
+ /* to ENOMEM by malloc() */
+
+ /* set some variables for later use */
+ __setup_vars(flags, &cs_precedes, &sep_by_space,
+ &sign_posn, &signstr);
+
+ /*
+ * Description of some LC_MONETARY's values:
+ *
+ * p_cs_precedes & n_cs_precedes
+ *
+ * = 1 - $currency_symbol precedes the value
+ * for a monetary quantity with a non-negative value
+ * = 0 - symbol succeeds the value
+ *
+ * p_sep_by_space & n_sep_by_space
+ *
+ * = 0 - no space separates $currency_symbol
+ * from the value for a monetary quantity with a
+ * non-negative value
+ * = 1 - space separates the symbol from the value
+ * = 2 - space separates the symbol and the sign string,
+ * if adjacent.
+ *
+ * p_sign_posn & n_sign_posn
+ *
+ * = 0 - parentheses enclose the quantity and the
+ * $currency_symbol
+ * = 1 - the sign string precedes the quantity and the
+ * $currency_symbol
+ * = 2 - the sign string succeeds the quantity and the
+ * $currency_symbol
+ * = 3 - the sign string precedes the $currency_symbol
+ * = 4 - the sign string succeeds the $currency_symbol
+ *
+ */
+
+ tmpptr = dst;
+
+ while (pad_size-- > 0)
+ PRINT(' ');
+
+ if (sign_posn == 0 && (flags & IS_NEGATIVE))
+ PRINT('(');
+
+ if (cs_precedes == 1) {
+ if (sign_posn == 1 || sign_posn == 3) {
+ PRINTS(signstr);
+ if (sep_by_space == 2) /* XXX: ? */
+ PRINT(' ');
+ }
+
+ if (!(flags & SUPRESS_CURR_SYMBOL)) {
+ PRINTS(currency_symbol);
+
+ if (sign_posn == 4) {
+ if (sep_by_space == 2)
+ PRINT(space_char);
+ PRINTS(signstr);
+ if (sep_by_space == 1)
+ PRINT(' ');
+ } else if (sep_by_space == 1)
+ PRINT(space_char);
+ }
+ } else if (sign_posn == 1)
+ PRINTS(signstr);
+
+ PRINTS(asciivalue);
+
+ if (cs_precedes == 0) {
+ if (sign_posn == 3) {
+ if (sep_by_space == 1)
+ PRINT(' ');
+ PRINTS(signstr);
+ }
+
+ if (!(flags & SUPRESS_CURR_SYMBOL)) {
+ if ((sign_posn == 3 && sep_by_space == 2)
+ || (sep_by_space == 1
+ && (sign_posn == 0
+ || sign_posn == 1
+ || sign_posn == 2
+ || sign_posn == 4)))
+ PRINT(space_char);
+ PRINTS(currency_symbol); /* XXX: len */
+ if (sign_posn == 4) {
+ if (sep_by_space == 2)
+ PRINT(' ');
+ PRINTS(signstr);
+ }
+ }
+ }
+
+ if (sign_posn == 2) {
+ if (sep_by_space == 2)
+ PRINT(' ');
+ PRINTS(signstr);
+ }
+
+ if (sign_posn == 0 && (flags & IS_NEGATIVE))
+ PRINT(')');
+
+ if (dst - tmpptr < width) {
+ if (flags & LEFT_JUSTIFY) {
+ while (dst - tmpptr < width)
+ PRINT(' ');
+ } else {
+ pad_size = dst-tmpptr;
+ memmove(tmpptr + width-pad_size, tmpptr,
+ pad_size);
+ memset(tmpptr, ' ', width-pad_size);
+ dst += width-pad_size;
+ }
+ }
+ }
+
+ PRINT('\0');
+ free(asciivalue);
+ free(currency_symbol);
+ return (dst - s - 1); /* return size of put data except trailing '\0' */
+
+e2big_error:
+ errno = E2BIG;
+ goto end_error;
+
+format_error:
+ errno = EINVAL;
+
+end_error:
+ sverrno = errno;
+ if (asciivalue != NULL)
+ free(asciivalue);
+ if (currency_symbol != NULL)
+ free(currency_symbol);
+ errno = sverrno;
+ return (-1);
+}
+ssize_t
+strfmon_l(char * __restrict s, size_t maxsize, locale_t loc, const char * __restrict format,
+ ...)
+{
+ size_t ret;
+ va_list ap;
+ va_start(ap, format);
+ ret = vstrfmon_l(s, maxsize, loc, format, ap);
+ va_end(ap);
+ return ret;
+}
+
+ssize_t
+strfmon(char * __restrict s, size_t maxsize, const char * __restrict format,
+ ...)
+{
+ size_t ret;
+ va_list ap;
+ va_start(ap, format);
+ ret = vstrfmon_l(s, maxsize, __get_locale(), format, ap);
+ va_end(ap);
+ return ret;
+}
+
+
+static void
+__setup_vars(int flags, char *cs_precedes, char *sep_by_space,
+ char *sign_posn, char **signstr) {
+
+ struct lconv *lc = localeconv();
+
+ if ((flags & IS_NEGATIVE) && (flags & USE_INTL_CURRENCY)) {
+ *cs_precedes = lc->int_n_cs_precedes;
+ *sep_by_space = lc->int_n_sep_by_space;
+ *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->int_n_sign_posn;
+ *signstr = (lc->negative_sign[0] == '\0') ? "-"
+ : lc->negative_sign;
+ } else if (flags & USE_INTL_CURRENCY) {
+ *cs_precedes = lc->int_p_cs_precedes;
+ *sep_by_space = lc->int_p_sep_by_space;
+ *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->int_p_sign_posn;
+ *signstr = lc->positive_sign;
+ } else if (flags & IS_NEGATIVE) {
+ *cs_precedes = lc->n_cs_precedes;
+ *sep_by_space = lc->n_sep_by_space;
+ *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->n_sign_posn;
+ *signstr = (lc->negative_sign[0] == '\0') ? "-"
+ : lc->negative_sign;
+ } else {
+ *cs_precedes = lc->p_cs_precedes;
+ *sep_by_space = lc->p_sep_by_space;
+ *sign_posn = (flags & PARENTH_POSN) ? 0 : lc->p_sign_posn;
+ *signstr = lc->positive_sign;
+ }
+
+ /* Set defult values for unspecified information. */
+ if (*cs_precedes != 0)
+ *cs_precedes = 1;
+ if (*sep_by_space == CHAR_MAX)
+ *sep_by_space = 0;
+ if (*sign_posn == CHAR_MAX)
+ *sign_posn = 0;
+}
+
+static int
+__calc_left_pad(int flags, char *cur_symb) {
+
+ char cs_precedes, sep_by_space, sign_posn, *signstr;
+ int left_chars = 0;
+
+ __setup_vars(flags, &cs_precedes, &sep_by_space, &sign_posn, &signstr);
+
+ if (cs_precedes != 0) {
+ left_chars += strlen(cur_symb);
+ if (sep_by_space != 0)
+ left_chars++;
+ }
+
+ switch (sign_posn) {
+ case 1:
+ left_chars += strlen(signstr);
+ break;
+ case 3:
+ case 4:
+ if (cs_precedes != 0)
+ left_chars += strlen(signstr);
+ }
+ return (left_chars);
+}
+
+static int
+get_groups(int size, char *grouping) {
+
+ int chars = 0;
+
+ if (*grouping == CHAR_MAX || *grouping <= 0) /* no grouping ? */
+ return (0);
+
+ while (size > (int)*grouping) {
+ chars++;
+ size -= (int)*grouping++;
+ /* no more grouping ? */
+ if (*grouping == CHAR_MAX)
+ break;
+ /* rest grouping with same value ? */
+ if (*grouping == 0) {
+ chars += (size - 1) / *(grouping - 1);
+ break;
+ }
+ }
+ return (chars);
+}
+
+/* convert double to ASCII */
+static char *
+__format_grouped_double(double value, int *flags,
+ int left_prec, int right_prec, int pad_char) {
+
+ char *rslt;
+ char *avalue;
+ int avalue_size;
+ char fmt[32];
+
+ size_t bufsize;
+ char *bufend;
+
+ int padded;
+
+ struct lconv *lc = localeconv();
+ char *grouping;
+ char decimal_point;
+ char thousands_sep;
+
+ int groups = 0;
+
+ grouping = lc->mon_grouping;
+ decimal_point = *lc->mon_decimal_point;
+ if (decimal_point == '\0')
+ decimal_point = *lc->decimal_point;
+ thousands_sep = *lc->mon_thousands_sep;
+ if (thousands_sep == '\0')
+ thousands_sep = *lc->thousands_sep;
+
+ /* fill left_prec with default value */
+ if (left_prec == -1)
+ left_prec = 0;
+
+ /* fill right_prec with default value */
+ if (right_prec == -1) {
+ if (*flags & USE_INTL_CURRENCY)
+ right_prec = lc->int_frac_digits;
+ else
+ right_prec = lc->frac_digits;
+
+ if (right_prec == CHAR_MAX) /* POSIX locale ? */
+ right_prec = 2;
+ }
+
+ if (*flags & NEED_GROUPING)
+ left_prec += get_groups(left_prec, grouping);
+
+ /* convert to string */
+ snprintf(fmt, sizeof(fmt), "%%%d.%df", left_prec + right_prec + 1,
+ right_prec);
+ avalue_size = asprintf(&avalue, fmt, value);
+ if (avalue_size < 0)
+ return (NULL);
+
+ /* make sure that we've enough space for result string */
+ bufsize = strlen(avalue)*2+1;
+ rslt = calloc(1, bufsize);
+ if (rslt == NULL) {
+ free(avalue);
+ return (NULL);
+ }
+ bufend = rslt + bufsize - 1; /* reserve space for trailing '\0' */
+
+ /* skip spaces at beggining */
+ padded = 0;
+ while (avalue[padded] == ' ') {
+ padded++;
+ avalue_size--;
+ }
+
+ if (right_prec > 0) {
+ bufend -= right_prec;
+ memcpy(bufend, avalue + avalue_size+padded-right_prec,
+ right_prec);
+ *--bufend = decimal_point;
+ avalue_size -= (right_prec + 1);
+ }
+
+ if ((*flags & NEED_GROUPING) &&
+ thousands_sep != '\0' && /* XXX: need investigation */
+ *grouping != CHAR_MAX &&
+ *grouping > 0) {
+ while (avalue_size > (int)*grouping) {
+ GRPCPY(*grouping);
+ GRPSEP;
+ grouping++;
+
+ /* no more grouping ? */
+ if (*grouping == CHAR_MAX)
+ break;
+
+ /* rest grouping with same value ? */
+ if (*grouping == 0) {
+ grouping--;
+ while (avalue_size > *grouping) {
+ GRPCPY(*grouping);
+ GRPSEP;
+ }
+ }
+ }
+ if (avalue_size != 0)
+ GRPCPY(avalue_size);
+ padded -= groups;
+
+ } else {
+ bufend -= avalue_size;
+ memcpy(bufend, avalue+padded, avalue_size);
+ if (right_prec == 0)
+ padded--; /* decrease assumed $decimal_point */
+ }
+
+ /* do padding with pad_char */
+ if (padded > 0) {
+ bufend -= padded;
+ memset(bufend, pad_char, padded);
+ }
+
+ bufsize = bufsize - (bufend - rslt) + 1;
+ memmove(rslt, bufend, bufsize);
+ free(avalue);
+ return (rslt);
+}
diff --git a/lib/libc/stdlib/strtod.3 b/lib/libc/stdlib/strtod.3
new file mode 100644
index 0000000..e19e5fe
--- /dev/null
+++ b/lib/libc/stdlib/strtod.3
@@ -0,0 +1,198 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strtod.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd May 11, 2010
+.Dt STRTOD 3
+.Os
+.Sh NAME
+.Nm strtod , strtof , strtold
+.Nd convert
+.Tn ASCII
+string to floating point
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft double
+.Fn strtod "const char * restrict nptr" "char ** restrict endptr"
+.Ft float
+.Fn strtof "const char * restrict nptr" "char ** restrict endptr"
+.Ft "long double"
+.Fn strtold "const char * restrict nptr" "char ** restrict endptr"
+.Sh DESCRIPTION
+These conversion
+functions convert the initial portion of the string
+pointed to by
+.Fa nptr
+to
+.Vt double ,
+.Vt float ,
+and
+.Vt "long double"
+representation, respectively.
+.Pp
+The expected form of the string is an optional plus (``+'') or minus
+sign (``\-'') followed by either:
+.Bl -bullet
+.It
+a decimal significand consisting of a sequence of decimal digits
+optionally containing a decimal-point character, or
+.It
+a hexadecimal significand consisting of a ``0X'' or ``0x'' followed
+by a sequence of hexadecimal digits optionally containing a
+decimal-point character.
+.El
+.Pp
+In both cases, the significand may be optionally followed by an
+exponent.
+An exponent consists of an ``E'' or ``e'' (for decimal
+constants) or a ``P'' or ``p'' (for hexadecimal constants),
+followed by an optional plus or minus sign, followed by a
+sequence of decimal digits.
+For decimal constants, the exponent indicates the power of 10 by
+which the significand should be scaled.
+For hexadecimal constants, the scaling is instead done by powers
+of 2.
+.Pp
+Alternatively, if the portion of the string following the optional
+plus or minus sign begins with
+.Dq INFINITY
+or
+.Dq NAN ,
+ignoring case, it is interpreted as an infinity or a quiet \*(Na,
+respectively.
+The syntax
+.Dq Xo Pf NAN( Ar "s" ) Xc ,
+where
+.Ar s
+is an alphanumeric string, produces the same value as the call
+.Fo nan
+.Qq Ar s Ns
+.Fc
+(respectively,
+.Fo nanf
+.Qq Ar s Ns
+.Fc
+and
+.Fo nanl
+.Qq Ar s Ns
+.Fc . )
+.Pp
+In any of the above cases, leading white-space characters in the
+string (as defined by the
+.Xr isspace 3
+function) are skipped.
+The decimal point
+character is defined in the program's locale (category
+.Dv LC_NUMERIC ) .
+.Sh RETURN VALUES
+The
+.Fn strtod ,
+.Fn strtof ,
+and
+.Fn strtold
+functions return the converted value, if any.
+.Pp
+If
+.Fa endptr
+is not
+.Dv NULL ,
+a pointer to the character after the last character used
+in the conversion is stored in the location referenced by
+.Fa endptr .
+.Pp
+If no conversion is performed, zero is returned and the value of
+.Fa nptr
+is stored in the location referenced by
+.Fa endptr .
+.Pp
+If the correct value would cause overflow, plus or minus
+.Dv HUGE_VAL ,
+.Dv HUGE_VALF ,
+or
+.Dv HUGE_VALL
+is returned (according to the sign and type of the return value), and
+.Er ERANGE
+is stored in
+.Va errno .
+If the correct value would cause underflow, zero is
+returned and
+.Er ERANGE
+is stored in
+.Va errno .
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er ERANGE
+Overflow or underflow occurred.
+.El
+.Sh SEE ALSO
+.Xr atof 3 ,
+.Xr atoi 3 ,
+.Xr atol 3 ,
+.Xr nan 3 ,
+.Xr strtol 3 ,
+.Xr strtoul 3 ,
+.Xr wcstod 3
+.Sh STANDARDS
+The
+.Fn strtod
+function
+conforms to
+.St -isoC-99 .
+.Sh AUTHORS
+The author of this software is
+.An David M. Gay .
+.Bd -literal
+Copyright (c) 1998 by Lucent Technologies
+All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and
+its documentation for any purpose and without fee is hereby
+granted, provided that the above copyright notice appear in all
+copies and that both that the copyright notice and this
+permission notice and warranty disclaimer appear in supporting
+documentation, and that the name of Lucent or any of its entities
+not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+LUCENT DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.
+IN NO EVENT SHALL LUCENT OR ANY OF ITS ENTITIES BE LIABLE FOR ANY
+SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
+IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF
+THIS SOFTWARE.
+.Ed
diff --git a/lib/libc/stdlib/strtoimax.c b/lib/libc/stdlib/strtoimax.c
new file mode 100644
index 0000000..9be773b
--- /dev/null
+++ b/lib/libc/stdlib/strtoimax.c
@@ -0,0 +1,153 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "from @(#)strtol.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include "xlocale_private.h"
+
+/*
+ * Convert a string to an intmax_t integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+intmax_t
+strtoimax_l(const char * __restrict nptr, char ** __restrict endptr, int base,
+ locale_t locale)
+{
+ const char *s;
+ uintmax_t acc;
+ char c;
+ uintmax_t cutoff;
+ int neg, any, cutlim;
+ FIX_LOCALE(locale);
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace_l((unsigned char)c, locale));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ acc = any = 0;
+ if (base < 2 || base > 36)
+ goto noconv;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for intmax_t is
+ * [-9223372036854775808..9223372036854775807] and the input base
+ * is 10, cutoff will be set to 922337203685477580 and cutlim to
+ * either 7 (neg==0) or 8 (neg==1), meaning that if we have
+ * accumulated a value > 922337203685477580, or equal but the
+ * next digit is > 7 (or 8), the number is too big, and we will
+ * return a range error.
+ *
+ * Set 'any' if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? (uintmax_t)-(INTMAX_MIN + INTMAX_MAX) + INTMAX_MAX
+ : INTMAX_MAX;
+ cutlim = cutoff % base;
+ cutoff /= base;
+ for ( ; ; c = *s++) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? INTMAX_MIN : INTMAX_MAX;
+ errno = ERANGE;
+ } else if (!any) {
+noconv:
+ errno = EINVAL;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != NULL)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (acc);
+}
+intmax_t
+strtoimax(const char * __restrict nptr, char ** __restrict endptr, int base)
+{
+ return strtoimax_l(nptr, endptr, base, __get_locale());
+}
diff --git a/lib/libc/stdlib/strtol.3 b/lib/libc/stdlib/strtol.3
new file mode 100644
index 0000000..02316f5
--- /dev/null
+++ b/lib/libc/stdlib/strtol.3
@@ -0,0 +1,222 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strtol.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd November 28, 2001
+.Dt STRTOL 3
+.Os
+.Sh NAME
+.Nm strtol , strtoll , strtoimax , strtoq
+.Nd "convert a string value to a"
+.Vt long , "long long" , intmax_t
+or
+.Vt quad_t
+integer
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.In limits.h
+.Ft long
+.Fn strtol "const char * restrict nptr" "char ** restrict endptr" "int base"
+.Ft long long
+.Fn strtoll "const char * restrict nptr" "char ** restrict endptr" "int base"
+.In inttypes.h
+.Ft intmax_t
+.Fn strtoimax "const char * restrict nptr" "char ** restrict endptr" "int base"
+.In sys/types.h
+.In stdlib.h
+.In limits.h
+.Ft quad_t
+.Fn strtoq "const char *nptr" "char **endptr" "int base"
+.Sh DESCRIPTION
+The
+.Fn strtol
+function
+converts the string in
+.Fa nptr
+to a
+.Vt long
+value.
+The
+.Fn strtoll
+function
+converts the string in
+.Fa nptr
+to a
+.Vt "long long"
+value.
+The
+.Fn strtoimax
+function
+converts the string in
+.Fa nptr
+to an
+.Vt intmax_t
+value.
+The
+.Fn strtoq
+function
+converts the string in
+.Fa nptr
+to a
+.Vt quad_t
+value.
+The conversion is done according to the given
+.Fa base ,
+which must be between 2 and 36 inclusive,
+or be the special value 0.
+.Pp
+The string may begin with an arbitrary amount of white space
+(as determined by
+.Xr isspace 3 )
+followed by a single optional
+.Ql +
+or
+.Ql -
+sign.
+If
+.Fa base
+is zero or 16,
+the string may then include a
+.Dq Li 0x
+prefix,
+and the number will be read in base 16; otherwise, a zero
+.Fa base
+is taken as 10 (decimal) unless the next character is
+.Ql 0 ,
+in which case it is taken as 8 (octal).
+.Pp
+The remainder of the string is converted to a
+.Vt long , "long long" , intmax_t
+or
+.Vt quad_t
+value in the obvious manner,
+stopping at the first character which is not a valid digit
+in the given base.
+(In bases above 10, the letter
+.Ql A
+in either upper or lower case
+represents 10,
+.Ql B
+represents 11, and so forth, with
+.Ql Z
+representing 35.)
+.Pp
+If
+.Fa endptr
+is not
+.Dv NULL ,
+.Fn strtol
+stores the address of the first invalid character in
+.Fa *endptr .
+If there were no digits at all, however,
+.Fn strtol
+stores the original value of
+.Fa nptr
+in
+.Fa *endptr .
+(Thus, if
+.Fa *nptr
+is not
+.Ql \e0
+but
+.Fa **endptr
+is
+.Ql \e0
+on return, the entire string was valid.)
+.Sh RETURN VALUES
+The
+.Fn strtol ,
+.Fn strtoll ,
+.Fn strtoimax
+and
+.Fn strtoq
+functions
+return the result of the conversion,
+unless the value would underflow or overflow.
+If no conversion could be performed, 0 is returned and
+the global variable
+.Va errno
+is set to
+.Er EINVAL
+(the last feature is not portable across all platforms).
+If an overflow or underflow occurs,
+.Va errno
+is set to
+.Er ERANGE
+and the function return value is clamped according
+to the following table.
+.Bl -column -offset indent ".Fn strtoimax" ".Sy underflow" ".Sy overflow"
+.It Sy Function Ta Sy underflow Ta Sy overflow
+.It Fn strtol Ta Dv LONG_MIN Ta Dv LONG_MAX
+.It Fn strtoll Ta Dv LLONG_MIN Ta Dv LLONG_MAX
+.It Fn strtoimax Ta Dv INTMAX_MIN Ta Dv INTMAX_MAX
+.It Fn strtoq Ta Dv LLONG_MIN Ta Dv LLONG_MAX
+.El
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value of
+.Fa base
+is not supported or
+no conversion could be performed
+(the last feature is not portable across all platforms).
+.It Bq Er ERANGE
+The given string was out of range; the value converted has been clamped.
+.El
+.Sh SEE ALSO
+.Xr atof 3 ,
+.Xr atoi 3 ,
+.Xr atol 3 ,
+.Xr strtod 3 ,
+.Xr strtonum 3 ,
+.Xr strtoul 3 ,
+.Xr wcstol 3
+.Sh STANDARDS
+The
+.Fn strtol
+function
+conforms to
+.St -isoC .
+The
+.Fn strtoll
+and
+.Fn strtoimax
+functions
+conform to
+.St -isoC-99 .
+The
+.Bx
+.Fn strtoq
+function is deprecated.
diff --git a/lib/libc/stdlib/strtol.c b/lib/libc/stdlib/strtol.c
new file mode 100644
index 0000000..f80ecb4
--- /dev/null
+++ b/lib/libc/stdlib/strtol.c
@@ -0,0 +1,158 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "xlocale_private.h"
+
+
+/*
+ * Convert a string to a long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+long
+strtol_l(const char * __restrict nptr, char ** __restrict endptr, int base,
+ locale_t locale)
+{
+ const char *s;
+ unsigned long acc;
+ char c;
+ unsigned long cutoff;
+ int neg, any, cutlim;
+ FIX_LOCALE(locale);
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace_l((unsigned char)c, locale));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ acc = any = 0;
+ if (base < 2 || base > 36)
+ goto noconv;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for longs is
+ * [-2147483648..2147483647] and the input base is 10,
+ * cutoff will be set to 214748364 and cutlim to either
+ * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
+ * a value > 214748364, or equal but the next digit is > 7 (or 8),
+ * the number is too big, and we will return a range error.
+ *
+ * Set 'any' if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? (unsigned long)-(LONG_MIN + LONG_MAX) + LONG_MAX
+ : LONG_MAX;
+ cutlim = cutoff % base;
+ cutoff /= base;
+ for ( ; ; c = *s++) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LONG_MIN : LONG_MAX;
+ errno = ERANGE;
+ } else if (!any) {
+noconv:
+ errno = EINVAL;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != NULL)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (acc);
+}
+long
+strtol(const char * __restrict nptr, char ** __restrict endptr, int base)
+{
+ return strtol_l(nptr, endptr, base, __get_locale());
+}
+long double
+strtold(const char * __restrict nptr, char ** __restrict endptr)
+{
+ return strtold_l(nptr, endptr, __get_locale());
+}
diff --git a/lib/libc/stdlib/strtoll.c b/lib/libc/stdlib/strtoll.c
new file mode 100644
index 0000000..6783327
--- /dev/null
+++ b/lib/libc/stdlib/strtoll.c
@@ -0,0 +1,153 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "xlocale_private.h"
+
+/*
+ * Convert a string to a long long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+long long
+strtoll_l(const char * __restrict nptr, char ** __restrict endptr, int base,
+ locale_t locale)
+{
+ const char *s;
+ unsigned long long acc;
+ char c;
+ unsigned long long cutoff;
+ int neg, any, cutlim;
+ FIX_LOCALE(locale);
+
+ /*
+ * Skip white space and pick up leading +/- sign if any.
+ * If base is 0, allow 0x for hex and 0 for octal, else
+ * assume decimal; if base is already 16, allow 0x.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace_l((unsigned char)c, locale));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ acc = any = 0;
+ if (base < 2 || base > 36)
+ goto noconv;
+
+ /*
+ * Compute the cutoff value between legal numbers and illegal
+ * numbers. That is the largest legal value, divided by the
+ * base. An input number that is greater than this value, if
+ * followed by a legal input character, is too big. One that
+ * is equal to this value may be valid or not; the limit
+ * between valid and invalid numbers is then based on the last
+ * digit. For instance, if the range for quads is
+ * [-9223372036854775808..9223372036854775807] and the input base
+ * is 10, cutoff will be set to 922337203685477580 and cutlim to
+ * either 7 (neg==0) or 8 (neg==1), meaning that if we have
+ * accumulated a value > 922337203685477580, or equal but the
+ * next digit is > 7 (or 8), the number is too big, and we will
+ * return a range error.
+ *
+ * Set 'any' if any `digits' consumed; make it negative to indicate
+ * overflow.
+ */
+ cutoff = neg ? (unsigned long long)-(LLONG_MIN + LLONG_MAX) + LLONG_MAX
+ : LLONG_MAX;
+ cutlim = cutoff % base;
+ cutoff /= base;
+ for ( ; ; c = *s++) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = neg ? LLONG_MIN : LLONG_MAX;
+ errno = ERANGE;
+ } else if (!any) {
+noconv:
+ errno = EINVAL;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != NULL)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (acc);
+}
+long long
+strtoll(const char * __restrict nptr, char ** __restrict endptr, int base)
+{
+ return strtoll_l(nptr, endptr, base, __get_locale());
+}
diff --git a/lib/libc/stdlib/strtonum.3 b/lib/libc/stdlib/strtonum.3
new file mode 100644
index 0000000..b83aadd
--- /dev/null
+++ b/lib/libc/stdlib/strtonum.3
@@ -0,0 +1,155 @@
+.\" Copyright (c) 2004 Ted Unangst
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" $OpenBSD: strtonum.3,v 1.13 2006/04/25 05:15:42 tedu Exp $
+.\" $FreeBSD$
+.\"
+.Dd April 29, 2004
+.Dt STRTONUM 3
+.Os
+.Sh NAME
+.Nm strtonum
+.Nd "reliably convert string value to an integer"
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft long long
+.Fo strtonum
+.Fa "const char *nptr"
+.Fa "long long minval"
+.Fa "long long maxval"
+.Fa "const char **errstr"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn strtonum
+function converts the string in
+.Fa nptr
+to a
+.Vt "long long"
+value.
+The
+.Fn strtonum
+function was designed to facilitate safe, robust programming
+and overcome the shortcomings of the
+.Xr atoi 3
+and
+.Xr strtol 3
+family of interfaces.
+.Pp
+The string may begin with an arbitrary amount of whitespace
+(as determined by
+.Xr isspace 3 )
+followed by a single optional
+.Ql +
+or
+.Ql -
+sign.
+.Pp
+The remainder of the string is converted to a
+.Vt "long long"
+value according to base 10.
+.Pp
+The value obtained is then checked against the provided
+.Fa minval
+and
+.Fa maxval
+bounds.
+If
+.Fa errstr
+is non-null,
+.Fn strtonum
+stores an error string in
+.Fa *errstr
+indicating the failure.
+.Sh RETURN VALUES
+The
+.Fn strtonum
+function returns the result of the conversion,
+unless the value would exceed the provided bounds or is invalid.
+On error, 0 is returned,
+.Va errno
+is set, and
+.Fa errstr
+will point to an error message.
+On success,
+.Fa *errstr
+will be set to
+.Dv NULL ;
+this fact can be used to differentiate
+a successful return of 0 from an error.
+.Sh EXAMPLES
+Using
+.Fn strtonum
+correctly is meant to be simpler than the alternative functions.
+.Bd -literal -offset indent
+int iterations;
+const char *errstr;
+
+iterations = strtonum(optarg, 1, 64, &errstr);
+if (errstr)
+ errx(1, "number of iterations is %s: %s", errstr, optarg);
+.Ed
+.Pp
+The above example will guarantee that the value of iterations is between
+1 and 64 (inclusive).
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er ERANGE
+The given string was out of range.
+.It Bq Er EINVAL
+The given string did not consist solely of digit characters.
+.It Bq Er EINVAL
+The supplied
+.Fa minval
+was larger than
+.Fa maxval .
+.El
+.Pp
+If an error occurs,
+.Fa errstr
+will be set to one of the following strings:
+.Pp
+.Bl -tag -width ".Li too large" -compact
+.It Li "too large"
+The result was larger than the provided maximum value.
+.It Li "too small"
+The result was smaller than the provided minimum value.
+.It Li invalid
+The string did not consist solely of digit characters.
+.El
+.Sh SEE ALSO
+.Xr atof 3 ,
+.Xr atoi 3 ,
+.Xr atol 3 ,
+.Xr atoll 3 ,
+.Xr sscanf 3 ,
+.Xr strtod 3 ,
+.Xr strtol 3 ,
+.Xr strtoul 3
+.Sh STANDARDS
+The
+.Fn strtonum
+function is a
+.Bx
+extension.
+The existing alternatives, such as
+.Xr atoi 3
+and
+.Xr strtol 3 ,
+are either impossible or difficult to use safely.
+.Sh HISTORY
+The
+.Fn strtonum
+function first appeared in
+.Ox 3.6 .
diff --git a/lib/libc/stdlib/strtonum.c b/lib/libc/stdlib/strtonum.c
new file mode 100644
index 0000000..6dccd97
--- /dev/null
+++ b/lib/libc/stdlib/strtonum.c
@@ -0,0 +1,68 @@
+/*-
+ * Copyright (c) 2004 Ted Unangst and Todd Miller
+ * All rights reserved.
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $OpenBSD: strtonum.c,v 1.6 2004/08/03 19:38:01 millert Exp $
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+
+#define INVALID 1
+#define TOOSMALL 2
+#define TOOLARGE 3
+
+long long
+strtonum(const char *numstr, long long minval, long long maxval,
+ const char **errstrp)
+{
+ long long ll = 0;
+ char *ep;
+ int error = 0;
+ struct errval {
+ const char *errstr;
+ int err;
+ } ev[4] = {
+ { NULL, 0 },
+ { "invalid", EINVAL },
+ { "too small", ERANGE },
+ { "too large", ERANGE },
+ };
+
+ ev[0].err = errno;
+ errno = 0;
+ if (minval > maxval)
+ error = INVALID;
+ else {
+ ll = strtoll(numstr, &ep, 10);
+ if (errno == EINVAL || numstr == ep || *ep != '\0')
+ error = INVALID;
+ else if ((ll == LLONG_MIN && errno == ERANGE) || ll < minval)
+ error = TOOSMALL;
+ else if ((ll == LLONG_MAX && errno == ERANGE) || ll > maxval)
+ error = TOOLARGE;
+ }
+ if (errstrp != NULL)
+ *errstrp = ev[error].errstr;
+ errno = ev[error].err;
+ if (error)
+ ll = 0;
+
+ return (ll);
+}
diff --git a/lib/libc/stdlib/strtoq.c b/lib/libc/stdlib/strtoq.c
new file mode 100644
index 0000000..afad51f
--- /dev/null
+++ b/lib/libc/stdlib/strtoq.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtoq.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <stdlib.h>
+
+/*
+ * Convert a string to a quad integer.
+ */
+quad_t
+strtoq(const char *nptr, char **endptr, int base)
+{
+
+ return strtoll(nptr, endptr, base);
+}
diff --git a/lib/libc/stdlib/strtoul.3 b/lib/libc/stdlib/strtoul.3
new file mode 100644
index 0000000..2c0f348
--- /dev/null
+++ b/lib/libc/stdlib/strtoul.3
@@ -0,0 +1,224 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strtoul.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd November 28, 2001
+.Dt STRTOUL 3
+.Os
+.Sh NAME
+.Nm strtoul , strtoull , strtoumax , strtouq
+.Nd "convert a string to an"
+.Vt "unsigned long" , "unsigned long long" , uintmax_t ,
+or
+.Vt u_quad_t
+integer
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.In limits.h
+.Ft "unsigned long"
+.Fn strtoul "const char * restrict nptr" "char ** restrict endptr" "int base"
+.Ft "unsigned long long"
+.Fn strtoull "const char * restrict nptr" "char ** restrict endptr" "int base"
+.In inttypes.h
+.Ft uintmax_t
+.Fn strtoumax "const char * restrict nptr" "char ** restrict endptr" "int base"
+.In sys/types.h
+.In stdlib.h
+.In limits.h
+.Ft u_quad_t
+.Fn strtouq "const char *nptr" "char **endptr" "int base"
+.Sh DESCRIPTION
+The
+.Fn strtoul
+function
+converts the string in
+.Fa nptr
+to an
+.Vt "unsigned long"
+value.
+The
+.Fn strtoull
+function
+converts the string in
+.Fa nptr
+to an
+.Vt "unsigned long long"
+value.
+The
+.Fn strtoumax
+function
+converts the string in
+.Fa nptr
+to an
+.Vt uintmax_t
+value.
+The
+.Fn strtouq
+function
+converts the string in
+.Fa nptr
+to a
+.Vt u_quad_t
+value.
+The conversion is done according to the given
+.Fa base ,
+which must be between 2 and 36 inclusive,
+or be the special value 0.
+.Pp
+The string may begin with an arbitrary amount of white space
+(as determined by
+.Xr isspace 3 )
+followed by a single optional
+.Ql +
+or
+.Ql -
+sign.
+If
+.Fa base
+is zero or 16,
+the string may then include a
+.Dq Li 0x
+prefix,
+and the number will be read in base 16; otherwise, a zero
+.Fa base
+is taken as 10 (decimal) unless the next character is
+.Ql 0 ,
+in which case it is taken as 8 (octal).
+.Pp
+The remainder of the string is converted to an
+.Vt "unsigned long"
+value in the obvious manner,
+stopping at the end of the string
+or at the first character that does not produce a valid digit
+in the given base.
+(In bases above 10, the letter
+.Ql A
+in either upper or lower case
+represents 10,
+.Ql B
+represents 11, and so forth, with
+.Ql Z
+representing 35.)
+.Pp
+If
+.Fa endptr
+is not
+.Dv NULL ,
+.Fn strtoul
+stores the address of the first invalid character in
+.Fa *endptr .
+If there were no digits at all, however,
+.Fn strtoul
+stores the original value of
+.Fa nptr
+in
+.Fa *endptr .
+(Thus, if
+.Fa *nptr
+is not
+.Ql \e0
+but
+.Fa **endptr
+is
+.Ql \e0
+on return, the entire string was valid.)
+.Sh RETURN VALUES
+The
+.Fn strtoul ,
+.Fn strtoull ,
+.Fn strtoumax
+and
+.Fn strtouq
+functions
+return either the result of the conversion
+or, if there was a leading minus sign,
+the negation of the result of the conversion,
+unless the original (non-negated) value would overflow;
+in the latter case,
+.Fn strtoul
+returns
+.Dv ULONG_MAX ,
+.Fn strtoull
+returns
+.Dv ULLONG_MAX ,
+.Fn strtoumax
+returns
+.Dv UINTMAX_MAX ,
+and
+.Fn strtouq
+returns
+.Dv ULLONG_MAX .
+In all cases,
+.Va errno
+is set to
+.Er ERANGE .
+If no conversion could be performed, 0 is returned and
+the global variable
+.Va errno
+is set to
+.Er EINVAL
+(the last feature is not portable across all platforms).
+.Sh ERRORS
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The value of
+.Fa base
+is not supported or
+no conversion could be performed
+(the last feature is not portable across all platforms).
+.It Bq Er ERANGE
+The given string was out of range; the value converted has been clamped.
+.El
+.Sh SEE ALSO
+.Xr strtol 3 ,
+.Xr strtonum 3 ,
+.Xr wcstoul 3
+.Sh STANDARDS
+The
+.Fn strtoul
+function
+conforms to
+.St -isoC .
+The
+.Fn strtoull
+and
+.Fn strtoumax
+functions
+conform to
+.St -isoC-99 .
+The
+.Bx
+.Fn strtouq
+function is deprecated.
diff --git a/lib/libc/stdlib/strtoul.c b/lib/libc/stdlib/strtoul.c
new file mode 100644
index 0000000..0ae0661
--- /dev/null
+++ b/lib/libc/stdlib/strtoul.c
@@ -0,0 +1,130 @@
+/*
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtoul.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include "xlocale_private.h"
+
+/*
+ * Convert a string to an unsigned long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long
+strtoul_l(const char * __restrict nptr, char ** __restrict endptr, int base, locale_t locale)
+{
+ const char *s;
+ unsigned long acc;
+ char c;
+ unsigned long cutoff;
+ int neg, any, cutlim;
+ FIX_LOCALE(locale);
+
+ /*
+ * See strtol for comments as to the logic used.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace_l((unsigned char)c, locale));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ acc = any = 0;
+ if (base < 2 || base > 36)
+ goto noconv;
+
+ cutoff = ULONG_MAX / base;
+ cutlim = ULONG_MAX % base;
+ for ( ; ; c = *s++) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULONG_MAX;
+ errno = ERANGE;
+ } else if (!any) {
+noconv:
+ errno = EINVAL;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != NULL)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (acc);
+}
+unsigned long
+strtoul(const char * __restrict nptr, char ** __restrict endptr, int base)
+{
+ return strtoul_l(nptr, endptr, base, __get_locale());
+}
diff --git a/lib/libc/stdlib/strtoull.c b/lib/libc/stdlib/strtoull.c
new file mode 100644
index 0000000..4b7f1c9
--- /dev/null
+++ b/lib/libc/stdlib/strtoull.c
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <limits.h>
+#include <errno.h>
+#include <ctype.h>
+#include <stdlib.h>
+#include "xlocale_private.h"
+
+/*
+ * Convert a string to an unsigned long long integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+unsigned long long
+strtoull_l(const char * __restrict nptr, char ** __restrict endptr, int base,
+ locale_t locale)
+{
+ const char *s;
+ unsigned long long acc;
+ char c;
+ unsigned long long cutoff;
+ int neg, any, cutlim;
+ FIX_LOCALE(locale);
+
+ /*
+ * See strtoq for comments as to the logic used.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace_l((unsigned char)c, locale));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ acc = any = 0;
+ if (base < 2 || base > 36)
+ goto noconv;
+
+ cutoff = ULLONG_MAX / base;
+ cutlim = ULLONG_MAX % base;
+ for ( ; ; c = *s++) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = ULLONG_MAX;
+ errno = ERANGE;
+ } else if (!any) {
+noconv:
+ errno = EINVAL;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != NULL)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (acc);
+}
+unsigned long long
+strtoull(const char * __restrict nptr, char ** __restrict endptr, int base)
+{
+ return strtoull_l(nptr, endptr, base, __get_locale());
+}
diff --git a/lib/libc/stdlib/strtoumax.c b/lib/libc/stdlib/strtoumax.c
new file mode 100644
index 0000000..d4362bb
--- /dev/null
+++ b/lib/libc/stdlib/strtoumax.c
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "from @(#)strtoul.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <inttypes.h>
+#include "xlocale_private.h"
+
+/*
+ * Convert a string to a uintmax_t integer.
+ *
+ * Assumes that the upper and lower case
+ * alphabets and digits are each contiguous.
+ */
+uintmax_t
+strtoumax_l(const char * __restrict nptr, char ** __restrict endptr, int base,
+ locale_t locale)
+{
+ const char *s;
+ uintmax_t acc;
+ char c;
+ uintmax_t cutoff;
+ int neg, any, cutlim;
+ FIX_LOCALE(locale);
+
+ /*
+ * See strtoimax for comments as to the logic used.
+ */
+ s = nptr;
+ do {
+ c = *s++;
+ } while (isspace_l((unsigned char)c, locale));
+ if (c == '-') {
+ neg = 1;
+ c = *s++;
+ } else {
+ neg = 0;
+ if (c == '+')
+ c = *s++;
+ }
+ if ((base == 0 || base == 16) &&
+ c == '0' && (*s == 'x' || *s == 'X') &&
+ ((s[1] >= '0' && s[1] <= '9') ||
+ (s[1] >= 'A' && s[1] <= 'F') ||
+ (s[1] >= 'a' && s[1] <= 'f'))) {
+ c = s[1];
+ s += 2;
+ base = 16;
+ }
+ if (base == 0)
+ base = c == '0' ? 8 : 10;
+ acc = any = 0;
+ if (base < 2 || base > 36)
+ goto noconv;
+
+ cutoff = UINTMAX_MAX / base;
+ cutlim = UINTMAX_MAX % base;
+ for ( ; ; c = *s++) {
+ if (c >= '0' && c <= '9')
+ c -= '0';
+ else if (c >= 'A' && c <= 'Z')
+ c -= 'A' - 10;
+ else if (c >= 'a' && c <= 'z')
+ c -= 'a' - 10;
+ else
+ break;
+ if (c >= base)
+ break;
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
+ any = -1;
+ else {
+ any = 1;
+ acc *= base;
+ acc += c;
+ }
+ }
+ if (any < 0) {
+ acc = UINTMAX_MAX;
+ errno = ERANGE;
+ } else if (!any) {
+noconv:
+ errno = EINVAL;
+ } else if (neg)
+ acc = -acc;
+ if (endptr != NULL)
+ *endptr = (char *)(any ? s - 1 : nptr);
+ return (acc);
+}
+uintmax_t
+strtoumax(const char * __restrict nptr, char ** __restrict endptr, int base)
+{
+ return strtoumax_l(nptr, endptr, base, __get_locale());
+}
diff --git a/lib/libc/stdlib/strtouq.c b/lib/libc/stdlib/strtouq.c
new file mode 100644
index 0000000..9638c11
--- /dev/null
+++ b/lib/libc/stdlib/strtouq.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtouq.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <stdlib.h>
+
+/*
+ * Convert a string to an unsigned quad integer.
+ */
+u_quad_t
+strtouq(const char *nptr, char **endptr, int base)
+{
+
+ return strtoull(nptr, endptr, base);
+}
diff --git a/lib/libc/stdlib/system.3 b/lib/libc/stdlib/system.3
new file mode 100644
index 0000000..3d13489
--- /dev/null
+++ b/lib/libc/stdlib/system.3
@@ -0,0 +1,99 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)system.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt SYSTEM 3
+.Os
+.Sh NAME
+.Nm system
+.Nd pass a command to the shell
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdlib.h
+.Ft int
+.Fn system "const char *string"
+.Sh DESCRIPTION
+The
+.Fn system
+function
+hands the argument
+.Fa string
+to the command interpreter
+.Xr sh 1 .
+The calling process waits for the shell
+to finish executing the command,
+ignoring
+.Dv SIGINT
+and
+.Dv SIGQUIT ,
+and blocking
+.Dv SIGCHLD .
+.Pp
+If
+.Fa string
+is a
+.Dv NULL
+pointer,
+.Fn system
+will return non-zero if the command interpreter
+.Xr sh 1
+is available, and zero if it is not.
+.Sh RETURN VALUES
+The
+.Fn system
+function
+returns the exit status of the shell as returned by
+.Xr waitpid 2 ,
+or \-1 if an error occurred when invoking
+.Xr fork 2
+or
+.Xr waitpid 2 .
+A return value of 127 means the execution of the shell
+failed.
+.Sh SEE ALSO
+.Xr sh 1 ,
+.Xr execve 2 ,
+.Xr fork 2 ,
+.Xr waitpid 2 ,
+.Xr popen 3
+.Sh STANDARDS
+The
+.Fn system
+function
+conforms to
+.St -isoC
+and is expected to be
+.St -p1003.2
+compatible.
diff --git a/lib/libc/stdlib/system.c b/lib/libc/stdlib/system.c
new file mode 100644
index 0000000..4f47edf
--- /dev/null
+++ b/lib/libc/stdlib/system.c
@@ -0,0 +1,97 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)system.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <stddef.h>
+#include <unistd.h>
+#include <paths.h>
+#include <errno.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+int
+__system(const char *command)
+{
+ pid_t pid, savedpid;
+ int pstat;
+ struct sigaction ign, intact, quitact;
+ sigset_t newsigblock, oldsigblock;
+
+ if (!command) /* just checking... */
+ return(1);
+
+ /*
+ * Ignore SIGINT and SIGQUIT, block SIGCHLD. Remember to save
+ * existing signal dispositions.
+ */
+ ign.sa_handler = SIG_IGN;
+ (void)sigemptyset(&ign.sa_mask);
+ ign.sa_flags = 0;
+ (void)_sigaction(SIGINT, &ign, &intact);
+ (void)_sigaction(SIGQUIT, &ign, &quitact);
+ (void)sigemptyset(&newsigblock);
+ (void)sigaddset(&newsigblock, SIGCHLD);
+ (void)_sigprocmask(SIG_BLOCK, &newsigblock, &oldsigblock);
+ switch(pid = fork()) {
+ case -1: /* error */
+ break;
+ case 0: /* child */
+ /*
+ * Restore original signal dispositions and exec the command.
+ */
+ (void)_sigaction(SIGINT, &intact, NULL);
+ (void)_sigaction(SIGQUIT, &quitact, NULL);
+ (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
+ execl(_PATH_BSHELL, "sh", "-c", command, (char *)NULL);
+ _exit(127);
+ default: /* parent */
+ savedpid = pid;
+ do {
+ pid = _wait4(savedpid, &pstat, 0, (struct rusage *)0);
+ } while (pid == -1 && errno == EINTR);
+ break;
+ }
+ (void)_sigaction(SIGINT, &intact, NULL);
+ (void)_sigaction(SIGQUIT, &quitact, NULL);
+ (void)_sigprocmask(SIG_SETMASK, &oldsigblock, NULL);
+ return(pid == -1 ? -1 : pstat);
+}
+
+__weak_reference(__system, system);
+__weak_reference(__system, _system);
diff --git a/lib/libc/stdlib/tdelete.c b/lib/libc/stdlib/tdelete.c
new file mode 100644
index 0000000..c83afb8
--- /dev/null
+++ b/lib/libc/stdlib/tdelete.c
@@ -0,0 +1,71 @@
+/* $NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $ */
+
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only, lint doesn't grok it.
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: tdelete.c,v 1.2 1999/09/16 11:45:37 lukem Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#define _SEARCH_PRIVATE
+#include <search.h>
+#include <stdlib.h>
+
+
+/*
+ * delete node with given key
+ *
+ * vkey: key to be deleted
+ * vrootp: address of the root of the tree
+ * compar: function to carry out node comparisons
+ */
+void *
+tdelete(const void * __restrict vkey, void ** __restrict vrootp,
+ int (*compar)(const void *, const void *))
+{
+ node_t **rootp = (node_t **)vrootp;
+ node_t *p, *q, *r;
+ int cmp;
+
+ if (rootp == NULL || (p = *rootp) == NULL)
+ return NULL;
+
+ while ((cmp = (*compar)(vkey, (*rootp)->key)) != 0) {
+ p = *rootp;
+ rootp = (cmp < 0) ?
+ &(*rootp)->llink : /* follow llink branch */
+ &(*rootp)->rlink; /* follow rlink branch */
+ if (*rootp == NULL)
+ return NULL; /* key not found */
+ }
+ r = (*rootp)->rlink; /* D1: */
+ if ((q = (*rootp)->llink) == NULL) /* Left NULL? */
+ q = r;
+ else if (r != NULL) { /* Right link is NULL? */
+ if (r->llink == NULL) { /* D2: Find successor */
+ r->llink = q;
+ q = r;
+ } else { /* D3: Find NULL link */
+ for (q = r->llink; q->llink != NULL; q = r->llink)
+ r = q;
+ r->llink = q->rlink;
+ q->llink = (*rootp)->llink;
+ q->rlink = (*rootp)->rlink;
+ }
+ }
+ free(*rootp); /* D4: Free node */
+ *rootp = q; /* link parent to new node */
+ return p;
+}
diff --git a/lib/libc/stdlib/tfind.c b/lib/libc/stdlib/tfind.c
new file mode 100644
index 0000000..c5d66cf
--- /dev/null
+++ b/lib/libc/stdlib/tfind.c
@@ -0,0 +1,48 @@
+/* $NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp $ */
+
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only, lint doesn't grok it.
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: tfind.c,v 1.2 1999/09/16 11:45:37 lukem Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#define _SEARCH_PRIVATE
+#include <stdlib.h>
+#include <search.h>
+
+/* find a node, or return 0 */
+void *
+tfind(vkey, vrootp, compar)
+ const void *vkey; /* key to be found */
+ void * const *vrootp; /* address of the tree root */
+ int (*compar)(const void *, const void *);
+{
+ node_t **rootp = (node_t **)vrootp;
+
+ if (rootp == NULL)
+ return NULL;
+
+ while (*rootp != NULL) { /* T1: */
+ int r;
+
+ if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */
+ return *rootp; /* key found */
+ rootp = (r < 0) ?
+ &(*rootp)->llink : /* T3: follow left branch */
+ &(*rootp)->rlink; /* T4: follow right branch */
+ }
+ return NULL;
+}
diff --git a/lib/libc/stdlib/tsearch.3 b/lib/libc/stdlib/tsearch.3
new file mode 100644
index 0000000..7a204d0
--- /dev/null
+++ b/lib/libc/stdlib/tsearch.3
@@ -0,0 +1,132 @@
+.\" $NetBSD$
+.\" Copyright (c) 1997 Todd C. Miller <Todd.Miller@courtesan.com>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" OpenBSD: tsearch.3,v 1.2 1998/06/21 22:13:49 millert Exp
+.\" $FreeBSD$
+.\"
+.Dd June 15, 1997
+.Dt TSEARCH 3
+.Os
+.Sh NAME
+.Nm tsearch , tfind , tdelete , twalk
+.Nd manipulate binary search trees
+.Sh SYNOPSIS
+.In search.h
+.Ft void *
+.Fn tdelete "const void * restrict key" "void ** restrict rootp" "int (*compar) (const void *, const void *)"
+.Ft void *
+.Fn tfind "const void *key" "void * const *rootp" "int (*compar) (const void *, const void *)"
+.Ft void *
+.Fn tsearch "const void *key" "void **rootp" "int (*compar) (const void *, const void *)"
+.Ft void
+.Fn twalk "const void *root" "void (*action) (const void *, VISIT, int)"
+.Sh DESCRIPTION
+The
+.Fn tdelete ,
+.Fn tfind ,
+.Fn tsearch ,
+and
+.Fn twalk
+functions manage binary search trees based on algorithms T and D
+from Knuth (6.2.2).
+The comparison function passed in by
+the user has the same style of return values as
+.Xr strcmp 3 .
+.Pp
+The
+.Fn tfind
+function
+searches for the datum matched by the argument
+.Fa key
+in the binary tree rooted at
+.Fa rootp ,
+returning a pointer to the datum if it is found and NULL
+if it is not.
+.Pp
+The
+.Fn tsearch
+function
+is identical to
+.Fn tfind
+except that if no match is found,
+.Fa key
+is inserted into the tree and a pointer to it is returned.
+If
+.Fa rootp
+points to a NULL value a new binary search tree is created.
+.Pp
+The
+.Fn tdelete
+function
+deletes a node from the specified binary search tree and returns
+a pointer to the parent of the node to be deleted.
+It takes the same arguments as
+.Fn tfind
+and
+.Fn tsearch .
+If the node to be deleted is the root of the binary search tree,
+.Fa rootp
+will be adjusted.
+.Pp
+The
+.Fn twalk
+function
+walks the binary search tree rooted in
+.Fa root
+and calls the function
+.Fa action
+on each node.
+The
+.Fa action
+function
+is called with three arguments: a pointer to the current node,
+a value from the enum
+.Sy "typedef enum { preorder, postorder, endorder, leaf } VISIT;"
+specifying the traversal type, and a node level (where level
+zero is the root of the tree).
+.Sh RETURN VALUES
+The
+.Fn tsearch
+function returns NULL if allocation of a new node fails (usually
+due to a lack of free memory).
+.Pp
+The
+.Fn tfind ,
+.Fn tsearch ,
+and
+.Fn tdelete
+functions
+return NULL if
+.Fa rootp
+is NULL or the datum cannot be found.
+.Pp
+The
+.Fn twalk
+function returns no value.
+.Sh SEE ALSO
+.Xr bsearch 3 ,
+.Xr hsearch 3 ,
+.Xr lsearch 3
diff --git a/lib/libc/stdlib/tsearch.c b/lib/libc/stdlib/tsearch.c
new file mode 100644
index 0000000..149c2bb
--- /dev/null
+++ b/lib/libc/stdlib/tsearch.c
@@ -0,0 +1,58 @@
+/* $NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp $ */
+
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only, lint doesn't grok it.
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: tsearch.c,v 1.3 1999/09/16 11:45:37 lukem Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#define _SEARCH_PRIVATE
+#include <search.h>
+#include <stdlib.h>
+
+/* find or insert datum into search tree */
+void *
+tsearch(vkey, vrootp, compar)
+ const void *vkey; /* key to be located */
+ void **vrootp; /* address of tree root */
+ int (*compar)(const void *, const void *);
+{
+ node_t *q;
+ node_t **rootp = (node_t **)vrootp;
+
+ if (rootp == NULL)
+ return NULL;
+
+ while (*rootp != NULL) { /* Knuth's T1: */
+ int r;
+
+ if ((r = (*compar)(vkey, (*rootp)->key)) == 0) /* T2: */
+ return *rootp; /* we found it! */
+
+ rootp = (r < 0) ?
+ &(*rootp)->llink : /* T3: follow left branch */
+ &(*rootp)->rlink; /* T4: follow right branch */
+ }
+
+ q = malloc(sizeof(node_t)); /* T5: key not found */
+ if (q != 0) { /* make new node */
+ *rootp = q; /* link new node to old */
+ /* LINTED const castaway ok */
+ q->key = (void *)vkey; /* initialize new node */
+ q->llink = q->rlink = NULL;
+ }
+ return q;
+}
diff --git a/lib/libc/stdlib/twalk.c b/lib/libc/stdlib/twalk.c
new file mode 100644
index 0000000..55f220f3
--- /dev/null
+++ b/lib/libc/stdlib/twalk.c
@@ -0,0 +1,58 @@
+/* $NetBSD: twalk.c,v 1.1 1999/02/22 10:33:16 christos Exp $ */
+
+/*
+ * Tree search generalized from Knuth (6.2.2) Algorithm T just like
+ * the AT&T man page says.
+ *
+ * The node_t structure is for internal use only, lint doesn't grok it.
+ *
+ * Written by reading the System V Interface Definition, not the code.
+ *
+ * Totally public domain.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: twalk.c,v 1.1 1999/02/22 10:33:16 christos Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#define _SEARCH_PRIVATE
+#include <search.h>
+#include <stdlib.h>
+
+static void trecurse(const node_t *,
+ void (*action)(const void *, VISIT, int), int level);
+
+/* Walk the nodes of a tree */
+static void
+trecurse(root, action, level)
+ const node_t *root; /* Root of the tree to be walked */
+ void (*action)(const void *, VISIT, int);
+ int level;
+{
+
+ if (root->llink == NULL && root->rlink == NULL)
+ (*action)(root, leaf, level);
+ else {
+ (*action)(root, preorder, level);
+ if (root->llink != NULL)
+ trecurse(root->llink, action, level + 1);
+ (*action)(root, postorder, level);
+ if (root->rlink != NULL)
+ trecurse(root->rlink, action, level + 1);
+ (*action)(root, endorder, level);
+ }
+}
+
+/* Walk the nodes of a tree */
+void
+twalk(vroot, action)
+ const void *vroot; /* Root of the tree to be walked */
+ void (*action)(const void *, VISIT, int);
+{
+ if (vroot != NULL && action != NULL)
+ trecurse(vroot, action, 0);
+}
diff --git a/lib/libc/stdtime/Makefile.inc b/lib/libc/stdtime/Makefile.inc
new file mode 100644
index 0000000..a039bc9
--- /dev/null
+++ b/lib/libc/stdtime/Makefile.inc
@@ -0,0 +1,21 @@
+# Makefile.inc,v 1.2 1994/09/13 21:26:01 wollman Exp
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/stdtime ${.CURDIR}/../locale \
+ ${.CURDIR}/../../contrib/tzcode/stdtime
+
+SRCS+= asctime.c difftime.c localtime.c strftime.c strptime.c timelocal.c \
+ time32.c
+
+SYM_MAPS+= ${.CURDIR}/stdtime/Symbol.map
+
+CFLAGS+= -I${.CURDIR}/../../contrib/tzcode/stdtime -I${.CURDIR}/stdtime
+
+MAN+= ctime.3 strftime.3 strptime.3 time2posix.3
+MAN+= tzfile.5
+
+MLINKS+=ctime.3 asctime.3 ctime.3 difftime.3 ctime.3 gmtime.3 \
+ ctime.3 localtime.3 ctime.3 mktime.3 ctime.3 timegm.3 \
+ ctime.3 ctime_r.3 ctime.3 localtime_r.3 ctime.3 gmtime_r.3 \
+ ctime.3 asctime_r.3
+MLINKS+=time2posix.3 posix2time.3
diff --git a/lib/libc/stdtime/Symbol.map b/lib/libc/stdtime/Symbol.map
new file mode 100644
index 0000000..3bee3735
--- /dev/null
+++ b/lib/libc/stdtime/Symbol.map
@@ -0,0 +1,35 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ _time32_to_time;
+ _time_to_time32;
+ _time64_to_time;
+ _time_to_time64;
+ _time_to_long;
+ _long_to_time;
+ _time_to_int;
+ _int_to_time;
+ strptime;
+ strftime;
+ tzname;
+ tzsetwall;
+ tzset;
+ localtime;
+ localtime_r;
+ gmtime;
+ gmtime_r;
+ offtime;
+ ctime;
+ ctime_r;
+ mktime;
+ timelocal;
+ timegm;
+ timeoff;
+ time2posix;
+ posix2time;
+ difftime;
+ asctime_r;
+ asctime;
+};
diff --git a/lib/libc/stdtime/strftime.3 b/lib/libc/stdtime/strftime.3
new file mode 100644
index 0000000..d5cdd7d
--- /dev/null
+++ b/lib/libc/stdtime/strftime.3
@@ -0,0 +1,278 @@
+.\" Copyright (c) 1989, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strftime.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd November 4, 2004
+.Dt STRFTIME 3
+.Os
+.Sh NAME
+.Nm strftime
+.Nd format date and time
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In time.h
+.Ft size_t
+.Fo strftime
+.Fa "char * restrict buf"
+.Fa "size_t maxsize"
+.Fa "const char * restrict format"
+.Fa "const struct tm * restrict timeptr"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn strftime
+function formats the information from
+.Fa timeptr
+into the buffer
+.Fa buf
+according to the string pointed to by
+.Fa format .
+.Pp
+The
+.Fa format
+string consists of zero or more conversion specifications and
+ordinary characters.
+All ordinary characters are copied directly into the buffer.
+A conversion specification consists of a percent sign
+.Dq Ql %
+and one other character.
+.Pp
+No more than
+.Fa maxsize
+characters will be placed into the array.
+If the total number of resulting characters, including the terminating
+NUL character, is not more than
+.Fa maxsize ,
+.Fn strftime
+returns the number of characters in the array, not counting the
+terminating NUL.
+Otherwise, zero is returned and the buffer contents are indeterminate.
+.Pp
+The conversion specifications are copied to the buffer after expansion
+as follows:-
+.Bl -tag -width "xxxx"
+.It Cm \&%A
+is replaced by national representation of the full weekday name.
+.It Cm %a
+is replaced by national representation of
+the abbreviated weekday name.
+.It Cm \&%B
+is replaced by national representation of the full month name.
+.It Cm %b
+is replaced by national representation of
+the abbreviated month name.
+.It Cm \&%C
+is replaced by (year / 100) as decimal number; single
+digits are preceded by a zero.
+.It Cm %c
+is replaced by national representation of time and date.
+.It Cm \&%D
+is equivalent to
+.Dq Li %m/%d/%y .
+.It Cm %d
+is replaced by the day of the month as a decimal number (01-31).
+.It Cm %E* %O*
+POSIX locale extensions.
+The sequences
+%Ec %EC %Ex %EX %Ey %EY
+%Od %Oe %OH %OI %Om %OM
+%OS %Ou %OU %OV %Ow %OW %Oy
+are supposed to provide alternate
+representations.
+.Pp
+Additionally %OB implemented
+to represent alternative months names
+(used standalone, without day mentioned).
+.It Cm %e
+is replaced by the day of the month as a decimal number (1-31); single
+digits are preceded by a blank.
+.It Cm \&%F
+is equivalent to
+.Dq Li %Y-%m-%d .
+.It Cm \&%G
+is replaced by a year as a decimal number with century.
+This year is the one that contains the greater part of
+the week (Monday as the first day of the week).
+.It Cm %g
+is replaced by the same year as in
+.Dq Li %G ,
+but as a decimal number without century (00-99).
+.It Cm \&%H
+is replaced by the hour (24-hour clock) as a decimal number (00-23).
+.It Cm %h
+the same as
+.Cm %b .
+.It Cm \&%I
+is replaced by the hour (12-hour clock) as a decimal number (01-12).
+.It Cm %j
+is replaced by the day of the year as a decimal number (001-366).
+.It Cm %k
+is replaced by the hour (24-hour clock) as a decimal number (0-23);
+single digits are preceded by a blank.
+.It Cm %l
+is replaced by the hour (12-hour clock) as a decimal number (1-12);
+single digits are preceded by a blank.
+.It Cm \&%M
+is replaced by the minute as a decimal number (00-59).
+.It Cm %m
+is replaced by the month as a decimal number (01-12).
+.It Cm %n
+is replaced by a newline.
+.It Cm %O*
+the same as
+.Cm %E* .
+.It Cm %p
+is replaced by national representation of either
+"ante meridiem" (a.m.)
+or
+"post meridiem" (p.m.)
+as appropriate.
+.It Cm \&%R
+is equivalent to
+.Dq Li %H:%M .
+.It Cm %r
+is equivalent to
+.Dq Li %I:%M:%S %p .
+.It Cm \&%S
+is replaced by the second as a decimal number (00-60).
+.It Cm %s
+is replaced by the number of seconds since the Epoch, UTC (see
+.Xr mktime 3 ) .
+.It Cm \&%T
+is equivalent to
+.Dq Li %H:%M:%S .
+.It Cm %t
+is replaced by a tab.
+.It Cm \&%U
+is replaced by the week number of the year (Sunday as the first day of
+the week) as a decimal number (00-53).
+.It Cm %u
+is replaced by the weekday (Monday as the first day of the week)
+as a decimal number (1-7).
+.It Cm \&%V
+is replaced by the week number of the year (Monday as the first day of
+the week) as a decimal number (01-53).
+If the week containing January
+1 has four or more days in the new year, then it is week 1; otherwise
+it is the last week of the previous year, and the next week is week 1.
+.It Cm %v
+is equivalent to
+.Dq Li %e-%b-%Y .
+.It Cm \&%W
+is replaced by the week number of the year (Monday as the first day of
+the week) as a decimal number (00-53).
+.It Cm %w
+is replaced by the weekday (Sunday as the first day of the week)
+as a decimal number (0-6).
+.It Cm \&%X
+is replaced by national representation of the time.
+.It Cm %x
+is replaced by national representation of the date.
+.It Cm \&%Y
+is replaced by the year with century as a decimal number.
+.It Cm %y
+is replaced by the year without century as a decimal number (00-99).
+.It Cm \&%Z
+is replaced by the time zone name.
+.It Cm %z
+is replaced by the time zone offset from UTC; a leading plus sign stands for
+east of UTC, a minus sign for west of UTC, hours and minutes follow
+with two digits each and no delimiter between them (common form for
+RFC 822 date headers).
+.It Cm %+
+is replaced by national representation of the date and time
+(the format is similar to that produced by
+.Xr date 1 ) .
+.It Cm %-*
+GNU libc extension.
+Do not do any padding when performing numerical outputs.
+.It Cm %_*
+GNU libc extension.
+Explicitly specify space for padding.
+.It Cm %0*
+GNU libc extension.
+Explicitly specify zero for padding.
+.It Cm %%
+is replaced by
+.Ql % .
+.El
+.Sh SEE ALSO
+.Xr date 1 ,
+.Xr printf 1 ,
+.Xr ctime 3 ,
+.Xr printf 3 ,
+.Xr strptime 3 ,
+.Xr wcsftime 3
+.Sh STANDARDS
+The
+.Fn strftime
+function
+conforms to
+.St -isoC
+with a lot of extensions including
+.Ql %C ,
+.Ql \&%D ,
+.Ql %E* ,
+.Ql %e ,
+.Ql %G ,
+.Ql %g ,
+.Ql %h ,
+.Ql %k ,
+.Ql %l ,
+.Ql %n ,
+.Ql %O* ,
+.Ql \&%R ,
+.Ql %r ,
+.Ql %s ,
+.Ql \&%T ,
+.Ql %t ,
+.Ql %u ,
+.Ql \&%V ,
+.Ql %z ,
+.Ql %+ .
+.Pp
+The peculiar week number and year in the replacements of
+.Ql %G ,
+.Ql %g
+and
+.Ql \&%V
+are defined in ISO 8601: 1988.
+.Sh BUGS
+There is no conversion specification for the phase of the moon.
+.Pp
+The
+.Fn strftime
+function does not correctly handle multibyte characters in the
+.Fa format
+argument.
diff --git a/lib/libc/stdtime/strftime.c b/lib/libc/stdtime/strftime.c
new file mode 100644
index 0000000..d3571ad
--- /dev/null
+++ b/lib/libc/stdtime/strftime.c
@@ -0,0 +1,648 @@
+/*
+ * Copyright (c) 1989 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms are permitted
+ * provided that the above copyright notice and this paragraph are
+ * duplicated in all such forms and that any documentation,
+ * advertising materials, and other materials related to such
+ * distribution and use acknowledge that the software was developed
+ * by the University of California, Berkeley. The name of the
+ * University may not be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#ifndef lint
+#ifndef NOID
+static const char elsieid[] = "@(#)strftime.3 8.3";
+/*
+** Based on the UCB version with the ID appearing below.
+** This is ANSIish only when "multibyte character == plain character".
+*/
+#endif /* !defined NOID */
+#endif /* !defined lint */
+
+#include "namespace.h"
+#include "private.h"
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static const char sccsid[] = "@(#)strftime.c 5.4 (Berkeley) 3/14/89";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "tzfile.h"
+#include <fcntl.h>
+#include <sys/stat.h>
+#include "un-namespace.h"
+#include "timelocal.h"
+
+static char * _add(const char *, char *, const char *);
+static char * _conv(int, const char *, char *, const char *);
+static char * _fmt(const char *, const struct tm *, char *, const char *,
+ int *, locale_t);
+static char * _yconv(int, int, int, int, char *, const char *);
+
+extern char * tzname[];
+
+#ifndef YEAR_2000_NAME
+#define YEAR_2000_NAME "CHECK_STRFTIME_FORMATS_FOR_TWO_DIGIT_YEARS"
+#endif /* !defined YEAR_2000_NAME */
+
+#define IN_NONE 0
+#define IN_SOME 1
+#define IN_THIS 2
+#define IN_ALL 3
+
+#define PAD_DEFAULT 0
+#define PAD_LESS 1
+#define PAD_SPACE 2
+#define PAD_ZERO 3
+
+static const char* fmt_padding[][4] = {
+ /* DEFAULT, LESS, SPACE, ZERO */
+#define PAD_FMT_MONTHDAY 0
+#define PAD_FMT_HMS 0
+#define PAD_FMT_CENTURY 0
+#define PAD_FMT_SHORTYEAR 0
+#define PAD_FMT_MONTH 0
+#define PAD_FMT_WEEKOFYEAR 0
+#define PAD_FMT_DAYOFMONTH 0
+ { "%02d", "%d", "%2d", "%02d" },
+#define PAD_FMT_SDAYOFMONTH 1
+#define PAD_FMT_SHMS 1
+ { "%2d", "%d", "%2d", "%02d" },
+#define PAD_FMT_DAYOFYEAR 2
+ { "%03d", "%d", "%3d", "%03d" },
+#define PAD_FMT_YEAR 3
+ { "%04d", "%d", "%4d", "%04d" }
+};
+
+size_t
+strftime_l(char * __restrict s, size_t maxsize, const char * __restrict format,
+ const struct tm * __restrict t, locale_t loc)
+{
+ char * p;
+ int warn;
+ FIX_LOCALE(loc);
+
+ tzset();
+ warn = IN_NONE;
+ p = _fmt(((format == NULL) ? "%c" : format), t, s, s + maxsize, &warn, loc);
+#ifndef NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU
+ if (warn != IN_NONE && getenv(YEAR_2000_NAME) != NULL) {
+ (void) fprintf_l(stderr, loc, "\n");
+ if (format == NULL)
+ (void) fprintf_l(stderr, loc, "NULL strftime format ");
+ else (void) fprintf_l(stderr, loc, "strftime format \"%s\" ",
+ format);
+ (void) fprintf_l(stderr, loc, "yields only two digits of years in ");
+ if (warn == IN_SOME)
+ (void) fprintf_l(stderr, loc, "some locales");
+ else if (warn == IN_THIS)
+ (void) fprintf_l(stderr, loc, "the current locale");
+ else (void) fprintf_l(stderr, loc, "all locales");
+ (void) fprintf_l(stderr, loc, "\n");
+ }
+#endif /* !defined NO_RUN_TIME_WARNINGS_ABOUT_YEAR_2000_PROBLEMS_THANK_YOU */
+ if (p == s + maxsize)
+ return 0;
+ *p = '\0';
+ return p - s;
+}
+
+size_t
+strftime(char * __restrict s, size_t maxsize, const char * __restrict format,
+ const struct tm * __restrict t)
+{
+ return strftime_l(s, maxsize, format, t, __get_locale());
+}
+
+static char *
+_fmt(format, t, pt, ptlim, warnp, loc)
+const char * format;
+const struct tm * const t;
+char * pt;
+const char * const ptlim;
+int * warnp;
+locale_t loc;
+{
+ int Ealternative, Oalternative, PadIndex;
+ struct lc_time_T *tptr = __get_current_time_locale(loc);
+
+ for ( ; *format; ++format) {
+ if (*format == '%') {
+ Ealternative = 0;
+ Oalternative = 0;
+ PadIndex = PAD_DEFAULT;
+label:
+ switch (*++format) {
+ case '\0':
+ --format;
+ break;
+ case 'A':
+ pt = _add((t->tm_wday < 0 ||
+ t->tm_wday >= DAYSPERWEEK) ?
+ "?" : tptr->weekday[t->tm_wday],
+ pt, ptlim);
+ continue;
+ case 'a':
+ pt = _add((t->tm_wday < 0 ||
+ t->tm_wday >= DAYSPERWEEK) ?
+ "?" : tptr->wday[t->tm_wday],
+ pt, ptlim);
+ continue;
+ case 'B':
+ pt = _add((t->tm_mon < 0 ||
+ t->tm_mon >= MONSPERYEAR) ?
+ "?" : (Oalternative ? tptr->alt_month :
+ tptr->month)[t->tm_mon],
+ pt, ptlim);
+ continue;
+ case 'b':
+ case 'h':
+ pt = _add((t->tm_mon < 0 ||
+ t->tm_mon >= MONSPERYEAR) ?
+ "?" : tptr->mon[t->tm_mon],
+ pt, ptlim);
+ continue;
+ case 'C':
+ /*
+ ** %C used to do a...
+ ** _fmt("%a %b %e %X %Y", t);
+ ** ...whereas now POSIX 1003.2 calls for
+ ** something completely different.
+ ** (ado, 1993-05-24)
+ */
+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 0,
+ pt, ptlim);
+ continue;
+ case 'c':
+ {
+ int warn2 = IN_SOME;
+
+ pt = _fmt(tptr->c_fmt, t, pt, ptlim, &warn2, loc);
+ if (warn2 == IN_ALL)
+ warn2 = IN_THIS;
+ if (warn2 > *warnp)
+ *warnp = warn2;
+ }
+ continue;
+ case 'D':
+ pt = _fmt("%m/%d/%y", t, pt, ptlim, warnp, loc);
+ continue;
+ case 'd':
+ pt = _conv(t->tm_mday, fmt_padding[PAD_FMT_DAYOFMONTH][PadIndex],
+ pt, ptlim);
+ continue;
+ case 'E':
+ if (Ealternative || Oalternative)
+ break;
+ Ealternative++;
+ goto label;
+ case 'O':
+ /*
+ ** C99 locale modifiers.
+ ** The sequences
+ ** %Ec %EC %Ex %EX %Ey %EY
+ ** %Od %oe %OH %OI %Om %OM
+ ** %OS %Ou %OU %OV %Ow %OW %Oy
+ ** are supposed to provide alternate
+ ** representations.
+ **
+ ** FreeBSD extension
+ ** %OB
+ */
+ if (Ealternative || Oalternative)
+ break;
+ Oalternative++;
+ goto label;
+ case 'e':
+ pt = _conv(t->tm_mday,
+ fmt_padding[PAD_FMT_SDAYOFMONTH][PadIndex], pt, ptlim);
+ continue;
+ case 'F':
+ pt = _fmt("%Y-%m-%d", t, pt, ptlim, warnp, loc);
+ continue;
+ case 'H':
+ pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_HMS][PadIndex],
+ pt, ptlim);
+ continue;
+ case 'I':
+ pt = _conv((t->tm_hour % 12) ?
+ (t->tm_hour % 12) : 12,
+ fmt_padding[PAD_FMT_HMS][PadIndex], pt, ptlim);
+ continue;
+ case 'j':
+ pt = _conv(t->tm_yday + 1,
+ fmt_padding[PAD_FMT_DAYOFYEAR][PadIndex], pt, ptlim);
+ continue;
+ case 'k':
+ /*
+ ** This used to be...
+ ** _conv(t->tm_hour % 12 ?
+ ** t->tm_hour % 12 : 12, 2, ' ');
+ ** ...and has been changed to the below to
+ ** match SunOS 4.1.1 and Arnold Robbins'
+ ** strftime version 3.0. That is, "%k" and
+ ** "%l" have been swapped.
+ ** (ado, 1993-05-24)
+ */
+ pt = _conv(t->tm_hour, fmt_padding[PAD_FMT_SHMS][PadIndex],
+ pt, ptlim);
+ continue;
+#ifdef KITCHEN_SINK
+ case 'K':
+ /*
+ ** After all this time, still unclaimed!
+ */
+ pt = _add("kitchen sink", pt, ptlim);
+ continue;
+#endif /* defined KITCHEN_SINK */
+ case 'l':
+ /*
+ ** This used to be...
+ ** _conv(t->tm_hour, 2, ' ');
+ ** ...and has been changed to the below to
+ ** match SunOS 4.1.1 and Arnold Robbin's
+ ** strftime version 3.0. That is, "%k" and
+ ** "%l" have been swapped.
+ ** (ado, 1993-05-24)
+ */
+ pt = _conv((t->tm_hour % 12) ?
+ (t->tm_hour % 12) : 12,
+ fmt_padding[PAD_FMT_SHMS][PadIndex], pt, ptlim);
+ continue;
+ case 'M':
+ pt = _conv(t->tm_min, fmt_padding[PAD_FMT_HMS][PadIndex],
+ pt, ptlim);
+ continue;
+ case 'm':
+ pt = _conv(t->tm_mon + 1,
+ fmt_padding[PAD_FMT_MONTH][PadIndex], pt, ptlim);
+ continue;
+ case 'n':
+ pt = _add("\n", pt, ptlim);
+ continue;
+ case 'p':
+ pt = _add((t->tm_hour >= (HOURSPERDAY / 2)) ?
+ tptr->pm :
+ tptr->am,
+ pt, ptlim);
+ continue;
+ case 'R':
+ pt = _fmt("%H:%M", t, pt, ptlim, warnp, loc);
+ continue;
+ case 'r':
+ pt = _fmt(tptr->ampm_fmt, t, pt, ptlim,
+ warnp, loc);
+ continue;
+ case 'S':
+ pt = _conv(t->tm_sec, fmt_padding[PAD_FMT_HMS][PadIndex],
+ pt, ptlim);
+ continue;
+ case 's':
+ {
+ struct tm tm;
+ char buf[INT_STRLEN_MAXIMUM(
+ time_t) + 1];
+ time_t mkt;
+
+ tm = *t;
+ mkt = mktime(&tm);
+ if (TYPE_SIGNED(time_t))
+ (void) sprintf(buf, "%ld",
+ (long) mkt);
+ else (void) sprintf(buf, "%lu",
+ (unsigned long) mkt);
+ pt = _add(buf, pt, ptlim);
+ }
+ continue;
+ case 'T':
+ pt = _fmt("%H:%M:%S", t, pt, ptlim, warnp, loc);
+ continue;
+ case 't':
+ pt = _add("\t", pt, ptlim);
+ continue;
+ case 'U':
+ pt = _conv((t->tm_yday + DAYSPERWEEK -
+ t->tm_wday) / DAYSPERWEEK,
+ fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex], pt, ptlim);
+ continue;
+ case 'u':
+ /*
+ ** From Arnold Robbins' strftime version 3.0:
+ ** "ISO 8601: Weekday as a decimal number
+ ** [1 (Monday) - 7]"
+ ** (ado, 1993-05-24)
+ */
+ pt = _conv((t->tm_wday == 0) ?
+ DAYSPERWEEK : t->tm_wday,
+ "%d", pt, ptlim);
+ continue;
+ case 'V': /* ISO 8601 week number */
+ case 'G': /* ISO 8601 year (four digits) */
+ case 'g': /* ISO 8601 year (two digits) */
+/*
+** From Arnold Robbins' strftime version 3.0: "the week number of the
+** year (the first Monday as the first day of week 1) as a decimal number
+** (01-53)."
+** (ado, 1993-05-24)
+**
+** From "http://www.ft.uni-erlangen.de/~mskuhn/iso-time.html" by Markus Kuhn:
+** "Week 01 of a year is per definition the first week which has the
+** Thursday in this year, which is equivalent to the week which contains
+** the fourth day of January. In other words, the first week of a new year
+** is the week which has the majority of its days in the new year. Week 01
+** might also contain days from the previous year and the week before week
+** 01 of a year is the last week (52 or 53) of the previous year even if
+** it contains days from the new year. A week starts with Monday (day 1)
+** and ends with Sunday (day 7). For example, the first week of the year
+** 1997 lasts from 1996-12-30 to 1997-01-05..."
+** (ado, 1996-01-02)
+*/
+ {
+ int year;
+ int base;
+ int yday;
+ int wday;
+ int w;
+
+ year = t->tm_year;
+ base = TM_YEAR_BASE;
+ yday = t->tm_yday;
+ wday = t->tm_wday;
+ for ( ; ; ) {
+ int len;
+ int bot;
+ int top;
+
+ len = isleap_sum(year, base) ?
+ DAYSPERLYEAR :
+ DAYSPERNYEAR;
+ /*
+ ** What yday (-3 ... 3) does
+ ** the ISO year begin on?
+ */
+ bot = ((yday + 11 - wday) %
+ DAYSPERWEEK) - 3;
+ /*
+ ** What yday does the NEXT
+ ** ISO year begin on?
+ */
+ top = bot -
+ (len % DAYSPERWEEK);
+ if (top < -3)
+ top += DAYSPERWEEK;
+ top += len;
+ if (yday >= top) {
+ ++base;
+ w = 1;
+ break;
+ }
+ if (yday >= bot) {
+ w = 1 + ((yday - bot) /
+ DAYSPERWEEK);
+ break;
+ }
+ --base;
+ yday += isleap_sum(year, base) ?
+ DAYSPERLYEAR :
+ DAYSPERNYEAR;
+ }
+#ifdef XPG4_1994_04_09
+ if ((w == 52 &&
+ t->tm_mon == TM_JANUARY) ||
+ (w == 1 &&
+ t->tm_mon == TM_DECEMBER))
+ w = 53;
+#endif /* defined XPG4_1994_04_09 */
+ if (*format == 'V')
+ pt = _conv(w, fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex],
+ pt, ptlim);
+ else if (*format == 'g') {
+ *warnp = IN_ALL;
+ pt = _yconv(year, base, 0, 1,
+ pt, ptlim);
+ } else pt = _yconv(year, base, 1, 1,
+ pt, ptlim);
+ }
+ continue;
+ case 'v':
+ /*
+ ** From Arnold Robbins' strftime version 3.0:
+ ** "date as dd-bbb-YYYY"
+ ** (ado, 1993-05-24)
+ */
+ pt = _fmt("%e-%b-%Y", t, pt, ptlim, warnp, loc);
+ continue;
+ case 'W':
+ pt = _conv((t->tm_yday + DAYSPERWEEK -
+ (t->tm_wday ?
+ (t->tm_wday - 1) :
+ (DAYSPERWEEK - 1))) / DAYSPERWEEK,
+ fmt_padding[PAD_FMT_WEEKOFYEAR][PadIndex], pt, ptlim);
+ continue;
+ case 'w':
+ pt = _conv(t->tm_wday, "%d", pt, ptlim);
+ continue;
+ case 'X':
+ pt = _fmt(tptr->X_fmt, t, pt, ptlim, warnp, loc);
+ continue;
+ case 'x':
+ {
+ int warn2 = IN_SOME;
+
+ pt = _fmt(tptr->x_fmt, t, pt, ptlim, &warn2, loc);
+ if (warn2 == IN_ALL)
+ warn2 = IN_THIS;
+ if (warn2 > *warnp)
+ *warnp = warn2;
+ }
+ continue;
+ case 'y':
+ *warnp = IN_ALL;
+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 0, 1,
+ pt, ptlim);
+ continue;
+ case 'Y':
+ pt = _yconv(t->tm_year, TM_YEAR_BASE, 1, 1,
+ pt, ptlim);
+ continue;
+ case 'Z':
+#ifdef TM_ZONE
+ if (t->TM_ZONE != NULL)
+ pt = _add(t->TM_ZONE, pt, ptlim);
+ else
+#endif /* defined TM_ZONE */
+ if (t->tm_isdst >= 0)
+ pt = _add(tzname[t->tm_isdst != 0],
+ pt, ptlim);
+ /*
+ ** C99 says that %Z must be replaced by the
+ ** empty string if the time zone is not
+ ** determinable.
+ */
+ continue;
+ case 'z':
+ {
+ int diff;
+ char const * sign;
+
+ if (t->tm_isdst < 0)
+ continue;
+#ifdef TM_GMTOFF
+ diff = t->TM_GMTOFF;
+#else /* !defined TM_GMTOFF */
+ /*
+ ** C99 says that the UTC offset must
+ ** be computed by looking only at
+ ** tm_isdst. This requirement is
+ ** incorrect, since it means the code
+ ** must rely on magic (in this case
+ ** altzone and timezone), and the
+ ** magic might not have the correct
+ ** offset. Doing things correctly is
+ ** tricky and requires disobeying C99;
+ ** see GNU C strftime for details.
+ ** For now, punt and conform to the
+ ** standard, even though it's incorrect.
+ **
+ ** C99 says that %z must be replaced by the
+ ** empty string if the time zone is not
+ ** determinable, so output nothing if the
+ ** appropriate variables are not available.
+ */
+ if (t->tm_isdst == 0)
+#ifdef USG_COMPAT
+ diff = -timezone;
+#else /* !defined USG_COMPAT */
+ continue;
+#endif /* !defined USG_COMPAT */
+ else
+#ifdef ALTZONE
+ diff = -altzone;
+#else /* !defined ALTZONE */
+ continue;
+#endif /* !defined ALTZONE */
+#endif /* !defined TM_GMTOFF */
+ if (diff < 0) {
+ sign = "-";
+ diff = -diff;
+ } else sign = "+";
+ pt = _add(sign, pt, ptlim);
+ diff /= SECSPERMIN;
+ diff = (diff / MINSPERHOUR) * 100 +
+ (diff % MINSPERHOUR);
+ pt = _conv(diff,
+ fmt_padding[PAD_FMT_YEAR][PadIndex], pt, ptlim);
+ }
+ continue;
+ case '+':
+ pt = _fmt(tptr->date_fmt, t, pt, ptlim,
+ warnp, loc);
+ continue;
+ case '-':
+ if (PadIndex != PAD_DEFAULT)
+ break;
+ PadIndex = PAD_LESS;
+ goto label;
+ case '_':
+ if (PadIndex != PAD_DEFAULT)
+ break;
+ PadIndex = PAD_SPACE;
+ goto label;
+ case '0':
+ if (PadIndex != PAD_DEFAULT)
+ break;
+ PadIndex = PAD_ZERO;
+ goto label;
+ case '%':
+ /*
+ ** X311J/88-090 (4.12.3.5): if conversion char is
+ ** undefined, behavior is undefined. Print out the
+ ** character itself as printf(3) also does.
+ */
+ default:
+ break;
+ }
+ }
+ if (pt == ptlim)
+ break;
+ *pt++ = *format;
+ }
+ return pt;
+}
+
+static char *
+_conv(n, format, pt, ptlim)
+const int n;
+const char * const format;
+char * const pt;
+const char * const ptlim;
+{
+ char buf[INT_STRLEN_MAXIMUM(int) + 1];
+
+ (void) sprintf(buf, format, n);
+ return _add(buf, pt, ptlim);
+}
+
+static char *
+_add(str, pt, ptlim)
+const char * str;
+char * pt;
+const char * const ptlim;
+{
+ while (pt < ptlim && (*pt = *str++) != '\0')
+ ++pt;
+ return pt;
+}
+
+/*
+** POSIX and the C Standard are unclear or inconsistent about
+** what %C and %y do if the year is negative or exceeds 9999.
+** Use the convention that %C concatenated with %y yields the
+** same output as %Y, and that %Y contains at least 4 bytes,
+** with more only if necessary.
+*/
+
+static char *
+_yconv(a, b, convert_top, convert_yy, pt, ptlim)
+const int a;
+const int b;
+const int convert_top;
+const int convert_yy;
+char * pt;
+const char * const ptlim;
+{
+ register int lead;
+ register int trail;
+
+#define DIVISOR 100
+ trail = a % DIVISOR + b % DIVISOR;
+ lead = a / DIVISOR + b / DIVISOR + trail / DIVISOR;
+ trail %= DIVISOR;
+ if (trail < 0 && lead > 0) {
+ trail += DIVISOR;
+ --lead;
+ } else if (lead < 0 && trail > 0) {
+ trail -= DIVISOR;
+ ++lead;
+ }
+ if (convert_top) {
+ if (lead == 0 && trail < 0)
+ pt = _add("-0", pt, ptlim);
+ else pt = _conv(lead, "%02d", pt, ptlim);
+ }
+ if (convert_yy)
+ pt = _conv(((trail < 0) ? -trail : trail), "%02d", pt, ptlim);
+ return pt;
+}
diff --git a/lib/libc/stdtime/strptime.3 b/lib/libc/stdtime/strptime.3
new file mode 100644
index 0000000..763696b
--- /dev/null
+++ b/lib/libc/stdtime/strptime.3
@@ -0,0 +1,173 @@
+.\"
+.\" Copyright (c) 1997 Joerg Wunsch
+.\"
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE DEVELOPERS BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\" "
+.Dd January 4, 2003
+.Dt STRPTIME 3
+.Os
+.Sh NAME
+.Nm strptime
+.Nd parse date and time string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In time.h
+.Ft char *
+.Fo strptime
+.Fa "const char * restrict buf"
+.Fa "const char * restrict format"
+.Fa "struct tm * restrict timeptr"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn strptime
+function parses the string in the buffer
+.Fa buf
+according to the string pointed to by
+.Fa format ,
+and fills in the elements of the structure pointed to by
+.Fa timeptr .
+The resulting values will be relative to the local time zone.
+Thus, it can be considered the reverse operation of
+.Xr strftime 3 .
+.Pp
+The
+.Fa format
+string consists of zero or more conversion specifications and
+ordinary characters.
+All ordinary characters are matched exactly with the buffer, where
+white space in the format string will match any amount of white space
+in the buffer.
+All conversion specifications are identical to those described in
+.Xr strftime 3 .
+.Pp
+Two-digit year values, including formats
+.Fa %y
+and
+.Fa \&%D ,
+are now interpreted as beginning at 1969 per POSIX requirements.
+Years 69-00 are interpreted in the 20th century (1969-2000), years
+01-68 in the 21st century (2001-2068).
+.Pp
+If the
+.Fa format
+string does not contain enough conversion specifications to completely
+specify the resulting
+.Vt struct tm ,
+the unspecified members of
+.Va timeptr
+are left untouched.
+For example, if
+.Fa format
+is
+.Dq Li "%H:%M:%S" ,
+only
+.Va tm_hour ,
+.Va tm_sec
+and
+.Va tm_min
+will be modified.
+If time relative to today is desired, initialize the
+.Fa timeptr
+structure with today's date before passing it to
+.Fn strptime .
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn strptime
+returns the pointer to the first character in
+.Fa buf
+that has not been required to satisfy the specified conversions in
+.Fa format .
+It returns
+.Dv NULL
+if one of the conversions failed.
+.Sh SEE ALSO
+.Xr date 1 ,
+.Xr scanf 3 ,
+.Xr strftime 3
+.Sh HISTORY
+The
+.Fn strptime
+function appeared in
+.Fx 3.0 .
+.Sh AUTHORS
+The
+.Fn strptime
+function has been contributed by Powerdog Industries.
+.Pp
+This man page was written by
+.An J\(:org Wunsch .
+.Sh BUGS
+Both the
+.Fa %e
+and
+.Fa %l
+format specifiers may incorrectly scan one too many digits
+if the intended values comprise only a single digit
+and that digit is followed immediately by another digit.
+Both specifiers accept zero-padded values,
+even though they are both defined as taking unpadded values.
+.Pp
+The
+.Fa %p
+format specifier has no effect unless it is parsed
+.Em after
+hour-related specifiers.
+Specifying
+.Fa %l
+without
+.Fa %p
+will produce undefined results.
+Note that 12AM
+(ante meridiem)
+is taken as midnight
+and 12PM
+(post meridiem)
+is taken as noon.
+.Pp
+The
+.Fa \&%U
+and
+.Fa %W
+format specifiers accept any value within the range 00 to 53
+without validating against other values supplied (like month
+or day of the year, for example).
+.Pp
+The
+.Fa %Z
+format specifier only accepts time zone abbreviations of the local time zone,
+or the value "GMT".
+This limitation is because of ambiguity due to of the over loading of time
+zone abbreviations.
+One such example is
+.Fa EST
+which is both Eastern Standard Time and Eastern Australia Summer Time.
+.Pp
+The
+.Fn strptime
+function does not correctly handle multibyte characters in the
+.Fa format
+argument.
diff --git a/lib/libc/stdtime/strptime.c b/lib/libc/stdtime/strptime.c
new file mode 100644
index 0000000..fb94dcd
--- /dev/null
+++ b/lib/libc/stdtime/strptime.c
@@ -0,0 +1,614 @@
+/*
+ * Powerdog Industries kindly requests feedback from anyone modifying
+ * this function:
+ *
+ * Date: Thu, 05 Jun 1997 23:17:17 -0400
+ * From: Kevin Ruddy <kevin.ruddy@powerdog.com>
+ * To: James FitzGibbon <james@nexis.net>
+ * Subject: Re: Use of your strptime(3) code (fwd)
+ *
+ * The reason for the "no mod" clause was so that modifications would
+ * come back and we could integrate them and reissue so that a wider
+ * audience could use it (thereby spreading the wealth). This has
+ * made it possible to get strptime to work on many operating systems.
+ * I'm not sure why that's "plain unacceptable" to the FreeBSD team.
+ *
+ * Anyway, you can change it to "with or without modification" as
+ * you see fit. Enjoy.
+ *
+ * Kevin Ruddy
+ * Powerdog Industries, Inc.
+ */
+/*
+ * Copyright (c) 1994 Powerdog Industries. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgement:
+ * This product includes software developed by Powerdog Industries.
+ * 4. The name of Powerdog Industries may not be used to endorse or
+ * promote products derived from this software without specific prior
+ * written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY POWERDOG INDUSTRIES ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE POWERDOG INDUSTRIES BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#ifndef lint
+#ifndef NOID
+static char copyright[] __unused =
+"@(#) Copyright (c) 1994 Powerdog Industries. All rights reserved.";
+static char sccsid[] __unused = "@(#)strptime.c 0.1 (Powerdog) 94/03/27";
+#endif /* !defined NOID */
+#endif /* not lint */
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <time.h>
+#include <ctype.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+#include "timelocal.h"
+
+static char * _strptime(const char *, const char *, struct tm *, int *, locale_t);
+
+#define asizeof(a) (sizeof (a) / sizeof ((a)[0]))
+
+static char *
+_strptime(const char *buf, const char *fmt, struct tm *tm, int *GMTp,
+ locale_t locale)
+{
+ char c;
+ const char *ptr;
+ int i,
+ len;
+ int Ealternative, Oalternative;
+ struct lc_time_T *tptr = __get_current_time_locale(locale);
+
+ ptr = fmt;
+ while (*ptr != 0) {
+ if (*buf == 0)
+ break;
+
+ c = *ptr++;
+
+ if (c != '%') {
+ if (isspace_l((unsigned char)c, locale))
+ while (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ buf++;
+ else if (c != *buf++)
+ return 0;
+ continue;
+ }
+
+ Ealternative = 0;
+ Oalternative = 0;
+label:
+ c = *ptr++;
+ switch (c) {
+ case 0:
+ case '%':
+ if (*buf++ != '%')
+ return 0;
+ break;
+
+ case '+':
+ buf = _strptime(buf, tptr->date_fmt, tm, GMTp, locale);
+ if (buf == 0)
+ return 0;
+ break;
+
+ case 'C':
+ if (!isdigit_l((unsigned char)*buf, locale))
+ return 0;
+
+ /* XXX This will break for 3-digit centuries. */
+ len = 2;
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++) {
+ i *= 10;
+ i += *buf - '0';
+ len--;
+ }
+ if (i < 19)
+ return 0;
+
+ tm->tm_year = i * 100 - 1900;
+ break;
+
+ case 'c':
+ buf = _strptime(buf, tptr->c_fmt, tm, GMTp, locale);
+ if (buf == 0)
+ return 0;
+ break;
+
+ case 'D':
+ buf = _strptime(buf, "%m/%d/%y", tm, GMTp, locale);
+ if (buf == 0)
+ return 0;
+ break;
+
+ case 'E':
+ if (Ealternative || Oalternative)
+ break;
+ Ealternative++;
+ goto label;
+
+ case 'O':
+ if (Ealternative || Oalternative)
+ break;
+ Oalternative++;
+ goto label;
+
+ case 'F':
+ buf = _strptime(buf, "%Y-%m-%d", tm, GMTp, locale);
+ if (buf == 0)
+ return 0;
+ break;
+
+ case 'R':
+ buf = _strptime(buf, "%H:%M", tm, GMTp, locale);
+ if (buf == 0)
+ return 0;
+ break;
+
+ case 'r':
+ buf = _strptime(buf, tptr->ampm_fmt, tm, GMTp, locale);
+ if (buf == 0)
+ return 0;
+ break;
+
+ case 'T':
+ buf = _strptime(buf, "%H:%M:%S", tm, GMTp, locale);
+ if (buf == 0)
+ return 0;
+ break;
+
+ case 'X':
+ buf = _strptime(buf, tptr->X_fmt, tm, GMTp, locale);
+ if (buf == 0)
+ return 0;
+ break;
+
+ case 'x':
+ buf = _strptime(buf, tptr->x_fmt, tm, GMTp, locale);
+ if (buf == 0)
+ return 0;
+ break;
+
+ case 'j':
+ if (!isdigit_l((unsigned char)*buf, locale))
+ return 0;
+
+ len = 3;
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++){
+ i *= 10;
+ i += *buf - '0';
+ len--;
+ }
+ if (i < 1 || i > 366)
+ return 0;
+
+ tm->tm_yday = i - 1;
+ break;
+
+ case 'M':
+ case 'S':
+ if (*buf == 0 ||
+ isspace_l((unsigned char)*buf, locale))
+ break;
+
+ if (!isdigit_l((unsigned char)*buf, locale))
+ return 0;
+
+ len = 2;
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++){
+ i *= 10;
+ i += *buf - '0';
+ len--;
+ }
+
+ if (c == 'M') {
+ if (i > 59)
+ return 0;
+ tm->tm_min = i;
+ } else {
+ if (i > 60)
+ return 0;
+ tm->tm_sec = i;
+ }
+
+ if (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ while (*ptr != 0 &&
+ !isspace_l((unsigned char)*ptr, locale))
+ ptr++;
+ break;
+
+ case 'H':
+ case 'I':
+ case 'k':
+ case 'l':
+ /*
+ * Of these, %l is the only specifier explicitly
+ * documented as not being zero-padded. However,
+ * there is no harm in allowing zero-padding.
+ *
+ * XXX The %l specifier may gobble one too many
+ * digits if used incorrectly.
+ */
+ if (!isdigit_l((unsigned char)*buf, locale))
+ return 0;
+
+ len = 2;
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++) {
+ i *= 10;
+ i += *buf - '0';
+ len--;
+ }
+ if (c == 'H' || c == 'k') {
+ if (i > 23)
+ return 0;
+ } else if (i > 12)
+ return 0;
+
+ tm->tm_hour = i;
+
+ if (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ while (*ptr != 0 &&
+ !isspace_l((unsigned char)*ptr, locale))
+ ptr++;
+ break;
+
+ case 'p':
+ /*
+ * XXX This is bogus if parsed before hour-related
+ * specifiers.
+ */
+ len = strlen(tptr->am);
+ if (strncasecmp_l(buf, tptr->am, len, locale) == 0) {
+ if (tm->tm_hour > 12)
+ return 0;
+ if (tm->tm_hour == 12)
+ tm->tm_hour = 0;
+ buf += len;
+ break;
+ }
+
+ len = strlen(tptr->pm);
+ if (strncasecmp_l(buf, tptr->pm, len, locale) == 0) {
+ if (tm->tm_hour > 12)
+ return 0;
+ if (tm->tm_hour != 12)
+ tm->tm_hour += 12;
+ buf += len;
+ break;
+ }
+
+ return 0;
+
+ case 'A':
+ case 'a':
+ for (i = 0; i < asizeof(tptr->weekday); i++) {
+ len = strlen(tptr->weekday[i]);
+ if (strncasecmp_l(buf, tptr->weekday[i],
+ len, locale) == 0)
+ break;
+ len = strlen(tptr->wday[i]);
+ if (strncasecmp_l(buf, tptr->wday[i],
+ len, locale) == 0)
+ break;
+ }
+ if (i == asizeof(tptr->weekday))
+ return 0;
+
+ tm->tm_wday = i;
+ buf += len;
+ break;
+
+ case 'U':
+ case 'W':
+ /*
+ * XXX This is bogus, as we can not assume any valid
+ * information present in the tm structure at this
+ * point to calculate a real value, so just check the
+ * range for now.
+ */
+ if (!isdigit_l((unsigned char)*buf, locale))
+ return 0;
+
+ len = 2;
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++) {
+ i *= 10;
+ i += *buf - '0';
+ len--;
+ }
+ if (i > 53)
+ return 0;
+
+ if (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ while (*ptr != 0 &&
+ !isspace_l((unsigned char)*ptr, locale))
+ ptr++;
+ break;
+
+ case 'w':
+ if (!isdigit_l((unsigned char)*buf, locale))
+ return 0;
+
+ i = *buf - '0';
+ if (i > 6)
+ return 0;
+
+ tm->tm_wday = i;
+
+ if (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ while (*ptr != 0 &&
+ !isspace_l((unsigned char)*ptr, locale))
+ ptr++;
+ break;
+
+ case 'd':
+ case 'e':
+ /*
+ * The %e specifier is explicitly documented as not
+ * being zero-padded but there is no harm in allowing
+ * such padding.
+ *
+ * XXX The %e specifier may gobble one too many
+ * digits if used incorrectly.
+ */
+ if (!isdigit_l((unsigned char)*buf, locale))
+ return 0;
+
+ len = 2;
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++) {
+ i *= 10;
+ i += *buf - '0';
+ len--;
+ }
+ if (i > 31)
+ return 0;
+
+ tm->tm_mday = i;
+
+ if (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ while (*ptr != 0 &&
+ !isspace_l((unsigned char)*ptr, locale))
+ ptr++;
+ break;
+
+ case 'B':
+ case 'b':
+ case 'h':
+ for (i = 0; i < asizeof(tptr->month); i++) {
+ if (Oalternative) {
+ if (c == 'B') {
+ len = strlen(tptr->alt_month[i]);
+ if (strncasecmp_l(buf,
+ tptr->alt_month[i],
+ len, locale) == 0)
+ break;
+ }
+ } else {
+ len = strlen(tptr->month[i]);
+ if (strncasecmp_l(buf, tptr->month[i],
+ len, locale) == 0)
+ break;
+ }
+ }
+ /*
+ * Try the abbreviated month name if the full name
+ * wasn't found and Oalternative was not requested.
+ */
+ if (i == asizeof(tptr->month) && !Oalternative) {
+ for (i = 0; i < asizeof(tptr->month); i++) {
+ len = strlen(tptr->mon[i]);
+ if (strncasecmp_l(buf, tptr->mon[i],
+ len, locale) == 0)
+ break;
+ }
+ }
+ if (i == asizeof(tptr->month))
+ return 0;
+
+ tm->tm_mon = i;
+ buf += len;
+ break;
+
+ case 'm':
+ if (!isdigit_l((unsigned char)*buf, locale))
+ return 0;
+
+ len = 2;
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++) {
+ i *= 10;
+ i += *buf - '0';
+ len--;
+ }
+ if (i < 1 || i > 12)
+ return 0;
+
+ tm->tm_mon = i - 1;
+
+ if (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ while (*ptr != 0 &&
+ !isspace_l((unsigned char)*ptr, locale))
+ ptr++;
+ break;
+
+ case 's':
+ {
+ char *cp;
+ int sverrno;
+ long n;
+ time_t t;
+
+ sverrno = errno;
+ errno = 0;
+ n = strtol_l(buf, &cp, 10, locale);
+ if (errno == ERANGE || (long)(t = n) != n) {
+ errno = sverrno;
+ return 0;
+ }
+ errno = sverrno;
+ buf = cp;
+ gmtime_r(&t, tm);
+ *GMTp = 1;
+ }
+ break;
+
+ case 'Y':
+ case 'y':
+ if (*buf == 0 ||
+ isspace_l((unsigned char)*buf, locale))
+ break;
+
+ if (!isdigit_l((unsigned char)*buf, locale))
+ return 0;
+
+ len = (c == 'Y') ? 4 : 2;
+ for (i = 0; len && *buf != 0 &&
+ isdigit_l((unsigned char)*buf, locale); buf++) {
+ i *= 10;
+ i += *buf - '0';
+ len--;
+ }
+ if (c == 'Y')
+ i -= 1900;
+ if (c == 'y' && i < 69)
+ i += 100;
+ if (i < 0)
+ return 0;
+
+ tm->tm_year = i;
+
+ if (*buf != 0 &&
+ isspace_l((unsigned char)*buf, locale))
+ while (*ptr != 0 &&
+ !isspace_l((unsigned char)*ptr, locale))
+ ptr++;
+ break;
+
+ case 'Z':
+ {
+ const char *cp;
+ char *zonestr;
+
+ for (cp = buf; *cp &&
+ isupper_l((unsigned char)*cp, locale); ++cp) {
+ /*empty*/}
+ if (cp - buf) {
+ zonestr = alloca(cp - buf + 1);
+ strncpy(zonestr, buf, cp - buf);
+ zonestr[cp - buf] = '\0';
+ tzset();
+ if (0 == strcmp(zonestr, "GMT")) {
+ *GMTp = 1;
+ } else if (0 == strcmp(zonestr, tzname[0])) {
+ tm->tm_isdst = 0;
+ } else if (0 == strcmp(zonestr, tzname[1])) {
+ tm->tm_isdst = 1;
+ } else {
+ return 0;
+ }
+ buf += cp - buf;
+ }
+ }
+ break;
+
+ case 'z':
+ {
+ int sign = 1;
+
+ if (*buf != '+') {
+ if (*buf == '-')
+ sign = -1;
+ else
+ return 0;
+ }
+
+ buf++;
+ i = 0;
+ for (len = 4; len > 0; len--) {
+ if (isdigit_l((unsigned char)*buf, locale)) {
+ i *= 10;
+ i += *buf - '0';
+ buf++;
+ } else
+ return 0;
+ }
+
+ tm->tm_hour -= sign * (i / 100);
+ tm->tm_min -= sign * (i % 100);
+ *GMTp = 1;
+ }
+ break;
+ }
+ }
+ return (char *)buf;
+}
+
+
+char *
+strptime_l(const char * __restrict buf, const char * __restrict fmt,
+ struct tm * __restrict tm, locale_t loc)
+{
+ char *ret;
+ int gmt;
+ FIX_LOCALE(loc);
+
+ gmt = 0;
+ ret = _strptime(buf, fmt, tm, &gmt, loc);
+ if (ret && gmt) {
+ time_t t = timegm(tm);
+ localtime_r(&t, tm);
+ }
+
+ return (ret);
+}
+char *
+strptime(const char * __restrict buf, const char * __restrict fmt,
+ struct tm * __restrict tm)
+{
+ return strptime_l(buf, fmt, tm, __get_locale());
+}
diff --git a/lib/libc/stdtime/time32.c b/lib/libc/stdtime/time32.c
new file mode 100644
index 0000000..e852a4f
--- /dev/null
+++ b/lib/libc/stdtime/time32.c
@@ -0,0 +1,100 @@
+/*-
+ * Copyright (c) 2001 FreeBSD Inc.
+ * All rights reserved.
+ *
+ * These routines are for converting time_t to fixed-bit representations
+ * for use in protocols or storage. When converting time to a larger
+ * representation of time_t these routines are expected to assume temporal
+ * locality and use the 50-year rule to properly set the msb bits. XXX
+ *
+ * Redistribution and use under the terms of the COPYRIGHT file at the
+ * base of the source tree.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <timeconv.h>
+
+/*
+ * Convert a 32 bit representation of time_t into time_t. XXX needs to
+ * implement the 50-year rule to handle post-2038 conversions.
+ */
+time_t
+_time32_to_time(__int32_t t32)
+{
+ return((time_t)t32);
+}
+
+/*
+ * Convert time_t to a 32 bit representation. If time_t is 64 bits we can
+ * simply chop it down. The resulting 32 bit representation can be
+ * converted back to a temporally local 64 bit time_t using time32_to_time.
+ */
+__int32_t
+_time_to_time32(time_t t)
+{
+ return((__int32_t)t);
+}
+
+/*
+ * Convert a 64 bit representation of time_t into time_t. If time_t is
+ * represented as 32 bits we can simply chop it and not support times
+ * past 2038.
+ */
+time_t
+_time64_to_time(__int64_t t64)
+{
+ return((time_t)t64);
+}
+
+/*
+ * Convert time_t to a 64 bit representation. If time_t is represented
+ * as 32 bits we simply sign-extend and do not support times past 2038.
+ */
+__int64_t
+_time_to_time64(time_t t)
+{
+ return((__int64_t)t);
+}
+
+/*
+ * Convert to/from 'long'. Depending on the sizeof(long) this may or
+ * may not require using the 50-year rule.
+ */
+long
+_time_to_long(time_t t)
+{
+ if (sizeof(long) == sizeof(__int64_t))
+ return(_time_to_time64(t));
+ return((long)t);
+}
+
+time_t
+_long_to_time(long tlong)
+{
+ if (sizeof(long) == sizeof(__int32_t))
+ return(_time32_to_time(tlong));
+ return((time_t)tlong);
+}
+
+/*
+ * Convert to/from 'int'. Depending on the sizeof(int) this may or
+ * may not require using the 50-year rule.
+ */
+int
+_time_to_int(time_t t)
+{
+ if (sizeof(int) == sizeof(__int64_t))
+ return(_time_to_time64(t));
+ return((int)t);
+}
+
+time_t
+_int_to_time(int tint)
+{
+ if (sizeof(int) == sizeof(__int32_t))
+ return(_time32_to_time(tint));
+ return((time_t)tint);
+}
diff --git a/lib/libc/stdtime/timelocal.c b/lib/libc/stdtime/timelocal.c
new file mode 100644
index 0000000..3d9d096
--- /dev/null
+++ b/lib/libc/stdtime/timelocal.c
@@ -0,0 +1,154 @@
+/*-
+ * Copyright (c) 2001 Alexey Zelkin <phantom@FreeBSD.org>
+ * Copyright (c) 1997 FreeBSD Inc.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stddef.h>
+
+#include "ldpart.h"
+#include "timelocal.h"
+
+struct xlocale_time {
+ struct xlocale_component header;
+ char *buffer;
+ struct lc_time_T locale;
+};
+
+struct xlocale_time __xlocale_global_time;
+
+#define LCTIME_SIZE (sizeof(struct lc_time_T) / sizeof(char *))
+
+static const struct lc_time_T _C_time_locale = {
+ {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+ "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
+ }, {
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"
+ }, {
+ "Sun", "Mon", "Tue", "Wed",
+ "Thu", "Fri", "Sat"
+ }, {
+ "Sunday", "Monday", "Tuesday", "Wednesday",
+ "Thursday", "Friday", "Saturday"
+ },
+
+ /* X_fmt */
+ "%H:%M:%S",
+
+ /*
+ * x_fmt
+ * Since the C language standard calls for
+ * "date, using locale's date format," anything goes.
+ * Using just numbers (as here) makes Quakers happier;
+ * it's also compatible with SVR4.
+ */
+ "%m/%d/%y",
+
+ /*
+ * c_fmt
+ */
+ "%a %b %e %H:%M:%S %Y",
+
+ /* am */
+ "AM",
+
+ /* pm */
+ "PM",
+
+ /* date_fmt */
+ "%a %b %e %H:%M:%S %Z %Y",
+
+ /* alt_month
+ * Standalone months forms for %OB
+ */
+ {
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"
+ },
+
+ /* md_order
+ * Month / day order in dates
+ */
+ "md",
+
+ /* ampm_fmt
+ * To determine 12-hour clock format time (empty, if N/A)
+ */
+ "%I:%M:%S %p"
+};
+
+static void destruct_time(void *v)
+{
+ struct xlocale_time *l = v;
+ if (l->buffer)
+ free(l->buffer);
+ free(l);
+}
+
+#include <stdio.h>
+struct lc_time_T *
+__get_current_time_locale(locale_t loc)
+{
+ return (loc->using_time_locale
+ ? &((struct xlocale_time *)loc->components[XLC_TIME])->locale
+ : (struct lc_time_T *)&_C_time_locale);
+}
+
+static int
+time_load_locale(struct xlocale_time *l, int *using_locale, const char *name)
+{
+ struct lc_time_T *time_locale = &l->locale;
+ return (__part_load_locale(name, using_locale,
+ &l->buffer, "LC_TIME",
+ LCTIME_SIZE, LCTIME_SIZE,
+ (const char **)time_locale));
+}
+int
+__time_load_locale(const char *name)
+{
+ return time_load_locale(&__xlocale_global_time,
+ &__xlocale_global_locale.using_time_locale, name);
+}
+void* __time_load(const char* name, locale_t loc)
+{
+ struct xlocale_time *new = calloc(sizeof(struct xlocale_time), 1);
+ new->header.header.destructor = destruct_time;
+ if (time_load_locale(new, &loc->using_time_locale, name) == _LDP_ERROR)
+ {
+ xlocale_release(new);
+ return NULL;
+ }
+ return new;
+}
+
diff --git a/lib/libc/stdtime/timelocal.h b/lib/libc/stdtime/timelocal.h
new file mode 100644
index 0000000..2e44415
--- /dev/null
+++ b/lib/libc/stdtime/timelocal.h
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 1997-2002 FreeBSD Project.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#ifndef _TIMELOCAL_H_
+#define _TIMELOCAL_H_
+#include "xlocale_private.h"
+
+/*
+ * Private header file for the strftime and strptime localization
+ * stuff.
+ */
+struct lc_time_T {
+ const char *mon[12];
+ const char *month[12];
+ const char *wday[7];
+ const char *weekday[7];
+ const char *X_fmt;
+ const char *x_fmt;
+ const char *c_fmt;
+ const char *am;
+ const char *pm;
+ const char *date_fmt;
+ const char *alt_month[12];
+ const char *md_order;
+ const char *ampm_fmt;
+};
+
+struct lc_time_T *__get_current_time_locale(locale_t);
+int __time_load_locale(const char *);
+
+#endif /* !_TIMELOCAL_H_ */
diff --git a/lib/libc/string/Makefile.inc b/lib/libc/string/Makefile.inc
new file mode 100644
index 0000000..1dbe317
--- /dev/null
+++ b/lib/libc/string/Makefile.inc
@@ -0,0 +1,86 @@
+# @(#)Makefile.inc 8.1 (Berkeley) 6/4/93
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/${LIBC_ARCH}/string ${.CURDIR}/string
+
+CFLAGS+= -I${.CURDIR}/locale
+
+# machine-independent string sources
+MISRCS+=bcmp.c bcopy.c bzero.c ffs.c ffsl.c ffsll.c fls.c flsl.c flsll.c \
+ memccpy.c memchr.c memrchr.c memcmp.c \
+ memcpy.c memmem.c memmove.c memset.c \
+ stpcpy.c stpncpy.c strcasecmp.c \
+ strcat.c strcasestr.c strchr.c strcmp.c strcoll.c strcpy.c strcspn.c \
+ strdup.c strerror.c strlcat.c strlcpy.c strlen.c strmode.c strncat.c \
+ strncmp.c strncpy.c strndup.c strnlen.c strnstr.c \
+ strpbrk.c strrchr.c strsep.c strsignal.c strspn.c strstr.c strtok.c \
+ strxfrm.c swab.c wcpcpy.c wcpncpy.c wcscasecmp.c wcscat.c \
+ wcschr.c wcscmp.c wcscoll.c wcscpy.c wcscspn.c wcsdup.c \
+ wcslcat.c wcslcpy.c wcslen.c wcsncasecmp.c wcsncat.c wcsncmp.c \
+ wcsncpy.c wcsnlen.c wcspbrk.c \
+ wcsrchr.c wcsspn.c wcsstr.c wcstok.c wcswidth.c wcsxfrm.c wmemchr.c \
+ wmemcmp.c \
+ wmemcpy.c wmemmove.c wmemset.c
+
+SYM_MAPS+= ${.CURDIR}/string/Symbol.map
+
+
+# machine-dependent string sources
+.sinclude "${.CURDIR}/${LIBC_ARCH}/string/Makefile.inc"
+
+MAN+= bcmp.3 bcopy.3 bstring.3 bzero.3 ffs.3 index.3 memccpy.3 memchr.3 \
+ memcmp.3 memcpy.3 memmem.3 memmove.3 memset.3 strcasecmp.3 strcat.3 \
+ strchr.3 strcmp.3 strcoll.3 strcpy.3 strcspn.3 strdup.3 strerror.3 \
+ string.3 strlcpy.3 strlen.3 strmode.3 strpbrk.3 strsep.3 \
+ strspn.3 strstr.3 strtok.3 strxfrm.3 swab.3 wcscoll.3 wcstok.3 \
+ wcswidth.3 wcsxfrm.3 wmemchr.3
+
+MLINKS+=ffs.3 ffsl.3 \
+ ffs.3 ffsll.3 \
+ ffs.3 fls.3 \
+ ffs.3 flsl.3 \
+ ffs.3 flsll.3
+MLINKS+=index.3 rindex.3
+MLINKS+=memchr.3 memrchr.3
+MLINKS+=strcasecmp.3 strncasecmp.3
+MLINKS+=strcat.3 strncat.3
+MLINKS+=strchr.3 strrchr.3
+MLINKS+=strcmp.3 strncmp.3
+MLINKS+=strcpy.3 stpcpy.3 \
+ strcpy.3 stpncpy.3 \
+ strcpy.3 strncpy.3
+MLINKS+=strdup.3 strndup.3
+MLINKS+=strerror.3 perror.3 \
+ strerror.3 strerror_r.3 \
+ strerror.3 sys_errlist.3 \
+ strerror.3 sys_nerr.3
+MLINKS+=strlcpy.3 strlcat.3
+MLINKS+=strlen.3 strnlen.3
+MLINKS+=strstr.3 strcasestr.3 \
+ strstr.3 strnstr.3
+MLINKS+=strtok.3 strtok_r.3
+MLINKS+=wmemchr.3 wcpcpy.3 \
+ wmemchr.3 wcpncpy.3 \
+ wmemchr.3 wcscasecmp.3 \
+ wmemchr.3 wcscat.3 \
+ wmemchr.3 wcschr.3 \
+ wmemchr.3 wcscmp.3 \
+ wmemchr.3 wcscpy.3 \
+ wmemchr.3 wcscspn.3 \
+ wmemchr.3 wcsdup.3 \
+ wmemchr.3 wcslcat.3 \
+ wmemchr.3 wcslcpy.3 \
+ wmemchr.3 wcslen.3 \
+ wmemchr.3 wcsncasecmp.3 \
+ wmemchr.3 wcsncat.3 \
+ wmemchr.3 wcsncmp.3 \
+ wmemchr.3 wcsncpy.3 \
+ wmemchr.3 wcsnlen.3 \
+ wmemchr.3 wcspbrk.3 \
+ wmemchr.3 wcsrchr.3 \
+ wmemchr.3 wcsspn.3 \
+ wmemchr.3 wcsstr.3 \
+ wmemchr.3 wmemcmp.3 \
+ wmemchr.3 wmemcpy.3 \
+ wmemchr.3 wmemmove.3 \
+ wmemchr.3 wmemset.3
diff --git a/lib/libc/string/Symbol.map b/lib/libc/string/Symbol.map
new file mode 100644
index 0000000..ef23465
--- /dev/null
+++ b/lib/libc/string/Symbol.map
@@ -0,0 +1,104 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ bcmp;
+ bcopy;
+ memcpy;
+ memmove;
+ ffs;
+ ffsl;
+ fls;
+ flsl;
+ index;
+ strchr;
+ memccpy;
+ memchr;
+ memcmp;
+ memmem;
+ bzero;
+ memset;
+ strrchr;
+ rindex;
+ stpcpy;
+ strcasecmp;
+ strncasecmp;
+ strcasestr;
+ strcat;
+ strcmp;
+ strcoll;
+ strcpy;
+ strcspn;
+ strdup;
+ strerror_r;
+ strerror;
+ strlcat;
+ strlcpy;
+ strlen;
+ strmode;
+ strncat;
+ strncmp;
+ strncpy;
+ strnstr;
+ strpbrk;
+ strsep;
+ strsignal;
+ strspn;
+ strstr;
+ strtok_r;
+ strtok;
+ strxfrm;
+ swab;
+ wcscat;
+ wcschr;
+ wcscmp;
+ wcscoll;
+ wcscpy;
+ wcscspn;
+ wcsdup;
+ wcslcat;
+ wcslcpy;
+ wcslen;
+ wcsncat;
+ wcsncmp;
+ wcsncpy;
+ wcspbrk;
+ wcsrchr;
+ wcsspn;
+ wcsstr;
+ wcstok;
+ wcswidth;
+ wcsxfrm;
+ wmemchr;
+ wmemcmp;
+ wmemcpy;
+ wmemmove;
+ wmemset;
+};
+
+FBSD_1.1 {
+ ffsll;
+ flsll;
+ memrchr;
+ stpncpy;
+ strndup;
+ strnlen;
+ wcpcpy;
+ wcpncpy;
+ wcscasecmp;
+ wcsncasecmp;
+ wcsnlen;
+};
+
+FBSD_1.3 {
+ strcasecmp_l;
+ strcasestr_l;
+ strncasecmp_l;
+ wcswidth_l;
+ wcwidth_l;
+};
+
+FBSDprivate_1.0 {
+ __strtok_r;
+};
diff --git a/lib/libc/string/bcmp.3 b/lib/libc/string/bcmp.3
new file mode 100644
index 0000000..d043c2c
--- /dev/null
+++ b/lib/libc/string/bcmp.3
@@ -0,0 +1,77 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)bcmp.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt BCMP 3
+.Os
+.Sh NAME
+.Nm bcmp
+.Nd compare byte string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In strings.h
+.Ft int
+.Fn bcmp "const void *b1" "const void *b2" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn bcmp
+function
+compares byte string
+.Fa b1
+against byte string
+.Fa b2 ,
+returning zero if they are identical, non-zero otherwise.
+Both strings are assumed to be
+.Fa len
+bytes long.
+Zero-length strings are always identical.
+.Pp
+The strings may overlap.
+.Sh SEE ALSO
+.Xr memcmp 3 ,
+.Xr strcasecmp 3 ,
+.Xr strcmp 3 ,
+.Xr strcoll 3 ,
+.Xr strxfrm 3
+.Sh HISTORY
+A
+.Fn bcmp
+function first appeared in
+.Bx 4.2 .
+Its prototype existed previously in
+.In string.h
+before it was moved to
+.In strings.h
+for
+.St -p1003.1-2001
+compliance.
diff --git a/lib/libc/string/bcmp.c b/lib/libc/string/bcmp.c
new file mode 100644
index 0000000..117a9a1
--- /dev/null
+++ b/lib/libc/string/bcmp.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bcmp.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <strings.h>
+
+/*
+ * bcmp -- vax cmpc3 instruction
+ */
+int
+bcmp(const void *b1, const void *b2, size_t length)
+{
+ char *p1, *p2;
+
+ if (length == 0)
+ return (0);
+ p1 = (char *)b1;
+ p2 = (char *)b2;
+ do
+ if (*p1++ != *p2++)
+ break;
+ while (--length);
+ return (length);
+}
diff --git a/lib/libc/string/bcopy.3 b/lib/libc/string/bcopy.3
new file mode 100644
index 0000000..23f7ac2
--- /dev/null
+++ b/lib/libc/string/bcopy.3
@@ -0,0 +1,77 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)bcopy.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt BCOPY 3
+.Os
+.Sh NAME
+.Nm bcopy
+.Nd copy byte string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In strings.h
+.Ft void
+.Fn bcopy "const void *src" "void *dst" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn bcopy
+function
+copies
+.Fa len
+bytes from string
+.Fa src
+to string
+.Fa dst .
+The two strings may overlap.
+If
+.Fa len
+is zero, no bytes are copied.
+.Sh SEE ALSO
+.Xr memccpy 3 ,
+.Xr memcpy 3 ,
+.Xr memmove 3 ,
+.Xr strcpy 3 ,
+.Xr strncpy 3
+.Sh HISTORY
+A
+.Fn bcopy
+function appeared in
+.Bx 4.2 .
+Its prototype existed previously in
+.In string.h
+before it was moved to
+.In strings.h
+for
+.St -p1003.1-2001
+compliance.
diff --git a/lib/libc/string/bcopy.c b/lib/libc/string/bcopy.c
new file mode 100644
index 0000000..bb1209c
--- /dev/null
+++ b/lib/libc/string/bcopy.c
@@ -0,0 +1,137 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)bcopy.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+/*
+ * sizeof(word) MUST BE A POWER OF TWO
+ * SO THAT wmask BELOW IS ALL ONES
+ */
+typedef int word; /* "word" used for optimal copy speed */
+
+#define wsize sizeof(word)
+#define wmask (wsize - 1)
+
+/*
+ * Copy a block of memory, handling overlap.
+ * This is the routine that actually implements
+ * (the portable versions of) bcopy, memcpy, and memmove.
+ */
+#if defined(MEMCOPY) || defined(MEMMOVE)
+#include <string.h>
+
+void *
+#ifdef MEMCOPY
+memcpy
+#else
+memmove
+#endif
+(void *dst0, const void *src0, size_t length)
+#else
+#include <strings.h>
+
+void
+bcopy(const void *src0, void *dst0, size_t length)
+#endif
+{
+ char *dst = dst0;
+ const char *src = src0;
+ size_t t;
+
+ if (length == 0 || dst == src) /* nothing to do */
+ goto done;
+
+ /*
+ * Macros: loop-t-times; and loop-t-times, t>0
+ */
+#define TLOOP(s) if (t) TLOOP1(s)
+#define TLOOP1(s) do { s; } while (--t)
+
+ if ((unsigned long)dst < (unsigned long)src) {
+ /*
+ * Copy forward.
+ */
+ t = (uintptr_t)src; /* only need low bits */
+ if ((t | (uintptr_t)dst) & wmask) {
+ /*
+ * Try to align operands. This cannot be done
+ * unless the low bits match.
+ */
+ if ((t ^ (uintptr_t)dst) & wmask || length < wsize)
+ t = length;
+ else
+ t = wsize - (t & wmask);
+ length -= t;
+ TLOOP1(*dst++ = *src++);
+ }
+ /*
+ * Copy whole words, then mop up any trailing bytes.
+ */
+ t = length / wsize;
+ TLOOP(*(word *)dst = *(word *)src; src += wsize; dst += wsize);
+ t = length & wmask;
+ TLOOP(*dst++ = *src++);
+ } else {
+ /*
+ * Copy backwards. Otherwise essentially the same.
+ * Alignment works as before, except that it takes
+ * (t&wmask) bytes to align, not wsize-(t&wmask).
+ */
+ src += length;
+ dst += length;
+ t = (uintptr_t)src;
+ if ((t | (uintptr_t)dst) & wmask) {
+ if ((t ^ (uintptr_t)dst) & wmask || length <= wsize)
+ t = length;
+ else
+ t &= wmask;
+ length -= t;
+ TLOOP1(*--dst = *--src);
+ }
+ t = length / wsize;
+ TLOOP(src -= wsize; dst -= wsize; *(word *)dst = *(word *)src);
+ t = length & wmask;
+ TLOOP(*--dst = *--src);
+ }
+done:
+#if defined(MEMCOPY) || defined(MEMMOVE)
+ return (dst0);
+#else
+ return;
+#endif
+}
diff --git a/lib/libc/string/bstring.3 b/lib/libc/string/bstring.3
new file mode 100644
index 0000000..b1aef1b
--- /dev/null
+++ b/lib/libc/string/bstring.3
@@ -0,0 +1,108 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)bstring.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt BSTRING 3
+.Os
+.Sh NAME
+.Nm bcmp ,
+.Nm bcopy ,
+.Nm bzero ,
+.Nm memccpy ,
+.Nm memchr ,
+.Nm memcmp ,
+.Nm memcpy ,
+.Nm memmove ,
+.Nm memset
+.Nd byte string operations
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft int
+.Fn bcmp "const void *b1" "const void *b2" "size_t len"
+.Ft void
+.Fn bcopy "const void *src" "void *dst" "size_t len"
+.Ft void
+.Fn bzero "void *b" "size_t len"
+.Ft void *
+.Fn memchr "const void *b" "int c" "size_t len"
+.Ft int
+.Fn memcmp "const void *b1" "const void *b2" "size_t len"
+.Ft void *
+.Fn memccpy "void *dst" "const void *src" "int c" "size_t len"
+.Ft void *
+.Fn memcpy "void *dst" "const void *src" "size_t len"
+.Ft void *
+.Fn memmove "void *dst" "const void *src" "size_t len"
+.Ft void *
+.Fn memset "void *b" "int c" "size_t len"
+.Sh DESCRIPTION
+These functions operate on variable length strings of bytes.
+They do not check for terminating null bytes as the routines
+listed in
+.Xr string 3
+do.
+.Pp
+See the specific manual pages for more information.
+.Sh SEE ALSO
+.Xr bcmp 3 ,
+.Xr bcopy 3 ,
+.Xr bzero 3 ,
+.Xr memccpy 3 ,
+.Xr memchr 3 ,
+.Xr memcmp 3 ,
+.Xr memcpy 3 ,
+.Xr memmove 3 ,
+.Xr memset 3
+.Sh STANDARDS
+The functions
+.Fn memchr ,
+.Fn memcmp ,
+.Fn memcpy ,
+.Fn memmove ,
+and
+.Fn memset
+conform to
+.St -isoC .
+.Sh HISTORY
+The functions
+.Fn bzero
+and
+.Fn memccpy
+appeared in
+.Bx 4.3 ;
+the functions
+.Fn bcmp ,
+.Fn bcopy ,
+appeared in
+.Bx 4.2 .
diff --git a/lib/libc/string/bzero.3 b/lib/libc/string/bzero.3
new file mode 100644
index 0000000..bc61d82
--- /dev/null
+++ b/lib/libc/string/bzero.3
@@ -0,0 +1,74 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)bzero.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt BZERO 3
+.Os
+.Sh NAME
+.Nm bzero
+.Nd write zeroes to a byte string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In strings.h
+.Ft void
+.Fn bzero "void *b" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn bzero
+function
+writes
+.Fa len
+zero bytes to the string
+.Fa b .
+If
+.Fa len
+is zero,
+.Fn bzero
+does nothing.
+.Sh SEE ALSO
+.Xr memset 3 ,
+.Xr swab 3
+.Sh HISTORY
+A
+.Fn bzero
+function
+appeared in
+.Bx 4.3 .
+Its prototype existed previously in
+.In string.h
+before it was moved to
+.In strings.h
+for
+.St -p1003.1-2001
+compliance.
diff --git a/lib/libc/string/bzero.c b/lib/libc/string/bzero.c
new file mode 100644
index 0000000..201bd64
--- /dev/null
+++ b/lib/libc/string/bzero.c
@@ -0,0 +1,5 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define BZERO
+#include "memset.c"
diff --git a/lib/libc/string/ffs.3 b/lib/libc/string/ffs.3
new file mode 100644
index 0000000..bf6f5f5
--- /dev/null
+++ b/lib/libc/string/ffs.3
@@ -0,0 +1,111 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)ffs.3 8.2 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd May 3, 2011
+.Dt FFS 3
+.Os
+.Sh NAME
+.Nm ffs ,
+.Nm ffsl ,
+.Nm ffsll ,
+.Nm fls ,
+.Nm flsl ,
+.Nm flsll
+.Nd find first or last bit set in a bit string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In strings.h
+.Ft int
+.Fn ffs "int value"
+.Ft int
+.Fn ffsl "long value"
+.Ft int
+.Fn ffsll "long long value"
+.Ft int
+.Fn fls "int value"
+.Ft int
+.Fn flsl "long value"
+.Ft int
+.Fn flsll "long long value"
+.Sh DESCRIPTION
+The
+.Fn ffs ,
+.Fn ffsl
+and
+.Fn ffsll
+functions find the first bit set
+(beginning with the least significant bit)
+in
+.Fa value
+and return the index of that bit.
+.Pp
+The
+.Fn fls ,
+.Fn flsl
+and
+.Fn flsll
+functions find the last bit set in
+.Fa value
+and return the index of that bit.
+.Pp
+Bits are numbered starting at 1 (the least significant bit).
+A return value of zero from any of these functions means that the
+argument was zero.
+.Sh SEE ALSO
+.Xr bitstring 3
+.Sh HISTORY
+The
+.Fn ffs
+function appeared in
+.Bx 4.3 .
+Its prototype existed previously in
+.In string.h
+before it was moved to
+.In strings.h
+for
+.St -p1003.1-2001
+compliance.
+.Pp
+The
+.Fn ffsl ,
+.Fn fls
+and
+.Fn flsl
+functions appeared in
+.Fx 5.3 .
+The
+.Fn ffsll
+and
+.Fn flsll
+functions appeared in
+.Fx 7.1 .
diff --git a/lib/libc/string/ffs.c b/lib/libc/string/ffs.c
new file mode 100644
index 0000000..9c3e0b3
--- /dev/null
+++ b/lib/libc/string/ffs.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ffs.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <strings.h>
+
+/*
+ * Find First Set bit
+ */
+int
+ffs(int mask)
+{
+ int bit;
+
+ if (mask == 0)
+ return(0);
+ for (bit = 1; !(mask & 1); bit++)
+ mask = (unsigned int)mask >> 1;
+ return (bit);
+}
diff --git a/lib/libc/string/ffsl.c b/lib/libc/string/ffsl.c
new file mode 100644
index 0000000..6a25afd
--- /dev/null
+++ b/lib/libc/string/ffsl.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <strings.h>
+
+/*
+ * Find First Set bit
+ */
+int
+ffsl(long mask)
+{
+ int bit;
+
+ if (mask == 0)
+ return (0);
+ for (bit = 1; !(mask & 1); bit++)
+ mask = (unsigned long)mask >> 1;
+ return (bit);
+}
diff --git a/lib/libc/string/ffsll.c b/lib/libc/string/ffsll.c
new file mode 100644
index 0000000..59e03bc
--- /dev/null
+++ b/lib/libc/string/ffsll.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <strings.h>
+
+/*
+ * Find First Set bit
+ */
+int
+ffsll(long long mask)
+{
+ int bit;
+
+ if (mask == 0)
+ return (0);
+ for (bit = 1; !(mask & 1); bit++)
+ mask = (unsigned long long)mask >> 1;
+ return (bit);
+}
diff --git a/lib/libc/string/fls.c b/lib/libc/string/fls.c
new file mode 100644
index 0000000..2a3a3f7
--- /dev/null
+++ b/lib/libc/string/fls.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <strings.h>
+
+/*
+ * Find Last Set bit
+ */
+int
+fls(int mask)
+{
+ int bit;
+
+ if (mask == 0)
+ return (0);
+ for (bit = 1; mask != 1; bit++)
+ mask = (unsigned int)mask >> 1;
+ return (bit);
+}
diff --git a/lib/libc/string/flsl.c b/lib/libc/string/flsl.c
new file mode 100644
index 0000000..8f60e33
--- /dev/null
+++ b/lib/libc/string/flsl.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <strings.h>
+
+/*
+ * Find Last Set bit
+ */
+int
+flsl(long mask)
+{
+ int bit;
+
+ if (mask == 0)
+ return (0);
+ for (bit = 1; mask != 1; bit++)
+ mask = (unsigned long)mask >> 1;
+ return (bit);
+}
diff --git a/lib/libc/string/flsll.c b/lib/libc/string/flsll.c
new file mode 100644
index 0000000..ab55627
--- /dev/null
+++ b/lib/libc/string/flsll.c
@@ -0,0 +1,48 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <strings.h>
+
+/*
+ * Find Last Set bit
+ */
+int
+flsll(long long mask)
+{
+ int bit;
+
+ if (mask == 0)
+ return (0);
+ for (bit = 1; mask != 1; bit++)
+ mask = (unsigned long long)mask >> 1;
+ return (bit);
+}
diff --git a/lib/libc/string/index.3 b/lib/libc/string/index.3
new file mode 100644
index 0000000..25f6f65
--- /dev/null
+++ b/lib/libc/string/index.3
@@ -0,0 +1,115 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)index.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd March 20, 2011
+.Dt INDEX 3
+.Os
+.Sh NAME
+.Nm index , rindex
+.Nd locate character in string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In strings.h
+.Ft "char *"
+.Fn index "const char *s" "int c"
+.Ft "char *"
+.Fn rindex "const char *s" "int c"
+.Sh DESCRIPTION
+.Bf -symbolic
+The
+.Fn index
+and
+.Fn rindex
+functions have been deprecated in favor of
+.Xr strchr 3
+and
+.Xr strrchr 3 .
+.Ef
+.Pp
+The
+.Fn index
+function
+locates the first occurrence of
+.Fa c
+(converted to a
+.Vt char )
+in the string pointed to by
+.Fa s .
+The terminating null character is considered part of the string;
+therefore if
+.Fa c
+is
+.Ql \e0 ,
+the functions locate the terminating
+.Ql \e0 .
+.Pp
+The
+.Fn rindex
+function is identical to
+.Fn index ,
+except it locates the last occurrence of
+.Fa c .
+.Sh RETURN VALUES
+The functions
+.Fn index
+and
+.Fn rindex
+return a pointer to the located character, or
+.Dv NULL
+if the character does not appear in the string.
+.Sh SEE ALSO
+.Xr memchr 3 ,
+.Xr strchr 3 ,
+.Xr strcspn 3 ,
+.Xr strpbrk 3 ,
+.Xr strrchr 3 ,
+.Xr strsep 3 ,
+.Xr strspn 3 ,
+.Xr strstr 3 ,
+.Xr strtok 3
+.Sh HISTORY
+The
+.Fn index
+and
+.Fn rindex
+functions appeared in
+.At v6 .
+Their prototypes existed previously in
+.In string.h
+before they were moved to
+.In strings.h
+for
+.St -p1003.1-2001
+compliance.
+The functions are not specified by
+.St -p1003.1-2008 .
diff --git a/lib/libc/string/memccpy.3 b/lib/libc/string/memccpy.3
new file mode 100644
index 0000000..40a25be
--- /dev/null
+++ b/lib/libc/string/memccpy.3
@@ -0,0 +1,74 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)memccpy.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd June 9, 1993
+.Dt MEMCCPY 3
+.Os
+.Sh NAME
+.Nm memccpy
+.Nd copy string until character found
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft void *
+.Fn memccpy "void *dst" "const void *src" "int c" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn memccpy
+function
+copies bytes from string
+.Fa src
+to string
+.Fa dst .
+If the character
+.Fa c
+(as converted to an
+.Vt "unsigned char" )
+occurs in the string
+.Fa src ,
+the copy stops and a pointer to the byte after the copy of
+.Fa c
+in the string
+.Fa dst
+is returned.
+Otherwise,
+.Fa len
+bytes are copied, and a NULL pointer is returned.
+.Sh SEE ALSO
+.Xr bcopy 3 ,
+.Xr memcpy 3 ,
+.Xr memmove 3 ,
+.Xr strcpy 3
+.Sh HISTORY
+The
+.Fn memccpy
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/string/memccpy.c b/lib/libc/string/memccpy.c
new file mode 100644
index 0000000..539d33e
--- /dev/null
+++ b/lib/libc/string/memccpy.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)memccpy.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+void *
+memccpy(void *t, const void *f, int c, size_t n)
+{
+
+ if (n) {
+ unsigned char *tp = t;
+ const unsigned char *fp = f;
+ unsigned char uc = c;
+ do {
+ if ((*tp++ = *fp++) == uc)
+ return (tp);
+ } while (--n != 0);
+ }
+ return (0);
+}
diff --git a/lib/libc/string/memchr.3 b/lib/libc/string/memchr.3
new file mode 100644
index 0000000..9f31fd1
--- /dev/null
+++ b/lib/libc/string/memchr.3
@@ -0,0 +1,106 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)memchr.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd April 9, 2008
+.Dt MEMCHR 3
+.Os
+.Sh NAME
+.Nm memchr
+.Nd locate byte in byte string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft void *
+.Fn memchr "const void *b" "int c" "size_t len"
+.Ft void *
+.Fn memrchr "const void *b" "int c" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn memchr
+function
+locates the first occurrence of
+.Fa c
+(converted to an
+.Vt "unsigned char" )
+in string
+.Fa b .
+.Pp
+The
+.Fn memrchr
+function behaves like
+.Fn memchr ,
+except that it locates the last occurrence of
+.Fa c
+in string
+.Fa b .
+.Sh RETURN VALUES
+The
+.Fn memchr
+and
+.Fn memrchr
+functions
+return a pointer to the byte located,
+or NULL if no such byte exists within
+.Fa len
+bytes.
+.Sh SEE ALSO
+.Xr memmem 3 ,
+.Xr strchr 3 ,
+.Xr strcspn 3 ,
+.Xr strpbrk 3 ,
+.Xr strrchr 3 ,
+.Xr strsep 3 ,
+.Xr strspn 3 ,
+.Xr strstr 3 ,
+.Xr strtok 3 ,
+.Xr wmemchr 3
+.Sh STANDARDS
+The
+.Fn memchr
+function
+conforms to
+.St -isoC .
+.Pp
+The
+.Fn memrchr
+function is a GNU extension and conforms to no standard.
+.Sh HISTORY
+The
+.Fn memrchr
+function first appeared in GNU libc 2.1.91, this implementation
+first appeared in
+.Fx 6.4 ,
+coming from
+.Ox 4.3 .
diff --git a/lib/libc/string/memchr.c b/lib/libc/string/memchr.c
new file mode 100644
index 0000000..d98d853
--- /dev/null
+++ b/lib/libc/string/memchr.c
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)memchr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+void *
+memchr(const void *s, int c, size_t n)
+{
+ if (n != 0) {
+ const unsigned char *p = s;
+
+ do {
+ if (*p++ == (unsigned char)c)
+ return ((void *)(p - 1));
+ } while (--n != 0);
+ }
+ return (NULL);
+}
diff --git a/lib/libc/string/memcmp.3 b/lib/libc/string/memcmp.3
new file mode 100644
index 0000000..88ed9a2
--- /dev/null
+++ b/lib/libc/string/memcmp.3
@@ -0,0 +1,84 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)memcmp.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt MEMCMP 3
+.Os
+.Sh NAME
+.Nm memcmp
+.Nd compare byte string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft int
+.Fn memcmp "const void *b1" "const void *b2" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn memcmp
+function
+compares byte string
+.Fa b1
+against byte string
+.Fa b2 .
+Both strings are assumed to be
+.Fa len
+bytes long.
+.Sh RETURN VALUES
+The
+.Fn memcmp
+function
+returns zero if the two strings are identical,
+otherwise returns the difference between the first two differing bytes
+(treated as
+.Vt "unsigned char"
+values, so that
+.Sq Li \e200
+is greater than
+.Sq Li \&\e0 ,
+for example).
+Zero-length strings are always identical.
+.Sh SEE ALSO
+.Xr bcmp 3 ,
+.Xr strcasecmp 3 ,
+.Xr strcmp 3 ,
+.Xr strcoll 3 ,
+.Xr strxfrm 3 ,
+.Xr wmemcmp 3
+.Sh STANDARDS
+The
+.Fn memcmp
+function
+conforms to
+.St -isoC .
diff --git a/lib/libc/string/memcmp.c b/lib/libc/string/memcmp.c
new file mode 100644
index 0000000..4a1b66e
--- /dev/null
+++ b/lib/libc/string/memcmp.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)memcmp.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+/*
+ * Compare memory regions.
+ */
+int
+memcmp(const void *s1, const void *s2, size_t n)
+{
+ if (n != 0) {
+ const unsigned char *p1 = s1, *p2 = s2;
+
+ do {
+ if (*p1++ != *p2++)
+ return (*--p1 - *--p2);
+ } while (--n != 0);
+ }
+ return (0);
+}
diff --git a/lib/libc/string/memcpy.3 b/lib/libc/string/memcpy.3
new file mode 100644
index 0000000..3f2e2dd
--- /dev/null
+++ b/lib/libc/string/memcpy.3
@@ -0,0 +1,88 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)memcpy.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt MEMCPY 3
+.Os
+.Sh NAME
+.Nm memcpy
+.Nd copy byte string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft void *
+.Fn memcpy "void *dst" "const void *src" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn memcpy
+function
+copies
+.Fa len
+bytes from string
+.Fa src
+to string
+.Fa dst .
+.Sh RETURN VALUES
+The
+.Fn memcpy
+function
+returns the original value of
+.Fa dst .
+.Sh SEE ALSO
+.Xr bcopy 3 ,
+.Xr memccpy 3 ,
+.Xr memmove 3 ,
+.Xr strcpy 3 ,
+.Xr wmemcpy 3
+.Sh STANDARDS
+The
+.Fn memcpy
+function
+conforms to
+.St -isoC .
+.Sh BUGS
+In this implementation
+.Fn memcpy
+is implemented using
+.Xr bcopy 3 ,
+and therefore the strings may overlap.
+On other systems, copying overlapping strings may produce surprises.
+Programs intended to be portable should use
+.Xr memmove 3
+when
+.Fa src
+and
+.Fa dst
+may overlap.
diff --git a/lib/libc/string/memcpy.c b/lib/libc/string/memcpy.c
new file mode 100644
index 0000000..ed03856
--- /dev/null
+++ b/lib/libc/string/memcpy.c
@@ -0,0 +1,5 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define MEMCOPY
+#include "bcopy.c"
diff --git a/lib/libc/string/memmem.3 b/lib/libc/string/memmem.3
new file mode 100644
index 0000000..73c267c
--- /dev/null
+++ b/lib/libc/string/memmem.3
@@ -0,0 +1,86 @@
+.\" Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com>
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. The name of the author may not be used to endorse or promote
+.\" products derived from this software without specific prior written
+.\" permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 24, 2005
+.Dt MEMMEM 3
+.Os
+.Sh NAME
+.Nm memmem
+.Nd "locate a byte substring in a byte string"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft "void *"
+.Fo memmem
+.Fa "const void *big" "size_t big_len"
+.Fa "const void *little" "size_t little_len"
+.Fc
+.Sh DESCRIPTION
+The
+.Fn memmem
+function
+locates the first occurrence of the byte string
+.Fa little
+in the byte string
+.Fa big .
+.Sh RETURN VALUES
+If
+.Fa big_len
+is smaller than
+.Fa little_len ,
+if
+.Fa little_len
+is 0, if
+.Fa big_len
+is 0 or if
+.Fa little
+occurs nowhere in
+.Fa big ,
+.Dv NULL
+is returned;
+otherwise a pointer to the first character of the first occurrence of
+.Fa little
+is returned.
+.Sh SEE ALSO
+.Xr memchr 3 ,
+.Xr strchr 3 ,
+.Xr strstr 3
+.Sh CONFORMING TO
+.Fn memmem
+is a GNU extension.
+.Sh HISTORY
+The
+.Fn memmem
+function first appeared in
+.Fx 6.0 .
+.Sh AUTHORS
+.An Pascal Gloor Aq pascal.gloor@spale.com
+.Sh BUGS
+This function was broken in Linux libc up to and including version 5.0.9
+and in GNU libc prior to version 2.1.
diff --git a/lib/libc/string/memmem.c b/lib/libc/string/memmem.c
new file mode 100644
index 0000000..72e6517
--- /dev/null
+++ b/lib/libc/string/memmem.c
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2005 Pascal Gloor <pascal.gloor@spale.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+/*
+ * Find the first occurrence of the byte string s in byte string l.
+ */
+
+void *
+memmem(const void *l, size_t l_len, const void *s, size_t s_len)
+{
+ register char *cur, *last;
+ const char *cl = (const char *)l;
+ const char *cs = (const char *)s;
+
+ /* we need something to compare */
+ if (l_len == 0 || s_len == 0)
+ return NULL;
+
+ /* "s" must be smaller or equal to "l" */
+ if (l_len < s_len)
+ return NULL;
+
+ /* special case where s_len == 1 */
+ if (s_len == 1)
+ return memchr(l, (int)*cs, l_len);
+
+ /* the last position where its possible to find "s" in "l" */
+ last = (char *)cl + l_len - s_len;
+
+ for (cur = (char *)cl; cur <= last; cur++)
+ if (cur[0] == cs[0] && memcmp(cur, cs, s_len) == 0)
+ return cur;
+
+ return NULL;
+}
diff --git a/lib/libc/string/memmove.3 b/lib/libc/string/memmove.3
new file mode 100644
index 0000000..8a1d52b
--- /dev/null
+++ b/lib/libc/string/memmove.3
@@ -0,0 +1,75 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)memmove.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt MEMMOVE 3
+.Os
+.Sh NAME
+.Nm memmove
+.Nd copy byte string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft void *
+.Fn memmove "void *dst" "const void *src" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn memmove
+function
+copies
+.Fa len
+bytes from string
+.Fa src
+to string
+.Fa dst .
+The two strings may overlap;
+the copy is always done in a non-destructive manner.
+.Sh RETURN VALUES
+The
+.Fn memmove
+function returns the original value of
+.Fa dst .
+.Sh SEE ALSO
+.Xr bcopy 3 ,
+.Xr memccpy 3 ,
+.Xr memcpy 3 ,
+.Xr strcpy 3 ,
+.Xr wmemmove 3
+.Sh STANDARDS
+The
+.Fn memmove
+function
+conforms to
+.St -isoC .
diff --git a/lib/libc/string/memmove.c b/lib/libc/string/memmove.c
new file mode 100644
index 0000000..05cf75a
--- /dev/null
+++ b/lib/libc/string/memmove.c
@@ -0,0 +1,5 @@
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#define MEMMOVE
+#include "bcopy.c"
diff --git a/lib/libc/string/memrchr.c b/lib/libc/string/memrchr.c
new file mode 100644
index 0000000..f477bc3
--- /dev/null
+++ b/lib/libc/string/memrchr.c
@@ -0,0 +1,40 @@
+/* $OpenBSD: memrchr.c,v 1.2 2007/11/27 16:22:12 martynas Exp $ */
+
+/*
+ * Copyright (c) 2007 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * $FreeBSD$
+ */
+
+#include <string.h>
+
+/*
+ * Reverse memchr()
+ * Find the last occurrence of 'c' in the buffer 's' of size 'n'.
+ */
+void *
+memrchr(const void *s, int c, size_t n)
+{
+ const unsigned char *cp;
+
+ if (n != 0) {
+ cp = (unsigned char *)s + n;
+ do {
+ if (*(--cp) == (unsigned char)c)
+ return((void *)cp);
+ } while (--n != 0);
+ }
+ return(NULL);
+}
diff --git a/lib/libc/string/memset.3 b/lib/libc/string/memset.3
new file mode 100644
index 0000000..07bd7aa
--- /dev/null
+++ b/lib/libc/string/memset.3
@@ -0,0 +1,72 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)memset.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt MEMSET 3
+.Os
+.Sh NAME
+.Nm memset
+.Nd write a byte to byte string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft void *
+.Fn memset "void *b" "int c" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn memset
+function
+writes
+.Fa len
+bytes of value
+.Fa c
+(converted to an
+.Vt "unsigned char" )
+to the string
+.Fa b .
+.Sh RETURN VALUES
+The
+.Fn memset
+function returns its first argument.
+.Sh SEE ALSO
+.Xr bzero 3 ,
+.Xr swab 3 ,
+.Xr wmemset 3
+.Sh STANDARDS
+The
+.Fn memset
+function
+conforms to
+.St -isoC .
diff --git a/lib/libc/string/memset.c b/lib/libc/string/memset.c
new file mode 100644
index 0000000..89f7e45
--- /dev/null
+++ b/lib/libc/string/memset.c
@@ -0,0 +1,128 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Mike Hibler and Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)memset.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+
+#include <limits.h>
+
+#define wsize sizeof(u_int)
+#define wmask (wsize - 1)
+
+#ifdef BZERO
+#include <strings.h>
+
+#define RETURN return
+#define VAL 0
+#define WIDEVAL 0
+
+void
+bzero(void *dst0, size_t length)
+#else
+#include <string.h>
+
+#define RETURN return (dst0)
+#define VAL c0
+#define WIDEVAL c
+
+void *
+memset(void *dst0, int c0, size_t length)
+#endif
+{
+ size_t t;
+#ifndef BZERO
+ u_int c;
+#endif
+ u_char *dst;
+
+ dst = dst0;
+ /*
+ * If not enough words, just fill bytes. A length >= 2 words
+ * guarantees that at least one of them is `complete' after
+ * any necessary alignment. For instance:
+ *
+ * |-----------|-----------|-----------|
+ * |00|01|02|03|04|05|06|07|08|09|0A|00|
+ * ^---------------------^
+ * dst dst+length-1
+ *
+ * but we use a minimum of 3 here since the overhead of the code
+ * to do word writes is substantial.
+ */
+ if (length < 3 * wsize) {
+ while (length != 0) {
+ *dst++ = VAL;
+ --length;
+ }
+ RETURN;
+ }
+
+#ifndef BZERO
+ if ((c = (u_char)c0) != 0) { /* Fill the word. */
+ c = (c << 8) | c; /* u_int is 16 bits. */
+#if UINT_MAX > 0xffff
+ c = (c << 16) | c; /* u_int is 32 bits. */
+#endif
+#if UINT_MAX > 0xffffffff
+ c = (c << 32) | c; /* u_int is 64 bits. */
+#endif
+ }
+#endif
+ /* Align destination by filling in bytes. */
+ if ((t = (long)dst & wmask) != 0) {
+ t = wsize - t;
+ length -= t;
+ do {
+ *dst++ = VAL;
+ } while (--t != 0);
+ }
+
+ /* Fill words. Length was >= 2*words so we know t >= 1 here. */
+ t = length / wsize;
+ do {
+ *(u_int *)dst = WIDEVAL;
+ dst += wsize;
+ } while (--t != 0);
+
+ /* Mop up trailing bytes, if any. */
+ t = length & wmask;
+ if (t != 0)
+ do {
+ *dst++ = VAL;
+ } while (--t != 0);
+ RETURN;
+}
diff --git a/lib/libc/string/stpcpy.c b/lib/libc/string/stpcpy.c
new file mode 100644
index 0000000..beb1159
--- /dev/null
+++ b/lib/libc/string/stpcpy.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1999
+ * David E. O'Brien
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcpy.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+char *
+stpcpy(char * __restrict to, const char * __restrict from)
+{
+
+ for (; (*to = *from); ++from, ++to);
+ return(to);
+}
diff --git a/lib/libc/string/stpncpy.c b/lib/libc/string/stpncpy.c
new file mode 100644
index 0000000..df70dc6
--- /dev/null
+++ b/lib/libc/string/stpncpy.c
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+char *
+stpncpy(char * __restrict dst, const char * __restrict src, size_t n)
+{
+
+ for (; n--; dst++, src++) {
+ if (!(*dst = *src)) {
+ char *ret = dst;
+ while (n--)
+ *++dst = '\0';
+ return (ret);
+ }
+ }
+ return (dst);
+}
diff --git a/lib/libc/string/strcasecmp.3 b/lib/libc/string/strcasecmp.3
new file mode 100644
index 0000000..2b2ef3e
--- /dev/null
+++ b/lib/libc/string/strcasecmp.3
@@ -0,0 +1,101 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strcasecmp.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd June 9, 1993
+.Dt STRCASECMP 3
+.Os
+.Sh NAME
+.Nm strcasecmp ,
+.Nm strncasecmp
+.Nd compare strings, ignoring case
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In strings.h
+.Ft int
+.Fn strcasecmp "const char *s1" "const char *s2"
+.Ft int
+.Fn strncasecmp "const char *s1" "const char *s2" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn strcasecmp
+and
+.Fn strncasecmp
+functions
+compare the null-terminated strings
+.Fa s1
+and
+.Fa s2 .
+.Pp
+The
+.Fn strncasecmp
+compares at most
+.Fa len
+characters.
+.Sh RETURN VALUES
+The
+.Fn strcasecmp
+and
+.Fn strncasecmp
+return an integer greater than, equal to, or less than 0,
+according as
+.Fa s1
+is lexicographically greater than, equal to, or less than
+.Fa s2
+after translation of each corresponding character to lower-case.
+The strings themselves are not modified.
+The comparison is done using unsigned characters, so that
+.Sq Li \e200
+is greater than
+.Ql \e0 .
+.Sh SEE ALSO
+.Xr bcmp 3 ,
+.Xr memcmp 3 ,
+.Xr strcmp 3 ,
+.Xr strcoll 3 ,
+.Xr strxfrm 3 ,
+.Xr tolower 3 ,
+.Xr wcscasecmp 3
+.Sh HISTORY
+The
+.Fn strcasecmp
+and
+.Fn strncasecmp
+functions first appeared in
+.Bx 4.4 .
+Their prototypes existed previously in
+.In string.h
+before they were moved to
+.In strings.h
+for
+.St -p1003.1-2001
+compliance.
diff --git a/lib/libc/string/strcasecmp.c b/lib/libc/string/strcasecmp.c
new file mode 100644
index 0000000..65e042e
--- /dev/null
+++ b/lib/libc/string/strcasecmp.c
@@ -0,0 +1,87 @@
+/*
+ * Copyright (c) 1987, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcasecmp.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <strings.h>
+#include <ctype.h>
+#include "xlocale_private.h"
+
+int
+strcasecmp_l(const char *s1, const char *s2, locale_t locale)
+{
+ const u_char
+ *us1 = (const u_char *)s1,
+ *us2 = (const u_char *)s2;
+ FIX_LOCALE(locale);
+
+ while (tolower_l(*us1, locale) == tolower_l(*us2++, locale))
+ if (*us1++ == '\0')
+ return (0);
+ return (tolower_l(*us1, locale) - tolower_l(*--us2, locale));
+}
+int
+strcasecmp(const char *s1, const char *s2)
+{
+ return strcasecmp_l(s1, s2, __get_locale());
+}
+
+int
+strncasecmp_l(const char *s1, const char *s2, size_t n, locale_t locale)
+{
+ FIX_LOCALE(locale);
+ if (n != 0) {
+ const u_char
+ *us1 = (const u_char *)s1,
+ *us2 = (const u_char *)s2;
+
+ do {
+ if (tolower_l(*us1, locale) != tolower_l(*us2++, locale))
+ return (tolower_l(*us1, locale) - tolower_l(*--us2, locale));
+ if (*us1++ == '\0')
+ break;
+ } while (--n != 0);
+ }
+ return (0);
+}
+
+int
+strncasecmp(const char *s1, const char *s2, size_t n)
+{
+ return strncasecmp_l(s1, s2, n, __get_locale());
+}
diff --git a/lib/libc/string/strcasestr.c b/lib/libc/string/strcasestr.c
new file mode 100644
index 0000000..5f39648
--- /dev/null
+++ b/lib/libc/string/strcasestr.c
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <ctype.h>
+#include <string.h>
+#include "xlocale_private.h"
+
+/*
+ * Find the first occurrence of find in s, ignore case.
+ */
+char *
+strcasestr_l(const char *s, const char *find, locale_t locale)
+{
+ char c, sc;
+ size_t len;
+ FIX_LOCALE(locale);
+
+ if ((c = *find++) != 0) {
+ c = tolower_l((unsigned char)c, locale);
+ len = strlen(find);
+ do {
+ do {
+ if ((sc = *s++) == 0)
+ return (NULL);
+ } while ((char)tolower_l((unsigned char)sc, locale) != c);
+ } while (strncasecmp_l(s, find, len, locale) != 0);
+ s--;
+ }
+ return ((char *)s);
+}
+char *
+strcasestr(const char *s, const char *find)
+{
+ return strcasestr_l(s, find, __get_locale());
+}
diff --git a/lib/libc/string/strcat.3 b/lib/libc/string/strcat.3
new file mode 100644
index 0000000..dfa55a4
--- /dev/null
+++ b/lib/libc/string/strcat.3
@@ -0,0 +1,157 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strcat.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd December 1, 2009
+.Dt STRCAT 3
+.Os
+.Sh NAME
+.Nm strcat ,
+.Nm strncat
+.Nd concatenate strings
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft char *
+.Fn strcat "char * restrict s" "const char * restrict append"
+.Ft char *
+.Fn strncat "char * restrict s" "const char * restrict append" "size_t count"
+.Sh DESCRIPTION
+The
+.Fn strcat
+and
+.Fn strncat
+functions
+append a copy of the null-terminated string
+.Fa append
+to the end of the null-terminated string
+.Fa s ,
+then add a terminating
+.Ql \e0 .
+The string
+.Fa s
+must have sufficient space to hold the result.
+.Pp
+The
+.Fn strncat
+function
+appends not more than
+.Fa count
+characters from
+.Fa append ,
+and then adds a terminating
+.Ql \e0 .
+.Sh RETURN VALUES
+The
+.Fn strcat
+and
+.Fn strncat
+functions
+return the pointer
+.Fa s .
+.Sh SEE ALSO
+.Xr bcopy 3 ,
+.Xr memccpy 3 ,
+.Xr memcpy 3 ,
+.Xr memmove 3 ,
+.Xr strcpy 3 ,
+.Xr strlcat 3 ,
+.Xr strlcpy 3 ,
+.Xr wcscat 3
+.Sh STANDARDS
+The
+.Fn strcat
+and
+.Fn strncat
+functions
+conform to
+.St -isoC .
+.Sh SECURITY CONSIDERATIONS
+The
+.Fn strcat
+function is easily misused in a manner
+which enables malicious users to arbitrarily change
+a running program's functionality through a buffer overflow attack.
+(See
+the FSA.)
+.Pp
+Avoid using
+.Fn strcat .
+Instead, use
+.Fn strncat
+or
+.Fn strlcat
+and ensure that no more characters are copied to the destination buffer
+than it can hold.
+.Pp
+Note that
+.Fn strncat
+can also be problematic.
+It may be a security concern for a string to be truncated at all.
+Since the truncated string will not be as long as the original,
+it may refer to a completely different resource
+and usage of the truncated resource
+could result in very incorrect behavior.
+Example:
+.Bd -literal
+void
+foo(const char *arbitrary_string)
+{
+ char onstack[8];
+
+#if defined(BAD)
+ /*
+ * This first strcat is bad behavior. Do not use strcat!
+ */
+ (void)strcat(onstack, arbitrary_string); /* BAD! */
+#elif defined(BETTER)
+ /*
+ * The following two lines demonstrate better use of
+ * strncat().
+ */
+ (void)strncat(onstack, arbitrary_string,
+ sizeof(onstack) - strlen(onstack) - 1);
+#elif defined(BEST)
+ /*
+ * These lines are even more robust due to testing for
+ * truncation.
+ */
+ if (strlen(arbitrary_string) + 1 >
+ sizeof(onstack) - strlen(onstack))
+ err(1, "onstack would be truncated");
+ (void)strncat(onstack, arbitrary_string,
+ sizeof(onstack) - strlen(onstack) - 1);
+#endif
+}
+.Ed
diff --git a/lib/libc/string/strcat.c b/lib/libc/string/strcat.c
new file mode 100644
index 0000000..1578276
--- /dev/null
+++ b/lib/libc/string/strcat.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcat.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+char *
+strcat(char * __restrict s, const char * __restrict append)
+{
+ char *save = s;
+
+ for (; *s; ++s);
+ while ((*s++ = *append++));
+ return(save);
+}
diff --git a/lib/libc/string/strchr.3 b/lib/libc/string/strchr.3
new file mode 100644
index 0000000..984eb06
--- /dev/null
+++ b/lib/libc/string/strchr.3
@@ -0,0 +1,96 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strchr.3 8.2 (Berkeley) 4/19/94
+.\" $FreeBSD$
+.\"
+.Dd April 19, 1994
+.Dt STRCHR 3
+.Os
+.Sh NAME
+.Nm strchr , strrchr
+.Nd locate character in string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft "char *"
+.Fn strchr "const char *s" "int c"
+.Ft "char *"
+.Fn strrchr "const char *s" "int c"
+.Sh DESCRIPTION
+The
+.Fn strchr
+function locates the first occurrence of
+.Fa c
+(converted to a
+.Vt char )
+in the string pointed to by
+.Fa s .
+The terminating null character is considered part of the string;
+therefore if
+.Fa c
+is
+.Ql \e0 ,
+the functions locate the terminating
+.Ql \e0 .
+.Pp
+The
+.Fn strrchr
+function is identical to
+.Fn strchr
+except it locates the last occurrence of
+.Fa c .
+.Sh RETURN VALUES
+The functions
+.Fn strchr
+and
+.Fn strrchr
+return a pointer to the located character, or
+.Dv NULL
+if the character does not appear in the string.
+.Sh SEE ALSO
+.Xr memchr 3 ,
+.Xr memmem 3 ,
+.Xr strcspn 3 ,
+.Xr strpbrk 3 ,
+.Xr strsep 3 ,
+.Xr strspn 3 ,
+.Xr strstr 3 ,
+.Xr strtok 3 ,
+.Xr wcschr 3
+.Sh STANDARDS
+The functions
+.Fn strchr
+and
+.Fn strrchr
+conform to
+.St -isoC .
diff --git a/lib/libc/string/strchr.c b/lib/libc/string/strchr.c
new file mode 100644
index 0000000..1245f13
--- /dev/null
+++ b/lib/libc/string/strchr.c
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)index.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stddef.h>
+#include <string.h>
+
+char *
+strchr(const char *p, int ch)
+{
+ char c;
+
+ c = ch;
+ for (;; ++p) {
+ if (*p == c)
+ return ((char *)p);
+ if (*p == '\0')
+ return (NULL);
+ }
+ /* NOTREACHED */
+}
+
+__weak_reference(strchr, index);
diff --git a/lib/libc/string/strcmp.3 b/lib/libc/string/strcmp.3
new file mode 100644
index 0000000..74d1a5c
--- /dev/null
+++ b/lib/libc/string/strcmp.3
@@ -0,0 +1,101 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strcmp.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd October 11, 2001
+.Dt STRCMP 3
+.Os
+.Sh NAME
+.Nm strcmp ,
+.Nm strncmp
+.Nd compare strings
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft int
+.Fn strcmp "const char *s1" "const char *s2"
+.Ft int
+.Fn strncmp "const char *s1" "const char *s2" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn strcmp
+and
+.Fn strncmp
+functions
+lexicographically compare the null-terminated strings
+.Fa s1
+and
+.Fa s2 .
+.Pp
+The
+.Fn strncmp
+function
+compares not more than
+.Fa len
+characters.
+Because
+.Fn strncmp
+is designed for comparing strings rather than binary data,
+characters that appear after a
+.Ql \e0
+character are not compared.
+.Sh RETURN VALUES
+The
+.Fn strcmp
+and
+.Fn strncmp
+functions return an integer greater than, equal to, or less than 0, according
+as the string
+.Fa s1
+is greater than, equal to, or less than the string
+.Fa s2 .
+The comparison is done using unsigned characters, so that
+.Ql \e200
+is greater than
+.Ql \e0 .
+.Sh SEE ALSO
+.Xr bcmp 3 ,
+.Xr memcmp 3 ,
+.Xr strcasecmp 3 ,
+.Xr strcoll 3 ,
+.Xr strxfrm 3 ,
+.Xr wcscmp 3
+.Sh STANDARDS
+The
+.Fn strcmp
+and
+.Fn strncmp
+functions
+conform to
+.St -isoC .
diff --git a/lib/libc/string/strcmp.c b/lib/libc/string/strcmp.c
new file mode 100644
index 0000000..95c778d
--- /dev/null
+++ b/lib/libc/string/strcmp.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcmp.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+/*
+ * Compare strings.
+ */
+int
+strcmp(const char *s1, const char *s2)
+{
+ while (*s1 == *s2++)
+ if (*s1++ == '\0')
+ return (0);
+ return (*(const unsigned char *)s1 - *(const unsigned char *)(s2 - 1));
+}
diff --git a/lib/libc/string/strcoll.3 b/lib/libc/string/strcoll.3
new file mode 100644
index 0000000..bb8b13f
--- /dev/null
+++ b/lib/libc/string/strcoll.3
@@ -0,0 +1,75 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strcoll.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt STRCOLL 3
+.Os
+.Sh NAME
+.Nm strcoll
+.Nd compare strings according to current collation
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft int
+.Fn strcoll "const char *s1" "const char *s2"
+.Sh DESCRIPTION
+The
+.Fn strcoll
+function
+lexicographically compares the null-terminated strings
+.Fa s1
+and
+.Fa s2
+according to the current locale collation
+and returns an integer greater than, equal to, or less than 0,
+according as
+.Fa s1
+is greater than, equal to, or less than
+.Fa s2 .
+If information about the current locale collation is not available,
+the value of
+.Fn strcmp s1 s2
+is returned.
+.Sh SEE ALSO
+.Xr setlocale 3 ,
+.Xr strcmp 3 ,
+.Xr strxfrm 3 ,
+.Xr wcscoll 3
+.Sh STANDARDS
+The
+.Fn strcoll
+function
+conforms to
+.St -isoC .
diff --git a/lib/libc/string/strcoll.c b/lib/libc/string/strcoll.c
new file mode 100644
index 0000000..a918fca
--- /dev/null
+++ b/lib/libc/string/strcoll.c
@@ -0,0 +1,102 @@
+/*-
+ * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
+ * at Electronni Visti IA, Kiev, Ukraine.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <string.h>
+#include "collate.h"
+
+#include <stdio.h>
+
+int
+strcoll_l(const char *s, const char *s2, locale_t locale)
+{
+ int len, len2, prim, prim2, sec, sec2, ret, ret2;
+ const char *t, *t2;
+ char *tt, *tt2;
+ FIX_LOCALE(locale);
+ struct xlocale_collate *table =
+ (struct xlocale_collate*)locale->components[XLC_COLLATE];
+
+ if (table->__collate_load_error)
+ return strcmp(s, s2);
+
+ len = len2 = 1;
+ ret = ret2 = 0;
+ if (table->__collate_substitute_nontrivial) {
+ t = tt = __collate_substitute(table, s);
+ t2 = tt2 = __collate_substitute(table, s2);
+ } else {
+ tt = tt2 = NULL;
+ t = s;
+ t2 = s2;
+ }
+ while(*t && *t2) {
+ prim = prim2 = 0;
+ while(*t && !prim) {
+ __collate_lookup(table, t, &len, &prim, &sec);
+ t += len;
+ }
+ while(*t2 && !prim2) {
+ __collate_lookup(table, t2, &len2, &prim2, &sec2);
+ t2 += len2;
+ }
+ if(!prim || !prim2)
+ break;
+ if(prim != prim2) {
+ ret = prim - prim2;
+ goto end;
+ }
+ if(!ret2)
+ ret2 = sec - sec2;
+ }
+ if(!*t && *t2)
+ ret = -(int)((u_char)*t2);
+ else if(*t && !*t2)
+ ret = (u_char)*t;
+ else if(!*t && !*t2)
+ ret = ret2;
+ end:
+ free(tt);
+ free(tt2);
+
+ return ret;
+}
+
+int
+strcoll(const char *s, const char *s2)
+{
+ return strcoll_l(s, s2, __get_locale());
+}
+
diff --git a/lib/libc/string/strcpy.3 b/lib/libc/string/strcpy.3
new file mode 100644
index 0000000..395e2f9
--- /dev/null
+++ b/lib/libc/string/strcpy.3
@@ -0,0 +1,216 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strcpy.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd February 28, 2009
+.Dt STRCPY 3
+.Os
+.Sh NAME
+.Nm stpcpy, stpncpy, strcpy , strncpy
+.Nd copy strings
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft char *
+.Fn stpcpy "char * restrict dst" "const char * restrict src"
+.Ft char *
+.Fn stpncpy "char * restrict dst" "const char * restrict src" "size_t len"
+.Ft char *
+.Fn strcpy "char * restrict dst" "const char * restrict src"
+.Ft char *
+.Fn strncpy "char * restrict dst" "const char * restrict src" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn stpcpy
+and
+.Fn strcpy
+functions
+copy the string
+.Fa src
+to
+.Fa dst
+(including the terminating
+.Ql \e0
+character.)
+.Pp
+The
+.Fn stpncpy
+and
+.Fn strncpy
+functions copy at most
+.Fa len
+characters from
+.Fa src
+into
+.Fa dst .
+If
+.Fa src
+is less than
+.Fa len
+characters long,
+the remainder of
+.Fa dst
+is filled with
+.Ql \e0
+characters.
+Otherwise,
+.Fa dst
+is
+.Em not
+terminated.
+.Sh RETURN VALUES
+The
+.Fn strcpy
+and
+.Fn strncpy
+functions
+return
+.Fa dst .
+The
+.Fn stpcpy
+and
+.Fn stpncpy
+functions return a pointer to the terminating
+.Ql \e0
+character of
+.Fa dst .
+If
+.Fn stpncpy
+does not terminate
+.Fa dst
+with a
+.Dv NUL
+character, it instead returns a pointer to
+.Li dst[n]
+(which does not necessarily refer to a valid memory location.)
+.Sh EXAMPLES
+The following sets
+.Va chararray
+to
+.Dq Li abc\e0\e0\e0 :
+.Bd -literal -offset indent
+char chararray[6];
+
+(void)strncpy(chararray, "abc", sizeof(chararray));
+.Ed
+.Pp
+The following sets
+.Va chararray
+to
+.Dq Li abcdef :
+.Bd -literal -offset indent
+char chararray[6];
+
+(void)strncpy(chararray, "abcdefgh", sizeof(chararray));
+.Ed
+.Pp
+Note that it does
+.Em not
+.Tn NUL
+terminate
+.Va chararray
+because the length of the source string is greater than or equal
+to the length argument.
+.Pp
+The following copies as many characters from
+.Va input
+to
+.Va buf
+as will fit and
+.Tn NUL
+terminates the result.
+Because
+.Fn strncpy
+does
+.Em not
+guarantee to
+.Tn NUL
+terminate the string itself, this must be done explicitly.
+.Bd -literal -offset indent
+char buf[1024];
+
+(void)strncpy(buf, input, sizeof(buf) - 1);
+buf[sizeof(buf) - 1] = '\e0';
+.Ed
+.Pp
+This could be better achieved using
+.Xr strlcpy 3 ,
+as shown in the following example:
+.Pp
+.Dl "(void)strlcpy(buf, input, sizeof(buf));"
+.Pp
+Note that because
+.Xr strlcpy 3
+is not defined in any standards, it should
+only be used when portability is not a concern.
+.Sh SEE ALSO
+.Xr bcopy 3 ,
+.Xr memccpy 3 ,
+.Xr memcpy 3 ,
+.Xr memmove 3 ,
+.Xr strlcpy 3 ,
+.Xr wcscpy 3
+.Sh STANDARDS
+The
+.Fn strcpy
+and
+.Fn strncpy
+functions
+conform to
+.St -isoC .
+The
+.Fn stpcpy
+and
+.Fn stpncpy
+functions conform to
+.St -p1003.1-2008 .
+.Sh HISTORY
+The
+.Fn stpcpy
+function first appeared in
+.Fx 4.4 ,
+and
+.Fn stpncpy
+was added in
+.Fx 8.0 .
+.Sh SECURITY CONSIDERATIONS
+The
+.Fn strcpy
+function is easily misused in a manner which enables malicious users
+to arbitrarily change a running program's functionality through a
+buffer overflow attack.
+(See
+the FSA
+and
+.Sx EXAMPLES . )
diff --git a/lib/libc/string/strcpy.c b/lib/libc/string/strcpy.c
new file mode 100644
index 0000000..fec284e
--- /dev/null
+++ b/lib/libc/string/strcpy.c
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcpy.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+char *
+strcpy(char * __restrict to, const char * __restrict from)
+{
+ char *save = to;
+
+ for (; (*to = *from); ++from, ++to);
+ return(save);
+}
diff --git a/lib/libc/string/strcspn.3 b/lib/libc/string/strcspn.3
new file mode 100644
index 0000000..d1df198
--- /dev/null
+++ b/lib/libc/string/strcspn.3
@@ -0,0 +1,88 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strcspn.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt STRCSPN 3
+.Os
+.Sh NAME
+.Nm strcspn
+.Nd span the complement of a string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft size_t
+.Fn strcspn "const char *s" "const char *charset"
+.Sh DESCRIPTION
+The
+.Fn strcspn
+function
+spans the initial part of the null-terminated string
+.Fa s
+as long as the characters from
+.Fa s
+do not occur in string
+.Fa charset
+(it
+spans the
+.Em complement
+of
+.Fa charset ) .
+In other words, it computes the string array index in
+.Fa s
+of the first character of
+.Fa s
+which is also in
+.Fa charset ,
+else the index of the first null character.
+.Sh RETURN VALUES
+The
+.Fn strcspn
+function
+returns the number of characters spanned.
+.Sh SEE ALSO
+.Xr memchr 3 ,
+.Xr strchr 3 ,
+.Xr strpbrk 3 ,
+.Xr strrchr 3 ,
+.Xr strsep 3 ,
+.Xr strspn 3 ,
+.Xr strstr 3 ,
+.Xr strtok 3
+.Sh STANDARDS
+The
+.Fn strcspn
+function
+conforms to
+.St -isoC .
diff --git a/lib/libc/string/strcspn.c b/lib/libc/string/strcspn.c
new file mode 100644
index 0000000..3879a3b
--- /dev/null
+++ b/lib/libc/string/strcspn.c
@@ -0,0 +1,72 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <limits.h>
+#include <string.h>
+
+#define IDX(c) ((u_char)(c) / LONG_BIT)
+#define BIT(c) ((u_long)1 << ((u_char)(c) % LONG_BIT))
+
+size_t
+strcspn(const char *s, const char *charset)
+{
+ /*
+ * NB: idx and bit are temporaries whose use causes gcc 3.4.2 to
+ * generate better code. Without them, gcc gets a little confused.
+ */
+ const char *s1;
+ u_long bit;
+ u_long tbl[(UCHAR_MAX + 1) / LONG_BIT];
+ int idx;
+
+ if(*s == '\0')
+ return (0);
+
+#if LONG_BIT == 64 /* always better to unroll on 64-bit architectures */
+ tbl[0] = 1;
+ tbl[3] = tbl[2] = tbl[1] = 0;
+#else
+ for (tbl[0] = idx = 1; idx < sizeof(tbl) / sizeof(tbl[0]); idx++)
+ tbl[idx] = 0;
+#endif
+ for (; *charset != '\0'; charset++) {
+ idx = IDX(*charset);
+ bit = BIT(*charset);
+ tbl[idx] |= bit;
+ }
+
+ for(s1 = s; ; s1++) {
+ idx = IDX(*s1);
+ bit = BIT(*s1);
+ if ((tbl[idx] & bit) != 0)
+ break;
+ }
+ return (s1 - s);
+}
diff --git a/lib/libc/string/strdup.3 b/lib/libc/string/strdup.3
new file mode 100644
index 0000000..04a2816
--- /dev/null
+++ b/lib/libc/string/strdup.3
@@ -0,0 +1,84 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strdup.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd December 5, 2008
+.Dt STRDUP 3
+.Os
+.Sh NAME
+.Nm strdup ,
+.Nm strndup
+.Nd save a copy of a string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft char *
+.Fn strdup "const char *str"
+.Ft char *
+.Fn strndup "const char *str" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn strdup
+function
+allocates sufficient memory for a copy
+of the string
+.Fa str ,
+does the copy, and returns a pointer to it.
+The pointer may subsequently be used as an
+argument to the function
+.Xr free 3 .
+.Pp
+If insufficient memory is available, NULL is returned and
+.Va errno
+is set to
+.Er ENOMEM .
+.Pp
+The
+.Fn strndup
+function copies at most
+.Fa len
+characters from the string
+.Fa str
+always
+.Dv NUL
+terminating the copied string.
+.Sh SEE ALSO
+.Xr free 3 ,
+.Xr malloc 3 ,
+.Xr wcsdup 3
+.Sh HISTORY
+The
+.Fn strdup
+function first appeared in
+.Bx 4.4 .
+The
+.Fn strndup
+function was added in
+.Fx 7.2 .
diff --git a/lib/libc/string/strdup.c b/lib/libc/string/strdup.c
new file mode 100644
index 0000000..570ad83
--- /dev/null
+++ b/lib/libc/string/strdup.c
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strdup.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *
+strdup(const char *str)
+{
+ size_t len;
+ char *copy;
+
+ len = strlen(str) + 1;
+ if ((copy = malloc(len)) == NULL)
+ return (NULL);
+ memcpy(copy, str, len);
+ return (copy);
+}
diff --git a/lib/libc/string/strerror.3 b/lib/libc/string/strerror.3
new file mode 100644
index 0000000..5961a84
--- /dev/null
+++ b/lib/libc/string/strerror.3
@@ -0,0 +1,190 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strerror.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd April 5, 2011
+.Dt STRERROR 3
+.Os
+.Sh NAME
+.Nm perror ,
+.Nm strerror ,
+.Nm strerror_r ,
+.Nm sys_errlist ,
+.Nm sys_nerr
+.Nd system error messages
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In stdio.h
+.Ft void
+.Fn perror "const char *string"
+.Vt extern const char * const sys_errlist[] ;
+.Vt extern const int sys_nerr ;
+.In string.h
+.Ft "char *"
+.Fn strerror "int errnum"
+.Ft int
+.Fn strerror_r "int errnum" "char *strerrbuf" "size_t buflen"
+.Sh DESCRIPTION
+The
+.Fn strerror ,
+.Fn strerror_r
+and
+.Fn perror
+functions look up the error message string corresponding to an
+error number.
+.Pp
+The
+.Fn strerror
+function accepts an error number argument
+.Fa errnum
+and returns a pointer to the corresponding
+message string.
+.Pp
+The
+.Fn strerror_r
+function renders the same result into
+.Fa strerrbuf
+for a maximum of
+.Fa buflen
+characters and returns 0 upon success.
+.Pp
+The
+.Fn perror
+function finds the error message corresponding to the current
+value of the global variable
+.Va errno
+.Pq Xr intro 2
+and writes it, followed by a newline, to the
+standard error file descriptor.
+If the argument
+.Fa string
+is
+.Pf non- Dv NULL
+and does not point to the null character,
+this string is prepended to the message
+string and separated from it by
+a colon and space
+.Pq Dq Li ":\ " ;
+otherwise, only the error message string is printed.
+.Pp
+If the error number is not recognized, these functions return an error message
+string containing
+.Dq Li "Unknown error:\ "
+followed by the error number in decimal.
+The
+.Fn strerror
+and
+.Fn strerror_r
+functions return
+.Er EINVAL
+as a warning.
+Error numbers recognized by this implementation fall in
+the range 0 <
+.Fa errnum
+<
+.Fa sys_nerr .
+The number 0 is also recognized, although applications that take advantage of
+this are likely to use unspecified values of
+.Va errno .
+.Pp
+If insufficient storage is provided in
+.Fa strerrbuf
+(as specified in
+.Fa buflen )
+to contain the error string,
+.Fn strerror_r
+returns
+.Er ERANGE
+and
+.Fa strerrbuf
+will contain an error message that has been truncated and
+.Dv NUL
+terminated to fit the length specified by
+.Fa buflen .
+.Pp
+The message strings can be accessed directly using the external
+array
+.Va sys_errlist .
+The external value
+.Va sys_nerr
+contains a count of the messages in
+.Va sys_errlist .
+The use of these variables is deprecated;
+.Fn strerror
+or
+.Fn strerror_r
+should be used instead.
+.Sh SEE ALSO
+.Xr intro 2 ,
+.Xr err 3 ,
+.Xr psignal 3
+.Sh STANDARDS
+The
+.Fn perror
+and
+.Fn strerror
+functions conform to
+.St -isoC-99 .
+The
+.Fn strerror_r
+function conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn strerror
+and
+.Fn perror
+functions first appeared in
+.Bx 4.4 .
+The
+.Fn strerror_r
+function was implemented in
+.Fx 4.4
+by
+.An Wes Peters Aq wes@FreeBSD.org .
+.Sh BUGS
+For unknown error numbers, the
+.Fn strerror
+function will return its result in a static buffer which
+may be overwritten by subsequent calls.
+.Pp
+The return type for
+.Fn strerror
+is missing a type-qualifier; it should actually be
+.Vt const char * .
+.Pp
+Programs that use the deprecated
+.Va sys_errlist
+variable often fail to compile because they declare it
+inconsistently.
diff --git a/lib/libc/string/strerror.c b/lib/libc/string/strerror.c
new file mode 100644
index 0000000..bfca871
--- /dev/null
+++ b/lib/libc/string/strerror.c
@@ -0,0 +1,126 @@
+/*-
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#if defined(NLS)
+#include <nl_types.h>
+#endif
+
+#include <limits.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+
+#define UPREFIX "Unknown error"
+
+/*
+ * Define a buffer size big enough to describe a 64-bit signed integer
+ * converted to ASCII decimal (19 bytes), with an optional leading sign
+ * (1 byte); finally, we get the prefix, delimiter (": ") and a trailing
+ * NUL from UPREFIX.
+ */
+#define EBUFSIZE (20 + 2 + sizeof(UPREFIX))
+
+/*
+ * Doing this by hand instead of linking with stdio(3) avoids bloat for
+ * statically linked binaries.
+ */
+static void
+errstr(int num, char *uprefix, char *buf, size_t len)
+{
+ char *t;
+ unsigned int uerr;
+ char tmp[EBUFSIZE];
+
+ t = tmp + sizeof(tmp);
+ *--t = '\0';
+ uerr = (num >= 0) ? num : -num;
+ do {
+ *--t = "0123456789"[uerr % 10];
+ } while (uerr /= 10);
+ if (num < 0)
+ *--t = '-';
+ *--t = ' ';
+ *--t = ':';
+ strlcpy(buf, uprefix, len);
+ strlcat(buf, t, len);
+}
+
+int
+strerror_r(int errnum, char *strerrbuf, size_t buflen)
+{
+ int retval = 0;
+#if defined(NLS)
+ int saved_errno = errno;
+ nl_catd catd;
+ catd = catopen("libc", NL_CAT_LOCALE);
+#endif
+
+ if (errnum < 0 || errnum >= sys_nerr) {
+ errstr(errnum,
+#if defined(NLS)
+ catgets(catd, 1, 0xffff, UPREFIX),
+#else
+ UPREFIX,
+#endif
+ strerrbuf, buflen);
+ retval = EINVAL;
+ } else {
+ if (strlcpy(strerrbuf,
+#if defined(NLS)
+ catgets(catd, 1, errnum, sys_errlist[errnum]),
+#else
+ sys_errlist[errnum],
+#endif
+ buflen) >= buflen)
+ retval = ERANGE;
+ }
+
+#if defined(NLS)
+ catclose(catd);
+ errno = saved_errno;
+#endif
+
+ return (retval);
+}
+
+char *
+strerror(int num)
+{
+ static char ebuf[NL_TEXTMAX];
+
+ if (strerror_r(num, ebuf, sizeof(ebuf)) != 0)
+ errno = EINVAL;
+ return (ebuf);
+}
diff --git a/lib/libc/string/string.3 b/lib/libc/string/string.3
new file mode 100644
index 0000000..b0e25a9
--- /dev/null
+++ b/lib/libc/string/string.3
@@ -0,0 +1,157 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek.
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)string.3 8.2 (Berkeley) 12/11/93
+.\" $FreeBSD$
+.\"
+.Dd December 11, 1993
+.Dt STRING 3
+.Os
+.Sh NAME
+.Nm stpcpy ,
+.Nm strcat ,
+.Nm strncat ,
+.Nm strchr ,
+.Nm strrchr ,
+.Nm strcmp ,
+.Nm strncmp ,
+.Nm strcasecmp ,
+.Nm strncasecmp ,
+.Nm strcpy ,
+.Nm strncpy ,
+.Nm strerror ,
+.Nm strlen ,
+.Nm strpbrk ,
+.Nm strsep ,
+.Nm strspn ,
+.Nm strcspn ,
+.Nm strstr ,
+.Nm strtok ,
+.Nm index ,
+.Nm rindex
+.Nd string specific functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft char *
+.Fn stpcpy "char *dst" "const char *src"
+.Ft char *
+.Fn strcat "char *s" "const char * append"
+.Ft char *
+.Fn strncat "char *s" "const char *append" "size_t count"
+.Ft char *
+.Fn strchr "const char *s" "int c"
+.Ft char *
+.Fn strrchr "const char *s" "int c"
+.Ft int
+.Fn strcmp "const char *s1" "const char *s2"
+.Ft int
+.Fn strncmp "const char *s1" "const char *s2" "size_t count"
+.Ft int
+.Fn strcasecmp "const char *s1" "const char *s2"
+.Ft int
+.Fn strncasecmp "const char *s1" "const char *s2" "size_t count"
+.Ft char *
+.Fn strcpy "char *dst" "const char *src"
+.Ft char *
+.Fn strncpy "char *dst" "const char *src" "size_t count"
+.Ft char *
+.Fn strerror "int errno"
+.Ft size_t
+.Fn strlen "const char *s"
+.Ft char *
+.Fn strpbrk "const char *s" "const char *charset"
+.Ft char *
+.Fn strsep "char **stringp" "const char *delim"
+.Ft size_t
+.Fn strspn "const char *s" "const char *charset"
+.Ft size_t
+.Fn strcspn "const char *s" "const char *charset"
+.Ft char *
+.Fn strstr "const char *big" "const char *little"
+.Ft char *
+.Fn strtok "char *s" "const char *delim"
+.Ft char *
+.Fn index "const char *s" "int c"
+.Ft char *
+.Fn rindex "const char *s" "int c"
+.Sh DESCRIPTION
+The string
+functions manipulate strings terminated by a
+null byte.
+.Pp
+See the specific manual pages for more information.
+For manipulating variable length generic objects as byte
+strings (without the null byte check), see
+.Xr bstring 3 .
+.Pp
+Except as noted in their specific manual pages,
+the string functions do not test the destination
+for size limitations.
+.Sh SEE ALSO
+.Xr bstring 3 ,
+.Xr index 3 ,
+.Xr rindex 3 ,
+.Xr stpcpy 3 ,
+.Xr strcasecmp 3 ,
+.Xr strcat 3 ,
+.Xr strchr 3 ,
+.Xr strcmp 3 ,
+.Xr strcpy 3 ,
+.Xr strcspn 3 ,
+.Xr strerror 3 ,
+.Xr strlen 3 ,
+.Xr strpbrk 3 ,
+.Xr strrchr 3 ,
+.Xr strsep 3 ,
+.Xr strspn 3 ,
+.Xr strstr 3 ,
+.Xr strtok 3
+.Sh STANDARDS
+The
+.Fn strcat ,
+.Fn strncat ,
+.Fn strchr ,
+.Fn strrchr ,
+.Fn strcmp ,
+.Fn strncmp ,
+.Fn strcpy ,
+.Fn strncpy ,
+.Fn strerror ,
+.Fn strlen ,
+.Fn strpbrk ,
+.Fn strspn ,
+.Fn strcspn ,
+.Fn strstr ,
+and
+.Fn strtok
+functions
+conform to
+.St -isoC .
diff --git a/lib/libc/string/strlcat.c b/lib/libc/string/strlcat.c
new file mode 100644
index 0000000..2d13be7
--- /dev/null
+++ b/lib/libc/string/strlcat.c
@@ -0,0 +1,58 @@
+/* $OpenBSD: strlcat.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(char * __restrict dst, const char * __restrict src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return(dlen + strlen(s));
+ while (*s != '\0') {
+ if (n != 1) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src)); /* count does not include NUL */
+}
diff --git a/lib/libc/string/strlcpy.3 b/lib/libc/string/strlcpy.3
new file mode 100644
index 0000000..19d3621
--- /dev/null
+++ b/lib/libc/string/strlcpy.3
@@ -0,0 +1,205 @@
+.\" $OpenBSD: strlcpy.3,v 1.19 2007/05/31 19:19:32 jmc Exp $
+.\"
+.\" Copyright (c) 1998, 2000 Todd C. Miller <Todd.Miller@courtesan.com>
+.\"
+.\" Permission to use, copy, modify, and distribute this software for any
+.\" purpose with or without fee is hereby granted, provided that the above
+.\" copyright notice and this permission notice appear in all copies.
+.\"
+.\" THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+.\" WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+.\" ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+.\" WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+.\" ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+.\" OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+.\"
+.\" THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+.\" AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+.\" THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+.\" EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+.\" PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+.\" OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+.\" WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+.\" OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+.\" ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 22, 1998
+.Dt STRLCPY 3
+.Os
+.Sh NAME
+.Nm strlcpy ,
+.Nm strlcat
+.Nd size-bounded string copying and concatenation
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft size_t
+.Fn strlcpy "char * restrict dst" "const char * restrict src" "size_t size"
+.Ft size_t
+.Fn strlcat "char * restrict dst" "const char * restrict src" "size_t size"
+.Sh DESCRIPTION
+The
+.Fn strlcpy
+and
+.Fn strlcat
+functions copy and concatenate strings respectively.
+They are designed
+to be safer, more consistent, and less error prone replacements for
+.Xr strncpy 3
+and
+.Xr strncat 3 .
+Unlike those functions,
+.Fn strlcpy
+and
+.Fn strlcat
+take the full size of the buffer (not just the length) and guarantee to
+NUL-terminate the result (as long as
+.Fa size
+is larger than 0 or, in the case of
+.Fn strlcat ,
+as long as there is at least one byte free in
+.Fa dst ) .
+Note that a byte for the NUL should be included in
+.Fa size .
+Also note that
+.Fn strlcpy
+and
+.Fn strlcat
+only operate on true
+.Dq C
+strings.
+This means that for
+.Fn strlcpy
+.Fa src
+must be NUL-terminated and for
+.Fn strlcat
+both
+.Fa src
+and
+.Fa dst
+must be NUL-terminated.
+.Pp
+The
+.Fn strlcpy
+function copies up to
+.Fa size
+- 1 characters from the NUL-terminated string
+.Fa src
+to
+.Fa dst ,
+NUL-terminating the result.
+.Pp
+The
+.Fn strlcat
+function appends the NUL-terminated string
+.Fa src
+to the end of
+.Fa dst .
+It will append at most
+.Fa size
+- strlen(dst) - 1 bytes, NUL-terminating the result.
+.Sh RETURN VALUES
+The
+.Fn strlcpy
+and
+.Fn strlcat
+functions return the total length of the string they tried to
+create.
+For
+.Fn strlcpy
+that means the length of
+.Fa src .
+For
+.Fn strlcat
+that means the initial length of
+.Fa dst
+plus
+the length of
+.Fa src .
+While this may seem somewhat confusing, it was done to make
+truncation detection simple.
+.Pp
+Note however, that if
+.Fn strlcat
+traverses
+.Fa size
+characters without finding a NUL, the length of the string is considered
+to be
+.Fa size
+and the destination string will not be NUL-terminated (since there was
+no space for the NUL).
+This keeps
+.Fn strlcat
+from running off the end of a string.
+In practice this should not happen (as it means that either
+.Fa size
+is incorrect or that
+.Fa dst
+is not a proper
+.Dq C
+string).
+The check exists to prevent potential security problems in incorrect code.
+.Sh EXAMPLES
+The following code fragment illustrates the simple case:
+.Bd -literal -offset indent
+char *s, *p, buf[BUFSIZ];
+
+\&...
+
+(void)strlcpy(buf, s, sizeof(buf));
+(void)strlcat(buf, p, sizeof(buf));
+.Ed
+.Pp
+To detect truncation, perhaps while building a pathname, something
+like the following might be used:
+.Bd -literal -offset indent
+char *dir, *file, pname[MAXPATHLEN];
+
+\&...
+
+if (strlcpy(pname, dir, sizeof(pname)) >= sizeof(pname))
+ goto toolong;
+if (strlcat(pname, file, sizeof(pname)) >= sizeof(pname))
+ goto toolong;
+.Ed
+.Pp
+Since it is known how many characters were copied the first time, things
+can be sped up a bit by using a copy instead of an append
+.Bd -literal -offset indent
+char *dir, *file, pname[MAXPATHLEN];
+size_t n;
+
+\&...
+
+n = strlcpy(pname, dir, sizeof(pname));
+if (n >= sizeof(pname))
+ goto toolong;
+if (strlcpy(pname + n, file, sizeof(pname) - n) >= sizeof(pname) - n)
+ goto toolong;
+.Ed
+.Pp
+However, one may question the validity of such optimizations, as they
+defeat the whole purpose of
+.Fn strlcpy
+and
+.Fn strlcat .
+As a matter of fact, the first version of this manual page got it wrong.
+.Sh SEE ALSO
+.Xr snprintf 3 ,
+.Xr strncat 3 ,
+.Xr strncpy 3 ,
+.Xr wcslcpy 3
+.Sh HISTORY
+The
+.Fn strlcpy
+and
+.Fn strlcat
+functions first appeared in
+.Ox 2.4 ,
+and made their appearance in
+.Fx 3.3 .
diff --git a/lib/libc/string/strlcpy.c b/lib/libc/string/strlcpy.c
new file mode 100644
index 0000000..451b6df
--- /dev/null
+++ b/lib/libc/string/strlcpy.c
@@ -0,0 +1,54 @@
+/* $OpenBSD: strlcpy.c,v 1.11 2006/05/05 15:27:38 millert Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char * __restrict dst, const char * __restrict src, size_t siz)
+{
+ char *d = dst;
+ const char *s = src;
+ size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0) {
+ while (--n != 0) {
+ if ((*d++ = *s++) == '\0')
+ break;
+ }
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}
diff --git a/lib/libc/string/strlen.3 b/lib/libc/string/strlen.3
new file mode 100644
index 0000000..bdbf4ff
--- /dev/null
+++ b/lib/libc/string/strlen.3
@@ -0,0 +1,92 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strlen.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd February 28, 2009
+.Dt STRLEN 3
+.Os
+.Sh NAME
+.Nm strlen, strnlen
+.Nd find length of string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft size_t
+.Fn strlen "const char *s"
+.Ft size_t
+.Fn strnlen "const char *s" "size_t maxlen"
+.Sh DESCRIPTION
+The
+.Fn strlen
+function
+computes the length of the string
+.Fa s .
+The
+.Fn strnlen
+function attempts to compute the length of
+.Fa s ,
+but never scans beyond the first
+.Fa maxlen
+bytes of
+.Fa s .
+.Sh RETURN VALUES
+The
+.Fn strlen
+function
+returns
+the number of characters that precede the
+terminating
+.Dv NUL
+character.
+The
+.Fn strnlen
+function returns either the same result as
+.Fn strlen
+or
+.Fa maxlen ,
+whichever is smaller.
+.Sh SEE ALSO
+.Xr string 3 ,
+.Xr wcslen 3 ,
+.Xr wcswidth 3
+.Sh STANDARDS
+The
+.Fn strlen
+function
+conforms to
+.St -isoC .
+The
+.Fn strnlen
+function conforms to
+.St -p1003.1-2008 .
diff --git a/lib/libc/string/strlen.c b/lib/libc/string/strlen.c
new file mode 100644
index 0000000..2bc1f2b
--- /dev/null
+++ b/lib/libc/string/strlen.c
@@ -0,0 +1,130 @@
+/*-
+ * Copyright (c) 2009, 2010 Xin LI <delphij@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/limits.h>
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Portable strlen() for 32-bit and 64-bit systems.
+ *
+ * Rationale: it is generally much more efficient to do word length
+ * operations and avoid branches on modern computer systems, as
+ * compared to byte-length operations with a lot of branches.
+ *
+ * The expression:
+ *
+ * ((x - 0x01....01) & ~x & 0x80....80)
+ *
+ * would evaluate to a non-zero value iff any of the bytes in the
+ * original word is zero.
+ *
+ * On multi-issue processors, we can divide the above expression into:
+ * a) (x - 0x01....01)
+ * b) (~x & 0x80....80)
+ * c) a & b
+ *
+ * Where, a) and b) can be partially computed in parallel.
+ *
+ * The algorithm above is found on "Hacker's Delight" by
+ * Henry S. Warren, Jr.
+ */
+
+/* Magic numbers for the algorithm */
+#if LONG_BIT == 32
+static const unsigned long mask01 = 0x01010101;
+static const unsigned long mask80 = 0x80808080;
+#elif LONG_BIT == 64
+static const unsigned long mask01 = 0x0101010101010101;
+static const unsigned long mask80 = 0x8080808080808080;
+#else
+#error Unsupported word size
+#endif
+
+#define LONGPTR_MASK (sizeof(long) - 1)
+
+/*
+ * Helper macro to return string length if we caught the zero
+ * byte.
+ */
+#define testbyte(x) \
+ do { \
+ if (p[x] == '\0') \
+ return (p - str + x); \
+ } while (0)
+
+size_t
+strlen(const char *str)
+{
+ const char *p;
+ const unsigned long *lp;
+ long va, vb;
+
+ /*
+ * Before trying the hard (unaligned byte-by-byte access) way
+ * to figure out whether there is a nul character, try to see
+ * if there is a nul character is within this accessible word
+ * first.
+ *
+ * p and (p & ~LONGPTR_MASK) must be equally accessible since
+ * they always fall in the same memory page, as long as page
+ * boundaries is integral multiple of word size.
+ */
+ lp = (const unsigned long *)((uintptr_t)str & ~LONGPTR_MASK);
+ va = (*lp - mask01);
+ vb = ((~*lp) & mask80);
+ lp++;
+ if (va & vb)
+ /* Check if we have \0 in the first part */
+ for (p = str; p < (const char *)lp; p++)
+ if (*p == '\0')
+ return (p - str);
+
+ /* Scan the rest of the string using word sized operation */
+ for (; ; lp++) {
+ va = (*lp - mask01);
+ vb = ((~*lp) & mask80);
+ if (va & vb) {
+ p = (const char *)(lp);
+ testbyte(0);
+ testbyte(1);
+ testbyte(2);
+ testbyte(3);
+#if (LONG_BIT >= 64)
+ testbyte(4);
+ testbyte(5);
+ testbyte(6);
+ testbyte(7);
+#endif
+ }
+ }
+
+ /* NOTREACHED */
+ return (0);
+}
diff --git a/lib/libc/string/strmode.3 b/lib/libc/string/strmode.3
new file mode 100644
index 0000000..1a072d8
--- /dev/null
+++ b/lib/libc/string/strmode.3
@@ -0,0 +1,142 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strmode.3 8.3 (Berkeley) 7/28/94
+.\" $FreeBSD$
+.\"
+.Dd July 28, 1994
+.Dt STRMODE 3
+.Os
+.Sh NAME
+.Nm strmode
+.Nd convert inode status information into a symbolic string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft void
+.Fn strmode "mode_t mode" "char *bp"
+.Sh DESCRIPTION
+The
+.Fn strmode
+function
+converts a file
+.Fa mode
+(the type and permission information associated with an inode, see
+.Xr stat 2 )
+into a symbolic string which is stored in the location referenced by
+.Fa bp .
+This stored string is eleven characters in length plus a trailing
+.Dv NUL .
+.Pp
+The first character is the inode type, and will be one of the following:
+.Pp
+.Bl -tag -width flag -offset indent -compact
+.It \-
+regular file
+.It b
+block special
+.It c
+character special
+.It d
+directory
+.It l
+symbolic link
+.It p
+fifo
+.It s
+socket
+.It w
+whiteout
+.It ?
+unknown inode type
+.El
+.Pp
+The next nine characters encode three sets of permissions, in three
+characters each.
+The first three characters are the permissions for the owner of the
+file, the second three for the group the file belongs to, and the
+third for the ``other'', or default, set of users.
+.Pp
+Permission checking is done as specifically as possible.
+If read permission is denied to the owner of a file in the first set
+of permissions, the owner of the file will not be able to read the file.
+This is true even if the owner is in the file's group and the group
+permissions allow reading or the ``other'' permissions allow reading.
+.Pp
+If the first character of the three character set is an ``r'', the file is
+readable for that set of users; if a dash ``\-'', it is not readable.
+.Pp
+If the second character of the three character set is a ``w'', the file is
+writable for that set of users; if a dash ``\-'', it is not writable.
+.Pp
+The third character is the first of the following characters that apply:
+.Bl -tag -width xxxx
+.It S
+If the character is part of the owner permissions and the file is not
+executable or the directory is not searchable by the owner, and the
+set-user-id bit is set.
+.It S
+If the character is part of the group permissions and the file is not
+executable or the directory is not searchable by the group, and the
+set-group-id bit is set.
+.It T
+If the character is part of the other permissions and the file is not
+executable or the directory is not searchable by others, and the ``sticky''
+.Pq Dv S_ISVTX
+bit is set.
+.It s
+If the character is part of the owner permissions and the file is
+executable or the directory searchable by the owner, and the set-user-id
+bit is set.
+.It s
+If the character is part of the group permissions and the file is
+executable or the directory searchable by the group, and the set-group-id
+bit is set.
+.It t
+If the character is part of the other permissions and the file is
+executable or the directory searchable by others, and the ``sticky''
+.Pq Dv S_ISVTX
+bit is set.
+.It x
+The file is executable or the directory is searchable.
+.It \-
+None of the above apply.
+.El
+.Pp
+The last character will always be a space.
+.Sh SEE ALSO
+.Xr chmod 1 ,
+.Xr find 1 ,
+.Xr stat 2 ,
+.Xr getmode 3 ,
+.Xr setmode 3
+.Sh HISTORY
+The
+.Fn strmode
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/string/strmode.c b/lib/libc/string/strmode.c
new file mode 100644
index 0000000..3aaa77e
--- /dev/null
+++ b/lib/libc/string/strmode.c
@@ -0,0 +1,148 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strmode.c 8.3 (Berkeley) 8/15/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <string.h>
+
+void
+strmode(/* mode_t */ int mode, char *p)
+{
+ /* print type */
+ switch (mode & S_IFMT) {
+ case S_IFDIR: /* directory */
+ *p++ = 'd';
+ break;
+ case S_IFCHR: /* character special */
+ *p++ = 'c';
+ break;
+ case S_IFBLK: /* block special */
+ *p++ = 'b';
+ break;
+ case S_IFREG: /* regular */
+ *p++ = '-';
+ break;
+ case S_IFLNK: /* symbolic link */
+ *p++ = 'l';
+ break;
+ case S_IFSOCK: /* socket */
+ *p++ = 's';
+ break;
+#ifdef S_IFIFO
+ case S_IFIFO: /* fifo */
+ *p++ = 'p';
+ break;
+#endif
+#ifdef S_IFWHT
+ case S_IFWHT: /* whiteout */
+ *p++ = 'w';
+ break;
+#endif
+ default: /* unknown */
+ *p++ = '?';
+ break;
+ }
+ /* usr */
+ if (mode & S_IRUSR)
+ *p++ = 'r';
+ else
+ *p++ = '-';
+ if (mode & S_IWUSR)
+ *p++ = 'w';
+ else
+ *p++ = '-';
+ switch (mode & (S_IXUSR | S_ISUID)) {
+ case 0:
+ *p++ = '-';
+ break;
+ case S_IXUSR:
+ *p++ = 'x';
+ break;
+ case S_ISUID:
+ *p++ = 'S';
+ break;
+ case S_IXUSR | S_ISUID:
+ *p++ = 's';
+ break;
+ }
+ /* group */
+ if (mode & S_IRGRP)
+ *p++ = 'r';
+ else
+ *p++ = '-';
+ if (mode & S_IWGRP)
+ *p++ = 'w';
+ else
+ *p++ = '-';
+ switch (mode & (S_IXGRP | S_ISGID)) {
+ case 0:
+ *p++ = '-';
+ break;
+ case S_IXGRP:
+ *p++ = 'x';
+ break;
+ case S_ISGID:
+ *p++ = 'S';
+ break;
+ case S_IXGRP | S_ISGID:
+ *p++ = 's';
+ break;
+ }
+ /* other */
+ if (mode & S_IROTH)
+ *p++ = 'r';
+ else
+ *p++ = '-';
+ if (mode & S_IWOTH)
+ *p++ = 'w';
+ else
+ *p++ = '-';
+ switch (mode & (S_IXOTH | S_ISVTX)) {
+ case 0:
+ *p++ = '-';
+ break;
+ case S_IXOTH:
+ *p++ = 'x';
+ break;
+ case S_ISVTX:
+ *p++ = 'T';
+ break;
+ case S_IXOTH | S_ISVTX:
+ *p++ = 't';
+ break;
+ }
+ *p++ = ' ';
+ *p = '\0';
+}
diff --git a/lib/libc/string/strncat.c b/lib/libc/string/strncat.c
new file mode 100644
index 0000000..fb2802c
--- /dev/null
+++ b/lib/libc/string/strncat.c
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strncat.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+/*
+ * Concatenate src on the end of dst. At most strlen(dst)+n+1 bytes
+ * are written at dst (at most n+1 bytes being appended). Return dst.
+ */
+char *
+strncat(char * __restrict dst, const char * __restrict src, size_t n)
+{
+ if (n != 0) {
+ char *d = dst;
+ const char *s = src;
+
+ while (*d != 0)
+ d++;
+ do {
+ if ((*d = *s++) == 0)
+ break;
+ d++;
+ } while (--n != 0);
+ *d = 0;
+ }
+ return (dst);
+}
diff --git a/lib/libc/string/strncmp.c b/lib/libc/string/strncmp.c
new file mode 100644
index 0000000..5bc3d5e
--- /dev/null
+++ b/lib/libc/string/strncmp.c
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strncmp.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+int
+strncmp(const char *s1, const char *s2, size_t n)
+{
+
+ if (n == 0)
+ return (0);
+ do {
+ if (*s1 != *s2++)
+ return (*(const unsigned char *)s1 -
+ *(const unsigned char *)(s2 - 1));
+ if (*s1++ == '\0')
+ break;
+ } while (--n != 0);
+ return (0);
+}
diff --git a/lib/libc/string/strncpy.c b/lib/libc/string/strncpy.c
new file mode 100644
index 0000000..980dbc7
--- /dev/null
+++ b/lib/libc/string/strncpy.c
@@ -0,0 +1,62 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strncpy.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+/*
+ * Copy src to dst, truncating or null-padding to always copy n bytes.
+ * Return dst.
+ */
+char *
+strncpy(char * __restrict dst, const char * __restrict src, size_t n)
+{
+ if (n != 0) {
+ char *d = dst;
+ const char *s = src;
+
+ do {
+ if ((*d++ = *s++) == '\0') {
+ /* NUL pad the remaining n-1 bytes */
+ while (--n != 0)
+ *d++ = '\0';
+ break;
+ }
+ } while (--n != 0);
+ }
+ return (dst);
+}
diff --git a/lib/libc/string/strndup.c b/lib/libc/string/strndup.c
new file mode 100644
index 0000000..abb1e03
--- /dev/null
+++ b/lib/libc/string/strndup.c
@@ -0,0 +1,51 @@
+/* $NetBSD: strndup.c,v 1.3 2007/01/14 23:41:24 cbiere Exp $ */
+
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stddef.h>
+#include <stdlib.h>
+#include <string.h>
+
+char *
+strndup(const char *str, size_t n)
+{
+ size_t len;
+ char *copy;
+
+ len = strnlen(str, n);
+ if ((copy = malloc(len + 1)) == NULL)
+ return (NULL);
+ memcpy(copy, str, len);
+ copy[len] = '\0';
+ return (copy);
+}
diff --git a/lib/libc/string/strnlen.c b/lib/libc/string/strnlen.c
new file mode 100644
index 0000000..f44151f
--- /dev/null
+++ b/lib/libc/string/strnlen.c
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+size_t
+strnlen(const char *s, size_t maxlen)
+{
+ size_t len;
+
+ for (len = 0; len < maxlen; len++, s++) {
+ if (!*s)
+ break;
+ }
+ return (len);
+}
diff --git a/lib/libc/string/strnstr.c b/lib/libc/string/strnstr.c
new file mode 100644
index 0000000..45be95d
--- /dev/null
+++ b/lib/libc/string/strnstr.c
@@ -0,0 +1,65 @@
+/*-
+ * Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strstr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+/*
+ * Find the first occurrence of find in s, where the search is limited to the
+ * first slen characters of s.
+ */
+char *
+strnstr(const char *s, const char *find, size_t slen)
+{
+ char c, sc;
+ size_t len;
+
+ if ((c = *find++) != '\0') {
+ len = strlen(find);
+ do {
+ do {
+ if (slen-- < 1 || (sc = *s++) == '\0')
+ return (NULL);
+ } while (sc != c);
+ if (len > slen)
+ return (NULL);
+ } while (strncmp(s, find, len) != 0);
+ s--;
+ }
+ return ((char *)s);
+}
diff --git a/lib/libc/string/strpbrk.3 b/lib/libc/string/strpbrk.3
new file mode 100644
index 0000000..7ed0ec7
--- /dev/null
+++ b/lib/libc/string/strpbrk.3
@@ -0,0 +1,77 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strpbrk.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt STRPBRK 3
+.Os
+.Sh NAME
+.Nm strpbrk
+.Nd locate multiple characters in string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft char *
+.Fn strpbrk "const char *s" "const char *charset"
+.Sh DESCRIPTION
+The
+.Fn strpbrk
+function
+locates in the null-terminated string
+.Fa s
+the first occurrence of any character in the string
+.Fa charset
+and returns a pointer to this character.
+If no characters from
+.Fa charset
+occur anywhere in
+.Fa s
+.Fn strpbrk
+returns NULL.
+.Sh SEE ALSO
+.Xr memchr 3 ,
+.Xr strchr 3 ,
+.Xr strcspn 3 ,
+.Xr strrchr 3 ,
+.Xr strsep 3 ,
+.Xr strspn 3 ,
+.Xr strstr 3 ,
+.Xr strtok 3 ,
+.Xr wcspbrk 3
+.Sh STANDARDS
+The
+.Fn strpbrk
+function
+conforms to
+.St -isoC .
diff --git a/lib/libc/string/strpbrk.c b/lib/libc/string/strpbrk.c
new file mode 100644
index 0000000..2069bee
--- /dev/null
+++ b/lib/libc/string/strpbrk.c
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 1985, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strpbrk.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+/*
+ * Find the first occurrence in s1 of a character in s2 (excluding NUL).
+ */
+char *
+strpbrk(const char *s1, const char *s2)
+{
+ const char *scanp;
+ int c, sc;
+
+ while ((c = *s1++) != 0) {
+ for (scanp = s2; (sc = *scanp++) != '\0';)
+ if (sc == c)
+ return ((char *)(s1 - 1));
+ }
+ return (NULL);
+}
diff --git a/lib/libc/string/strrchr.c b/lib/libc/string/strrchr.c
new file mode 100644
index 0000000..be9f978
--- /dev/null
+++ b/lib/libc/string/strrchr.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rindex.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stddef.h>
+#include <string.h>
+
+char *
+strrchr(const char *p, int ch)
+{
+ char *save;
+ char c;
+
+ c = ch;
+ for (save = NULL;; ++p) {
+ if (*p == c)
+ save = (char *)p;
+ if (*p == '\0')
+ return (save);
+ }
+ /* NOTREACHED */
+}
+
+__weak_reference(strrchr, rindex);
diff --git a/lib/libc/string/strsep.3 b/lib/libc/string/strsep.3
new file mode 100644
index 0000000..9432a88
--- /dev/null
+++ b/lib/libc/string/strsep.3
@@ -0,0 +1,135 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strsep.3 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd December 5, 2008
+.Dt STRSEP 3
+.Os
+.Sh NAME
+.Nm strsep
+.Nd separate strings
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft char *
+.Fn strsep "char **stringp" "const char *delim"
+.Sh DESCRIPTION
+The
+.Fn strsep
+function locates, in the string referenced by
+.Fa *stringp ,
+the first occurrence of any character in the string
+.Fa delim
+(or the terminating
+.Ql \e0
+character) and replaces it with a
+.Ql \e0 .
+The location of the next character after the delimiter character
+(or NULL, if the end of the string was reached) is stored in
+.Fa *stringp .
+The original value of
+.Fa *stringp
+is returned.
+.Pp
+An
+.Dq empty
+field (i.e., a character in the string
+.Fa delim
+occurs as the first character of
+.Fa *stringp )
+can be detected by comparing the location referenced by the returned pointer
+to
+.Ql \e0 .
+.Pp
+If
+.Fa *stringp
+is initially
+.Dv NULL ,
+.Fn strsep
+returns
+.Dv NULL .
+.Sh EXAMPLES
+The following uses
+.Fn strsep
+to parse a string, and prints each token in separate line:
+.Bd -literal -offset indent
+char *token, *string, *tofree;
+
+tofree = string = strdup("abc,def,ghi");
+assert(string != NULL);
+
+while ((token = strsep(&string, ",")) != NULL)
+ printf("%s\en", token);
+
+free(tofree);
+.Ed
+.Pp
+The following uses
+.Fn strsep
+to parse a string, containing tokens delimited by white space, into an
+argument vector:
+.Bd -literal -offset indent
+char **ap, *argv[10], *inputstring;
+
+for (ap = argv; (*ap = strsep(&inputstring, " \et")) != NULL;)
+ if (**ap != '\e0')
+ if (++ap >= &argv[10])
+ break;
+.Ed
+.Sh SEE ALSO
+.Xr memchr 3 ,
+.Xr strchr 3 ,
+.Xr strcspn 3 ,
+.Xr strpbrk 3 ,
+.Xr strrchr 3 ,
+.Xr strspn 3 ,
+.Xr strstr 3 ,
+.Xr strtok 3
+.Sh HISTORY
+The
+.Fn strsep
+function
+is intended as a replacement for the
+.Fn strtok
+function.
+While the
+.Fn strtok
+function should be preferred for portability reasons (it conforms to
+.St -isoC )
+it is unable to handle empty fields, i.e., detect fields delimited by
+two adjacent delimiter characters, or to be used for more than a single
+string at a time.
+The
+.Fn strsep
+function first appeared in
+.Bx 4.4 .
diff --git a/lib/libc/string/strsep.c b/lib/libc/string/strsep.c
new file mode 100644
index 0000000..670ab04
--- /dev/null
+++ b/lib/libc/string/strsep.c
@@ -0,0 +1,75 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strsep.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+#include <stdio.h>
+
+/*
+ * Get next token from string *stringp, where tokens are possibly-empty
+ * strings separated by characters from delim.
+ *
+ * Writes NULs into the string at *stringp to end tokens.
+ * delim need not remain constant from call to call.
+ * On return, *stringp points past the last NUL written (if there might
+ * be further tokens), or is NULL (if there are definitely no more tokens).
+ *
+ * If *stringp is NULL, strsep returns NULL.
+ */
+char *
+strsep(char **stringp, const char *delim)
+{
+ char *s;
+ const char *spanp;
+ int c, sc;
+ char *tok;
+
+ if ((s = *stringp) == NULL)
+ return (NULL);
+ for (tok = s;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = 0;
+ *stringp = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
diff --git a/lib/libc/string/strsignal.c b/lib/libc/string/strsignal.c
new file mode 100644
index 0000000..c51f34d
--- /dev/null
+++ b/lib/libc/string/strsignal.c
@@ -0,0 +1,152 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strerror.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#if defined(NLS)
+#include <nl_types.h>
+#endif
+#include <limits.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include "reentrant.h"
+#include "un-namespace.h"
+
+#define UPREFIX "Unknown signal"
+
+static char sig_ebuf[NL_TEXTMAX];
+static char sig_ebuf_err[NL_TEXTMAX];
+static once_t sig_init_once = ONCE_INITIALIZER;
+static thread_key_t sig_key;
+static int sig_keycreated = 0;
+
+static void
+sig_keycreate(void)
+{
+ sig_keycreated = (thr_keycreate(&sig_key, free) == 0);
+}
+
+static char *
+sig_tlsalloc(void)
+{
+ char *ebuf = NULL;
+
+ if (thr_main() != 0)
+ ebuf = sig_ebuf;
+ else {
+ if (thr_once(&sig_init_once, sig_keycreate) != 0 ||
+ !sig_keycreated)
+ goto thr_err;
+ if ((ebuf = thr_getspecific(sig_key)) == NULL) {
+ if ((ebuf = malloc(sizeof(sig_ebuf))) == NULL)
+ goto thr_err;
+ if (thr_setspecific(sig_key, ebuf) != 0) {
+ free(ebuf);
+ ebuf = NULL;
+ goto thr_err;
+ }
+ }
+ }
+thr_err:
+ if (ebuf == NULL)
+ ebuf = sig_ebuf_err;
+ return (ebuf);
+}
+
+/* XXX: negative 'num' ? (REGR) */
+char *
+strsignal(int num)
+{
+ char *ebuf;
+ char tmp[20];
+ size_t n;
+ int signum;
+ char *t, *p;
+
+#if defined(NLS)
+ int saved_errno = errno;
+ nl_catd catd;
+ catd = catopen("libc", NL_CAT_LOCALE);
+#endif
+
+ ebuf = sig_tlsalloc();
+
+ if (num > 0 && num < sys_nsig) {
+ n = strlcpy(ebuf,
+#if defined(NLS)
+ catgets(catd, 2, num, sys_siglist[num]),
+#else
+ sys_siglist[num],
+#endif
+ sizeof(sig_ebuf));
+ } else {
+ n = strlcpy(ebuf,
+#if defined(NLS)
+ catgets(catd, 2, 0xffff, UPREFIX),
+#else
+ UPREFIX,
+#endif
+ sizeof(sig_ebuf));
+ }
+
+ signum = num;
+ if (num < 0)
+ signum = -signum;
+
+ t = tmp;
+ do {
+ *t++ = "0123456789"[signum % 10];
+ } while (signum /= 10);
+ if (num < 0)
+ *t++ = '-';
+
+ p = (ebuf + n);
+ *p++ = ':';
+ *p++ = ' ';
+
+ for (;;) {
+ *p++ = *--t;
+ if (t <= tmp)
+ break;
+ }
+ *p = '\0';
+
+#if defined(NLS)
+ catclose(catd);
+ errno = saved_errno;
+#endif
+ return (ebuf);
+}
diff --git a/lib/libc/string/strspn.3 b/lib/libc/string/strspn.3
new file mode 100644
index 0000000..72a1d32
--- /dev/null
+++ b/lib/libc/string/strspn.3
@@ -0,0 +1,84 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strspn.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt STRSPN 3
+.Os
+.Sh NAME
+.Nm strspn
+.Nd span a string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft size_t
+.Fn strspn "const char *s" "const char *charset"
+.Sh DESCRIPTION
+The
+.Fn strspn
+function
+spans the initial part of the null-terminated string
+.Fa s
+as long as the characters from
+.Fa s
+occur in the null-terminated string
+.Fa charset .
+In other words, it computes the string array index in
+.Fa s
+of the first character of
+.Fa s
+which is not in
+.Fa charset ,
+else the index of the first null character.
+.Sh RETURN VALUES
+The
+.Fn strspn
+function
+returns the number of characters spanned.
+.Sh SEE ALSO
+.Xr memchr 3 ,
+.Xr strchr 3 ,
+.Xr strcspn 3 ,
+.Xr strpbrk 3 ,
+.Xr strrchr 3 ,
+.Xr strsep 3 ,
+.Xr strstr 3 ,
+.Xr strtok 3 ,
+.Xr wcsspn 3
+.Sh STANDARDS
+The
+.Fn strspn
+function
+conforms to
+.St -isoC .
diff --git a/lib/libc/string/strspn.c b/lib/libc/string/strspn.c
new file mode 100644
index 0000000..5dbac0a
--- /dev/null
+++ b/lib/libc/string/strspn.c
@@ -0,0 +1,71 @@
+/*-
+ * Copyright (c) 2005 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <limits.h>
+#include <string.h>
+
+#define IDX(c) ((u_char)(c) / LONG_BIT)
+#define BIT(c) ((u_long)1 << ((u_char)(c) % LONG_BIT))
+
+size_t
+strspn(const char *s, const char *charset)
+{
+ /*
+ * NB: idx and bit are temporaries whose use causes gcc 3.4.2 to
+ * generate better code. Without them, gcc gets a little confused.
+ */
+ const char *s1;
+ u_long bit;
+ u_long tbl[(UCHAR_MAX + 1) / LONG_BIT];
+ int idx;
+
+ if(*s == '\0')
+ return (0);
+
+#if LONG_BIT == 64 /* always better to unroll on 64-bit architectures */
+ tbl[3] = tbl[2] = tbl[1] = tbl[0] = 0;
+#else
+ for (idx = 0; idx < sizeof(tbl) / sizeof(tbl[0]); idx++)
+ tbl[idx] = 0;
+#endif
+ for (; *charset != '\0'; charset++) {
+ idx = IDX(*charset);
+ bit = BIT(*charset);
+ tbl[idx] |= bit;
+ }
+
+ for(s1 = s; ; s1++) {
+ idx = IDX(*s1);
+ bit = BIT(*s1);
+ if ((tbl[idx] & bit) == 0)
+ break;
+ }
+ return (s1 - s);
+}
diff --git a/lib/libc/string/strstr.3 b/lib/libc/string/strstr.3
new file mode 100644
index 0000000..74ebdff
--- /dev/null
+++ b/lib/libc/string/strstr.3
@@ -0,0 +1,145 @@
+.\" Copyright (c) 2001 Mike Barcroft <mike@FreeBSD.org>
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strstr.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd October 11, 2001
+.Dt STRSTR 3
+.Os
+.Sh NAME
+.Nm strstr , strcasestr , strnstr
+.Nd locate a substring in a string
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft char *
+.Fn strstr "const char *big" "const char *little"
+.Ft char *
+.Fn strcasestr "const char *big" "const char *little"
+.Ft char *
+.Fn strnstr "const char *big" "const char *little" "size_t len"
+.Sh DESCRIPTION
+The
+.Fn strstr
+function
+locates the first occurrence of the null-terminated string
+.Fa little
+in the null-terminated string
+.Fa big .
+.Pp
+The
+.Fn strcasestr
+function is similar to
+.Fn strstr ,
+but ignores the case of both strings.
+.Pp
+The
+.Fn strnstr
+function
+locates the first occurrence of the null-terminated string
+.Fa little
+in the string
+.Fa big ,
+where not more than
+.Fa len
+characters are searched.
+Characters that appear after a
+.Ql \e0
+character are not searched.
+Since the
+.Fn strnstr
+function is a
+.Fx
+specific API, it should only be used when portability is not a concern.
+.Sh RETURN VALUES
+If
+.Fa little
+is an empty string,
+.Fa big
+is returned;
+if
+.Fa little
+occurs nowhere in
+.Fa big ,
+.Dv NULL
+is returned;
+otherwise a pointer to the first character of the first occurrence of
+.Fa little
+is returned.
+.Sh EXAMPLES
+The following sets the pointer
+.Va ptr
+to the
+.Qq Li Bar Baz
+portion of
+.Va largestring :
+.Bd -literal -offset indent
+const char *largestring = "Foo Bar Baz";
+const char *smallstring = "Bar";
+char *ptr;
+
+ptr = strstr(largestring, smallstring);
+.Ed
+.Pp
+The following sets the pointer
+.Va ptr
+to
+.Dv NULL ,
+because only the first 4 characters of
+.Va largestring
+are searched:
+.Bd -literal -offset indent
+const char *largestring = "Foo Bar Baz";
+const char *smallstring = "Bar";
+char *ptr;
+
+ptr = strnstr(largestring, smallstring, 4);
+.Ed
+.Sh SEE ALSO
+.Xr memchr 3 ,
+.Xr memmem 3 ,
+.Xr strchr 3 ,
+.Xr strcspn 3 ,
+.Xr strpbrk 3 ,
+.Xr strrchr 3 ,
+.Xr strsep 3 ,
+.Xr strspn 3 ,
+.Xr strtok 3 ,
+.Xr wcsstr 3
+.Sh STANDARDS
+The
+.Fn strstr
+function
+conforms to
+.St -isoC .
diff --git a/lib/libc/string/strstr.c b/lib/libc/string/strstr.c
new file mode 100644
index 0000000..82b4c5a
--- /dev/null
+++ b/lib/libc/string/strstr.c
@@ -0,0 +1,61 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strstr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+
+/*
+ * Find the first occurrence of find in s.
+ */
+char *
+strstr(const char *s, const char *find)
+{
+ char c, sc;
+ size_t len;
+
+ if ((c = *find++) != '\0') {
+ len = strlen(find);
+ do {
+ do {
+ if ((sc = *s++) == '\0')
+ return (NULL);
+ } while (sc != c);
+ } while (strncmp(s, find, len) != 0);
+ s--;
+ }
+ return ((char *)s);
+}
diff --git a/lib/libc/string/strtok.3 b/lib/libc/string/strtok.3
new file mode 100644
index 0000000..e19579f
--- /dev/null
+++ b/lib/libc/string/strtok.3
@@ -0,0 +1,172 @@
+.\" Copyright (c) 1998 Softweyr LLC. All rights reserved.
+.\"
+.\" strtok_r, from Berkeley strtok
+.\" Oct 13, 1998 by Wes Peters <wes@softweyr.com>
+.\"
+.\" Copyright (c) 1988, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notices, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above
+.\" copyright notices, this list of conditions and the following
+.\" disclaimer in the documentation and/or other materials provided
+.\" with the distribution.
+.\"
+.\" 4. Neither the name of Softweyr LLC, the University nor the names
+.\" of its contributors may be used to endorse or promote products
+.\" derived from this software without specific prior written
+.\" permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND
+.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+.\" DISCLAIMED. IN NO EVENT SHALL SOFTWEYR LLC, THE REGENTS, OR
+.\" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strtok.3 8.2 (Berkeley) 2/3/94
+.\" $FreeBSD$
+.\"
+.Dd November 27, 1998
+.Dt STRTOK 3
+.Os
+.Sh NAME
+.Nm strtok , strtok_r
+.Nd string tokens
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft char *
+.Fn strtok "char *str" "const char *sep"
+.Ft char *
+.Fn strtok_r "char *str" "const char *sep" "char **last"
+.Sh DESCRIPTION
+.Bf -symbolic
+This interface is obsoleted by
+.Xr strsep 3 .
+.Ef
+.Pp
+The
+.Fn strtok
+function
+is used to isolate sequential tokens in a null-terminated string,
+.Fa str .
+These tokens are separated in the string by at least one of the
+characters in
+.Fa sep .
+The first time that
+.Fn strtok
+is called,
+.Fa str
+should be specified; subsequent calls, wishing to obtain further tokens
+from the same string, should pass a null pointer instead.
+The separator string,
+.Fa sep ,
+must be supplied each time, and may change between calls.
+.Pp
+The implementation will behave as if no library function calls
+.Fn strtok .
+.Pp
+The
+.Fn strtok_r
+function is a reentrant version of
+.Fn strtok .
+The context pointer
+.Fa last
+must be provided on each call.
+The
+.Fn strtok_r
+function
+may also be used to nest two parsing loops within one another, as
+long as separate context pointers are used.
+.Pp
+The
+.Fn strtok
+and
+.Fn strtok_r
+functions
+return a pointer to the beginning of each subsequent token in the string,
+after replacing the token itself with a
+.Dv NUL
+character.
+When no more tokens remain, a null pointer is returned.
+.Sh EXAMPLES
+The following uses
+.Fn strtok_r
+to parse two strings using separate contexts:
+.Bd -literal
+char test[80], blah[80];
+char *sep = "\e\e/:;=-";
+char *word, *phrase, *brkt, *brkb;
+
+strcpy(test, "This;is.a:test:of=the/string\e\etokenizer-function.");
+
+for (word = strtok_r(test, sep, &brkt);
+ word;
+ word = strtok_r(NULL, sep, &brkt))
+{
+ strcpy(blah, "blah:blat:blab:blag");
+
+ for (phrase = strtok_r(blah, sep, &brkb);
+ phrase;
+ phrase = strtok_r(NULL, sep, &brkb))
+ {
+ printf("So far we're at %s:%s\en", word, phrase);
+ }
+}
+.Ed
+.Sh SEE ALSO
+.Xr memchr 3 ,
+.Xr strchr 3 ,
+.Xr strcspn 3 ,
+.Xr strpbrk 3 ,
+.Xr strrchr 3 ,
+.Xr strsep 3 ,
+.Xr strspn 3 ,
+.Xr strstr 3 ,
+.Xr wcstok 3
+.Sh STANDARDS
+The
+.Fn strtok
+function
+conforms to
+.St -isoC .
+.Sh AUTHORS
+.An Wes Peters ,
+Softweyr LLC:
+.Aq wes@softweyr.com
+.Pp
+Based on the
+.Fx 3.0
+implementation.
+.Sh BUGS
+The System V
+.Fn strtok ,
+if handed a string containing only delimiter characters,
+will not alter the next starting point, so that a call to
+.Fn strtok
+with a different (or empty) delimiter string
+may return a
+.Pf non- Dv NULL
+value.
+Since this implementation always alters the next starting point,
+such a sequence of calls would always return
+.Dv NULL .
diff --git a/lib/libc/string/strtok.c b/lib/libc/string/strtok.c
new file mode 100644
index 0000000..b0c428b
--- /dev/null
+++ b/lib/libc/string/strtok.c
@@ -0,0 +1,136 @@
+/*-
+ * Copyright (c) 1998 Softweyr LLC. All rights reserved.
+ *
+ * strtok_r, from Berkeley strtok
+ * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
+ *
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notices, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notices, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTWEYR LLC, THE
+ * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strtok.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stddef.h>
+#ifdef DEBUG_STRTOK
+#include <stdio.h>
+#endif
+#include <string.h>
+
+char *__strtok_r(char *, const char *, char **);
+
+__weak_reference(__strtok_r, strtok_r);
+
+char *
+__strtok_r(char *s, const char *delim, char **last)
+{
+ char *spanp, *tok;
+ int c, sc;
+
+ if (s == NULL && (s = *last) == NULL)
+ return (NULL);
+
+ /*
+ * Skip (span) leading delimiters (s += strspn(s, delim), sort of).
+ */
+cont:
+ c = *s++;
+ for (spanp = (char *)delim; (sc = *spanp++) != 0;) {
+ if (c == sc)
+ goto cont;
+ }
+
+ if (c == 0) { /* no non-delimiter characters */
+ *last = NULL;
+ return (NULL);
+ }
+ tok = s - 1;
+
+ /*
+ * Scan token (scan for delimiters: s += strcspn(s, delim), sort of).
+ * Note that delim must have one NUL; we stop if we see that, too.
+ */
+ for (;;) {
+ c = *s++;
+ spanp = (char *)delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == 0)
+ s = NULL;
+ else
+ s[-1] = '\0';
+ *last = s;
+ return (tok);
+ }
+ } while (sc != 0);
+ }
+ /* NOTREACHED */
+}
+
+char *
+strtok(char *s, const char *delim)
+{
+ static char *last;
+
+ return (__strtok_r(s, delim, &last));
+}
+
+#ifdef DEBUG_STRTOK
+/*
+ * Test the tokenizer.
+ */
+int
+main(void)
+{
+ char blah[80], test[80];
+ char *brkb, *brkt, *phrase, *sep, *word;
+
+ sep = "\\/:;=-";
+ phrase = "foo";
+
+ printf("String tokenizer test:\n");
+ strcpy(test, "This;is.a:test:of=the/string\\tokenizer-function.");
+ for (word = strtok(test, sep); word; word = strtok(NULL, sep))
+ printf("Next word is \"%s\".\n", word);
+ strcpy(test, "This;is.a:test:of=the/string\\tokenizer-function.");
+
+ for (word = strtok_r(test, sep, &brkt); word;
+ word = strtok_r(NULL, sep, &brkt)) {
+ strcpy(blah, "blah:blat:blab:blag");
+
+ for (phrase = strtok_r(blah, sep, &brkb); phrase;
+ phrase = strtok_r(NULL, sep, &brkb))
+ printf("So far we're at %s:%s\n", word, phrase);
+ }
+
+ return (0);
+}
+
+#endif /* DEBUG_STRTOK */
diff --git a/lib/libc/string/strxfrm.3 b/lib/libc/string/strxfrm.3
new file mode 100644
index 0000000..5f33763
--- /dev/null
+++ b/lib/libc/string/strxfrm.3
@@ -0,0 +1,96 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strxfrm.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd June 4, 1993
+.Dt STRXFRM 3
+.Os
+.Sh NAME
+.Nm strxfrm
+.Nd transform a string under locale
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In string.h
+.Ft size_t
+.Fn strxfrm "char * restrict dst" "const char * restrict src" "size_t n"
+.Sh DESCRIPTION
+The
+.Fn strxfrm
+function transforms a null-terminated string pointed to by
+.Fa src
+according to the current locale collation if any,
+then copies the transformed string
+into
+.Fa dst .
+Not more than
+.Fa n
+characters are copied into
+.Fa dst ,
+including the terminating null character added.
+If
+.Fa n
+is set to 0
+(it helps to determine an actual size needed
+for transformation),
+.Fa dst
+is permitted to be a NULL pointer.
+.Pp
+Comparing two strings using
+.Fn strcmp
+after
+.Fn strxfrm
+is equal to comparing
+two original strings with
+.Fn strcoll .
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn strxfrm
+returns the length of the transformed string not including
+the terminating null character.
+If this value is
+.Fa n
+or more, the contents of
+.Fa dst
+are indeterminate.
+.Sh SEE ALSO
+.Xr setlocale 3 ,
+.Xr strcmp 3 ,
+.Xr strcoll 3 ,
+.Xr wcsxfrm 3
+.Sh STANDARDS
+The
+.Fn strxfrm
+function
+conforms to
+.St -isoC .
diff --git a/lib/libc/string/strxfrm.c b/lib/libc/string/strxfrm.c
new file mode 100644
index 0000000..b758b0c
--- /dev/null
+++ b/lib/libc/string/strxfrm.c
@@ -0,0 +1,89 @@
+/*-
+ * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
+ * at Electronni Visti IA, Kiev, Ukraine.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <string.h>
+#include "collate.h"
+
+size_t
+strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t loc);
+size_t
+strxfrm(char * __restrict dest, const char * __restrict src, size_t len)
+{
+ return strxfrm_l(dest, src, len, __get_locale());
+}
+
+size_t
+strxfrm_l(char * __restrict dest, const char * __restrict src, size_t len, locale_t locale)
+{
+ int prim, sec, l;
+ size_t slen;
+ char *s, *ss;
+ FIX_LOCALE(locale);
+ struct xlocale_collate *table =
+ (struct xlocale_collate*)locale->components[XLC_COLLATE];
+
+ if (!*src) {
+ if (len > 0)
+ *dest = '\0';
+ return 0;
+ }
+
+ if (table->__collate_load_error)
+ return strlcpy(dest, src, len);
+
+ slen = 0;
+ prim = sec = 0;
+ ss = s = __collate_substitute(table, src);
+ while (*s) {
+ while (*s && !prim) {
+ __collate_lookup(table, s, &l, &prim, &sec);
+ s += l;
+ }
+ if (prim) {
+ if (len > 1) {
+ *dest++ = (char)prim;
+ len--;
+ }
+ slen++;
+ prim = 0;
+ }
+ }
+ free(ss);
+ if (len > 0)
+ *dest = '\0';
+
+ return slen;
+}
diff --git a/lib/libc/string/swab.3 b/lib/libc/string/swab.3
new file mode 100644
index 0000000..0c9deea
--- /dev/null
+++ b/lib/libc/string/swab.3
@@ -0,0 +1,67 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)swab.3 8.1 (Berkeley) 6/4/93
+.\" $FreeBSD$
+.\"
+.Dd March 4, 2012
+.Dt SWAB 3
+.Os
+.Sh NAME
+.Nm swab
+.Nd swap adjacent bytes
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft void
+.Fn swab "const void * restrict src" "void * restrict dst" "ssize_t len"
+.Sh DESCRIPTION
+The function
+.Fn swab
+copies
+.Fa len
+bytes from the location referenced by
+.Fa src
+to the location referenced by
+.Fa dst ,
+swapping adjacent bytes.
+.Pp
+The argument
+.Fa len
+must be an even number.
+If
+.Fa len
+is less than zero, nothing will be done.
+.Sh SEE ALSO
+.Xr bzero 3 ,
+.Xr memset 3
+.Sh HISTORY
+A
+.Fn swab
+function appeared in
+.At v7 .
diff --git a/lib/libc/string/swab.c b/lib/libc/string/swab.c
new file mode 100644
index 0000000..ec6cbf0
--- /dev/null
+++ b/lib/libc/string/swab.c
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Jeffrey Mogul.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)swab.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <unistd.h>
+
+void
+swab(const void * __restrict from, void * __restrict to, ssize_t len)
+{
+ unsigned long temp;
+ int n;
+ char *fp, *tp;
+
+ if (len <= 0)
+ return;
+ n = len >> 1;
+ fp = (char *)from;
+ tp = (char *)to;
+#define STEP temp = *fp++,*tp++ = *fp++,*tp++ = temp
+ /* round to multiple of 8 */
+ for (; n & 0x7; --n)
+ STEP;
+ for (n >>= 3; n > 0; --n) {
+ STEP; STEP; STEP; STEP;
+ STEP; STEP; STEP; STEP;
+ }
+}
diff --git a/lib/libc/string/wcpcpy.c b/lib/libc/string/wcpcpy.c
new file mode 100644
index 0000000..df63d72
--- /dev/null
+++ b/lib/libc/string/wcpcpy.c
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 1999
+ * David E. O'Brien
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcpy.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcpcpy(wchar_t * __restrict to, const wchar_t * __restrict from)
+{
+
+ for (; (*to = *from); ++from, ++to);
+ return(to);
+}
diff --git a/lib/libc/string/wcpncpy.c b/lib/libc/string/wcpncpy.c
new file mode 100644
index 0000000..87b361c
--- /dev/null
+++ b/lib/libc/string/wcpncpy.c
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcpncpy(wchar_t * __restrict dst, const wchar_t * __restrict src, size_t n)
+{
+
+ for (; n--; dst++, src++) {
+ if (!(*dst = *src)) {
+ wchar_t *ret = dst;
+ while (n--)
+ *++dst = L'\0';
+ return (ret);
+ }
+ }
+ return (dst);
+}
diff --git a/lib/libc/string/wcscasecmp.c b/lib/libc/string/wcscasecmp.c
new file mode 100644
index 0000000..0143543
--- /dev/null
+++ b/lib/libc/string/wcscasecmp.c
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+#include <wctype.h>
+
+int
+wcscasecmp(const wchar_t *s1, const wchar_t *s2)
+{
+ wchar_t c1, c2;
+
+ for (; *s1; s1++, s2++) {
+ c1 = towlower(*s1);
+ c2 = towlower(*s2);
+ if (c1 != c2)
+ return ((int)c1 - c2);
+ }
+ return (-*s2);
+}
diff --git a/lib/libc/string/wcscat.c b/lib/libc/string/wcscat.c
new file mode 100644
index 0000000..7ae4e80
--- /dev/null
+++ b/lib/libc/string/wcscat.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcscat.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcscat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcscat(wchar_t * __restrict s1, const wchar_t * __restrict s2)
+{
+ wchar_t *cp;
+
+ cp = s1;
+ while (*cp != L'\0')
+ cp++;
+ while ((*cp++ = *s2++) != L'\0')
+ ;
+
+ return (s1);
+}
diff --git a/lib/libc/string/wcschr.c b/lib/libc/string/wcschr.c
new file mode 100644
index 0000000..1df1fe6
--- /dev/null
+++ b/lib/libc/string/wcschr.c
@@ -0,0 +1,41 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcschr(const wchar_t *s, wchar_t c)
+{
+
+ while (*s != c && *s != L'\0')
+ s++;
+ if (*s == c)
+ return ((wchar_t *)s);
+ return (NULL);
+}
diff --git a/lib/libc/string/wcscmp.c b/lib/libc/string/wcscmp.c
new file mode 100644
index 0000000..2d48914
--- /dev/null
+++ b/lib/libc/string/wcscmp.c
@@ -0,0 +1,56 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strcmp.c 8.1 (Berkeley) 6/4/93";
+#if 0
+__RCSID("$NetBSD: wcscmp.c,v 1.3 2001/01/05 12:13:12 itojun Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+/*
+ * Compare strings.
+ */
+int
+wcscmp(const wchar_t *s1, const wchar_t *s2)
+{
+
+ while (*s1 == *s2++)
+ if (*s1++ == '\0')
+ return (0);
+ /* XXX assumes wchar_t = int */
+ return (*(const unsigned int *)s1 - *(const unsigned int *)--s2);
+}
diff --git a/lib/libc/string/wcscoll.3 b/lib/libc/string/wcscoll.3
new file mode 100644
index 0000000..6a3eedb
--- /dev/null
+++ b/lib/libc/string/wcscoll.3
@@ -0,0 +1,108 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strcoll.3 8.1 (Berkeley) 6/4/93
+.\" FreeBSD: src/lib/libc/string/strcoll.3,v 1.11 2001/10/01 16:09:00 ru Exp
+.\" $FreeBSD$
+.\"
+.Dd October 4, 2002
+.Dt WCSCOLL 3
+.Os
+.Sh NAME
+.Nm wcscoll
+.Nd compare wide strings according to current collation
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft int
+.Fn wcscoll "const wchar_t *s1" "const wchar_t *s2"
+.Sh DESCRIPTION
+The
+.Fn wcscoll
+function compares the null-terminated strings
+.Fa s1
+and
+.Fa s2
+according to the current locale collation order.
+In the
+.Dq Li C
+locale,
+.Fn wcscoll
+is equivalent to
+.Fn wcscmp .
+.Sh RETURN VALUES
+The
+.Fn wcscoll
+function
+returns an integer greater than, equal to, or less than 0,
+if
+.Fa s1
+is greater than, equal to, or less than
+.Fa s2 .
+.Pp
+No return value is reserved to indicate errors;
+callers should set
+.Va errno
+to 0 before calling
+.Fn wcscoll .
+If it is non-zero upon return from
+.Fn wcscoll ,
+an error has occurred.
+.Sh ERRORS
+The
+.Fn wcscoll
+function will fail if:
+.Bl -tag -width Er
+.It Bq Er EILSEQ
+An invalid wide character code was specified.
+.It Bq Er ENOMEM
+Cannot allocate enough memory for temporary buffers.
+.El
+.Sh SEE ALSO
+.Xr setlocale 3 ,
+.Xr strcoll 3 ,
+.Xr wcscmp 3 ,
+.Xr wcsxfrm 3
+.Sh STANDARDS
+The
+.Fn wcscoll
+function
+conforms to
+.St -isoC-99 .
+.Sh BUGS
+The current implementation of
+.Fn wcscoll
+only works in single-byte
+.Dv LC_CTYPE
+locales, and falls back to using
+.Fn wcscmp
+in locales with extended character sets.
diff --git a/lib/libc/string/wcscoll.c b/lib/libc/string/wcscoll.c
new file mode 100644
index 0000000..3c51015
--- /dev/null
+++ b/lib/libc/string/wcscoll.c
@@ -0,0 +1,112 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "collate.h"
+
+static char *__mbsdup(const wchar_t *);
+
+/*
+ * Placeholder implementation of wcscoll(). Attempts to use the single-byte
+ * collation ordering where possible, and falls back on wcscmp() in locales
+ * with extended character sets.
+ */
+int
+wcscoll_l(const wchar_t *ws1, const wchar_t *ws2, locale_t locale)
+{
+ char *mbs1, *mbs2;
+ int diff, sverrno;
+ FIX_LOCALE(locale);
+ struct xlocale_collate *table =
+ (struct xlocale_collate*)locale->components[XLC_COLLATE];
+
+ if (table->__collate_load_error || MB_CUR_MAX > 1)
+ /*
+ * Locale has no special collating order, could not be
+ * loaded, or has an extended character set; do a fast binary
+ * comparison.
+ */
+ return (wcscmp(ws1, ws2));
+
+ if ((mbs1 = __mbsdup(ws1)) == NULL || (mbs2 = __mbsdup(ws2)) == NULL) {
+ /*
+ * Out of memory or illegal wide chars; fall back to wcscmp()
+ * but leave errno indicating the error. Callers that don't
+ * check for error will get a reasonable but often slightly
+ * incorrect result.
+ */
+ sverrno = errno;
+ free(mbs1);
+ errno = sverrno;
+ return (wcscmp(ws1, ws2));
+ }
+
+ diff = strcoll_l(mbs1, mbs2, locale);
+ sverrno = errno;
+ free(mbs1);
+ free(mbs2);
+ errno = sverrno;
+
+ return (diff);
+}
+
+int
+wcscoll(const wchar_t *ws1, const wchar_t *ws2)
+{
+ return wcscoll_l(ws1, ws2, __get_locale());
+}
+
+static char *
+__mbsdup(const wchar_t *ws)
+{
+ static const mbstate_t initial;
+ mbstate_t st;
+ const wchar_t *wcp;
+ size_t len;
+ char *mbs;
+
+ wcp = ws;
+ st = initial;
+ if ((len = wcsrtombs(NULL, &wcp, 0, &st)) == (size_t)-1)
+ return (NULL);
+ if ((mbs = malloc(len + 1)) == NULL)
+ return (NULL);
+ st = initial;
+ wcsrtombs(mbs, &ws, len + 1, &st);
+
+ return (mbs);
+}
diff --git a/lib/libc/string/wcscpy.c b/lib/libc/string/wcscpy.c
new file mode 100644
index 0000000..0c6e1f2
--- /dev/null
+++ b/lib/libc/string/wcscpy.c
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcscpy.c,v 1.2 2000/12/21 04:51:09 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcscpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcscpy(wchar_t * __restrict s1, const wchar_t * __restrict s2)
+{
+ wchar_t *cp;
+
+ cp = s1;
+ while ((*cp++ = *s2++) != L'\0')
+ ;
+
+ return (s1);
+}
diff --git a/lib/libc/string/wcscspn.c b/lib/libc/string/wcscspn.c
new file mode 100644
index 0000000..7729dc8
--- /dev/null
+++ b/lib/libc/string/wcscspn.c
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcscspn.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcscspn.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+size_t
+wcscspn(const wchar_t *s, const wchar_t *set)
+{
+ const wchar_t *p;
+ const wchar_t *q;
+
+ p = s;
+ while (*p) {
+ q = set;
+ while (*q) {
+ if (*p == *q)
+ goto done;
+ q++;
+ }
+ p++;
+ }
+
+done:
+ return (p - s);
+}
diff --git a/lib/libc/string/wcsdup.c b/lib/libc/string/wcsdup.c
new file mode 100644
index 0000000..1e5db92
--- /dev/null
+++ b/lib/libc/string/wcsdup.c
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2005 Tim J. Robbins.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <wchar.h>
+
+wchar_t *
+wcsdup(const wchar_t *s)
+{
+ wchar_t *copy;
+ size_t len;
+
+ len = wcslen(s) + 1;
+ if ((copy = malloc(len * sizeof(wchar_t))) == NULL)
+ return (NULL);
+ return (wmemcpy(copy, s, len));
+}
diff --git a/lib/libc/string/wcslcat.c b/lib/libc/string/wcslcat.c
new file mode 100644
index 0000000..f5f1e1e
--- /dev/null
+++ b/lib/libc/string/wcslcat.c
@@ -0,0 +1,74 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from OpenBSD: strlcat.c,v 1.3 2000/11/24 11:10:02 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcslcat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <wchar.h>
+
+/*
+ * Appends src to string dst of size siz (unlike wcsncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns wcslen(initial dst) + wcslen(src); if retval >= siz,
+ * truncation occurred.
+ */
+size_t
+wcslcat(wchar_t *dst, const wchar_t *src, size_t siz)
+{
+ wchar_t *d = dst;
+ const wchar_t *s = src;
+ size_t n = siz;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (*d != '\0' && n-- != 0)
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return(dlen + wcslen(s));
+ while (*s != '\0') {
+ if (n != 1) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src)); /* count does not include NUL */
+}
diff --git a/lib/libc/string/wcslcpy.c b/lib/libc/string/wcslcpy.c
new file mode 100644
index 0000000..b104a06
--- /dev/null
+++ b/lib/libc/string/wcslcpy.c
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * from OpenBSD: strlcpy.c,v 1.4 1999/05/01 18:56:41 millert Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcslcpy.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <wchar.h>
+
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns wcslen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+wcslcpy(wchar_t *dst, const wchar_t *src, size_t siz)
+{
+ wchar_t *d = dst;
+ const wchar_t *s = src;
+ size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0 && --n != 0) {
+ do {
+ if ((*d++ = *s++) == 0)
+ break;
+ } while (--n != 0);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}
diff --git a/lib/libc/string/wcslen.c b/lib/libc/string/wcslen.c
new file mode 100644
index 0000000..ca3004e
--- /dev/null
+++ b/lib/libc/string/wcslen.c
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcslen.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcslen.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+size_t
+wcslen(const wchar_t *s)
+{
+ const wchar_t *p;
+
+ p = s;
+ while (*p)
+ p++;
+
+ return p - s;
+}
diff --git a/lib/libc/string/wcsncasecmp.c b/lib/libc/string/wcsncasecmp.c
new file mode 100644
index 0000000..a42d98c
--- /dev/null
+++ b/lib/libc/string/wcsncasecmp.c
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+#include <wctype.h>
+
+int
+wcsncasecmp(const wchar_t *s1, const wchar_t *s2, size_t n)
+{
+ wchar_t c1, c2;
+
+ if (n == 0)
+ return (0);
+ for (; *s1; s1++, s2++) {
+ c1 = towlower(*s1);
+ c2 = towlower(*s2);
+ if (c1 != c2)
+ return ((int)c1 - c2);
+ if (--n == 0)
+ return (0);
+ }
+ return (-*s2);
+}
diff --git a/lib/libc/string/wcsncat.c b/lib/libc/string/wcsncat.c
new file mode 100644
index 0000000..44f1ff9
--- /dev/null
+++ b/lib/libc/string/wcsncat.c
@@ -0,0 +1,57 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcsncat.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcsncat.c,v 1.1 2000/12/23 23:14:36 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcsncat(wchar_t * __restrict s1, const wchar_t * __restrict s2, size_t n)
+{
+ wchar_t *p;
+ wchar_t *q;
+ const wchar_t *r;
+
+ p = s1;
+ while (*p)
+ p++;
+ q = p;
+ r = s2;
+ while (*r && n) {
+ *q++ = *r++;
+ n--;
+ }
+ *q = '\0';
+ return s1;
+}
diff --git a/lib/libc/string/wcsncmp.c b/lib/libc/string/wcsncmp.c
new file mode 100644
index 0000000..86d7a51
--- /dev/null
+++ b/lib/libc/string/wcsncmp.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strncmp.c 8.1 (Berkeley) 6/4/93";
+__RCSID("$NetBSD: wcsncmp.c,v 1.3 2001/01/05 12:13:13 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+int
+wcsncmp(const wchar_t *s1, const wchar_t *s2, size_t n)
+{
+
+ if (n == 0)
+ return (0);
+ do {
+ if (*s1 != *s2++) {
+ /* XXX assumes wchar_t = int */
+ return (*(const unsigned int *)s1 -
+ *(const unsigned int *)--s2);
+ }
+ if (*s1++ == 0)
+ break;
+ } while (--n != 0);
+ return (0);
+}
diff --git a/lib/libc/string/wcsncpy.c b/lib/libc/string/wcsncpy.c
new file mode 100644
index 0000000..00d986b
--- /dev/null
+++ b/lib/libc/string/wcsncpy.c
@@ -0,0 +1,64 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strncpy.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+/*
+ * Copy src to dst, truncating or null-padding to always copy n bytes.
+ * Return dst.
+ */
+wchar_t *
+wcsncpy(wchar_t * __restrict dst, const wchar_t * __restrict src, size_t n)
+{
+ if (n != 0) {
+ wchar_t *d = dst;
+ const wchar_t *s = src;
+
+ do {
+ if ((*d++ = *s++) == L'\0') {
+ /* NUL pad the remaining n-1 bytes */
+ while (--n != 0)
+ *d++ = L'\0';
+ break;
+ }
+ } while (--n != 0);
+ }
+ return (dst);
+}
diff --git a/lib/libc/string/wcsnlen.c b/lib/libc/string/wcsnlen.c
new file mode 100644
index 0000000..f03cf76
--- /dev/null
+++ b/lib/libc/string/wcsnlen.c
@@ -0,0 +1,42 @@
+/*-
+ * Copyright (c) 2009 David Schultz <das@FreeBSD.org>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+size_t
+wcsnlen(const wchar_t *s, size_t maxlen)
+{
+ size_t len;
+
+ for (len = 0; len < maxlen; len++, s++) {
+ if (!*s)
+ break;
+ }
+ return (len);
+}
diff --git a/lib/libc/string/wcspbrk.c b/lib/libc/string/wcspbrk.c
new file mode 100644
index 0000000..2ff71ba
--- /dev/null
+++ b/lib/libc/string/wcspbrk.c
@@ -0,0 +1,58 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcspbrk.c,v 1.2 2000/12/21 05:07:25 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcspbrk.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcspbrk(const wchar_t *s, const wchar_t *set)
+{
+ const wchar_t *p;
+ const wchar_t *q;
+
+ p = s;
+ while (*p) {
+ q = set;
+ while (*q) {
+ if (*p == *q) {
+ /* LINTED interface specification */
+ return (wchar_t *)p;
+ }
+ q++;
+ }
+ p++;
+ }
+ return NULL;
+}
diff --git a/lib/libc/string/wcsrchr.c b/lib/libc/string/wcsrchr.c
new file mode 100644
index 0000000..37c81ec
--- /dev/null
+++ b/lib/libc/string/wcsrchr.c
@@ -0,0 +1,47 @@
+/*-
+ * Copyright (c) 2002 Tim J. Robbins
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcsrchr(const wchar_t *s, wchar_t c)
+{
+ const wchar_t *last;
+
+ last = NULL;
+ for (;;) {
+ if (*s == c)
+ last = s;
+ if (*s == L'\0')
+ break;
+ s++;
+ }
+
+ return ((wchar_t *)last);
+}
diff --git a/lib/libc/string/wcsspn.c b/lib/libc/string/wcsspn.c
new file mode 100644
index 0000000..6569206
--- /dev/null
+++ b/lib/libc/string/wcsspn.c
@@ -0,0 +1,60 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wcsspn.c,v 1.1 1999/12/29 21:47:45 tshiozak Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wcsspn.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+size_t
+wcsspn(const wchar_t *s, const wchar_t *set)
+{
+ const wchar_t *p;
+ const wchar_t *q;
+
+ p = s;
+ while (*p) {
+ q = set;
+ while (*q) {
+ if (*p == *q)
+ break;
+ q++;
+ }
+ if (!*q)
+ goto done;
+ p++;
+ }
+
+done:
+ return (p - s);
+}
diff --git a/lib/libc/string/wcsstr.c b/lib/libc/string/wcsstr.c
new file mode 100644
index 0000000..a9dc27b
--- /dev/null
+++ b/lib/libc/string/wcsstr.c
@@ -0,0 +1,63 @@
+/*-
+ * Copyright (c) 1990, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)strstr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+/*
+ * Find the first occurrence of find in s.
+ */
+wchar_t *
+wcsstr(const wchar_t * __restrict s, const wchar_t * __restrict find)
+{
+ wchar_t c, sc;
+ size_t len;
+
+ if ((c = *find++) != L'\0') {
+ len = wcslen(find);
+ do {
+ do {
+ if ((sc = *s++) == L'\0')
+ return (NULL);
+ } while (sc != c);
+ } while (wcsncmp(s, find, len) != 0);
+ s--;
+ }
+ return ((wchar_t *)s);
+}
diff --git a/lib/libc/string/wcstok.3 b/lib/libc/string/wcstok.3
new file mode 100644
index 0000000..0de24d8
--- /dev/null
+++ b/lib/libc/string/wcstok.3
@@ -0,0 +1,133 @@
+.\" Copyright (c) 1998 Softweyr LLC. All rights reserved.
+.\"
+.\" strtok_r, from Berkeley strtok
+.\" Oct 13, 1998 by Wes Peters <wes@softweyr.com>
+.\"
+.\" Copyright (c) 1988, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" the American National Standards Committee X3, on Information
+.\" Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notices, this list of conditions and the following disclaimer.
+.\"
+.\" 2. Redistributions in binary form must reproduce the above
+.\" copyright notices, this list of conditions and the following
+.\" disclaimer in the documentation and/or other materials provided
+.\" with the distribution.
+.\"
+.\" 3. All advertising materials mentioning features or use of this
+.\" software must display the following acknowledgement:
+.\"
+.\" This product includes software developed by Softweyr LLC, the
+.\" University of California, Berkeley, and its contributors.
+.\"
+.\" 4. Neither the name of Softweyr LLC, the University nor the names
+.\" of its contributors may be used to endorse or promote products
+.\" derived from this software without specific prior written
+.\" permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND
+.\" CONTRIBUTORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+.\" INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+.\" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+.\" DISCLAIMED. IN NO EVENT SHALL SOFTWEYR LLC, THE REGENTS, OR
+.\" CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+.\" SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+.\" LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+.\" USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+.\" ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+.\" OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd October 3, 2002
+.Dt WCSTOK 3
+.Os
+.Sh NAME
+.Nm wcstok
+.Nd split wide-character string into tokens
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft wchar_t *
+.Fn wcstok "wchar_t * restrict str" "const wchar_t * restrict sep" "wchar_t ** restrict last"
+.Sh DESCRIPTION
+The
+.Fn wcstok
+function
+is used to isolate sequential tokens in a null-terminated wide character
+string,
+.Fa str .
+These tokens are separated in the string by at least one of the
+characters in
+.Fa sep .
+The first time that
+.Fn wcstok
+is called,
+.Fa str
+should be specified; subsequent calls, wishing to obtain further tokens
+from the same string, should pass a null pointer instead.
+The separator string,
+.Fa sep ,
+must be supplied each time, and may change between calls.
+The context pointer
+.Fa last
+must be provided on each call.
+.Pp
+The
+.Fn wcstok
+function is the wide character counterpart of the
+.Fn strtok_r
+function.
+.Sh RETURN VALUES
+The
+.Fn wcstok
+function
+returns a pointer to the beginning of each subsequent token in the string,
+after replacing the token itself with a null wide character (L'\e0').
+When no more tokens remain, a null pointer is returned.
+.Sh EXAMPLES
+The following code fragment splits a wide character string on
+.Tn ASCII
+space, tab and newline characters and writes the tokens to
+standard output:
+.Bd -literal -offset indent
+const wchar_t *seps = L" \et\en";
+wchar_t *last, *tok, text[] = L" \enone\ettwo\et\etthree \en";
+
+for (tok = wcstok(text, seps, &last); tok != NULL;
+ tok = wcstok(NULL, seps, &last))
+ wprintf(L"%ls\en", tok);
+.Ed
+.Sh COMPATIBILITY
+Some early implementations of
+.Fn wcstok
+omit the
+context pointer argument,
+.Fa last ,
+and maintain state across calls in a static variable like
+.Fn strtok
+does.
+.Sh SEE ALSO
+.Xr strtok 3 ,
+.Xr wcschr 3 ,
+.Xr wcscspn 3 ,
+.Xr wcspbrk 3 ,
+.Xr wcsrchr 3 ,
+.Xr wcsspn 3
+.Sh STANDARDS
+The
+.Fn wcstok
+function
+conforms to
+.St -isoC-99 .
diff --git a/lib/libc/string/wcstok.c b/lib/libc/string/wcstok.c
new file mode 100644
index 0000000..5a77117
--- /dev/null
+++ b/lib/libc/string/wcstok.c
@@ -0,0 +1,86 @@
+/*-
+ * Copyright (c) 1998 Softweyr LLC. All rights reserved.
+ *
+ * strtok_r, from Berkeley strtok
+ * Oct 13, 1998 by Wes Peters <wes@softweyr.com>
+ *
+ * Copyright (c) 1988, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notices, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notices, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY SOFTWEYR LLC, THE REGENTS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+ * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL SOFTWEYR LLC, THE
+ * REGENTS, OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wcstok(wchar_t * __restrict s, const wchar_t * __restrict delim,
+ wchar_t ** __restrict last)
+{
+ const wchar_t *spanp;
+ wchar_t *tok;
+ wchar_t c, sc;
+
+ if (s == NULL && (s = *last) == NULL)
+ return (NULL);
+
+ /*
+ * Skip (span) leading delimiters (s += wcsspn(s, delim), sort of).
+ */
+cont:
+ c = *s++;
+ for (spanp = delim; (sc = *spanp++) != L'\0';) {
+ if (c == sc)
+ goto cont;
+ }
+
+ if (c == L'\0') { /* no non-delimiter characters */
+ *last = NULL;
+ return (NULL);
+ }
+ tok = s - 1;
+
+ /*
+ * Scan token (scan for delimiters: s += wcscspn(s, delim), sort of).
+ * Note that delim must have one NUL; we stop if we see that, too.
+ */
+ for (;;) {
+ c = *s++;
+ spanp = delim;
+ do {
+ if ((sc = *spanp++) == c) {
+ if (c == L'\0')
+ s = NULL;
+ else
+ s[-1] = L'\0';
+ *last = s;
+ return (tok);
+ }
+ } while (sc != L'\0');
+ }
+ /* NOTREACHED */
+}
diff --git a/lib/libc/string/wcswidth.3 b/lib/libc/string/wcswidth.3
new file mode 100644
index 0000000..76d32ad
--- /dev/null
+++ b/lib/libc/string/wcswidth.3
@@ -0,0 +1,62 @@
+.\" Copyright (c) 2002 Tim J. Robbins
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd August 20, 2002
+.Dt WCSWIDTH 3
+.Os
+.Sh NAME
+.Nm wcswidth
+.Nd "number of column positions in wide-character string"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft int
+.Fn wcswidth "const wchar_t *pwcs" "size_t n"
+.Sh DESCRIPTION
+The
+.Fn wcswidth
+function determines the number of column positions required for the first
+.Fa n
+characters of
+.Fa pwcs ,
+or until a null wide character (L'\e0') is encountered.
+.Sh RETURN VALUES
+The
+.Fn wcswidth
+function returns 0 if
+.Fa pwcs
+is an empty string (L""),
+\-1 if a non-printing wide character is encountered,
+otherwise it returns the number of column positions occupied.
+.Sh SEE ALSO
+.Xr iswprint 3 ,
+.Xr wcwidth 3
+.Sh STANDARDS
+The
+.Fn wcswidth
+function conforms to
+.St -p1003.1-2001 .
diff --git a/lib/libc/string/wcswidth.c b/lib/libc/string/wcswidth.c
new file mode 100644
index 0000000..4095c8d
--- /dev/null
+++ b/lib/libc/string/wcswidth.c
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 1989, 1993
+ * The Regents of the University of California. All rights reserved.
+ * (c) UNIX System Laboratories, Inc.
+ * All or some portions of this file are derived from material licensed
+ * to the University of California by American Telephone and Telegraph
+ * Co. or Unix System Laboratories, Inc. and are reproduced herein with
+ * the permission of UNIX System Laboratories, Inc.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Paul Borman at Krystal Technologies.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+#include "xlocale_private.h"
+
+int
+wcswidth_l(const wchar_t *pwcs, size_t n, locale_t locale)
+{
+ wchar_t wc;
+ int len, l;
+ FIX_LOCALE(locale);
+
+ len = 0;
+ while (n-- > 0 && (wc = *pwcs++) != L'\0') {
+ if ((l = wcwidth_l(wc, locale)) < 0)
+ return (-1);
+ len += l;
+ }
+ return (len);
+}
+
+int
+wcswidth(const wchar_t *pwcs, size_t n)
+{
+ return wcswidth_l(pwcs, n, __get_locale());
+}
diff --git a/lib/libc/string/wcsxfrm.3 b/lib/libc/string/wcsxfrm.3
new file mode 100644
index 0000000..b5add9c
--- /dev/null
+++ b/lib/libc/string/wcsxfrm.3
@@ -0,0 +1,122 @@
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)strxfrm.3 8.1 (Berkeley) 6/4/93
+.\" FreeBSD: src/lib/libc/string/strxfrm.3,v 1.16 2002/09/06 11:24:06 tjr Exp
+.\" $FreeBSD$
+.\"
+.Dd October 4, 2002
+.Dt WCSXFRM 3
+.Os
+.Sh NAME
+.Nm wcsxfrm
+.Nd transform a wide string under locale
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft size_t
+.Fn wcsxfrm "wchar_t * restrict dst" "const wchar_t * restrict src" "size_t n"
+.Sh DESCRIPTION
+The
+.Fn wcsxfrm
+function transforms a null-terminated wide character string pointed to by
+.Fa src
+according to the current locale collation order
+then copies the transformed string
+into
+.Fa dst .
+No more than
+.Fa n
+wide characters are copied into
+.Fa dst ,
+including the terminating null character added.
+If
+.Fa n
+is set to 0
+(it helps to determine an actual size needed
+for transformation),
+.Fa dst
+is permitted to be a
+.Dv NULL
+pointer.
+.Pp
+Comparing two strings using
+.Fn wcscmp
+after
+.Fn wcsxfrm
+is equivalent to comparing
+two original strings with
+.Fn wcscoll .
+.Sh RETURN VALUES
+Upon successful completion,
+.Fn wcsxfrm
+returns the length of the transformed string not including
+the terminating null character.
+If this value is
+.Fa n
+or more, the contents of
+.Fa dst
+are indeterminate.
+.Sh SEE ALSO
+.Xr setlocale 3 ,
+.Xr strxfrm 3 ,
+.Xr wcscmp 3 ,
+.Xr wcscoll 3
+.Sh STANDARDS
+The
+.Fn wcsxfrm
+function
+conforms to
+.St -isoC-99 .
+.Sh BUGS
+The current implementation of
+.Fn wcsxfrm
+only works in single-byte
+.Dv LC_CTYPE
+locales, and falls back to using
+.Fn wcsncpy
+in locales with extended character sets.
+.Pp
+Comparing two strings using
+.Fn wcscmp
+after
+.Fn wcsxfrm
+is
+.Em not
+always equivalent to comparison with
+.Fn wcscoll ;
+.Fn wcsxfrm
+only stores information about primary collation weights into
+.Fa dst ,
+whereas
+.Fn wcscoll
+compares characters using both primary and secondary weights.
diff --git a/lib/libc/string/wcsxfrm.c b/lib/libc/string/wcsxfrm.c
new file mode 100644
index 0000000..cea667e
--- /dev/null
+++ b/lib/libc/string/wcsxfrm.c
@@ -0,0 +1,129 @@
+/*-
+ * Copyright (c) 1995 Alex Tatmanjants <alex@elvisti.kiev.ua>
+ * at Electronni Visti IA, Kiev, Ukraine.
+ * All rights reserved.
+ *
+ * Copyright (c) 2011 The FreeBSD Foundation
+ * All rights reserved.
+ * Portions of this software were developed by David Chisnall
+ * under sponsorship from the FreeBSD Foundation.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+#if 0
+__FBSDID("FreeBSD: src/lib/libc/string/strxfrm.c,v 1.15 2002/09/06 11:24:06 tjr Exp ");
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+#include <string.h>
+#include <wchar.h>
+#include "collate.h"
+
+static char *__mbsdup(const wchar_t *);
+
+/*
+ * Placeholder wcsxfrm() implementation. See wcscoll.c for a description of
+ * the logic used.
+ */
+size_t
+wcsxfrm_l(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len, locale_t locale)
+{
+ int prim, sec, l;
+ size_t slen;
+ char *mbsrc, *s, *ss;
+ FIX_LOCALE(locale);
+ struct xlocale_collate *table =
+ (struct xlocale_collate*)locale->components[XLC_COLLATE];
+
+ if (*src == L'\0') {
+ if (len != 0)
+ *dest = L'\0';
+ return (0);
+ }
+
+ if (table->__collate_load_error || MB_CUR_MAX > 1) {
+ slen = wcslen(src);
+ if (len > 0) {
+ if (slen < len)
+ wcscpy(dest, src);
+ else {
+ wcsncpy(dest, src, len - 1);
+ dest[len - 1] = L'\0';
+ }
+ }
+ return (slen);
+ }
+
+ mbsrc = __mbsdup(src);
+ slen = 0;
+ prim = sec = 0;
+ ss = s = __collate_substitute(table, mbsrc);
+ while (*s != '\0') {
+ while (*s != '\0' && prim == 0) {
+ __collate_lookup(table, s, &l, &prim, &sec);
+ s += l;
+ }
+ if (prim != 0) {
+ if (len > 1) {
+ *dest++ = (wchar_t)prim;
+ len--;
+ }
+ slen++;
+ prim = 0;
+ }
+ }
+ free(ss);
+ free(mbsrc);
+ if (len != 0)
+ *dest = L'\0';
+
+ return (slen);
+}
+size_t
+wcsxfrm(wchar_t * __restrict dest, const wchar_t * __restrict src, size_t len)
+{
+ return wcsxfrm_l(dest, src, len, __get_locale());
+}
+
+static char *
+__mbsdup(const wchar_t *ws)
+{
+ static const mbstate_t initial;
+ mbstate_t st;
+ const wchar_t *wcp;
+ size_t len;
+ char *mbs;
+
+ wcp = ws;
+ st = initial;
+ if ((len = wcsrtombs(NULL, &wcp, 0, &st)) == (size_t)-1)
+ return (NULL);
+ if ((mbs = malloc(len + 1)) == NULL)
+ return (NULL);
+ st = initial;
+ wcsrtombs(mbs, &ws, len + 1, &st);
+
+ return (mbs);
+}
diff --git a/lib/libc/string/wmemchr.3 b/lib/libc/string/wmemchr.3
new file mode 100644
index 0000000..30fb091
--- /dev/null
+++ b/lib/libc/string/wmemchr.3
@@ -0,0 +1,174 @@
+.\" $NetBSD: wmemchr.3,v 1.4 2001/01/02 11:26:23 itojun Exp $
+.\"
+.\" Copyright (c) 1990, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" This code is derived from software contributed to Berkeley by
+.\" Chris Torek and the American National Standards Committee X3,
+.\" on Information Processing Systems.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" from: @(#)strcpy.3 8.1 (Berkeley) 6/4/93
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 4, 2009
+.Dt WMEMCHR 3
+.Os
+.Sh NAME
+.Nm wmemchr ,
+.Nm wmemcmp ,
+.Nm wmemcpy ,
+.Nm wmemmove ,
+.Nm wmemset ,
+.Nm wcpcpy ,
+.Nm wcpncpy ,
+.Nm wcscasecmp ,
+.Nm wcscat ,
+.Nm wcschr ,
+.Nm wcscmp ,
+.Nm wcscpy ,
+.Nm wcscspn ,
+.Nm wcsdup ,
+.Nm wcslcat ,
+.Nm wcslcpy ,
+.Nm wcslen ,
+.Nm wcsncasecmp ,
+.Nm wcsncat ,
+.Nm wcsncmp ,
+.Nm wcsncpy ,
+.Nm wcsnlen ,
+.Nm wcspbrk ,
+.Nm wcsrchr ,
+.Nm wcsspn ,
+.Nm wcsstr
+.Nd wide character string manipulation operations
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In wchar.h
+.Ft wchar_t *
+.Fn wmemchr "const wchar_t *s" "wchar_t c" "size_t n"
+.Ft int
+.Fn wmemcmp "const wchar_t *s1" "const wchar_t *s2" "size_t n"
+.Ft wchar_t *
+.Fn wmemcpy "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
+.Ft wchar_t *
+.Fn wmemmove "wchar_t *s1" "const wchar_t *s2" "size_t n"
+.Ft wchar_t *
+.Fn wmemset "wchar_t *s" "wchar_t c" "size_t n"
+.Ft wchar_t *
+.Fn wcpcpy "wchar_t *s1" "wchar_t *s2"
+.Ft wchar_t *
+.Fn wcpncpy "wchar_t *s1" "wchar_t *s2" "size_t n"
+.Ft int
+.Fn wcscasecmp "const wchar_t *s1" "const wchar_t *s2"
+.Ft wchar_t *
+.Fn wcscat "wchar_t * restrict s1" "const wchar_t * restrict s2"
+.Ft wchar_t *
+.Fn wcschr "const wchar_t *s" "wchar_t c"
+.Ft int
+.Fn wcscmp "const wchar_t *s1" "const wchar_t *s2"
+.Ft wchar_t *
+.Fn wcscpy "wchar_t * restrict s1" "const wchar_t * restrict s2"
+.Ft size_t
+.Fn wcscspn "const wchar_t *s1" "const wchar_t *s2"
+.Ft wchar_t *
+.Fn wcsdup "const wchar_t *s"
+.Ft size_t
+.Fn wcslcat "wchar_t *s1" "const wchar_t *s2" "size_t n"
+.Ft size_t
+.Fn wcslcpy "wchar_t *s1" "const wchar_t *s2" "size_t n"
+.Ft size_t
+.Fn wcslen "const wchar_t *s"
+.Ft int
+.Fn wcsncasecmp "const wchar_t *s1" "const wchar_t *s2" "size_t n"
+.Ft wchar_t *
+.Fn wcsncat "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
+.Ft int
+.Fn wcsncmp "const wchar_t *s1" "const wchar_t * s2" "size_t n"
+.Ft wchar_t *
+.Fn wcsncpy "wchar_t * restrict s1" "const wchar_t * restrict s2" "size_t n"
+.Ft size_t
+.Fn wcsnlen "const wchar_t *s" "size_t maxlen"
+.Ft wchar_t *
+.Fn wcspbrk "const wchar_t *s1" "const wchar_t *s2"
+.Ft wchar_t *
+.Fn wcsrchr "const wchar_t *s" "wchar_t c"
+.Ft size_t
+.Fn wcsspn "const wchar_t *s1" "const wchar_t *s2"
+.Ft wchar_t *
+.Fn wcsstr "const wchar_t * restrict s1" "const wchar_t * restrict s2"
+.Sh DESCRIPTION
+The functions implement string manipulation operations over wide character
+strings.
+For a detailed description, refer to documents for the respective single-byte
+counterpart, such as
+.Xr memchr 3 .
+.Sh SEE ALSO
+.Xr memchr 3 ,
+.Xr memcmp 3 ,
+.Xr memcpy 3 ,
+.Xr memmove 3 ,
+.Xr memset 3 ,
+.Xr stpcpy 3 ,
+.Xr stpncpy 3 ,
+.Xr strcasecmp 3 ,
+.Xr strcat 3 ,
+.Xr strchr 3 ,
+.Xr strcmp 3 ,
+.Xr strcpy 3 ,
+.Xr strcspn 3 ,
+.Xr strdup 3 ,
+.Xr strlcat 3 ,
+.Xr strlcpy 3 ,
+.Xr strlen 3 ,
+.Xr strncat 3 ,
+.Xr strncmp 3 ,
+.Xr strncpy 3 ,
+.Xr strnlen 3 ,
+.Xr strpbrk 3 ,
+.Xr strrchr 3 ,
+.Xr strspn 3 ,
+.Xr strstr 3
+.Sh STANDARDS
+These functions conform to
+.St -isoC-99 ,
+with the exception of
+.Fn wcpcpy ,
+.Fn wcpncpy ,
+.Fn wcscasecmp ,
+.Fn wcsdup ,
+.Fn wcsncasecmp ,
+and
+.Fn wcsnlen ,
+which conform to
+.St -p1003.1-2008 ;
+and
+.Fn wcslcat
+and
+.Fn wcslcpy ,
+which are extensions.
diff --git a/lib/libc/string/wmemchr.c b/lib/libc/string/wmemchr.c
new file mode 100644
index 0000000..cab89c9
--- /dev/null
+++ b/lib/libc/string/wmemchr.c
@@ -0,0 +1,52 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wmemchr.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemchr.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wmemchr(const wchar_t *s, wchar_t c, size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ if (*s == c) {
+ /* LINTED const castaway */
+ return (wchar_t *)s;
+ }
+ s++;
+ }
+ return NULL;
+}
diff --git a/lib/libc/string/wmemcmp.c b/lib/libc/string/wmemcmp.c
new file mode 100644
index 0000000..fdb1f986
--- /dev/null
+++ b/lib/libc/string/wmemcmp.c
@@ -0,0 +1,53 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wmemcmp.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemcmp.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+int
+wmemcmp(const wchar_t *s1, const wchar_t *s2, size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ if (*s1 != *s2) {
+ /* wchar might be unsigned */
+ return *s1 > *s2 ? 1 : -1;
+ }
+ s1++;
+ s2++;
+ }
+ return 0;
+}
diff --git a/lib/libc/string/wmemcpy.c b/lib/libc/string/wmemcpy.c
new file mode 100644
index 0000000..c10770c
--- /dev/null
+++ b/lib/libc/string/wmemcpy.c
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wmemcpy.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemcpy.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+#include <wchar.h>
+
+wchar_t *
+wmemcpy(wchar_t * __restrict d, const wchar_t * __restrict s, size_t n)
+{
+ return (wchar_t *)memcpy(d, s, n * sizeof(wchar_t));
+}
diff --git a/lib/libc/string/wmemmove.c b/lib/libc/string/wmemmove.c
new file mode 100644
index 0000000..05cfd10
--- /dev/null
+++ b/lib/libc/string/wmemmove.c
@@ -0,0 +1,44 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wmemmove.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemmove.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <string.h>
+#include <wchar.h>
+
+wchar_t *
+wmemmove(wchar_t *d, const wchar_t *s, size_t n)
+{
+ return (wchar_t *)memmove(d, s, n * sizeof(wchar_t));
+}
diff --git a/lib/libc/string/wmemset.c b/lib/libc/string/wmemset.c
new file mode 100644
index 0000000..0e96356
--- /dev/null
+++ b/lib/libc/string/wmemset.c
@@ -0,0 +1,51 @@
+/*-
+ * Copyright (c)1999 Citrus Project,
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * citrus Id: wmemset.c,v 1.2 2000/12/20 14:08:31 itojun Exp
+ */
+
+#include <sys/cdefs.h>
+#if 0
+#if defined(LIBC_SCCS) && !defined(lint)
+__RCSID("$NetBSD: wmemset.c,v 1.1 2000/12/23 23:14:37 itojun Exp $");
+#endif /* LIBC_SCCS and not lint */
+#endif
+__FBSDID("$FreeBSD$");
+
+#include <wchar.h>
+
+wchar_t *
+wmemset(wchar_t *s, wchar_t c, size_t n)
+{
+ size_t i;
+ wchar_t *p;
+
+ p = (wchar_t *)s;
+ for (i = 0; i < n; i++) {
+ *p = c;
+ p++;
+ }
+ return s;
+}
diff --git a/lib/libc/sys/Makefile.inc b/lib/libc/sys/Makefile.inc
index 09d4016..61d1713 100644
--- a/lib/libc/sys/Makefile.inc
+++ b/lib/libc/sys/Makefile.inc
@@ -18,7 +18,10 @@
# Sources common to both syscall interfaces:
SRCS+= stack_protector.c stack_protector_compat.c __error.c
.if !defined(WITHOUT_SYSCALL_COMPAT)
-SRCS+= fcntl.c ftruncate.c lseek.c mmap.c pread.c pwrite.c truncate.c
+SYSCALL_COMPAT_SRCS= fcntl.c ftruncate.c lseek.c mmap.c pread.c \
+ pwrite.c truncate.c
+SRCS+= ${SYSCALL_COMPAT_SRCS}
+NOASM+= ${SYSCALL_COMPAT_SRCS:S/.c/.o/}
PSEUDO+= _fcntl.o
.endif
SRCS+= sigwait.c
@@ -53,26 +56,35 @@ SYM_MAPS+= ${.CURDIR}/sys/Symbol.map
# Generated files
CLEANFILES+= ${SASM} ${SPSEUDO}
+.if ${MACHINE_CPUARCH} == "amd64" || ${MACHINE_CPUARCH} == "i386" || \
+ ${MACHINE_CPUARCH} == "powerpc"
+NOTE_GNU_STACK='\t.section .note.GNU-stack,"",%%progbits\n'
+.else
+NOTE_GNU_STACK=''
+.endif
+
${SASM}:
printf '#include "compat.h"\n' > ${.TARGET}
printf '#include "SYS.h"\nRSYSCALL(${.PREFIX})\n' >> ${.TARGET}
+ printf ${NOTE_GNU_STACK} >>${.TARGET}
${SPSEUDO}:
printf '#include "compat.h"\n' > ${.TARGET}
printf '#include "SYS.h"\nPSEUDO(${.PREFIX:S/_//})\n' \
>> ${.TARGET}
+ printf ${NOTE_GNU_STACK} >>${.TARGET}
MAN+= abort2.2 accept.2 access.2 acct.2 adjtime.2 \
aio_cancel.2 aio_error.2 aio_read.2 aio_return.2 \
aio_suspend.2 aio_waitcomplete.2 aio_write.2 \
- bind.2 brk.2 chdir.2 chflags.2 \
+ bind.2 brk.2 cap_enter.2 cap_new.2 chdir.2 chflags.2 \
chmod.2 chown.2 chroot.2 clock_gettime.2 close.2 closefrom.2 \
connect.2 cpuset.2 cpuset_getaffinity.2 dup.2 execve.2 _exit.2 \
- extattr_get_file.2 fcntl.2 fhopen.2 flock.2 fork.2 fsync.2 \
+ extattr_get_file.2 fcntl.2 ffclock.2 fhopen.2 flock.2 fork.2 fsync.2 \
getdirentries.2 getdtablesize.2 \
getfh.2 getfsstat.2 getgid.2 getgroups.2 getitimer.2 getlogin.2 \
- getpeername.2 getpgrp.2 getpid.2 getpriority.2 getrlimit.2 \
- getrusage.2 getsid.2 getsockname.2 \
+ getloginclass.2 getpeername.2 getpgrp.2 getpid.2 getpriority.2 \
+ getrlimit.2 getrusage.2 getsid.2 getsockname.2 \
getsockopt.2 gettimeofday.2 getuid.2 \
intro.2 ioctl.2 issetugid.2 jail.2 kenv.2 kill.2 \
kldfind.2 kldfirstmod.2 kldload.2 kldnext.2 kldstat.2 kldsym.2 \
@@ -84,7 +96,8 @@ MAN+= abort2.2 accept.2 access.2 acct.2 adjtime.2 \
mq_setattr.2 \
msgctl.2 msgget.2 msgrcv.2 msgsnd.2 \
msync.2 munmap.2 nanosleep.2 nfssvc.2 ntp_adjtime.2 open.2 \
- pathconf.2 pipe.2 poll.2 posix_openpt.2 profil.2 \
+ pathconf.2 pdfork.2 pipe.2 poll.2 posix_fadvise.2 posix_fallocate.2 \
+ posix_openpt.2 profil.2 \
pselect.2 ptrace.2 quotactl.2 \
read.2 readlink.2 reboot.2 recv.2 rename.2 revoke.2 rfork.2 rmdir.2 \
rtprio.2
@@ -106,6 +119,8 @@ MAN+= sctp_generic_recvmsg.2 sctp_generic_sendmsg.2 sctp_peeloff.2 \
MLINKS+=access.2 eaccess.2 access.2 faccessat.2
MLINKS+=brk.2 sbrk.2
+MLINKS+=cap_enter.2 cap_getmode.2
+MLINKS+=cap_new.2 cap_getrights.2
MLINKS+=chdir.2 fchdir.2
MLINKS+=chflags.2 fchflags.2 chflags.2 lchflags.2
MLINKS+=chmod.2 fchmod.2 chmod.2 fchmodat.2 chmod.2 lchmod.2
@@ -127,6 +142,8 @@ MLINKS+=extattr_get_file.2 extattr.2 \
extattr_get_file.2 extattr_set_fd.2 \
extattr_get_file.2 extattr_set_file.2 \
extattr_get_file.2 extattr_set_link.2
+MLINKS+=ffclock.2 ffclock_getcounter.2 ffclock.2 ffclock_getestimate.2 \
+ ffclock.2 ffclock_setestimate.2
MLINKS+=fhopen.2 fhstat.2 fhopen.2 fhstatfs.2
MLINKS+=getdirentries.2 getdents.2
MLINKS+=getfh.2 lgetfh.2
@@ -134,6 +151,7 @@ MLINKS+=getgid.2 getegid.2
MLINKS+=getitimer.2 setitimer.2
MLINKS+=getlogin.2 getlogin_r.3
MLINKS+=getlogin.2 setlogin.2
+MLINKS+=getloginclass.2 setloginclass.2
MLINKS+=getpgrp.2 getpgid.2
MLINKS+=getpid.2 getppid.2
MLINKS+=getpriority.2 setpriority.2
@@ -147,7 +165,7 @@ MLINKS+=jail.2 jail_attach.2 \
jail.2 jail_remove.2 \
jail.2 jail_set.2
MLINKS+=kldunload.2 kldunloadf.2
-MLINKS+=kqueue.2 kevent.2
+MLINKS+=kqueue.2 kevent.2 kqueue.2 EV_SET.3
MLINKS+=link.2 linkat.2
MLINKS+=madvise.2 posix_madvise.2
MLINKS+=mkdir.2 mkdirat.2
@@ -163,10 +181,14 @@ MLINKS+=ntp_adjtime.2 ntp_gettime.2
MLINKS+=open.2 openat.2
MLINKS+=pathconf.2 fpathconf.2
MLINKS+=pathconf.2 lpathconf.2
+MLINKS+=pdfork.2 pdgetpid.2\
+ pdfork.2 pdkill.2 \
+ pdfork.2 pdwait4.2
MLINKS+=read.2 pread.2 read.2 preadv.2 read.2 readv.2
MLINKS+=readlink.2 readlinkat.2
MLINKS+=recv.2 recvfrom.2 recv.2 recvmsg.2
MLINKS+=rename.2 renameat.2
+MLINKS+=rtprio.2 rtprio_thread.2
.if !defined(NO_P1003_1B)
MLINKS+=sched_get_priority_max.2 sched_get_priority_min.2 \
sched_get_priority_max.2 sched_rr_get_interval.2
diff --git a/lib/libc/sys/Symbol.map b/lib/libc/sys/Symbol.map
index 74751f9..f1c1567 100644
--- a/lib/libc/sys/Symbol.map
+++ b/lib/libc/sys/Symbol.map
@@ -360,6 +360,31 @@ FBSD_1.1 {
unlinkat;
};
+FBSD_1.2 {
+ cap_enter;
+ cap_getmode;
+ cap_new;
+ cap_getrights;
+ ffclock_getcounter;
+ ffclock_getestimate;
+ ffclock_setestimate;
+ getloginclass;
+ pdfork;
+ pdgetpid;
+ pdkill;
+ posix_fallocate;
+ rctl_get_racct;
+ rctl_get_rules;
+ rctl_get_limits;
+ rctl_add_rule;
+ rctl_remove_rule;
+ setloginclass;
+};
+
+FBSD_1.3 {
+ posix_fadvise;
+};
+
FBSDprivate_1.0 {
___acl_aclcheck_fd;
__sys___acl_aclcheck_fd;
diff --git a/lib/libc/sys/cap_enter.2 b/lib/libc/sys/cap_enter.2
new file mode 100644
index 0000000..5454ec9
--- /dev/null
+++ b/lib/libc/sys/cap_enter.2
@@ -0,0 +1,102 @@
+.\"
+.\" Copyright (c) 2008-2009 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed at the University of Cambridge Computer
+.\" Laboratory with support from a grant from Google, Inc.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 25, 2012
+.Dt CAP_ENTER 2
+.Os
+.Sh NAME
+.Nm cap_enter ,
+.Nm cap_getmode
+.Nd Capability mode system calls
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/capability.h
+.Ft int
+.Fn cap_enter "void"
+.Ft int
+.Fn cap_getmode "u_int *modep"
+.Sh DESCRIPTION
+.Fn cap_enter
+places the current process into capability mode, a mode of execution in which
+processes may only issue system calls operating on file descriptors or
+reading limited global system state.
+Access to global name spaces, such as file system or IPC name spaces, is
+prevented.
+If the process is already in a capability mode sandbox, the system call is a
+no-op.
+Future process descendants create with
+.Xr fork 2
+or
+.Xr pdfork 2
+will be placed in capability mode from inception.
+.Pp
+When combined with capabilities created with
+.Xr cap_new 2 ,
+.Fn cap_enter
+may be used to create kernel-enforced sandboxes in which
+appropriately-crafted applications or application components may be run.
+.Pp
+.Fn cap_getmode
+returns a flag indicating whether or not the process is in a capability mode
+sandbox.
+.Sh CAVEAT
+Creating effective process sandboxes is a tricky process that involves
+identifying the least possible rights required by the process and then
+passing those rights into the process in a safe manner.
+See the CAVEAT
+section of
+.Xr cap_new 2
+for why this is particularly tricky with UNIX file descriptors as the
+canonical representation of a right.
+Consumers of
+.Fn cap_enter
+should also be aware of other inherited rights, such as access to VM
+resources, memory contents, and other process properties that should be
+considered.
+It is advisable to use
+.Xr fexecve 2
+to create a runtime environment inside the sandbox that has as few implicitly
+acquired rights as possible.
+.Sh RETURN VALUES
+.Rv -std cap_enter cap_getmode
+.Sh SEE ALSO
+.Xr cap_new 2 ,
+.Xr fexecve 2 ,
+.Xr capsicum 4
+.Sh HISTORY
+Support for capabilities and capabilities mode was developed as part of the
+.Tn TrustedBSD
+Project.
+.Sh AUTHORS
+These functions and the capability facility were created by
+.An "Robert N. M. Watson"
+at the University of Cambridge Computer Laboratory with support from a grant
+from Google, Inc.
diff --git a/lib/libc/sys/cap_new.2 b/lib/libc/sys/cap_new.2
new file mode 100644
index 0000000..a18fd3b
--- /dev/null
+++ b/lib/libc/sys/cap_new.2
@@ -0,0 +1,475 @@
+.\"
+.\" Copyright (c) 2008-2010 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed at the University of Cambridge Computer
+.\" Laboratory with support from a grant from Google, Inc.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd July 20, 2011
+.Dt CAP_NEW 2
+.Os
+.Sh NAME
+.Nm cap_new ,
+.Nm cap_getrights
+.Nd System calls to manipulate capabilities
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/capability.h
+.Ft int
+.Fn cap_new "int fd" "cap_rights_t rights"
+.Ft int
+.Fn cap_getrights "int fd" "cap_rights_t *rightsp"
+.Sh DESCRIPTION
+Capabilities are special file descriptors derived from an existing file
+descriptor, such as one returned by
+.Xr fhopen 2 ,
+.Xr kqueue 2 ,
+.Xr mq_open 2 ,
+.Xr open 2 ,
+.Xr pipe 2 ,
+.Xr shm_open 2 ,
+.Xr socket 2 ,
+or
+.Xr socketpair 2 ,
+but with a restricted set of permitted operations determined by a rights
+mask set when the capability is created.
+These restricted rights cannot be changed after the capability is created,
+although further capabilities with yet more restricted rights may be created
+from an existing capability.
+In every other sense, a capability behaves in the same way as the file
+descriptor it was created from.
+.Pp
+.Fn cap_new
+creates a new capability for the existing file descriptor
+.Fa fd ,
+and returns a file descriptor for it.
+Operations on the capability will be limited to those permitted by
+.Fa rights ,
+which is static for the lifetime of the capability.
+If
+.Fa fd
+refers to an existing capability, then
+.Fa rights
+must be equal to or a subset of the rights on that capability.
+As with
+.Xr dup 2
+and
+.Xr dup2 2 ,
+many properties are shared between the new capability and the existing file
+descriptor, including open file flags, blocking disposition, and file offset.
+Many applications will prefer to use the
+.Xr cap_limitfd 3
+library call, part of
+.Xr libcapsicum 3 ,
+as it offers a more convenient interface.
+.Pp
+.Fn cap_getrights
+queries the rights associated with the capability referred to by file
+descriptor
+.Fa fd .
+.Pp
+These system calls, when combined with
+.Xr cap_enter 2 ,
+may be used to construct process sandboxes with highly granular rights
+assignment.
+.Sh RIGHTS
+The following rights may be specified in a new capability rights mask:
+.Bl -tag -width CAP_EXTATTR_DELETE
+.It Dv CAP_ACCEPT
+Permit
+.Xr accept 2 .
+.It Dv CAP_ACL_CHECK
+Permit checking of an ACL on a file descriptor; there is no cross-reference
+for this system call.
+.It Dv CAP_ACL_DELETE
+Permit
+.Xr acl_delete_fd_np 3 .
+.It Dv CAP_ACL_GET
+Permit
+.Xr acl_get_fd 3
+and
+.Xr acl_get_fd_np 3 .
+.It Dv CAP_ACL_SET
+Permit
+.Xr acl_set_fd 3
+and
+.Xr acl_set_fd_np 3 .
+.It Dv CAP_BIND
+Permit
+.Xr bind 2 .
+Note that sockets can also become bound implicitly as a result of
+.Xr connect 2
+or
+.Xr send 2 ,
+and that socket options set with
+.Xr setsockopt 2
+may also affect binding behavior.
+.It Dv CAP_CONNECT
+Permit
+.Xr connect 2 ;
+also required for
+.Xr sendto 2
+with a non-NULL destination address.
+.It Dv CAP_EVENT
+Permit
+.Xr select 2 ,
+.Xr poll 2 ,
+and
+.Xr kevent 2
+to be used in monitoring the file descriptor for events.
+.It Dv CAP_FEXECVE
+Permit
+.Xr fexecve 2 ;
+.Dv CAP_READ
+will also be required.
+.It Dv CAP_EXTATTR_DELETE
+Permit
+.Xr extattr_delete_fd 2 .
+.It Dv CAP_EXTATTR_GET
+Permit
+.Xr extattr_get_fd 2 .
+.It Dv CAP_EXTATTR_LIST
+Permit
+.Xr extattr_list_fd 2 .
+.It Dv CAP_EXTATTR_SET
+Permit
+.Xr extattr_set_fd 2 .
+.It Dv CAP_FCHDIR
+Permit
+.Xr fchdir 2 .
+.It Dv CAP_FCHFLAGS
+Permit
+.Xr fchflags 2 .
+.It Dv CAP_FCHMOD
+Permit
+.Xr fchmod 2 .
+.It Dv CAP_FCHOWN
+Permit
+.Xr fchown 2 .
+.It Dv CAP_FCNTL
+Permit
+.Xr fcntl 2 ;
+be aware that this call provides indirect access to other operations, such as
+.Xr flock 2 .
+.It Dv CAP_FLOCK
+Permit
+.Xr flock 2
+and related calls.
+.It Dv CAP_FPATHCONF
+Permit
+.Xr fpathconf 2 .
+.It Dv CAP_FSCK
+Permit UFS background-fsck operations on the descriptor.
+.It Dv CAP_FSTAT
+Permit
+.Xr fstat 2 .
+.It Dv CAP_FSTATFS
+Permit
+.Xr fstatfs 2 .
+.It Dv CAP_FSYNC
+Permit
+.Xr aio_fsync 2
+and
+.Xr fsync 2 .
+.Pp
+.It Dv CAP_FTRUNCATE
+Permit
+.Xr ftruncate 2 .
+.It Dv CAP_FUTIMES
+Permit
+.Xr futimes 2 .
+.It Dv CAP_GETPEERNAME
+Permit
+.Xr getpeername 2 .
+.It Dv CAP_GETSOCKNAME
+Permit
+.Xr getsockname 2 .
+.It Dv CAP_GETSOCKOPT
+Permit
+.Xr getsockopt 2 .
+.It Dv CAP_IOCTL
+Permit
+.Xr ioctl 2 .
+Be aware that this system call has enormous scope, including potentially
+global scope for some objects.
+.It Dv CAP_KEVENT
+Permit
+.Xr kevent 2 ;
+.Dv CAP_EVENT
+is also required on file descriptors that will be monitored using
+.Xr kevent 2 .
+.It Dv CAP_LISTEN
+Permit
+.Xr listen 2 ;
+not much use (generally) without
+.Dv CAP_BIND .
+.It Dv CAP_LOOKUP
+Permit the file descriptor to be used as a starting directory for calls such
+as
+.Xr linkat 2 ,
+.Xr openat 2 ,
+and
+.Xr unlinkat 2 .
+Note that these calls are not available in capability mode as they manipulate
+a global name space; see
+.Xr cap_enter 2
+for details.
+.It Dv CAP_MAC_GET
+Permit
+.Xr mac_get_fd 3 .
+.It Dv CAP_MAC_SET
+Permit
+.Xr mac_set_fd 3 .
+.It Dv CAP_MMAP
+Permit
+.Xr mmap 2 ;
+specific invocations may also require
+.Dv CAP_READ
+or
+.Dv CAP_WRITE .
+.Pp
+.It Dv CAP_PDGETPID
+Permit
+.Xr pdgetpid 2 .
+.It Dv CAP_PDKILL
+Permit
+.Xr pdkill 2 .
+.It Dv CAP_PDWAIT
+Permit
+.Xr pdwait4 2 .
+.It Dv CAP_PEELOFF
+Permit
+.Xr sctp_peeloff 2 .
+.It Dv CAP_READ
+Allow
+.Xr aio_read 2 ,
+.Xr pread 2 ,
+.Xr read 2 ,
+.Xr recv 2 ,
+.Xr recvfrom 2 ,
+.Xr recvmsg 2 ,
+and related system calls.
+.Pp
+For files and other seekable objects,
+.Dv CAP_SEEK
+may also be required.
+.It Dv CAP_REVOKE
+Permit
+.Xr frevoke 2
+in certain ABI compatibility modes that support this system call.
+.It Dv CAP_SEEK
+Permit operations that seek on the file descriptor, such as
+.Xr lseek 2 ,
+but also required for I/O system calls that modify the file offset, such as
+.Xr read 2
+and
+.Xr write 2 .
+.It Dv CAP_SEM_GETVALUE
+Permit
+.Xr sem_getvalue 3 .
+.It Dv CAP_SEM_POST
+Permit
+.Xr sem_post 3 .
+.It Dv CAP_SEM_WAIT
+Permit
+.Xr sem_wait 3
+and
+.Xr sem_trywait 3 .
+.It Dv CAP_SETSOCKOPT
+Permit
+.Xr setsockopt 2 ;
+this controls various aspects of socket behavior and may affect binding,
+connecting, and other behaviors with global scope.
+.It Dv CAP_SHUTDOWN
+Permit explicit
+.Xr shutdown 2 ;
+closing the socket will also generally shut down any connections on it.
+.It Dv CAP_TTYHOOK
+Allow configuration of TTY hooks, such as
+.Xr snp 4 ,
+on the file descriptor.
+.It Dv CAP_WRITE
+Allow
+.Xr aio_write 2 ,
+.Xr pwrite 2 ,
+.Xr send 2 ,
+.Xr sendmsg 2 ,
+.Xr sendto 2 ,
+.Xr write 2 ,
+and related system calls.
+.Pp
+For files and other seekable objects,
+.Dv CAP_SEEK
+may also be required.
+.Pp
+For
+.Xr sendto 2
+with a non-NULL connection address,
+.Dv CAP_CONNECT
+is also required.
+.El
+.Sh CAVEAT
+The
+.Fn cap_new
+system call and the capabilities it creates may be used to assign
+fine-grained rights to sandboxed processes running in capability mode.
+However, the semantics of objects accessed via file descriptors are complex,
+so caution should be exercised in passing object capabilities into sandboxes.
+.Sh RETURN VALUES
+If successful,
+.Fn cap_new
+returns a non-negative integer, termed a file descriptor.
+It returns -1 on failure, and sets
+.Va errno
+to indicate the error.
+.Pp
+.Rv -std cap_getrights
+.Sh ERRORS
+.Fn cap_new
+may return the following errors:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa fd
+argument is not a valid active descriptor.
+.It Bq Er EINVAL
+An invalid right has been requested in
+.Fa rights .
+.It Bq Er EMFILE
+The process has already reached its limit for open file descriptors.
+.It Bq Er ENFILE
+The system file table is full.
+.It Bq Er EPERM
+.Fa rights
+contains requested rights not present in the current rights mask associated
+with the capability referenced by
+.Fa fd ,
+if any.
+.El
+.Pp
+.Fn cap_getrights
+may return the following errors:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa fd
+argument is not a valid active descriptor.
+.It Bq Er EINVAL
+The
+.Fa fd
+argument is not a capability.
+.El
+.Sh SEE ALSO
+.Xr accept 2 ,
+.Xr aio_fsync 2 ,
+.Xr aio_read 2 ,
+.Xr aio_write 2 ,
+.Xr bind 2 ,
+.Xr cap_enter 2 ,
+.Xr connect 2 ,
+.Xr dup 2 ,
+.Xr dup2 2 ,
+.Xr extattr_delete_fd 2 ,
+.Xr extattr_get_fd 2 ,
+.Xr extattr_list_fd 2 ,
+.Xr extattr_set_fd 2 ,
+.Xr fchflags 2 ,
+.Xr fchown 2 ,
+.Xr fcntl 2 ,
+.Xr fexecve 2 ,
+.Xr fhopen 2 ,
+.Xr flock 2 ,
+.Xr fpathconf 2 ,
+.Xr fstat 2 ,
+.Xr fstatfs 2 ,
+.Xr fsync 2 ,
+.Xr ftruncate 2 ,
+.Xr futimes 2 ,
+.Xr getpeername 2 ,
+.Xr getsockname 2 ,
+.Xr getsockopt 2 ,
+.Xr ioctl 2 ,
+.Xr kevent 2 ,
+.Xr kqueue 2 ,
+.Xr linkat 2 ,
+.Xr listen 2 ,
+.Xr mmap 2 ,
+.Xr mq_open 2 ,
+.Xr open 2 ,
+.Xr openat 2 ,
+.Xr pdgetpid 2 ,
+.Xr pdkill 2 ,
+.Xr pdwait4 2 ,
+.Xr pipe 2 ,
+.Xr poll 2 ,
+.Xr pread 2 ,
+.Xr pwrite 2 ,
+.Xr read 2 ,
+.Xr recv 2 ,
+.Xr recvfrom 2 ,
+.Xr recvmsg 2 ,
+.Xr sctp_peeloff 2 ,
+.Xr select 2 ,
+.Xr send 2 ,
+.Xr sendmsg 2 ,
+.Xr sendto 2 ,
+.Xr setsockopt 2 ,
+.Xr shm_open 2 ,
+.Xr shutdown 2 ,
+.Xr socket 2 ,
+.Xr socketpair 2 ,
+.Xr unlinkat 2 ,
+.Xr write 2 ,
+.Xr acl_delete_fd_np 3 ,
+.Xr acl_get_fd 3 ,
+.Xr acl_get_fd_np 3 ,
+.Xr acl_set_fd_np 3 ,
+.Xr cap_limitfd 3 ,
+.Xr libcapsicum 3 ,
+.Xr mac_get_fd 3 ,
+.Xr mac_set_fd 3 ,
+.Xr sem_getvalue 3 ,
+.Xr sem_post 3 ,
+.Xr sem_trywait 3 ,
+.Xr sem_wait 3 ,
+.Xr capsicum 4 ,
+.Xr snp 4
+.Sh HISTORY
+Support for capabilities and capabilities mode was developed as part of the
+.Tn TrustedBSD
+Project.
+.Sh AUTHORS
+These functions and the capability facility were created by
+.An "Robert N. M. Watson"
+at the University of Cambridge Computer Laboratory with support from a grant
+from Google, Inc.
+.Sh BUGS
+This man page should list the set of permitted system calls more specifically
+for each capability right.
+.Pp
+Capability rights sometimes have unclear indirect impacts, which should be
+documented, or at least hinted at.
diff --git a/lib/libc/sys/chflags.2 b/lib/libc/sys/chflags.2
index 7780427..1c2eb78 100644
--- a/lib/libc/sys/chflags.2
+++ b/lib/libc/sys/chflags.2
@@ -28,7 +28,7 @@
.\" @(#)chflags.2 8.3 (Berkeley) 5/2/95
.\" $FreeBSD$
.\"
-.Dd May 16, 2006
+.Dd Apr 13, 2012
.Dt CHFLAGS 2
.Os
.Sh NAME
@@ -114,8 +114,7 @@ The
and
.Dv SF_ARCHIVED
flags may only be set or unset by the super-user.
-Attempts to set these flags by non-super-users are rejected, attempts by
-non-superusers to clear flags that are already unset are silently ignored.
+Attempts to toggle these flags by non-super-users are rejected.
These flags may be set at any time, but normally may only be unset when
the system is in single-user mode.
(See
@@ -124,7 +123,7 @@ for details.)
.Pp
The
.Dv SF_SNAPSHOT
-flag is maintained by the system and cannot be changed by any user.
+flag is maintained by the system and cannot be toggled.
.Sh RETURN VALUES
.Rv -std
.Sh ERRORS
@@ -154,12 +153,12 @@ or
is set and the user is either not the super-user or
securelevel is greater than 0.
.It Bq Er EPERM
-A non-super-user tries to set one of
-.Dv SF_IMMUTABLE , SF_APPEND ,
+A non-super-user attempted to toggle one of
+.Dv SF_ARCHIVED , SF_IMMUTABLE , SF_APPEND ,
or
.Dv SF_NOUNLINK .
.It Bq Er EPERM
-User tries to set or remove the
+An attempt was made to toggle the
.Dv SF_SNAPSHOT
flag.
.It Bq Er EROFS
@@ -174,7 +173,9 @@ An
.Tn I/O
error occurred while reading from or writing to the file system.
.It Bq Er EOPNOTSUPP
-The underlying file system does not support file flags.
+The underlying file system does not support file flags, or
+does not support all of the flags set in
+.Fa flags .
.El
.Pp
The
@@ -199,10 +200,14 @@ or
is set and the user is either not the super-user or
securelevel is greater than 0.
.It Bq Er EPERM
-A non-super-user tries to set one of
-.Dv SF_IMMUTABLE , SF_APPEND ,
+A non-super-user attempted to toggle one of
+.Dv SF_ARCHIVED , SF_IMMUTABLE , SF_APPEND ,
or
.Dv SF_NOUNLINK .
+.It Bq Er EPERM
+An attempt was made to toggle the
+.Dv SF_SNAPSHOT
+flag.
.It Bq Er EROFS
The file resides on a read-only file system.
.It Bq Er EIO
@@ -210,7 +215,9 @@ An
.Tn I/O
error occurred while reading from or writing to the file system.
.It Bq Er EOPNOTSUPP
-The underlying file system does not support file flags.
+The underlying file system does not support file flags, or
+does not support all of the flags set in
+.Fa flags .
.El
.Sh SEE ALSO
.Xr chflags 1 ,
diff --git a/lib/libc/sys/chmod.2 b/lib/libc/sys/chmod.2
index 3547aec..997df88e 100644
--- a/lib/libc/sys/chmod.2
+++ b/lib/libc/sys/chmod.2
@@ -161,7 +161,7 @@ The sticky bit may be
set by any user on a directory which the user owns or has appropriate
permissions.
For more details of the properties of the sticky bit, see
-.Xr sticky 8 .
+.Xr sticky 7 .
.Pp
If mode ISUID (set UID) is set on a directory,
and the MNT_SUIDDIR option was used in the mount of the file system,
@@ -289,7 +289,7 @@ nor a file descriptor associated with a directory.
.Xr chown 2 ,
.Xr open 2 ,
.Xr stat 2 ,
-.Xr sticky 8
+.Xr sticky 7
.Sh STANDARDS
The
.Fn chmod
diff --git a/lib/libc/sys/chroot.2 b/lib/libc/sys/chroot.2
index ecf2eb5..060d064 100644
--- a/lib/libc/sys/chroot.2
+++ b/lib/libc/sys/chroot.2
@@ -28,7 +28,7 @@
.\" @(#)chroot.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd June 4, 1993
+.Dd January 3, 2012
.Dt CHROOT 2
.Os
.Sh NAME
@@ -134,9 +134,27 @@ The
.Fn chroot
system call appeared in
.Bx 4.2 .
+It was marked as
+.Dq legacy
+in
+.St -susv2 ,
+and was removed in subsequent standards.
.Sh BUGS
If the process is able to change its working directory to the target
directory, but another access control check fails (such as a check for
open directories, or a MAC check), it is possible that this system
call may return an error, with the working directory of the process
left changed.
+.Sh SECURITY CONSIDERATIONS
+The system have many hardcoded paths to files where it may load after
+the process starts.
+It is generally recommended to drop privileges immediately after a
+successful
+.Nm
+call,
+and restrict write access to a limited subtree of the
+.Nm
+root,
+for instance,
+setup the sandbox so that the sandboxed user will have no write
+access to any well-known system directories.
diff --git a/lib/libc/sys/close.2 b/lib/libc/sys/close.2
index 524322b..c3a0972 100644
--- a/lib/libc/sys/close.2
+++ b/lib/libc/sys/close.2
@@ -28,7 +28,7 @@
.\" @(#)close.2 8.2 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
-.Dd December 4, 2006
+.Dd January 22, 2012
.Dt CLOSE 2
.Os
.Sh NAME
@@ -118,6 +118,10 @@ The underlying object did not fit, cached data was lost.
The underlying object was a stream socket that was shut down by the peer
before all pending data was delivered.
.El
+.Pp
+In case of any error except
+.Er EBADF ,
+the supplied file descriptor is deallocated and therefore is no longer valid.
.Sh SEE ALSO
.Xr accept 2 ,
.Xr closefrom 2 ,
diff --git a/lib/libc/sys/cpuset.2 b/lib/libc/sys/cpuset.2
index 1cdff68..652d3ae 100644
--- a/lib/libc/sys/cpuset.2
+++ b/lib/libc/sys/cpuset.2
@@ -77,7 +77,7 @@ while application developers will manipulate anonymous sets using
To select the correct set a value of type
.Ft cpulevel_t
is used.
-The following values for
+The following values for
.Fa level
are supported:
.Bl -column CPU_LEVEL_CPUSET -offset indent
@@ -137,7 +137,7 @@ Children inherit this set after a call to
.Xr fork 2 .
.Pp
.Fn cpuset_setid
-attempts to set the id of the object specified by the
+attempts to set the id of the object specified by the
.Fa which
argument.
Currently
@@ -149,12 +149,12 @@ Upon successful completion all of the threads in the target process will
be running on CPUs permitted by the set.
.Pp
.Fn cpuset_getid
-retrieves a set id from the object indicated by
+retrieves a set id from the object indicated by
.Fa which
and stores it in the space pointed to by
.Fa setid .
The retrieved id may be that of either the root or assigned set
-depending on the value of
+depending on the value of
.Fa level .
.Fa level
should be
diff --git a/lib/libc/sys/cpuset_getaffinity.2 b/lib/libc/sys/cpuset_getaffinity.2
index 5c75b92..4fbbc4e 100644
--- a/lib/libc/sys/cpuset_getaffinity.2
+++ b/lib/libc/sys/cpuset_getaffinity.2
@@ -45,7 +45,7 @@
.Fn cpuset_getaffinity
and
.Fn cpuset_setaffinity
-allow the manipulation of sets of CPUs available to processes, threads,
+allow the manipulation of sets of CPUs available to processes, threads,
interrupts, jails and other resources.
These functions may manipulate sets of CPUs that contain many processes
or per-object anonymous masks that effect only a single object.
@@ -108,7 +108,6 @@ and
.Fa id
to the value in
.Fa mask .
-.Pp
.Sh RETURN VALUES
.Rv -std
.Sh ERRORS
diff --git a/lib/libc/sys/dup.2 b/lib/libc/sys/dup.2
index c87b386..d2a4b7e 100644
--- a/lib/libc/sys/dup.2
+++ b/lib/libc/sys/dup.2
@@ -28,7 +28,7 @@
.\" @(#)dup.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd June 4, 1993
+.Dd August 14, 2011
.Dt DUP 2
.Os
.Sh NAME
@@ -115,6 +115,11 @@ and
is a valid descriptor, then
.Fn dup2
is successful, and does nothing.
+.Pp
+The related
+.Xr cap_new 2
+system call allows file descriptors to be duplicated with restrictions on
+their use.
.Sh RETURN VALUES
The value -1 is returned if an error occurs in either call.
The external variable
@@ -123,22 +128,30 @@ indicates the cause of the error.
.Sh ERRORS
The
.Fn dup
-and
-.Fn dup2
-system calls fail if:
+system call fails if:
.Bl -tag -width Er
.It Bq Er EBADF
The
.Fa oldd
-or
-.Fa newd
argument
is not a valid active descriptor
.It Bq Er EMFILE
Too many descriptors are active.
.El
+The
+.Fn dup2
+system call fails if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa oldd
+argument is not a valid active descriptor or the
+.Fa newd
+argument is negative or exceeds the maximum allowable descriptor number
+.El
.Sh SEE ALSO
.Xr accept 2 ,
+.Xr cap_new 2 ,
.Xr close 2 ,
.Xr fcntl 2 ,
.Xr getdtablesize 2 ,
diff --git a/lib/libc/sys/fcntl.2 b/lib/libc/sys/fcntl.2
index a801b60..beceb72 100644
--- a/lib/libc/sys/fcntl.2
+++ b/lib/libc/sys/fcntl.2
@@ -28,7 +28,7 @@
.\" @(#)fcntl.2 8.2 (Berkeley) 1/12/94
.\" $FreeBSD$
.\"
-.Dd September 28, 2009
+.Dd January 28, 2012
.Dt FCNTL 2
.Os
.Sh NAME
@@ -143,6 +143,22 @@ process groups are specified by supplying
as negative, otherwise
.Fa arg
is interpreted as a process ID.
+.It Dv F_READAHEAD
+Set or clear the read ahead amount for sequential access to the third
+argument,
+.Fa arg ,
+which is rounded up to the nearest block size.
+A zero value in
+.Fa arg
+turns off read ahead.
+.It Dv F_RDAHEAD
+Equivalent to Darwin counterpart which sets read ahead amount of 128KB
+when the third argument,
+.Fa arg
+is non-zero.
+A zero value in
+.Fa arg
+turns off read ahead.
.El
.Pp
The flags for the
@@ -241,22 +257,6 @@ will be interrupted if the signal handler has not specified the
.Dv SA_RESTART
(see
.Xr sigaction 2 ) .
-.It Dv F_READAHEAD
-Set or clear the read ahead amount for sequential access to the third
-argument,
-.Fa arg ,
-which is rounded up to the nearest block size.
-A zero value in
-.Fa arg
-turns off read ahead.
-.It Dv F_RDAHEAD
-Equivalent to Darwin counterpart which sets read ahead amount of 128KB
-when the third argument,
-.Fa arg
-is non-zero.
-A zero value in
-.Fa arg
-turns off read ahead.
.El
.Pp
When a shared lock has been set on a segment of a file,
@@ -539,8 +539,6 @@ The argument
.Fa cmd
is
.Dv F_DUPFD
-or
-.Dv F_DUP2FD
and the maximum number of file descriptors permitted for the
process are already in use,
or no file descriptors greater than or equal to
diff --git a/lib/libc/sys/ffclock.2 b/lib/libc/sys/ffclock.2
new file mode 100644
index 0000000..0e8f09b
--- /dev/null
+++ b/lib/libc/sys/ffclock.2
@@ -0,0 +1,177 @@
+.\" Copyright (c) 2011 The University of Melbourne
+.\" All rights reserved.
+.\"
+.\" This documentation was written by Julien Ridoux at the University of
+.\" Melbourne under sponsorship from the FreeBSD Foundation.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd November 21, 2011
+.Dt FFCLOCK 2
+.Os
+.Sh NAME
+.Nm ffclock_getcounter ,
+.Nm ffclock_getestimate ,
+.Nm ffclock_setestimate
+.Nd Retrieve feed-forward counter, get and set feed-forward clock estimates.
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/timeffc.h
+.Ft int
+.Fn ffclock_getcounter "ffcounter *ffcount"
+.Ft int
+.Fn ffclock_getestimate "struct ffclock_estimate *cest"
+.Ft int
+.Fn ffclock_setestimate "struct ffclock_estimate *cest"
+.Sh DESCRIPTION
+The ffclock is an alternative method to synchronise the system clock.
+The ffclock implements a feed-forward paradigm and decouples the timestamping
+and timekeeping kernel functions.
+This ensures that past clock errors do not affect current timekeeping, an
+approach radically different from the feedback alternative implemented by the
+ntpd daemon when adjusting the system clock.
+The feed-forward approach has demonstrated better performance and higher
+robustness than a feedback approach when synchronising over the network.
+.Pp
+In the feed-forward context, a
+.Em timestamp
+is a cumulative value of the ticks of the timecounter, which can be converted
+into seconds by using the feed-forward
+.Em clock estimates.
+.Pp
+The
+.Fn ffclock_getcounter
+system call allows the calling process to retrieve the current value of the
+feed-forward counter maintained by the kernel.
+.Pp
+The
+.Fn ffclock_getestimate
+and
+.Fn ffclock_setestimate
+system calls allow the caller to get and set the kernel's feed-forward clock
+parameter estimates respectively.
+The
+.Fn ffclock_setestimate
+system call should be invoked by a single instance of a feed-forward
+synchronisation daemon.
+The
+.Fn ffclock_getestimate
+system call can be called by any process to retrieve the feed-forward clock
+estimates.
+.Pp
+The feed-forward approach does not require that the clock estimates be retrieved
+every time a timestamp is to be converted into seconds.
+The number of system calls can therefore be greatly reduced if the calling
+process retrieves the clock estimates from the clock synchronisation daemon
+instead.
+The
+.Fn ffclock_getestimate
+must be used when the feed-forward synchronisation daemon is not running
+.Po see
+.Sx USAGE
+below
+.Pc .
+.Pp
+The clock parameter estimates structure pointed to by
+.Fa cest
+is defined in
+.In sys/timeffc.h
+as:
+.Bd -literal
+struct ffclock_estimate {
+ struct bintime update_time; /* Time of last estimates update. */
+ ffcounter update_ffcount; /* Counter value at last update. */
+ ffcounter leapsec_next; /* Counter value of next leap second. */
+ uint64_t period; /* Estimate of counter period. */
+ uint32_t errb_abs; /* Bound on absolute clock error [ns]. */
+ uint32_t errb_rate; /* Bound on counter rate error [ps/s]. */
+ uint32_t status; /* Clock status. */
+ int16_t leapsec_total; /* All leap seconds seen so far. */
+ int8_t leapsec; /* Next leap second (in {-1,0,1}). */
+};
+.Ed
+.Pp
+Only the super-user may set the feed-forward clock estimates.
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+The following error codes may be set in
+.Va errno :
+.Bl -tag -width Er
+.It Bq Er EFAULT
+The
+.Fa ffcount
+or
+.Fa cest
+pointer referenced invalid memory.
+.It Bq Er EPERM
+A user other than the super-user attempted to set the feed-forward clock
+parameter estimates.
+.El
+.Sh USAGE
+The feed-forward paradigm enables the definition of specialised clock functions.
+.Pp
+In its simplest form,
+.Fn ffclock_getcounter
+can be used to establish strict order between events or to measure small time
+intervals very accurately with a minimum performance cost.
+.Pp
+Different methods exist to access absolute time
+.Po or
+.Qq wall-clock time
+.Pc tracked by the ffclock.
+The simplest method uses the ffclock sysctl interface
+.Va kern.ffclock
+to make the system clock return the ffclock time.
+The
+.Xr clock_gettime 2
+system call can then be used to retrieve the current time seen by the
+feed-forward clock.
+Note that this setting affects the entire system and that a feed-forward
+synchronisation daemon should be running.
+.Pp
+A less automated method consists of retrieving the feed-forward counter
+timestamp from the kernel and using the feed-forward clock parameter estimates
+to convert the timestamp into seconds.
+The feed-forward clock parameter estimates can be retrieved from the kernel or
+from the synchronisation daemon directly (preferred).
+This method allows converting timestamps using different clock models as needed
+by the application, while collecting meaningful upper bounds on current clock
+error.
+.Sh SEE ALSO
+.Xr date 1 ,
+.Xr adjtime 2 ,
+.Xr clock_gettime 2 ,
+.Xr ctime 3
+.Sh HISTORY
+Feed-forward clock support first appeared in
+.Fx 10.0 .
+.Sh AUTHORS
+.An -nosplit
+The feed-forward clock support was written by
+.An Julien Ridoux Aq jridoux@unimelb.edu.au
+in collaboration with
+.An Darryl Veitch Aq dveitch@unimelb.edu.au
+at the University of Melbourne under sponsorship from the FreeBSD Foundation.
diff --git a/lib/libc/sys/flock.2 b/lib/libc/sys/flock.2
index 93f1f66..6106bf4 100644
--- a/lib/libc/sys/flock.2
+++ b/lib/libc/sys/flock.2
@@ -28,7 +28,7 @@
.\" @(#)flock.2 8.2 (Berkeley) 12/11/93
.\" $FreeBSD$
.\"
-.Dd January 22, 2008
+.Dd November 9, 2011
.Dt FLOCK 2
.Os
.Sh NAME
@@ -154,6 +154,8 @@ refers to an object other than a file.
The argument
.Fa fd
refers to an object that does not support file locking.
+.It Bq Er ENOLCK
+A lock was requested, but no locks are available.
.El
.Sh SEE ALSO
.Xr close 2 ,
diff --git a/lib/libc/sys/getdirentries.2 b/lib/libc/sys/getdirentries.2
index e16e7f2..3fe1632 100644
--- a/lib/libc/sys/getdirentries.2
+++ b/lib/libc/sys/getdirentries.2
@@ -71,10 +71,10 @@ The data in the buffer is a series of
.Vt dirent
structures each containing the following entries:
.Bd -literal -offset indent
-u_int32_t d_fileno;
-u_int16_t d_reclen;
-u_int8_t d_type;
-u_int8_t d_namlen;
+uint32_t d_fileno;
+uint16_t d_reclen;
+uint8_t d_type;
+uint8_t d_namlen;
char d_name[MAXNAMELEN + 1]; /* see below */
.Ed
.Pp
diff --git a/lib/libc/sys/getfh.2 b/lib/libc/sys/getfh.2
index c8f6d9d..b44d4af 100644
--- a/lib/libc/sys/getfh.2
+++ b/lib/libc/sys/getfh.2
@@ -28,7 +28,7 @@
.\" @(#)getfh.2 8.1 (Berkeley) 6/9/93
.\" $FreeBSD$
.\"
-.Dd April 6, 2004
+.Dd April 14, 2011
.Dt GETFH 2
.Os
.Sh NAME
@@ -104,6 +104,10 @@ An
.Tn I/O
error occurred while reading from or writing to the file system.
.El
+.Sh SEE ALSO
+.Xr fhopen 2 ,
+.Xr open 2 ,
+.Xr stat 2
.Sh HISTORY
The
.Fn getfh
diff --git a/lib/libc/sys/getgroups.2 b/lib/libc/sys/getgroups.2
index c02b229..66238a1 100644
--- a/lib/libc/sys/getgroups.2
+++ b/lib/libc/sys/getgroups.2
@@ -28,7 +28,7 @@
.\" @(#)getgroups.2 8.2 (Berkeley) 4/16/94
.\" $FreeBSD$
.\"
-.Dd March 5, 1999
+.Dd January 21, 2011
.Dt GETGROUPS 2
.Os
.Sh NAME
@@ -37,7 +37,6 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
-.In sys/param.h
.In unistd.h
.Ft int
.Fn getgroups "int gidsetlen" "gid_t *gidset"
@@ -66,6 +65,12 @@ is zero,
returns the number of supplementary group IDs associated with
the calling process without modifying the array pointed to by
.Fa gidset .
+.Pp
+The value of
+.Dv {NGROUPS_MAX}
+should be obtained using
+.Xr sysconf 3
+to avoid hard-coding it into the executable.
.Sh RETURN VALUES
A successful call returns the number of groups in the group set.
A value of -1 indicates that an error occurred, and the error
@@ -88,7 +93,8 @@ an invalid address.
.El
.Sh SEE ALSO
.Xr setgroups 2 ,
-.Xr initgroups 3
+.Xr initgroups 3 ,
+.Xr sysconf 3
.Sh STANDARDS
The
.Fn getgroups
diff --git a/lib/libc/sys/getloginclass.2 b/lib/libc/sys/getloginclass.2
new file mode 100644
index 0000000..6817330
--- /dev/null
+++ b/lib/libc/sys/getloginclass.2
@@ -0,0 +1,97 @@
+.\"-
+.\" Copyright (c) 2011 Edward Tomasz Napierala
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 6, 2011
+.Dt GETLOGINCLASS 2
+.Os
+.Sh NAME
+.Nm getloginclass ,
+.Nm setloginclass
+.Nd get/set login class
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In unistd.h
+.Ft int
+.Fn getloginclass "char *name" "size_t len"
+.Ft int
+.Fn setloginclass "const char *name"
+.Sh DESCRIPTION
+The
+.Fn getloginclass
+routine returns the login class name associated with the calling process,
+as previously set by
+.Fn setloginclass .
+The caller must provide the buffer
+.Fa name
+with length
+.Fa len
+bytes to hold the result.
+The buffer should be at least
+.Dv MAXLOGNAME
+bytes in length.
+.Pp
+The
+.Fn setloginclass
+system call sets the login class of the calling process to
+.Fa name .
+This system call is restricted to the super-user, and is normally used
+only when a new session is being created on behalf of the named user
+(for example, at login time, or when a remote shell is invoked).
+Processes inherit login class from their parents.
+.Sh RETURN VALUES
+.Rv -std
+.Sh ERRORS
+The following errors may be returned by these calls:
+.Bl -tag -width Er
+.It Bq Er EFAULT
+The
+.Fa name
+argument gave an invalid address.
+.It Bq Er EINVAL
+The
+.Fa name
+argument pointed to a string that was too long.
+Login class names are limited to
+.Dv MAXLOGNAME
+(from
+.In sys/param.h )
+characters, currently 17 including null.
+.It Bq Er EPERM
+The caller tried to set the login class and was not the super-user.
+.It Bq Er ENAMETOOLONG
+The size of the buffer is smaller than the result to be returned.
+.El
+.Sh SEE ALSO
+.Xr setusercontext 3
+.Sh HISTORY
+The
+.Fn getloginclass
+and
+.Fn setloginclass
+system calls first appeared in
+.Fx 9.0 .
diff --git a/lib/libc/sys/getpriority.2 b/lib/libc/sys/getpriority.2
index 28d1f14..ae70f5f 100644
--- a/lib/libc/sys/getpriority.2
+++ b/lib/libc/sys/getpriority.2
@@ -129,10 +129,10 @@ or
.Dv PRIO_USER .
.El
.Pp
-.Bl -tag -width Er
In addition to the errors indicated above,
.Fn setpriority
will fail if:
+.Bl -tag -width Er
.It Bq Er EPERM
A process was located, but neither its effective nor real user
ID matched the effective user ID of the caller.
diff --git a/lib/libc/sys/getsockopt.2 b/lib/libc/sys/getsockopt.2
index d3472d0..1e0d3f91 100644
--- a/lib/libc/sys/getsockopt.2
+++ b/lib/libc/sys/getsockopt.2
@@ -28,7 +28,7 @@
.\" @(#)getsockopt.2 8.4 (Berkeley) 5/2/95
.\" $FreeBSD$
.\"
-.Dd June 13, 2008
+.Dd February 26, 2012
.Dt GETSOCKOPT 2
.Os
.Sh NAME
@@ -172,6 +172,8 @@ for the socket
.It Dv SO_BINTIME Ta "enables reception of a timestamp with datagrams"
.It Dv SO_ACCEPTCONN Ta "get listening status of the socket (get only)"
.It Dv SO_TYPE Ta "get the type of the socket (get only)"
+.It Dv SO_PROTOCOL Ta "get the protocol number for the socket (get only)"
+.It Dv SO_PROTOTYPE Ta "SunOS alias for the Linux SO_PROTOCOL (get only)"
.It Dv SO_ERROR Ta "get and clear error on the socket (get only)"
.It Dv SO_SETFIB Ta "set the associated FIB (routing table) for the socket (set only)"
.El
@@ -184,15 +186,18 @@ The following options are recognized in
.It Dv SO_LISTENQLIMIT Ta "get backlog limit of the socket (get only)"
.It Dv SO_LISTENQLEN Ta "get complete queue length of the socket (get only)"
.It Dv SO_LISTENINCQLEN Ta "get incomplete queue length of the socket (get only)"
+.It Dv SO_USER_COOKIE Ta "set the 'so_user_cookie' value for the socket (uint32_t, set only)"
.El
.Pp
.Dv SO_DEBUG
enables debugging in the underlying protocol modules.
+.Pp
.Dv SO_REUSEADDR
indicates that the rules used in validating addresses supplied
in a
.Xr bind 2
system call should allow reuse of local addresses.
+.Pp
.Dv SO_REUSEPORT
allows completely duplicate bindings by multiple processes
if they all set
@@ -200,6 +205,7 @@ if they all set
before binding the port.
This option permits multiple instances of a program to each
receive UDP/IP multicast or broadcast datagrams destined for the bound port.
+.Pp
.Dv SO_KEEPALIVE
enables the
periodic transmission of messages on a connected socket.
@@ -208,6 +214,7 @@ connected party fail to respond to these messages, the connection is
considered broken and processes using the socket are notified via a
.Dv SIGPIPE
signal when attempting to send data.
+.Pp
.Dv SO_DONTROUTE
indicates that outgoing messages should
bypass the standard routing facilities.
@@ -244,6 +251,7 @@ The option
requests permission to send broadcast datagrams
on the socket.
Broadcast was a privileged operation in earlier versions of the system.
+.Pp
With protocols that support out-of-band data, the
.Dv SO_OOBINLINE
option
@@ -256,6 +264,7 @@ calls without the
.Dv MSG_OOB
flag.
Some protocols always behave as if this option is set.
+.Pp
.Dv SO_SNDBUF
and
.Dv SO_RCVBUF
@@ -285,6 +294,7 @@ only if the low water mark amount could be processed.
The default value for
.Dv SO_SNDLOWAT
is set to a convenient size for network efficiency, often 1024.
+.Pp
.Dv SO_RCVLOWAT
is an option to set the minimum count for input operations.
In general, receive calls will block until any (non-zero) amount of data
@@ -317,6 +327,7 @@ In the current implementation, this timer is restarted each time additional
data are delivered to the protocol,
implying that the limit applies to output portions ranging in size
from the low water mark to the high water mark for output.
+.Pp
.Dv SO_RCVTIMEO
is an option to set a timeout value for input operations.
It accepts a
@@ -338,6 +349,15 @@ The value must be from 0 to one less than the number returned from
the sysctl
.Em net.fibs .
.Pp
+.Dv SO_USER_COOKIE
+can be used to set the uint32_t so_user_cookie field in the socket.
+The value is an uint32_t, and can be used in the kernel code that
+manipulates traffic related to the socket.
+The default value for the field is 0.
+As an example, the value can be used as the skipto target or
+pipe number in
+.Nm ipfw/dummynet .
+.Pp
.Dv SO_ACCEPTFILTER
places an
.Xr accept_filter 9
@@ -431,7 +451,10 @@ and for
.Ed
.Pp
.Dv SO_ACCEPTCONN ,
-.Dv SO_TYPE
+.Dv SO_TYPE ,
+.Dv SO_PROTOCOL
+(and its alias
+.Dv SO_PROTOTYPE )
and
.Dv SO_ERROR
are options used only with
@@ -445,6 +468,12 @@ system call was invoked on the socket.
returns the type of the socket, such as
.Dv SOCK_STREAM ;
it is useful for servers that inherit sockets on startup.
+.Dv SO_PROTOCOL
+returns the protocol number for the socket, for
+.Dv AF_INET
+and
+.Dv AF_INET6
+address families.
.Dv SO_ERROR
returns any pending error on the socket and clears
the error status.
@@ -515,7 +544,9 @@ on a non-listening socket was attempted.
.Sh HISTORY
The
.Fn getsockopt
-system call appeared in
+and
+.Fn setsockopt
+system calls appeared in
.Bx 4.2 .
.Sh BUGS
Several of the socket options should be handled at lower levels of the system.
diff --git a/lib/libc/sys/intro.2 b/lib/libc/sys/intro.2
index e5ff9df..1a22ea2 100644
--- a/lib/libc/sys/intro.2
+++ b/lib/libc/sys/intro.2
@@ -467,6 +467,8 @@ A device or socket encountered an unrecoverable protocol error.
.It Er 93 ENOTCAPABLE Em "Capabilities insufficient" .
An operation on a capability file descriptor requires greater privilege than
the capability allows.
+.It Er 94 ECAPMODE Em "Not permitted in capability mode" .
+The system call or operation is not permitted for capability mode processes.
.El
.Sh DEFINITIONS
.Bl -tag -width Ds
diff --git a/lib/libc/sys/jail.2 b/lib/libc/sys/jail.2
index 74b0dde..a2d692a 100644
--- a/lib/libc/sys/jail.2
+++ b/lib/libc/sys/jail.2
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd June 23, 2009
+.Dd February 8, 2012
.Dt JAIL 2
.Os
.Sh NAME
@@ -59,7 +59,7 @@ system call sets up a jail and locks the current process in it.
The argument is a pointer to a structure describing the prison:
.Bd -literal -offset indent
struct jail {
- u_int32_t version;
+ uint32_t version;
char *path;
char *hostname;
char *jailname;
@@ -296,7 +296,7 @@ flag is not set.
The jail referred to by a
.Va jid
is not accessible by the process, because the process is in a different
-jail.
+jail.
.It Bq Er EEXIST
The jail referred to by a
.Va jid
@@ -344,7 +344,7 @@ parameter does not exist.
The jail referred to by a
.Va jid
is not accessible by the process, because the process is in a different
-jail.
+jail.
.It Bq Er ENOENT
The
.Va lastjid
@@ -362,6 +362,8 @@ and
system calls
will fail if:
.Bl -tag -width Er
+.It Bq Er EPERM
+A user other than the super-user attempted to attach to or remove a jail.
.It Bq Er EINVAL
The jail specified by
.Fa jid
diff --git a/lib/libc/sys/kill.2 b/lib/libc/sys/kill.2
index d46dc1f..0389559 100644
--- a/lib/libc/sys/kill.2
+++ b/lib/libc/sys/kill.2
@@ -28,7 +28,7 @@
.\" @(#)kill.2 8.3 (Berkeley) 4/19/94
.\" $FreeBSD$
.\"
-.Dd April 19, 1994
+.Dd March 15, 2012
.Dt KILL 2
.Os
.Sh NAME
@@ -121,11 +121,8 @@ The
argument
is not a valid signal number.
.It Bq Er ESRCH
-No process can be found corresponding to that specified by
+No process or process group can be found corresponding to that specified by
.Fa pid .
-.It Bq Er ESRCH
-The process id was given as 0
-but the sending process does not have a process group.
.It Bq Er EPERM
The sending process is not the super-user and its effective
user id does not match the effective user-id of the receiving process.
@@ -137,6 +134,7 @@ of the group could not be signaled.
.Xr getpid 2 ,
.Xr killpg 2 ,
.Xr sigaction 2 ,
+.Xr sigqueue 2 ,
.Xr raise 3 ,
.Xr init 8
.Sh STANDARDS
diff --git a/lib/libc/sys/kldstat.2 b/lib/libc/sys/kldstat.2
index 0d28928..8b4e532 100644
--- a/lib/libc/sys/kldstat.2
+++ b/lib/libc/sys/kldstat.2
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd March 3, 1999
+.Dd March 28, 2012
.Dt KLDSTAT 2
.Os
.Sh NAME
@@ -47,12 +47,12 @@ into
.Fa stat .
.Bd -literal
struct kld_file_stat {
- int version; /* set to sizeof(linker_file_stat) */
+ int version; /* set to sizeof(struct kld_file_stat) */
char name[MAXPATHLEN];
int refs;
int id;
- caddr_t address; /* load address */
- size_t size; /* size in bytes */
+ caddr_t address;
+ size_t size;
char pathname[MAXPATHLEN];
};
.Ed
@@ -76,7 +76,7 @@ The id of the file specified in
.It address
The load address of the kld file.
.It size
-The size of the file.
+The amount of memory in bytes allocated by the file.
.It pathname
The full name of the file referred to by
.Fa fileid ,
diff --git a/lib/libc/sys/kqueue.2 b/lib/libc/sys/kqueue.2
index a1b6177..63a662f 100644
--- a/lib/libc/sys/kqueue.2
+++ b/lib/libc/sys/kqueue.2
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd September 15, 2009
+.Dd February 15, 2012
.Dt KQUEUE 2
.Os
.Sh NAME
@@ -203,7 +203,7 @@ will not return it.
The filter itself is not disabled.
.It EV_DISPATCH
Disable the event source immediately after delivery of an event.
-See
+See
.Dv EV_DISABLE
above.
.It EV_DELETE
@@ -217,7 +217,7 @@ any pending events.
When passed as input, it forces
.Dv EV_ERROR
to always be returned.
-When a filter is successfully added the
+When a filter is successfully added the
.Va data
field will be zero.
.It EV_ONESHOT
@@ -322,6 +322,9 @@ The sigevent portion of the AIO request is filled in, with
.Va sigev_notify_kqueue
containing the descriptor of the kqueue that the event should
be attached to,
+.Va sigev_notify_kevent_flags
+containing the kevent flags which should be EV_ONESHOT, EV_CLEAR or
+EV_DISPATCH,
.Va sigev_value
containing the udata value, and
.Va sigev_notify
@@ -446,10 +449,10 @@ Establishes a user event identified by
.Va ident
which is not associated with any kernel mechanism but is triggered by
user level code.
-The lower 24 bits of the
+The lower 24 bits of the
.Va fflags
may be used for user defined flags and manipulated using the following:
-.Bl -tag -width XXNOTE_FFLAGSMASK
+.Bl -tag -width XXNOTE_FFLAGSMASK
.It Dv NOTE_FFNOP
Ignore the input
.Va fflags .
@@ -459,7 +462,7 @@ Bitwise AND
.It Dv NOTE_FFOR
Bitwise OR
.Va fflags .
-.It Dv NOTE_COPY
+.It Dv NOTE_FFCOPY
Copy
.Va fflags .
.It Dv NOTE_FFCTRLMASK
diff --git a/lib/libc/sys/kse.2 b/lib/libc/sys/kse.2
index 92c1de2..41fcc37 100644
--- a/lib/libc/sys/kse.2
+++ b/lib/libc/sys/kse.2
@@ -676,4 +676,4 @@ This manual page was written by
.An "Archie Cobbs" Aq archie@FreeBSD.org .
.Sh BUGS
The KSE code is
-.Ud .
+.Ud
diff --git a/lib/libc/sys/ktrace.2 b/lib/libc/sys/ktrace.2
index aaf6192..1740d75 100644
--- a/lib/libc/sys/ktrace.2
+++ b/lib/libc/sys/ktrace.2
@@ -28,7 +28,7 @@
.\" @(#)ktrace.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd July 13, 2008
+.Dd October 10, 2011
.Dt KTRACE 2
.Os
.Sh NAME
@@ -67,12 +67,12 @@ The
argument specifies the requested ktrace operation.
The defined operations are:
.Bl -column KTRFLAG_DESCENDXXX -offset indent
-.It "KTROP_SET Enable trace points specified in"
+.It KTROP_SET Ta "Enable trace points specified in"
.Fa trpoints .
-.It "KTROP_CLEAR Disable trace points specified in
+.It KTROP_CLEAR Ta "Disable trace points specified in"
.Fa trpoints .
-.It "KTROP_CLEARFILE Stop all tracing."
-.It "KTRFLAG_DESCEND The tracing change should apply to the"
+.It KTROP_CLEARFILE Ta "Stop all tracing."
+.It KTRFLAG_DESCEND Ta "The tracing change should apply to the"
specified process and all its current children.
.El
.Pp
@@ -80,15 +80,21 @@ The
.Fa trpoints
argument specifies the trace points of interest.
The defined trace points are:
-.Bl -column KTRFAC_SYSCALLXXX -offset indent
-.It "KTRFAC_SYSCALL Trace system calls."
-.It "KTRFAC_SYSRET Trace return values from system calls."
-.It "KTRFAC_NAMEI Trace name lookup operations."
-.It "KTRFAC_GENIO Trace all I/O (note that this option can"
+.Bl -column KTRFAC_PROCCTORXXX -offset indent
+.It KTRFAC_SYSCALL Ta "Trace system calls."
+.It KTRFAC_SYSRET Ta "Trace return values from system calls."
+.It KTRFAC_NAMEI Ta "Trace name lookup operations."
+.It KTRFAC_GENIO Ta "Trace all I/O (note that this option can"
generate much output).
-.It "KTRFAC_PSIG Trace posted signals."
-.It "KTRFAC_CSW Trace context switch points."
-.It "KTRFAC_INHERIT Inherit tracing to future children."
+.It KTRFAC_PSIG Ta "Trace posted signals."
+.It KTRFAC_CSW Ta "Trace context switch points."
+.It KTRFAC_USER Ta "Trace application-specific events."
+.It KTRFAC_STRUCT Ta "Trace certain data structures."
+.It KTRFAC_SYSCTL Ta "Trace sysctls."
+.It KTRFAC_PROCCTOR Ta "Trace process construction."
+.It KTRFAC_PROCDTOR Ta "Trace process destruction."
+.It KTRFAC_CAPFAIL Ta "Trace capability failures."
+.It KTRFAC_INHERIT Ta "Inherit tracing to future children."
.El
.Pp
Each tracing event outputs a record composed of a generic header
@@ -96,12 +102,12 @@ followed by a trace point specific structure.
The generic header is:
.Bd -literal
struct ktr_header {
- int ktr_len; /* length of buf */
- short ktr_type; /* trace record type */
- pid_t ktr_pid; /* process id */
- char ktr_comm[MAXCOMLEN+1]; /* command name */
- struct timeval ktr_time; /* timestamp */
- intptr_t ktr_tid; /* was ktr_buffer */
+ int ktr_len; /* length of buf */
+ short ktr_type; /* trace record type */
+ pid_t ktr_pid; /* process id */
+ char ktr_comm[MAXCOMLEN+1]; /* command name */
+ struct timeval ktr_time; /* timestamp */
+ intptr_t ktr_tid; /* was ktr_buffer */
};
.Ed
.Pp
diff --git a/lib/libc/sys/madvise.2 b/lib/libc/sys/madvise.2
index 48f0e5a..b5ea6b2 100644
--- a/lib/libc/sys/madvise.2
+++ b/lib/libc/sys/madvise.2
@@ -169,7 +169,8 @@ was specified and the process does not have superuser privileges.
.Xr mincore 2 ,
.Xr mprotect 2 ,
.Xr msync 2 ,
-.Xr munmap 2
+.Xr munmap 2 ,
+.Xr posix_fadvise 2
.Sh STANDARDS
The
.Fn posix_madvise
diff --git a/lib/libc/sys/mknod.2 b/lib/libc/sys/mknod.2
index 0fc8771..a406068 100644
--- a/lib/libc/sys/mknod.2
+++ b/lib/libc/sys/mknod.2
@@ -28,7 +28,7 @@
.\" @(#)mknod.2 8.1 (Berkeley) 6/4/93
.\" $FreeBSD$
.\"
-.Dd April 10, 2008
+.Dd January 16, 2011
.Dt MKNOD 2
.Os
.Sh NAME
@@ -38,7 +38,7 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
-.In unistd.h
+.In sys/stat.h
.Ft int
.Fn mknod "const char *path" "mode_t mode" "dev_t dev"
.Ft int
diff --git a/lib/libc/sys/mmap.2 b/lib/libc/sys/mmap.2
index 0b1f35f..73ffb2e 100644
--- a/lib/libc/sys/mmap.2
+++ b/lib/libc/sys/mmap.2
@@ -28,7 +28,7 @@
.\" @(#)mmap.2 8.4 (Berkeley) 5/11/95
.\" $FreeBSD$
.\"
-.Dd August 28, 2010
+.Dd March 18, 2012
.Dt MMAP 2
.Os
.Sh NAME
@@ -205,7 +205,7 @@ command and
system call generally do not flush dirty NOSYNC VM data.
The
.Xr msync 2
-system call is obsolete since
+system call is usually not needed since
.Bx
implements a coherent file system buffer cache.
However, it may be
@@ -346,9 +346,6 @@ was specified and the
argument was not available.
.Dv MAP_ANON
was specified and insufficient memory was available.
-The system has reached the per-process mmap limit specified in the
-.Va vm.max_proc_mmap
-sysctl.
.El
.Sh SEE ALSO
.Xr madvise 2 ,
@@ -359,8 +356,7 @@ sysctl.
.Xr msync 2 ,
.Xr munlock 2 ,
.Xr munmap 2 ,
-.Xr getpagesize 3 ,
-.Xr make.conf 5
+.Xr getpagesize 3
.Sh BUGS
The
.Fa len
diff --git a/lib/libc/sys/mq_setattr.2 b/lib/libc/sys/mq_setattr.2
index 2e5a6b1..79e523d 100644
--- a/lib/libc/sys/mq_setattr.2
+++ b/lib/libc/sys/mq_setattr.2
@@ -37,7 +37,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 29, 2005
+.Dd May 17, 2011
.Dt MQ_SETATTR 2
.Os
.Sh NAME
@@ -50,7 +50,7 @@
.Ft int
.Fo mq_setattr
.Fa "mqd_t mqdes"
-.Fa "struct mq_attr *restrict mqstat"
+.Fa "const struct mq_attr *restrict mqstat"
.Fa "struct mq_attr *restrict omqstat"
.Fc
.Sh DESCRIPTION
diff --git a/lib/libc/sys/msync.2 b/lib/libc/sys/msync.2
index cb15925..42d8005 100644
--- a/lib/libc/sys/msync.2
+++ b/lib/libc/sys/msync.2
@@ -28,7 +28,7 @@
.\" @(#)msync.2 8.2 (Berkeley) 6/21/94
.\" $FreeBSD$
.\"
-.Dd June 21, 1994
+.Dd March 18, 2012
.Dt MSYNC 2
.Os
.Sh NAME
@@ -98,6 +98,9 @@ The
argument
was both MS_ASYNC and MS_INVALIDATE.
Only one of these flags is allowed.
+.It Bq Er EIO
+ An error occurred while writing at least one of the pages in
+the specified region.
.El
.Sh SEE ALSO
.Xr madvise 2 ,
@@ -113,7 +116,7 @@ system call first appeared in
.Sh BUGS
The
.Fn msync
-system call is obsolete since
+system call is usually not needed since
.Bx
implements a coherent file system buffer cache.
However, it may be used to associate dirty VM pages with file system
diff --git a/lib/libc/sys/nfssvc.2 b/lib/libc/sys/nfssvc.2
index cf52187..f816231 100644
--- a/lib/libc/sys/nfssvc.2
+++ b/lib/libc/sys/nfssvc.2
@@ -143,14 +143,14 @@ and a pointer to a
struct nfsd_srvargs {
struct nfsd *nsd_nfsd; /* Pointer to in kernel nfsd struct */
uid_t nsd_uid; /* Effective uid mapped to cred */
- u_int32_t nsd_haddr; /* Ip address of client */
+ uint32_t nsd_haddr; /* Ip address of client */
struct ucred nsd_cr; /* Cred. uid maps to */
int nsd_authlen; /* Length of auth string (ret) */
u_char *nsd_authstr; /* Auth string (ret) */
int nsd_verflen; /* and the verifier */
u_char *nsd_verfstr;
struct timeval nsd_timestamp; /* timestamp from verifier */
- u_int32_t nsd_ttl; /* credential ttl (sec) */
+ uint32_t nsd_ttl; /* credential ttl (sec) */
NFSKERBKEY_T nsd_key; /* Session key */
};
.Ed
diff --git a/lib/libc/sys/open.2 b/lib/libc/sys/open.2
index deca8bc..041f9dc 100644
--- a/lib/libc/sys/open.2
+++ b/lib/libc/sys/open.2
@@ -28,7 +28,7 @@
.\" @(#)open.2 8.2 (Berkeley) 11/16/93
.\" $FreeBSD$
.\"
-.Dd February 28, 2009
+.Dd March 25, 2011
.Dt OPEN 2
.Os
.Sh NAME
@@ -118,6 +118,7 @@ O_NOFOLLOW do not follow symlinks
O_NOCTTY don't assign controlling terminal
O_TTY_INIT restore default terminal attributes
O_DIRECTORY error if file is not a directory
+O_CLOEXEC set FD_CLOEXEC upon open
.Ed
.Pp
Opening a file with
@@ -231,6 +232,11 @@ from opening files which are even unsafe to open with
.Dv O_RDONLY ,
such as device nodes.
.Pp
+.Dv O_CLOEXEC
+may be used to set
+.Dv FD_CLOEXEC
+flag for the newly returned file descriptor.
+.Pp
If successful,
.Fn open
returns a non-negative integer, termed a file descriptor.
@@ -241,12 +247,17 @@ file is set to the beginning of the file.
When a new file is created it is given the group of the directory
which contains it.
.Pp
-The new descriptor is set to remain open across
+Unless
+.Dv O_CLOEXEC
+flag was specified,
+the new descriptor is set to remain open across
.Xr execve 2
system calls; see
-.Xr close 2
+.Xr close 2 ,
+.Xr fcntl 2
and
-.Xr fcntl 2 .
+.Dv O_CLOEXEC
+description.
.Pp
The system imposes a limit on the number of file descriptors
open simultaneously by one process.
@@ -404,7 +415,7 @@ of
.Dv O_WRONLY ,
.Dv O_RDWR
and
-.Dv O_EXEC.
+.Dv O_EXEC .
.It Bq Eq EBADF
The
.Fa path
diff --git a/lib/libc/sys/pathconf.2 b/lib/libc/sys/pathconf.2
index 495bc65..8bdd5b8 100644
--- a/lib/libc/sys/pathconf.2
+++ b/lib/libc/sys/pathconf.2
@@ -87,9 +87,7 @@ while
returns information about the file the link references.
.Pp
The available values are as follows:
-.Pp
.Bl -tag -width 6n
-.Pp
.It Li _PC_LINK_MAX
The maximum file link count.
.It Li _PC_MAX_CANON
@@ -175,7 +173,7 @@ return a positive number that represents the minimum hole size returned in
bytes.
The offsets of holes returned will be aligned to this same value.
A special value of 1 is returned if the file system does not specify the minimum
-hole size but still reports holes.
+hole size but still reports holes.
.El
.Sh RETURN VALUES
If the call to
@@ -234,11 +232,11 @@ Too many symbolic links were encountered in translating the pathname.
An I/O error occurred while reading from or writing to the file system.
.El
.Pp
-.Bl -tag -width Er
The
.Fn fpathconf
system call
will fail if:
+.Bl -tag -width Er
.It Bq Er EBADF
The
.Fa fd
diff --git a/lib/libc/sys/pdfork.2 b/lib/libc/sys/pdfork.2
new file mode 100644
index 0000000..0808fbc
--- /dev/null
+++ b/lib/libc/sys/pdfork.2
@@ -0,0 +1,183 @@
+.\"
+.\" Copyright (c) 2009-2010 Robert N. M. Watson
+.\" All rights reserved.
+.\"
+.\" This software was developed at the University of Cambridge Computer
+.\" Laboratory with support from a grant from Google, Inc.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd February 25, 2012
+.Dt PDFORK 2
+.Os
+.Sh NAME
+.Nm pdfork ,
+.Nm pdgetpid ,
+.Nm pdkill ,
+.Nm pdwait4
+.Nd System calls to manage process descriptors
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In sys/procdesc.h
+.Ft int
+.Fn pdfork "int *fdp" "int flags"
+.Ft int
+.Fn pdgetpid "int fd" "pid_t *pidp"
+.Ft int
+.Fn pdkill "int fd" "int signum"
+.Ft int
+.Fn pdwait4 "int fd" "int *status" "int options" "struct rusage *rusage"
+.Sh DESCRIPTION
+Process descriptors are special file descriptors that represent processes,
+and are created using
+.Fn pdfork ,
+a variant of
+.Xr fork 2 ,
+which, if successful, returns a process descriptor in the integer pointed to
+by
+.Fa pidp .
+Processes created via
+.Fn pdfork
+will not cause
+.Dv SIGCHLD
+on termination.
+.Fn pdfork
+can accept the flags:
+.Bl -tag -width ".Dv PD_DAEMON"
+.It Dv PD_DAEMON
+Instead of the default terminate-on-close behaviour, allow the process to
+live until it is explicitly killed with
+.Xr kill 2 .
+.Pp
+This option is not permitted in Capsicum capability mode (see
+.Xr cap_enter 2 ) .
+.El
+.Pp
+.Fn pdgetpid
+queries the process ID (PID) if the process descriptor
+.Fa fd .
+.Pp
+.Fn pdkill
+is functionally identical to
+.Xr kill 2 ,
+except that it accepts a process descriptor,
+.Fa fd ,
+rather than a PID.
+.Pp
+.Fn pdwait4
+behaves identically to
+.Xr wait4 2 ,
+but operates with respect to a process descriptor argument rather than a PID.
+.Pp
+The following system calls also have effects specific to process descriptors:
+.Pp
+.Xr fstat 2
+queries status of a process descriptor; currently only the
+.Fa st_mode ,
+.Fa st_birthtime ,
+.Fa st_atime ,
+.Fa st_ctime
+and
+.Fa st_mtime
+fields are defined.
+If the owner read, write, and execute bits are set then the
+process represented by the process descriptor is still alive.
+.Pp
+.Xr poll 2
+and
+.Xr select 2
+allow waiting for process state transitions; currently only
+.Dv POLLHUP
+is defined, and will be raised when the process dies.
+.Pp
+.Xr close 2
+will close the process descriptor unless
+.Dv PD_DAEMON
+is set; if the process is still alive and this is
+the last reference to the process descriptor, the process will be terminated
+with the signal
+.Dv SIGKILL .
+.Sh RETURN VALUES
+.Fn pdfork
+returns a PID, 0 or -1, as
+.Xr fork 2
+does.
+.Pp
+.Fn pdgetpid
+and
+.Fn pdkill
+return 0 on success and -1 on failure.
+.Pp
+.Fn pdwait4
+returns a PID on success and -1 on failure.
+.Sh ERRORS
+These functions may return the same error numbers as their PID-based equivalents
+(e.g.
+.Fn pdfork
+may return the same error numbers as
+.Xr fork 2 ) ,
+with the following additions:
+.Bl -tag -width Er
+.It Bq Er EINVAL
+The signal number given to
+.Fn pdkill
+is invalid.
+.It Bq Er ENOTCAPABLE
+The process descriptor being operated on has insufficient rights (e.g.
+.Dv CAP_PDKILL
+for
+.Fn pdkill ) .
+.El
+.Sh SEE ALSO
+.Xr close 2 ,
+.Xr fork 2 ,
+.Xr fstat 2 ,
+.Xr kill 2 ,
+.Xr poll 2 ,
+.Xr wait4 2
+.Sh HISTORY
+The
+.Fn pdfork ,
+.Fn pdgetpid ,
+.Fn pdkill
+and
+.Fn pdwait4
+system calls first appeared in
+.Fx 9.0 .
+.Pp
+Support for process descriptors mode was developed as part of the
+.Tn TrustedBSD
+Project.
+.Sh AUTHORS
+.An -nosplit
+These functions and the capability facility were created by
+.An "Robert N. M. Watson" Aq rwatson@FreeBSD.org
+and
+.An "Jonathan Anderson" Aq jonathan@FreeBSD.org
+at the University of Cambridge Computer Laboratory with support from a grant
+from Google, Inc.
+.Sh BUGS
+.Fn pdwait4
+has not yet been implemented.
diff --git a/lib/libc/sys/posix_fadvise.2 b/lib/libc/sys/posix_fadvise.2
new file mode 100644
index 0000000..37453ff
--- /dev/null
+++ b/lib/libc/sys/posix_fadvise.2
@@ -0,0 +1,138 @@
+.\" Copyright (c) 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)madvise.2 8.1 (Berkeley) 6/9/93
+.\" $FreeBSD$
+.\"
+.Dd February 25, 2012
+.Dt POSIX_FADVISE 2
+.Os
+.Sh NAME
+.Nm posix_fadvise
+.Nd give advice about use of file data
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In fcntl.h
+.Ft int
+.Fn posix_fadvise "int fd" "off_t offset" "off_t len" "int advice"
+.Sh DESCRIPTION
+The
+.Fn posix_fadvise
+system call
+allows a process to describe to the system its data access behavior for an
+open file descriptor
+.Fa fd .
+The advice covers the data starting at offset
+.Fa offset
+and continuing for
+.Fa len
+bytes.
+If
+.Fa len
+is zero,
+all data from
+.Fa offset
+to the end of the file is covered.
+.Pp
+The behavior is specified by the
+.Fa advice
+parameter and may be one of:
+.Bl -tag -width POSIX_FADV_SEQUENTIAL
+.It Dv POSIX_FADV_NORMAL
+Tells the system to revert to the default data access behavior.
+.It Dv POSIX_FADV_RANDOM
+Is a hint that file data will be accessed randomly,
+and prefetching is likely not advantageous.
+.It Dv POSIX_FADV_SEQUENTIAL
+Tells the system that file data will be accessed sequentially.
+This currently does nothing as the default behavior uses heuristics to
+detect sequential behavior.
+.It Dv POSIX_FADV_WILLNEED
+Tells the system that the specified data will be accessed in the near future.
+The system may initiate an asynchronous read of the data if it is not already
+present in memory.
+.It Dv POSIX_FADV_DONTNEED
+Tells the system that the specified data will not be accessed in the near
+future.
+The system may decrease the in-memory priority of clean data within the
+specified range and future access to this data may require a read operation.
+.It Dv POSIX_FADV_NOREUSE
+Tells the system that the specified data will only be accessed once and
+then not reused.
+Accesses to data within the specified range are treated as if the file
+descriptor has the
+.Dv O_DIRECT
+flag enabled.
+.El
+.Sh RETURN VALUES
+.Rv -std posix_fadvise
+.Sh ERRORS
+The
+.Fn posix_fadvise
+system call will fail if:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa fd
+argument is not a valid file descriptor.
+.It Bq Er EINVAL
+The
+.Fa advice
+argument is not valid.
+.It Bq Er EINVAL
+The
+.Fa offset
+or
+.Fa len
+arguments are negative,
+or
+.Fa offset
++
+.Fa len
+is greater than the maximum file size.
+.It Bq Er ENODEV
+The
+.Fa fd
+argument does not refer to a regular file.
+.It Bq Er ESPIPE
+The
+.Fa fd
+argument is associated with a pipe or FIFO.
+.El
+.Sh SEE ALSO
+.Xr madvise 2
+.Sh STANDARDS
+The
+.Fn posix_fadvise
+interface conforms to
+.St -p1003.1-2001 .
+.Sh HISTORY
+The
+.Fn posix_fadvise
+system call first appeared in
+.Fx 10.0 .
diff --git a/lib/libc/sys/posix_fallocate.2 b/lib/libc/sys/posix_fallocate.2
new file mode 100644
index 0000000..087c68c
--- /dev/null
+++ b/lib/libc/sys/posix_fallocate.2
@@ -0,0 +1,145 @@
+.\" Copyright (c) 1980, 1991, 1993
+.\" The Regents of the University of California. All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 4. Neither the name of the University nor the names of its contributors
+.\" may be used to endorse or promote products derived from this software
+.\" without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" @(#)open.2 8.2 (Berkeley) 11/16/93
+.\" $FreeBSD$
+.\"
+.Dd February 25, 2012
+.Dt POSIX_FALLOCATE 2
+.Os
+.Sh NAME
+.Nm posix_fallocate
+.Nd pre-allocate storage for a range in a file
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In fcntl.h
+.Ft int
+.Fn posix_fallocate "int fd" "off_t offset" "off_t len"
+.Sh DESCRIPTION
+Required storage for the range
+.Fa offset
+to
+.Fa offset +
+.Fa len
+in the file referenced by
+.Fa fd
+is guaranteed to be allocated upon successful return.
+That is, if
+.Fn posix_fallocate
+returns successfully, subsequent writes to the specified file data
+will not fail due to lack of free space on the file system storage
+media.
+Any existing file data in the specified range is unmodified.
+If
+.Fa offset +
+.Fa len
+is beyond the current file size, then
+.Fn posix_fallocate
+will adjust the file size to
+.Fa offset +
+.Fa len .
+Otherwise, the file size will not be changed.
+.Pp
+Space allocated by
+.Fn posix_fallocate
+will be freed by a successful call to
+.Xr creat 2
+or
+.Xr open 2
+that truncates the size of the file.
+Space allocated via
+.Fn posix_fallocate
+may be freed by a successful call to
+.Xr ftruncate 2
+that reduces the file size to a size smaller than
+.Fa offset +
+.Fa len .
+.Sh RETURN VALUES
+If successful,
+.Fn posix_fallocate
+returns zero.
+It returns -1 on failure, and sets
+.Va errno
+to indicate the error.
+.Sh ERRORS
+Possible failure conditions:
+.Bl -tag -width Er
+.It Bq Er EBADF
+The
+.Fa fd
+argument is not a valid file descriptor.
+.It Bq Er EBADF
+The
+.Fa fd
+argument references a file that was opened without write permission.
+.It Bq Er EFBIG
+The value of
+.Fa offset +
+.Fa len
+is greater than the maximum file size.
+.It Bq Er EINTR
+A signal was caught during execution.
+.It Bq Er EINVAL
+The
+.Fa len
+argument was zero or the
+.Fa offset
+argument was less than zero.
+.It Bq Er EIO
+An I/O error occurred while reading from or writing to a file system.
+.It Bq Er ENODEV
+The
+.Fa fd
+argument does not refer to a regular file.
+.It Bq Er ENOSPC
+There is insufficient free space remaining on the file system storage
+media.
+.It Bq Er ESPIPE
+The
+.Fa fd
+argument is associated with a pipe or FIFO.
+.El
+.Sh SEE ALSO
+.Xr creat 2 ,
+.Xr ftruncate 2 ,
+.Xr open 2 ,
+.Xr unlink 2
+.Sh STANDARDS
+The
+.Fn posix_fallocate
+system call conforms to
+.St -p1003.1-2004 .
+.Sh HISTORY
+The
+.Fn posix_fallocate
+function appeared in
+.Fx 9.0 .
+.Sh AUTHORS
+.Fn posix_fallocate
+and this manual page were initially written by
+.An Matthew Fleming Aq mdf@FreeBSD.org .
diff --git a/lib/libc/sys/ptrace.2 b/lib/libc/sys/ptrace.2
index f40574b..9dda8ee 100644
--- a/lib/libc/sys/ptrace.2
+++ b/lib/libc/sys/ptrace.2
@@ -2,7 +2,7 @@
.\" $NetBSD: ptrace.2,v 1.2 1995/02/27 12:35:37 cgd Exp $
.\"
.\" This file is in the public domain.
-.Dd July 10, 2010
+.Dd February 19, 2012
.Dt PTRACE 2
.Os
.Sh NAME
@@ -295,6 +295,8 @@ struct ptrace_lwpinfo {
sigset_t pl_sigmask;
sigset_t pl_siglist;
siginfo_t pl_siginfo;
+ char pl_tdname[MAXCOMLEN + 1];
+ int pl_child_pid;
};
.Ed
.Pp
@@ -345,6 +347,19 @@ Indicates that
member of
.Vt "struct ptrace_lwpinfo"
contains valid information.
+.It PL_FLAG_FORKED
+Indicates that the process is returning from a call to
+.Fn fork 2
+that created a new child process.
+The process identifier of the new process is available in the
+.Va pl_child_pid
+member of
+.Vt "struct ptrace_lwpinfo" .
+.It PL_FLAG_CHILD
+The flag is set for first event reported from a new child, which is
+automatically attached due to
+.Dv PT_FOLLOW_FORK
+enabled.
.El
.It pl_sigmask
The current signal mask of the LWP
@@ -356,11 +371,20 @@ on an LWP siglist until the thread is selected for delivery.
The siginfo that accompanies the signal pending.
Only valid for
.Dv PL_EVENT_SIGNAL
-kind of stop, when
-.Va pl_flags
-has
+stop when
.Dv PL_FLAG_SI
-set.
+is set in
+.Va pl_flags .
+.It pl_tdname
+The name of the thread.
+.It pl_child_pid
+The process identifier of the new child process.
+Only valid for a
+.Dv PL_EVENT_SIGNAL
+stop when
+.Dv PL_FLAG_FORKED
+is set in
+.Va pl_flags .
.El
.It PT_GETNUMLWPS
This request returns the number of kernel threads associated with the
@@ -391,6 +415,21 @@ This request will trace the specified process on each system call exit.
.It PT_SYSCALL
This request will trace the specified process
on each system call entry and exit.
+.It PT_FOLLOW_FORK
+This request controls tracing for new child processes of a traced process.
+If
+.Fa data
+is non-zero,
+then new child processes will enable tracing and stop before executing their
+first instruction.
+If
+.Fa data
+is zero, then new child processes will execute without tracing enabled.
+By default, tracing is not enabled for new child processes.
+Child processes do not inherit this property.
+The traced process will set the
+.Dv PL_FLAG_FORKED
+flag upon exit from a system call that creates a new process.
.It PT_VM_TIMESTAMP
This request returns the generation number or timestamp of the memory map of
the traced process as the return value from
@@ -402,7 +441,7 @@ This request is used to iterate over the entries of the VM map of the traced
process.
The
.Fa addr
-argument specifies a pointer to a
+argument specifies a pointer to a
.Vt "struct ptrace_vm_entry" ,
which is defined as follows:
.Bd -literal
@@ -565,10 +604,3 @@ The
.Fn ptrace
function appeared in
.At v7 .
-.Sh BUGS
-The
-.Dv PL_FLAG_SCE ,
-.Dv PL_FLAG_SCX
-and
-.Dv PL_FLAG_EXEC
-are not implemented for MIPS and ARM architectures.
diff --git a/lib/libc/sys/quotactl.2 b/lib/libc/sys/quotactl.2
index ff3cb4b..6dabff0 100644
--- a/lib/libc/sys/quotactl.2
+++ b/lib/libc/sys/quotactl.2
@@ -113,7 +113,7 @@ Only the super-user may turn quotas off.
.It Dv Q_GETQUOTASIZE
Get the wordsize used to represent the quotas for the user or group
(as determined by the command type).
-Possible values are 32 for the old-style quota file
+Possible values are 32 for the old-style quota file
and 64 for the new-style quota file.
The
.Fa addr
@@ -199,7 +199,7 @@ The
.Fa id
argument to
.Dv Q_GETQUOTA ,
-.Dv Q_SETQUOTA
+.Dv Q_SETQUOTA
or
.Dv Q_SETUSE
is a negative value.
diff --git a/lib/libc/sys/read.2 b/lib/libc/sys/read.2
index 19e4ffe..06e0ef1 100644
--- a/lib/libc/sys/read.2
+++ b/lib/libc/sys/read.2
@@ -28,7 +28,7 @@
.\" @(#)read.2 8.4 (Berkeley) 2/26/94
.\" $FreeBSD$
.\"
-.Dd October 11, 2006
+.Dd January 22, 2012
.Dt READ 2
.Os
.Sh NAME
@@ -41,12 +41,12 @@
.Lb libc
.Sh SYNOPSIS
.In sys/types.h
-.In sys/uio.h
.In unistd.h
.Ft ssize_t
.Fn read "int d" "void *buf" "size_t nbytes"
.Ft ssize_t
.Fn pread "int d" "void *buf" "size_t nbytes" "off_t offset"
+.In sys/uio.h
.Ft ssize_t
.Fn readv "int d" "const struct iovec *iov" "int iovcnt"
.Ft ssize_t
diff --git a/lib/libc/sys/rfork.2 b/lib/libc/sys/rfork.2
index c0f264a..222bac4 100644
--- a/lib/libc/sys/rfork.2
+++ b/lib/libc/sys/rfork.2
@@ -5,7 +5,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd May 14, 2007
+.Dd July 12, 2011
.Dt RFORK 2
.Os
.Sh NAME
@@ -80,11 +80,22 @@ the new process to run on the provided stack.
See
.Xr rfork_thread 3
for information.
+Note that a lot of code will not run correctly in such an environment.
.It Dv RFSIGSHARE
If set, the kernel will force sharing the sigacts structure between the
child and the parent.
+.It Dv RFTSIGZMB
+If set, the kernel will deliver a specified signal to the parent
+upon the child exit, instead of default SIGCHLD.
+The signal number
+.Dv signum
+is specified by oring the
+.Dv RFTSIGFLAGS(signum)
+expression into
+.Fa flags .
+Specifying signal number 0 disables signal delivery upon the child exit.
.It Dv RFLINUXTHPN
-If set, the kernel will return SIGUSR1 instead of SIGCHILD upon thread
+If set, the kernel will deliver SIGUSR1 instead of SIGCHLD upon thread
exit for the child.
This is intended to mimic certain Linux clone behaviour.
.El
@@ -163,6 +174,8 @@ would be exceeded (see
Both the RFFDG and the RFCFDG flags were specified.
.It Bq Er EINVAL
Any flags not listed above were specified.
+.It Bq Er EINVAL
+An invalid signal number was specified.
.It Bq Er ENOMEM
There is insufficient swap space for the new process.
.El
@@ -171,24 +184,9 @@ There is insufficient swap space for the new process.
.Xr intro 2 ,
.Xr minherit 2 ,
.Xr vfork 2 ,
+.Xr pthread_create 3 ,
.Xr rfork_thread 3
.Sh HISTORY
The
.Fn rfork
function first appeared in Plan9.
-.Sh BUGS
-.Fx
-does not yet implement a native
-.Fn clone
-library call, and the current pthreads implementation does not use
-.Fn rfork
-with RFMEM.
-A native port of the linux threads library,
-.Pa /usr/ports/devel/linuxthreads ,
-contains a working
-.Fn clone
-call that utilizes RFMEM.
-The
-.Xr rfork_thread 3
-function can often be used instead of
-.Fn clone .
diff --git a/lib/libc/sys/rtprio.2 b/lib/libc/sys/rtprio.2
index afed81e..faad941 100644
--- a/lib/libc/sys/rtprio.2
+++ b/lib/libc/sys/rtprio.2
@@ -1,3 +1,4 @@
+.\"-
.\" Copyright (c) 1994, Henrik Vestergaard Draboel
.\" All rights reserved.
.\"
@@ -26,15 +27,40 @@
.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
.\" SUCH DAMAGE.
+.\"-
+.\" Copyright (c) 2011 Xin LI <delphij@FreeBSD.org>
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
.\"
.\" $FreeBSD$
.\"
-.Dd July 23, 1994
+.Dd December 27, 2011
.Dt RTPRIO 2
.Os
.Sh NAME
-.Nm rtprio
-.Nd examine or modify a process realtime or idle priority
+.Nm rtprio ,
+.Nm rtprio_thread
+.Nd examine or modify realtime or idle priority
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
@@ -42,11 +68,18 @@
.In sys/rtprio.h
.Ft int
.Fn rtprio "int function" "pid_t pid" "struct rtprio *rtp"
+.Ft int
+.Fn rtprio_thread "int function" "lwpid_t lwpid" "struct rtprio *rtp"
.Sh DESCRIPTION
The
.Fn rtprio
system call
-is used to lookup or change the realtime or idle priority of a process.
+is used to lookup or change the realtime or idle priority of a process,
+or the calling thread.
+The
+.Fn rtprio_thread
+system call
+is used to lookup or change the realtime or idle priority of a thread.
.Pp
The
.Fa function
@@ -54,10 +87,31 @@ argument
specifies the operation to be performed.
RTP_LOOKUP to lookup the current priority,
and RTP_SET to set the priority.
-The
+.Pp
+For the
+.Fn rtprio
+system call,
+the
.Fa pid
argument
-specifies the process to be used, 0 for the current process.
+specifies the process to operate on,
+0 for the calling thread.
+When
+.Fa pid
+is non-zero,
+the system call reports the highest priority in the process,
+or sets all threads' priority in the process,
+depending on value of the
+.Fa function
+argument.
+.Pp
+For the
+.Fn rtprio_thread
+system call,
+the
+.Fa lwpid
+specifies the thread to operate on,
+0 for the calling thread.
.Pp
The
.Fa *rtp
@@ -83,12 +137,12 @@ field ranges between 0 and
.Pp
Realtime and idle priority is inherited through fork() and exec().
.Pp
-A realtime process can only be preempted by a process of equal or
-higher priority, or by an interrupt; idle priority processes will run only
-when no other real/normal priority process is runnable.
-Higher real/idle priority processes
-preempt lower real/idle priority processes.
-Processes of equal real/idle priority are run round-robin.
+A realtime thread can only be preempted by a thread of equal or
+higher priority, or by an interrupt; idle priority threads will run only
+when no other real/normal priority thread is runnable.
+Higher real/idle priority threads
+preempt lower real/idle priority threads.
+Threads of equal real/idle priority are run round-robin.
.Sh RETURN VALUES
.Rv -std rtprio
.Sh ERRORS
@@ -102,12 +156,17 @@ The specified
.Fa prio
was out of range.
.It Bq Er EPERM
-The calling process is not allowed to set the realtime priority.
+The calling thread is not allowed to set the realtime priority.
Only
-root is allowed to change the realtime priority of any process, and non-root
-may only change the idle priority of the current process.
+root is allowed to change the realtime priority of any thread, and non-root
+may only change the idle priority of threads the user owns,
+when the
+.Xr sysctl 8
+variable
+.Va security.bsd.unprivileged_idprio
+is set to non-zero.
.It Bq Er ESRCH
-The specified process was not found.
+The specified process or thread was not found or visible.
.El
.Sh SEE ALSO
.Xr nice 1 ,
@@ -115,7 +174,8 @@ The specified process was not found.
.Xr rtprio 1 ,
.Xr setpriority 2 ,
.Xr nice 3 ,
-.Xr renice 8
+.Xr renice 8 ,
+.Xr p_cansee 9 .
.Sh AUTHORS
.An -nosplit
The original author was
@@ -124,3 +184,7 @@ This implementation in
.Fx
was substantially rewritten by
.An David Greenman .
+The
+.Fn rtprio_thread
+system call was implemented by
+.An David Xu .
diff --git a/lib/libc/sys/sctp_generic_sendmsg.2 b/lib/libc/sys/sctp_generic_sendmsg.2
index fee4211..1a2b128 100644
--- a/lib/libc/sys/sctp_generic_sendmsg.2
+++ b/lib/libc/sys/sctp_generic_sendmsg.2
@@ -54,7 +54,7 @@ and
.Fn sctp_generic_sendmsg_iov
are the true system calls used by the
.Xr sctp_sendmsg 3
-and
+and
.Xr sctp_send 3
function calls.
These are more efficient since they are
@@ -68,7 +68,7 @@ For detailed usage please see either the
.Xr sctp_send 3
or
.Xr sctp_sendmsg 3
-function calls.
+function calls.
.Sh RETURN VALUES
The call returns the number of bytes written on success and -1 upon failure.
.Sh ERRORS
diff --git a/lib/libc/sys/sctp_peeloff.2 b/lib/libc/sys/sctp_peeloff.2
index d94f280..40a026d 100644
--- a/lib/libc/sys/sctp_peeloff.2
+++ b/lib/libc/sys/sctp_peeloff.2
@@ -51,7 +51,6 @@ The
system call attempts detach the association specified by
.Fa id
into its own separate socket.
-.Pp
.Sh RETURN VALUES
The call returns -1 on failure and the new socket descriptor
upon success.
@@ -61,7 +60,7 @@ The
system call can return the following errors:
.Bl -tag -width Er
.It Bq Er ENOTCONN
-The
+The
.Fa id
given to the call does not map to a valid
association.
diff --git a/lib/libc/sys/select.2 b/lib/libc/sys/select.2
index 2435e37..59a7998 100644
--- a/lib/libc/sys/select.2
+++ b/lib/libc/sys/select.2
@@ -222,6 +222,6 @@ Thus, it is unwise to assume that the timeout value will be unmodified
by the
.Fn select
system call.
-.Fx
+.Fx
does not modify the return value, which can cause problems for applications
ported from other systems.
diff --git a/lib/libc/sys/sendfile.2 b/lib/libc/sys/sendfile.2
index d9f8cab..9d1fba5 100644
--- a/lib/libc/sys/sendfile.2
+++ b/lib/libc/sys/sendfile.2
@@ -104,7 +104,7 @@ variable pointed to by
The
.Fa flags
argument is a bitmap of these values:
-.Bl -item -offset indent
+.Bl -item -offset indent
.It
.Dv SF_NODISKIO .
This flag causes any
diff --git a/lib/libc/sys/setfib.2 b/lib/libc/sys/setfib.2
index a65a064..ef561d2 100644
--- a/lib/libc/sys/setfib.2
+++ b/lib/libc/sys/setfib.2
@@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd August 8, 2008
+.Dd March 19, 2012
.Dt SETFIB 2
.Os
.Sh NAME
@@ -45,11 +45,30 @@ subsequent to the call, to be that of the argument
The
.Fa fib
argument
-may be between 0 and the current system maximum which
-may be retrieved by the
+must be greater than or equal to 0
+and less than the current system maximum which
+may be retrieved by the
.Va net.fibs
sysctl.
-The default fib of the process will be applied to all protocol families
+The system maximum is set in the kernel configuration file with
+.Bd -ragged -offset indent
+.Cd "options ROUTETABLES=" Ns Em N
+.Ed
+.Pp
+or in
+.Pa /boot/loader.conf
+with
+.Pp
+.Dl net.fibs= Ns Qq Em N
+.Pp
+where
+.Em N
+is an integer.
+However, this maximum is capped at 16 due to the implementation storing
+the fib number in a 4-bit field in
+.Xr mbuf 9
+flags.
+The default fib of the process will be applied to all protocol families
that support multiple fibs, and ignored by those that do not.
The default fib for a process may be overridden for a socket with the use
of the
diff --git a/lib/libc/sys/setuid.2 b/lib/libc/sys/setuid.2
index 4bb4a68..4c7d5ad 100644
--- a/lib/libc/sys/setuid.2
+++ b/lib/libc/sys/setuid.2
@@ -170,7 +170,7 @@ potentially sensitive data.
.Pp
To prevent these files from remaining open after an
.Xr exec 3
-call, be sure to set the close-on-exec flag is set:
+call, be sure to set the close-on-exec flag:
.Bd -literal
void
pseudocode(void)
diff --git a/lib/libc/sys/shm_open.2 b/lib/libc/sys/shm_open.2
index a2fa502..cc12132 100644
--- a/lib/libc/sys/shm_open.2
+++ b/lib/libc/sys/shm_open.2
@@ -139,7 +139,6 @@ The
.Fn shm_unlink
system call removes a shared memory object named
.Fa path .
-.Pp
.Sh RETURN VALUES
If successful,
.Fn shm_open
diff --git a/lib/libc/sys/shmat.2 b/lib/libc/sys/shmat.2
index 8fe340c..fd1db93 100644
--- a/lib/libc/sys/shmat.2
+++ b/lib/libc/sys/shmat.2
@@ -35,7 +35,6 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
-.In machine/param.h
.In sys/types.h
.In sys/ipc.h
.In sys/shm.h
diff --git a/lib/libc/sys/shmctl.2 b/lib/libc/sys/shmctl.2
index d3299af..98ddf13 100644
--- a/lib/libc/sys/shmctl.2
+++ b/lib/libc/sys/shmctl.2
@@ -34,7 +34,6 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
-.In machine/param.h
.In sys/types.h
.In sys/ipc.h
.In sys/shm.h
diff --git a/lib/libc/sys/shmget.2 b/lib/libc/sys/shmget.2
index e7fd6d1..3094345 100644
--- a/lib/libc/sys/shmget.2
+++ b/lib/libc/sys/shmget.2
@@ -25,7 +25,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd July 3, 1995
+.Dd December 17, 2010
.Dt SHMGET 2
.Os
.Sh NAME
@@ -34,7 +34,6 @@
.Sh LIBRARY
.Lb libc
.Sh SYNOPSIS
-.In machine/param.h
.In sys/types.h
.In sys/ipc.h
.In sys/shm.h
@@ -80,17 +79,17 @@ the following constants into the
.Fa flag
argument:
.Bl -tag -width XSHM_WXX6XXX
-.It Dv SHM_R
-Read access for user.
-.It Dv SHM_W
-Write access for user.
-.It Dv ( SHM_R>>3 )
+.It Dv S_IRUSR
+Read access for owner.
+.It Dv S_IWUSR
+Write access for owner.
+.It Dv S_IRGRP
Read access for group.
-.It Dv ( SHM_W>>3 )
+.It Dv S_IWGRP
Write access for group.
-.It Dv ( SHM_R>>6 )
+.It Dv S_IROTH
Read access for other.
-.It Dv ( SHM_W>>6 )
+.It Dv S_IWOTH
Write access for other.
.El
.\"
@@ -143,4 +142,5 @@ already exists.
.Xr shmat 2 ,
.Xr shmctl 2 ,
.Xr shmdt 2 ,
+.Xr stat 2 ,
.Xr ftok 3
diff --git a/lib/libc/sys/sigqueue.2 b/lib/libc/sys/sigqueue.2
index 780b6a0..9e6a4c5 100644
--- a/lib/libc/sys/sigqueue.2
+++ b/lib/libc/sys/sigqueue.2
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 11, 2005
+.Dd March 10, 2012
.Dt SIGQUEUE 2
.Os
.Sh NAME
@@ -126,6 +126,7 @@ The process
does not exist.
.El
.Sh SEE ALSO
+.Xr kill 2 ,
.Xr sigaction 2 ,
.Xr sigpending 2 ,
.Xr sigqueue 2 ,
diff --git a/lib/libc/sys/sigwait.2 b/lib/libc/sys/sigwait.2
index 8c00cf4..a9e605c 100644
--- a/lib/libc/sys/sigwait.2
+++ b/lib/libc/sys/sigwait.2
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 11, 2005
+.Dd August 24, 2011
.Dt SIGWAIT 2
.Os
.Sh NAME
@@ -82,6 +82,14 @@ selected, it will be the lowest numbered one.
The selection order between realtime
and non-realtime signals, or between multiple pending non-realtime signals,
is unspecified.
+.Sh IMPLEMENTATION NOTES
+The
+.Fn sigwait
+function is implemented as a wrapper around the
+.Fn __sys_sigwait
+system call, which retries the call on
+.Er EINTR
+error.
.Sh RETURN VALUES
If successful,
.Fn sigwait
diff --git a/lib/libc/sys/sigwaitinfo.2 b/lib/libc/sys/sigwaitinfo.2
index 41be9e2..a83de06 100644
--- a/lib/libc/sys/sigwaitinfo.2
+++ b/lib/libc/sys/sigwaitinfo.2
@@ -27,7 +27,7 @@
.\"
.\" $FreeBSD$
.\"
-.Dd November 11, 2005
+.Dd August 24, 2011
.Dt SIGTIMEDWAIT 2
.Os
.Sh NAME
@@ -116,6 +116,16 @@ except that the selected signal number shall be stored in the
member, and the cause of the signal shall be stored in the
.Va si_code
member.
+Besides this, the
+.Fn sigwaitinfo
+and
+.Fn sigtimedwait
+system calls may return
+.Er EINTR
+if interrupted by signal, which is not allowed for the
+.Fn sigwait
+function.
+.Pp
If any value is queued to the selected signal, the first such queued
value is dequeued and, if the info argument is
.Pf non- Dv NULL ,
diff --git a/lib/libc/sys/stat.2 b/lib/libc/sys/stat.2
index 85f0cf0..b6c03ab 100644
--- a/lib/libc/sys/stat.2
+++ b/lib/libc/sys/stat.2
@@ -28,7 +28,7 @@
.\" @(#)stat.2 8.4 (Berkeley) 5/1/95
.\" $FreeBSD$
.\"
-.Dd March 28, 2010
+.Dd November 17, 2011
.Dt STAT 2
.Os
.Sh NAME
@@ -345,10 +345,10 @@ represented correctly in the structure pointed to by
.Fa sb .
.El
.Pp
-.Bl -tag -width Er
The
.Fn fstat
system call will fail if:
+.Bl -tag -width Er
.It Bq Er EBADF
The
.Fa fd
@@ -401,8 +401,8 @@ nor a file descriptor associated with a directory.
.Xr fhstat 2 ,
.Xr statfs 2 ,
.Xr utimes 2 ,
-.Xr symlink 7 ,
-.Xr sticky 8
+.Xr sticky 7 ,
+.Xr symlink 7
.Sh STANDARDS
The
.Fn stat
@@ -411,7 +411,7 @@ and
system calls are expected to conform to
.St -p1003.1-90 .
The
-.Fn fchownat
+.Fn fstatat
system call follows The Open Group Extended API Set 2 specification.
.Sh HISTORY
The
diff --git a/lib/libc/sys/timer_create.2 b/lib/libc/sys/timer_create.2
index 3fb415c..316cea3 100644
--- a/lib/libc/sys/timer_create.2
+++ b/lib/libc/sys/timer_create.2
@@ -151,7 +151,7 @@ memory protection fault.
.Sh SEE ALSO
.Xr clock_getres 2 ,
.Xr timer_delete 2 ,
-.Xr timer_getoverun 2 ,
+.Xr timer_getoverrun 2 ,
.Xr siginfo 3
.Sh STANDARDS
The
diff --git a/lib/libc/sys/wait.2 b/lib/libc/sys/wait.2
index 2e084d2..e4812fc 100644
--- a/lib/libc/sys/wait.2
+++ b/lib/libc/sys/wait.2
@@ -66,6 +66,19 @@ the
.Fa status
area contains termination information about the process that exited
as defined below.
+The
+.Fn wait
+call is the same as
+.Fn wait4
+with a
+.Fa wpid
+value of -1,
+with an
+.Fa options
+value of zero,
+and a
+.Fa rusage
+value of zero.
.Pp
The
.Fn wait4
diff --git a/lib/libc/sys/write.2 b/lib/libc/sys/write.2
index 6d60835..d22b985 100644
--- a/lib/libc/sys/write.2
+++ b/lib/libc/sys/write.2
@@ -28,7 +28,7 @@
.\" @(#)write.2 8.5 (Berkeley) 4/2/94
.\" $FreeBSD$
.\"
-.Dd July 7, 2005
+.Dd January 22, 2012
.Dt WRITE 2
.Os
.Sh NAME
@@ -41,12 +41,12 @@
.Lb libc
.Sh SYNOPSIS
.In sys/types.h
-.In sys/uio.h
.In unistd.h
.Ft ssize_t
.Fn write "int d" "const void *buf" "size_t nbytes"
.Ft ssize_t
.Fn pwrite "int d" "const void *buf" "size_t nbytes" "off_t offset"
+.In sys/uio.h
.Ft ssize_t
.Fn writev "int d" "const struct iovec *iov" "int iovcnt"
.Ft ssize_t
diff --git a/lib/libc/uuid/Makefile.inc b/lib/libc/uuid/Makefile.inc
new file mode 100644
index 0000000..595f0d0
--- /dev/null
+++ b/lib/libc/uuid/Makefile.inc
@@ -0,0 +1,24 @@
+# $FreeBSD$
+
+# DCE 1.1 UUID implementation sources
+
+.PATH: ${.CURDIR}/uuid
+
+SRCS+= uuid_compare.c uuid_create.c uuid_create_nil.c uuid_equal.c \
+ uuid_from_string.c uuid_hash.c uuid_is_nil.c uuid_stream.c \
+ uuid_to_string.c
+SYM_MAPS+= ${.CURDIR}/uuid/Symbol.map
+
+MAN+= uuid.3
+MLINKS+=uuid.3 uuid_compare.3
+MLINKS+=uuid.3 uuid_create.3
+MLINKS+=uuid.3 uuid_create_nil.3
+MLINKS+=uuid.3 uuid_equal.3
+MLINKS+=uuid.3 uuid_from_string.3
+MLINKS+=uuid.3 uuid_hash.3
+MLINKS+=uuid.3 uuid_is_nil.3
+MLINKS+=uuid.3 uuid_enc_le.3
+MLINKS+=uuid.3 uuid_dec_le.3
+MLINKS+=uuid.3 uuid_enc_be.3
+MLINKS+=uuid.3 uuid_dec_be.3
+MLINKS+=uuid.3 uuid_to_string.3
diff --git a/lib/libc/uuid/Symbol.map b/lib/libc/uuid/Symbol.map
new file mode 100644
index 0000000..10acc78
--- /dev/null
+++ b/lib/libc/uuid/Symbol.map
@@ -0,0 +1,21 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ uuid_to_string;
+ uuid_is_nil;
+ uuid_hash;
+ uuid_from_string;
+ uuid_equal;
+ uuid_create_nil;
+ uuid_create;
+ uuid_compare;
+};
+
+FBSD_1.1 {
+ uuid_enc_le;
+ uuid_dec_le;
+ uuid_enc_be;
+ uuid_dec_be;
+};
diff --git a/lib/libc/uuid/uuid.3 b/lib/libc/uuid/uuid.3
new file mode 100644
index 0000000..4fa41de
--- /dev/null
+++ b/lib/libc/uuid/uuid.3
@@ -0,0 +1,136 @@
+.\" Copyright (c) 2002 Marcel Moolenaar
+.\" Copyright (c) 2002 Hiten Mahesh Pandya
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+.\" BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+.\" LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+.\" AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+.\" OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd March 1, 2012
+.Dt UUID 3
+.Os
+.Sh NAME
+.Nm uuid_compare , uuid_create , uuid_create_nil , uuid_equal ,
+.Nm uuid_from_string , uuid_hash , uuid_is_nil , uuid_to_string
+.Nd DCE 1.1 compliant UUID functions
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In uuid.h
+.Ft int32_t
+.Fn uuid_compare "const uuid_t *uuid1" "const uuid_t *uuid2" "uint32_t *status"
+.Ft void
+.Fn uuid_create "uuid_t *uuid" "uint32_t *status"
+.Ft void
+.Fn uuid_create_nil "uuid_t *uuid" "uint32_t *status"
+.Ft int32_t
+.Fn uuid_equal "const uuid_t *uuid1" "const uuid_t *uuid2" "uint32_t *status"
+.Ft void
+.Fn uuid_from_string "const char *str" "uuid_t *uuid" "uint32_t *status"
+.Ft uint16_t
+.Fn uuid_hash "const uuid_t *uuid" "uint32_t *status"
+.Ft int32_t
+.Fn uuid_is_nil "const uuid_t *uuid" "uint32_t *status"
+.Ft void
+.Fn uuid_to_string "const uuid_t *uuid" "char **str" "uint32_t *status"
+.Ft void
+.Fn uuid_enc_le "void *buf" "const uuid_t *uuid"
+.Ft void
+.Fn uuid_dec_le "const void *buf" "uuid_t *"
+.Ft void
+.Fn uuid_enc_be "void *buf" "const uuid_t *uuid"
+.Ft void
+.Fn uuid_dec_be "const void *buf" "uuid_t *"
+.Sh DESCRIPTION
+The family of DCE 1.1 compliant UUID functions allow applications to operate
+on universally unique identifiers, or UUIDs.
+The
+.Fn uuid_create
+and
+.Fn uuid_create_nil
+functions create UUIDs.
+The
+.Fn uuid_compare ,
+.Fn uuid_equal
+and
+.Fn uuid_is_nil
+functions can be used to test UUIDs.
+To convert from the binary representation to the string representation or
+vice versa, use
+.Fn uuid_to_string
+or
+.Fn uuid_from_string
+respectively.
+A 16-bit hash value can be obtained by calling
+.Fn uuid_hash .
+.Pp
+The
+.Fn uuid_to_string
+function set
+.Fa *str
+to be a pointer to a buffer sufficiently large to hold the string.
+This pointer should be passed to
+.Xr free 3
+to release the allocated storage when it is no longer needed.
+.Pp
+The
+.Fn uuid_enc_le
+and
+.Fn uuid_enc_be
+functions encode a binary representation of a UUID into an octet stream
+in little-endian and big-endian byte-order, respectively.
+The destination buffer must be pre-allocated by the caller, and must be
+large enough to hold the 16-octet binary UUID.
+These routines are not part of the DCE RPC API.
+They are provided for convenience.
+.Pp
+The
+.Fn uuid_dec_le
+and
+.Fn uuid_dec_be
+functions decode a UUID from an octet stream in little-endian and
+big-endian byte-order, respectively.
+These routines are not part of the DCE RPC API.
+They are provided for convenience.
+.Sh RETURN VALUES
+The successful or unsuccessful completion of the function is returned in
+the
+.Fa status
+argument.
+Possible values are:
+.Bl -tag -width ".Dv uuid_s_invalid_string_uuid"
+.It Dv uuid_s_ok
+The function completed successfully.
+.It Dv uuid_s_bad_version
+The UUID does not have a known version.
+.It Dv uuid_s_invalid_string_uuid
+The string representation of an UUID is not valid.
+.It Dv uuid_s_no_memory
+The function can not allocate memory to store an UUID representation.
+.El
+.Sh SEE ALSO
+.Xr uuidgen 1 ,
+.Xr uuidgen 2
+.Sh STANDARDS
+The UUID functions conform to the DCE 1.1 RPC specification.
+.Sh BUGS
+This manpage can be improved.
diff --git a/lib/libc/uuid/uuid_compare.c b/lib/libc/uuid/uuid_compare.c
new file mode 100644
index 0000000..13d7c27
--- /dev/null
+++ b/lib/libc/uuid/uuid_compare.c
@@ -0,0 +1,76 @@
+/*-
+ * Copyright (c) 2002,2005 Marcel Moolenaar
+ * Copyright (c) 2002 Hiten Mahesh Pandya
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <string.h>
+#include <uuid.h>
+
+/* A macro used to improve the readability of uuid_compare(). */
+#define DIFF_RETURN(a, b, field) do { \
+ if ((a)->field != (b)->field) \
+ return (((a)->field < (b)->field) ? -1 : 1); \
+} while (0)
+
+/*
+ * uuid_compare() - compare two UUIDs.
+ * See also:
+ * http://www.opengroup.org/onlinepubs/009629399/uuid_compare.htm
+ *
+ * NOTE: Either UUID can be NULL, meaning a nil UUID. nil UUIDs are smaller
+ * than any non-nil UUID.
+ */
+int32_t
+uuid_compare(const uuid_t *a, const uuid_t *b, uint32_t *status)
+{
+ int res;
+
+ if (status != NULL)
+ *status = uuid_s_ok;
+
+ /* Deal with NULL or equal pointers. */
+ if (a == b)
+ return (0);
+ if (a == NULL)
+ return ((uuid_is_nil(b, NULL)) ? 0 : -1);
+ if (b == NULL)
+ return ((uuid_is_nil(a, NULL)) ? 0 : 1);
+
+ /* We have to compare the hard way. */
+ DIFF_RETURN(a, b, time_low);
+ DIFF_RETURN(a, b, time_mid);
+ DIFF_RETURN(a, b, time_hi_and_version);
+ DIFF_RETURN(a, b, clock_seq_hi_and_reserved);
+ DIFF_RETURN(a, b, clock_seq_low);
+
+ res = memcmp(a->node, b->node, sizeof(a->node));
+ if (res)
+ return ((res < 0) ? -1 : 1);
+ return (0);
+}
+
+#undef DIFF_RETURN
diff --git a/lib/libc/uuid/uuid_create.c b/lib/libc/uuid/uuid_create.c
new file mode 100644
index 0000000..da3f1d3
--- /dev/null
+++ b/lib/libc/uuid/uuid_create.c
@@ -0,0 +1,45 @@
+/*-
+ * Copyright (c) 2002 Marcel Moolenaar
+ * Copyright (c) 2002 Hiten Mahesh Pandya
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <uuid.h>
+
+/*
+ * uuid_create() - create an UUID.
+ * See also:
+ * http://www.opengroup.org/onlinepubs/009629399/uuid_create.htm
+ */
+void
+uuid_create(uuid_t *u, uint32_t *status)
+{
+
+ if (status)
+ *status = uuid_s_ok;
+
+ uuidgen(u, 1);
+}
diff --git a/lib/libc/uuid/uuid_create_nil.c b/lib/libc/uuid/uuid_create_nil.c
new file mode 100644
index 0000000..6e85ae7
--- /dev/null
+++ b/lib/libc/uuid/uuid_create_nil.c
@@ -0,0 +1,46 @@
+/*-
+ * Copyright (c) 2002 Marcel Moolenaar
+ * Copyright (c) 2002 Hiten Mahesh Pandya
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <strings.h>
+#include <uuid.h>
+
+/*
+ * uuid_create_nil() - create a nil UUID.
+ * See also:
+ * http://www.opengroup.org/onlinepubs/009629399/uuid_create_nil.htm
+ */
+void
+uuid_create_nil(uuid_t *u, uint32_t *status)
+{
+
+ if (status)
+ *status = uuid_s_ok;
+
+ bzero(u, sizeof(*u));
+}
diff --git a/lib/libc/uuid/uuid_equal.c b/lib/libc/uuid/uuid_equal.c
new file mode 100644
index 0000000..e4c48e5
--- /dev/null
+++ b/lib/libc/uuid/uuid_equal.c
@@ -0,0 +1,55 @@
+/*-
+ * Copyright (c) 2002,2005 Marcel Moolenaar
+ * Copyright (c) 2002 Hiten Mahesh Pandya
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <string.h>
+#include <uuid.h>
+
+/*
+ * uuid_equal() - compare for equality.
+ * See also:
+ * http://www.opengroup.org/onlinepubs/009629399/uuid_equal.htm
+ */
+int32_t
+uuid_equal(const uuid_t *a, const uuid_t *b, uint32_t *status)
+{
+
+ if (status != NULL)
+ *status = uuid_s_ok;
+
+ /* Deal with equal or NULL pointers. */
+ if (a == b)
+ return (1);
+ if (a == NULL)
+ return (uuid_is_nil(b, NULL));
+ if (b == NULL)
+ return (uuid_is_nil(a, NULL));
+
+ /* Do a byte for byte comparison. */
+ return ((memcmp(a, b, sizeof(uuid_t))) ? 0 : 1);
+}
diff --git a/lib/libc/uuid/uuid_from_string.c b/lib/libc/uuid/uuid_from_string.c
new file mode 100644
index 0000000..b09a04d
--- /dev/null
+++ b/lib/libc/uuid/uuid_from_string.c
@@ -0,0 +1,92 @@
+/*-
+ * Copyright (c) 2002 Marcel Moolenaar
+ * Copyright (c) 2002 Hiten Mahesh Pandya
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <uuid.h>
+
+/*
+ * uuid_from_string() - convert a string representation of an UUID into
+ * a binary representation.
+ * See also:
+ * http://www.opengroup.org/onlinepubs/009629399/uuid_from_string.htm
+ *
+ * NOTE: The sequence field is in big-endian, while the time fields are in
+ * native byte order.
+ */
+void
+uuid_from_string(const char *s, uuid_t *u, uint32_t *status)
+{
+ int n;
+
+ /* Short-circuit 2 special cases: NULL pointer and empty string. */
+ if (s == NULL || *s == '\0') {
+ uuid_create_nil(u, status);
+ return;
+ }
+
+ /* Assume the worst. */
+ if (status != NULL)
+ *status = uuid_s_invalid_string_uuid;
+
+ /* The UUID string representation has a fixed length. */
+ if (strlen(s) != 36)
+ return;
+
+ /*
+ * We only work with "new" UUIDs. New UUIDs have the form:
+ * 01234567-89ab-cdef-0123-456789abcdef
+ * The so called "old" UUIDs, which we don't support, have the form:
+ * 0123456789ab.cd.ef.01.23.45.67.89.ab
+ */
+ if (s[8] != '-')
+ return;
+
+ n = sscanf(s,
+ "%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx",
+ &u->time_low, &u->time_mid, &u->time_hi_and_version,
+ &u->clock_seq_hi_and_reserved, &u->clock_seq_low, &u->node[0],
+ &u->node[1], &u->node[2], &u->node[3], &u->node[4], &u->node[5]);
+
+ /* Make sure we have all conversions. */
+ if (n != 11)
+ return;
+
+ /* We have a successful scan. Check semantics... */
+ n = u->clock_seq_hi_and_reserved;
+ if ((n & 0x80) != 0x00 && /* variant 0? */
+ (n & 0xc0) != 0x80 && /* variant 1? */
+ (n & 0xe0) != 0xc0) { /* variant 2? */
+ if (status != NULL)
+ *status = uuid_s_bad_version;
+ } else {
+ if (status != NULL)
+ *status = uuid_s_ok;
+ }
+}
diff --git a/lib/libc/uuid/uuid_hash.c b/lib/libc/uuid/uuid_hash.c
new file mode 100644
index 0000000..e5695ee
--- /dev/null
+++ b/lib/libc/uuid/uuid_hash.c
@@ -0,0 +1,49 @@
+/*-
+ * Copyright (c) 2002,2005 Marcel Moolenaar
+ * Copyright (c) 2002 Hiten Mahesh Pandya
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <uuid.h>
+
+/*
+ * uuid_hash() - generate a hash value.
+ * See also:
+ * http://www.opengroup.org/onlinepubs/009629399/uuid_hash.htm
+ */
+uint16_t
+uuid_hash(const uuid_t *u, uint32_t *status)
+{
+
+ if (status)
+ *status = uuid_s_ok;
+
+ /*
+ * Use the most frequently changing bits in the UUID as the hash
+ * value. This should yield a good enough distribution...
+ */
+ return ((u) ? u->time_low & 0xffff : 0);
+}
diff --git a/lib/libc/uuid/uuid_is_nil.c b/lib/libc/uuid/uuid_is_nil.c
new file mode 100644
index 0000000..ee18653
--- /dev/null
+++ b/lib/libc/uuid/uuid_is_nil.c
@@ -0,0 +1,54 @@
+/*-
+ * Copyright (c) 2002,2005 Marcel Moolenaar
+ * Copyright (c) 2002 Hiten Mahesh Pandya
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <uuid.h>
+
+/*
+ * uuid_is_nil() - return whether the UUID is a nil UUID.
+ * See also:
+ * http://www.opengroup.org/onlinepubs/009629399/uuid_is_nil.htm
+ */
+int32_t
+uuid_is_nil(const uuid_t *u, uint32_t *status)
+{
+ const uint32_t *p;
+
+ if (status)
+ *status = uuid_s_ok;
+
+ if (!u)
+ return (1);
+
+ /*
+ * Pick the largest type that has equivalent alignment constraints
+ * as an UUID and use it to test if the UUID consists of all zeroes.
+ */
+ p = (const uint32_t*)u;
+ return ((p[0] == 0 && p[1] == 0 && p[2] == 0 && p[3] == 0) ? 1 : 0);
+}
diff --git a/lib/libc/uuid/uuid_stream.c b/lib/libc/uuid/uuid_stream.c
new file mode 100644
index 0000000..a7cfd7d
--- /dev/null
+++ b/lib/libc/uuid/uuid_stream.c
@@ -0,0 +1,113 @@
+/* $NetBSD: uuid_stream.c,v 1.3 2008/04/19 18:21:38 plunky Exp $ */
+
+/*-
+ * Copyright (c) 2002 Marcel Moolenaar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/endian.h>
+#include <uuid.h>
+
+/*
+ * Encode/Decode UUID into octet-stream.
+ * http://www.opengroup.org/dce/info/draft-leach-uuids-guids-01.txt
+ *
+ * 0 1 2 3
+ * 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | time_low |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | time_mid | time_hi_and_version |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * |clk_seq_hi_res | clk_seq_low | node (0-1) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ * | node (2-5) |
+ * +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+ *
+ * NOTE: These routines are not part of the DCE RPC API. They are
+ * provided for convenience.
+ */
+
+void
+uuid_enc_le(void *buf, const uuid_t *uuid)
+{
+ uint8_t *p = buf;
+ int i;
+
+ le32enc(p, uuid->time_low);
+ le16enc(p + 4, uuid->time_mid);
+ le16enc(p + 6, uuid->time_hi_and_version);
+ p[8] = uuid->clock_seq_hi_and_reserved;
+ p[9] = uuid->clock_seq_low;
+ for (i = 0; i < _UUID_NODE_LEN; i++)
+ p[10 + i] = uuid->node[i];
+}
+
+void
+uuid_dec_le(const void *buf, uuid_t *uuid)
+{
+ const uint8_t *p = buf;
+ int i;
+
+ uuid->time_low = le32dec(p);
+ uuid->time_mid = le16dec(p + 4);
+ uuid->time_hi_and_version = le16dec(p + 6);
+ uuid->clock_seq_hi_and_reserved = p[8];
+ uuid->clock_seq_low = p[9];
+ for (i = 0; i < _UUID_NODE_LEN; i++)
+ uuid->node[i] = p[10 + i];
+}
+
+void
+uuid_enc_be(void *buf, const uuid_t *uuid)
+{
+ uint8_t *p = buf;
+ int i;
+
+ be32enc(p, uuid->time_low);
+ be16enc(p + 4, uuid->time_mid);
+ be16enc(p + 6, uuid->time_hi_and_version);
+ p[8] = uuid->clock_seq_hi_and_reserved;
+ p[9] = uuid->clock_seq_low;
+ for (i = 0; i < _UUID_NODE_LEN; i++)
+ p[10 + i] = uuid->node[i];
+}
+
+void
+uuid_dec_be(const void *buf, uuid_t *uuid)
+{
+ const uint8_t *p = buf;
+ int i;
+
+ uuid->time_low = be32dec(p);
+ uuid->time_mid = be16dec(p + 4);
+ uuid->time_hi_and_version = be16dec(p + 6);
+ uuid->clock_seq_hi_and_reserved = p[8];
+ uuid->clock_seq_low = p[9];
+ for (i = 0; i < _UUID_NODE_LEN; i++)
+ uuid->node[i] = p[10 + i];
+}
diff --git a/lib/libc/uuid/uuid_to_string.c b/lib/libc/uuid/uuid_to_string.c
new file mode 100644
index 0000000..f816391
--- /dev/null
+++ b/lib/libc/uuid/uuid_to_string.c
@@ -0,0 +1,67 @@
+/*-
+ * Copyright (c) 2002,2005 Marcel Moolenaar
+ * Copyright (c) 2002 Hiten Mahesh Pandya
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * $FreeBSD$
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <uuid.h>
+
+/*
+ * uuid_to_string() - Convert a binary UUID into a string representation.
+ * See also:
+ * http://www.opengroup.org/onlinepubs/009629399/uuid_to_string.htm
+ *
+ * NOTE: The references given above do not have a status code for when
+ * the string could not be allocated. The status code has been
+ * taken from the Hewlett-Packard implementation.
+ */
+void
+uuid_to_string(const uuid_t *u, char **s, uint32_t *status)
+{
+ uuid_t nil;
+
+ if (status != NULL)
+ *status = uuid_s_ok;
+
+ /* Why allow a NULL-pointer here? */
+ if (s == 0)
+ return;
+
+ if (u == NULL) {
+ u = &nil;
+ uuid_create_nil(&nil, NULL);
+ }
+
+ asprintf(s, "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
+ u->time_low, u->time_mid, u->time_hi_and_version,
+ u->clock_seq_hi_and_reserved, u->clock_seq_low, u->node[0],
+ u->node[1], u->node[2], u->node[3], u->node[4], u->node[5]);
+
+ if (*s == NULL && status != NULL)
+ *status = uuid_s_no_memory;
+}
diff --git a/lib/libc/xdr/Makefile.inc b/lib/libc/xdr/Makefile.inc
new file mode 100644
index 0000000..d1bb208
--- /dev/null
+++ b/lib/libc/xdr/Makefile.inc
@@ -0,0 +1,52 @@
+# @(#)Makefile 5.11 (Berkeley) 9/6/90
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/xdr ${.CURDIR}/.
+SRCS+= xdr.c xdr_array.c xdr_float.c xdr_mem.c \
+ xdr_rec.c xdr_reference.c xdr_sizeof.c \
+ xdr_stdio.c
+
+SYM_MAPS+= ${.CURDIR}/xdr/Symbol.map
+
+MAN+= xdr.3
+
+MLINKS+= rpc_xdr.3 xdr_accepted_reply.3 \
+ rpc_xdr.3 xdr_authsys_parms.3 \
+ rpc_xdr.3 xdr_callhdr.3 \
+ rpc_xdr.3 xdr_callmsg.3 \
+ rpc_xdr.3 xdr_opaque_auth.3 \
+ rpc_xdr.3 xdr_rejected_reply.3 \
+ rpc_xdr.3 xdr_replymsg.3 \
+ xdr.3 xdr_array.3 \
+ xdr.3 xdr_bool.3 \
+ xdr.3 xdr_bytes.3 \
+ xdr.3 xdr_char.3 \
+ xdr.3 xdr_destroy.3 \
+ xdr.3 xdr_double.3 \
+ xdr.3 xdr_enum.3 \
+ xdr.3 xdr_float.3 \
+ xdr.3 xdr_free.3 \
+ xdr.3 xdr_getpos.3 \
+ xdr.3 xdr_inline.3 \
+ xdr.3 xdr_int.3 \
+ xdr.3 xdr_long.3 \
+ xdr.3 xdrmem_create.3 \
+ xdr.3 xdr_opaque.3 \
+ xdr.3 xdr_pointer.3 \
+ xdr.3 xdrrec_create.3 \
+ xdr.3 xdrrec_endofrecord.3 \
+ xdr.3 xdrrec_eof.3 \
+ xdr.3 xdrrec_skiprecord.3 \
+ xdr.3 xdr_reference.3 \
+ xdr.3 xdr_setpos.3 \
+ xdr.3 xdr_short.3 \
+ xdr.3 xdr_sizeof.3 \
+ xdr.3 xdrstdio_create.3 \
+ xdr.3 xdr_string.3 \
+ xdr.3 xdr_u_char.3 \
+ xdr.3 xdr_u_long.3 \
+ xdr.3 xdr_u_short.3 \
+ xdr.3 xdr_union.3 \
+ xdr.3 xdr_vector.3 \
+ xdr.3 xdr_void.3 \
+ xdr.3 xdr_wrapstring.3
diff --git a/lib/libc/xdr/Symbol.map b/lib/libc/xdr/Symbol.map
new file mode 100644
index 0000000..a8eb3a1
--- /dev/null
+++ b/lib/libc/xdr/Symbol.map
@@ -0,0 +1,56 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ xdr_free;
+ xdr_void;
+ xdr_int;
+ xdr_u_int;
+ xdr_long;
+ xdr_u_long;
+ xdr_int32_t;
+ xdr_u_int32_t;
+ xdr_short;
+ xdr_u_short;
+ xdr_int16_t;
+ xdr_u_int16_t;
+ xdr_char;
+ xdr_u_char;
+ xdr_bool;
+ xdr_enum;
+ xdr_opaque;
+ xdr_bytes;
+ xdr_netobj;
+ xdr_union;
+ xdr_string;
+ xdr_wrapstring;
+ xdr_int64_t;
+ xdr_u_int64_t;
+ xdr_hyper;
+ xdr_u_hyper;
+ xdr_longlong_t;
+ xdr_u_longlong_t;
+ xdr_array;
+ xdr_vector;
+ xdr_float;
+ xdr_double;
+ xdrmem_create;
+ xdrrec_create;
+ xdrrec_skiprecord;
+ xdrrec_eof;
+ xdrrec_endofrecord;
+ xdr_reference;
+ xdr_pointer;
+ xdrstdio_create;
+};
+
+FBSD_1.1 {
+ xdr_uint16_t;
+ xdr_uint32_t;
+ xdr_uint64_t;
+};
+
+FBSD_1.2 {
+ xdr_sizeof;
+};
diff --git a/lib/libc/xdr/xdr.3 b/lib/libc/xdr/xdr.3
new file mode 100644
index 0000000..69f2544
--- /dev/null
+++ b/lib/libc/xdr/xdr.3
@@ -0,0 +1,847 @@
+.\" @(#)xdr.3n 2.2 88/08/03 4.0 RPCSRC; from 1.16 88/03/14 SMI
+.\" $FreeBSD$
+.\"
+.Dd February 16, 1988
+.Dt XDR 3
+.Os
+.Sh NAME
+.Nm xdr ,
+.Nm xdr_array ,
+.Nm xdr_bool ,
+.Nm xdr_bytes ,
+.Nm xdr_char ,
+.Nm xdr_destroy ,
+.Nm xdr_double ,
+.Nm xdr_enum ,
+.Nm xdr_float ,
+.Nm xdr_free ,
+.Nm xdr_getpos ,
+.Nm xdr_hyper ,
+.Nm xdr_inline ,
+.Nm xdr_int ,
+.Nm xdr_long ,
+.Nm xdr_longlong_t ,
+.Nm xdrmem_create ,
+.Nm xdr_opaque ,
+.Nm xdr_pointer ,
+.Nm xdrrec_create ,
+.Nm xdrrec_endofrecord ,
+.Nm xdrrec_eof ,
+.Nm xdrrec_skiprecord ,
+.Nm xdr_reference ,
+.Nm xdr_setpos ,
+.Nm xdr_short ,
+.Nm xdr_sizeof,
+.Nm xdrstdio_create ,
+.Nm xdr_string ,
+.Nm xdr_u_char ,
+.Nm xdr_u_hyper ,
+.Nm xdr_u_int ,
+.Nm xdr_u_long ,
+.Nm xdr_u_longlong_t ,
+.Nm xdr_u_short ,
+.Nm xdr_union ,
+.Nm xdr_vector ,
+.Nm xdr_void ,
+.Nm xdr_wrapstring
+.Nd "library routines for external data representation"
+.Sh LIBRARY
+.Lb libc
+.Sh SYNOPSIS
+.In rpc/types.h
+.In rpc/xdr.h
+.Pp
+See
+.Sx DESCRIPTION
+for function declarations.
+.Sh DESCRIPTION
+These routines allow C programmers to describe
+arbitrary data structures in a machine-independent fashion.
+Data for remote procedure calls are transmitted using these
+routines.
+.Pp
+.Bl -tag -width indent -compact
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fo xdr_array
+.Fa "XDR *xdrs"
+.Fa "char **arrp"
+.Fa "u_int *sizep"
+.Fa "u_int maxsize"
+.Fa "u_int elsize"
+.Fa "xdrproc_t elproc"
+.Fc
+.Xc
+.Pp
+A filter primitive that translates between variable-length
+arrays
+and their corresponding external representations.
+The
+.Fa arrp
+argument
+is the address of the pointer to the array, while
+.Fa sizep
+is the address of the element count of the array;
+this element count cannot exceed
+.Fa maxsize .
+The
+.Fa elsize
+argument
+is the
+.Ic sizeof
+each of the array's elements, and
+.Fa elproc
+is an
+.Tn XDR
+filter that translates between
+the array elements' C form, and their external
+representation.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_bool "XDR *xdrs" "bool_t *bp"
+.Xc
+.Pp
+A filter primitive that translates between booleans (C
+integers)
+and their external representations.
+When encoding data, this
+filter produces values of either one or zero.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_bytes "XDR *xdrs" "char **sp" "u_int *sizep" "u_int maxsize"
+.Xc
+.Pp
+A filter primitive that translates between counted byte
+strings and their external representations.
+The
+.Fa sp
+argument
+is the address of the string pointer.
+The length of the
+string is located at address
+.Fa sizep ;
+strings cannot be longer than
+.Fa maxsize .
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_char "XDR *xdrs" "char *cp"
+.Xc
+.Pp
+A filter primitive that translates between C characters
+and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+Note: encoded characters are not packed, and occupy 4 bytes
+each.
+For arrays of characters, it is worthwhile to
+consider
+.Fn xdr_bytes ,
+.Fn xdr_opaque
+or
+.Fn xdr_string .
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn xdr_destroy "XDR *xdrs"
+.Xc
+.Pp
+A macro that invokes the destroy routine associated with the
+.Tn XDR
+stream,
+.Fa xdrs .
+Destruction usually involves freeing private data structures
+associated with the stream.
+Using
+.Fa xdrs
+after invoking
+.Fn xdr_destroy
+is undefined.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_double "XDR *xdrs" "double *dp"
+.Xc
+.Pp
+A filter primitive that translates between C
+.Vt double
+precision numbers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_enum "XDR *xdrs" "enum_t *ep"
+.Xc
+.Pp
+A filter primitive that translates between C
+.Vt enum Ns s
+(actually integers) and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_float "XDR *xdrs" "float *fp"
+.Xc
+.Pp
+A filter primitive that translates between C
+.Vt float Ns s
+and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn xdr_free "xdrproc_t proc" "void *objp"
+.Xc
+.Pp
+Generic freeing routine.
+The first argument is the
+.Tn XDR
+routine for the object being freed.
+The second argument
+is a pointer to the object itself.
+Note: the pointer passed
+to this routine is
+.Em not
+freed, but what it points to
+.Em is
+freed (recursively).
+.Pp
+.It Xo
+.Ft u_int
+.Xc
+.It Xo
+.Fn xdr_getpos "XDR *xdrs"
+.Xc
+.Pp
+A macro that invokes the get\-position routine
+associated with the
+.Tn XDR
+stream,
+.Fa xdrs .
+The routine returns an unsigned integer,
+which indicates the position of the
+.Tn XDR
+byte stream.
+A desirable feature of
+.Tn XDR
+streams is that simple arithmetic works with this number,
+although the
+.Tn XDR
+stream instances need not guarantee this.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_hyper "XDR *xdrs" "quad_t *llp"
+.Xc
+A filter primitive that translates between ANSI C
+.Vt "long long"
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft "long *"
+.Xc
+.It Xo
+.Fn xdr_inline "XDR *xdrs" "int len"
+.Xc
+.Pp
+A macro that invokes the in-line routine associated with the
+.Tn XDR
+stream,
+.Fa xdrs .
+The routine returns a pointer
+to a contiguous piece of the stream's buffer;
+.Fa len
+is the byte length of the desired buffer.
+Note: pointer is cast to
+.Vt "long *" .
+.Pp
+Warning:
+.Fn xdr_inline
+may return
+.Dv NULL
+(0)
+if it cannot allocate a contiguous piece of a buffer.
+Therefore the behavior may vary among stream instances;
+it exists for the sake of efficiency.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_int "XDR *xdrs" "int *ip"
+.Xc
+.Pp
+A filter primitive that translates between C integers
+and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_long "XDR *xdrs" "long *lp"
+.Xc
+.Pp
+A filter primitive that translates between C
+.Vt long
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_longlong_t "XDR *xdrs" "quad_t *llp"
+.Xc
+A filter primitive that translates between ANSI C
+.Vt "long long"
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn xdrmem_create "XDR *xdrs" "char *addr" "u_int size" "enum xdr_op op"
+.Xc
+.Pp
+This routine initializes the
+.Tn XDR
+stream object pointed to by
+.Fa xdrs .
+The stream's data is written to, or read from,
+a chunk of memory at location
+.Fa addr
+whose length is no more than
+.Fa size
+bytes long.
+The
+.Fa op
+argument
+determines the direction of the
+.Tn XDR
+stream
+(either
+.Dv XDR_ENCODE ,
+.Dv XDR_DECODE ,
+or
+.Dv XDR_FREE ) .
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_opaque "XDR *xdrs" "char *cp" "u_int cnt"
+.Xc
+.Pp
+A filter primitive that translates between fixed size opaque
+data
+and its external representation.
+The
+.Fa cp
+argument
+is the address of the opaque object, and
+.Fa cnt
+is its size in bytes.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_pointer "XDR *xdrs" "char **objpp" "u_int objsize" "xdrproc_t xdrobj"
+.Xc
+.Pp
+Like
+.Fn xdr_reference
+except that it serializes
+.Dv NULL
+pointers, whereas
+.Fn xdr_reference
+does not.
+Thus,
+.Fn xdr_pointer
+can represent
+recursive data structures, such as binary trees or
+linked lists.
+.Pp
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fo xdrrec_create
+.Fa "XDR *xdrs"
+.Fa "u_int sendsize"
+.Fa "u_int recvsize"
+.Fa "void *handle"
+.Fa "int \*(lp*readit\*(rp\*(lp\*(rp"
+.Fa "int \*(lp*writeit\*(rp\*(lp\*(rp"
+.Fc
+.Xc
+.Pp
+This routine initializes the
+.Tn XDR
+stream object pointed to by
+.Fa xdrs .
+The stream's data is written to a buffer of size
+.Fa sendsize ;
+a value of zero indicates the system should use a suitable
+default.
+The stream's data is read from a buffer of size
+.Fa recvsize ;
+it too can be set to a suitable default by passing a zero
+value.
+When a stream's output buffer is full,
+.Fn writeit
+is called.
+Similarly, when a stream's input buffer is empty,
+.Fn readit
+is called.
+The behavior of these two routines is similar to
+the
+system calls
+.Xr read 2
+and
+.Xr write 2 ,
+except that
+.Fa handle
+is passed to the former routines as the first argument.
+Note: the
+.Tn XDR
+stream's
+.Fa op
+field must be set by the caller.
+.Pp
+Warning: this
+.Tn XDR
+stream implements an intermediate record stream.
+Therefore there are additional bytes in the stream
+to provide record boundary information.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdrrec_endofrecord "XDR *xdrs" "int sendnow"
+.Xc
+.Pp
+This routine can be invoked only on
+streams created by
+.Fn xdrrec_create .
+The data in the output buffer is marked as a completed
+record,
+and the output buffer is optionally written out if
+.Fa sendnow
+is non-zero.
+This routine returns one if it succeeds, zero
+otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdrrec_eof "XDR *xdrs"
+.Xc
+.Pp
+This routine can be invoked only on
+streams created by
+.Fn xdrrec_create .
+After consuming the rest of the current record in the stream,
+this routine returns one if the stream has no more input,
+zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdrrec_skiprecord "XDR *xdrs"
+.Xc
+.Pp
+This routine can be invoked only on
+streams created by
+.Fn xdrrec_create .
+It tells the
+.Tn XDR
+implementation that the rest of the current record
+in the stream's input buffer should be discarded.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_reference "XDR *xdrs" "char **pp" "u_int size" "xdrproc_t proc"
+.Xc
+.Pp
+A primitive that provides pointer chasing within structures.
+The
+.Fa pp
+argument
+is the address of the pointer;
+.Fa size
+is the
+.Ic sizeof
+the structure that
+.Fa *pp
+points to; and
+.Fa proc
+is an
+.Tn XDR
+procedure that filters the structure
+between its C form and its external representation.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+Warning: this routine does not understand
+.Dv NULL
+pointers.
+Use
+.Fn xdr_pointer
+instead.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_setpos "XDR *xdrs" "u_int pos"
+.Xc
+.Pp
+A macro that invokes the set position routine associated with
+the
+.Tn XDR
+stream
+.Fa xdrs .
+The
+.Fa pos
+argument
+is a position value obtained from
+.Fn xdr_getpos .
+This routine returns one if the
+.Tn XDR
+stream could be repositioned,
+and zero otherwise.
+.Pp
+Warning: it is difficult to reposition some types of
+.Tn XDR
+streams, so this routine may fail with one
+type of stream and succeed with another.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_short "XDR *xdrs" "short *sp"
+.Xc
+.Pp
+A filter primitive that translates between C
+.Vt short
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft unsigned long
+.Xc
+.It Xo
+.Fn xdr_sizeof "xdrproc_t func" "void *data"
+.Xc
+.Pp
+This routine returns the amount of memory required to encode
+.Fa data
+using filter
+.Fa func .
+.Pp
+.It Li "#ifdef _STDIO_H_"
+.It Li "/* XDR using stdio library */"
+.It Xo
+.Ft void
+.Xc
+.It Xo
+.Fn xdrstdio_create "XDR *xdrs" "FILE *file" "enum xdr_op op"
+.Xc
+.It Li "#endif"
+.Pp
+This routine initializes the
+.Tn XDR
+stream object pointed to by
+.Fa xdrs .
+The
+.Tn XDR
+stream data is written to, or read from, the Standard
+.Tn I/O
+stream
+.Fa file .
+The
+.Fa op
+argument
+determines the direction of the
+.Tn XDR
+stream (either
+.Dv XDR_ENCODE ,
+.Dv XDR_DECODE ,
+or
+.Dv XDR_FREE ) .
+.Pp
+Warning: the destroy routine associated with such
+.Tn XDR
+streams calls
+.Xr fflush 3
+on the
+.Fa file
+stream, but never
+.Xr fclose 3 .
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_string "XDR *xdrs" "char **sp" "u_int maxsize"
+.Xc
+.Pp
+A filter primitive that translates between C strings and
+their
+corresponding external representations.
+Strings cannot be longer than
+.Fa maxsize .
+Note:
+.Fa sp
+is the address of the string's pointer.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_u_char "XDR *xdrs" "unsigned char *ucp"
+.Xc
+.Pp
+A filter primitive that translates between
+.Vt unsigned
+C characters and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_u_hyper "XDR *xdrs" "u_quad_t *ullp"
+.Xc
+A filter primitive that translates between
+.Vt unsigned
+ANSI C
+.Vt long long
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_u_int "XDR *xdrs" "unsigned *up"
+.Xc
+.Pp
+A filter primitive that translates between C
+.Vt unsigned
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_u_long "XDR *xdrs" "unsigned long *ulp"
+.Xc
+.Pp
+A filter primitive that translates between C
+.Vt "unsigned long"
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_u_longlong_t "XDR *xdrs" "u_quad_t *ullp"
+.Xc
+A filter primitive that translates between
+.Vt unsigned
+ANSI C
+.Vt "long long"
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_u_short "XDR *xdrs" "unsigned short *usp"
+.Xc
+.Pp
+A filter primitive that translates between C
+.Vt "unsigned short"
+integers and their external representations.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fo xdr_union
+.Fa "XDR *xdrs"
+.Fa "enum_t *dscmp"
+.Fa "char *unp"
+.Fa "const struct xdr_discrim *choices"
+.Fa "xdrproc_t defaultarm"
+.Fc
+.Xc
+.Pp
+A filter primitive that translates between a discriminated C
+.Vt union
+and its corresponding external representation.
+It first
+translates the discriminant of the union located at
+.Fa dscmp .
+This discriminant is always an
+.Vt enum_t .
+Next the union located at
+.Fa unp
+is translated.
+The
+.Fa choices
+argument
+is a pointer to an array of
+.Vt xdr_discrim
+structures.
+Each structure contains an ordered pair of
+.Bq Va value , proc .
+If the union's discriminant is equal to the associated
+.Va value ,
+then the
+.Fn proc
+is called to translate the union.
+The end of the
+.Vt xdr_discrim
+structure array is denoted by a routine of value
+.Dv NULL .
+If the discriminant is not found in the
+.Fa choices
+array, then the
+.Fn defaultarm
+procedure is called (if it is not
+.Dv NULL ) .
+Returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fo xdr_vector
+.Fa "XDR *xdrs"
+.Fa "char *arrp"
+.Fa "u_int size"
+.Fa "u_int elsize"
+.Fa "xdrproc_t elproc"
+.Fc
+.Xc
+.Pp
+A filter primitive that translates between fixed-length
+arrays
+and their corresponding external representations.
+The
+.Fa arrp
+argument
+is the address of the pointer to the array, while
+.Fa size
+is the element count of the array.
+The
+.Fa elsize
+argument
+is the
+.Ic sizeof
+each of the array's elements, and
+.Fa elproc
+is an
+.Tn XDR
+filter that translates between
+the array elements' C form, and their external
+representation.
+This routine returns one if it succeeds, zero otherwise.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_void void
+.Xc
+.Pp
+This routine always returns one.
+It may be passed to
+.Tn RPC
+routines that require a function argument,
+where nothing is to be done.
+.Pp
+.It Xo
+.Ft int
+.Xc
+.It Xo
+.Fn xdr_wrapstring "XDR *xdrs" "char **sp"
+.Xc
+.Pp
+A primitive that calls
+.Fn xdr_string xdrs sp MAXUN.UNSIGNED ;
+where
+.Dv MAXUN.UNSIGNED
+is the maximum value of an unsigned integer.
+The
+.Fn xdr_wrapstring
+function
+is handy because the
+.Tn RPC
+package passes a maximum of two
+.Tn XDR
+routines as arguments, and
+.Fn xdr_string ,
+one of the most frequently used primitives, requires three.
+Returns one if it succeeds, zero otherwise.
+.El
+.Sh SEE ALSO
+.Xr rpc 3
+.Rs
+.%T "eXternal Data Representation Standard: Protocol Specification"
+.Re
+.Rs
+.%T "eXternal Data Representation: Sun Technical Notes"
+.Re
+.Rs
+.%T "XDR: External Data Representation Standard"
+.%O RFC1014
+.%Q "Sun Microsystems, Inc., USC\-ISI"
+.Re
+.Sh HISTORY
+The
+.Nm xdr_sizeof
+function first appeared in
+.Fx 9.0 .
diff --git a/lib/libc/xdr/xdr.c b/lib/libc/xdr/xdr.c
new file mode 100644
index 0000000..337cdc0
--- /dev/null
+++ b/lib/libc/xdr/xdr.c
@@ -0,0 +1,967 @@
+/* $NetBSD: xdr.c,v 1.22 2000/07/06 03:10:35 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)xdr.c 1.35 87/08/12";
+static char *sccsid = "@(#)xdr.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * xdr.c, Generic XDR routines implementation.
+ *
+ * Copyright (C) 1986, Sun Microsystems, Inc.
+ *
+ * These are the "generic" xdr routines used to serialize and de-serialize
+ * most common data items. See xdr.h for more info on the interface to
+ * xdr.
+ */
+
+#include "namespace.h"
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include "un-namespace.h"
+
+typedef quad_t longlong_t; /* ANSI long long type */
+typedef u_quad_t u_longlong_t; /* ANSI unsigned long long type */
+
+/*
+ * constants specific to the xdr "protocol"
+ */
+#define XDR_FALSE ((long) 0)
+#define XDR_TRUE ((long) 1)
+#define LASTUNSIGNED ((u_int) 0-1)
+
+/*
+ * for unit alignment
+ */
+static const char xdr_zero[BYTES_PER_XDR_UNIT] = { 0, 0, 0, 0 };
+
+/*
+ * Free a data structure using XDR
+ * Not a filter, but a convenient utility nonetheless
+ */
+void
+xdr_free(proc, objp)
+ xdrproc_t proc;
+ void *objp;
+{
+ XDR x;
+
+ x.x_op = XDR_FREE;
+ (*proc)(&x, objp);
+}
+
+/*
+ * XDR nothing
+ */
+bool_t
+xdr_void(void)
+{
+
+ return (TRUE);
+}
+
+
+/*
+ * XDR integers
+ */
+bool_t
+xdr_int(xdrs, ip)
+ XDR *xdrs;
+ int *ip;
+{
+ long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (long) *ip;
+ return (XDR_PUTLONG(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &l)) {
+ return (FALSE);
+ }
+ *ip = (int) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned integers
+ */
+bool_t
+xdr_u_int(xdrs, up)
+ XDR *xdrs;
+ u_int *up;
+{
+ u_long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (u_long) *up;
+ return (XDR_PUTLONG(xdrs, (long *)&l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, (long *)&l)) {
+ return (FALSE);
+ }
+ *up = (u_int) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+
+/*
+ * XDR long integers
+ * same as xdr_u_long - open coded to save a proc call!
+ */
+bool_t
+xdr_long(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ return (XDR_PUTLONG(xdrs, lp));
+ case XDR_DECODE:
+ return (XDR_GETLONG(xdrs, lp));
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned long integers
+ * same as xdr_long - open coded to save a proc call!
+ */
+bool_t
+xdr_u_long(xdrs, ulp)
+ XDR *xdrs;
+ u_long *ulp;
+{
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ return (XDR_PUTLONG(xdrs, (long *)ulp));
+ case XDR_DECODE:
+ return (XDR_GETLONG(xdrs, (long *)ulp));
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+
+/*
+ * XDR 32-bit integers
+ * same as xdr_u_int32_t - open coded to save a proc call!
+ */
+bool_t
+xdr_int32_t(xdrs, int32_p)
+ XDR *xdrs;
+ int32_t *int32_p;
+{
+ long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (long) *int32_p;
+ return (XDR_PUTLONG(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &l)) {
+ return (FALSE);
+ }
+ *int32_p = (int32_t) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned 32-bit integers
+ * same as xdr_int32_t - open coded to save a proc call!
+ */
+bool_t
+xdr_u_int32_t(xdrs, u_int32_p)
+ XDR *xdrs;
+ u_int32_t *u_int32_p;
+{
+ u_long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (u_long) *u_int32_p;
+ return (XDR_PUTLONG(xdrs, (long *)&l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, (long *)&l)) {
+ return (FALSE);
+ }
+ *u_int32_p = (u_int32_t) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned 32-bit integers
+ * same as xdr_int32_t - open coded to save a proc call!
+ */
+bool_t
+xdr_uint32_t(xdrs, u_int32_p)
+ XDR *xdrs;
+ uint32_t *u_int32_p;
+{
+ u_long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (u_long) *u_int32_p;
+ return (XDR_PUTLONG(xdrs, (long *)&l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, (long *)&l)) {
+ return (FALSE);
+ }
+ *u_int32_p = (u_int32_t) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+/*
+ * XDR short integers
+ */
+bool_t
+xdr_short(xdrs, sp)
+ XDR *xdrs;
+ short *sp;
+{
+ long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (long) *sp;
+ return (XDR_PUTLONG(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &l)) {
+ return (FALSE);
+ }
+ *sp = (short) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned short integers
+ */
+bool_t
+xdr_u_short(xdrs, usp)
+ XDR *xdrs;
+ u_short *usp;
+{
+ u_long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (u_long) *usp;
+ return (XDR_PUTLONG(xdrs, (long *)&l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, (long *)&l)) {
+ return (FALSE);
+ }
+ *usp = (u_short) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+
+/*
+ * XDR 16-bit integers
+ */
+bool_t
+xdr_int16_t(xdrs, int16_p)
+ XDR *xdrs;
+ int16_t *int16_p;
+{
+ long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (long) *int16_p;
+ return (XDR_PUTLONG(xdrs, &l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &l)) {
+ return (FALSE);
+ }
+ *int16_p = (int16_t) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned 16-bit integers
+ */
+bool_t
+xdr_u_int16_t(xdrs, u_int16_p)
+ XDR *xdrs;
+ u_int16_t *u_int16_p;
+{
+ u_long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (u_long) *u_int16_p;
+ return (XDR_PUTLONG(xdrs, (long *)&l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, (long *)&l)) {
+ return (FALSE);
+ }
+ *u_int16_p = (u_int16_t) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned 16-bit integers
+ */
+bool_t
+xdr_uint16_t(xdrs, u_int16_p)
+ XDR *xdrs;
+ uint16_t *u_int16_p;
+{
+ u_long l;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ l = (u_long) *u_int16_p;
+ return (XDR_PUTLONG(xdrs, (long *)&l));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, (long *)&l)) {
+ return (FALSE);
+ }
+ *u_int16_p = (u_int16_t) l;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+
+/*
+ * XDR a char
+ */
+bool_t
+xdr_char(xdrs, cp)
+ XDR *xdrs;
+ char *cp;
+{
+ int i;
+
+ i = (*cp);
+ if (!xdr_int(xdrs, &i)) {
+ return (FALSE);
+ }
+ *cp = i;
+ return (TRUE);
+}
+
+/*
+ * XDR an unsigned char
+ */
+bool_t
+xdr_u_char(xdrs, cp)
+ XDR *xdrs;
+ u_char *cp;
+{
+ u_int u;
+
+ u = (*cp);
+ if (!xdr_u_int(xdrs, &u)) {
+ return (FALSE);
+ }
+ *cp = u;
+ return (TRUE);
+}
+
+/*
+ * XDR booleans
+ */
+bool_t
+xdr_bool(xdrs, bp)
+ XDR *xdrs;
+ bool_t *bp;
+{
+ long lb;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ lb = *bp ? XDR_TRUE : XDR_FALSE;
+ return (XDR_PUTLONG(xdrs, &lb));
+
+ case XDR_DECODE:
+ if (!XDR_GETLONG(xdrs, &lb)) {
+ return (FALSE);
+ }
+ *bp = (lb == XDR_FALSE) ? FALSE : TRUE;
+ return (TRUE);
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+/*
+ * XDR enumerations
+ */
+bool_t
+xdr_enum(xdrs, ep)
+ XDR *xdrs;
+ enum_t *ep;
+{
+ enum sizecheck { SIZEVAL }; /* used to find the size of an enum */
+
+ /*
+ * enums are treated as ints
+ */
+ /* LINTED */ if (sizeof (enum sizecheck) == sizeof (long)) {
+ return (xdr_long(xdrs, (long *)(void *)ep));
+ } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (int)) {
+ return (xdr_int(xdrs, (int *)(void *)ep));
+ } else /* LINTED */ if (sizeof (enum sizecheck) == sizeof (short)) {
+ return (xdr_short(xdrs, (short *)(void *)ep));
+ } else {
+ return (FALSE);
+ }
+}
+
+/*
+ * XDR opaque data
+ * Allows the specification of a fixed size sequence of opaque bytes.
+ * cp points to the opaque object and cnt gives the byte length.
+ */
+bool_t
+xdr_opaque(xdrs, cp, cnt)
+ XDR *xdrs;
+ caddr_t cp;
+ u_int cnt;
+{
+ u_int rndup;
+ static int crud[BYTES_PER_XDR_UNIT];
+
+ /*
+ * if no data we are done
+ */
+ if (cnt == 0)
+ return (TRUE);
+
+ /*
+ * round byte count to full xdr units
+ */
+ rndup = cnt % BYTES_PER_XDR_UNIT;
+ if (rndup > 0)
+ rndup = BYTES_PER_XDR_UNIT - rndup;
+
+ if (xdrs->x_op == XDR_DECODE) {
+ if (!XDR_GETBYTES(xdrs, cp, cnt)) {
+ return (FALSE);
+ }
+ if (rndup == 0)
+ return (TRUE);
+ return (XDR_GETBYTES(xdrs, (caddr_t)(void *)crud, rndup));
+ }
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ if (!XDR_PUTBYTES(xdrs, cp, cnt)) {
+ return (FALSE);
+ }
+ if (rndup == 0)
+ return (TRUE);
+ return (XDR_PUTBYTES(xdrs, xdr_zero, rndup));
+ }
+
+ if (xdrs->x_op == XDR_FREE) {
+ return (TRUE);
+ }
+
+ return (FALSE);
+}
+
+/*
+ * XDR counted bytes
+ * *cpp is a pointer to the bytes, *sizep is the count.
+ * If *cpp is NULL maxsize bytes are allocated
+ */
+bool_t
+xdr_bytes(xdrs, cpp, sizep, maxsize)
+ XDR *xdrs;
+ char **cpp;
+ u_int *sizep;
+ u_int maxsize;
+{
+ char *sp = *cpp; /* sp is the actual string pointer */
+ u_int nodesize;
+
+ /*
+ * first deal with the length since xdr bytes are counted
+ */
+ if (! xdr_u_int(xdrs, sizep)) {
+ return (FALSE);
+ }
+ nodesize = *sizep;
+ if ((nodesize > maxsize) && (xdrs->x_op != XDR_FREE)) {
+ return (FALSE);
+ }
+
+ /*
+ * now deal with the actual bytes
+ */
+ switch (xdrs->x_op) {
+
+ case XDR_DECODE:
+ if (nodesize == 0) {
+ return (TRUE);
+ }
+ if (sp == NULL) {
+ *cpp = sp = mem_alloc(nodesize);
+ }
+ if (sp == NULL) {
+ warnx("xdr_bytes: out of memory");
+ return (FALSE);
+ }
+ /* FALLTHROUGH */
+
+ case XDR_ENCODE:
+ return (xdr_opaque(xdrs, sp, nodesize));
+
+ case XDR_FREE:
+ if (sp != NULL) {
+ mem_free(sp, nodesize);
+ *cpp = NULL;
+ }
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+/*
+ * Implemented here due to commonality of the object.
+ */
+bool_t
+xdr_netobj(xdrs, np)
+ XDR *xdrs;
+ struct netobj *np;
+{
+
+ return (xdr_bytes(xdrs, &np->n_bytes, &np->n_len, MAX_NETOBJ_SZ));
+}
+
+/*
+ * XDR a descriminated union
+ * Support routine for discriminated unions.
+ * You create an array of xdrdiscrim structures, terminated with
+ * an entry with a null procedure pointer. The routine gets
+ * the discriminant value and then searches the array of xdrdiscrims
+ * looking for that value. It calls the procedure given in the xdrdiscrim
+ * to handle the discriminant. If there is no specific routine a default
+ * routine may be called.
+ * If there is no specific or default routine an error is returned.
+ */
+bool_t
+xdr_union(xdrs, dscmp, unp, choices, dfault)
+ XDR *xdrs;
+ enum_t *dscmp; /* enum to decide which arm to work on */
+ char *unp; /* the union itself */
+ const struct xdr_discrim *choices; /* [value, xdr proc] for each arm */
+ xdrproc_t dfault; /* default xdr routine */
+{
+ enum_t dscm;
+
+ /*
+ * we deal with the discriminator; it's an enum
+ */
+ if (! xdr_enum(xdrs, dscmp)) {
+ return (FALSE);
+ }
+ dscm = *dscmp;
+
+ /*
+ * search choices for a value that matches the discriminator.
+ * if we find one, execute the xdr routine for that value.
+ */
+ for (; choices->proc != NULL_xdrproc_t; choices++) {
+ if (choices->value == dscm)
+ return ((*(choices->proc))(xdrs, unp));
+ }
+
+ /*
+ * no match - execute the default xdr routine if there is one
+ */
+ return ((dfault == NULL_xdrproc_t) ? FALSE :
+ (*dfault)(xdrs, unp));
+}
+
+
+/*
+ * Non-portable xdr primitives.
+ * Care should be taken when moving these routines to new architectures.
+ */
+
+
+/*
+ * XDR null terminated ASCII strings
+ * xdr_string deals with "C strings" - arrays of bytes that are
+ * terminated by a NULL character. The parameter cpp references a
+ * pointer to storage; If the pointer is null, then the necessary
+ * storage is allocated. The last parameter is the max allowed length
+ * of the string as specified by a protocol.
+ */
+bool_t
+xdr_string(xdrs, cpp, maxsize)
+ XDR *xdrs;
+ char **cpp;
+ u_int maxsize;
+{
+ char *sp = *cpp; /* sp is the actual string pointer */
+ u_int size;
+ u_int nodesize;
+
+ /*
+ * first deal with the length since xdr strings are counted-strings
+ */
+ switch (xdrs->x_op) {
+ case XDR_FREE:
+ if (sp == NULL) {
+ return(TRUE); /* already free */
+ }
+ /* FALLTHROUGH */
+ case XDR_ENCODE:
+ size = strlen(sp);
+ break;
+ case XDR_DECODE:
+ break;
+ }
+ if (! xdr_u_int(xdrs, &size)) {
+ return (FALSE);
+ }
+ if (size > maxsize) {
+ return (FALSE);
+ }
+ nodesize = size + 1;
+
+ /*
+ * now deal with the actual bytes
+ */
+ switch (xdrs->x_op) {
+
+ case XDR_DECODE:
+ if (nodesize == 0) {
+ return (TRUE);
+ }
+ if (sp == NULL)
+ *cpp = sp = mem_alloc(nodesize);
+ if (sp == NULL) {
+ warnx("xdr_string: out of memory");
+ return (FALSE);
+ }
+ sp[size] = 0;
+ /* FALLTHROUGH */
+
+ case XDR_ENCODE:
+ return (xdr_opaque(xdrs, sp, size));
+
+ case XDR_FREE:
+ mem_free(sp, nodesize);
+ *cpp = NULL;
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+/*
+ * Wrapper for xdr_string that can be called directly from
+ * routines like clnt_call
+ */
+bool_t
+xdr_wrapstring(xdrs, cpp)
+ XDR *xdrs;
+ char **cpp;
+{
+ return xdr_string(xdrs, cpp, LASTUNSIGNED);
+}
+
+/*
+ * NOTE: xdr_hyper(), xdr_u_hyper(), xdr_longlong_t(), and xdr_u_longlong_t()
+ * are in the "non-portable" section because they require that a `long long'
+ * be a 64-bit type.
+ *
+ * --thorpej@netbsd.org, November 30, 1999
+ */
+
+/*
+ * XDR 64-bit integers
+ */
+bool_t
+xdr_int64_t(xdrs, llp)
+ XDR *xdrs;
+ int64_t *llp;
+{
+ u_long ul[2];
+
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ ul[0] = (u_long)((u_int64_t)*llp >> 32) & 0xffffffff;
+ ul[1] = (u_long)((u_int64_t)*llp) & 0xffffffff;
+ if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
+ return (FALSE);
+ return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
+ case XDR_DECODE:
+ if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
+ return (FALSE);
+ if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
+ return (FALSE);
+ *llp = (int64_t)
+ (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
+ return (TRUE);
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+
+/*
+ * XDR unsigned 64-bit integers
+ */
+bool_t
+xdr_u_int64_t(xdrs, ullp)
+ XDR *xdrs;
+ u_int64_t *ullp;
+{
+ u_long ul[2];
+
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ ul[0] = (u_long)(*ullp >> 32) & 0xffffffff;
+ ul[1] = (u_long)(*ullp) & 0xffffffff;
+ if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
+ return (FALSE);
+ return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
+ case XDR_DECODE:
+ if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
+ return (FALSE);
+ if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
+ return (FALSE);
+ *ullp = (u_int64_t)
+ (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
+ return (TRUE);
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+/*
+ * XDR unsigned 64-bit integers
+ */
+bool_t
+xdr_uint64_t(xdrs, ullp)
+ XDR *xdrs;
+ uint64_t *ullp;
+{
+ u_long ul[2];
+
+ switch (xdrs->x_op) {
+ case XDR_ENCODE:
+ ul[0] = (u_long)(*ullp >> 32) & 0xffffffff;
+ ul[1] = (u_long)(*ullp) & 0xffffffff;
+ if (XDR_PUTLONG(xdrs, (long *)&ul[0]) == FALSE)
+ return (FALSE);
+ return (XDR_PUTLONG(xdrs, (long *)&ul[1]));
+ case XDR_DECODE:
+ if (XDR_GETLONG(xdrs, (long *)&ul[0]) == FALSE)
+ return (FALSE);
+ if (XDR_GETLONG(xdrs, (long *)&ul[1]) == FALSE)
+ return (FALSE);
+ *ullp = (u_int64_t)
+ (((u_int64_t)ul[0] << 32) | ((u_int64_t)ul[1]));
+ return (TRUE);
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+
+/*
+ * XDR hypers
+ */
+bool_t
+xdr_hyper(xdrs, llp)
+ XDR *xdrs;
+ longlong_t *llp;
+{
+
+ /*
+ * Don't bother open-coding this; it's a fair amount of code. Just
+ * call xdr_int64_t().
+ */
+ return (xdr_int64_t(xdrs, (int64_t *)llp));
+}
+
+
+/*
+ * XDR unsigned hypers
+ */
+bool_t
+xdr_u_hyper(xdrs, ullp)
+ XDR *xdrs;
+ u_longlong_t *ullp;
+{
+
+ /*
+ * Don't bother open-coding this; it's a fair amount of code. Just
+ * call xdr_u_int64_t().
+ */
+ return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp));
+}
+
+
+/*
+ * XDR longlong_t's
+ */
+bool_t
+xdr_longlong_t(xdrs, llp)
+ XDR *xdrs;
+ longlong_t *llp;
+{
+
+ /*
+ * Don't bother open-coding this; it's a fair amount of code. Just
+ * call xdr_int64_t().
+ */
+ return (xdr_int64_t(xdrs, (int64_t *)llp));
+}
+
+
+/*
+ * XDR u_longlong_t's
+ */
+bool_t
+xdr_u_longlong_t(xdrs, ullp)
+ XDR *xdrs;
+ u_longlong_t *ullp;
+{
+
+ /*
+ * Don't bother open-coding this; it's a fair amount of code. Just
+ * call xdr_u_int64_t().
+ */
+ return (xdr_u_int64_t(xdrs, (u_int64_t *)ullp));
+}
diff --git a/lib/libc/xdr/xdr_array.c b/lib/libc/xdr/xdr_array.c
new file mode 100644
index 0000000..6c35452
--- /dev/null
+++ b/lib/libc/xdr/xdr_array.c
@@ -0,0 +1,163 @@
+/* $NetBSD: xdr_array.c,v 1.12 2000/01/22 22:19:18 mycroft Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)xdr_array.c 1.10 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)xdr_array.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * xdr_array.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These are the "non-trivial" xdr primitives used to serialize and de-serialize
+ * arrays. See xdr.h for more info on the interface to xdr.
+ */
+
+#include "namespace.h"
+#include <err.h>
+#include <limits.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include "un-namespace.h"
+
+/*
+ * XDR an array of arbitrary elements
+ * *addrp is a pointer to the array, *sizep is the number of elements.
+ * If addrp is NULL (*sizep * elsize) bytes are allocated.
+ * elsize is the size (in bytes) of each element, and elproc is the
+ * xdr procedure to call to handle each element of the array.
+ */
+bool_t
+xdr_array(xdrs, addrp, sizep, maxsize, elsize, elproc)
+ XDR *xdrs;
+ caddr_t *addrp; /* array pointer */
+ u_int *sizep; /* number of elements */
+ u_int maxsize; /* max numberof elements */
+ u_int elsize; /* size in bytes of each element */
+ xdrproc_t elproc; /* xdr routine to handle each element */
+{
+ u_int i;
+ caddr_t target = *addrp;
+ u_int c; /* the actual element count */
+ bool_t stat = TRUE;
+ u_int nodesize;
+
+ /* like strings, arrays are really counted arrays */
+ if (!xdr_u_int(xdrs, sizep)) {
+ return (FALSE);
+ }
+ c = *sizep;
+ if ((c > maxsize || UINT_MAX/elsize < c) &&
+ (xdrs->x_op != XDR_FREE)) {
+ return (FALSE);
+ }
+ nodesize = c * elsize;
+
+ /*
+ * if we are deserializing, we may need to allocate an array.
+ * We also save time by checking for a null array if we are freeing.
+ */
+ if (target == NULL)
+ switch (xdrs->x_op) {
+ case XDR_DECODE:
+ if (c == 0)
+ return (TRUE);
+ *addrp = target = mem_alloc(nodesize);
+ if (target == NULL) {
+ warnx("xdr_array: out of memory");
+ return (FALSE);
+ }
+ memset(target, 0, nodesize);
+ break;
+
+ case XDR_FREE:
+ return (TRUE);
+
+ case XDR_ENCODE:
+ break;
+ }
+
+ /*
+ * now we xdr each element of array
+ */
+ for (i = 0; (i < c) && stat; i++) {
+ stat = (*elproc)(xdrs, target);
+ target += elsize;
+ }
+
+ /*
+ * the array may need freeing
+ */
+ if (xdrs->x_op == XDR_FREE) {
+ mem_free(*addrp, nodesize);
+ *addrp = NULL;
+ }
+ return (stat);
+}
+
+/*
+ * xdr_vector():
+ *
+ * XDR a fixed length array. Unlike variable-length arrays,
+ * the storage of fixed length arrays is static and unfreeable.
+ * > basep: base of the array
+ * > size: size of the array
+ * > elemsize: size of each element
+ * > xdr_elem: routine to XDR each element
+ */
+bool_t
+xdr_vector(xdrs, basep, nelem, elemsize, xdr_elem)
+ XDR *xdrs;
+ char *basep;
+ u_int nelem;
+ u_int elemsize;
+ xdrproc_t xdr_elem;
+{
+ u_int i;
+ char *elptr;
+
+ elptr = basep;
+ for (i = 0; i < nelem; i++) {
+ if (!(*xdr_elem)(xdrs, elptr)) {
+ return(FALSE);
+ }
+ elptr += elemsize;
+ }
+ return(TRUE);
+}
diff --git a/lib/libc/xdr/xdr_float.c b/lib/libc/xdr/xdr_float.c
new file mode 100644
index 0000000..0a4f09f
--- /dev/null
+++ b/lib/libc/xdr/xdr_float.c
@@ -0,0 +1,309 @@
+/* $NetBSD: xdr_float.c,v 1.23 2000/07/17 04:59:51 matt Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)xdr_float.c 1.12 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)xdr_float.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * xdr_float.c, Generic XDR routines implementation.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These are the "floating point" xdr routines used to (de)serialize
+ * most common data items. See xdr.h for more info on the interface to
+ * xdr.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+#include <sys/param.h>
+
+#include <stdio.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include "un-namespace.h"
+
+/*
+ * NB: Not portable.
+ * This routine works on machines with IEEE754 FP and Vaxen.
+ */
+
+#if defined(__m68k__) || defined(__sparc__) || defined(__i386__) || \
+ defined(__mips__) || defined(__ns32k__) || defined(__alpha__) || \
+ defined(__arm__) || defined(__ppc__) || defined(__ia64__) || \
+ defined(__arm26__) || defined(__sparc64__) || defined(__amd64__)
+#include <machine/endian.h>
+#define IEEEFP
+#endif
+
+#if defined(__vax__)
+
+/* What IEEE single precision floating point looks like on a Vax */
+struct ieee_single {
+ unsigned int mantissa: 23;
+ unsigned int exp : 8;
+ unsigned int sign : 1;
+};
+
+/* Vax single precision floating point */
+struct vax_single {
+ unsigned int mantissa1 : 7;
+ unsigned int exp : 8;
+ unsigned int sign : 1;
+ unsigned int mantissa2 : 16;
+};
+
+#define VAX_SNG_BIAS 0x81
+#define IEEE_SNG_BIAS 0x7f
+
+static struct sgl_limits {
+ struct vax_single s;
+ struct ieee_single ieee;
+} sgl_limits[2] = {
+ {{ 0x7f, 0xff, 0x0, 0xffff }, /* Max Vax */
+ { 0x0, 0xff, 0x0 }}, /* Max IEEE */
+ {{ 0x0, 0x0, 0x0, 0x0 }, /* Min Vax */
+ { 0x0, 0x0, 0x0 }} /* Min IEEE */
+};
+#endif /* vax */
+
+bool_t
+xdr_float(xdrs, fp)
+ XDR *xdrs;
+ float *fp;
+{
+#ifndef IEEEFP
+ struct ieee_single is;
+ struct vax_single vs, *vsp;
+ struct sgl_limits *lim;
+ int i;
+#endif
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+#ifdef IEEEFP
+ return (XDR_PUTINT32(xdrs, (int32_t *)fp));
+#else
+ vs = *((struct vax_single *)fp);
+ for (i = 0, lim = sgl_limits;
+ i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
+ i++, lim++) {
+ if ((vs.mantissa2 == lim->s.mantissa2) &&
+ (vs.exp == lim->s.exp) &&
+ (vs.mantissa1 == lim->s.mantissa1)) {
+ is = lim->ieee;
+ goto shipit;
+ }
+ }
+ is.exp = vs.exp - VAX_SNG_BIAS + IEEE_SNG_BIAS;
+ is.mantissa = (vs.mantissa1 << 16) | vs.mantissa2;
+ shipit:
+ is.sign = vs.sign;
+ return (XDR_PUTINT32(xdrs, (int32_t *)&is));
+#endif
+
+ case XDR_DECODE:
+#ifdef IEEEFP
+ return (XDR_GETINT32(xdrs, (int32_t *)fp));
+#else
+ vsp = (struct vax_single *)fp;
+ if (!XDR_GETINT32(xdrs, (int32_t *)&is))
+ return (FALSE);
+ for (i = 0, lim = sgl_limits;
+ i < sizeof(sgl_limits)/sizeof(struct sgl_limits);
+ i++, lim++) {
+ if ((is.exp == lim->ieee.exp) &&
+ (is.mantissa == lim->ieee.mantissa)) {
+ *vsp = lim->s;
+ goto doneit;
+ }
+ }
+ vsp->exp = is.exp - IEEE_SNG_BIAS + VAX_SNG_BIAS;
+ vsp->mantissa2 = is.mantissa;
+ vsp->mantissa1 = (is.mantissa >> 16);
+ doneit:
+ vsp->sign = is.sign;
+ return (TRUE);
+#endif
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
+
+#if defined(__vax__)
+/* What IEEE double precision floating point looks like on a Vax */
+struct ieee_double {
+ unsigned int mantissa1 : 20;
+ unsigned int exp : 11;
+ unsigned int sign : 1;
+ unsigned int mantissa2 : 32;
+};
+
+/* Vax double precision floating point */
+struct vax_double {
+ unsigned int mantissa1 : 7;
+ unsigned int exp : 8;
+ unsigned int sign : 1;
+ unsigned int mantissa2 : 16;
+ unsigned int mantissa3 : 16;
+ unsigned int mantissa4 : 16;
+};
+
+#define VAX_DBL_BIAS 0x81
+#define IEEE_DBL_BIAS 0x3ff
+#define MASK(nbits) ((1 << nbits) - 1)
+
+static struct dbl_limits {
+ struct vax_double d;
+ struct ieee_double ieee;
+} dbl_limits[2] = {
+ {{ 0x7f, 0xff, 0x0, 0xffff, 0xffff, 0xffff }, /* Max Vax */
+ { 0x0, 0x7ff, 0x0, 0x0 }}, /* Max IEEE */
+ {{ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}, /* Min Vax */
+ { 0x0, 0x0, 0x0, 0x0 }} /* Min IEEE */
+};
+
+#endif /* vax */
+
+
+bool_t
+xdr_double(xdrs, dp)
+ XDR *xdrs;
+ double *dp;
+{
+#ifdef IEEEFP
+ int32_t *i32p;
+ bool_t rv;
+#else
+ int32_t *lp;
+ struct ieee_double id;
+ struct vax_double vd;
+ struct dbl_limits *lim;
+ int i;
+#endif
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+#ifdef IEEEFP
+ i32p = (int32_t *)(void *)dp;
+#if BYTE_ORDER == BIG_ENDIAN
+ rv = XDR_PUTINT32(xdrs, i32p);
+ if (!rv)
+ return (rv);
+ rv = XDR_PUTINT32(xdrs, i32p+1);
+#else
+ rv = XDR_PUTINT32(xdrs, i32p+1);
+ if (!rv)
+ return (rv);
+ rv = XDR_PUTINT32(xdrs, i32p);
+#endif
+ return (rv);
+#else
+ vd = *((struct vax_double *)dp);
+ for (i = 0, lim = dbl_limits;
+ i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+ i++, lim++) {
+ if ((vd.mantissa4 == lim->d.mantissa4) &&
+ (vd.mantissa3 == lim->d.mantissa3) &&
+ (vd.mantissa2 == lim->d.mantissa2) &&
+ (vd.mantissa1 == lim->d.mantissa1) &&
+ (vd.exp == lim->d.exp)) {
+ id = lim->ieee;
+ goto shipit;
+ }
+ }
+ id.exp = vd.exp - VAX_DBL_BIAS + IEEE_DBL_BIAS;
+ id.mantissa1 = (vd.mantissa1 << 13) | (vd.mantissa2 >> 3);
+ id.mantissa2 = ((vd.mantissa2 & MASK(3)) << 29) |
+ (vd.mantissa3 << 13) |
+ ((vd.mantissa4 >> 3) & MASK(13));
+ shipit:
+ id.sign = vd.sign;
+ lp = (int32_t *)&id;
+ return (XDR_PUTINT32(xdrs, lp++) && XDR_PUTINT32(xdrs, lp));
+#endif
+
+ case XDR_DECODE:
+#ifdef IEEEFP
+ i32p = (int32_t *)(void *)dp;
+#if BYTE_ORDER == BIG_ENDIAN
+ rv = XDR_GETINT32(xdrs, i32p);
+ if (!rv)
+ return (rv);
+ rv = XDR_GETINT32(xdrs, i32p+1);
+#else
+ rv = XDR_GETINT32(xdrs, i32p+1);
+ if (!rv)
+ return (rv);
+ rv = XDR_GETINT32(xdrs, i32p);
+#endif
+ return (rv);
+#else
+ lp = (int32_t *)&id;
+ if (!XDR_GETINT32(xdrs, lp++) || !XDR_GETINT32(xdrs, lp))
+ return (FALSE);
+ for (i = 0, lim = dbl_limits;
+ i < sizeof(dbl_limits)/sizeof(struct dbl_limits);
+ i++, lim++) {
+ if ((id.mantissa2 == lim->ieee.mantissa2) &&
+ (id.mantissa1 == lim->ieee.mantissa1) &&
+ (id.exp == lim->ieee.exp)) {
+ vd = lim->d;
+ goto doneit;
+ }
+ }
+ vd.exp = id.exp - IEEE_DBL_BIAS + VAX_DBL_BIAS;
+ vd.mantissa1 = (id.mantissa1 >> 13);
+ vd.mantissa2 = ((id.mantissa1 & MASK(13)) << 3) |
+ (id.mantissa2 >> 29);
+ vd.mantissa3 = (id.mantissa2 >> 13);
+ vd.mantissa4 = (id.mantissa2 << 3);
+ doneit:
+ vd.sign = id.sign;
+ *dp = *((double *)&vd);
+ return (TRUE);
+#endif
+
+ case XDR_FREE:
+ return (TRUE);
+ }
+ /* NOTREACHED */
+ return (FALSE);
+}
diff --git a/lib/libc/xdr/xdr_mem.c b/lib/libc/xdr/xdr_mem.c
new file mode 100644
index 0000000..138269c
--- /dev/null
+++ b/lib/libc/xdr/xdr_mem.c
@@ -0,0 +1,260 @@
+/* $NetBSD: xdr_mem.c,v 1.15 2000/01/22 22:19:18 mycroft Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)xdr_mem.c 1.19 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)xdr_mem.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * xdr_mem.h, XDR implementation using memory buffers.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * If you have some data to be interpreted as external data representation
+ * or to be converted to external data representation in a memory buffer,
+ * then this is the package for you.
+ *
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+
+#include <netinet/in.h>
+
+#include <string.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include "un-namespace.h"
+
+static void xdrmem_destroy(XDR *);
+static bool_t xdrmem_getlong_aligned(XDR *, long *);
+static bool_t xdrmem_putlong_aligned(XDR *, const long *);
+static bool_t xdrmem_getlong_unaligned(XDR *, long *);
+static bool_t xdrmem_putlong_unaligned(XDR *, const long *);
+static bool_t xdrmem_getbytes(XDR *, char *, u_int);
+static bool_t xdrmem_putbytes(XDR *, const char *, u_int);
+/* XXX: w/64-bit pointers, u_int not enough! */
+static u_int xdrmem_getpos(XDR *);
+static bool_t xdrmem_setpos(XDR *, u_int);
+static int32_t *xdrmem_inline_aligned(XDR *, u_int);
+static int32_t *xdrmem_inline_unaligned(XDR *, u_int);
+
+static const struct xdr_ops xdrmem_ops_aligned = {
+ xdrmem_getlong_aligned,
+ xdrmem_putlong_aligned,
+ xdrmem_getbytes,
+ xdrmem_putbytes,
+ xdrmem_getpos,
+ xdrmem_setpos,
+ xdrmem_inline_aligned,
+ xdrmem_destroy
+};
+
+static const struct xdr_ops xdrmem_ops_unaligned = {
+ xdrmem_getlong_unaligned,
+ xdrmem_putlong_unaligned,
+ xdrmem_getbytes,
+ xdrmem_putbytes,
+ xdrmem_getpos,
+ xdrmem_setpos,
+ xdrmem_inline_unaligned,
+ xdrmem_destroy
+};
+
+/*
+ * The procedure xdrmem_create initializes a stream descriptor for a
+ * memory buffer.
+ */
+void
+xdrmem_create(xdrs, addr, size, op)
+ XDR *xdrs;
+ char *addr;
+ u_int size;
+ enum xdr_op op;
+{
+
+ xdrs->x_op = op;
+ xdrs->x_ops = ((unsigned long)addr & (sizeof(int32_t) - 1))
+ ? &xdrmem_ops_unaligned : &xdrmem_ops_aligned;
+ xdrs->x_private = xdrs->x_base = addr;
+ xdrs->x_handy = size;
+}
+
+/*ARGSUSED*/
+static void
+xdrmem_destroy(xdrs)
+ XDR *xdrs;
+{
+
+}
+
+static bool_t
+xdrmem_getlong_aligned(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+
+ if (xdrs->x_handy < sizeof(int32_t))
+ return (FALSE);
+ xdrs->x_handy -= sizeof(int32_t);
+ *lp = ntohl(*(u_int32_t *)xdrs->x_private);
+ xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putlong_aligned(xdrs, lp)
+ XDR *xdrs;
+ const long *lp;
+{
+
+ if (xdrs->x_handy < sizeof(int32_t))
+ return (FALSE);
+ xdrs->x_handy -= sizeof(int32_t);
+ *(u_int32_t *)xdrs->x_private = htonl((u_int32_t)*lp);
+ xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_getlong_unaligned(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+ u_int32_t l;
+
+ if (xdrs->x_handy < sizeof(int32_t))
+ return (FALSE);
+ xdrs->x_handy -= sizeof(int32_t);
+ memmove(&l, xdrs->x_private, sizeof(int32_t));
+ *lp = ntohl(l);
+ xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putlong_unaligned(xdrs, lp)
+ XDR *xdrs;
+ const long *lp;
+{
+ u_int32_t l;
+
+ if (xdrs->x_handy < sizeof(int32_t))
+ return (FALSE);
+ xdrs->x_handy -= sizeof(int32_t);
+ l = htonl((u_int32_t)*lp);
+ memmove(xdrs->x_private, &l, sizeof(int32_t));
+ xdrs->x_private = (char *)xdrs->x_private + sizeof(int32_t);
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_getbytes(xdrs, addr, len)
+ XDR *xdrs;
+ char *addr;
+ u_int len;
+{
+
+ if (xdrs->x_handy < len)
+ return (FALSE);
+ xdrs->x_handy -= len;
+ memmove(addr, xdrs->x_private, len);
+ xdrs->x_private = (char *)xdrs->x_private + len;
+ return (TRUE);
+}
+
+static bool_t
+xdrmem_putbytes(xdrs, addr, len)
+ XDR *xdrs;
+ const char *addr;
+ u_int len;
+{
+
+ if (xdrs->x_handy < len)
+ return (FALSE);
+ xdrs->x_handy -= len;
+ memmove(xdrs->x_private, addr, len);
+ xdrs->x_private = (char *)xdrs->x_private + len;
+ return (TRUE);
+}
+
+static u_int
+xdrmem_getpos(xdrs)
+ XDR *xdrs;
+{
+
+ /* XXX w/64-bit pointers, u_int not enough! */
+ return (u_int)((u_long)xdrs->x_private - (u_long)xdrs->x_base);
+}
+
+static bool_t
+xdrmem_setpos(xdrs, pos)
+ XDR *xdrs;
+ u_int pos;
+{
+ char *newaddr = xdrs->x_base + pos;
+ char *lastaddr = (char *)xdrs->x_private + xdrs->x_handy;
+
+ if (newaddr > lastaddr)
+ return (FALSE);
+ xdrs->x_private = newaddr;
+ xdrs->x_handy = (u_int)(lastaddr - newaddr); /* XXX sizeof(u_int) <? sizeof(ptrdiff_t) */
+ return (TRUE);
+}
+
+static int32_t *
+xdrmem_inline_aligned(xdrs, len)
+ XDR *xdrs;
+ u_int len;
+{
+ int32_t *buf = 0;
+
+ if (xdrs->x_handy >= len) {
+ xdrs->x_handy -= len;
+ buf = (int32_t *)xdrs->x_private;
+ xdrs->x_private = (char *)xdrs->x_private + len;
+ }
+ return (buf);
+}
+
+/* ARGSUSED */
+static int32_t *
+xdrmem_inline_unaligned(xdrs, len)
+ XDR *xdrs;
+ u_int len;
+{
+
+ return (0);
+}
diff --git a/lib/libc/xdr/xdr_rec.c b/lib/libc/xdr/xdr_rec.c
new file mode 100644
index 0000000..dc4aa18
--- /dev/null
+++ b/lib/libc/xdr/xdr_rec.c
@@ -0,0 +1,795 @@
+/* $NetBSD: xdr_rec.c,v 1.18 2000/07/06 03:10:35 christos Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)xdr_rec.c 1.21 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)xdr_rec.c 2.2 88/08/01 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * xdr_rec.c, Implements TCP/IP based XDR streams with a "record marking"
+ * layer above tcp (for rpc's use).
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * These routines interface XDRSTREAMS to a tcp/ip connection.
+ * There is a record marking layer between the xdr stream
+ * and the tcp transport level. A record is composed on one or more
+ * record fragments. A record fragment is a thirty-two bit header followed
+ * by n bytes of data, where n is contained in the header. The header
+ * is represented as a htonl(u_long). Thegh order bit encodes
+ * whether or not the fragment is the last fragment of the record
+ * (1 => fragment is last, 0 => more fragments to follow.
+ * The other 31 bits encode the byte length of the fragment.
+ */
+
+#include "namespace.h"
+#include <sys/types.h>
+
+#include <netinet/in.h>
+
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <rpc/auth.h>
+#include <rpc/svc.h>
+#include <rpc/clnt.h>
+#include <sys/stddef.h>
+#include "un-namespace.h"
+#include "rpc_com.h"
+
+static bool_t xdrrec_getlong(XDR *, long *);
+static bool_t xdrrec_putlong(XDR *, const long *);
+static bool_t xdrrec_getbytes(XDR *, char *, u_int);
+
+static bool_t xdrrec_putbytes(XDR *, const char *, u_int);
+static u_int xdrrec_getpos(XDR *);
+static bool_t xdrrec_setpos(XDR *, u_int);
+static int32_t *xdrrec_inline(XDR *, u_int);
+static void xdrrec_destroy(XDR *);
+
+static const struct xdr_ops xdrrec_ops = {
+ xdrrec_getlong,
+ xdrrec_putlong,
+ xdrrec_getbytes,
+ xdrrec_putbytes,
+ xdrrec_getpos,
+ xdrrec_setpos,
+ xdrrec_inline,
+ xdrrec_destroy
+};
+
+/*
+ * A record is composed of one or more record fragments.
+ * A record fragment is a four-byte header followed by zero to
+ * 2**32-1 bytes. The header is treated as a long unsigned and is
+ * encode/decoded to the network via htonl/ntohl. The low order 31 bits
+ * are a byte count of the fragment. The highest order bit is a boolean:
+ * 1 => this fragment is the last fragment of the record,
+ * 0 => this fragment is followed by more fragment(s).
+ *
+ * The fragment/record machinery is not general; it is constructed to
+ * meet the needs of xdr and rpc based on tcp.
+ */
+
+#define LAST_FRAG ((u_int32_t)(1 << 31))
+
+typedef struct rec_strm {
+ char *tcp_handle;
+ /*
+ * out-goung bits
+ */
+ int (*writeit)(void *, void *, int);
+ char *out_base; /* output buffer (points to frag header) */
+ char *out_finger; /* next output position */
+ char *out_boundry; /* data cannot up to this address */
+ u_int32_t *frag_header; /* beginning of curren fragment */
+ bool_t frag_sent; /* true if buffer sent in middle of record */
+ /*
+ * in-coming bits
+ */
+ int (*readit)(void *, void *, int);
+ u_long in_size; /* fixed size of the input buffer */
+ char *in_base;
+ char *in_finger; /* location of next byte to be had */
+ char *in_boundry; /* can read up to this location */
+ long fbtbc; /* fragment bytes to be consumed */
+ bool_t last_frag;
+ u_int sendsize;
+ u_int recvsize;
+
+ bool_t nonblock;
+ bool_t in_haveheader;
+ u_int32_t in_header;
+ char *in_hdrp;
+ int in_hdrlen;
+ int in_reclen;
+ int in_received;
+ int in_maxrec;
+} RECSTREAM;
+
+static u_int fix_buf_size(u_int);
+static bool_t flush_out(RECSTREAM *, bool_t);
+static bool_t fill_input_buf(RECSTREAM *);
+static bool_t get_input_bytes(RECSTREAM *, char *, int);
+static bool_t set_input_fragment(RECSTREAM *);
+static bool_t skip_input_bytes(RECSTREAM *, long);
+static bool_t realloc_stream(RECSTREAM *, int);
+
+
+/*
+ * Create an xdr handle for xdrrec
+ * xdrrec_create fills in xdrs. Sendsize and recvsize are
+ * send and recv buffer sizes (0 => use default).
+ * tcp_handle is an opaque handle that is passed as the first parameter to
+ * the procedures readit and writeit. Readit and writeit are read and
+ * write respectively. They are like the system
+ * calls expect that they take an opaque handle rather than an fd.
+ */
+void
+xdrrec_create(xdrs, sendsize, recvsize, tcp_handle, readit, writeit)
+ XDR *xdrs;
+ u_int sendsize;
+ u_int recvsize;
+ void *tcp_handle;
+ /* like read, but pass it a tcp_handle, not sock */
+ int (*readit)(void *, void *, int);
+ /* like write, but pass it a tcp_handle, not sock */
+ int (*writeit)(void *, void *, int);
+{
+ RECSTREAM *rstrm = mem_alloc(sizeof(RECSTREAM));
+
+ if (rstrm == NULL) {
+ warnx("xdrrec_create: out of memory");
+ /*
+ * This is bad. Should rework xdrrec_create to
+ * return a handle, and in this case return NULL
+ */
+ return;
+ }
+ rstrm->sendsize = sendsize = fix_buf_size(sendsize);
+ rstrm->out_base = mem_alloc(rstrm->sendsize);
+ if (rstrm->out_base == NULL) {
+ warnx("xdrrec_create: out of memory");
+ mem_free(rstrm, sizeof(RECSTREAM));
+ return;
+ }
+ rstrm->recvsize = recvsize = fix_buf_size(recvsize);
+ rstrm->in_base = mem_alloc(recvsize);
+ if (rstrm->in_base == NULL) {
+ warnx("xdrrec_create: out of memory");
+ mem_free(rstrm->out_base, sendsize);
+ mem_free(rstrm, sizeof(RECSTREAM));
+ return;
+ }
+ /*
+ * now the rest ...
+ */
+ xdrs->x_ops = &xdrrec_ops;
+ xdrs->x_private = rstrm;
+ rstrm->tcp_handle = tcp_handle;
+ rstrm->readit = readit;
+ rstrm->writeit = writeit;
+ rstrm->out_finger = rstrm->out_boundry = rstrm->out_base;
+ rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base;
+ rstrm->out_finger += sizeof(u_int32_t);
+ rstrm->out_boundry += sendsize;
+ rstrm->frag_sent = FALSE;
+ rstrm->in_size = recvsize;
+ rstrm->in_boundry = rstrm->in_base;
+ rstrm->in_finger = (rstrm->in_boundry += recvsize);
+ rstrm->fbtbc = 0;
+ rstrm->last_frag = TRUE;
+ rstrm->in_haveheader = FALSE;
+ rstrm->in_hdrlen = 0;
+ rstrm->in_hdrp = (char *)(void *)&rstrm->in_header;
+ rstrm->nonblock = FALSE;
+ rstrm->in_reclen = 0;
+ rstrm->in_received = 0;
+}
+
+
+/*
+ * The reoutines defined below are the xdr ops which will go into the
+ * xdr handle filled in by xdrrec_create.
+ */
+
+static bool_t
+xdrrec_getlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ int32_t *buflp = (int32_t *)(void *)(rstrm->in_finger);
+ int32_t mylong;
+
+ /* first try the inline, fast case */
+ if ((rstrm->fbtbc >= sizeof(int32_t)) &&
+ (((long)rstrm->in_boundry - (long)buflp) >= sizeof(int32_t))) {
+ *lp = (long)ntohl((u_int32_t)(*buflp));
+ rstrm->fbtbc -= sizeof(int32_t);
+ rstrm->in_finger += sizeof(int32_t);
+ } else {
+ if (! xdrrec_getbytes(xdrs, (char *)(void *)&mylong,
+ sizeof(int32_t)))
+ return (FALSE);
+ *lp = (long)ntohl((u_int32_t)mylong);
+ }
+ return (TRUE);
+}
+
+static bool_t
+xdrrec_putlong(xdrs, lp)
+ XDR *xdrs;
+ const long *lp;
+{
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ int32_t *dest_lp = ((int32_t *)(void *)(rstrm->out_finger));
+
+ if ((rstrm->out_finger += sizeof(int32_t)) > rstrm->out_boundry) {
+ /*
+ * this case should almost never happen so the code is
+ * inefficient
+ */
+ rstrm->out_finger -= sizeof(int32_t);
+ rstrm->frag_sent = TRUE;
+ if (! flush_out(rstrm, FALSE))
+ return (FALSE);
+ dest_lp = ((int32_t *)(void *)(rstrm->out_finger));
+ rstrm->out_finger += sizeof(int32_t);
+ }
+ *dest_lp = (int32_t)htonl((u_int32_t)(*lp));
+ return (TRUE);
+}
+
+static bool_t /* must manage buffers, fragments, and records */
+xdrrec_getbytes(xdrs, addr, len)
+ XDR *xdrs;
+ char *addr;
+ u_int len;
+{
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ int current;
+
+ while (len > 0) {
+ current = (int)rstrm->fbtbc;
+ if (current == 0) {
+ if (rstrm->last_frag)
+ return (FALSE);
+ if (! set_input_fragment(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (len < current) ? len : current;
+ if (! get_input_bytes(rstrm, addr, current))
+ return (FALSE);
+ addr += current;
+ rstrm->fbtbc -= current;
+ len -= current;
+ }
+ return (TRUE);
+}
+
+static bool_t
+xdrrec_putbytes(xdrs, addr, len)
+ XDR *xdrs;
+ const char *addr;
+ u_int len;
+{
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ size_t current;
+
+ while (len > 0) {
+ current = (size_t)((u_long)rstrm->out_boundry -
+ (u_long)rstrm->out_finger);
+ current = (len < current) ? len : current;
+ memmove(rstrm->out_finger, addr, current);
+ rstrm->out_finger += current;
+ addr += current;
+ len -= current;
+ if (rstrm->out_finger == rstrm->out_boundry) {
+ rstrm->frag_sent = TRUE;
+ if (! flush_out(rstrm, FALSE))
+ return (FALSE);
+ }
+ }
+ return (TRUE);
+}
+
+static u_int
+xdrrec_getpos(xdrs)
+ XDR *xdrs;
+{
+ RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ off_t pos;
+
+ pos = lseek((int)(u_long)rstrm->tcp_handle, (off_t)0, 1);
+ if (pos == -1)
+ pos = 0;
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ pos += rstrm->out_finger - rstrm->out_base;
+ break;
+
+ case XDR_DECODE:
+ pos -= rstrm->in_boundry - rstrm->in_finger;
+ break;
+
+ default:
+ pos = (off_t) -1;
+ break;
+ }
+ return ((u_int) pos);
+}
+
+static bool_t
+xdrrec_setpos(xdrs, pos)
+ XDR *xdrs;
+ u_int pos;
+{
+ RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ u_int currpos = xdrrec_getpos(xdrs);
+ int delta = currpos - pos;
+ char *newpos;
+
+ if ((int)currpos != -1)
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ newpos = rstrm->out_finger - delta;
+ if ((newpos > (char *)(void *)(rstrm->frag_header)) &&
+ (newpos < rstrm->out_boundry)) {
+ rstrm->out_finger = newpos;
+ return (TRUE);
+ }
+ break;
+
+ case XDR_DECODE:
+ newpos = rstrm->in_finger - delta;
+ if ((delta < (int)(rstrm->fbtbc)) &&
+ (newpos <= rstrm->in_boundry) &&
+ (newpos >= rstrm->in_base)) {
+ rstrm->in_finger = newpos;
+ rstrm->fbtbc -= delta;
+ return (TRUE);
+ }
+ break;
+
+ case XDR_FREE:
+ break;
+ }
+ return (FALSE);
+}
+
+static int32_t *
+xdrrec_inline(xdrs, len)
+ XDR *xdrs;
+ u_int len;
+{
+ RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+ int32_t *buf = NULL;
+
+ switch (xdrs->x_op) {
+
+ case XDR_ENCODE:
+ if ((rstrm->out_finger + len) <= rstrm->out_boundry) {
+ buf = (int32_t *)(void *)rstrm->out_finger;
+ rstrm->out_finger += len;
+ }
+ break;
+
+ case XDR_DECODE:
+ if ((len <= rstrm->fbtbc) &&
+ ((rstrm->in_finger + len) <= rstrm->in_boundry)) {
+ buf = (int32_t *)(void *)rstrm->in_finger;
+ rstrm->fbtbc -= len;
+ rstrm->in_finger += len;
+ }
+ break;
+
+ case XDR_FREE:
+ break;
+ }
+ return (buf);
+}
+
+static void
+xdrrec_destroy(xdrs)
+ XDR *xdrs;
+{
+ RECSTREAM *rstrm = (RECSTREAM *)xdrs->x_private;
+
+ mem_free(rstrm->out_base, rstrm->sendsize);
+ mem_free(rstrm->in_base, rstrm->recvsize);
+ mem_free(rstrm, sizeof(RECSTREAM));
+}
+
+
+/*
+ * Exported routines to manage xdr records
+ */
+
+/*
+ * Before reading (deserializing from the stream, one should always call
+ * this procedure to guarantee proper record alignment.
+ */
+bool_t
+xdrrec_skiprecord(xdrs)
+ XDR *xdrs;
+{
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ enum xprt_stat xstat;
+
+ if (rstrm->nonblock) {
+ if (__xdrrec_getrec(xdrs, &xstat, FALSE)) {
+ rstrm->fbtbc = 0;
+ return TRUE;
+ }
+ if (rstrm->in_finger == rstrm->in_boundry &&
+ xstat == XPRT_MOREREQS) {
+ rstrm->fbtbc = 0;
+ return TRUE;
+ }
+ return FALSE;
+ }
+
+ while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
+ if (! skip_input_bytes(rstrm, rstrm->fbtbc))
+ return (FALSE);
+ rstrm->fbtbc = 0;
+ if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
+ return (FALSE);
+ }
+ rstrm->last_frag = FALSE;
+ return (TRUE);
+}
+
+/*
+ * Look ahead function.
+ * Returns TRUE iff there is no more input in the buffer
+ * after consuming the rest of the current record.
+ */
+bool_t
+xdrrec_eof(xdrs)
+ XDR *xdrs;
+{
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+
+ while (rstrm->fbtbc > 0 || (! rstrm->last_frag)) {
+ if (! skip_input_bytes(rstrm, rstrm->fbtbc))
+ return (TRUE);
+ rstrm->fbtbc = 0;
+ if ((! rstrm->last_frag) && (! set_input_fragment(rstrm)))
+ return (TRUE);
+ }
+ if (rstrm->in_finger == rstrm->in_boundry)
+ return (TRUE);
+ return (FALSE);
+}
+
+/*
+ * The client must tell the package when an end-of-record has occurred.
+ * The second paraemters tells whether the record should be flushed to the
+ * (output) tcp stream. (This let's the package support batched or
+ * pipelined procedure calls.) TRUE => immmediate flush to tcp connection.
+ */
+bool_t
+xdrrec_endofrecord(xdrs, sendnow)
+ XDR *xdrs;
+ bool_t sendnow;
+{
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ u_long len; /* fragment length */
+
+ if (sendnow || rstrm->frag_sent ||
+ ((u_long)rstrm->out_finger + sizeof(u_int32_t) >=
+ (u_long)rstrm->out_boundry)) {
+ rstrm->frag_sent = FALSE;
+ return (flush_out(rstrm, TRUE));
+ }
+ len = (u_long)(rstrm->out_finger) - (u_long)(rstrm->frag_header) -
+ sizeof(u_int32_t);
+ *(rstrm->frag_header) = htonl((u_int32_t)len | LAST_FRAG);
+ rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_finger;
+ rstrm->out_finger += sizeof(u_int32_t);
+ return (TRUE);
+}
+
+/*
+ * Fill the stream buffer with a record for a non-blocking connection.
+ * Return true if a record is available in the buffer, false if not.
+ */
+bool_t
+__xdrrec_getrec(xdrs, statp, expectdata)
+ XDR *xdrs;
+ enum xprt_stat *statp;
+ bool_t expectdata;
+{
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+ ssize_t n;
+ int fraglen;
+
+ if (!rstrm->in_haveheader) {
+ n = rstrm->readit(rstrm->tcp_handle, rstrm->in_hdrp,
+ (int)sizeof (rstrm->in_header) - rstrm->in_hdrlen);
+ if (n == 0) {
+ *statp = expectdata ? XPRT_DIED : XPRT_IDLE;
+ return FALSE;
+ }
+ if (n < 0) {
+ *statp = XPRT_DIED;
+ return FALSE;
+ }
+ rstrm->in_hdrp += n;
+ rstrm->in_hdrlen += n;
+ if (rstrm->in_hdrlen < sizeof (rstrm->in_header)) {
+ *statp = XPRT_MOREREQS;
+ return FALSE;
+ }
+ rstrm->in_header = ntohl(rstrm->in_header);
+ fraglen = (int)(rstrm->in_header & ~LAST_FRAG);
+ if (fraglen == 0 || fraglen > rstrm->in_maxrec ||
+ (rstrm->in_reclen + fraglen) > rstrm->in_maxrec) {
+ *statp = XPRT_DIED;
+ return FALSE;
+ }
+ rstrm->in_reclen += fraglen;
+ if (rstrm->in_reclen > rstrm->recvsize)
+ realloc_stream(rstrm, rstrm->in_reclen);
+ if (rstrm->in_header & LAST_FRAG) {
+ rstrm->in_header &= ~LAST_FRAG;
+ rstrm->last_frag = TRUE;
+ }
+ /*
+ * We can only reasonably expect to read once from a
+ * non-blocking stream. Reading the fragment header
+ * may have drained the stream.
+ */
+ expectdata = FALSE;
+ }
+
+ n = rstrm->readit(rstrm->tcp_handle,
+ rstrm->in_base + rstrm->in_received,
+ (rstrm->in_reclen - rstrm->in_received));
+
+ if (n < 0) {
+ *statp = XPRT_DIED;
+ return FALSE;
+ }
+
+ if (n == 0) {
+ *statp = expectdata ? XPRT_DIED : XPRT_IDLE;
+ return FALSE;
+ }
+
+ rstrm->in_received += n;
+
+ if (rstrm->in_received == rstrm->in_reclen) {
+ rstrm->in_haveheader = FALSE;
+ rstrm->in_hdrp = (char *)(void *)&rstrm->in_header;
+ rstrm->in_hdrlen = 0;
+ if (rstrm->last_frag) {
+ rstrm->fbtbc = rstrm->in_reclen;
+ rstrm->in_boundry = rstrm->in_base + rstrm->in_reclen;
+ rstrm->in_finger = rstrm->in_base;
+ rstrm->in_reclen = rstrm->in_received = 0;
+ *statp = XPRT_MOREREQS;
+ return TRUE;
+ }
+ }
+
+ *statp = XPRT_MOREREQS;
+ return FALSE;
+}
+
+bool_t
+__xdrrec_setnonblock(xdrs, maxrec)
+ XDR *xdrs;
+ int maxrec;
+{
+ RECSTREAM *rstrm = (RECSTREAM *)(xdrs->x_private);
+
+ rstrm->nonblock = TRUE;
+ if (maxrec == 0)
+ maxrec = rstrm->recvsize;
+ rstrm->in_maxrec = maxrec;
+ return TRUE;
+}
+
+/*
+ * Internal useful routines
+ */
+static bool_t
+flush_out(rstrm, eor)
+ RECSTREAM *rstrm;
+ bool_t eor;
+{
+ u_int32_t eormask = (eor == TRUE) ? LAST_FRAG : 0;
+ u_int32_t len = (u_int32_t)((u_long)(rstrm->out_finger) -
+ (u_long)(rstrm->frag_header) - sizeof(u_int32_t));
+
+ *(rstrm->frag_header) = htonl(len | eormask);
+ len = (u_int32_t)((u_long)(rstrm->out_finger) -
+ (u_long)(rstrm->out_base));
+ if ((*(rstrm->writeit))(rstrm->tcp_handle, rstrm->out_base, (int)len)
+ != (int)len)
+ return (FALSE);
+ rstrm->frag_header = (u_int32_t *)(void *)rstrm->out_base;
+ rstrm->out_finger = (char *)rstrm->out_base + sizeof(u_int32_t);
+ return (TRUE);
+}
+
+static bool_t /* knows nothing about records! Only about input buffers */
+fill_input_buf(rstrm)
+ RECSTREAM *rstrm;
+{
+ char *where;
+ u_int32_t i;
+ int len;
+
+ if (rstrm->nonblock)
+ return FALSE;
+
+ where = rstrm->in_base;
+ i = (u_int32_t)((u_long)rstrm->in_boundry % BYTES_PER_XDR_UNIT);
+ where += i;
+ len = (u_int32_t)(rstrm->in_size - i);
+ if ((len = (*(rstrm->readit))(rstrm->tcp_handle, where, len)) == -1)
+ return (FALSE);
+ rstrm->in_finger = where;
+ where += len;
+ rstrm->in_boundry = where;
+ return (TRUE);
+}
+
+static bool_t /* knows nothing about records! Only about input buffers */
+get_input_bytes(rstrm, addr, len)
+ RECSTREAM *rstrm;
+ char *addr;
+ int len;
+{
+ size_t current;
+
+ if (rstrm->nonblock) {
+ if (len > (int)(rstrm->in_boundry - rstrm->in_finger))
+ return FALSE;
+ memcpy(addr, rstrm->in_finger, (size_t)len);
+ rstrm->in_finger += len;
+ return TRUE;
+ }
+
+ while (len > 0) {
+ current = (size_t)((long)rstrm->in_boundry -
+ (long)rstrm->in_finger);
+ if (current == 0) {
+ if (! fill_input_buf(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (len < current) ? len : current;
+ memmove(addr, rstrm->in_finger, current);
+ rstrm->in_finger += current;
+ addr += current;
+ len -= current;
+ }
+ return (TRUE);
+}
+
+static bool_t /* next two bytes of the input stream are treated as a header */
+set_input_fragment(rstrm)
+ RECSTREAM *rstrm;
+{
+ u_int32_t header;
+
+ if (rstrm->nonblock)
+ return FALSE;
+ if (! get_input_bytes(rstrm, (char *)(void *)&header, sizeof(header)))
+ return (FALSE);
+ header = ntohl(header);
+ rstrm->last_frag = ((header & LAST_FRAG) == 0) ? FALSE : TRUE;
+ /*
+ * Sanity check. Try not to accept wildly incorrect
+ * record sizes. Unfortunately, the only record size
+ * we can positively identify as being 'wildly incorrect'
+ * is zero. Ridiculously large record sizes may look wrong,
+ * but we don't have any way to be certain that they aren't
+ * what the client actually intended to send us.
+ */
+ if (header == 0)
+ return(FALSE);
+ rstrm->fbtbc = header & (~LAST_FRAG);
+ return (TRUE);
+}
+
+static bool_t /* consumes input bytes; knows nothing about records! */
+skip_input_bytes(rstrm, cnt)
+ RECSTREAM *rstrm;
+ long cnt;
+{
+ u_int32_t current;
+
+ while (cnt > 0) {
+ current = (size_t)((long)rstrm->in_boundry -
+ (long)rstrm->in_finger);
+ if (current == 0) {
+ if (! fill_input_buf(rstrm))
+ return (FALSE);
+ continue;
+ }
+ current = (u_int32_t)((cnt < current) ? cnt : current);
+ rstrm->in_finger += current;
+ cnt -= current;
+ }
+ return (TRUE);
+}
+
+static u_int
+fix_buf_size(s)
+ u_int s;
+{
+
+ if (s < 100)
+ s = 4000;
+ return (RNDUP(s));
+}
+
+/*
+ * Reallocate the input buffer for a non-block stream.
+ */
+static bool_t
+realloc_stream(rstrm, size)
+ RECSTREAM *rstrm;
+ int size;
+{
+ ptrdiff_t diff;
+ char *buf;
+
+ if (size > rstrm->recvsize) {
+ buf = realloc(rstrm->in_base, (size_t)size);
+ if (buf == NULL)
+ return FALSE;
+ diff = buf - rstrm->in_base;
+ rstrm->in_finger += diff;
+ rstrm->in_base = buf;
+ rstrm->in_boundry = buf + size;
+ rstrm->recvsize = size;
+ rstrm->in_size = size;
+ }
+
+ return TRUE;
+}
diff --git a/lib/libc/xdr/xdr_reference.c b/lib/libc/xdr/xdr_reference.c
new file mode 100644
index 0000000..5a497b6
--- /dev/null
+++ b/lib/libc/xdr/xdr_reference.c
@@ -0,0 +1,143 @@
+/* $NetBSD: xdr_reference.c,v 1.13 2000/01/22 22:19:18 mycroft Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)xdr_reference.c 1.11 87/08/11 SMI";
+static char *sccsid = "@(#)xdr_reference.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * xdr_reference.c, Generic XDR routines impelmentation.
+ *
+ * Copyright (C) 1987, Sun Microsystems, Inc.
+ *
+ * These are the "non-trivial" xdr primitives used to serialize and de-serialize
+ * "pointers". See xdr.h for more info on the interface to xdr.
+ */
+
+#include "namespace.h"
+#include <err.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include "libc_private.h"
+
+/*
+ * XDR an indirect pointer
+ * xdr_reference is for recursively translating a structure that is
+ * referenced by a pointer inside the structure that is currently being
+ * translated. pp references a pointer to storage. If *pp is null
+ * the necessary storage is allocated.
+ * size is the sizeof the referneced structure.
+ * proc is the routine to handle the referenced structure.
+ */
+bool_t
+xdr_reference(xdrs, pp, size, proc)
+ XDR *xdrs;
+ caddr_t *pp; /* the pointer to work on */
+ u_int size; /* size of the object pointed to */
+ xdrproc_t proc; /* xdr routine to handle the object */
+{
+ caddr_t loc = *pp;
+ bool_t stat;
+
+ if (loc == NULL)
+ switch (xdrs->x_op) {
+ case XDR_FREE:
+ return (TRUE);
+
+ case XDR_DECODE:
+ *pp = loc = (caddr_t) mem_alloc(size);
+ if (loc == NULL) {
+ warnx("xdr_reference: out of memory");
+ return (FALSE);
+ }
+ memset(loc, 0, size);
+ break;
+
+ case XDR_ENCODE:
+ break;
+ }
+
+ stat = (*proc)(xdrs, loc);
+
+ if (xdrs->x_op == XDR_FREE) {
+ mem_free(loc, size);
+ *pp = NULL;
+ }
+ return (stat);
+}
+
+
+/*
+ * xdr_pointer():
+ *
+ * XDR a pointer to a possibly recursive data structure. This
+ * differs with xdr_reference in that it can serialize/deserialiaze
+ * trees correctly.
+ *
+ * What's sent is actually a union:
+ *
+ * union object_pointer switch (boolean b) {
+ * case TRUE: object_data data;
+ * case FALSE: void nothing;
+ * }
+ *
+ * > objpp: Pointer to the pointer to the object.
+ * > obj_size: size of the object.
+ * > xdr_obj: routine to XDR an object.
+ *
+ */
+bool_t
+xdr_pointer(xdrs,objpp,obj_size,xdr_obj)
+ XDR *xdrs;
+ char **objpp;
+ u_int obj_size;
+ xdrproc_t xdr_obj;
+{
+
+ bool_t more_data;
+
+ more_data = (*objpp != NULL);
+ if (! xdr_bool(xdrs,&more_data)) {
+ return (FALSE);
+ }
+ if (! more_data) {
+ *objpp = NULL;
+ return (TRUE);
+ }
+ return (xdr_reference(xdrs,objpp,obj_size,xdr_obj));
+}
diff --git a/lib/libc/xdr/xdr_sizeof.c b/lib/libc/xdr/xdr_sizeof.c
new file mode 100644
index 0000000..f33c613
--- /dev/null
+++ b/lib/libc/xdr/xdr_sizeof.c
@@ -0,0 +1,168 @@
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * xdr_sizeof.c
+ *
+ * Copyright 1990 Sun Microsystems, Inc.
+ *
+ * General purpose routine to see how much space something will use
+ * when serialized using XDR.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include <sys/types.h>
+#include <stdlib.h>
+#include "un-namespace.h"
+
+/* ARGSUSED */
+static bool_t
+x_putlong(xdrs, longp)
+ XDR *xdrs;
+ long *longp;
+{
+ xdrs->x_handy += BYTES_PER_XDR_UNIT;
+ return (TRUE);
+}
+
+/* ARGSUSED */
+static bool_t
+x_putbytes(xdrs, bp, len)
+ XDR *xdrs;
+ char *bp;
+ u_int len;
+{
+ xdrs->x_handy += len;
+ return (TRUE);
+}
+
+static u_int
+x_getpostn(xdrs)
+ XDR *xdrs;
+{
+ return (xdrs->x_handy);
+}
+
+/* ARGSUSED */
+static bool_t
+x_setpostn(xdrs, pos)
+ XDR *xdrs;
+ u_int pos;
+{
+ /* This is not allowed */
+ return (FALSE);
+}
+
+static int32_t *
+x_inline(xdrs, len)
+ XDR *xdrs;
+ u_int len;
+{
+ if (len == 0) {
+ return (NULL);
+ }
+ if (xdrs->x_op != XDR_ENCODE) {
+ return (NULL);
+ }
+ if (len < (u_int)(uintptr_t)xdrs->x_base) {
+ /* x_private was already allocated */
+ xdrs->x_handy += len;
+ return ((int32_t *) xdrs->x_private);
+ } else {
+ /* Free the earlier space and allocate new area */
+ if (xdrs->x_private)
+ free(xdrs->x_private);
+ if ((xdrs->x_private = (caddr_t) malloc(len)) == NULL) {
+ xdrs->x_base = 0;
+ return (NULL);
+ }
+ xdrs->x_base = (caddr_t)(uintptr_t)len;
+ xdrs->x_handy += len;
+ return ((int32_t *) xdrs->x_private);
+ }
+}
+
+static int
+harmless()
+{
+ /* Always return FALSE/NULL, as the case may be */
+ return (0);
+}
+
+static void
+x_destroy(xdrs)
+ XDR *xdrs;
+{
+ xdrs->x_handy = 0;
+ xdrs->x_base = 0;
+ if (xdrs->x_private) {
+ free(xdrs->x_private);
+ xdrs->x_private = NULL;
+ }
+ return;
+}
+
+unsigned long
+xdr_sizeof(func, data)
+ xdrproc_t func;
+ void *data;
+{
+ XDR x;
+ struct xdr_ops ops;
+ bool_t stat;
+ /* to stop ANSI-C compiler from complaining */
+ typedef bool_t (* dummyfunc1)(XDR *, long *);
+ typedef bool_t (* dummyfunc2)(XDR *, caddr_t, u_int);
+
+ ops.x_putlong = x_putlong;
+ ops.x_putbytes = x_putbytes;
+ ops.x_inline = x_inline;
+ ops.x_getpostn = x_getpostn;
+ ops.x_setpostn = x_setpostn;
+ ops.x_destroy = x_destroy;
+
+ /* the other harmless ones */
+ ops.x_getlong = (dummyfunc1) harmless;
+ ops.x_getbytes = (dummyfunc2) harmless;
+
+ x.x_op = XDR_ENCODE;
+ x.x_ops = &ops;
+ x.x_handy = 0;
+ x.x_private = (caddr_t) NULL;
+ x.x_base = (caddr_t) 0;
+
+ stat = func(&x, data);
+ if (x.x_private)
+ free(x.x_private);
+ return (stat == TRUE ? (unsigned) x.x_handy: 0);
+}
diff --git a/lib/libc/xdr/xdr_stdio.c b/lib/libc/xdr/xdr_stdio.c
new file mode 100644
index 0000000..8c1724d
--- /dev/null
+++ b/lib/libc/xdr/xdr_stdio.c
@@ -0,0 +1,196 @@
+/* $NetBSD: xdr_stdio.c,v 1.14 2000/01/22 22:19:19 mycroft Exp $ */
+
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *sccsid2 = "@(#)xdr_stdio.c 1.16 87/08/11 Copyr 1984 Sun Micro";
+static char *sccsid = "@(#)xdr_stdio.c 2.1 88/07/29 4.0 RPCSRC";
+#endif
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * xdr_stdio.c, XDR implementation on standard i/o file.
+ *
+ * Copyright (C) 1984, Sun Microsystems, Inc.
+ *
+ * This set of routines implements a XDR on a stdio stream.
+ * XDR_ENCODE serializes onto the stream, XDR_DECODE de-serializes
+ * from the stream.
+ */
+
+#include "namespace.h"
+#include <stdio.h>
+
+#include <arpa/inet.h>
+#include <rpc/types.h>
+#include <rpc/xdr.h>
+#include "un-namespace.h"
+
+static void xdrstdio_destroy(XDR *);
+static bool_t xdrstdio_getlong(XDR *, long *);
+static bool_t xdrstdio_putlong(XDR *, const long *);
+static bool_t xdrstdio_getbytes(XDR *, char *, u_int);
+static bool_t xdrstdio_putbytes(XDR *, const char *, u_int);
+static u_int xdrstdio_getpos(XDR *);
+static bool_t xdrstdio_setpos(XDR *, u_int);
+static int32_t *xdrstdio_inline(XDR *, u_int);
+
+/*
+ * Ops vector for stdio type XDR
+ */
+static const struct xdr_ops xdrstdio_ops = {
+ xdrstdio_getlong, /* deseraialize a long int */
+ xdrstdio_putlong, /* seraialize a long int */
+ xdrstdio_getbytes, /* deserialize counted bytes */
+ xdrstdio_putbytes, /* serialize counted bytes */
+ xdrstdio_getpos, /* get offset in the stream */
+ xdrstdio_setpos, /* set offset in the stream */
+ xdrstdio_inline, /* prime stream for inline macros */
+ xdrstdio_destroy /* destroy stream */
+};
+
+/*
+ * Initialize a stdio xdr stream.
+ * Sets the xdr stream handle xdrs for use on the stream file.
+ * Operation flag is set to op.
+ */
+void
+xdrstdio_create(xdrs, file, op)
+ XDR *xdrs;
+ FILE *file;
+ enum xdr_op op;
+{
+
+ xdrs->x_op = op;
+ xdrs->x_ops = &xdrstdio_ops;
+ xdrs->x_private = file;
+ xdrs->x_handy = 0;
+ xdrs->x_base = 0;
+}
+
+/*
+ * Destroy a stdio xdr stream.
+ * Cleans up the xdr stream handle xdrs previously set up by xdrstdio_create.
+ */
+static void
+xdrstdio_destroy(xdrs)
+ XDR *xdrs;
+{
+ (void)fflush((FILE *)xdrs->x_private);
+ /* XXX: should we close the file ?? */
+}
+
+static bool_t
+xdrstdio_getlong(xdrs, lp)
+ XDR *xdrs;
+ long *lp;
+{
+ u_int32_t temp;
+
+ if (fread(&temp, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1)
+ return (FALSE);
+ *lp = (long)ntohl(temp);
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_putlong(xdrs, lp)
+ XDR *xdrs;
+ const long *lp;
+{
+ int32_t mycopy = htonl((u_int32_t)*lp);
+
+ if (fwrite(&mycopy, sizeof(int32_t), 1, (FILE *)xdrs->x_private) != 1)
+ return (FALSE);
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_getbytes(xdrs, addr, len)
+ XDR *xdrs;
+ char *addr;
+ u_int len;
+{
+
+ if ((len != 0) && (fread(addr, (size_t)len, 1, (FILE *)xdrs->x_private) != 1))
+ return (FALSE);
+ return (TRUE);
+}
+
+static bool_t
+xdrstdio_putbytes(xdrs, addr, len)
+ XDR *xdrs;
+ const char *addr;
+ u_int len;
+{
+
+ if ((len != 0) && (fwrite(addr, (size_t)len, 1,
+ (FILE *)xdrs->x_private) != 1))
+ return (FALSE);
+ return (TRUE);
+}
+
+static u_int
+xdrstdio_getpos(xdrs)
+ XDR *xdrs;
+{
+
+ return ((u_int) ftell((FILE *)xdrs->x_private));
+}
+
+static bool_t
+xdrstdio_setpos(xdrs, pos)
+ XDR *xdrs;
+ u_int pos;
+{
+
+ return ((fseek((FILE *)xdrs->x_private, (long)pos, 0) < 0) ?
+ FALSE : TRUE);
+}
+
+/* ARGSUSED */
+static int32_t *
+xdrstdio_inline(xdrs, len)
+ XDR *xdrs;
+ u_int len;
+{
+
+ /*
+ * Must do some work to implement this: must insure
+ * enough data in the underlying stdio buffer,
+ * that the buffer is aligned so that we can indirect through a
+ * long *, and stuff this pointer in xdrs->x_buf. Doing
+ * a fread or fwrite to a scratch buffer would defeat
+ * most of the gains to be had here and require storage
+ * management on this buffer, so we don't do this.
+ */
+ return (NULL);
+}
diff --git a/lib/libc/yp/Makefile.inc b/lib/libc/yp/Makefile.inc
new file mode 100644
index 0000000..6faa9a5
--- /dev/null
+++ b/lib/libc/yp/Makefile.inc
@@ -0,0 +1,19 @@
+# from: @(#)Makefile.inc 5.3 (Berkeley) 2/20/91
+# $FreeBSD$
+
+# yp sources
+.PATH: ${.CURDIR}/yp
+
+SRCS+= xdryp.c yp.h yp_xdr.c yplib.c
+CLEANFILES+= yp.h yp_xdr.c
+
+SYM_MAPS+= ${.CURDIR}/yp/Symbol.map
+
+RPCSRC= ${DESTDIR}/usr/include/rpcsvc/yp.x
+RPCGEN= RPCGEN_CPP=${CPP:Q} rpcgen -C
+
+yp_xdr.c: ${RPCSRC}
+ ${RPCGEN} -c -o ${.TARGET} ${RPCSRC}
+
+yp.h: ${RPCSRC}
+ ${RPCGEN} -h -o ${.TARGET} ${RPCSRC}
diff --git a/lib/libc/yp/Symbol.map b/lib/libc/yp/Symbol.map
new file mode 100644
index 0000000..cf2470a
--- /dev/null
+++ b/lib/libc/yp/Symbol.map
@@ -0,0 +1,25 @@
+/*
+ * $FreeBSD$
+ */
+
+FBSD_1.0 {
+ xdr_datum;
+ xdr_ypresp_all_seq;
+ ypresp_data;
+ ypresp_allfn;
+ ypbinderr_string;
+ _yp_dobind;
+ yp_bind;
+ yp_unbind;
+ yp_match;
+ yp_get_default_domain;
+ yp_first;
+ yp_next;
+ yp_all;
+ yp_order;
+ yp_master;
+ yp_maplist;
+ yperr_string;
+ ypprot_err;
+ _yp_check;
+};
diff --git a/lib/libc/yp/xdryp.c b/lib/libc/yp/xdryp.c
new file mode 100644
index 0000000..bb9096b
--- /dev/null
+++ b/lib/libc/yp/xdryp.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <rpc/rpc.h>
+#include <rpcsvc/yp.h>
+#include <stdlib.h>
+#include <string.h>
+
+extern int (*ypresp_allfn)();
+extern void *ypresp_data;
+
+/*
+ * I'm leaving the xdr_datum() function in purely for backwards
+ * compatibility. yplib.c doesn't actually use it, but it's listed
+ * in yp_prot.h as being available, so it's probably a good idea to
+ * leave it in case somebody goes looking for it.
+ */
+typedef struct {
+ char *dptr;
+ int dsize;
+} datum;
+
+bool_t
+xdr_datum(XDR *xdrs, datum *objp)
+{
+ if (!xdr_bytes(xdrs, (char **)&objp->dptr, (u_int *)&objp->dsize, YPMAXRECORD)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_ypresp_all_seq(XDR *xdrs, u_long *objp)
+{
+ struct ypresp_all out;
+ u_long status;
+ char *key, *val;
+ int r;
+
+ bzero(&out, sizeof out);
+ while (1) {
+ if (!xdr_ypresp_all(xdrs, &out)) {
+ xdr_free((xdrproc_t)xdr_ypresp_all, &out);
+ *objp = YP_YPERR;
+ return (FALSE);
+ }
+ if (out.more == 0) {
+ xdr_free((xdrproc_t)xdr_ypresp_all, &out);
+ *objp = YP_NOMORE;
+ return (TRUE);
+ }
+ status = out.ypresp_all_u.val.stat;
+ switch (status) {
+ case YP_TRUE:
+ key = (char *)malloc(out.ypresp_all_u.val.key.keydat_len + 1);
+ if (key == NULL) {
+ xdr_free((xdrproc_t)xdr_ypresp_all, &out);
+ *objp = YP_YPERR;
+ return (FALSE);
+ }
+ bcopy(out.ypresp_all_u.val.key.keydat_val, key,
+ out.ypresp_all_u.val.key.keydat_len);
+ key[out.ypresp_all_u.val.key.keydat_len] = '\0';
+ val = (char *)malloc(out.ypresp_all_u.val.val.valdat_len + 1);
+ if (val == NULL) {
+ free(key);
+ xdr_free((xdrproc_t)xdr_ypresp_all, &out);
+ *objp = YP_YPERR;
+ return (FALSE);
+ }
+ bcopy(out.ypresp_all_u.val.val.valdat_val, val,
+ out.ypresp_all_u.val.val.valdat_len);
+ val[out.ypresp_all_u.val.val.valdat_len] = '\0';
+ xdr_free((xdrproc_t)xdr_ypresp_all, &out);
+
+ r = (*ypresp_allfn)(status,
+ key, out.ypresp_all_u.val.key.keydat_len,
+ val, out.ypresp_all_u.val.val.valdat_len,
+ ypresp_data);
+ *objp = status;
+ free(key);
+ free(val);
+ if (r)
+ return (TRUE);
+ break;
+ case YP_NOMORE:
+ xdr_free((xdrproc_t)xdr_ypresp_all, &out);
+ *objp = YP_NOMORE;
+ return (TRUE);
+ default:
+ xdr_free((xdrproc_t)xdr_ypresp_all, &out);
+ *objp = status;
+ return (TRUE);
+ }
+ }
+}
diff --git a/lib/libc/yp/yplib.c b/lib/libc/yp/yplib.c
new file mode 100644
index 0000000..3dfc0aa
--- /dev/null
+++ b/lib/libc/yp/yplib.c
@@ -0,0 +1,1220 @@
+/*
+ * Copyright (c) 1992/3 Theo de Raadt <deraadt@fsa.ca>
+ * Copyright (c) 1998 Bill Paul <wpaul@ctr.columbia.edu>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include "reentrant.h"
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/file.h>
+#include <sys/uio.h>
+#include <arpa/inet.h>
+#include <errno.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <rpc/rpc.h>
+#include <rpc/xdr.h>
+#include <rpcsvc/yp.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
+/*
+ * We have to define these here due to clashes between yp_prot.h and
+ * yp.h.
+ */
+
+#define YPMATCHCACHE
+
+#ifdef YPMATCHCACHE
+struct ypmatch_ent {
+ char *ypc_map;
+ keydat ypc_key;
+ valdat ypc_val;
+ time_t ypc_expire_t;
+ struct ypmatch_ent *ypc_next;
+};
+#define YPLIB_MAXCACHE 5 /* At most 5 entries */
+#define YPLIB_EXPIRE 5 /* Expire after 5 seconds */
+#endif
+
+struct dom_binding {
+ struct dom_binding *dom_pnext;
+ char dom_domain[YPMAXDOMAIN + 1];
+ struct sockaddr_in dom_server_addr;
+ u_short dom_server_port;
+ int dom_socket;
+ CLIENT *dom_client;
+ u_short dom_local_port; /* now I finally know what this is for. */
+ long dom_vers;
+#ifdef YPMATCHCACHE
+ struct ypmatch_ent *cache;
+ int ypmatch_cachecnt;
+#endif
+};
+
+#include <rpcsvc/ypclnt.h>
+
+#ifndef BINDINGDIR
+#define BINDINGDIR "/var/yp/binding"
+#endif
+#define MAX_RETRIES 20
+
+extern bool_t xdr_domainname(), xdr_ypbind_resp();
+extern bool_t xdr_ypreq_key(), xdr_ypresp_val();
+extern bool_t xdr_ypreq_nokey(), xdr_ypresp_key_val();
+extern bool_t xdr_ypresp_all(), xdr_ypresp_all_seq();
+extern bool_t xdr_ypresp_master();
+
+int (*ypresp_allfn)();
+void *ypresp_data;
+
+static void _yp_unbind(struct dom_binding *);
+struct dom_binding *_ypbindlist;
+static char _yp_domain[MAXHOSTNAMELEN];
+int _yplib_timeout = 20;
+
+static mutex_t _ypmutex = MUTEX_INITIALIZER;
+#define YPLOCK() mutex_lock(&_ypmutex);
+#define YPUNLOCK() mutex_unlock(&_ypmutex);
+
+#ifdef YPMATCHCACHE
+static void
+ypmatch_cache_delete(struct dom_binding *ypdb, struct ypmatch_ent *prev,
+ struct ypmatch_ent *cur)
+{
+ if (prev == NULL)
+ ypdb->cache = cur->ypc_next;
+ else
+ prev->ypc_next = cur->ypc_next;
+
+ free(cur->ypc_map);
+ free(cur->ypc_key.keydat_val);
+ free(cur->ypc_val.valdat_val);
+ free(cur);
+
+ ypdb->ypmatch_cachecnt--;
+
+ return;
+}
+
+static void
+ypmatch_cache_flush(struct dom_binding *ypdb)
+{
+ struct ypmatch_ent *n, *c = ypdb->cache;
+
+ while (c != NULL) {
+ n = c->ypc_next;
+ ypmatch_cache_delete(ypdb, NULL, c);
+ c = n;
+ }
+
+ return;
+}
+
+static void
+ypmatch_cache_expire(struct dom_binding *ypdb)
+{
+ struct ypmatch_ent *c = ypdb->cache;
+ struct ypmatch_ent *n, *p = NULL;
+ time_t t;
+
+ time(&t);
+
+ while (c != NULL) {
+ if (t >= c->ypc_expire_t) {
+ n = c->ypc_next;
+ ypmatch_cache_delete(ypdb, p, c);
+ c = n;
+ } else {
+ p = c;
+ c = c->ypc_next;
+ }
+ }
+
+ return;
+}
+
+static void
+ypmatch_cache_insert(struct dom_binding *ypdb, char *map, keydat *key,
+ valdat *val)
+{
+ struct ypmatch_ent *new;
+
+ /* Do an expire run to maybe open up a slot. */
+ if (ypdb->ypmatch_cachecnt)
+ ypmatch_cache_expire(ypdb);
+
+ /*
+ * If there are no slots free, then force an expire of
+ * the least recently used entry.
+ */
+ if (ypdb->ypmatch_cachecnt >= YPLIB_MAXCACHE) {
+ struct ypmatch_ent *o = NULL, *c = ypdb->cache;
+ time_t oldest = 0;
+
+ oldest = ~oldest;
+
+ while (c != NULL) {
+ if (c->ypc_expire_t < oldest) {
+ oldest = c->ypc_expire_t;
+ o = c;
+ }
+ c = c->ypc_next;
+ }
+
+ if (o == NULL)
+ return;
+ o->ypc_expire_t = 0;
+ ypmatch_cache_expire(ypdb);
+ }
+
+ new = malloc(sizeof(struct ypmatch_ent));
+ if (new == NULL)
+ return;
+
+ new->ypc_map = strdup(map);
+ if (new->ypc_map == NULL) {
+ free(new);
+ return;
+ }
+ new->ypc_key.keydat_val = malloc(key->keydat_len);
+ if (new->ypc_key.keydat_val == NULL) {
+ free(new->ypc_map);
+ free(new);
+ return;
+ }
+ new->ypc_val.valdat_val = malloc(val->valdat_len);
+ if (new->ypc_val.valdat_val == NULL) {
+ free(new->ypc_val.valdat_val);
+ free(new->ypc_map);
+ free(new);
+ return;
+ }
+
+ new->ypc_expire_t = time(NULL) + YPLIB_EXPIRE;
+ new->ypc_key.keydat_len = key->keydat_len;
+ new->ypc_val.valdat_len = val->valdat_len;
+ bcopy(key->keydat_val, new->ypc_key.keydat_val, key->keydat_len);
+ bcopy(val->valdat_val, new->ypc_val.valdat_val, val->valdat_len);
+
+ new->ypc_next = ypdb->cache;
+ ypdb->cache = new;
+
+ ypdb->ypmatch_cachecnt++;
+
+ return;
+}
+
+static bool_t
+ypmatch_cache_lookup(struct dom_binding *ypdb, char *map, keydat *key,
+ valdat *val)
+{
+ struct ypmatch_ent *c;
+
+ ypmatch_cache_expire(ypdb);
+
+ for (c = ypdb->cache; c != NULL; c = c->ypc_next) {
+ if (strcmp(map, c->ypc_map))
+ continue;
+ if (key->keydat_len != c->ypc_key.keydat_len)
+ continue;
+ if (bcmp(key->keydat_val, c->ypc_key.keydat_val,
+ key->keydat_len))
+ continue;
+ }
+
+ if (c == NULL)
+ return(FALSE);
+
+ val->valdat_len = c->ypc_val.valdat_len;
+ val->valdat_val = c->ypc_val.valdat_val;
+
+ return(TRUE);
+}
+#endif
+
+const char *
+ypbinderr_string(int incode)
+{
+ static char err[80];
+ switch (incode) {
+ case 0:
+ return ("Success");
+ case YPBIND_ERR_ERR:
+ return ("Internal ypbind error");
+ case YPBIND_ERR_NOSERV:
+ return ("Domain not bound");
+ case YPBIND_ERR_RESC:
+ return ("System resource allocation failure");
+ }
+ sprintf(err, "Unknown ypbind error: #%d\n", incode);
+ return (err);
+}
+
+int
+_yp_dobind(char *dom, struct dom_binding **ypdb)
+{
+ static pid_t pid = -1;
+ char path[MAXPATHLEN];
+ struct dom_binding *ysd, *ysd2;
+ struct ypbind_resp ypbr;
+ struct timeval tv;
+ struct sockaddr_in clnt_sin;
+ int clnt_sock, fd;
+ pid_t gpid;
+ CLIENT *client;
+ int new = 0, r;
+ int retries = 0;
+ struct sockaddr_in check;
+ socklen_t checklen = sizeof(struct sockaddr_in);
+
+ /* Not allowed; bad doggie. Bad. */
+ if (strchr(dom, '/') != NULL)
+ return(YPERR_BADARGS);
+
+ gpid = getpid();
+ if (!(pid == -1 || pid == gpid)) {
+ ysd = _ypbindlist;
+ while (ysd) {
+ if (ysd->dom_client != NULL)
+ _yp_unbind(ysd);
+ ysd2 = ysd->dom_pnext;
+ free(ysd);
+ ysd = ysd2;
+ }
+ _ypbindlist = NULL;
+ }
+ pid = gpid;
+
+ if (ypdb != NULL)
+ *ypdb = NULL;
+
+ if (dom == NULL || strlen(dom) == 0)
+ return (YPERR_BADARGS);
+
+ for (ysd = _ypbindlist; ysd; ysd = ysd->dom_pnext)
+ if (strcmp(dom, ysd->dom_domain) == 0)
+ break;
+
+
+ if (ysd == NULL) {
+ ysd = (struct dom_binding *)malloc(sizeof *ysd);
+ if (ysd == NULL)
+ return (YPERR_RESRC);
+ bzero((char *)ysd, sizeof *ysd);
+ ysd->dom_socket = -1;
+ ysd->dom_vers = 0;
+ new = 1;
+ } else {
+ /* Check the socket -- may have been hosed by the caller. */
+ if (_getsockname(ysd->dom_socket, (struct sockaddr *)&check,
+ &checklen) == -1 || check.sin_family != AF_INET ||
+ check.sin_port != ysd->dom_local_port) {
+ /* Socket became bogus somehow... need to rebind. */
+ int save, sock;
+
+ sock = ysd->dom_socket;
+ save = _dup(ysd->dom_socket);
+ if (ysd->dom_client != NULL)
+ clnt_destroy(ysd->dom_client);
+ ysd->dom_vers = 0;
+ ysd->dom_client = NULL;
+ sock = _dup2(save, sock);
+ _close(save);
+ }
+ }
+
+again:
+ retries++;
+ if (retries > MAX_RETRIES) {
+ if (new)
+ free(ysd);
+ return(YPERR_YPBIND);
+ }
+#ifdef BINDINGDIR
+ if (ysd->dom_vers == 0) {
+ /*
+ * We're trying to make a new binding: zorch the
+ * existing handle now (if any).
+ */
+ if (ysd->dom_client != NULL) {
+ clnt_destroy(ysd->dom_client);
+ ysd->dom_client = NULL;
+ ysd->dom_socket = -1;
+ }
+ snprintf(path, sizeof(path), "%s/%s.%d", BINDINGDIR, dom, 2);
+ if ((fd = _open(path, O_RDONLY)) == -1) {
+ /* no binding file, YP is dead. */
+ /* Try to bring it back to life. */
+ _close(fd);
+ goto skipit;
+ }
+ if (_flock(fd, LOCK_EX|LOCK_NB) == -1 && errno == EWOULDBLOCK) {
+ struct iovec iov[2];
+ struct ypbind_resp ybr;
+ u_short ypb_port;
+
+ iov[0].iov_base = (caddr_t)&ypb_port;
+ iov[0].iov_len = sizeof ypb_port;
+ iov[1].iov_base = (caddr_t)&ybr;
+ iov[1].iov_len = sizeof ybr;
+
+ r = _readv(fd, iov, 2);
+ if (r != iov[0].iov_len + iov[1].iov_len) {
+ _close(fd);
+ ysd->dom_vers = -1;
+ goto again;
+ }
+
+ bzero(&ysd->dom_server_addr, sizeof ysd->dom_server_addr);
+ ysd->dom_server_addr.sin_family = AF_INET;
+ ysd->dom_server_addr.sin_len = sizeof(struct sockaddr_in);
+ bcopy(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
+ &ysd->dom_server_addr.sin_addr.s_addr,
+ sizeof(ysd->dom_server_addr.sin_addr.s_addr));
+ bcopy(&ybr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
+ &ysd->dom_server_addr.sin_port,
+ sizeof(ysd->dom_server_addr.sin_port));
+
+ ysd->dom_server_port = ysd->dom_server_addr.sin_port;
+ _close(fd);
+ goto gotit;
+ } else {
+ /* no lock on binding file, YP is dead. */
+ /* Try to bring it back to life. */
+ _close(fd);
+ goto skipit;
+ }
+ }
+skipit:
+#endif
+ if (ysd->dom_vers == -1 || ysd->dom_vers == 0) {
+ /*
+ * We're trying to make a new binding: zorch the
+ * existing handle now (if any).
+ */
+ if (ysd->dom_client != NULL) {
+ clnt_destroy(ysd->dom_client);
+ ysd->dom_client = NULL;
+ ysd->dom_socket = -1;
+ }
+ bzero((char *)&clnt_sin, sizeof clnt_sin);
+ clnt_sin.sin_family = AF_INET;
+ clnt_sin.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+
+ clnt_sock = RPC_ANYSOCK;
+ client = clnttcp_create(&clnt_sin, YPBINDPROG, YPBINDVERS, &clnt_sock,
+ 0, 0);
+ if (client == NULL) {
+ /*
+ * These conditions indicate ypbind just isn't
+ * alive -- we probably don't want to shoot our
+ * mouth off in this case; instead generate error
+ * messages only for really exotic problems.
+ */
+ if (rpc_createerr.cf_stat != RPC_PROGNOTREGISTERED &&
+ (rpc_createerr.cf_stat != RPC_SYSTEMERROR &&
+ rpc_createerr.cf_error.re_errno == ECONNREFUSED))
+ clnt_pcreateerror("clnttcp_create");
+ if (new)
+ free(ysd);
+ return (YPERR_YPBIND);
+ }
+
+ /*
+ * Check the port number -- should be < IPPORT_RESERVED.
+ * If not, it's possible someone has registered a bogus
+ * ypbind with the portmapper and is trying to trick us.
+ */
+ if (ntohs(clnt_sin.sin_port) >= IPPORT_RESERVED) {
+ if (client != NULL)
+ clnt_destroy(client);
+ if (new)
+ free(ysd);
+ return(YPERR_YPBIND);
+ }
+ tv.tv_sec = _yplib_timeout/2;
+ tv.tv_usec = 0;
+ r = clnt_call(client, YPBINDPROC_DOMAIN,
+ (xdrproc_t)xdr_domainname, &dom,
+ (xdrproc_t)xdr_ypbind_resp, &ypbr, tv);
+ if (r != RPC_SUCCESS) {
+ clnt_destroy(client);
+ ysd->dom_vers = -1;
+ if (r == RPC_PROGUNAVAIL || r == RPC_PROCUNAVAIL) {
+ if (new)
+ free(ysd);
+ return(YPERR_YPBIND);
+ }
+ fprintf(stderr,
+ "YP: server for domain %s not responding, retrying\n", dom);
+ goto again;
+ } else {
+ if (ypbr.ypbind_status != YPBIND_SUCC_VAL) {
+ struct timespec time_to_sleep, time_remaining;
+
+ clnt_destroy(client);
+ ysd->dom_vers = -1;
+
+ time_to_sleep.tv_sec = _yplib_timeout/2;
+ time_to_sleep.tv_nsec = 0;
+ _nanosleep(&time_to_sleep,
+ &time_remaining);
+ goto again;
+ }
+ }
+ clnt_destroy(client);
+
+ bzero((char *)&ysd->dom_server_addr, sizeof ysd->dom_server_addr);
+ ysd->dom_server_addr.sin_family = AF_INET;
+ bcopy(&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port,
+ &ysd->dom_server_addr.sin_port,
+ sizeof(ysd->dom_server_addr.sin_port));
+ bcopy(&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_addr,
+ &ysd->dom_server_addr.sin_addr.s_addr,
+ sizeof(ysd->dom_server_addr.sin_addr.s_addr));
+
+ /*
+ * We could do a reserved port check here too, but this
+ * could pose compatibility problems. The local ypbind is
+ * supposed to decide whether or not to trust yp servers
+ * on insecure ports. For now, we trust its judgement.
+ */
+ ysd->dom_server_port =
+ *(u_short *)&ypbr.ypbind_resp_u.ypbind_bindinfo.ypbind_binding_port;
+gotit:
+ ysd->dom_vers = YPVERS;
+ strlcpy(ysd->dom_domain, dom, sizeof(ysd->dom_domain));
+ }
+
+ /* Don't rebuild the connection to the server unless we have to. */
+ if (ysd->dom_client == NULL) {
+ tv.tv_sec = _yplib_timeout/2;
+ tv.tv_usec = 0;
+ ysd->dom_socket = RPC_ANYSOCK;
+ ysd->dom_client = clntudp_bufcreate(&ysd->dom_server_addr,
+ YPPROG, YPVERS, tv, &ysd->dom_socket, 1280, 2304);
+ if (ysd->dom_client == NULL) {
+ clnt_pcreateerror("clntudp_create");
+ ysd->dom_vers = -1;
+ goto again;
+ }
+ if (_fcntl(ysd->dom_socket, F_SETFD, 1) == -1)
+ perror("fcntl: F_SETFD");
+ /*
+ * We want a port number associated with this socket
+ * so that we can check its authenticity later.
+ */
+ checklen = sizeof(struct sockaddr_in);
+ bzero((char *)&check, checklen);
+ _bind(ysd->dom_socket, (struct sockaddr *)&check, checklen);
+ check.sin_family = AF_INET;
+ if (!_getsockname(ysd->dom_socket,
+ (struct sockaddr *)&check, &checklen)) {
+ ysd->dom_local_port = check.sin_port;
+ } else {
+ clnt_destroy(ysd->dom_client);
+ if (new)
+ free(ysd);
+ return(YPERR_YPBIND);
+ }
+ }
+
+ if (new) {
+ ysd->dom_pnext = _ypbindlist;
+ _ypbindlist = ysd;
+ }
+
+ /*
+ * Set low retry timeout to realistically handle UDP packet
+ * loss for YP packet bursts.
+ */
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+ clnt_control(ysd->dom_client, CLSET_RETRY_TIMEOUT, (char*)&tv);
+
+ if (ypdb != NULL)
+ *ypdb = ysd;
+ return (0);
+}
+
+static void
+_yp_unbind(struct dom_binding *ypb)
+{
+ struct sockaddr_in check;
+ socklen_t checklen = sizeof(struct sockaddr_in);
+
+ if (ypb->dom_client != NULL) {
+ /* Check the socket -- may have been hosed by the caller. */
+ if (_getsockname(ypb->dom_socket, (struct sockaddr *)&check,
+ &checklen) == -1 || check.sin_family != AF_INET ||
+ check.sin_port != ypb->dom_local_port) {
+ int save, sock;
+
+ sock = ypb->dom_socket;
+ save = _dup(ypb->dom_socket);
+ clnt_destroy(ypb->dom_client);
+ sock = _dup2(save, sock);
+ _close(save);
+ } else
+ clnt_destroy(ypb->dom_client);
+ }
+
+ ypb->dom_client = NULL;
+ ypb->dom_socket = -1;
+ ypb->dom_vers = -1;
+#ifdef YPMATCHCACHE
+ ypmatch_cache_flush(ypb);
+#endif
+}
+
+static int
+yp_bind_locked(char *dom)
+{
+ return (_yp_dobind(dom, NULL));
+}
+
+int
+yp_bind(char *dom)
+{
+ int r;
+
+ YPLOCK();
+ r = yp_bind_locked(dom);
+ YPUNLOCK();
+ return (r);
+}
+
+static void
+yp_unbind_locked(char *dom)
+{
+ struct dom_binding *ypb, *ypbp;
+
+ ypbp = NULL;
+ for (ypb = _ypbindlist; ypb; ypb = ypb->dom_pnext) {
+ if (strcmp(dom, ypb->dom_domain) == 0) {
+ _yp_unbind(ypb);
+ if (ypbp)
+ ypbp->dom_pnext = ypb->dom_pnext;
+ else
+ _ypbindlist = ypb->dom_pnext;
+ free(ypb);
+ return;
+ }
+ ypbp = ypb;
+ }
+ return;
+}
+
+void
+yp_unbind(char *dom)
+{
+ YPLOCK();
+ yp_unbind_locked(dom);
+ YPUNLOCK();
+}
+
+int
+yp_match(char *indomain, char *inmap, const char *inkey, int inkeylen,
+ char **outval, int *outvallen)
+{
+ struct dom_binding *ysd;
+ struct ypresp_val yprv;
+ struct timeval tv;
+ struct ypreq_key yprk;
+ int r;
+
+ *outval = NULL;
+ *outvallen = 0;
+
+ /* Sanity check */
+
+ if (inkey == NULL || !strlen(inkey) || inkeylen <= 0 ||
+ inmap == NULL || !strlen(inmap) ||
+ indomain == NULL || !strlen(indomain))
+ return (YPERR_BADARGS);
+
+ YPLOCK();
+ if (_yp_dobind(indomain, &ysd) != 0) {
+ YPUNLOCK();
+ return(YPERR_DOMAIN);
+ }
+
+ yprk.domain = indomain;
+ yprk.map = inmap;
+ yprk.key.keydat_val = (char *)inkey;
+ yprk.key.keydat_len = inkeylen;
+
+#ifdef YPMATCHCACHE
+ if (ypmatch_cache_lookup(ysd, yprk.map, &yprk.key, &yprv.val) == TRUE) {
+/*
+ if (!strcmp(_yp_domain, indomain) && ypmatch_find(inmap, inkey,
+ inkeylen, &yprv.val.valdat_val, &yprv.val.valdat_len)) {
+*/
+ *outvallen = yprv.val.valdat_len;
+ *outval = (char *)malloc(*outvallen+1);
+ if (*outval == NULL) {
+ _yp_unbind(ysd);
+ *outvallen = 0;
+ YPUNLOCK();
+ return (YPERR_RESRC);
+ }
+ bcopy(yprv.val.valdat_val, *outval, *outvallen);
+ (*outval)[*outvallen] = '\0';
+ YPUNLOCK();
+ return (0);
+ }
+ _yp_unbind(ysd);
+#endif
+
+again:
+ if (_yp_dobind(indomain, &ysd) != 0) {
+ YPUNLOCK();
+ return (YPERR_DOMAIN);
+ }
+
+ tv.tv_sec = _yplib_timeout;
+ tv.tv_usec = 0;
+
+ bzero((char *)&yprv, sizeof yprv);
+
+ r = clnt_call(ysd->dom_client, YPPROC_MATCH,
+ (xdrproc_t)xdr_ypreq_key, &yprk,
+ (xdrproc_t)xdr_ypresp_val, &yprv, tv);
+ if (r != RPC_SUCCESS) {
+ clnt_perror(ysd->dom_client, "yp_match: clnt_call");
+ _yp_unbind(ysd);
+ goto again;
+ }
+
+ if (!(r = ypprot_err(yprv.stat))) {
+ *outvallen = yprv.val.valdat_len;
+ *outval = (char *)malloc(*outvallen+1);
+ if (*outval == NULL) {
+ _yp_unbind(ysd);
+ *outvallen = 0;
+ xdr_free((xdrproc_t)xdr_ypresp_val, &yprv);
+ YPUNLOCK();
+ return (YPERR_RESRC);
+ }
+ bcopy(yprv.val.valdat_val, *outval, *outvallen);
+ (*outval)[*outvallen] = '\0';
+#ifdef YPMATCHCACHE
+ ypmatch_cache_insert(ysd, yprk.map, &yprk.key, &yprv.val);
+#endif
+ }
+
+ xdr_free((xdrproc_t)xdr_ypresp_val, &yprv);
+ YPUNLOCK();
+ return (r);
+}
+
+static int
+yp_get_default_domain_locked(char **domp)
+{
+ *domp = NULL;
+ if (_yp_domain[0] == '\0')
+ if (getdomainname(_yp_domain, sizeof _yp_domain))
+ return (YPERR_NODOM);
+ *domp = _yp_domain;
+ return (0);
+}
+
+int
+yp_get_default_domain(char **domp)
+{
+ int r;
+
+ YPLOCK();
+ r = yp_get_default_domain_locked(domp);
+ YPUNLOCK();
+ return (r);
+}
+
+int
+yp_first(char *indomain, char *inmap, char **outkey, int *outkeylen,
+ char **outval, int *outvallen)
+{
+ struct ypresp_key_val yprkv;
+ struct ypreq_nokey yprnk;
+ struct dom_binding *ysd;
+ struct timeval tv;
+ int r;
+
+ /* Sanity check */
+
+ if (indomain == NULL || !strlen(indomain) ||
+ inmap == NULL || !strlen(inmap))
+ return (YPERR_BADARGS);
+
+ *outkey = *outval = NULL;
+ *outkeylen = *outvallen = 0;
+
+ YPLOCK();
+again:
+ if (_yp_dobind(indomain, &ysd) != 0) {
+ YPUNLOCK();
+ return (YPERR_DOMAIN);
+ }
+
+ tv.tv_sec = _yplib_timeout;
+ tv.tv_usec = 0;
+
+ yprnk.domain = indomain;
+ yprnk.map = inmap;
+ bzero((char *)&yprkv, sizeof yprkv);
+
+ r = clnt_call(ysd->dom_client, YPPROC_FIRST,
+ (xdrproc_t)xdr_ypreq_nokey, &yprnk,
+ (xdrproc_t)xdr_ypresp_key_val, &yprkv, tv);
+ if (r != RPC_SUCCESS) {
+ clnt_perror(ysd->dom_client, "yp_first: clnt_call");
+ _yp_unbind(ysd);
+ goto again;
+ }
+ if (!(r = ypprot_err(yprkv.stat))) {
+ *outkeylen = yprkv.key.keydat_len;
+ *outkey = (char *)malloc(*outkeylen+1);
+ if (*outkey == NULL) {
+ _yp_unbind(ysd);
+ *outkeylen = 0;
+ xdr_free((xdrproc_t)xdr_ypresp_key_val, &yprkv);
+ YPUNLOCK();
+ return (YPERR_RESRC);
+ }
+ bcopy(yprkv.key.keydat_val, *outkey, *outkeylen);
+ (*outkey)[*outkeylen] = '\0';
+ *outvallen = yprkv.val.valdat_len;
+ *outval = (char *)malloc(*outvallen+1);
+ if (*outval == NULL) {
+ free(*outkey);
+ _yp_unbind(ysd);
+ *outkeylen = *outvallen = 0;
+ xdr_free((xdrproc_t)xdr_ypresp_key_val, &yprkv);
+ YPUNLOCK();
+ return (YPERR_RESRC);
+ }
+ bcopy(yprkv.val.valdat_val, *outval, *outvallen);
+ (*outval)[*outvallen] = '\0';
+ }
+
+ xdr_free((xdrproc_t)xdr_ypresp_key_val, &yprkv);
+ YPUNLOCK();
+ return (r);
+}
+
+int
+yp_next(char *indomain, char *inmap, char *inkey, int inkeylen,
+ char **outkey, int *outkeylen, char **outval, int *outvallen)
+{
+ struct ypresp_key_val yprkv;
+ struct ypreq_key yprk;
+ struct dom_binding *ysd;
+ struct timeval tv;
+ int r;
+
+ /* Sanity check */
+
+ if (inkey == NULL || !strlen(inkey) || inkeylen <= 0 ||
+ inmap == NULL || !strlen(inmap) ||
+ indomain == NULL || !strlen(indomain))
+ return (YPERR_BADARGS);
+
+ *outkey = *outval = NULL;
+ *outkeylen = *outvallen = 0;
+
+ YPLOCK();
+again:
+ if (_yp_dobind(indomain, &ysd) != 0) {
+ YPUNLOCK();
+ return (YPERR_DOMAIN);
+ }
+
+ tv.tv_sec = _yplib_timeout;
+ tv.tv_usec = 0;
+
+ yprk.domain = indomain;
+ yprk.map = inmap;
+ yprk.key.keydat_val = inkey;
+ yprk.key.keydat_len = inkeylen;
+ bzero((char *)&yprkv, sizeof yprkv);
+
+ r = clnt_call(ysd->dom_client, YPPROC_NEXT,
+ (xdrproc_t)xdr_ypreq_key, &yprk,
+ (xdrproc_t)xdr_ypresp_key_val, &yprkv, tv);
+ if (r != RPC_SUCCESS) {
+ clnt_perror(ysd->dom_client, "yp_next: clnt_call");
+ _yp_unbind(ysd);
+ goto again;
+ }
+ if (!(r = ypprot_err(yprkv.stat))) {
+ *outkeylen = yprkv.key.keydat_len;
+ *outkey = (char *)malloc(*outkeylen+1);
+ if (*outkey == NULL) {
+ _yp_unbind(ysd);
+ *outkeylen = 0;
+ xdr_free((xdrproc_t)xdr_ypresp_key_val, &yprkv);
+ YPUNLOCK();
+ return (YPERR_RESRC);
+ }
+ bcopy(yprkv.key.keydat_val, *outkey, *outkeylen);
+ (*outkey)[*outkeylen] = '\0';
+ *outvallen = yprkv.val.valdat_len;
+ *outval = (char *)malloc(*outvallen+1);
+ if (*outval == NULL) {
+ free(*outkey);
+ _yp_unbind(ysd);
+ *outkeylen = *outvallen = 0;
+ xdr_free((xdrproc_t)xdr_ypresp_key_val, &yprkv);
+ YPUNLOCK();
+ return (YPERR_RESRC);
+ }
+ bcopy(yprkv.val.valdat_val, *outval, *outvallen);
+ (*outval)[*outvallen] = '\0';
+ }
+
+ xdr_free((xdrproc_t)xdr_ypresp_key_val, &yprkv);
+ YPUNLOCK();
+ return (r);
+}
+
+int
+yp_all(char *indomain, char *inmap, struct ypall_callback *incallback)
+{
+ struct ypreq_nokey yprnk;
+ struct dom_binding *ysd;
+ struct timeval tv;
+ struct sockaddr_in clnt_sin;
+ CLIENT *clnt;
+ u_long status, savstat;
+ int clnt_sock;
+
+ /* Sanity check */
+
+ if (indomain == NULL || !strlen(indomain) ||
+ inmap == NULL || !strlen(inmap))
+ return (YPERR_BADARGS);
+
+ YPLOCK();
+again:
+
+ if (_yp_dobind(indomain, &ysd) != 0) {
+ YPUNLOCK();
+ return (YPERR_DOMAIN);
+ }
+
+ tv.tv_sec = _yplib_timeout;
+ tv.tv_usec = 0;
+
+ /* YPPROC_ALL manufactures its own channel to ypserv using TCP */
+
+ clnt_sock = RPC_ANYSOCK;
+ clnt_sin = ysd->dom_server_addr;
+ clnt_sin.sin_port = 0;
+ clnt = clnttcp_create(&clnt_sin, YPPROG, YPVERS, &clnt_sock, 0, 0);
+ if (clnt == NULL) {
+ YPUNLOCK();
+ printf("clnttcp_create failed\n");
+ return (YPERR_PMAP);
+ }
+
+ yprnk.domain = indomain;
+ yprnk.map = inmap;
+ ypresp_allfn = incallback->foreach;
+ ypresp_data = (void *)incallback->data;
+
+ if (clnt_call(clnt, YPPROC_ALL,
+ (xdrproc_t)xdr_ypreq_nokey, &yprnk,
+ (xdrproc_t)xdr_ypresp_all_seq, &status, tv) != RPC_SUCCESS) {
+ clnt_perror(ysd->dom_client, "yp_all: clnt_call");
+ clnt_destroy(clnt);
+ _yp_unbind(ysd);
+ goto again;
+ }
+
+ clnt_destroy(clnt);
+ savstat = status;
+ xdr_free((xdrproc_t)xdr_ypresp_all_seq, &status); /* not really needed... */
+ YPUNLOCK();
+ if (savstat != YP_NOMORE)
+ return (ypprot_err(savstat));
+ return (0);
+}
+
+int
+yp_order(char *indomain, char *inmap, int *outorder)
+{
+ struct dom_binding *ysd;
+ struct ypresp_order ypro;
+ struct ypreq_nokey yprnk;
+ struct timeval tv;
+ int r;
+
+ /* Sanity check */
+
+ if (indomain == NULL || !strlen(indomain) ||
+ inmap == NULL || !strlen(inmap))
+ return (YPERR_BADARGS);
+
+ YPLOCK();
+again:
+ if (_yp_dobind(indomain, &ysd) != 0) {
+ YPUNLOCK();
+ return (YPERR_DOMAIN);
+ }
+
+ tv.tv_sec = _yplib_timeout;
+ tv.tv_usec = 0;
+
+ yprnk.domain = indomain;
+ yprnk.map = inmap;
+
+ bzero((char *)(char *)&ypro, sizeof ypro);
+
+ r = clnt_call(ysd->dom_client, YPPROC_ORDER,
+ (xdrproc_t)xdr_ypreq_nokey, &yprnk,
+ (xdrproc_t)xdr_ypresp_order, &ypro, tv);
+
+ /*
+ * NIS+ in YP compat mode doesn't support the YPPROC_ORDER
+ * procedure.
+ */
+ if (r == RPC_PROCUNAVAIL) {
+ YPUNLOCK();
+ return(YPERR_YPERR);
+ }
+
+ if (r != RPC_SUCCESS) {
+ clnt_perror(ysd->dom_client, "yp_order: clnt_call");
+ _yp_unbind(ysd);
+ goto again;
+ }
+
+ if (!(r = ypprot_err(ypro.stat))) {
+ *outorder = ypro.ordernum;
+ }
+
+ xdr_free((xdrproc_t)xdr_ypresp_order, &ypro);
+ YPUNLOCK();
+ return (r);
+}
+
+int
+yp_master(char *indomain, char *inmap, char **outname)
+{
+ struct dom_binding *ysd;
+ struct ypresp_master yprm;
+ struct ypreq_nokey yprnk;
+ struct timeval tv;
+ int r;
+
+ /* Sanity check */
+
+ if (indomain == NULL || !strlen(indomain) ||
+ inmap == NULL || !strlen(inmap))
+ return (YPERR_BADARGS);
+ YPLOCK();
+again:
+ if (_yp_dobind(indomain, &ysd) != 0) {
+ YPUNLOCK();
+ return (YPERR_DOMAIN);
+ }
+
+ tv.tv_sec = _yplib_timeout;
+ tv.tv_usec = 0;
+
+ yprnk.domain = indomain;
+ yprnk.map = inmap;
+
+ bzero((char *)&yprm, sizeof yprm);
+
+ r = clnt_call(ysd->dom_client, YPPROC_MASTER,
+ (xdrproc_t)xdr_ypreq_nokey, &yprnk,
+ (xdrproc_t)xdr_ypresp_master, &yprm, tv);
+ if (r != RPC_SUCCESS) {
+ clnt_perror(ysd->dom_client, "yp_master: clnt_call");
+ _yp_unbind(ysd);
+ goto again;
+ }
+
+ if (!(r = ypprot_err(yprm.stat))) {
+ *outname = (char *)strdup(yprm.peer);
+ }
+
+ xdr_free((xdrproc_t)xdr_ypresp_master, &yprm);
+ YPUNLOCK();
+ return (r);
+}
+
+int
+yp_maplist(char *indomain, struct ypmaplist **outmaplist)
+{
+ struct dom_binding *ysd;
+ struct ypresp_maplist ypml;
+ struct timeval tv;
+ int r;
+
+ /* Sanity check */
+
+ if (indomain == NULL || !strlen(indomain))
+ return (YPERR_BADARGS);
+
+ YPLOCK();
+again:
+ if (_yp_dobind(indomain, &ysd) != 0) {
+ YPUNLOCK();
+ return (YPERR_DOMAIN);
+ }
+
+ tv.tv_sec = _yplib_timeout;
+ tv.tv_usec = 0;
+
+ bzero((char *)&ypml, sizeof ypml);
+
+ r = clnt_call(ysd->dom_client, YPPROC_MAPLIST,
+ (xdrproc_t)xdr_domainname, &indomain,
+ (xdrproc_t)xdr_ypresp_maplist, &ypml,tv);
+ if (r != RPC_SUCCESS) {
+ clnt_perror(ysd->dom_client, "yp_maplist: clnt_call");
+ _yp_unbind(ysd);
+ goto again;
+ }
+ if (!(r = ypprot_err(ypml.stat))) {
+ *outmaplist = ypml.maps;
+ }
+
+ /* NO: xdr_free((xdrproc_t)xdr_ypresp_maplist, &ypml);*/
+ YPUNLOCK();
+ return (r);
+}
+
+const char *
+yperr_string(int incode)
+{
+ static char err[80];
+
+ switch (incode) {
+ case 0:
+ return ("Success");
+ case YPERR_BADARGS:
+ return ("Request arguments bad");
+ case YPERR_RPC:
+ return ("RPC failure");
+ case YPERR_DOMAIN:
+ return ("Can't bind to server which serves this domain");
+ case YPERR_MAP:
+ return ("No such map in server's domain");
+ case YPERR_KEY:
+ return ("No such key in map");
+ case YPERR_YPERR:
+ return ("YP server error");
+ case YPERR_RESRC:
+ return ("Local resource allocation failure");
+ case YPERR_NOMORE:
+ return ("No more records in map database");
+ case YPERR_PMAP:
+ return ("Can't communicate with portmapper");
+ case YPERR_YPBIND:
+ return ("Can't communicate with ypbind");
+ case YPERR_YPSERV:
+ return ("Can't communicate with ypserv");
+ case YPERR_NODOM:
+ return ("Local domain name not set");
+ case YPERR_BADDB:
+ return ("Server data base is bad");
+ case YPERR_VERS:
+ return ("YP server version mismatch - server can't supply service.");
+ case YPERR_ACCESS:
+ return ("Access violation");
+ case YPERR_BUSY:
+ return ("Database is busy");
+ }
+ sprintf(err, "YP unknown error %d\n", incode);
+ return (err);
+}
+
+int
+ypprot_err(unsigned int incode)
+{
+ switch (incode) {
+ case YP_TRUE:
+ return (0);
+ case YP_FALSE:
+ return (YPERR_YPBIND);
+ case YP_NOMORE:
+ return (YPERR_NOMORE);
+ case YP_NOMAP:
+ return (YPERR_MAP);
+ case YP_NODOM:
+ return (YPERR_DOMAIN);
+ case YP_NOKEY:
+ return (YPERR_KEY);
+ case YP_BADOP:
+ return (YPERR_YPERR);
+ case YP_BADDB:
+ return (YPERR_BADDB);
+ case YP_YPERR:
+ return (YPERR_YPERR);
+ case YP_BADARGS:
+ return (YPERR_BADARGS);
+ case YP_VERS:
+ return (YPERR_VERS);
+ }
+ return (YPERR_YPERR);
+}
+
+int
+_yp_check(char **dom)
+{
+ char *unused;
+
+ YPLOCK();
+ if (_yp_domain[0]=='\0')
+ if (yp_get_default_domain_locked(&unused)) {
+ YPUNLOCK();
+ return (0);
+ }
+
+ if (dom)
+ *dom = _yp_domain;
+
+ if (yp_bind_locked(_yp_domain) == 0) {
+ yp_unbind_locked(_yp_domain);
+ YPUNLOCK();
+ return (1);
+ }
+ YPUNLOCK();
+ return (0);
+}
OpenPOWER on IntegriCloud